Fix T59595: Grease Pencil and CameraView

The perspective effect deformed the stroke. Now when you are in camera view and the lock axis is not enabled, the stroke is reprojected flat over the view to remove any deformation.

Also fixed reproject operator to use the origin set in topbar and not cursor 3D always.
This commit is contained in:
Antonio Vazquez 2018-12-19 17:07:12 +01:00
parent d9ac4653e7
commit 1fc75dbbce
Notes: blender-bot 2023-02-14 07:39:46 +01:00
Referenced by issue #59929, Blender 2.8 command line
Referenced by issue #59643, Clicking on Armature in Scene Collection causes hard crash
Referenced by issue #59637, Crash report - Overlays -> Face Orientation causes crash.
Referenced by issue #59595, Grease Pencil and Camera View
6 changed files with 77 additions and 4 deletions

View File

@ -88,6 +88,7 @@
/* Temporary fill operation data (op->customdata) */
typedef struct tGPDfill {
bContext *C;
struct Main *bmain;
struct Depsgraph *depsgraph;
struct wmWindow *win; /* window where painting originated */
@ -819,6 +820,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
const int cfra_eval = (int)DEG_get_ctime(tgpf->depsgraph);
ToolSettings *ts = tgpf->scene->toolsettings;
const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) && (tgpf->rv3d->persp == RV3D_CAMOB);
Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
if (brush == NULL) {
return;
@ -936,6 +938,11 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
gp_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpd, tgpf->gpl, pt);
}
/* if camera view, reproject flat to view to avoid perspective effect */
if (is_camera) {
ED_gpencil_project_stroke_to_view(tgpf->C, tgpf->gpl, gps);
}
/* simplify stroke */
for (int b = 0; b < tgpf->fill_simplylvl; b++) {
BKE_gpencil_simplify_fixed(gps);
@ -1004,6 +1011,7 @@ static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op))
Main *bmain = CTX_data_main(C);
/* set current scene and window info */
tgpf->C = C;
tgpf->bmain = CTX_data_main(C);
tgpf->scene = CTX_data_scene(C);
tgpf->ob = CTX_data_active_object(C);

View File

@ -193,6 +193,8 @@ void ED_gp_draw_fill(struct tGPDdraw *tgpw);
/* gpencil_utils.c */
typedef struct GP_SpaceConversion {
struct Scene *scene;
struct Object *ob;
struct bGPdata *gpd;
struct bGPDlayer *gpl;

View File

@ -845,10 +845,12 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
ToolSettings *ts = p->scene->toolsettings;
Depsgraph *depsgraph = p->depsgraph;
Object *obact = (Object *)p->ownerPtr.data;
RegionView3D *rv3d = p->ar->regiondata;
const int def_nr = obact->actdef - 1;
const bool have_weight = (bool)BLI_findlink(&obact->defbase, def_nr);
const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) && (rv3d->persp == RV3D_CAMOB);
int i, totelem;
/* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
@ -976,6 +978,11 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* if parented change position relative to parent object */
gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
}
/* if camera view, reproject flat to view to avoid perspective effect */
if (is_camera) {
ED_gpencil_project_stroke_to_view(p->C, p->gpl, gps);
}
}
else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
/* first point */
@ -987,6 +994,10 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
gp_reproject_toplane(p, gps);
/* if parented change position relative to parent object */
gp_apply_parent_point(depsgraph, obact, gpd, gpl, pt);
/* if camera view, reproject flat to view to avoid perspective effect */
if (is_camera) {
ED_gpencil_project_stroke_to_view(p->C, p->gpl, gps);
}
/* copy pressure and time */
pt->pressure = ptc->pressure;
pt->strength = ptc->strength;
@ -1146,6 +1157,10 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
gp_reproject_toplane(p, gps);
/* change position relative to parent object */
gp_apply_parent(depsgraph, obact, gpd, gpl, gps);
/* if camera view, reproject flat to view to avoid perspective effect */
if (is_camera) {
ED_gpencil_project_stroke_to_view(p->C, p->gpl, gps);
}
if (depth_arr)
MEM_freeN(depth_arr);

View File

@ -641,6 +641,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
char *align_flag = &ts->gpencil_v3d_align;
bool is_depth = (bool)(*align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) && (tgpi->rv3d->persp == RV3D_CAMOB);
if (tgpi->type == GP_STROKE_BOX)
gps->totpoints = (tgpi->tot_edges * 4 + tgpi->tot_stored_edges);
@ -946,6 +947,11 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
gp_apply_parent_point(tgpi->depsgraph, tgpi->ob, tgpi->gpd, tgpi->gpl, pt);
}
/* if camera view, reproject flat to view to avoid perspective effect */
if (is_camera) {
ED_gpencil_project_stroke_to_view(C, tgpi->gpl, gps);
}
/* force fill recalc */
gps->flag |= GP_STROKE_RECALC_CACHES;

View File

@ -522,6 +522,9 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
unit_m4(r_gsc->mat);
/* store settings */
r_gsc->scene = CTX_data_scene(C);
r_gsc->ob = CTX_data_active_object(C);
r_gsc->sa = sa;
r_gsc->ar = ar;
r_gsc->v2d = &ar->v2d;
@ -738,8 +741,11 @@ void gp_point_to_xy_fl(
bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen_co[2], float r_out[3])
{
const RegionView3D *rv3d = gsc->ar->regiondata;
float *rvec = scene->cursor.location;
float ref[3] = {rvec[0], rvec[1], rvec[2]};
float rvec[3];
ED_gp_get_drawing_reference(scene, gsc->ob, gsc->gpl,
scene->toolsettings->gpencil_v3d_align, rvec);
float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
float mval_f[2], mval_prj[2];
@ -747,7 +753,7 @@ bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen
copy_v2_v2(mval_f, screen_co);
if (ED_view3d_project_float_global(gsc->ar, ref, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
if (ED_view3d_project_float_global(gsc->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
sub_v2_v2v2(mval_f, mval_prj, mval_f);
ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac);
sub_v3_v3v3(r_out, rvec, dvec);
@ -838,6 +844,40 @@ void ED_gp_get_drawing_reference(
}
}
void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps)
{
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = (bGPdata *)ob->data;
GP_SpaceConversion gsc = { NULL };
bGPDspoint *pt;
int i;
float diff_mat[4][4];
float inverse_diff_mat[4][4];
/* init space conversion stuff */
gp_point_conversion_init(C, &gsc);
ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
/* Adjust each point */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
float xy[2];
bGPDspoint pt2;
gp_point_to_parent_space(pt, diff_mat, &pt2);
gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
/* Planar - All on same plane parallel to the viewplane */
gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
/* Unapply parent corrections */
mul_m4_v3(inverse_diff_mat, &pt->x);
}
}
/**
* Reproject all points of the stroke to a plane locked to axis to avoid stroke offset

View File

@ -239,6 +239,8 @@ void ED_gp_project_point_to_plane(
void ED_gp_get_drawing_reference(
const struct Scene *scene, const struct Object *ob,
struct bGPDlayer *gpl, char align_flag, float vec[3]);
void ED_gpencil_project_stroke_to_view(
struct bContext *C, struct bGPDlayer *gpl, struct bGPDstroke *gps);
/* set sculpt cursor */
void ED_gpencil_toggle_brush_cursor(struct bContext *C, bool enable, void *customdata);