From cd596fa1c7ece1e8129a5766c7cdcd5be22245cd Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sun, 29 Jan 2017 12:07:14 -0300 Subject: Remove struct `PreDefProject` and store all immutable parameters within the new struct `SnapData` In order to simplify the reading of these functions, the parameters: `snap_to`, `mval`, `ray_start`, `ray_dir`, `view_proj` and `depth_range` are now stored in the struct `SnapData` --- .../editors/transform/transform_snap_object.c | 496 +++++++++++---------- 1 file changed, 272 insertions(+), 224 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index fba965f69a7..f0177edf20b 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -59,6 +59,18 @@ #include "transform.h" +typedef struct SnapData { + short snap_to; + float mval[2]; + float ray_origin[3]; + float ray_start[3]; + float ray_dir[3]; + float pmat[4][4]; /* perspective matrix */ + float win_half[2];/* win x and y */ + enum eViewProj view_proj; + float depth_range[2]; +} SnapData; + typedef struct SnapObjectData { enum { SNAP_MESH = 1, @@ -232,26 +244,40 @@ typedef struct BVHTreeFromMeshType { char type; } BVHTreeFromMeshType; -typedef struct PreDefProject { - float pmat[4][4]; /* perspective matrix multiplied by object matrix */ - float win_half[2]; - float dist_px_sq; -} PreDefProject; - -static void precalc_project( - PreDefProject *projectdefs, const ARegion *ar, - const float dist_px, float obmat[4][4]) +/* + * Generates a struct with the immutable parameters that will be used on all objects. + * + * \param snap_to: Element to snap, Vertice, Edge or Face. + * \param view_proj: ORTHO or PERSP. + * Currently only works one at a time, but can eventually operate as flag. + * + * \param mval: Mouse coords. + * (When NULL, ray-casting is handled without any projection matrix correction.) + * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min. + * \param ray_start: ray_origin moved for the start clipping plane (clip_min). + * \param ray_direction: Unit length direction of the ray. + * \param depth_range: distances of clipe plane min and clip plane max; + */ +static void set_SnapData( + SnapData *snapdata, + const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj, + const float mval[2], const float ray_origin[3], const float ray_start[3], + const float ray_direction[3], const float depth_range[2]) { - float (*pmat)[4] = ((RegionView3D *)ar->regiondata)->persmat; - if (obmat) { - mul_m4_m4m4(projectdefs->pmat, pmat, obmat); - } - else { - copy_m4_m4(projectdefs->pmat, pmat); - } - projectdefs->win_half[0] = ar->winx / 2; - projectdefs->win_half[1] = ar->winy / 2; - projectdefs->dist_px_sq = SQUARE(dist_px); + if (ar) { + copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat); + snapdata->win_half[0] = ar->winx / 2; + snapdata->win_half[1] = ar->winy / 2; + } + if (mval) { + copy_v2_v2(snapdata->mval, mval); + } + snapdata->snap_to = snap_to; + copy_v3_v3(snapdata->ray_origin, ray_origin); + copy_v3_v3(snapdata->ray_start, ray_start); + copy_v3_v3(snapdata->ray_dir, ray_direction); + snapdata->view_proj = view_proj; + copy_v2_v2(snapdata->depth_range, depth_range); } static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index) @@ -322,14 +348,12 @@ static void get_edge_verts( } static bool test_projected_vert_dist( - PreDefProject *projectdefs, - const float co[3], const enum eViewProj view_proj, - const float mval[2], const float depth_range[2], - float r_co[3]) + const float depth_range[2], const float mval[2], const float co[3], + float pmat[4][4], const float win_half[2], const bool is_persp, + float *dist_px_sq, float r_co[3]) { float depth; - float(*pmat)[4] = projectdefs->pmat; - if (view_proj == VIEW_PROJ_PERSP) { + if (is_persp) { depth = mul_project_m4_v3_zfac(pmat, co); if (depth < depth_range[0] || depth > depth_range[1]) { return false; @@ -341,34 +365,35 @@ static bool test_projected_vert_dist( (dot_m4_v3_row_y(pmat, co) + pmat[3][1]), }; - if (view_proj == VIEW_PROJ_PERSP) { + if (is_persp) { mul_v2_fl(co2d, 1 / depth); } co2d[0] += 1.0f; co2d[1] += 1.0f; - co2d[0] *= projectdefs->win_half[0]; - co2d[1] *= projectdefs->win_half[1]; + co2d[0] *= win_half[0]; + co2d[1] *= win_half[1]; const float dist_sq = len_squared_v2v2(mval, co2d); - if (dist_sq < projectdefs->dist_px_sq) { + if (dist_sq < *dist_px_sq) { copy_v3_v3(r_co, co); - projectdefs->dist_px_sq = dist_sq; + *dist_px_sq = dist_sq; return true; } return false; } static bool test_projected_edge_dist( - PreDefProject *projectdefs, - const float va[3], const float vb[3], const float ray_start[3], const float ray_normal[3], - const enum eViewProj view_proj, const float mval[2], const float depth_range[2], - float r_co[3]) + const float depth_range[2], const float mval[2], + float pmat[4][4], const float win_half[2], const bool is_persp, + const float ray_start[3], const float ray_dir[3], + const float va[3], const float vb[3], + float *dist_px_sq, float r_co[3]) { float tmp_co[3], depth; - dist_squared_ray_to_seg_v3(ray_start, ray_normal, va, vb, tmp_co, &depth); - return test_projected_vert_dist(projectdefs, tmp_co, view_proj, mval, depth_range, r_co); + dist_squared_ray_to_seg_v3(ray_start, ray_dir, va, vb, tmp_co, &depth); + return test_projected_vert_dist(depth_range, mval, tmp_co, pmat, win_half, is_persp, dist_px_sq, r_co); } /** \} */ @@ -383,11 +408,15 @@ typedef struct Object_Nearest2dPrecalc { float ray_direction_local[3]; float ray_inv_dir[3]; - PreDefProject projectdefs; + float depth_range[2]; + float pmat[4][4]; /* perspective matrix multiplied by object matrix */ + float win_half[2]; + bool is_persp; + float dist_px_sq; + float mval[2]; bool sign[3]; bool r_axis_closest[3]; - float depth_range[2]; void *userdata; int index; @@ -397,16 +426,24 @@ typedef struct Object_Nearest2dPrecalc { static void nearest2d_precalc( - Object_Nearest2dPrecalc *neasrest_precalc, const ARegion *ar, + Object_Nearest2dPrecalc *neasrest_precalc, SnapData *snapdata, const float dist_px, float obmat[4][4], - const float ray_origin_local[3], const float ray_direction_local[3], - const float mval[2], const float depth_range[2]) + const float ray_origin_local[3], const float ray_direction_local[3]) { - precalc_project(&neasrest_precalc->projectdefs, ar, dist_px, obmat); + if (obmat) { + mul_m4_m4m4(neasrest_precalc->pmat, snapdata->pmat, obmat); + } + else { + copy_m4_m4(neasrest_precalc->pmat, snapdata->pmat); + } + copy_v2_v2(neasrest_precalc->win_half, snapdata->win_half); + neasrest_precalc->dist_px_sq = SQUARE(dist_px); + neasrest_precalc->is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + copy_v2_v2(neasrest_precalc->depth_range, snapdata->depth_range); + copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local); copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local); - copy_v2_v2(neasrest_precalc->mval, mval); - copy_v2_v2(neasrest_precalc->depth_range, depth_range); + copy_v2_v2(neasrest_precalc->mval, snapdata->mval); for (int i = 0; i < 3; i++) { neasrest_precalc->ray_inv_dir[i] = @@ -456,9 +493,9 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us (local_bvmax[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1], (local_bvmax[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2], }; - /* va[3] and vb[3] are the coordinates of the AABB edge closest to the ray */ + /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */ float va[3], vb[3]; - /* rtmin and rtmax are the distances of the minimum and maximum ray hits on the AABB */ + /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */ float rtmin, rtmax; int main_axis; @@ -506,10 +543,10 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us /* if rtmin < rtmax, ray intersect `AABB` */ if (rtmin <= rtmax) { #ifdef IGNORE_BEHIND_RAY - /* `if rtmax < depth_min`, the hit is behind us - * TODO: Check if the entire AABB is behind ray - * this will prevent unnecessary leaf testing*/ - if (rtmax < depth_range[0]) { + /* `if rtmax < depth_min`, the hit is behind us */ + if (rtmax < data->depth_range[0]) { + /* TODO: TODO: Check if the entire AABB is behind ray + * this will prevent unnecessary leaf testing */ return false; } #endif @@ -518,9 +555,9 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us return true; } #ifdef IGNORE_BEHIND_RAY - /* `if rtmin < depth_min`, the hit is behing us - * TODO: Check if the entire AABB is behind ray */ - else if (rtmin < depth_range[0]) { + /* `if rtmin < depth_min`, the hit is behing us */ + else if (rtmin < data->depth_range[0]) { + /* TODO: Test if the AABB is totally behind ray */ return false; } #endif @@ -534,7 +571,7 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us } float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]); - float (*pmat)[4] = data->projectdefs.pmat; + float (*pmat)[4] = data->pmat; float depth_a = mul_project_m4_v3_zfac(pmat, va); float depth_b = depth_a + pmat[main_axis][3] * scale; @@ -555,10 +592,10 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us vb2d[0] += 1.0f; vb2d[1] += 1.0f; - va2d[0] *= data->projectdefs.win_half[0]; - va2d[1] *= data->projectdefs.win_half[1]; - vb2d[0] *= data->projectdefs.win_half[0]; - vb2d[1] *= data->projectdefs.win_half[1]; + va2d[0] *= data->win_half[0]; + va2d[1] *= data->win_half[1]; + vb2d[0] *= data->win_half[0]; + vb2d[1] *= data->win_half[1]; //float dvec[2], edge[2], rdist; //sub_v2_v2v2(dvec, data->mval, va2d); @@ -587,7 +624,7 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us else { rdist = len_squared_v2v2(data->mval, va2d); } - return rdist < data->projectdefs.dist_px_sq; + return rdist < data->dist_px_sq; } static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata) @@ -599,12 +636,13 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo (bounds[2].min + bounds[2].max) / 2, }; - /* Although this function is also used in the Othogonal view (VIEW_PROJ_ORTHO), - * we put `eViewProj view_proj` as` VIEW_PROJ_PERSP` because it works in both cases - * (with the disadvantage of executing unnecessary calculations) */ if (test_projected_vert_dist( - &neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP, - neasrest_precalc->mval, neasrest_precalc->depth_range, + neasrest_precalc->depth_range, + neasrest_precalc->mval, co, + neasrest_precalc->pmat, + neasrest_precalc->win_half, + neasrest_precalc->is_persp, + &neasrest_precalc->dist_px_sq, neasrest_precalc->co)) { copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no); @@ -620,13 +658,16 @@ static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int i const float *v_pair[2]; get_edge_verts(neasrest_precalc->userdata, index, v_pair); - /* Although this function is also used in the Othogonal view (VIEW_PROJ_ORTHO), - * we put `eViewProj view_proj` as` VIEW_PROJ_PERSP` because it works in both cases - * (with the disadvantage of executing unnecessary calculations) */ if (test_projected_edge_dist( - &neasrest_precalc->projectdefs, v_pair[0], v_pair[1], - neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local, - VIEW_PROJ_PERSP, neasrest_precalc->mval, neasrest_precalc->depth_range, + neasrest_precalc->depth_range, + neasrest_precalc->mval, + neasrest_precalc->pmat, + neasrest_precalc->win_half, + neasrest_precalc->is_persp, + neasrest_precalc->ray_origin_local, + neasrest_precalc->ray_direction_local, + v_pair[0], v_pair[1], + &neasrest_precalc->dist_px_sq, neasrest_precalc->co)) { sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]); @@ -649,9 +690,8 @@ static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char a * \{ */ static bool snapArmature( - const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4], - const short snap_to, const float origin[3], const float dir[3], - const float mval[2], const enum eViewProj view_proj, const float depth_range[2], + SnapData *snapdata, + Object *ob, bArmature *arm, float obmat[4][4], /* read/write args */ float *dist_px, /* return args */ @@ -659,36 +699,47 @@ static bool snapArmature( { bool retval = false; - float ray_start_local[3], ray_normal_local[3]; - if (snap_to != SCE_SNAP_MODE_VERTEX) { + float ray_start_local[3], ray_normal_local[3]; /* Used only in the snap to edges */ + if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { float imat[4][4]; invert_m4_m4(imat, obmat); - copy_v3_v3(ray_start_local, origin); - copy_v3_v3(ray_normal_local, dir); + copy_v3_v3(ray_start_local, snapdata->ray_origin); + copy_v3_v3(ray_normal_local, snapdata->ray_dir); mul_m4_v3(imat, ray_start_local); mul_mat3_m4_v3(imat, ray_normal_local); } + else if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) { /* Currently only edge and vert */ + return retval; + } - PreDefProject projectdefs; - precalc_project(&projectdefs, ar, *dist_px, obmat); + bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + float lpmat[4][4], dist_px_sq; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + dist_px_sq = SQUARE(*dist_px); if (arm->edbo) { for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) { if (eBone->layer & arm->layer) { /* skip hidden or moving (selected) bones */ if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) { - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: retval |= test_projected_vert_dist( - &projectdefs, eBone->head, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, eBone->head, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); retval |= test_projected_vert_dist( - &projectdefs, eBone->tail, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, eBone->tail, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); break; case SCE_SNAP_MODE_EDGE: retval |= test_projected_edge_dist( - &projectdefs, eBone->head, eBone->tail, ray_start_local, ray_normal_local, - view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, lpmat, + snapdata->win_half, is_persp, ray_start_local, ray_normal_local, + eBone->head, eBone->tail, + &dist_px_sq, r_loc); break; } } @@ -703,24 +754,30 @@ static bool snapArmature( const float *head_vec = pchan->pose_head; const float *tail_vec = pchan->pose_tail; - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: retval |= test_projected_vert_dist( - &projectdefs, head_vec, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, head_vec, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); retval |= test_projected_vert_dist( - &projectdefs, tail_vec, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, tail_vec, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); break; case SCE_SNAP_MODE_EDGE: retval |= test_projected_edge_dist( - &projectdefs, head_vec, tail_vec, ray_start_local, ray_normal_local, - view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, lpmat, + snapdata->win_half, is_persp, ray_start_local, ray_normal_local, + head_vec, tail_vec, + &dist_px_sq, r_loc); break; } } } } if (retval) { - *dist_px = sqrtf(projectdefs.dist_px_sq); + *dist_px = sqrtf(dist_px_sq); mul_m4_v3(obmat, r_loc); return true; } @@ -728,9 +785,8 @@ static bool snapArmature( } static bool snapCurve( - const ARegion *ar, Object *ob, Curve *cu, float obmat[4][4], - const short snap_to, const float mval[2], const enum eViewProj view_proj, - const float depth_range[2], + SnapData *snapdata, + Object *ob, Curve *cu, float obmat[4][4], /* read/write args */ float *dist_px, /* return args */ @@ -739,16 +795,18 @@ static bool snapCurve( bool retval = false; /* only vertex snapping mode (eg control points and handles) supported for now) */ - if (snap_to != SCE_SNAP_MODE_VERTEX) { + if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) { return retval; } - PreDefProject projectdefs; - precalc_project(&projectdefs, ar, *dist_px, obmat); + bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + float lpmat[4][4], dist_px_sq; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + dist_px_sq = SQUARE(*dist_px); for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { for (int u = 0; u < nu->pntsu; u++) { - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: { if (ob->mode == OB_MODE_EDIT) { @@ -758,19 +816,25 @@ static bool snapCurve( break; } retval |= test_projected_vert_dist( - &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1], + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */ if (!(nu->bezt[u].f1 & SELECT) && !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) { retval |= test_projected_vert_dist( - &projectdefs, nu->bezt[u].vec[0], view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[0], + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } if (!(nu->bezt[u].f3 & SELECT) && !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) { retval |= test_projected_vert_dist( - &projectdefs, nu->bezt[u].vec[2], view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[2], + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } } else { @@ -779,7 +843,9 @@ static bool snapCurve( break; } retval |= test_projected_vert_dist( - &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bp[u].vec, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } } else { @@ -787,11 +853,15 @@ static bool snapCurve( if (nu->pntsu > 1) { if (nu->bezt) { retval |= test_projected_vert_dist( - &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1], + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } else { retval |= test_projected_vert_dist( - &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, nu->bp[u].vec, + lpmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } } } @@ -803,7 +873,7 @@ static bool snapCurve( } } if (retval) { - *dist_px = sqrtf(projectdefs.dist_px_sq); + *dist_px = sqrtf(dist_px_sq); mul_m4_v3(obmat, r_loc); return true; } @@ -812,9 +882,8 @@ static bool snapCurve( /* may extend later (for now just snaps to empty center) */ static bool snapEmpty( - const ARegion *ar, Object *ob, float obmat[4][4], - const short snap_to, const float mval[2], const enum eViewProj view_proj, - const float depth_range[2], + SnapData *snapdata, + Object *ob, float obmat[4][4], /* read/write args */ float *dist_px, /* return args */ @@ -827,15 +896,18 @@ static bool snapEmpty( } /* for now only vertex supported */ - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: { - PreDefProject projectdefs; - precalc_project(&projectdefs, ar, *dist_px, NULL); + bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + float dist_px_sq = SQUARE(*dist_px); float tmp_co[3]; copy_v3_v3(tmp_co, obmat[3]); - if (test_projected_vert_dist(&projectdefs, tmp_co, view_proj, mval, depth_range, r_loc)) { - *dist_px = sqrtf(projectdefs.dist_px_sq); + if (test_projected_vert_dist( + snapdata->depth_range, snapdata->mval, tmp_co, + snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc)) { + *dist_px = sqrtf(dist_px_sq); retval = true; } break; @@ -848,9 +920,8 @@ static bool snapEmpty( } static bool snapCamera( - const SnapObjectContext *sctx, Object *object, float obmat[4][4], - const short snap_to, const float mval[2], const enum eViewProj view_proj, - const float depth_range[2], + const SnapObjectContext *sctx, SnapData *snapdata, + Object *object, float obmat[4][4], /* read/write args */ float *dist_px, /* return args */ @@ -858,8 +929,8 @@ static bool snapCamera( { Scene *scene = sctx->scene; - PreDefProject projectdefs; - precalc_project(&projectdefs, sctx->v3d_data.ar, *dist_px, NULL); + bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + float dist_px_sq = SQUARE(*dist_px); float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4]; bool retval = false; @@ -880,7 +951,7 @@ static bool snapCamera( invert_m4_m4(orig_camera_imat, orig_camera_mat); invert_m4_m4(imat, obmat); - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_VERTEX: { MovieTrackingObject *tracking_object; @@ -920,7 +991,9 @@ static bool snapCamera( mul_m4_v3(vertex_obmat, bundle_pos); retval |= test_projected_vert_dist( - &projectdefs, bundle_pos, view_proj, mval, depth_range, r_loc); + snapdata->depth_range, snapdata->mval, bundle_pos, + snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc); } } @@ -931,7 +1004,7 @@ static bool snapCamera( } if (retval) { - *dist_px = sqrtf(projectdefs.dist_px_sq); + *dist_px = sqrtf(dist_px_sq); return true; } return false; @@ -943,18 +1016,10 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt) return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly; } -struct NearestDM_Data { - void *bvhdata; - const float *depth_range; - float *ray_depth; -}; - static bool snapDerivedMesh( - SnapObjectContext *sctx, + SnapObjectContext *sctx, SnapData *snapdata, Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index, - const short snap_to, const float mval[2], const enum eViewProj view_proj, bool do_bb, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], - const float depth_range[2], + bool do_bb, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -963,12 +1028,12 @@ static bool snapDerivedMesh( { bool retval = false; - if (snap_to == SCE_SNAP_MODE_FACE) { + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { if (dm->getNumPolys(dm) == 0) { return retval; } } - else if (snap_to == SCE_SNAP_MODE_EDGE) { + else if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { if (dm->getNumEdges(dm) == 0) { return retval; } @@ -980,7 +1045,9 @@ static bool snapDerivedMesh( } { - bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && (view_proj == VIEW_PROJ_ORTHO); + bool need_ray_start_correction_init = + (snapdata->snap_to == SCE_SNAP_MODE_FACE) && + (snapdata->view_proj == VIEW_PROJ_ORTHO); float imat[4][4]; float timat[3][3]; /* transpose inverse matrix for normals */ @@ -990,8 +1057,8 @@ static bool snapDerivedMesh( invert_m4_m4(imat, obmat); transpose_m3_m4(timat, imat); - copy_v3_v3(ray_start_local, ray_start); - copy_v3_v3(ray_normal_local, ray_normal); + copy_v3_v3(ray_start_local, snapdata->ray_start); + copy_v3_v3(ray_normal_local, snapdata->ray_dir); mul_m4_v3(imat, ray_start_local); mul_mat3_m4_v3(imat, ray_normal_local); @@ -1015,7 +1082,7 @@ static bool snapDerivedMesh( /* Exact value here is arbitrary (ideally we would scale in pixel-space based on 'dist_px'), * scale up so we can snap against verts & edges on the boundbox, see T46816. */ - if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { + if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { BKE_boundbox_scale(&bb_temp, bb, 1.0f + 1e-1f); bb = &bb_temp; } @@ -1044,7 +1111,7 @@ static bool snapDerivedMesh( } int tree_index = -1; - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_FACE: tree_index = 2; break; @@ -1075,7 +1142,7 @@ static bool snapDerivedMesh( } if (treedata && treedata->tree == NULL) { - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_FACE: bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6); break; @@ -1092,12 +1159,12 @@ static bool snapDerivedMesh( return retval; } - if (snap_to == SCE_SNAP_MODE_FACE) { + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already * been *inside* boundbox, leading to snap failures (see T38409). * Note also ar might be null (see T38435), in this case we assume ray_start is ok! */ - if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ + if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ if (need_ray_start_correction_init) { /* We *need* a reasonably valid len_diff in this case. * Use BHVTree to find the closest face from ray_start_local. @@ -1116,7 +1183,7 @@ static bool snapDerivedMesh( } float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); + copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far @@ -1124,7 +1191,8 @@ static bool snapDerivedMesh( */ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale); + ray_start_local, ray_org_local, ray_normal_local, + len_diff + snapdata->depth_range[0] * local_scale); local_depth -= len_diff; } else { @@ -1186,7 +1254,7 @@ static bool snapDerivedMesh( const ARegion *ar = sctx->v3d_data.ar; float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); + copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; @@ -1195,11 +1263,11 @@ static bool snapDerivedMesh( neasrest_precalc.userdata = &treedata_type; neasrest_precalc.index = -1; - nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat, - ray_org_local, ray_normal_local, mval, depth_range); + nearest2d_precalc(&neasrest_precalc, snapdata, *dist_px, obmat, + ray_org_local, ray_normal_local); BVHTree_WalkLeafCallback cb_walk_leaf = - (snap_to == SCE_SNAP_MODE_VERTEX) ? + (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; BLI_bvhtree_walk_dfs( @@ -1214,7 +1282,7 @@ static bool snapDerivedMesh( mul_m3_v3(timat, r_no); normalize_v3(r_no); } - *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); + *dist_px = sqrtf(neasrest_precalc.dist_px_sq); retval = true; } @@ -1231,11 +1299,8 @@ static bool snapDerivedMesh( } static bool snapEditMesh( - SnapObjectContext *sctx, + SnapObjectContext *sctx, SnapData *snapdata, Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index, - const short snap_to, const float mval[2], const enum eViewProj view_proj, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], - const float depth_range[2], /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -1244,12 +1309,12 @@ static bool snapEditMesh( { bool retval = false; - if (snap_to == SCE_SNAP_MODE_FACE) { + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { if (em->bm->totface == 0) { return retval; } } - if (snap_to == SCE_SNAP_MODE_EDGE) { + if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { if (em->bm->totedge == 0) { return retval; } @@ -1268,7 +1333,7 @@ static bool snapEditMesh( invert_m4_m4(imat, obmat); transpose_m3_m4(timat, imat); - copy_v3_v3(ray_normal_local, ray_normal); + copy_v3_v3(ray_normal_local, snapdata->ray_dir); mul_mat3_m4_v3(imat, ray_normal_local); @@ -1287,7 +1352,7 @@ static bool snapEditMesh( } int tree_index = -1; - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_FACE: tree_index = 2; break; @@ -1311,7 +1376,7 @@ static bool snapEditMesh( } if (treedata && treedata->tree == NULL) { - switch (snap_to) { + switch (snapdata->snap_to) { case SCE_SNAP_MODE_FACE: { BLI_bitmap *looptri_mask = NULL; @@ -1369,9 +1434,9 @@ static bool snapEditMesh( return retval; } - if (snap_to == SCE_SNAP_MODE_FACE) { + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { float ray_start_local[3]; - copy_v3_v3(ray_start_local, ray_start); + copy_v3_v3(ray_start_local, snapdata->ray_start); mul_m4_v3(imat, ray_start_local); /* local scale in normal direction */ @@ -1386,7 +1451,7 @@ static bool snapEditMesh( * Note also ar might be null (see T38435), in this case we assume ray_start is ok! */ float len_diff = 0.0f; - if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ + if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ /* We *need* a reasonably valid len_diff in this case. * Use BHVTree to find the closest face from ray_start_local. */ @@ -1402,7 +1467,7 @@ static bool snapEditMesh( len_diff = dot_v3v3(dvec, ray_normal_local); float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); + copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); /* We pass a temp ray_start, set from object's boundbox, @@ -1411,7 +1476,8 @@ static bool snapEditMesh( */ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale); + ray_start_local, ray_org_local, ray_normal_local, + len_diff + snapdata->depth_range[0] * local_scale); local_depth -= len_diff; } } @@ -1470,7 +1536,7 @@ static bool snapEditMesh( const ARegion *ar = sctx->v3d_data.ar; float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); + copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; @@ -1479,11 +1545,11 @@ static bool snapEditMesh( neasrest_precalc.userdata = &treedata_type; neasrest_precalc.index = -1; - nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat, - ray_org_local, ray_normal_local, mval, depth_range); + nearest2d_precalc(&neasrest_precalc, snapdata, *dist_px, obmat, + ray_org_local, ray_normal_local); BVHTree_WalkLeafCallback cb_walk_leaf = - (snap_to == SCE_SNAP_MODE_VERTEX) ? + (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; BLI_bvhtree_walk_dfs( @@ -1498,7 +1564,7 @@ static bool snapEditMesh( mul_m3_v3(timat, r_no); normalize_v3(r_no); } - *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); + *dist_px = sqrtf(neasrest_precalc.dist_px_sq); retval = true; } @@ -1520,11 +1586,9 @@ static bool snapEditMesh( * \note Duplicate args here are documented at #snapObjectsRay */ static bool snapObject( - SnapObjectContext *sctx, + SnapObjectContext *sctx, SnapData *snapdata, Object *ob, float obmat[4][4], const unsigned int ob_index, - bool use_obedit, const short snap_to, const float mval[2], - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], - const float depth_range[2], + bool use_obedit, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -1532,12 +1596,6 @@ static bool snapObject( Object **r_ob, float r_obmat[4][4], ListBase *r_hit_list) { - const enum eViewProj view_proj = - ((sctx->use_v3d == false) || (mval == NULL)) ? VIEW_PROJ_NONE : - (((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO); - - const ARegion *ar = sctx->v3d_data.ar; - bool retval = false; if (ob->type == OB_MESH) { @@ -1546,9 +1604,7 @@ static bool snapObject( if (use_obedit) { em = BKE_editmesh_from_object(ob); retval = snapEditMesh( - sctx, ob, em, obmat, ob_index, - snap_to, mval, view_proj, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, ob, em, obmat, ob_index, ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); @@ -1565,9 +1621,8 @@ static bool snapObject( dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH); } retval = snapDerivedMesh( - sctx, ob, dm, obmat, ob_index, - snap_to, mval, view_proj, true, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, ob, dm, obmat, ob_index, + true, ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); @@ -1575,31 +1630,30 @@ static bool snapObject( dm->release(dm); } } - else if (snap_to != SCE_SNAP_MODE_FACE) { + else if (snapdata->snap_to != SCE_SNAP_MODE_FACE) { if (ob->type == OB_ARMATURE) { retval = snapArmature( - ar, ob, ob->data, obmat, snap_to, ray_origin, ray_normal, - mval, view_proj, depth_range, dist_px, + snapdata, + ob, ob->data, obmat, dist_px, r_loc, r_no); } else if (ob->type == OB_CURVE) { retval = snapCurve( - ar, ob, ob->data, obmat, snap_to, mval, view_proj, - depth_range, + snapdata, + ob, ob->data, obmat, dist_px, r_loc, r_no); } else if (ob->type == OB_EMPTY) { retval = snapEmpty( - ar, ob, obmat, snap_to, mval, view_proj, - depth_range, + snapdata, + ob, obmat, dist_px, r_loc, r_no); } else if (ob->type == OB_CAMERA) { retval = snapCamera( - sctx, ob, obmat, snap_to, mval, view_proj, - depth_range, + sctx, snapdata, ob, obmat, dist_px, r_loc, r_no); } @@ -1622,18 +1676,9 @@ static bool snapObject( * Walks through all objects in the scene to find the closest snap element ray. * * \param sctx: Snap context to store data. - * \param snap_to: Element to snap, Vertice, Edge or Face. - * Currently only works one at a time, but can eventually operate as flag. - * + * \param snapdata: struct generated in `get_snapdata`. * \param snap_select: from enum SnapSelect. - * * \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping. - * \param mval: Mouse coords. - * When NULL, ray-casting is handled without any projection matrix correction. - * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min. - * \param ray_start: ray_origin moved for the start clipping plane (clip_min). - * \param ray_normal: Unit length direction of the ray. - * \param depth_range: distances of clipe plane min and clip plane max; * * Read/Write Args * --------------- @@ -1654,11 +1699,9 @@ static bool snapObject( * */ static bool snapObjectsRay( - SnapObjectContext *sctx, - const unsigned short snap_to, const SnapSelect snap_select, - const bool use_object_edit_cage, const float mval[2], - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], - const float depth_range[2], + SnapObjectContext *sctx, SnapData *snapdata, + const SnapSelect snap_select, + const bool use_object_edit_cage, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -1681,9 +1724,7 @@ static bool snapObjectsRay( Object *ob = base_act->object; retval |= snapObject( - sctx, ob, ob->obmat, ob_index++, - false, snap_to, mval, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, ob, ob->obmat, ob_index++, false, ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } @@ -1717,9 +1758,8 @@ static bool snapObjectsRay( Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob; retval |= snapObject( - sctx, dupli_snap, dupli_ob->mat, ob_index++, - use_obedit_dupli, snap_to, mval, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, dupli_snap, dupli_ob->mat, + ob_index++, use_obedit_dupli, ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } @@ -1731,9 +1771,7 @@ static bool snapObjectsRay( Object *ob_snap = use_obedit ? obedit : ob; retval |= snapObject( - sctx, ob_snap, ob->obmat, ob_index++, - use_obedit, snap_to, mval, - ray_origin, ray_start, ray_normal, depth_range, + sctx, snapdata, ob_snap, ob->obmat, ob_index++, use_obedit, ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } @@ -1842,10 +1880,13 @@ bool ED_transform_snap_object_project_ray_ex( Object **r_ob, float r_obmat[4][4]) { const float depth_range[2] = {0.0f, FLT_MAX}; + + SnapData snapdata; + set_SnapData(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, r_loc, r_loc, r_no, depth_range); + return snapObjectsRay( - sctx, - snap_to, params->snap_select, params->use_object_edit_cage, NULL, - ray_start, ray_start, ray_normal, depth_range, + sctx, &snapdata, + params->snap_select, params->use_object_edit_cage, ray_depth, NULL, r_loc, r_no, r_index, r_ob, r_obmat, NULL); } @@ -1874,10 +1915,13 @@ bool ED_transform_snap_object_project_ray_all( float ray_depth_prev = ray_depth; #endif + SnapData snapdata; + set_SnapData(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, + ray_start, ray_start, ray_normal, depth_range); + bool retval = snapObjectsRay( - sctx, - snap_to, params->snap_select, params->use_object_edit_cage, NULL, - ray_start, ray_start, ray_normal, depth_range, + sctx, &snapdata, + params->snap_select, params->use_object_edit_cage, &ray_depth, NULL, NULL, NULL, NULL, NULL, NULL, r_hit_list); @@ -2037,10 +2081,14 @@ bool ED_transform_snap_object_project_view3d_ex( ray_depth = &ray_depth_fallback; } + SnapData snapdata; + const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO; + set_SnapData(&snapdata, ar, snap_to, view_proj, mval, + ray_start, ray_start, ray_normal, depth_range); + return snapObjectsRay( - sctx, - snap_to, params->snap_select, params->use_object_edit_cage, - mval, ray_origin, ray_start, ray_normal, depth_range, + sctx, &snapdata, + params->snap_select, params->use_object_edit_cage, ray_depth, dist_px, r_loc, r_no, r_index, NULL, NULL, NULL); } -- cgit v1.2.3 From 88b0b22914cc2333b022080d2e2f1f235f924db7 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sun, 29 Jan 2017 12:26:15 -0300 Subject: fix T50486: Don't always do the `ray_start_correction` in the ortho view You need to make sure that ray_start is really far away, because even in the Orthografic view, in some cases, the ray can start inside the object --- .../editors/transform/transform_snap_object.c | 66 +++++++++++++--------- 1 file changed, 39 insertions(+), 27 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index f0177edf20b..bd8596ca1bc 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1181,19 +1181,25 @@ static bool snapDerivedMesh( len_diff = dot_v3v3(dvec, ray_normal_local); } } - float ray_org_local[3]; + /* You need to make sure that ray_start is really far away, + * because even in the Orthografic view, in some cases, + * the ray can start inside the object (see T50486) */ + if (len_diff > 400.0f) { + float ray_org_local[3]; - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); - /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far - * away ray_start values (as returned in case of ortho view3d), see T38358. - */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, - len_diff + snapdata->depth_range[0] * local_scale); - local_depth -= len_diff; + /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with + * very far away ray_start values (as returned in case of ortho view3d), see T38358. + */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + madd_v3_v3v3fl( + ray_start_local, ray_org_local, ray_normal_local, + len_diff + snapdata->depth_range[0] * local_scale); + local_depth -= len_diff; + } + else len_diff = 0.0f; } else { len_diff = 0.0f; @@ -1446,8 +1452,8 @@ static bool snapEditMesh( local_depth *= local_scale; } - /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already - * been *inside* boundbox, leading to snap failures (see T38409). + /* Only use closer ray_start in case of ortho view! In perspective one, ray_start + * may already been *inside* boundbox, leading to snap failures (see T38409). * Note also ar might be null (see T38435), in this case we assume ray_start is ok! */ float len_diff = 0.0f; @@ -1465,20 +1471,26 @@ static bool snapEditMesh( float dvec[3]; sub_v3_v3v3(dvec, nearest.co, ray_start_local); len_diff = dot_v3v3(dvec, ray_normal_local); - float ray_org_local[3]; - - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); - - /* We pass a temp ray_start, set from object's boundbox, - * to avoid precision issues with very far away ray_start values - * (as returned in case of ortho view3d), see T38358. - */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, - len_diff + snapdata->depth_range[0] * local_scale); - local_depth -= len_diff; + /* You need to make sure that ray_start is really far away, + * because even in the Orthografic view, in some cases, + * the ray can start inside the object (see T50486) */ + if (len_diff > 400.0f) { + float ray_org_local[3]; + + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); + + /* We pass a temp ray_start, set from object's boundbox, + * to avoid precision issues with very far away ray_start values + * (as returned in case of ortho view3d), see T38358. + */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + madd_v3_v3v3fl( + ray_start_local, ray_org_local, ray_normal_local, + len_diff + snapdata->depth_range[0] * local_scale); + local_depth -= len_diff; + } + else len_diff = 0.0f; } } if (r_hit_list) { -- cgit v1.2.3 From dead79a16a8e307d6dc2de21380347460c6ddddb Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sun, 29 Jan 2017 13:13:14 -0300 Subject: Rename func `set_SnapData` to `snap_data_set` Don't use CamelCase in functions and try to keep area affected first, and action last, in names --- source/blender/editors/transform/transform_snap_object.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index bd8596ca1bc..0f7b62d7bad 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -258,7 +258,7 @@ typedef struct BVHTreeFromMeshType { * \param ray_direction: Unit length direction of the ray. * \param depth_range: distances of clipe plane min and clip plane max; */ -static void set_SnapData( +static void snap_data_set( SnapData *snapdata, const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj, const float mval[2], const float ray_origin[3], const float ray_start[3], @@ -1894,7 +1894,7 @@ bool ED_transform_snap_object_project_ray_ex( const float depth_range[2] = {0.0f, FLT_MAX}; SnapData snapdata; - set_SnapData(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, r_loc, r_loc, r_no, depth_range); + snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, r_loc, r_loc, r_no, depth_range); return snapObjectsRay( sctx, &snapdata, @@ -1928,7 +1928,7 @@ bool ED_transform_snap_object_project_ray_all( #endif SnapData snapdata; - set_SnapData(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, + snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, ray_start, ray_start, ray_normal, depth_range); bool retval = snapObjectsRay( @@ -2095,7 +2095,7 @@ bool ED_transform_snap_object_project_view3d_ex( SnapData snapdata; const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO; - set_SnapData(&snapdata, ar, snap_to, view_proj, mval, + snap_data_set(&snapdata, ar, snap_to, view_proj, mval, ray_start, ray_start, ray_normal, depth_range); return snapObjectsRay( -- cgit v1.2.3 From cf6ca226fa58d7a03be6cebb73a88eeb57497cf4 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sun, 29 Jan 2017 13:56:58 -0300 Subject: New math_geom function `isect_ray_aabb_v3_simple` The new `isect_ray_aabb_v3_simple` function replaces the `BKE_boundbox_ray_hit_check` and can be used in BVHTree Root (first AABB). So it is much more efficient. --- source/blender/editors/transform/transform_snap_object.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 0f7b62d7bad..a562a66597e 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1087,13 +1087,16 @@ static bool snapDerivedMesh( bb = &bb_temp; } - /* was local_depth, see: T47838 */ - len_diff = BVH_RAYCAST_DIST_MAX; + float tmin, tmax; - if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) { + /* was BKE_boundbox_ray_hit_check, see: T50486 */ + if (!isect_ray_aabb_v3_simple( + ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &tmin, &tmax)) + { return retval; } - need_ray_start_correction_init = false; + /* was local_depth, see: T47838 */ + len_diff = tmin > 0 ? tmin : tmax; } } -- cgit v1.2.3 From 6c23a1b8b951ba76965ae2b33188dfaa4b4f2a29 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sun, 29 Jan 2017 14:19:58 -0300 Subject: Remove `BKE_boundbox_ray_hit_check` Remove `BKE_boundbox_ray_hit_check` since it is no longer being used and can be easily replaced by `isect_ray_aabb_v3_simple` --- source/blender/editors/transform/transform_snap_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index a562a66597e..47bb86561a1 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1089,7 +1089,7 @@ static bool snapDerivedMesh( float tmin, tmax; - /* was BKE_boundbox_ray_hit_check, see: T50486 */ + /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ if (!isect_ray_aabb_v3_simple( ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &tmin, &tmax)) { -- cgit v1.2.3 From 167ab03f36a912c1e23f75d30102e545e336bf26 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 30 Jan 2017 02:19:18 -0300 Subject: Solve compilation error: Field has incomplete type 'enum eViewProj' Error reported by @tomjpsun Patch D2491 --- source/blender/editors/transform/transform_snap_object.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 47bb86561a1..87c28c30a46 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -59,6 +59,12 @@ #include "transform.h" +enum eViewProj { + VIEW_PROJ_NONE = -1, + VIEW_PROJ_ORTHO = 0, + VIEW_PROJ_PERSP = -1, +}; + typedef struct SnapData { short snap_to; float mval[2]; @@ -122,12 +128,6 @@ struct SnapObjectContext { }; -enum eViewProj { - VIEW_PROJ_NONE = -1, - VIEW_PROJ_ORTHO = 0, - VIEW_PROJ_PERSP = -1, -}; - static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt); -- cgit v1.2.3 From 318ee2e8c108c7a6e03a78dd4877e2ce67f8f5e0 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 30 Jan 2017 02:26:00 -0300 Subject: Fix unreported bug: parameter ray_start repeated The bug would only be seen in terms of performance --- source/blender/editors/transform/transform_snap_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 87c28c30a46..43eb02889bb 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -2099,7 +2099,7 @@ bool ED_transform_snap_object_project_view3d_ex( SnapData snapdata; const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO; snap_data_set(&snapdata, ar, snap_to, view_proj, mval, - ray_start, ray_start, ray_normal, depth_range); + ray_origin, ray_start, ray_normal, depth_range); return snapObjectsRay( sctx, &snapdata, -- cgit v1.2.3 From 505ff16dbff03a90ddc9e2d53cd1694e38beb49c Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 30 Jan 2017 02:49:41 -0300 Subject: Snap System: BVH: ignore AABBs behind ray This provides a slight improvement in performance in specific cases, such as when the observer is inside a high poly object and executes snap to edge or vertex --- .../blender/editors/transform/transform_snap_object.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 43eb02889bb..0624288f94f 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -542,12 +542,16 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us /* if rtmin < rtmax, ray intersect `AABB` */ if (rtmin <= rtmax) { +#define IGNORE_BEHIND_RAY #ifdef IGNORE_BEHIND_RAY /* `if rtmax < depth_min`, the hit is behind us */ if (rtmax < data->depth_range[0]) { - /* TODO: TODO: Check if the entire AABB is behind ray - * this will prevent unnecessary leaf testing */ - return false; + /* Test if the entire AABB is behind us */ + float dvec[3]; + sub_v3_v3v3(dvec, local_bvmax, data->ray_origin_local); + if (dot_v3v3(dvec, data->ray_direction_local) < (data->depth_range[0])) { + return false; + } } #endif const float proj = rtmin * data->ray_direction_local[main_axis]; @@ -557,10 +561,15 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us #ifdef IGNORE_BEHIND_RAY /* `if rtmin < depth_min`, the hit is behing us */ else if (rtmin < data->depth_range[0]) { - /* TODO: Test if the AABB is totally behind ray */ - return false; + /* Test if the entire AABB is behind us */ + float dvec[3]; + sub_v3_v3v3(dvec, local_bvmax, data->ray_origin_local); + if (dot_v3v3(dvec, data->ray_direction_local) < (data->depth_range[0])) { + return false; + } } #endif +#undef IGNORE_BEHIND_RAY if (data->sign[main_axis]) { va[main_axis] = local_bvmax[main_axis]; vb[main_axis] = local_bvmin[main_axis]; -- cgit v1.2.3 From 62f2c44ffb602a8a78f3db13791ac912cd09be8f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Jan 2017 09:25:21 +0100 Subject: Cleanup: Unused function and and variables in snap code Please doublecheck ED_transform_snap_object_project_ray_ex() is really valid, it's weird to have extra arguments here unused. --- .../editors/transform/transform_snap_object.c | 25 +--------------------- 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 0624288f94f..3f8e1176f3a 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -280,25 +280,6 @@ static void snap_data_set( copy_v2_v2(snapdata->depth_range, depth_range); } -static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index) -{ - switch (meshdata->type) { - case SNAP_MESH: - { - BVHTreeFromMesh *data = meshdata->userdata; - const MVert *vert = data->vert; - return vert[index].co; - } - case SNAP_EDIT_MESH: - { - BVHTreeFromEditMesh *data = meshdata->userdata; - BMVert *eve = BM_vert_at_index(data->em->bm, index); - return eve->co; - } - } - return NULL; -} - static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3]) { switch (meshdata->type) { @@ -1269,8 +1250,6 @@ static bool snapDerivedMesh( } /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ else { - const ARegion *ar = sctx->v3d_data.ar; - float ray_org_local[3]; copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); @@ -1557,8 +1536,6 @@ static bool snapEditMesh( } } else { - const ARegion *ar = sctx->v3d_data.ar; - float ray_org_local[3]; copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); @@ -1898,7 +1875,7 @@ bool ED_transform_snap_object_project_ray_ex( SnapObjectContext *sctx, const unsigned short snap_to, const struct SnapObjectParams *params, - const float ray_start[3], const float ray_normal[3], + const float UNUSED(ray_start[3]), const float UNUSED(ray_normal[3]), float *ray_depth, float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4]) -- cgit v1.2.3 From 997a210b086f93a881b10cb1c3ba6bedcb33676a Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 30 Jan 2017 18:30:19 -0300 Subject: Fix T49632: Grease pencil in "Edit Strokes" mode: Snap tool did not snap points to active object A simple confusion between enums: ~SNAP_NOT_ACTIVE~ --- source/blender/editors/transform/transform_snap.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index f8bb124e943..87ac54b2bd9 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -569,7 +569,9 @@ static void initSnappingMode(TransInfo *t) else if (t->tsnap.applySnap != NULL && // A snapping function actually exist (obedit == NULL) ) // Object Mode { - t->tsnap.modeSelect = SNAP_NOT_SELECTED; + /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632) + * TODO: perform self snap in gpencil_strokes */ + t->tsnap.modeSelect = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_ALL : SNAP_NOT_SELECTED; } else { /* Grid if snap is not possible */ @@ -1214,7 +1216,7 @@ bool snapObjectsTransform( t->tsnap.object_context, t->scene->toolsettings->snap_mode, &(const struct SnapObjectParams){ - .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect, + .snap_select = t->tsnap.modeSelect, .use_object_edit_cage = (t->flag & T_EDIT) != 0, }, mval, dist_px, NULL, @@ -1304,7 +1306,7 @@ bool peelObjectsTransform( t->tsnap.object_context, mval, &(const struct SnapObjectParams){ - .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect, + .snap_select = t->tsnap.modeSelect, .use_object_edit_cage = (t->flag & T_EDIT) != 0, }, use_peel_object, -- cgit v1.2.3 From eadfd901ad7c3af4d85b05618352a96a9b4ca9de Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 30 Jan 2017 21:41:44 +0100 Subject: Optimization: pass Main to BKE_library_foreach_ID_link() and use its relations. Use Main->relations in BKE_library_foreach_ID_link(), when possible (i.e. IDWALK_READONLY is set), and if the data is available of course. This is quite minor optimization, no sensible improvements are expected, but does not hurt either to avoid potentially tens of looping over e.g. objects constraints and modifiers, or heap of drivers... --- source/blender/editors/object/object_relations.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index d30022c01f8..01c307fa0d2 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2170,12 +2170,12 @@ static void tag_localizable_objects(bContext *C, const int mode) */ for (Object *object = bmain->object.first; object; object = object->id.next) { if ((object->id.tag & LIB_TAG_DOIT) == 0) { - BKE_library_foreach_ID_link(&object->id, tag_localizable_looper, NULL, IDWALK_READONLY); + BKE_library_foreach_ID_link(NULL, &object->id, tag_localizable_looper, NULL, IDWALK_READONLY); } if (object->data) { ID *data_id = (ID *) object->data; if ((data_id->tag & LIB_TAG_DOIT) == 0) { - BKE_library_foreach_ID_link(data_id, tag_localizable_looper, NULL, IDWALK_READONLY); + BKE_library_foreach_ID_link(NULL, data_id, tag_localizable_looper, NULL, IDWALK_READONLY); } } } -- cgit v1.2.3 From a50b173952c85a51828f28569a9923bd29764292 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 30 Jan 2017 22:27:38 -0300 Subject: Use the same solution to test the pixel distance to the AABB, with BoundBox The previous solution took arbitrary values to determine if the mouse was near or not to the Bound Box (it simply scaled the Bound Box). Now the same function that detected the distance from the BVHTree nodes to the mouse is used in the Bound Box --- .../editors/transform/transform_snap_object.c | 291 +++++++++++++-------- 1 file changed, 177 insertions(+), 114 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 3f8e1176f3a..5d9892cd503 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -244,7 +244,7 @@ typedef struct BVHTreeFromMeshType { char type; } BVHTreeFromMeshType; -/* +/** * Generates a struct with the immutable parameters that will be used on all objects. * * \param snap_to: Element to snap, Vertice, Edge or Face. @@ -376,15 +376,7 @@ static bool test_projected_edge_dist( dist_squared_ray_to_seg_v3(ray_start, ray_dir, va, vb, tmp_co, &depth); return test_projected_vert_dist(depth_range, mval, tmp_co, pmat, win_half, is_persp, dist_px_sq, r_co); } - -/** \} */ - - -/* -------------------------------------------------------------------- */ - -/** \Walk DFS - * \{ */ -typedef struct Object_Nearest2dPrecalc { +typedef struct Nearest2dPrecalc { float ray_origin_local[3]; float ray_direction_local[3]; float ray_inv_dir[3]; @@ -392,76 +384,65 @@ typedef struct Object_Nearest2dPrecalc { float depth_range[2]; float pmat[4][4]; /* perspective matrix multiplied by object matrix */ float win_half[2]; - bool is_persp; - float dist_px_sq; float mval[2]; bool sign[3]; - bool r_axis_closest[3]; - - void *userdata; - int index; - float co[3]; - float no[3]; -} Object_Nearest2dPrecalc; - +} Nearest2dPrecalc; -static void nearest2d_precalc( - Object_Nearest2dPrecalc *neasrest_precalc, SnapData *snapdata, - const float dist_px, float obmat[4][4], +/** + * \param lpmat: Perspective matrix multiplied by object matrix + */ +static void dist_squared_to_projected_aabb_precalc( + struct Nearest2dPrecalc *neasrest_precalc, + float lpmat[4][4], const float win_half[2], + const float depth_range[2], const float mval[2], const float ray_origin_local[3], const float ray_direction_local[3]) { - if (obmat) { - mul_m4_m4m4(neasrest_precalc->pmat, snapdata->pmat, obmat); - } - else { - copy_m4_m4(neasrest_precalc->pmat, snapdata->pmat); - } - copy_v2_v2(neasrest_precalc->win_half, snapdata->win_half); - neasrest_precalc->dist_px_sq = SQUARE(dist_px); - neasrest_precalc->is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; - copy_v2_v2(neasrest_precalc->depth_range, snapdata->depth_range); + copy_m4_m4(neasrest_precalc->pmat, lpmat); + copy_v2_v2(neasrest_precalc->win_half, win_half); + copy_v2_v2(neasrest_precalc->depth_range, depth_range); copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local); copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local); - copy_v2_v2(neasrest_precalc->mval, snapdata->mval); + copy_v2_v2(neasrest_precalc->mval, mval); for (int i = 0; i < 3; i++) { - neasrest_precalc->ray_inv_dir[i] = + neasrest_precalc->ray_inv_dir[i] = (neasrest_precalc->ray_direction_local[i] != 0.0f) ? (1.0f / neasrest_precalc->ray_direction_local[i]) : FLT_MAX; neasrest_precalc->sign[i] = (neasrest_precalc->ray_inv_dir[i] < 0.0f); - neasrest_precalc->r_axis_closest[i] = true; } } -static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data) +static float dist_squared_to_projected_aabb( + struct Nearest2dPrecalc *data, + const float bbmin[3], const float bbmax[3], + bool r_axis_closest[3]) { - Object_Nearest2dPrecalc *data = user_data; float local_bvmin[3], local_bvmax[3]; if (data->sign[0]) { - local_bvmin[0] = bounds[0].max; - local_bvmax[0] = bounds[0].min; + local_bvmin[0] = bbmax[0]; + local_bvmax[0] = bbmin[0]; } else { - local_bvmin[0] = bounds[0].min; - local_bvmax[0] = bounds[0].max; + local_bvmin[0] = bbmin[0]; + local_bvmax[0] = bbmax[0]; } if (data->sign[1]) { - local_bvmin[1] = bounds[1].max; - local_bvmax[1] = bounds[1].min; + local_bvmin[1] = bbmax[1]; + local_bvmax[1] = bbmin[1]; } else { - local_bvmin[1] = bounds[1].min; - local_bvmax[1] = bounds[1].max; + local_bvmin[1] = bbmin[1]; + local_bvmax[1] = bbmax[1]; } if (data->sign[2]) { - local_bvmin[2] = bounds[2].max; - local_bvmax[2] = bounds[2].min; + local_bvmin[2] = bbmax[2]; + local_bvmax[2] = bbmin[2]; } else { - local_bvmin[2] = bounds[2].min; - local_bvmax[2] = bounds[2].max; + local_bvmin[2] = bbmin[2]; + local_bvmax[2] = bbmax[2]; } const float tmin[3] = { @@ -484,38 +465,38 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us rtmax = tmax[0]; va[0] = vb[0] = local_bvmax[0]; main_axis = 3; - data->r_axis_closest[0] = data->sign[0]; + r_axis_closest[0] = data->sign[0]; } else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { rtmax = tmax[1]; va[1] = vb[1] = local_bvmax[1]; main_axis = 2; - data->r_axis_closest[1] = data->sign[1]; + r_axis_closest[1] = data->sign[1]; } else { rtmax = tmax[2]; va[2] = vb[2] = local_bvmax[2]; main_axis = 1; - data->r_axis_closest[2] = data->sign[2]; + r_axis_closest[2] = data->sign[2]; } if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { rtmin = tmin[0]; va[0] = vb[0] = local_bvmin[0]; main_axis -= 3; - data->r_axis_closest[0] = !data->sign[0]; + r_axis_closest[0] = !data->sign[0]; } else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { rtmin = tmin[1]; va[1] = vb[1] = local_bvmin[1]; main_axis -= 1; - data->r_axis_closest[1] = !data->sign[1]; + r_axis_closest[1] = !data->sign[1]; } else { rtmin = tmin[2]; va[2] = vb[2] = local_bvmin[2]; main_axis -= 2; - data->r_axis_closest[2] = !data->sign[2]; + r_axis_closest[2] = !data->sign[2]; } if (main_axis < 0) { main_axis += 3; @@ -531,13 +512,13 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us float dvec[3]; sub_v3_v3v3(dvec, local_bvmax, data->ray_origin_local); if (dot_v3v3(dvec, data->ray_direction_local) < (data->depth_range[0])) { - return false; + return FLT_MAX; } } #endif const float proj = rtmin * data->ray_direction_local[main_axis]; - data->r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj); - return true; + r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj); + return 0.0f; } #ifdef IGNORE_BEHIND_RAY /* `if rtmin < depth_min`, the hit is behing us */ @@ -546,7 +527,7 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us float dvec[3]; sub_v3_v3v3(dvec, local_bvmax, data->ray_origin_local); if (dot_v3v3(dvec, data->ray_direction_local) < (data->depth_range[0])) { - return false; + return FLT_MAX; } } #endif @@ -598,28 +579,90 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us lambda /= edge[0] * edge[0] + edge[1] * edge[1]; if (lambda <= 0.0f) { rdist = len_squared_v2v2(data->mval, va2d); - data->r_axis_closest[main_axis] = true; + r_axis_closest[main_axis] = true; } else if (lambda >= 1.0f) { rdist = len_squared_v2v2(data->mval, vb2d); - data->r_axis_closest[main_axis] = false; + r_axis_closest[main_axis] = false; } else { va2d[0] += edge[0] * lambda; va2d[1] += edge[1] * lambda; rdist = len_squared_v2v2(data->mval, va2d); - data->r_axis_closest[main_axis] = lambda < 0.5f; + r_axis_closest[main_axis] = lambda < 0.5f; } } else { rdist = len_squared_v2v2(data->mval, va2d); } + return rdist; +} + +static float dist_squared_to_projected_aabb_simple( + float lpmat[4][4], const float win_half[2], + const float depth_range[2], const float mval[2], + const float ray_origin_local[3], const float ray_direction_local[3], + const float bbmin[3], const float bbmax[3]) +{ + struct Nearest2dPrecalc data; + dist_squared_to_projected_aabb_precalc( + &data, lpmat, win_half, depth_range, + mval, ray_origin_local, ray_direction_local); + + bool dummy[3] = {true, true, true}; + return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy); +} + +static float dist_aabb_to_plane( + const float bbmin[3], const float bbmax[3], + const float plane_co[3], const float plane_no[3]) +{ + const float local_bvmin[3] = { + (plane_no[0] < 0) ? bbmax[0] : bbmin[0], + (plane_no[1] < 0) ? bbmax[1] : bbmin[1], + (plane_no[2] < 0) ? bbmax[2] : bbmin[2], + }; + float dvec[3]; + sub_v3_v3v3(dvec, local_bvmin, plane_co); + return dot_v3v3(dvec, plane_no); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \Walk DFS + * \{ */ +typedef struct Nearest2dUserData { + struct Nearest2dPrecalc data_precalc; + + bool is_persp; + float dist_px_sq; + + bool r_axis_closest[3]; + + void *userdata; + int index; + float co[3]; + float no[3]; +} Nearest2dUserData; + + +static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data) +{ + Nearest2dUserData *data = user_data; + const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min}; + const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max}; + const float rdist = dist_squared_to_projected_aabb( + &data->data_precalc, bbmin, bbmax, data->r_axis_closest); return rdist < data->dist_px_sq; } static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata) { - struct Object_Nearest2dPrecalc *neasrest_precalc = userdata; + struct Nearest2dUserData *data = userdata; + struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc; const float co[3] = { (bounds[0].min + bounds[0].max) / 2, (bounds[1].min + bounds[1].max) / 2, @@ -631,44 +674,45 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo neasrest_precalc->mval, co, neasrest_precalc->pmat, neasrest_precalc->win_half, - neasrest_precalc->is_persp, - &neasrest_precalc->dist_px_sq, - neasrest_precalc->co)) + data->is_persp, + &data->dist_px_sq, + data->co)) { - copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no); - neasrest_precalc->index = index; + copy_vert_no(data->userdata, index, data->no); + data->index = index; } return true; } static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata) { - struct Object_Nearest2dPrecalc *neasrest_precalc = userdata; + struct Nearest2dUserData *data = userdata; + struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc; const float *v_pair[2]; - get_edge_verts(neasrest_precalc->userdata, index, v_pair); + get_edge_verts(data->userdata, index, v_pair); if (test_projected_edge_dist( neasrest_precalc->depth_range, neasrest_precalc->mval, neasrest_precalc->pmat, neasrest_precalc->win_half, - neasrest_precalc->is_persp, + data->is_persp, neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local, v_pair[0], v_pair[1], - &neasrest_precalc->dist_px_sq, - neasrest_precalc->co)) + &data->dist_px_sq, + data->co)) { - sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]); - neasrest_precalc->index = index; + sub_v3_v3v3(data->no, v_pair[0], v_pair[1]); + data->index = index; } return true; } static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata) { - const bool *r_axis_closest = ((struct Object_Nearest2dPrecalc *)userdata)->r_axis_closest; + const bool *r_axis_closest = ((struct Nearest2dUserData *)userdata)->r_axis_closest; return r_axis_closest[axis]; } @@ -1060,6 +1104,14 @@ static bool snapDerivedMesh( local_depth *= local_scale; } + float lpmat[4][4]; + float ray_org_local[3]; + if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); + } + if (do_bb) { BoundBox *bb = BKE_object_boundbox_get(ob); @@ -1070,23 +1122,28 @@ static bool snapDerivedMesh( * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */ bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f); - /* Exact value here is arbitrary (ideally we would scale in pixel-space based on 'dist_px'), - * scale up so we can snap against verts & edges on the boundbox, see T46816. */ + /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { - BKE_boundbox_scale(&bb_temp, bb, 1.0f + 1e-1f); - bb = &bb_temp; + float dist_px_sq = dist_squared_to_projected_aabb_simple( + lpmat, snapdata->win_half, snapdata->depth_range, snapdata->mval, + ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); + if (dist_px_sq > SQUARE(*dist_px)) + { + return retval; + } } - - float tmin, tmax; - - /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ - if (!isect_ray_aabb_v3_simple( - ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &tmin, &tmax)) - { - return retval; + else { + /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ + if (!isect_ray_aabb_v3_simple( + ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) + { + return retval; + } } /* was local_depth, see: T47838 */ - len_diff = tmin > 0 ? tmin : tmax; + len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local); + if (len_diff < 0) len_diff = 0.0f; + need_ray_start_correction_init = false; } } @@ -1250,18 +1307,18 @@ static bool snapDerivedMesh( } /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ else { - float ray_org_local[3]; - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); - BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; - Object_Nearest2dPrecalc neasrest_precalc; - neasrest_precalc.userdata = &treedata_type; - neasrest_precalc.index = -1; + Nearest2dUserData neasrest2d = { + .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .userdata = &treedata_type, + .index = -1}; - nearest2d_precalc(&neasrest_precalc, snapdata, *dist_px, obmat, - ray_org_local, ray_normal_local); + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, snapdata->win_half, + snapdata->depth_range, snapdata->mval, ray_org_local, ray_normal_local); BVHTree_WalkLeafCallback cb_walk_leaf = (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? @@ -1269,17 +1326,17 @@ static bool snapDerivedMesh( BLI_bvhtree_walk_dfs( treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); - if (neasrest_precalc.index != -1) { - copy_v3_v3(r_loc, neasrest_precalc.co); + if (neasrest2d.index != -1) { + copy_v3_v3(r_loc, neasrest2d.co); mul_m4_v3(obmat, r_loc); if (r_no) { - copy_v3_v3(r_no, neasrest_precalc.no); + copy_v3_v3(r_no, neasrest2d.no); mul_m3_v3(timat, r_no); normalize_v3(r_no); } - *dist_px = sqrtf(neasrest_precalc.dist_px_sq); + *dist_px = sqrtf(neasrest2d.dist_px_sq); retval = true; } @@ -1542,12 +1599,18 @@ static bool snapEditMesh( BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; - Object_Nearest2dPrecalc neasrest_precalc; - neasrest_precalc.userdata = &treedata_type; - neasrest_precalc.index = -1; + Nearest2dUserData neasrest2d = { + .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .userdata = &treedata_type, + .index = -1}; - nearest2d_precalc(&neasrest_precalc, snapdata, *dist_px, obmat, - ray_org_local, ray_normal_local); + float lpmat[4][4]; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, snapdata->win_half, + snapdata->depth_range, snapdata->mval, ray_org_local, ray_normal_local); BVHTree_WalkLeafCallback cb_walk_leaf = (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? @@ -1555,17 +1618,17 @@ static bool snapEditMesh( BLI_bvhtree_walk_dfs( treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); - if (neasrest_precalc.index != -1) { - copy_v3_v3(r_loc, neasrest_precalc.co); + if (neasrest2d.index != -1) { + copy_v3_v3(r_loc, neasrest2d.co); mul_m4_v3(obmat, r_loc); if (r_no) { - copy_v3_v3(r_no, neasrest_precalc.no); + copy_v3_v3(r_no, neasrest2d.no); mul_m3_v3(timat, r_no); normalize_v3(r_no); } - *dist_px = sqrtf(neasrest_precalc.dist_px_sq); + *dist_px = sqrtf(neasrest2d.dist_px_sq); retval = true; } -- cgit v1.2.3 From b841d60bf8ac865d456c466892503561fd6ca97c Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 30 Jan 2017 22:49:44 -0300 Subject: Snap System: Return depth by snapping to edges and vertices, because the Ruler only works right this way The Ruler snaps to the element with the lowest depth. --- .../editors/transform/transform_snap_object.c | 45 ++++++++++++++-------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 5d9892cd503..83b04cb7f72 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -235,6 +235,12 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH /** \Common utilities * \{ */ +MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3]) +{ + float dvec[3]; + sub_v3_v3v3(dvec, co, ray_start); + return dot_v3v3(dvec, ray_dir); +} /** * Struct that kepts basic information about a BVHTree build from a editmesh. @@ -509,9 +515,9 @@ static float dist_squared_to_projected_aabb( /* `if rtmax < depth_min`, the hit is behind us */ if (rtmax < data->depth_range[0]) { /* Test if the entire AABB is behind us */ - float dvec[3]; - sub_v3_v3v3(dvec, local_bvmax, data->ray_origin_local); - if (dot_v3v3(dvec, data->ray_direction_local) < (data->depth_range[0])) { + float depth = depth_get( + local_bvmax, data->ray_origin_local, data->ray_direction_local); + if (depth < (data->depth_range[0])) { return FLT_MAX; } } @@ -524,9 +530,9 @@ static float dist_squared_to_projected_aabb( /* `if rtmin < depth_min`, the hit is behing us */ else if (rtmin < data->depth_range[0]) { /* Test if the entire AABB is behind us */ - float dvec[3]; - sub_v3_v3v3(dvec, local_bvmax, data->ray_origin_local); - if (dot_v3v3(dvec, data->ray_direction_local) < (data->depth_range[0])) { + float depth = depth_get( + local_bvmax, data->ray_origin_local, data->ray_direction_local); + if (depth < (data->depth_range[0])) { return FLT_MAX; } } @@ -622,9 +628,7 @@ static float dist_aabb_to_plane( (plane_no[1] < 0) ? bbmax[1] : bbmin[1], (plane_no[2] < 0) ? bbmax[2] : bbmin[2], }; - float dvec[3]; - sub_v3_v3v3(dvec, local_bvmin, plane_co); - return dot_v3v3(dvec, plane_no); + return depth_get(local_bvmin, plane_co, plane_no); } /** \} */ @@ -727,7 +731,7 @@ static bool snapArmature( SnapData *snapdata, Object *ob, bArmature *arm, float obmat[4][4], /* read/write args */ - float *dist_px, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { @@ -813,6 +817,7 @@ static bool snapArmature( if (retval) { *dist_px = sqrtf(dist_px_sq); mul_m4_v3(obmat, r_loc); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); return true; } return false; @@ -822,7 +827,7 @@ static bool snapCurve( SnapData *snapdata, Object *ob, Curve *cu, float obmat[4][4], /* read/write args */ - float *dist_px, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { @@ -909,6 +914,7 @@ static bool snapCurve( if (retval) { *dist_px = sqrtf(dist_px_sq); mul_m4_v3(obmat, r_loc); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); return true; } return false; @@ -919,7 +925,7 @@ static bool snapEmpty( SnapData *snapdata, Object *ob, float obmat[4][4], /* read/write args */ - float *dist_px, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { @@ -942,6 +948,7 @@ static bool snapEmpty( snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq, r_loc)) { *dist_px = sqrtf(dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); retval = true; } break; @@ -957,7 +964,7 @@ static bool snapCamera( const SnapObjectContext *sctx, SnapData *snapdata, Object *object, float obmat[4][4], /* read/write args */ - float *dist_px, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { @@ -1039,6 +1046,7 @@ static bool snapCamera( if (retval) { *dist_px = sqrtf(dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); return true; } return false; @@ -1337,6 +1345,7 @@ static bool snapDerivedMesh( normalize_v3(r_no); } *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); retval = true; } @@ -1629,6 +1638,7 @@ static bool snapEditMesh( normalize_v3(r_no); } *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); retval = true; } @@ -1698,27 +1708,28 @@ static bool snapObject( if (ob->type == OB_ARMATURE) { retval = snapArmature( snapdata, - ob, ob->data, obmat, dist_px, + ob, ob->data, obmat, + ray_depth, dist_px, r_loc, r_no); } else if (ob->type == OB_CURVE) { retval = snapCurve( snapdata, ob, ob->data, obmat, - dist_px, + ray_depth, dist_px, r_loc, r_no); } else if (ob->type == OB_EMPTY) { retval = snapEmpty( snapdata, ob, obmat, - dist_px, + ray_depth, dist_px, r_loc, r_no); } else if (ob->type == OB_CAMERA) { retval = snapCamera( sctx, snapdata, ob, obmat, - dist_px, + ray_depth, dist_px, r_loc, r_no); } } -- cgit v1.2.3 From d07e2416dbdfa89fd698aab2fda4804dd6368f1d Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 30 Jan 2017 23:49:09 -0300 Subject: Fix bug not reported: Ruler/Protractor: Snap to vertices and edges was not considering the depth variation Taking advantage of the area, the depth is decreased 0.01 BU to each loop to give priority to elements in order: Vertice > Edge > Face. This increases the threshold and improves the snap to multiple elements --- .../editors/transform/transform_snap_object.c | 34 ++++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 83b04cb7f72..bed451a32d8 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1114,10 +1114,13 @@ static bool snapDerivedMesh( float lpmat[4][4]; float ray_org_local[3]; + float depth_range_local[2]; if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { mul_m4_m4m4(lpmat, snapdata->pmat, obmat); copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); + depth_range_local[0] = snapdata->depth_range[0] * local_scale; + depth_range_local[1] = local_depth + depth_range_local[0]; } if (do_bb) { @@ -1326,7 +1329,7 @@ static bool snapDerivedMesh( dist_squared_to_projected_aabb_precalc( &neasrest2d.data_precalc, lpmat, snapdata->win_half, - snapdata->depth_range, snapdata->mval, ray_org_local, ray_normal_local); + depth_range_local, snapdata->mval, ray_org_local, ray_normal_local); BVHTree_WalkLeafCallback cb_walk_leaf = (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? @@ -1400,6 +1403,13 @@ static bool snapEditMesh( mul_mat3_m4_v3(imat, ray_normal_local); + /* local scale in normal direction */ + float local_scale = normalize_v3(ray_normal_local); + float local_depth = *ray_depth; + if (local_depth != BVH_RAYCAST_DIST_MAX) { + local_depth *= local_scale; + } + SnapObjectData_EditMesh *sod = NULL; BVHTreeFromEditMesh *treedata = NULL, treedata_stack; @@ -1502,13 +1512,6 @@ static bool snapEditMesh( copy_v3_v3(ray_start_local, snapdata->ray_start); mul_m4_v3(imat, ray_start_local); - /* local scale in normal direction */ - float local_scale = normalize_v3(ray_normal_local); - float local_depth = *ray_depth; - if (local_depth != BVH_RAYCAST_DIST_MAX) { - local_depth *= local_scale; - } - /* Only use closer ray_start in case of ortho view! In perspective one, ray_start * may already been *inside* boundbox, leading to snap failures (see T38409). * Note also ar might be null (see T38435), in this case we assume ray_start is ok! @@ -1615,8 +1618,10 @@ static bool snapEditMesh( .userdata = &treedata_type, .index = -1}; - float lpmat[4][4]; + float lpmat[4][4], depth_range_local[2]; mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + depth_range_local[0] = snapdata->depth_range[0] * local_scale; + depth_range_local[1] = local_depth + depth_range_local[0]; dist_squared_to_projected_aabb_precalc( &neasrest2d.data_precalc, lpmat, snapdata->win_half, snapdata->depth_range, snapdata->mval, ray_org_local, ray_normal_local); @@ -2077,9 +2082,6 @@ static bool transform_snap_context_project_view3d_mixed_impl( for (int i = 0; i < 3; i++) { if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) { - if (use_depth == false) { - ray_depth = BVH_RAYCAST_DIST_MAX; - } if (ED_transform_snap_object_project_view3d( sctx, @@ -2088,6 +2090,14 @@ static bool transform_snap_context_project_view3d_mixed_impl( r_co, r_no)) { is_hit = true; + if (use_depth == false) { + ray_depth = BVH_RAYCAST_DIST_MAX; + } + else { + /* 0.01 is a random but small value to prioritizing + * the first elements of the loop */ + ray_depth -= 0.01f; + } } } } -- cgit v1.2.3 From b5682a6fdd8a3ebbea1fd4a75c72fe8c9c3326c5 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 31 Jan 2017 10:41:25 +0100 Subject: Cleanup: use 'cb_flag', not 'cd_flag' for library_query callbacks. `cd_flag` tends to be used for CustomData flags in mesh area, while for library_query those are rather callback flags... --- source/blender/editors/animation/anim_filter.c | 2 +- source/blender/editors/object/object_relations.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index c12a050e9ba..2f73eb6b71c 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -2223,7 +2223,7 @@ typedef struct tAnimFilterModifiersContext { /* dependency walker callback for modifier dependencies */ -static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cd_flag)) +static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cb_flag)) { tAnimFilterModifiersContext *afm = (tAnimFilterModifiersContext *)afm_ptr; ID *owner_id = &ob->id; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 01c307fa0d2..b5fbe4ba586 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2133,7 +2133,7 @@ enum { }; static int tag_localizable_looper( - void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int UNUSED(cd_flag)) + void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int UNUSED(cb_flag)) { if (*id_pointer) { (*id_pointer)->tag &= ~LIB_TAG_DOIT; -- cgit v1.2.3 From b3690cdecde587119944b88da0259ec96d6fe1ec Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Jan 2017 11:55:29 +0100 Subject: Fix variable shadow and avoid calculating same value twice --- source/blender/editors/transform/transform_snap_object.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index bed451a32d8..d1bcec39611 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1117,12 +1117,13 @@ static bool snapDerivedMesh( float depth_range_local[2]; if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); depth_range_local[0] = snapdata->depth_range[0] * local_scale; depth_range_local[1] = local_depth + depth_range_local[0]; } + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); + if (do_bb) { BoundBox *bb = BKE_object_boundbox_get(ob); @@ -1246,11 +1247,6 @@ static bool snapDerivedMesh( * because even in the Orthografic view, in some cases, * the ray can start inside the object (see T50486) */ if (len_diff > 400.0f) { - float ray_org_local[3]; - - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); - /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with * very far away ray_start values (as returned in case of ortho view3d), see T38358. */ -- cgit v1.2.3 From 75a4c836d60126aaa899c1ac79cb3ad38c5aaa7a Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 31 Jan 2017 17:10:34 -0300 Subject: Snap System: Invert the test order of the elements to snap (useful for ruler) When the function that tests snap on multiple elements starts from the face and ends at the vertex, the transition between elements becomes much smoother. --- .../editors/transform/transform_snap_object.c | 85 +++++++++++++--------- 1 file changed, 50 insertions(+), 35 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index d1bcec39611..5e4aea63bb6 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -387,7 +387,7 @@ typedef struct Nearest2dPrecalc { float ray_direction_local[3]; float ray_inv_dir[3]; - float depth_range[2]; + float ray_min_dist; float pmat[4][4]; /* perspective matrix multiplied by object matrix */ float win_half[2]; @@ -401,12 +401,12 @@ typedef struct Nearest2dPrecalc { static void dist_squared_to_projected_aabb_precalc( struct Nearest2dPrecalc *neasrest_precalc, float lpmat[4][4], const float win_half[2], - const float depth_range[2], const float mval[2], + const float ray_min_dist, const float mval[2], const float ray_origin_local[3], const float ray_direction_local[3]) { copy_m4_m4(neasrest_precalc->pmat, lpmat); copy_v2_v2(neasrest_precalc->win_half, win_half); - copy_v2_v2(neasrest_precalc->depth_range, depth_range); + neasrest_precalc->ray_min_dist = ray_min_dist; copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local); copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local); @@ -513,11 +513,11 @@ static float dist_squared_to_projected_aabb( #define IGNORE_BEHIND_RAY #ifdef IGNORE_BEHIND_RAY /* `if rtmax < depth_min`, the hit is behind us */ - if (rtmax < data->depth_range[0]) { + if (rtmax < data->ray_min_dist) { /* Test if the entire AABB is behind us */ float depth = depth_get( local_bvmax, data->ray_origin_local, data->ray_direction_local); - if (depth < (data->depth_range[0])) { + if (depth < (data->ray_min_dist)) { return FLT_MAX; } } @@ -528,11 +528,11 @@ static float dist_squared_to_projected_aabb( } #ifdef IGNORE_BEHIND_RAY /* `if rtmin < depth_min`, the hit is behing us */ - else if (rtmin < data->depth_range[0]) { + else if (rtmin < data->ray_min_dist) { /* Test if the entire AABB is behind us */ float depth = depth_get( local_bvmax, data->ray_origin_local, data->ray_direction_local); - if (depth < (data->depth_range[0])) { + if (depth < (data->ray_min_dist)) { return FLT_MAX; } } @@ -606,13 +606,13 @@ static float dist_squared_to_projected_aabb( static float dist_squared_to_projected_aabb_simple( float lpmat[4][4], const float win_half[2], - const float depth_range[2], const float mval[2], + const float ray_min_dist, const float mval[2], const float ray_origin_local[3], const float ray_direction_local[3], const float bbmin[3], const float bbmax[3]) { struct Nearest2dPrecalc data; dist_squared_to_projected_aabb_precalc( - &data, lpmat, win_half, depth_range, + &data, lpmat, win_half, ray_min_dist, mval, ray_origin_local, ray_direction_local); bool dummy[3] = {true, true, true}; @@ -646,6 +646,7 @@ typedef struct Nearest2dUserData { bool r_axis_closest[3]; + float depth_range[2]; void *userdata; int index; float co[3]; @@ -674,7 +675,7 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo }; if (test_projected_vert_dist( - neasrest_precalc->depth_range, + data->depth_range, neasrest_precalc->mval, co, neasrest_precalc->pmat, neasrest_precalc->win_half, @@ -697,7 +698,7 @@ static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int i get_edge_verts(data->userdata, index, v_pair); if (test_projected_edge_dist( - neasrest_precalc->depth_range, + data->depth_range, neasrest_precalc->mval, neasrest_precalc->pmat, neasrest_precalc->win_half, @@ -1114,11 +1115,10 @@ static bool snapDerivedMesh( float lpmat[4][4]; float ray_org_local[3]; - float depth_range_local[2]; + float ray_min_dist; if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - depth_range_local[0] = snapdata->depth_range[0] * local_scale; - depth_range_local[1] = local_depth + depth_range_local[0]; + ray_min_dist = snapdata->depth_range[0] * local_scale; } copy_v3_v3(ray_org_local, snapdata->ray_origin); @@ -1137,7 +1137,7 @@ static bool snapDerivedMesh( /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { float dist_px_sq = dist_squared_to_projected_aabb_simple( - lpmat, snapdata->win_half, snapdata->depth_range, snapdata->mval, + lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); if (dist_px_sq > SQUARE(*dist_px)) { @@ -1320,12 +1320,13 @@ static bool snapDerivedMesh( .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, .dist_px_sq = SQUARE(*dist_px), .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, .userdata = &treedata_type, .index = -1}; dist_squared_to_projected_aabb_precalc( &neasrest2d.data_precalc, lpmat, snapdata->win_half, - depth_range_local, snapdata->mval, ray_org_local, ray_normal_local); + ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local); BVHTree_WalkLeafCallback cb_walk_leaf = (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? @@ -1611,16 +1612,16 @@ static bool snapEditMesh( .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, .dist_px_sq = SQUARE(*dist_px), .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, .userdata = &treedata_type, .index = -1}; - float lpmat[4][4], depth_range_local[2]; + float lpmat[4][4]; mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - depth_range_local[0] = snapdata->depth_range[0] * local_scale; - depth_range_local[1] = local_depth + depth_range_local[0]; dist_squared_to_projected_aabb_precalc( &neasrest2d.data_precalc, lpmat, snapdata->win_half, - snapdata->depth_range, snapdata->mval, ray_org_local, ray_normal_local); + (snapdata->depth_range[0] * local_scale), snapdata->mval, + ray_org_local, ray_normal_local); BVHTree_WalkLeafCallback cb_walk_leaf = (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? @@ -2076,23 +2077,37 @@ static bool transform_snap_context_project_view3d_mixed_impl( BLI_assert(snap_to_flag != 0); BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0); - for (int i = 0; i < 3; i++) { - if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) { - - if (ED_transform_snap_object_project_view3d( - sctx, - elem_type[i], params, - mval, dist_px, &ray_depth, - r_co, r_no)) - { - is_hit = true; - if (use_depth == false) { - ray_depth = BVH_RAYCAST_DIST_MAX; - } - else { + if (use_depth) { + const float dist_px_orig = *dist_px; + for (int i = 2; i >= 0; i--) { + if (snap_to_flag & (1 << i)) { + if (i == 0) + *dist_px = dist_px_orig; + if (ED_transform_snap_object_project_view3d( + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) + { /* 0.01 is a random but small value to prioritizing * the first elements of the loop */ - ray_depth -= 0.01f; + ray_depth += 0.01f; + is_hit = true; + } + } + } + } + else { + for (int i = 0; i < 3; i++) { + if (snap_to_flag & (1 << i)) { + if (ED_transform_snap_object_project_view3d( + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) + { + is_hit = true; + break; } } } -- cgit v1.2.3 From 92258f3678b464894479a2939d848341394bfcd1 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 31 Jan 2017 21:43:44 -0300 Subject: Snap System: BVH: Ignore calculations, in parent nodes, used only in perspective view Strangely this change does not affect the performance very much. Suzanne subdividide 6x (ortho view): Before:0.00013983 After :0.00013920 But it makes it easier to read the code --- .../editors/transform/transform_snap_object.c | 35 ++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 5e4aea63bb6..85209b07677 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -389,6 +389,7 @@ typedef struct Nearest2dPrecalc { float ray_min_dist; float pmat[4][4]; /* perspective matrix multiplied by object matrix */ + bool is_persp; float win_half[2]; float mval[2]; @@ -400,11 +401,12 @@ typedef struct Nearest2dPrecalc { */ static void dist_squared_to_projected_aabb_precalc( struct Nearest2dPrecalc *neasrest_precalc, - float lpmat[4][4], const float win_half[2], + float lpmat[4][4], bool is_persp, const float win_half[2], const float ray_min_dist, const float mval[2], const float ray_origin_local[3], const float ray_direction_local[3]) { copy_m4_m4(neasrest_precalc->pmat, lpmat); + neasrest_precalc->is_persp = is_persp; copy_v2_v2(neasrest_precalc->win_half, win_half); neasrest_precalc->ray_min_dist = ray_min_dist; @@ -549,20 +551,24 @@ static float dist_squared_to_projected_aabb( float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]); float (*pmat)[4] = data->pmat; - float depth_a = mul_project_m4_v3_zfac(pmat, va); - float depth_b = depth_a + pmat[main_axis][3] * scale; float va2d[2] = { (dot_m4_v3_row_x(pmat, va) + pmat[3][0]), (dot_m4_v3_row_y(pmat, va) + pmat[3][1]), }; float vb2d[2] = { - (va2d[0] + pmat[main_axis][0] * scale) / depth_b, - (va2d[1] + pmat[main_axis][1] * scale) / depth_b, + (va2d[0] + pmat[main_axis][0] * scale), + (va2d[1] + pmat[main_axis][1] * scale), }; - va2d[0] /= depth_a; - va2d[1] /= depth_a; + if (data->is_persp) { + float depth_a = mul_project_m4_v3_zfac(pmat, va); + float depth_b = depth_a + pmat[main_axis][3] * scale; + va2d[0] /= depth_a; + va2d[1] /= depth_a; + vb2d[0] /= depth_b; + vb2d[1] /= depth_b; + } va2d[0] += 1.0f; va2d[1] += 1.0f; @@ -612,7 +618,7 @@ static float dist_squared_to_projected_aabb_simple( { struct Nearest2dPrecalc data; dist_squared_to_projected_aabb_precalc( - &data, lpmat, win_half, ray_min_dist, + &data, lpmat, true, win_half, ray_min_dist, mval, ray_origin_local, ray_direction_local); bool dummy[3] = {true, true, true}; @@ -641,7 +647,6 @@ static float dist_aabb_to_plane( typedef struct Nearest2dUserData { struct Nearest2dPrecalc data_precalc; - bool is_persp; float dist_px_sq; bool r_axis_closest[3]; @@ -679,7 +684,7 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo neasrest_precalc->mval, co, neasrest_precalc->pmat, neasrest_precalc->win_half, - data->is_persp, + neasrest_precalc->is_persp, &data->dist_px_sq, data->co)) { @@ -702,7 +707,7 @@ static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int i neasrest_precalc->mval, neasrest_precalc->pmat, neasrest_precalc->win_half, - data->is_persp, + neasrest_precalc->is_persp, neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local, v_pair[0], v_pair[1], @@ -1317,7 +1322,6 @@ static bool snapDerivedMesh( BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; Nearest2dUserData neasrest2d = { - .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, .dist_px_sq = SQUARE(*dist_px), .r_axis_closest = {1.0f, 1.0f, 1.0f}, .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, @@ -1325,7 +1329,8 @@ static bool snapDerivedMesh( .index = -1}; dist_squared_to_projected_aabb_precalc( - &neasrest2d.data_precalc, lpmat, snapdata->win_half, + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local); BVHTree_WalkLeafCallback cb_walk_leaf = @@ -1609,7 +1614,6 @@ static bool snapEditMesh( BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; Nearest2dUserData neasrest2d = { - .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, .dist_px_sq = SQUARE(*dist_px), .r_axis_closest = {1.0f, 1.0f, 1.0f}, .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, @@ -1619,7 +1623,8 @@ static bool snapEditMesh( float lpmat[4][4]; mul_m4_m4m4(lpmat, snapdata->pmat, obmat); dist_squared_to_projected_aabb_precalc( - &neasrest2d.data_precalc, lpmat, snapdata->win_half, + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, (snapdata->depth_range[0] * local_scale), snapdata->mval, ray_org_local, ray_normal_local); -- cgit v1.2.3 From fb61711b1a9ef96becec8eb15916f057055f567b Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 1 Feb 2017 12:52:26 +0100 Subject: Fix T50570: pressing pgup or pgdn in any scrollable area irreversably alters scrolling speed. 'page' prop of scroll up/down operators would get stuck once set once by pageup/down keys... Now only take this prop into account if explicitely set, not when its value is inherited from previous run. --- source/blender/editors/interface/view2d_ops.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index d2b2f12c1a5..fa2c1f25cfc 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -447,7 +447,8 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltax", 0); RNA_int_set(op->ptr, "deltay", -40); - if (RNA_boolean_get(op->ptr, "page")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page"); + if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) { ARegion *ar = CTX_wm_region(C); RNA_int_set(op->ptr, "deltay", ar->v2d.mask.ymin - ar->v2d.mask.ymax); } @@ -497,7 +498,8 @@ static int view_scrollup_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltax", 0); RNA_int_set(op->ptr, "deltay", 40); - if (RNA_boolean_get(op->ptr, "page")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page"); + if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) { ARegion *ar = CTX_wm_region(C); RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&ar->v2d.mask)); } -- cgit v1.2.3 From feb588060a6c33c42b3bbf4a5c15283644a342f9 Mon Sep 17 00:00:00 2001 From: raa Date: Thu, 2 Feb 2017 17:30:50 +0300 Subject: Fix T50497: prop_search not correctly drew in UI (D2473) --- .../blender/editors/interface/interface_layout.c | 28 ++++++++-------------- 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 7262b453e02..ca2538022b0 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2078,15 +2078,7 @@ static void ui_litem_estimate_row(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); - if (item->type == ITEM_BUTTON) { - const uiBut *but = ((uiButtonItem *)item)->but; - const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0'); - - min_size_flag = min_size_flag && icon_only; - } - else { - min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); - } + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); litem->w += itemw; litem->h = MAX2(itemh, litem->h); @@ -2232,15 +2224,7 @@ static void ui_litem_estimate_column(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); - if (item->type == ITEM_BUTTON) { - const uiBut *but = ((uiButtonItem *)item)->but; - const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0'); - - min_size_flag = min_size_flag && icon_only; - } - else { - min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); - } + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); litem->w = MAX2(litem->w, itemw); litem->h += itemh; @@ -3336,6 +3320,14 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but) bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem"); bitem->item.type = ITEM_BUTTON; bitem->but = but; + + int w, h; + ui_item_size((uiItem *)bitem, &w, &h); + /* XXX uiBut hasn't scaled yet + * we can flag the button as not expandable, depending on its size */ + if (w <= 2 * UI_UNIT_X) + bitem->item.flag |= UI_ITEM_MIN; + BLI_addtail(&layout->items, bitem); if (layout->context) { -- cgit v1.2.3 From 9f67367f0aae46f022adb9b47d91c01b35ab9b0f Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 2 Feb 2017 21:37:53 +0100 Subject: Fix T50084: Adding torus re-orders UV layers. Issue was indeed in join operation, mesh in which we join all others could be re-added to final data after others, leading to undesired re-ordering of CD layers, and existing vertices etc. being shifted away from their original indices, etc. All kind of more or less bad and undesired changes, fixed by always re-inserting destination mesh first. Also cleaned up a bit that code, it was doing some rather non-recommanded things (like allocating zero-sized mem, doing own coocking to remove a data-block from main, etc.). --- source/blender/editors/mesh/meshtools.c | 444 +++++++++++++++++--------------- 1 file changed, 238 insertions(+), 206 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index b26989113d4..743efb246ab 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -75,26 +75,213 @@ /* join selected meshes into the active mesh, context sensitive * return 0 if no join is made (error) and 1 if the join is done */ +static void join_mesh_single( + Main *bmain, Scene *scene, + Object *ob_dst, Base *base_src, float imat[4][4], + MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp, + CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata, + int totvert, int totedge, int totloop, int totpoly, + Key *key, Key *nkey, + Material **matar, int *matmap, int totcol, + int *vertofs, int *edgeofs, int *loopofs, int *polyofs) +{ + int a, b; + + Mesh *me = base_src->object->data; + MVert *mvert = *mvert_pp; + MEdge *medge = *medge_pp; + MLoop *mloop = *mloop_pp; + MPoly *mpoly = *mpoly_pp; + + if (me->totvert) { + /* merge customdata flag */ + ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag; + + /* standard data */ + CustomData_merge(&me->vdata, vdata, CD_MASK_MESH, CD_DEFAULT, totvert); + CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert); + + /* vertex groups */ + MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT); + + /* NB: vertex groups here are new version */ + if (dvert) { + for (a = 0; a < me->totvert; a++) { + for (b = 0; b < dvert[a].totweight; b++) { + /* Find the old vertex group */ + bDeformGroup *dg, *odg = BLI_findlink(&base_src->object->defbase, dvert[a].dw[b].def_nr); + int index; + if (odg) { + /* Search for a match in the new object, and set new index */ + for (dg = ob_dst->defbase.first, index = 0; dg; dg = dg->next, index++) { + if (STREQ(dg->name, odg->name)) { + dvert[a].dw[b].def_nr = index; + break; + } + } + } + } + } + } + + /* if this is the object we're merging into, no need to do anything */ + if (base_src->object != ob_dst) { + float cmat[4][4]; + + /* watch this: switch matmul order really goes wrong */ + mul_m4_m4m4(cmat, imat, base_src->object->obmat); + + /* transform vertex coordinates into new space */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) { + mul_m4_v3(cmat, mvert->co); + } + + /* for each shapekey in destination mesh: + * - if there's a matching one, copy it across (will need to transform vertices into new space...) + * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) + */ + if (key) { + /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs; + + /* check if this mesh has such a shapekey */ + KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL; + if (okb) { + /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ + float (*ocos)[3] = okb->data; + for (a = 0; a < me->totvert; a++, cos++, ocos++) { + copy_v3_v3(*cos, *ocos); + mul_m4_v3(cmat, *cos); + } + } + else { + /* copy this mesh's vertex coordinates to the destination shapekey */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { + copy_v3_v3(*cos, mvert->co); + } + } + } + } + } + else { + /* for each shapekey in destination mesh: + * - if it was an 'original', copy the appropriate data from nkey + * - otherwise, copy across plain coordinates (no need to transform coordinates) + */ + if (key) { + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs; + + /* check if this was one of the original shapekeys */ + KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; + if (okb) { + /* copy this mesh's shapekey to the destination shapekey */ + float (*ocos)[3] = okb->data; + for (a = 0; a < me->totvert; a++, cos++, ocos++) { + copy_v3_v3(*cos, *ocos); + } + } + else { + /* copy base-coordinates to the destination shapekey */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { + copy_v3_v3(*cos, mvert->co); + } + } + } + } + } + } + + if (me->totedge) { + CustomData_merge(&me->edata, edata, CD_MASK_MESH, CD_DEFAULT, totedge); + CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge); + + for (a = 0; a < me->totedge; a++, medge++) { + medge->v1 += *vertofs; + medge->v2 += *vertofs; + } + } + + if (me->totloop) { + if (base_src->object != ob_dst) { + MultiresModifierData *mmd; + + multiresModifier_prepare_join(scene, base_src->object, ob_dst); + + if ((mmd = get_multires_modifier(scene, base_src->object, true))) { + ED_object_iter_other(bmain, base_src->object, true, + ED_object_multires_update_totlevels_cb, + &mmd->totlvl); + } + } + + CustomData_merge(&me->ldata, ldata, CD_MASK_MESH, CD_DEFAULT, totloop); + CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop); + + for (a = 0; a < me->totloop; a++, mloop++) { + mloop->v += *vertofs; + mloop->e += *edgeofs; + } + } + + if (me->totpoly) { + if (matmap) { + /* make mapping for materials */ + for (a = 1; a <= base_src->object->totcol; a++) { + Material *ma = give_current_material(base_src->object, a); + + for (b = 0; b < totcol; b++) { + if (ma == matar[b]) { + matmap[a - 1] = b; + break; + } + } + } + } + + CustomData_merge(&me->pdata, pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); + CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly); + + for (a = 0; a < me->totpoly; a++, mpoly++) { + mpoly->loopstart += *loopofs; + mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0; + } + } + + /* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */ + *vertofs += me->totvert; + *mvert_pp += me->totvert; + *edgeofs += me->totedge; + *medge_pp += me->totedge; + *loopofs += me->totloop; + *mloop_pp += me->totloop; + *polyofs += me->totpoly; + *mpoly_pp += me->totpoly; +} + int join_mesh_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); - Material **matar, *ma; + Base *ob_base = CTX_data_active_base(C); + Object *ob = ob_base->object; + Material **matar = NULL, *ma; Mesh *me; - MVert *mvert, *mv; + MVert *mvert = NULL; MEdge *medge = NULL; MPoly *mpoly = NULL; MLoop *mloop = NULL; Key *key, *nkey = NULL; - KeyBlock *kb, *okb, *kbn; - float imat[4][4], cmat[4][4], *fp1, *fp2; + KeyBlock *kb, *kbn; + float imat[4][4]; int a, b, totcol, totmat = 0, totedge = 0, totvert = 0; int totloop = 0, totpoly = 0, vertofs, *matmap = NULL; - int i, j, index, haskey = 0, edgeofs, loopofs, polyofs; + int i, haskey = 0, edgeofs, loopofs, polyofs; bool ok = false; bDeformGroup *dg, *odg; - MDeformVert *dvert; CustomData vdata, edata, fdata, ldata, pdata; if (scene->obedit) { @@ -154,8 +341,10 @@ int join_mesh_exec(bContext *C, wmOperator *op) BKE_mesh_tessface_clear(me); /* new material indices and material array */ - matar = MEM_callocN(sizeof(void *) * totmat, "join_mesh matar"); - if (totmat) matmap = MEM_callocN(sizeof(int) * totmat, "join_mesh matmap"); + if (totmat) { + matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar"); + matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap"); + } totcol = ob->totcol; /* obact materials in new main array, is nicer start! */ @@ -214,7 +403,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) ma = give_current_material(base->object, a); for (b = 0; b < totcol; b++) { - if (ma == matar[b]) break; + if (ma == matar[b]) { + break; + } } if (b == totcol) { matar[b] = ma; @@ -223,8 +414,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) } totcol++; } - if (totcol >= MAXMAT) + if (totcol >= MAXMAT) { break; + } } } @@ -301,187 +493,41 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* inverse transform for all selected meshes in this object */ invert_m4_m4(imat, ob->obmat); - + + /* Add back active mesh first. This allows to keep things similar as they were, as much as possible (i.e. data from + * active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084. + */ + join_mesh_single( + bmain, scene, + ob, ob_base, imat, + &mvert, &medge, &mloop, &mpoly, + &vdata, &edata, &ldata, &pdata, + totvert, totedge, totloop, totpoly, + key, nkey, + matar, matmap, totcol, + &vertofs, &edgeofs, &loopofs, &polyofs); + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { + if (base->object == ob) { + continue; + } /* only join if this is a mesh */ if (base->object->type == OB_MESH) { - me = base->object->data; - - if (me->totvert) { - - /* merge customdata flag */ - ((Mesh *)ob->data)->cd_flag |= me->cd_flag; - - /* standard data */ - CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); - CustomData_copy_data_named(&me->vdata, &vdata, 0, vertofs, me->totvert); - - /* vertex groups */ - dvert = CustomData_get(&vdata, vertofs, CD_MDEFORMVERT); - - /* NB: vertex groups here are new version */ - if (dvert) { - for (i = 0; i < me->totvert; i++) { - for (j = 0; j < dvert[i].totweight; j++) { - /* Find the old vertex group */ - odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr); - if (odg) { - /* Search for a match in the new object, and set new index */ - for (dg = ob->defbase.first, index = 0; dg; dg = dg->next, index++) { - if (STREQ(dg->name, odg->name)) { - dvert[i].dw[j].def_nr = index; - break; - } - } - } - } - } - } - - /* if this is the object we're merging into, no need to do anything */ - if (base->object != ob) { - /* watch this: switch matmul order really goes wrong */ - mul_m4_m4m4(cmat, imat, base->object->obmat); - - /* transform vertex coordinates into new space */ - for (a = 0, mv = mvert; a < me->totvert; a++, mv++) { - mul_m4_v3(cmat, mv->co); - } - - /* for each shapekey in destination mesh: - * - if there's a matching one, copy it across (will need to transform vertices into new space...) - * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) - */ - if (key) { - /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ - for (kb = key->block.first; kb; kb = kb->next) { - /* get pointer to where to write data for this mesh in shapekey's data array */ - fp1 = ((float *)kb->data) + (vertofs * 3); - - /* check if this mesh has such a shapekey */ - okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL; - - if (okb) { - /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ - fp2 = ((float *)(okb->data)); - for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { - copy_v3_v3(fp1, fp2); - mul_m4_v3(cmat, fp1); - } - } - else { - /* copy this mesh's vertex coordinates to the destination shapekey */ - mv = mvert; - for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { - copy_v3_v3(fp1, mv->co); - } - } - } - } - } - else { - /* for each shapekey in destination mesh: - * - if it was an 'original', copy the appropriate data from nkey - * - otherwise, copy across plain coordinates (no need to transform coordinates) - */ - if (key) { - for (kb = key->block.first; kb; kb = kb->next) { - /* get pointer to where to write data for this mesh in shapekey's data array */ - fp1 = ((float *)kb->data) + (vertofs * 3); - - /* check if this was one of the original shapekeys */ - okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; - if (okb) { - /* copy this mesh's shapekey to the destination shapekey */ - fp2 = ((float *)(okb->data)); - for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { - copy_v3_v3(fp1, fp2); - } - } - else { - /* copy base-coordinates to the destination shapekey */ - mv = mvert; - for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { - copy_v3_v3(fp1, mv->co); - } - } - } - } - } - - /* advance mvert pointer to end of base mesh's data */ - mvert += me->totvert; - } - - if (me->totedge) { - CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); - CustomData_copy_data_named(&me->edata, &edata, 0, edgeofs, me->totedge); - - for (a = 0; a < me->totedge; a++, medge++) { - medge->v1 += vertofs; - medge->v2 += vertofs; - } - } - - if (me->totloop) { - if (base->object != ob) { - MultiresModifierData *mmd; - - multiresModifier_prepare_join(scene, base->object, ob); + join_mesh_single( + bmain, scene, + ob, base, imat, + &mvert, &medge, &mloop, &mpoly, + &vdata, &edata, &ldata, &pdata, + totvert, totedge, totloop, totpoly, + key, nkey, + matar, matmap, totcol, + &vertofs, &edgeofs, &loopofs, &polyofs); - if ((mmd = get_multires_modifier(scene, base->object, true))) { - ED_object_iter_other(bmain, base->object, true, - ED_object_multires_update_totlevels_cb, - &mmd->totlvl); - } - } - - CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop); - CustomData_copy_data_named(&me->ldata, &ldata, 0, loopofs, me->totloop); - - for (a = 0; a < me->totloop; a++, mloop++) { - mloop->v += vertofs; - mloop->e += edgeofs; - } - } - - if (me->totpoly) { - if (totmat) { - /* make mapping for materials */ - for (a = 1; a <= base->object->totcol; a++) { - ma = give_current_material(base->object, a); - - for (b = 0; b < totcol; b++) { - if (ma == matar[b]) { - matmap[a - 1] = b; - break; - } - } - } - } - - CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); - CustomData_copy_data_named(&me->pdata, &pdata, 0, polyofs, me->totpoly); - - for (a = 0; a < me->totpoly; a++, mpoly++) { - mpoly->loopstart += loopofs; - mpoly->mat_nr = matmap ? matmap[(int)mpoly->mat_nr] : 0; - } - - polyofs += me->totpoly; - } - - /* these are used for relinking (cannot be set earlier, - * or else reattaching goes wrong) - */ - vertofs += me->totvert; - edgeofs += me->totedge; - loopofs += me->totloop; - /* free base, now that data is merged */ - if (base->object != ob) + if (base->object != ob) { ED_base_object_free_and_unlink(bmain, scene, base); + } } } CTX_DATA_END; @@ -529,34 +575,20 @@ int join_mesh_exec(bContext *C, wmOperator *op) if (totcol) { me->mat = matar; - ob->mat = MEM_callocN(sizeof(void *) * totcol, "join obmatar"); - ob->matbits = MEM_callocN(sizeof(char) * totcol, "join obmatbits"); + ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar"); + ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits"); + MEM_freeN(matmap); } - else - MEM_freeN(matar); - + ob->totcol = me->totcol = totcol; - if (matmap) MEM_freeN(matmap); - /* other mesh users */ test_all_objects_materials(bmain, (ID *)me); /* free temp copy of destination shapekeys (if applicable) */ if (nkey) { - /* XXX 2.5 Animato */ -#if 0 - /* free it's ipo too - both are not actually freed from memory yet as ID-blocks */ - if (nkey->ipo) { - BKE_ipo_free(nkey->ipo); - BLI_remlink(&bmain->ipo, nkey->ipo); - MEM_freeN(nkey->ipo); - } -#endif - - BKE_key_free(nkey); - BLI_remlink(&bmain->key, nkey); - MEM_freeN(nkey); + /* We can assume nobody is using that ID currently. */ + BKE_libblock_free_ex(bmain, nkey, false, false); } /* ensure newly inserted keys are time sorted */ @@ -564,7 +596,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) BKE_key_sort(key); } - DAG_relations_tag_update(bmain); // removed objects, need to rebuild dag + DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); -- cgit v1.2.3 From ddf99214dc0677542d6ca300c3ee49549e6514bc Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 3 Feb 2017 02:27:57 -0300 Subject: fix T49494: snap_align_rotation should use a local pivot to make the transformation The problem was simple, just transform the global coordinates of t->tsnap.snapTarget to local coordinates. (Some comments were added to the code) --- source/blender/editors/transform/transform.c | 27 +++++++++++++++++++++++---- source/blender/editors/transform/transform.h | 4 ++-- 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 31ffa019e4e..5929aba48a4 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -3722,6 +3722,12 @@ static void initRotation(TransInfo *t) copy_v3_v3(t->axis_orig, t->axis); } +/** + * Applies values of rotation to `td->loc` and `td->ext->quat` + * based on a rotation matrix (mat) and a pivot (center). + * + * Protected axis and other transform settings are taken into account. + */ static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], const float *center) { float vec[3], totmat[3][3], smat[3][3]; @@ -4339,9 +4345,22 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) { TransData *td = t->data; float tvec[3]; - int i; - for (i = 0; i < t->total; i++, td++) { + /* you only need to "apply_snap_align_rotation" when a snap point is found (t->tsnap.status & POINT_INIT) + * so, maybe inside this function is not the best place to apply this rotation. + * but you need "handle snapping rotation before doing the translation" (really?) */ + const bool apply_snap_align_rotation = usingSnappingNormal(t) && (t->tsnap.status & POINT_INIT); + float pivot[3]; + if (apply_snap_align_rotation) { + copy_v3_v3(pivot, t->tsnap.snapTarget); + /* The pivot has to be in local-space (see T49494) */ + if (t->flag & (T_EDIT | T_POSE)) { + Object *ob = t->obedit ? t->obedit : t->poseobj; + mul_m4_v3(ob->imat, pivot); + } + } + + for (int i = 0; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; @@ -4352,7 +4371,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) bool use_rotate_offset = false; /* handle snapping rotation before doing the translation */ - if (usingSnappingNormal(t)) { + if (apply_snap_align_rotation) { float mat[3][3]; if (validSnappingNormal(t)) { @@ -4370,7 +4389,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) unit_m3(mat); } - ElementRotation_ex(t, td, mat, t->tsnap.snapTarget); + ElementRotation_ex(t, td, mat, pivot); if (td->loc) { use_rotate_offset = true; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 7ea4448a44e..d60eb2f0778 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -84,8 +84,8 @@ typedef struct TransSnap { bool peel; bool snap_spatial_grid; short status; - float snapPoint[3]; /* snapping from this point */ - float snapTarget[3]; /* to this point */ + float snapPoint[3]; /* snapping from this point (in global-space)*/ + float snapTarget[3]; /* to this point (in global-space)*/ float snapNormal[3]; char snapNodeBorder; ListBase points; -- cgit v1.2.3 From f3a7104adbe23e85b1ff1ef010d01c80b0868f6b Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 3 Feb 2017 15:47:44 +0100 Subject: Fix T49860: Copying vgroups between objects sharing the same obdata was not possible. Pretty straight forward actually, just do not bother about obdata part of vgroups in that case, only copy object part of it. And let's curse once again those stuff spread accross several types of data-blocks... --- source/blender/editors/object/object_vgroup.c | 61 +++++++++++++++------------ 1 file changed, 33 insertions(+), 28 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 56f59dca9a1..3c406764157 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -363,8 +363,8 @@ void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot /* matching index only */ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) { - MDeformVert **dvert_array_from, **dvf; - MDeformVert **dvert_array, **dv; + MDeformVert **dvert_array_from = NULL, **dvf; + MDeformVert **dvert_array = NULL, **dv; int dvert_tot_from; int dvert_tot; int i; @@ -375,26 +375,30 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) if (ob == ob_from) return true; - ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false); - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); - - if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) { + /* in case we copy vgroup between two objects using same data, we only have to care about object side of things. */ + if (ob->data != ob_from->data) { + ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false); ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); - new_vgroup = true; - } - if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) { + if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) { + ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); + new_vgroup = true; + } - if (dvert_array) MEM_freeN(dvert_array); - if (dvert_array_from) MEM_freeN(dvert_array_from); + if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) { + if (dvert_array) + MEM_freeN(dvert_array); + if (dvert_array_from) + MEM_freeN(dvert_array_from); - if (new_vgroup == true) { - /* free the newly added vgroup since it wasn't compatible */ - BKE_object_defgroup_remove_all(ob); - } + if (new_vgroup == true) { + /* free the newly added vgroup since it wasn't compatible */ + BKE_object_defgroup_remove_all(ob); + } - /* if true: both are 0 and nothing needs changing, consider this a success */ - return (dvert_tot == dvert_tot_from); + /* if true: both are 0 and nothing needs changing, consider this a success */ + return (dvert_tot == dvert_tot_from); + } } /* do the copy */ @@ -412,22 +416,23 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) MEM_freeN(remap); } - dvf = dvert_array_from; - dv = dvert_array; + if (dvert_array_from != NULL && dvert_array != NULL) { + dvf = dvert_array_from; + dv = dvert_array; - for (i = 0; i < dvert_tot; i++, dvf++, dv++) { - if ((*dv)->dw) - MEM_freeN((*dv)->dw); + for (i = 0; i < dvert_tot; i++, dvf++, dv++) { + MEM_SAFE_FREE((*dv)->dw); + *(*dv) = *(*dvf); - *(*dv) = *(*dvf); + if ((*dv)->dw) { + (*dv)->dw = MEM_dupallocN((*dv)->dw); + } + } - if ((*dv)->dw) - (*dv)->dw = MEM_dupallocN((*dv)->dw); + MEM_freeN(dvert_array); + MEM_freeN(dvert_array_from); } - MEM_freeN(dvert_array); - MEM_freeN(dvert_array_from); - return true; } -- cgit v1.2.3 From 0b4a9caf51244fb85efea9d2fb41335f87cda762 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 3 Feb 2017 12:57:02 -0300 Subject: Forgotten in committee ddf99214dc06 In obect mode, the rotation matrix need to be restored to the initial value if a snap point is not found --- source/blender/editors/transform/transform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 5929aba48a4..1916f9b4dab 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4346,10 +4346,10 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) TransData *td = t->data; float tvec[3]; - /* you only need to "apply_snap_align_rotation" when a snap point is found (t->tsnap.status & POINT_INIT) + /* The ideal would be "apply_snap_align_rotation" only when a snap point is found * so, maybe inside this function is not the best place to apply this rotation. * but you need "handle snapping rotation before doing the translation" (really?) */ - const bool apply_snap_align_rotation = usingSnappingNormal(t) && (t->tsnap.status & POINT_INIT); + const bool apply_snap_align_rotation = usingSnappingNormal(t);// && (t->tsnap.status & POINT_INIT); float pivot[3]; if (apply_snap_align_rotation) { copy_v3_v3(pivot, t->tsnap.snapTarget); -- cgit v1.2.3 From 21f376780941f986e99db83793409c3222bca091 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 3 Feb 2017 13:15:44 -0300 Subject: fix T46892: snap to closest point now works with Individual Origins The code looks for the closest element between its centers. In the case of islands, the center of each vertex is the center of the island. The solution here is to skip the search for islands when the operation is translation --- source/blender/editors/transform/transform_conversions.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index ce3d903b8f6..091a5773cf0 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2393,7 +2393,12 @@ static void createTransEditVerts(TransInfo *t) editmesh_set_connectivity_distance(em->bm, mtx, dists); } - if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + /* Only in case of rotation and resize, we want the elements of the edited + * object to behave as groups whose pivot are the individual origins + * + * TODO: use island_info to detect the closest point when the "Snap Target" + * in Blender UI is "Closest" */ + if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) { island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map); } -- cgit v1.2.3 From a0561a05efc93a1d8778dedae0bce680650d9d08 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 3 Feb 2017 19:03:31 -0300 Subject: Remove flag: `SNAP_OBJECT_USE_CACHE` from snap_context Since the cache is created in one way or another, this flag is not really making a difference More details here: D2496 --- .../blender/editors/armature/editarmature_sketch.c | 5 + .../include/ED_transform_snap_object_context.h | 4 - source/blender/editors/mesh/editmesh_tools.c | 2 +- source/blender/editors/space_view3d/view3d_ruler.c | 2 +- source/blender/editors/space_view3d/view3d_walk.c | 2 +- source/blender/editors/transform/transform_snap.c | 2 +- .../editors/transform/transform_snap_object.c | 899 ++++++++++----------- 7 files changed, 438 insertions(+), 478 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index cc4c1809fbc..f6c04e9570a 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -970,6 +970,9 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S ToolSettings *ts = CTX_data_tool_settings(C); int point_added = 0; + /* TODO: Since the function `ED_transform_snap_object_context_create_view3d` creates a cache, + * the ideal would be to call this function only at the beginning of the snap operation, + * or at the beginning of the operator itself */ struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( CTX_data_main(C), CTX_data_scene(C), 0, CTX_wm_region(C), CTX_wm_view3d(C)); @@ -1038,6 +1041,8 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S } } + /* TODO: The ideal would be to call this function only once. + * At the end of the operator */ ED_transform_snap_object_context_destroy(snap_context); return point_added; } diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 7944b434057..6eaae49912c 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -65,10 +65,6 @@ struct SnapObjectParams { unsigned int use_object_edit_cage : 1; }; -enum { - SNAP_OBJECT_USE_CACHE = (1 << 0), -}; - typedef struct SnapObjectContext SnapObjectContext; SnapObjectContext *ED_transform_snap_object_context_create( struct Main *bmain, struct Scene *scene, int flag); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 8f004bcf72b..65ee097e8e1 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -306,7 +306,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) ED_view3d_init_mats_rv3d(obedit, ar->regiondata); struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE, + CTX_data_main(C), CTX_data_scene(C), 0, ar, CTX_wm_view3d(C)); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index 688f459108b..aefe30bbe32 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -280,7 +280,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) } else if (state == RULER_STATE_DRAG) { ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE, + CTX_data_main(C), CTX_data_scene(C), 0, ruler_info->ar, CTX_wm_view3d(C)); } else { diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 17c08ed4205..542dc410bc3 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -588,7 +588,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->rv3d->rflag |= RV3D_NAVIGATING; walk->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), walk->scene, SNAP_OBJECT_USE_CACHE, + CTX_data_main(C), walk->scene, 0, walk->ar, walk->v3d); walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 87ac54b2bd9..318d2718969 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -601,7 +601,7 @@ static void initSnappingMode(TransInfo *t) if (t->spacetype == SPACE_VIEW3D) { if (t->tsnap.object_context == NULL) { t->tsnap.object_context = ED_transform_snap_object_context_create_view3d( - G.main, t->scene, SNAP_OBJECT_USE_CACHE, + G.main, t->scene, 0, t->ar, t->view); ED_transform_snap_object_context_set_editmesh_callbacks( diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 85209b07677..07617ec577c 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1092,274 +1092,259 @@ static bool snapDerivedMesh( } } - { - bool need_ray_start_correction_init = - (snapdata->snap_to == SCE_SNAP_MODE_FACE) && - (snapdata->view_proj == VIEW_PROJ_ORTHO); + bool need_ray_start_correction_init = + (snapdata->snap_to == SCE_SNAP_MODE_FACE) && + (snapdata->view_proj == VIEW_PROJ_ORTHO); - float imat[4][4]; - float timat[3][3]; /* transpose inverse matrix for normals */ - float ray_start_local[3], ray_normal_local[3]; - float local_scale, local_depth, len_diff; + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_start_local[3], ray_normal_local[3]; + float local_scale, local_depth, len_diff; - invert_m4_m4(imat, obmat); - transpose_m3_m4(timat, imat); + invert_m4_m4(imat, obmat); + transpose_m3_m4(timat, imat); - copy_v3_v3(ray_start_local, snapdata->ray_start); - copy_v3_v3(ray_normal_local, snapdata->ray_dir); + copy_v3_v3(ray_start_local, snapdata->ray_start); + copy_v3_v3(ray_normal_local, snapdata->ray_dir); - mul_m4_v3(imat, ray_start_local); - mul_mat3_m4_v3(imat, ray_normal_local); + mul_m4_v3(imat, ray_start_local); + mul_mat3_m4_v3(imat, ray_normal_local); - /* local scale in normal direction */ - local_scale = normalize_v3(ray_normal_local); - local_depth = *ray_depth; - if (local_depth != BVH_RAYCAST_DIST_MAX) { - local_depth *= local_scale; - } + /* local scale in normal direction */ + local_scale = normalize_v3(ray_normal_local); + local_depth = *ray_depth; + if (local_depth != BVH_RAYCAST_DIST_MAX) { + local_depth *= local_scale; + } - float lpmat[4][4]; - float ray_org_local[3]; - float ray_min_dist; - if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { - mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - ray_min_dist = snapdata->depth_range[0] * local_scale; - } + float lpmat[4][4]; + float ray_org_local[3]; + float ray_min_dist; + if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + ray_min_dist = snapdata->depth_range[0] * local_scale; + } - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); - if (do_bb) { - BoundBox *bb = BKE_object_boundbox_get(ob); + if (do_bb) { + BoundBox *bb = BKE_object_boundbox_get(ob); - if (bb) { - BoundBox bb_temp; + if (bb) { + BoundBox bb_temp; - /* We cannot afford a bounding box with some null dimension, which may happen in some cases... - * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */ - bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f); + /* We cannot afford a bounding box with some null dimension, which may happen in some cases... + * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */ + bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f); - /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */ - if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { - float dist_px_sq = dist_squared_to_projected_aabb_simple( - lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, - ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); - if (dist_px_sq > SQUARE(*dist_px)) - { - return retval; - } + /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */ + if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { + float dist_px_sq = dist_squared_to_projected_aabb_simple( + lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, + ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); + if (dist_px_sq > SQUARE(*dist_px)) + { + return retval; } - else { - /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ - if (!isect_ray_aabb_v3_simple( - ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) - { - return retval; - } + } + else { + /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ + if (!isect_ray_aabb_v3_simple( + ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) + { + return retval; } - /* was local_depth, see: T47838 */ - len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local); - if (len_diff < 0) len_diff = 0.0f; - need_ray_start_correction_init = false; } + /* was local_depth, see: T47838 */ + len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local); + if (len_diff < 0) len_diff = 0.0f; + need_ray_start_correction_init = false; } + } - SnapObjectData_Mesh *sod = NULL; - BVHTreeFromMesh *treedata = NULL, treedata_stack; - - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { - sod = *sod_p; - } - else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_MESH; - } + SnapObjectData_Mesh *sod = NULL; + BVHTreeFromMesh *treedata = NULL; - int tree_index = -1; - switch (snapdata->snap_to) { - case SCE_SNAP_MODE_FACE: - tree_index = 2; - break; - case SCE_SNAP_MODE_EDGE: - tree_index = 1; - break; - case SCE_SNAP_MODE_VERTEX: - tree_index = 0; - break; - } - if (tree_index != -1) { - if (sod->bvh_trees[tree_index] == NULL) { - sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); - } - treedata = sod->bvh_trees[tree_index]; + void **sod_p; + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + sod = *sod_p; + } + else { + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_MESH; + } - /* the tree is owned by the DM and may have been freed since we last used! */ - if (treedata && treedata->tree) { - if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) { - free_bvhtree_from_mesh(treedata); - } - } - } - } - else { - treedata = &treedata_stack; - memset(treedata, 0, sizeof(*treedata)); + int tree_index = -1; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + tree_index = 2; + break; + case SCE_SNAP_MODE_EDGE: + tree_index = 1; + break; + case SCE_SNAP_MODE_VERTEX: + tree_index = 0; + break; + } + if (tree_index != -1) { + if (sod->bvh_trees[tree_index] == NULL) { + sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); } + treedata = sod->bvh_trees[tree_index]; - if (treedata && treedata->tree == NULL) { - switch (snapdata->snap_to) { - case SCE_SNAP_MODE_FACE: - bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6); - break; - case SCE_SNAP_MODE_EDGE: - bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6); - break; - case SCE_SNAP_MODE_VERTEX: - bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6); - break; + /* the tree is owned by the DM and may have been freed since we last used! */ + if (treedata && treedata->tree) { + if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) { + free_bvhtree_from_mesh(treedata); } } + } - if (!treedata || !treedata->tree) { - return retval; + if (treedata && treedata->tree == NULL) { + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6); + break; + case SCE_SNAP_MODE_EDGE: + bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6); + break; + case SCE_SNAP_MODE_VERTEX: + bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6); + break; } + } + if (!treedata || !treedata->tree) { + return retval; + } - if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { - /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already - * been *inside* boundbox, leading to snap failures (see T38409). - * Note also ar might be null (see T38435), in this case we assume ray_start is ok! - */ - if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ - if (need_ray_start_correction_init) { - /* We *need* a reasonably valid len_diff in this case. - * Use BHVTree to find the closest face from ray_start_local. - */ - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); - if (nearest.index != -1) { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - } - } - /* You need to make sure that ray_start is really far away, - * because even in the Orthografic view, in some cases, - * the ray can start inside the object (see T50486) */ - if (len_diff > 400.0f) { - /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with - * very far away ray_start values (as returned in case of ortho view3d), see T38358. - */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, - len_diff + snapdata->depth_range[0] * local_scale); - local_depth -= len_diff; + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { + /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already + * been *inside* boundbox, leading to snap failures (see T38409). + * Note also ar might be null (see T38435), in this case we assume ray_start is ok! + */ + if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ + if (need_ray_start_correction_init) { + /* We *need* a reasonably valid len_diff in this case. + * Use BHVTree to find the closest face from ray_start_local. + */ + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); + if (nearest.index != -1) { + float dvec[3]; + sub_v3_v3v3(dvec, nearest.co, ray_start_local); + len_diff = dot_v3v3(dvec, ray_normal_local); } - else len_diff = 0.0f; - } - else { - len_diff = 0.0f; } - if (r_hit_list) { - struct RayCastAll_Data data; - - data.bvhdata = treedata; - data.raycast_callback = treedata->raycast_callback; - data.obmat = obmat; - data.timat = timat; - data.len_diff = len_diff; - data.local_scale = local_scale; - data.ob = ob; - data.ob_uuid = ob_index; - data.hit_list = r_hit_list; - data.retval = retval; - - BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); - - retval = data.retval; + /* You need to make sure that ray_start is really far away, + * because even in the Orthografic view, in some cases, + * the ray can start inside the object (see T50486) */ + if (len_diff > 400.0f) { + /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with + * very far away ray_start values (as returned in case of ortho view3d), see T38358. + */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + madd_v3_v3v3fl( + ray_start_local, ray_org_local, ray_normal_local, + len_diff + snapdata->depth_range[0] * local_scale); + local_depth -= len_diff; } - else { - BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; + else len_diff = 0.0f; + } + else { + len_diff = 0.0f; + } + if (r_hit_list) { + struct RayCastAll_Data data; + + data.bvhdata = treedata; + data.raycast_callback = treedata->raycast_callback; + data.obmat = obmat; + data.timat = timat; + data.len_diff = len_diff; + data.local_scale = local_scale; + data.ob = ob; + data.ob_uuid = ob_index; + data.hit_list = r_hit_list; + data.retval = retval; + + BLI_bvhtree_ray_cast_all( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); + + retval = data.retval; + } + else { + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - if (BLI_bvhtree_ray_cast( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - &hit, treedata->raycast_callback, treedata) != -1) - { - hit.dist += len_diff; - hit.dist /= local_scale; - if (hit.dist <= *ray_depth) { - *ray_depth = hit.dist; - copy_v3_v3(r_loc, hit.co); - - /* back to worldspace */ - mul_m4_v3(obmat, r_loc); - - if (r_no) { - copy_v3_v3(r_no, hit.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } + if (BLI_bvhtree_ray_cast( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + &hit, treedata->raycast_callback, treedata) != -1) + { + hit.dist += len_diff; + hit.dist /= local_scale; + if (hit.dist <= *ray_depth) { + *ray_depth = hit.dist; + copy_v3_v3(r_loc, hit.co); + + /* back to worldspace */ + mul_m4_v3(obmat, r_loc); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } - retval = true; + retval = true; - if (r_index) { - *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]); - } + if (r_index) { + *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]); } } } } - /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ - else { - BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; - - Nearest2dUserData neasrest2d = { - .dist_px_sq = SQUARE(*dist_px), - .r_axis_closest = {1.0f, 1.0f, 1.0f}, - .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, - .userdata = &treedata_type, - .index = -1}; - - dist_squared_to_projected_aabb_precalc( - &neasrest2d.data_precalc, lpmat, - snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, - ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local); - - BVHTree_WalkLeafCallback cb_walk_leaf = - (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? - cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - - BLI_bvhtree_walk_dfs( - treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); - - if (neasrest2d.index != -1) { - copy_v3_v3(r_loc, neasrest2d.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, neasrest2d.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } - *dist_px = sqrtf(neasrest2d.dist_px_sq); - *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); - - retval = true; + } + /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ + else { + BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; + + Nearest2dUserData neasrest2d = { + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .userdata = &treedata_type, + .index = -1}; + + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, + ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local); + + BVHTree_WalkLeafCallback cb_walk_leaf = + (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; + + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); + + if (neasrest2d.index != -1) { + copy_v3_v3(r_loc, neasrest2d.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest2d.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); } - } + *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); - if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) { - if (treedata) { - free_bvhtree_from_mesh(treedata); - } + retval = true; } } @@ -1393,268 +1378,246 @@ static bool snapEditMesh( } } - { - float imat[4][4]; - float timat[3][3]; /* transpose inverse matrix for normals */ - float ray_normal_local[3]; + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_normal_local[3]; - invert_m4_m4(imat, obmat); - transpose_m3_m4(timat, imat); + invert_m4_m4(imat, obmat); + transpose_m3_m4(timat, imat); - copy_v3_v3(ray_normal_local, snapdata->ray_dir); + copy_v3_v3(ray_normal_local, snapdata->ray_dir); - mul_mat3_m4_v3(imat, ray_normal_local); + mul_mat3_m4_v3(imat, ray_normal_local); - /* local scale in normal direction */ - float local_scale = normalize_v3(ray_normal_local); - float local_depth = *ray_depth; - if (local_depth != BVH_RAYCAST_DIST_MAX) { - local_depth *= local_scale; - } + /* local scale in normal direction */ + float local_scale = normalize_v3(ray_normal_local); + float local_depth = *ray_depth; + if (local_depth != BVH_RAYCAST_DIST_MAX) { + local_depth *= local_scale; + } - SnapObjectData_EditMesh *sod = NULL; + SnapObjectData_EditMesh *sod = NULL; - BVHTreeFromEditMesh *treedata = NULL, treedata_stack; + BVHTreeFromEditMesh *treedata = NULL; - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { - sod = *sod_p; - } - else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_EDIT_MESH; - } + void **sod_p; + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + sod = *sod_p; + } + else { + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_EDIT_MESH; + } - int tree_index = -1; - switch (snapdata->snap_to) { - case SCE_SNAP_MODE_FACE: - tree_index = 2; - break; - case SCE_SNAP_MODE_EDGE: - tree_index = 1; - break; - case SCE_SNAP_MODE_VERTEX: - tree_index = 0; - break; - } - if (tree_index != -1) { - if (sod->bvh_trees[tree_index] == NULL) { - sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); - } - treedata = sod->bvh_trees[tree_index]; - } - } - else { - treedata = &treedata_stack; - memset(treedata, 0, sizeof(*treedata)); + int tree_index = -1; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + tree_index = 2; + break; + case SCE_SNAP_MODE_EDGE: + tree_index = 1; + break; + case SCE_SNAP_MODE_VERTEX: + tree_index = 0; + break; + } + if (tree_index != -1) { + if (sod->bvh_trees[tree_index] == NULL) { + sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); } + treedata = sod->bvh_trees[tree_index]; + } - if (treedata && treedata->tree == NULL) { - switch (snapdata->snap_to) { - case SCE_SNAP_MODE_FACE: - { - BLI_bitmap *looptri_mask = NULL; - int looptri_num_active = -1; - if (sctx->callbacks.edit_mesh.test_face_fn) { - looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__); - looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( - em->bm, looptri_mask, - sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_looptri_ex(treedata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6, NULL); - if (looptri_mask) { - MEM_freeN(looptri_mask); - } - break; + if (treedata && treedata->tree == NULL) { + BLI_bitmap *elem_mask = NULL; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + { + int looptri_num_active = -1; + if (sctx->callbacks.edit_mesh.test_face_fn) { + elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); + looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( + em->bm, elem_mask, + sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); } - case SCE_SNAP_MODE_EDGE: - { - BLI_bitmap *edges_mask = NULL; - int edges_num_active = -1; - if (sctx->callbacks.edit_mesh.test_edge_fn) { - edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); - edges_num_active = BM_iter_mesh_bitmap_from_filter( - BM_EDGES_OF_MESH, em->bm, edges_mask, - (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, - sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_edges_ex(treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6); - if (edges_mask) { - MEM_freeN(edges_mask); - } - break; + bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL); + break; + } + case SCE_SNAP_MODE_EDGE: + { + int edges_num_active = -1; + if (sctx->callbacks.edit_mesh.test_edge_fn) { + elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); + edges_num_active = BM_iter_mesh_bitmap_from_filter( + BM_EDGES_OF_MESH, em->bm, elem_mask, + (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, + sctx->callbacks.edit_mesh.user_data); } - case SCE_SNAP_MODE_VERTEX: - { - BLI_bitmap *verts_mask = NULL; - int verts_num_active = -1; - if (sctx->callbacks.edit_mesh.test_vert_fn) { - verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); - verts_num_active = BM_iter_mesh_bitmap_from_filter( - BM_VERTS_OF_MESH, em->bm, verts_mask, - (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, - sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_verts_ex(treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6); - if (verts_mask) { - MEM_freeN(verts_mask); - } - break; + bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6); + break; + } + case SCE_SNAP_MODE_VERTEX: + { + int verts_num_active = -1; + if (sctx->callbacks.edit_mesh.test_vert_fn) { + elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); + verts_num_active = BM_iter_mesh_bitmap_from_filter( + BM_VERTS_OF_MESH, em->bm, elem_mask, + (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, + sctx->callbacks.edit_mesh.user_data); } + bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6); + break; } } - - if (!treedata || !treedata->tree) { - return retval; + if (elem_mask) { + MEM_freeN(elem_mask); } + } - if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { - float ray_start_local[3]; - copy_v3_v3(ray_start_local, snapdata->ray_start); - mul_m4_v3(imat, ray_start_local); + if (!treedata || !treedata->tree) { + return retval; + } - /* Only use closer ray_start in case of ortho view! In perspective one, ray_start - * may already been *inside* boundbox, leading to snap failures (see T38409). - * Note also ar might be null (see T38435), in this case we assume ray_start is ok! + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { + float ray_start_local[3]; + copy_v3_v3(ray_start_local, snapdata->ray_start); + mul_m4_v3(imat, ray_start_local); + + /* Only use closer ray_start in case of ortho view! In perspective one, ray_start + * may already been *inside* boundbox, leading to snap failures (see T38409). + * Note also ar might be null (see T38435), in this case we assume ray_start is ok! + */ + float len_diff = 0.0f; + if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ + /* We *need* a reasonably valid len_diff in this case. + * Use BHVTree to find the closest face from ray_start_local. */ - float len_diff = 0.0f; - if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ - /* We *need* a reasonably valid len_diff in this case. - * Use BHVTree to find the closest face from ray_start_local. - */ - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - if (BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) - { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - /* You need to make sure that ray_start is really far away, - * because even in the Orthografic view, in some cases, - * the ray can start inside the object (see T50486) */ - if (len_diff > 400.0f) { - float ray_org_local[3]; - - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); - - /* We pass a temp ray_start, set from object's boundbox, - * to avoid precision issues with very far away ray_start values - * (as returned in case of ortho view3d), see T38358. - */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, - len_diff + snapdata->depth_range[0] * local_scale); - local_depth -= len_diff; - } - else len_diff = 0.0f; + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + if (BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) + { + float dvec[3]; + sub_v3_v3v3(dvec, nearest.co, ray_start_local); + len_diff = dot_v3v3(dvec, ray_normal_local); + /* You need to make sure that ray_start is really far away, + * because even in the Orthografic view, in some cases, + * the ray can start inside the object (see T50486) */ + if (len_diff > 400.0f) { + float ray_org_local[3]; + + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); + + /* We pass a temp ray_start, set from object's boundbox, + * to avoid precision issues with very far away ray_start values + * (as returned in case of ortho view3d), see T38358. + */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + madd_v3_v3v3fl( + ray_start_local, ray_org_local, ray_normal_local, + len_diff + snapdata->depth_range[0] * local_scale); + local_depth -= len_diff; } + else len_diff = 0.0f; } - if (r_hit_list) { - struct RayCastAll_Data data; - - data.bvhdata = treedata; - data.raycast_callback = treedata->raycast_callback; - data.obmat = obmat; - data.timat = timat; - data.len_diff = len_diff; - data.local_scale = local_scale; - data.ob = ob; - data.ob_uuid = ob_index; - data.hit_list = r_hit_list; - data.retval = retval; - - BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); - - retval = data.retval; - } - else { - BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; + } + if (r_hit_list) { + struct RayCastAll_Data data; + + data.bvhdata = treedata; + data.raycast_callback = treedata->raycast_callback; + data.obmat = obmat; + data.timat = timat; + data.len_diff = len_diff; + data.local_scale = local_scale; + data.ob = ob; + data.ob_uuid = ob_index; + data.hit_list = r_hit_list; + data.retval = retval; + + BLI_bvhtree_ray_cast_all( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); + + retval = data.retval; + } + else { + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - if (BLI_bvhtree_ray_cast( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - &hit, treedata->raycast_callback, treedata) != -1) - { - hit.dist += len_diff; - hit.dist /= local_scale; - if (hit.dist <= *ray_depth) { - *ray_depth = hit.dist; - copy_v3_v3(r_loc, hit.co); - - /* back to worldspace */ - mul_m4_v3(obmat, r_loc); - - if (r_no) { - copy_v3_v3(r_no, hit.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } + if (BLI_bvhtree_ray_cast( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + &hit, treedata->raycast_callback, treedata) != -1) + { + hit.dist += len_diff; + hit.dist /= local_scale; + if (hit.dist <= *ray_depth) { + *ray_depth = hit.dist; + copy_v3_v3(r_loc, hit.co); + + /* back to worldspace */ + mul_m4_v3(obmat, r_loc); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } - retval = true; + retval = true; - if (r_index) { - *r_index = hit.index; - } + if (r_index) { + *r_index = hit.index; } } } } - else { - float ray_org_local[3]; - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); - - BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; - - Nearest2dUserData neasrest2d = { - .dist_px_sq = SQUARE(*dist_px), - .r_axis_closest = {1.0f, 1.0f, 1.0f}, - .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, - .userdata = &treedata_type, - .index = -1}; - - float lpmat[4][4]; - mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - dist_squared_to_projected_aabb_precalc( - &neasrest2d.data_precalc, lpmat, - snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, - (snapdata->depth_range[0] * local_scale), snapdata->mval, - ray_org_local, ray_normal_local); - - BVHTree_WalkLeafCallback cb_walk_leaf = - (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? - cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - - BLI_bvhtree_walk_dfs( - treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); - - if (neasrest2d.index != -1) { - copy_v3_v3(r_loc, neasrest2d.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, neasrest2d.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } - *dist_px = sqrtf(neasrest2d.dist_px_sq); - *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + } + else { + float ray_org_local[3]; + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); - retval = true; - } - } + BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; + + Nearest2dUserData neasrest2d = { + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .userdata = &treedata_type, + .index = -1}; - if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) { - if (treedata) { - free_bvhtree_from_editmesh(treedata); + float lpmat[4][4]; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, + (snapdata->depth_range[0] * local_scale), snapdata->mval, + ray_org_local, ray_normal_local); + + BVHTree_WalkLeafCallback cb_walk_leaf = + (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; + + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); + + if (neasrest2d.index != -1) { + copy_v3_v3(r_loc, neasrest2d.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest2d.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); } + *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + + retval = true; } } @@ -1894,10 +1857,8 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d( sctx->v3d_data.ar = ar; sctx->v3d_data.v3d = v3d; - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - sctx->cache.object_map = BLI_ghash_ptr_new(__func__); - sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - } + sctx->cache.object_map = BLI_ghash_ptr_new(__func__); + sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); return sctx; } @@ -1930,10 +1891,8 @@ static void snap_object_data_free(void *sod_v) void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) { - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); - BLI_memarena_free(sctx->cache.mem_arena); - } + BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); + BLI_memarena_free(sctx->cache.mem_arena); MEM_freeN(sctx); } -- cgit v1.2.3 From c367e23d460e5dea8ff810e23b7ab192f7a09b6e Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 3 Feb 2017 20:08:57 -0300 Subject: Snap System: Use callbaks to differentiate how referenced vertives of DerivedMeshs and Bmeshs Before it was informed the type of object in the `userdata`, and a same function ran between the types to obtain the coordinates of the vertices --- .../editors/transform/transform_snap_object.c | 106 +++++++++------------ 1 file changed, 43 insertions(+), 63 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 07617ec577c..d778fa06f52 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -235,21 +235,6 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH /** \Common utilities * \{ */ -MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3]) -{ - float dvec[3]; - sub_v3_v3v3(dvec, co, ray_start); - return dot_v3v3(dvec, ray_dir); -} - -/** - * Struct that kepts basic information about a BVHTree build from a editmesh. - */ -typedef struct BVHTreeFromMeshType { - void *userdata; - char type; -} BVHTreeFromMeshType; - /** * Generates a struct with the immutable parameters that will be used on all objects. * @@ -286,52 +271,42 @@ static void snap_data_set( copy_v2_v2(snapdata->depth_range, depth_range); } -static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3]) +MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3]) { - switch (meshdata->type) { - case SNAP_MESH: - { - BVHTreeFromMesh *data = meshdata->userdata; - const MVert *vert = data->vert + index; - normal_short_to_float_v3(r_no, vert->no); - break; - } - case SNAP_EDIT_MESH: - { - BVHTreeFromEditMesh *data = meshdata->userdata; - BMVert *eve = BM_vert_at_index(data->em->bm, index); - copy_v3_v3(r_no, eve->no); - break; - } - } + float dvec[3]; + sub_v3_v3v3(dvec, co, ray_start); + return dot_v3v3(dvec, ray_dir); } -static void get_edge_verts( - const BVHTreeFromMeshType *meshdata, const int index, - const float *v_pair[2]) +static void copy_dm_vert_no(const int index, float r_no[3], const BVHTreeFromMesh *data) { - switch (meshdata->type) { - case SNAP_MESH: - { - BVHTreeFromMesh *data = meshdata->userdata; + const MVert *vert = data->vert + index; - const MVert *vert = data->vert; - const MEdge *edge = data->edge + index; + normal_short_to_float_v3(r_no, vert->no); +} - v_pair[0] = vert[edge->v1].co; - v_pair[1] = vert[edge->v2].co; - break; - } - case SNAP_EDIT_MESH: - { - BVHTreeFromEditMesh *data = meshdata->userdata; - BMEdge *eed = BM_edge_at_index(data->em->bm, index); +static void copy_bvert_no(const int index, float r_no[3], const BVHTreeFromEditMesh *data) +{ + BMVert *eve = BM_vert_at_index(data->em->bm, index); - v_pair[0] = eed->v1->co; - v_pair[1] = eed->v2->co; - break; - } - } + copy_v3_v3(r_no, eve->no); +} + +static void get_dm_edge_verts(const int index, const float *v_pair[2], const BVHTreeFromMesh *data) +{ + const MVert *vert = data->vert; + const MEdge *edge = data->edge + index; + + v_pair[0] = vert[edge->v1].co; + v_pair[1] = vert[edge->v2].co; +} + +static void get_bedge_verts(const int index, const float *v_pair[2], const BVHTreeFromEditMesh *data) +{ + BMEdge *eed = BM_edge_at_index(data->em->bm, index); + + v_pair[0] = eed->v1->co; + v_pair[1] = eed->v2->co; } static bool test_projected_vert_dist( @@ -422,6 +397,7 @@ static void dist_squared_to_projected_aabb_precalc( } } +/* Returns the distance from a 2d coordinate to a BoundBox (Projected) */ static float dist_squared_to_projected_aabb( struct Nearest2dPrecalc *data, const float bbmin[3], const float bbmax[3], @@ -652,7 +628,11 @@ typedef struct Nearest2dUserData { bool r_axis_closest[3]; float depth_range[2]; + void *userdata; + void(*get_edge_verts)(int, const float*[2], void*); + void(*copy_vert_no)(int, float[3], void*); + int index; float co[3]; float no[3]; @@ -688,7 +668,7 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo &data->dist_px_sq, data->co)) { - copy_vert_no(data->userdata, index, data->no); + data->copy_vert_no(index, data->no, data->userdata); data->index = index; } return true; @@ -700,7 +680,7 @@ static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int i struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc; const float *v_pair[2]; - get_edge_verts(data->userdata, index, v_pair); + data->get_edge_verts(index, v_pair, data->userdata); if (test_projected_edge_dist( data->depth_range, @@ -1311,13 +1291,13 @@ static bool snapDerivedMesh( } /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ else { - BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; - Nearest2dUserData neasrest2d = { .dist_px_sq = SQUARE(*dist_px), .r_axis_closest = {1.0f, 1.0f, 1.0f}, - .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, - .userdata = &treedata_type, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .userdata = treedata, + .get_edge_verts = get_dm_edge_verts, + .copy_vert_no = copy_dm_vert_no, .index = -1}; dist_squared_to_projected_aabb_precalc( @@ -1581,13 +1561,13 @@ static bool snapEditMesh( copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); - BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; - Nearest2dUserData neasrest2d = { .dist_px_sq = SQUARE(*dist_px), .r_axis_closest = {1.0f, 1.0f, 1.0f}, .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, - .userdata = &treedata_type, + .userdata = treedata, + .get_edge_verts = get_bedge_verts, + .copy_vert_no = copy_bvert_no, .index = -1}; float lpmat[4][4]; -- cgit v1.2.3 From a2c469edc2ddb70a844aea3060dd45b9f3efffee Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sat, 4 Feb 2017 21:51:27 +0100 Subject: Fix (unreported) crash in new snap code. Looks like `object_map` and `mem_arena` may be NULL sometimes... Also, cleaned up function pointers declaration of Nearest2dUserData, those were warning out in gcc. Please, *always* use typdef defined prototypes for function pointers, it is sooooo much cleaner and clearer that way. And easy to convert from compatible functions too. --- .../editors/transform/transform_snap_object.c | 24 ++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index d778fa06f52..1a5cabd1da8 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -620,6 +620,10 @@ static float dist_aabb_to_plane( /** \Walk DFS * \{ */ + +typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const float *v_pair[2], void *data); +typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data); + typedef struct Nearest2dUserData { struct Nearest2dPrecalc data_precalc; @@ -630,8 +634,8 @@ typedef struct Nearest2dUserData { float depth_range[2]; void *userdata; - void(*get_edge_verts)(int, const float*[2], void*); - void(*copy_vert_no)(int, float[3], void*); + Nearest2DGetEdgeVertsCallback get_edge_verts; + Nearest2DCopyVertNoCallback copy_vert_no; int index; float co[3]; @@ -1296,8 +1300,8 @@ static bool snapDerivedMesh( .r_axis_closest = {1.0f, 1.0f, 1.0f}, .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, .userdata = treedata, - .get_edge_verts = get_dm_edge_verts, - .copy_vert_no = copy_dm_vert_no, + .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts, + .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no, .index = -1}; dist_squared_to_projected_aabb_precalc( @@ -1566,8 +1570,8 @@ static bool snapEditMesh( .r_axis_closest = {1.0f, 1.0f, 1.0f}, .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, .userdata = treedata, - .get_edge_verts = get_bedge_verts, - .copy_vert_no = copy_bvert_no, + .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts, + .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no, .index = -1}; float lpmat[4][4]; @@ -1871,8 +1875,12 @@ static void snap_object_data_free(void *sod_v) void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) { - BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); - BLI_memarena_free(sctx->cache.mem_arena); + if (sctx->cache.object_map) { + BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); + } + if (sctx->cache.mem_arena) { + BLI_memarena_free(sctx->cache.mem_arena); + } MEM_freeN(sctx); } -- cgit v1.2.3 From 47caf343c0ac597cc37048dc40d24a31b94fb238 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sat, 4 Feb 2017 18:17:15 -0300 Subject: fix T50592: Scene.raycast not working Ray_start and ray_normal values were being ignored --- .../editors/transform/transform_snap_object.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 1a5cabd1da8..0e4ec12e18f 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1827,6 +1827,9 @@ SnapObjectContext *ED_transform_snap_object_context_create( sctx->bmain = bmain; sctx->scene = scene; + sctx->cache.object_map = BLI_ghash_ptr_new(__func__); + sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + return sctx; } @@ -1841,9 +1844,6 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d( sctx->v3d_data.ar = ar; sctx->v3d_data.v3d = v3d; - sctx->cache.object_map = BLI_ghash_ptr_new(__func__); - sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - return sctx; } @@ -1875,12 +1875,8 @@ static void snap_object_data_free(void *sod_v) void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) { - if (sctx->cache.object_map) { - BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); - } - if (sctx->cache.mem_arena) { - BLI_memarena_free(sctx->cache.mem_arena); - } + BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); + BLI_memarena_free(sctx->cache.mem_arena); MEM_freeN(sctx); } @@ -1903,7 +1899,7 @@ bool ED_transform_snap_object_project_ray_ex( SnapObjectContext *sctx, const unsigned short snap_to, const struct SnapObjectParams *params, - const float UNUSED(ray_start[3]), const float UNUSED(ray_normal[3]), + const float ray_start[3], const float ray_normal[3], float *ray_depth, float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4]) @@ -1911,7 +1907,9 @@ bool ED_transform_snap_object_project_ray_ex( const float depth_range[2] = {0.0f, FLT_MAX}; SnapData snapdata; - snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, r_loc, r_loc, r_no, depth_range); + snap_data_set( + &snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, + NULL, ray_start, ray_start, ray_normal, depth_range); return snapObjectsRay( sctx, &snapdata, -- cgit v1.2.3 From 22156d951dbd4e1150ede7fd3769347265694bd7 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 6 Feb 2017 01:01:39 -0300 Subject: fix T50602: Avoid crash when executing `transform_snap_context_project_view3d_mixed` with `dist_px` NULL --- source/blender/editors/transform/transform_snap_object.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 0e4ec12e18f..7c9dc43dbe4 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -2028,11 +2028,13 @@ static bool transform_snap_context_project_view3d_mixed_impl( BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0); if (use_depth) { - const float dist_px_orig = *dist_px; + const float dist_px_orig = dist_px ? *dist_px : 0; for (int i = 2; i >= 0; i--) { if (snap_to_flag & (1 << i)) { - if (i == 0) + if (i == 0) { + BLI_assert(dist_px != NULL); *dist_px = dist_px_orig; + } if (ED_transform_snap_object_project_view3d( sctx, elem_type[i], params, -- cgit v1.2.3 From 117d90b3da4201fb2df64ad44e823b29a0f8569b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 29 Jan 2017 00:05:41 +1300 Subject: Fix: GPencil delete operators did not respect color locking --- source/blender/editors/gpencil/gpencil_edit.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 5b011b679a6..e118e490f25 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -953,6 +953,9 @@ static int gp_dissolve_selected_points(bContext *C) /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(gpl, gps) == false) + continue; if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; @@ -1165,6 +1168,9 @@ static int gp_delete_selected_points(bContext *C) /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(gpl, gps) == false) + continue; if (gps->flag & GP_STROKE_SELECT) { @@ -1204,7 +1210,7 @@ static int gp_delete_exec(bContext *C, wmOperator *op) case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */ result = gp_delete_selected_points(C); break; - + case GP_DELETEOP_FRAME: /* active frame */ result = gp_actframe_delete_exec(C, op); break; -- cgit v1.2.3 From 351eb4fad148acf86df9e2abafd28bcad5ef9e00 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 9 Feb 2017 18:59:51 +1300 Subject: More tweaks to Normalisation options in Graph Editor * Added a new dedicated icon for normalize * Only use an icon for "Auto" --- source/blender/editors/include/UI_icons.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 8579778ff79..8420591aa3e 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -653,9 +653,9 @@ DEF_ICON(IPO_BACK) DEF_ICON(IPO_EASE_IN) DEF_ICON(IPO_EASE_OUT) DEF_ICON(IPO_EASE_IN_OUT) +DEF_ICON(NORMALIZE_FCURVES) #ifndef DEF_ICON_BLANK_SKIP /* available */ - DEF_ICON(BLANK203) DEF_ICON(BLANK204) DEF_ICON(BLANK205) DEF_ICON(BLANK206) -- cgit v1.2.3 From d2f4900d1a93ad188c87f983d0024073627c70db Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 9 Feb 2017 19:08:58 +1300 Subject: Use a smaller cross icon for clearing search box contents --- source/blender/editors/interface/interface_widgets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index d43a94c5514..b3736a71e74 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1584,7 +1584,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f); if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) { - widget_draw_icon(but, ICON_X, alpha, &temp, false); + widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, false); } else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) { widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false); -- cgit v1.2.3 From e523cde5740514edd0c19eff042c61132bb517ca Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Thu, 9 Feb 2017 09:26:12 -0500 Subject: Cleanup: Remove commented code Code has been commented from before 2010 and relates to old Background image code. --- source/blender/editors/space_view3d/space_view3d.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 075b1faf502..964f4bcdd9c 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1256,21 +1256,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot } break; } - - /* removed since BKE_image_user_frame_calc is now called in view3d_draw_bgpic because screen_ops doesnt call the notifier. */ -#if 0 - if (wmn->category == NC_SCENE && wmn->data == ND_FRAME) { - View3D *v3d = area->spacedata.first; - BGpic *bgpic = v3d->bgpicbase.first; - - for (; bgpic; bgpic = bgpic->next) { - if (bgpic->ima) { - Scene *scene = wmn->reference; - BKE_image_user_frame_calc(&bgpic->iuser, scene->r.cfra, 0); - } - } - } -#endif } const char *view3d_context_dir[] = { -- cgit v1.2.3 From 9d8a9cacc309063b27f1d0535b2ab8d7ea10c233 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 10 Feb 2017 18:10:26 +0100 Subject: De-duplicate min/max calculation in F-Curve normalization --- source/blender/editors/animation/anim_draw.c | 36 +++++++++++----------------- 1 file changed, 14 insertions(+), 22 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 33e44d73894..0a0952870c3 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -308,6 +308,7 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo fcu->prev_norm_factor = 1.0f; if (fcu->bezt) { + const bool use_preview_only = PRVRANGEON; BezTriple *bezt; int i; float max_coord = -FLT_MAX; @@ -318,29 +319,20 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo return 1.0f; } - if (PRVRANGEON) { - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) { - max_coord = max_ff(max_coord, bezt->vec[0][1]); - max_coord = max_ff(max_coord, bezt->vec[1][1]); - max_coord = max_ff(max_coord, bezt->vec[2][1]); - - min_coord = min_ff(min_coord, bezt->vec[0][1]); - min_coord = min_ff(min_coord, bezt->vec[1][1]); - min_coord = min_ff(min_coord, bezt->vec[2][1]); - } - } - } - else { - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - max_coord = max_ff(max_coord, bezt->vec[0][1]); - max_coord = max_ff(max_coord, bezt->vec[1][1]); - max_coord = max_ff(max_coord, bezt->vec[2][1]); - - min_coord = min_ff(min_coord, bezt->vec[0][1]); - min_coord = min_ff(min_coord, bezt->vec[1][1]); - min_coord = min_ff(min_coord, bezt->vec[2][1]); + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + if (use_preview_only && !IN_RANGE_INCL(bezt->vec[1][0], + scene->r.psfra, + scene->r.pefra)) + { + continue; } + max_coord = max_ff(max_coord, bezt->vec[0][1]); + max_coord = max_ff(max_coord, bezt->vec[1][1]); + max_coord = max_ff(max_coord, bezt->vec[2][1]); + + min_coord = min_ff(min_coord, bezt->vec[0][1]); + min_coord = min_ff(min_coord, bezt->vec[1][1]); + min_coord = min_ff(min_coord, bezt->vec[2][1]); } if (max_coord > min_coord) { -- cgit v1.2.3 From 9148ce9f3c245c3a9c10857f69e9d338c5593d3d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 13 Feb 2017 10:00:46 +0100 Subject: F-Curve normalization: Do proper curve min/max instead of handle min/max Would be cool to find some way to cache the results. --- source/blender/editors/animation/anim_draw.c | 74 +++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 7 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 0a0952870c3..a4ba95420c1 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -46,6 +46,8 @@ #include "BLI_dlrbTree.h" #include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_nla.h" #include "BKE_mask.h" @@ -309,7 +311,7 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo fcu->prev_norm_factor = 1.0f; if (fcu->bezt) { const bool use_preview_only = PRVRANGEON; - BezTriple *bezt; + const BezTriple *bezt; int i; float max_coord = -FLT_MAX; float min_coord = FLT_MAX; @@ -326,13 +328,71 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo { continue; } - max_coord = max_ff(max_coord, bezt->vec[0][1]); - max_coord = max_ff(max_coord, bezt->vec[1][1]); - max_coord = max_ff(max_coord, bezt->vec[2][1]); - min_coord = min_ff(min_coord, bezt->vec[0][1]); - min_coord = min_ff(min_coord, bezt->vec[1][1]); - min_coord = min_ff(min_coord, bezt->vec[2][1]); + if (i == 0) { + /* We ignore extrapolation flags and handle here, and use the + * control point position only. so we normalize "interesting" + * part of the curve. + * + * Here we handle left extrapolation. + */ + max_coord = max_ff(max_coord, bezt->vec[1][1]); + + min_coord = min_ff(min_coord, bezt->vec[1][1]); + } + else { + const BezTriple *prev_bezt = bezt - 1; + if (prev_bezt->ipo == BEZT_IPO_CONST) { + /* Constant interpolation: previous CV value is used up + * to the current keyframe. + */ + max_coord = max_ff(max_coord, bezt->vec[1][1]); + min_coord = min_ff(min_coord, bezt->vec[1][1]); + } + else if (prev_bezt->ipo == BEZT_IPO_LIN) { + /* Linear interpolation: min/max using both previous and + * and current CV. + */ + max_coord = max_ff(max_coord, bezt->vec[1][1]); + min_coord = min_ff(min_coord, bezt->vec[1][1]); + max_coord = max_ff(max_coord, prev_bezt->vec[1][1]); + min_coord = min_ff(min_coord, prev_bezt->vec[1][1]); + } + else if (prev_bezt->ipo == BEZT_IPO_BEZ) { + const int resol = fcu->driver + ? 32 + : min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])), 32); + if (resol < 2) { + max_coord = max_ff(max_coord, prev_bezt->vec[1][1]); + min_coord = min_ff(min_coord, prev_bezt->vec[1][1]); + } + else { + float data[120]; + float v1[2], v2[2], v3[2], v4[2]; + + v1[0] = prev_bezt->vec[1][0]; + v1[1] = prev_bezt->vec[1][1]; + v2[0] = prev_bezt->vec[2][0]; + v2[1] = prev_bezt->vec[2][1]; + + v3[0] = bezt->vec[0][0]; + v3[1] = bezt->vec[0][1]; + v4[0] = bezt->vec[1][0]; + v4[1] = bezt->vec[1][1]; + + correct_bezpart(v1, v2, v3, v4); + + BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3); + BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3); + + for (int j = 0; j <= resol; ++j) { + const float *fp = &data[j * 3]; + max_coord = max_ff(max_coord, fp[1]); + min_coord = min_ff(min_coord, fp[1]); + } + } + } + } } if (max_coord > min_coord) { -- cgit v1.2.3