diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index d0b581abaf2..0e1a5e613b2 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -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); diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 7d386c18c64..668fc076b2e 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -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; diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 35e7ca1132f..ce15b2ba6b0 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -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); diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index a2f9de39940..1e41e132e18 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -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; diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index fcfe6132948..22a7e68d825 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -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 diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 4c453c67f6b..4b419263a37 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -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);