diff options
Diffstat (limited to 'source/blender/editors/transform/transform_snap_object.c')
-rw-r--r-- | source/blender/editors/transform/transform_snap_object.c | 297 |
1 files changed, 166 insertions, 131 deletions
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 7a8a123cf79..1601acb1c8f 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -221,22 +221,40 @@ static void iter_snap_objects(SnapObjectContext *sctx, Base *base_act = view_layer->basact; for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { - if ((BASE_VISIBLE(v3d, base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 && - !((snap_select == SNAP_NOT_SELECTED && - ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) || - (snap_select == SNAP_NOT_ACTIVE && base == base_act))) { - Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object); - if (obj_eval->transflag & OB_DUPLI) { - DupliObject *dupli_ob; - ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval); - for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { - sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data); - } - free_object_duplilist(lb); + + if (!BASE_VISIBLE(v3d, base)) { + continue; + } + + if (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE) { + /* pass */ + } + else if (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) { + continue; + } + + if (snap_select == SNAP_NOT_SELECTED) { + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { + continue; } + } + else if (snap_select == SNAP_NOT_ACTIVE) { + if (base == base_act) { + continue; + } + } - sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data); + Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object); + if (obj_eval->transflag & OB_DUPLI) { + DupliObject *dupli_ob; + ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval); + for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { + sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data); + } + free_object_duplilist(lb); } + + sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data); } } @@ -336,7 +354,7 @@ static bool raycastMesh(SnapObjectContext *sctx, const float ray_dir[3], Object *ob, Mesh *me, - float obmat[4][4], + const float obmat[4][4], const unsigned int ob_index, bool use_hide, /* read/write args */ @@ -509,7 +527,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx, const float ray_dir[3], Object *ob, BMEditMesh *em, - float obmat[4][4], + const float obmat[4][4], const unsigned int ob_index, /* read/write args */ float *ray_depth, @@ -692,7 +710,7 @@ static bool raycastObj(SnapObjectContext *sctx, const float ray_start[3], const float ray_dir[3], Object *ob, - float obmat[4][4], + const float obmat[4][4], const unsigned int ob_index, bool use_obedit, bool use_occlusion_test, @@ -905,10 +923,10 @@ static bool raycastObjects(SnapObjectContext *sctx, /* Test BoundBox */ static bool snap_bound_box_check_dist(float min[3], - float max[3], - float lpmat[4][4], - float win_size[2], - float mval[2], + const float max[3], + const float lpmat[4][4], + const float win_size[2], + const float mval[2], float dist_px_sq) { /* In vertex and edges you need to get the pixel distance from ray to BoundBox, @@ -1202,7 +1220,7 @@ static void cb_snap_tri_verts(void *userdata, static short snap_mesh_polygon(SnapObjectContext *sctx, SnapData *snapdata, Object *ob, - float obmat[4][4], + const float obmat[4][4], /* read/write args */ float *dist_px, /* return args */ @@ -1254,8 +1272,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index]; const MLoop *ml = &treedata->loop[mp->loopstart]; - if (snapdata->snap_to_flag & - (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { + if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { elem = SCE_SNAP_MODE_EDGE; BLI_assert(treedata->edge != NULL); for (int i = mp->totloop; i--; ml++) { @@ -1292,8 +1309,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, BMFace *f = BM_face_at_index(em->bm, *r_index); BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); - if (snapdata->snap_to_flag & - (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { + if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { elem = SCE_SNAP_MODE_EDGE; BM_mesh_elem_index_ensure(em->bm, BM_EDGE); BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE); @@ -1346,7 +1362,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, SnapData *snapdata, Object *ob, - float obmat[4][4], + const float obmat[4][4], float original_dist_px, const float prev_co[3], /* read/write args */ @@ -1362,22 +1378,6 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, return elem; } - float lpmat[4][4]; - mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - - struct DistProjectedAABBPrecalc neasrest_precalc; - dist_squared_to_projected_aabb_precalc( - &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); - - Nearest2dUserData nearest2d = { - .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, - }; - - BVHTreeNearest nearest = { - .index = -1, - .dist_sq = SQUARE(original_dist_px), - }; - SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob); if (sod == NULL) { /* The object is in edit mode, and the key used @@ -1388,18 +1388,22 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, BLI_assert(sod != NULL); - if (sod->type == SNAP_MESH) { - nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata; - nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get; - nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get; - nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy; - } - else { - BLI_assert(sod->type == SNAP_EDIT_MESH); - nearest2d.userdata = BKE_editmesh_from_object(ob); - nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get; - nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get; - nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy; + Nearest2dUserData nearest2d; + { + nearest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; + if (sod->type == SNAP_MESH) { + nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata; + nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get; + nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get; + nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy; + } + else { + BLI_assert(sod->type == SNAP_EDIT_MESH); + nearest2d.userdata = BKE_editmesh_from_object(ob); + nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get; + nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get; + nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy; + } } int vindex[2]; @@ -1409,6 +1413,20 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, nearest2d.get_vert_co(vindex[0], &v_pair[0], nearest2d.userdata); nearest2d.get_vert_co(vindex[1], &v_pair[1], nearest2d.userdata); + struct DistProjectedAABBPrecalc neasrest_precalc; + { + float lpmat[4][4]; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + + dist_squared_to_projected_aabb_precalc( + &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); + } + + BVHTreeNearest nearest = { + .index = -1, + .dist_sq = SQUARE(original_dist_px), + }; + float lambda; if (!isect_ray_seg_v3(neasrest_precalc.ray_origin, neasrest_precalc.ray_direction, @@ -1418,8 +1436,14 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, /* do nothing */ } else { - if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { - if (lambda < 0.25f || 0.75f < lambda) { + short snap_to_flag = snapdata->snap_to_flag; + int e_mode_len = ((snap_to_flag & SCE_SNAP_MODE_EDGE) != 0) + + ((snap_to_flag & SCE_SNAP_MODE_VERTEX) != 0) + + ((snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) != 0); + + float range = 1.0f / (2 * e_mode_len - 1); + if (snap_to_flag & SCE_SNAP_MODE_VERTEX) { + if (lambda < (range) || (1.0f - range) < lambda) { int v_id = lambda < 0.5f ? 0 : 1; if (test_projected_vert_dist(&neasrest_precalc, @@ -1436,8 +1460,9 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, } } - if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) { - if (0.375f < lambda && lambda < 0.625f) { + if (snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) { + range *= e_mode_len - 1; + if ((range) < lambda && lambda < (1.0f - range)) { float vmid[3]; mid_v3_v3v3(vmid, v_pair[0], v_pair[1]); @@ -1468,21 +1493,25 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, if (IN_RANGE(lambda, 0.0f, 1.0f)) { interp_v3_v3v3(v_near, va_g, vb_g, lambda); - if ((len_squared_v3v3(prev_co, v_near) > FLT_EPSILON) && - test_projected_vert_dist(&neasrest_precalc, - NULL, - 0, - nearest2d.is_persp, - v_near, - &nearest.dist_sq, - nearest.co)) { - float v_nor[2][3]; - nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata); - nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata); - mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]); + if (len_squared_v3v3(prev_co, v_near) > FLT_EPSILON) { + dist_squared_to_projected_aabb_precalc( + &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval); - nearest.index = *r_index; - elem = SCE_SNAP_MODE_EDGE_PERPENDICULAR; + if (test_projected_vert_dist(&neasrest_precalc, + NULL, + 0, + nearest2d.is_persp, + v_near, + &nearest.dist_sq, + nearest.co)) { + float v_nor[2][3]; + nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata); + nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata); + mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]); + + nearest.index = *r_index; + elem = SCE_SNAP_MODE_EDGE_PERPENDICULAR; + } } } } @@ -1513,7 +1542,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, static short snapArmature(SnapData *snapdata, Object *ob, - float obmat[4][4], + const float obmat[4][4], bool use_obedit, /* read/write args */ float *dist_px, @@ -1658,7 +1687,7 @@ static short snapArmature(SnapData *snapdata, static short snapCurve(SnapData *snapdata, Object *ob, - float obmat[4][4], + const float obmat[4][4], bool use_obedit, /* read/write args */ float *dist_px, @@ -1688,7 +1717,7 @@ static short snapCurve(SnapData *snapdata, if (use_obedit == false) { /* Test BoundBox */ - BoundBox *bb = BKE_curve_texspace_get(cu, NULL, NULL, NULL); + BoundBox *bb = BKE_curve_boundbox_get(ob); if (bb && !snap_bound_box_check_dist( bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) { return 0; @@ -1809,7 +1838,7 @@ static short snapCurve(SnapData *snapdata, /* may extend later (for now just snaps to empty center) */ static short snapEmpty(SnapData *snapdata, Object *ob, - float obmat[4][4], + const float obmat[4][4], /* read/write args */ float *dist_px, /* return args */ @@ -1891,12 +1920,6 @@ static short snapCamera(const SnapObjectContext *sctx, return retval; } - float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; - transpose_m4_m4(tobmat, obmat); - for (int i = snapdata->clip_plane_len; i--;) { - mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); - } - tracking = &clip->tracking; BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat); @@ -1942,7 +1965,7 @@ static short snapCamera(const SnapObjectContext *sctx, mul_m4_v3(vertex_obmat, bundle_pos); if (test_projected_vert_dist(&neasrest_precalc, - clip_planes_local, + snapdata->clip_plane, snapdata->clip_plane_len, is_persp, bundle_pos, @@ -1970,7 +1993,7 @@ static short snapMesh(SnapObjectContext *sctx, SnapData *snapdata, Object *ob, Mesh *me, - float obmat[4][4], + const float obmat[4][4], /* read/write args */ float *dist_px, /* return args */ @@ -2120,8 +2143,7 @@ static short snapMesh(SnapObjectContext *sctx, last_index = nearest.index; } - if (snapdata->snap_to_flag & - (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { + if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { if (bvhtree[0]) { /* snap to loose edges */ BLI_bvhtree_find_nearest_projected(bvhtree[0], @@ -2209,7 +2231,7 @@ static short snapEditMesh(SnapObjectContext *sctx, SnapData *snapdata, Object *ob, BMEditMesh *em, - float obmat[4][4], + const float obmat[4][4], /* read/write args */ float *dist_px, /* return args */ @@ -2287,8 +2309,7 @@ static short snapEditMesh(SnapObjectContext *sctx, } } - if (snapdata->snap_to_flag & - (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { + if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { if (sod->bvh_trees[1] == NULL) { sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); } @@ -2335,7 +2356,6 @@ static short snapEditMesh(SnapObjectContext *sctx, .index = -1, .dist_sq = dist_px_sq, }; - int last_index = nearest.index; short elem = SCE_SNAP_MODE_VERTEX; float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; @@ -2345,7 +2365,7 @@ static short snapEditMesh(SnapObjectContext *sctx, mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); } - if (treedata_vert && snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { + if (treedata_vert && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) { BM_mesh_elem_table_ensure(em->bm, BM_VERT); BLI_bvhtree_find_nearest_projected(treedata_vert->tree, lpmat, @@ -2356,12 +2376,11 @@ static short snapEditMesh(SnapObjectContext *sctx, &nearest, cb_snap_vert, &nearest2d); - - last_index = nearest.index; } - if (treedata_edge && snapdata->snap_to_flag & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | - SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { + if (treedata_edge && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) { + int last_index = nearest.index; + nearest.index = -1; BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT); BLI_bvhtree_find_nearest_projected(treedata_edge->tree, lpmat, @@ -2373,9 +2392,12 @@ static short snapEditMesh(SnapObjectContext *sctx, cb_snap_edge, &nearest2d); - if (last_index != nearest.index) { + if (nearest.index != -1) { elem = SCE_SNAP_MODE_EDGE; } + else { + nearest.index = last_index; + } } if (nearest.index != -1) { @@ -2770,11 +2792,11 @@ static short transform_snap_context_project_view3d_mixed_impl( 0); short retval = 0; - bool has_hit = false; - int index = -1; - float loc[3], no[3], obmat[4][4]; + bool has_hit = false; Object *ob = NULL; + float loc[3], no[3], obmat[4][4]; + int index = -1; const ARegion *ar = sctx->v3d_data.ar; const RegionView3D *rv3d = ar->regiondata; @@ -2783,7 +2805,6 @@ static short transform_snap_context_project_view3d_mixed_impl( if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) { float ray_start[3], ray_normal[3]; - if (!ED_view3d_win_to_ray_clipped_ex(sctx->depsgraph, sctx->v3d_data.ar, sctx->v3d_data.v3d, @@ -2802,12 +2823,26 @@ static short transform_snap_context_project_view3d_mixed_impl( if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) { retval = SCE_SNAP_MODE_FACE; + + copy_v3_v3(r_loc, loc); + if (r_no) { + copy_v3_v3(r_no, no); + } + if (r_ob) { + *r_ob = ob; + } + if (r_obmat) { + copy_m4_m4(r_obmat, obmat); + } + if (r_index) { + *r_index = index; + } } } if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { - short elem; + short elem_test, elem = 0; float dist_px_tmp = *dist_px; SnapData snapdata; @@ -2815,9 +2850,14 @@ static short transform_snap_context_project_view3d_mixed_impl( snapdata.win_size[0] = ar->winx; snapdata.win_size[1] = ar->winy; copy_v2_v2(snapdata.mval, mval); - snapdata.snap_to_flag = snap_to_flag; snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO; + /* First snap to edge instead of middle or perpendicular. */ + snapdata.snap_to_flag = snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE); + if (snap_to_flag & (SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { + snapdata.snap_to_flag |= SCE_SNAP_MODE_EDGE; + } + planes_from_projmat( snapdata.pmat, NULL, NULL, NULL, NULL, snapdata.clip_plane[0], snapdata.clip_plane[1]); @@ -2838,10 +2878,9 @@ static short transform_snap_context_project_view3d_mixed_impl( new_clipplane[3] += 0.01f; /* Try to snap only to the polygon. */ - elem = snap_mesh_polygon(sctx, &snapdata, ob, obmat, &dist_px_tmp, loc, no, &index); - - if (elem) { - retval = elem; + elem_test = snap_mesh_polygon(sctx, &snapdata, ob, obmat, &dist_px_tmp, loc, no, &index); + if (elem_test) { + elem = elem_test; } /* Add the new clip plane to the beginning of the list. */ @@ -2853,45 +2892,41 @@ static short transform_snap_context_project_view3d_mixed_impl( snapdata.has_occlusion_plane = true; } - elem = snapObjectsRay(sctx, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat); - - if (elem) { - retval = elem; + elem_test = snapObjectsRay(sctx, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat); + if (elem_test) { + elem = elem_test; } - if ((retval == SCE_SNAP_MODE_EDGE) && + if ((elem == SCE_SNAP_MODE_EDGE) && (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR))) { + snapdata.snap_to_flag = snap_to_flag; elem = snap_mesh_edge_verts_mixed( sctx, &snapdata, ob, obmat, *dist_px, prev_co, &dist_px_tmp, loc, no, &index); } - if (elem) { + if (elem & snap_to_flag) { retval = elem; - } - retval &= snap_to_flag; - *dist_px = dist_px_tmp; - } + copy_v3_v3(r_loc, loc); + if (r_no) { + copy_v3_v3(r_no, no); + } + if (r_ob) { + *r_ob = ob; + } + if (r_obmat) { + copy_m4_m4(r_obmat, obmat); + } + if (r_index) { + *r_index = index; + } - if (retval) { - copy_v3_v3(r_loc, loc); - if (r_no) { - copy_v3_v3(r_no, no); - } - if (r_ob) { - *r_ob = ob; - } - if (r_obmat) { - copy_m4_m4(r_obmat, obmat); - } - if (r_index) { - *r_index = index; + *dist_px = dist_px_tmp; } - return retval; } - return 0; + return retval; } short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, |