Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_snap_object.c
| Show First 20 Lines • Show All 1,254 Lines • ▼ Show 20 Lines | if (sod->type == SNAP_MESH) { | ||||
| nearest2d.userdata = treedata; | nearest2d.userdata = treedata; | ||||
| nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get; | nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get; | ||||
| nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get; | nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get; | ||||
| nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy; | nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy; | ||||
| const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index]; | const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index]; | ||||
| const MLoop *ml = &treedata->loop[mp->loopstart]; | const MLoop *ml = &treedata->loop[mp->loopstart]; | ||||
| if (snapdata->snap_to_flag & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT)) { | if (snapdata->snap_to_flag & | ||||
| (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { | |||||
| elem = SCE_SNAP_MODE_EDGE; | elem = SCE_SNAP_MODE_EDGE; | ||||
| BLI_assert(treedata->edge != NULL); | BLI_assert(treedata->edge != NULL); | ||||
| for (int i = mp->totloop; i--; ml++) { | for (int i = mp->totloop; i--; ml++) { | ||||
| cb_snap_edge(&nearest2d, | cb_snap_edge(&nearest2d, | ||||
| ml->e, | ml->e, | ||||
| &neasrest_precalc, | &neasrest_precalc, | ||||
| clip_planes_local, | clip_planes_local, | ||||
| snapdata->clip_plane_len, | snapdata->clip_plane_len, | ||||
| Show All 20 Lines | else { | ||||
| nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get; | nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get; | ||||
| nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get; | nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get; | ||||
| nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy; | nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy; | ||||
| BM_mesh_elem_table_ensure(em->bm, BM_FACE); | BM_mesh_elem_table_ensure(em->bm, BM_FACE); | ||||
| BMFace *f = BM_face_at_index(em->bm, *r_index); | BMFace *f = BM_face_at_index(em->bm, *r_index); | ||||
| BMLoop *l_iter, *l_first; | BMLoop *l_iter, *l_first; | ||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f); | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| if (snapdata->snap_to_flag & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT)) { | if (snapdata->snap_to_flag & | ||||
| (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { | |||||
| elem = SCE_SNAP_MODE_EDGE; | elem = SCE_SNAP_MODE_EDGE; | ||||
| BM_mesh_elem_index_ensure(em->bm, BM_EDGE); | BM_mesh_elem_index_ensure(em->bm, BM_EDGE); | ||||
| BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE); | BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE); | ||||
| do { | do { | ||||
| cb_snap_edge(&nearest2d, | cb_snap_edge(&nearest2d, | ||||
| BM_elem_index_get(l_iter->e), | BM_elem_index_get(l_iter->e), | ||||
| &neasrest_precalc, | &neasrest_precalc, | ||||
| clip_planes_local, | clip_planes_local, | ||||
| Show All 38 Lines | static short snap_mesh_polygon(SnapObjectContext *sctx, | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, | static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, | ||||
| SnapData *snapdata, | SnapData *snapdata, | ||||
| Object *ob, | Object *ob, | ||||
| float obmat[4][4], | float obmat[4][4], | ||||
| float original_dist_px, | float original_dist_px, | ||||
| const float prev_co[3], | |||||
| /* read/write args */ | /* read/write args */ | ||||
| float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], | float r_loc[3], | ||||
| float r_no[3], | float r_no[3], | ||||
| int *r_index) | int *r_index) | ||||
| { | { | ||||
| short elem = SCE_SNAP_MODE_EDGE; | short elem = SCE_SNAP_MODE_EDGE; | ||||
| ▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) { | ||||
| nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata); | nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata); | ||||
| nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata); | nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata); | ||||
| mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]); | mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]); | ||||
| nearest.index = *r_index; | nearest.index = *r_index; | ||||
| elem = SCE_SNAP_MODE_EDGE_MIDPOINT; | elem = SCE_SNAP_MODE_EDGE_MIDPOINT; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (prev_co && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { | |||||
| float v_near[3], va_g[3], vb_g[3]; | |||||
| mul_v3_m4v3(va_g, obmat, v_pair[0]); | |||||
| mul_v3_m4v3(vb_g, obmat, v_pair[1]); | |||||
| lambda = line_point_factor_v3(prev_co, va_g, vb_g); | |||||
| if (IN_RANGE(lambda, 0.0f, 1.0f)) { | |||||
| interp_v3_v3v3(v_near, va_g, vb_g, lambda); | |||||
| 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; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| if (nearest.index != -1) { | if (nearest.index != -1) { | ||||
| *dist_px = sqrtf(nearest.dist_sq); | *dist_px = sqrtf(nearest.dist_sq); | ||||
| copy_v3_v3(r_loc, nearest.co); | copy_v3_v3(r_loc, nearest.co); | ||||
| if (elem != SCE_SNAP_MODE_EDGE_PERPENDICULAR) { | |||||
| mul_m4_v3(obmat, r_loc); | mul_m4_v3(obmat, r_loc); | ||||
| } | |||||
| if (r_no) { | if (r_no) { | ||||
| float imat[4][4]; | float imat[4][4]; | ||||
| invert_m4_m4(imat, obmat); | invert_m4_m4(imat, obmat); | ||||
| copy_v3_v3(r_no, nearest.no); | copy_v3_v3(r_no, nearest.no); | ||||
| mul_transposed_mat3_m4_v3(imat, r_no); | mul_transposed_mat3_m4_v3(imat, r_no); | ||||
| normalize_v3(r_no); | normalize_v3(r_no); | ||||
| ▲ Show 20 Lines • Show All 609 Lines • ▼ Show 20 Lines | BLI_bvhtree_find_nearest_projected(bvhtree[1], | ||||
| snapdata->clip_plane_len, | snapdata->clip_plane_len, | ||||
| &nearest, | &nearest, | ||||
| cb_snap_vert, | cb_snap_vert, | ||||
| &nearest2d); | &nearest2d); | ||||
| last_index = nearest.index; | last_index = nearest.index; | ||||
| } | } | ||||
| if (snapdata->snap_to_flag & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT)) { | if (snapdata->snap_to_flag & | ||||
| (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { | |||||
| if (bvhtree[0]) { | if (bvhtree[0]) { | ||||
| /* snap to loose edges */ | /* snap to loose edges */ | ||||
| BLI_bvhtree_find_nearest_projected(bvhtree[0], | BLI_bvhtree_find_nearest_projected(bvhtree[0], | ||||
| lpmat, | lpmat, | ||||
| snapdata->win_size, | snapdata->win_size, | ||||
| snapdata->mval, | snapdata->mval, | ||||
| clip_planes_local, | clip_planes_local, | ||||
| snapdata->clip_plane_len, | snapdata->clip_plane_len, | ||||
| ▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | if (treedata_vert->tree == NULL) { | ||||
| MEM_freeN(verts_mask); | MEM_freeN(verts_mask); | ||||
| } | } | ||||
| else { | else { | ||||
| bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, em_bvh_cache); | bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, em_bvh_cache); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (snapdata->snap_to_flag & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT)) { | if (snapdata->snap_to_flag & | ||||
| (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { | |||||
| if (sod->bvh_trees[1] == NULL) { | if (sod->bvh_trees[1] == NULL) { | ||||
| sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); | sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); | ||||
| } | } | ||||
| treedata_edge = sod->bvh_trees[1]; | treedata_edge = sod->bvh_trees[1]; | ||||
| if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) { | if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) { | ||||
| /* The tree is owned by the Mesh and may have been freed since we last used! */ | /* The tree is owned by the Mesh and may have been freed since we last used! */ | ||||
| if (treedata_edge->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_edge->tree)) { | if (treedata_edge->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_edge->tree)) { | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | BLI_bvhtree_find_nearest_projected(treedata_vert->tree, | ||||
| snapdata->clip_plane_len, | snapdata->clip_plane_len, | ||||
| &nearest, | &nearest, | ||||
| cb_snap_vert, | cb_snap_vert, | ||||
| &nearest2d); | &nearest2d); | ||||
| last_index = nearest.index; | last_index = nearest.index; | ||||
| } | } | ||||
| if (treedata_edge && | if (treedata_edge && snapdata->snap_to_flag & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | | ||||
| snapdata->snap_to_flag & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT)) { | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { | ||||
| BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT); | BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT); | ||||
| BLI_bvhtree_find_nearest_projected(treedata_edge->tree, | BLI_bvhtree_find_nearest_projected(treedata_edge->tree, | ||||
| lpmat, | lpmat, | ||||
| snapdata->win_size, | snapdata->win_size, | ||||
| snapdata->mval, | snapdata->mval, | ||||
| clip_planes_local, | clip_planes_local, | ||||
| snapdata->clip_plane_len, | snapdata->clip_plane_len, | ||||
| &nearest, | &nearest, | ||||
| ▲ Show 20 Lines • Show All 379 Lines • ▼ Show 20 Lines | return transform_snap_context_project_ray_impl( | ||||
| sctx, params, ray_origin, ray_direction, ray_depth, r_co, r_no); | sctx, params, ray_origin, ray_direction, ray_depth, r_co, r_no); | ||||
| } | } | ||||
| static short transform_snap_context_project_view3d_mixed_impl( | static short transform_snap_context_project_view3d_mixed_impl( | ||||
| SnapObjectContext *sctx, | SnapObjectContext *sctx, | ||||
| const unsigned short snap_to_flag, | const unsigned short snap_to_flag, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float mval[2], | const float mval[2], | ||||
| const float prev_co[3], | |||||
| float *dist_px, | float *dist_px, | ||||
| float r_loc[3], | float r_loc[3], | ||||
| float r_no[3], | float r_no[3], | ||||
| int *r_index, | int *r_index, | ||||
| Object **r_ob, | Object **r_ob, | ||||
| float r_obmat[4][4]) | float r_obmat[4][4]) | ||||
| { | { | ||||
| BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | | BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | | ||||
| SCE_SNAP_MODE_EDGE_MIDPOINT)) != 0); | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) != | ||||
| 0); | |||||
| short retval = 0; | short retval = 0; | ||||
| bool has_hit = false; | bool has_hit = false; | ||||
| int index = -1; | int index = -1; | ||||
| float loc[3], no[3], obmat[4][4]; | float loc[3], no[3], obmat[4][4]; | ||||
| Object *ob = NULL; | Object *ob = NULL; | ||||
| Show All 21 Lines | if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) { | ||||
| has_hit = raycastObjects( | has_hit = raycastObjects( | ||||
| sctx, params, ray_start, ray_normal, &dummy_ray_depth, loc, no, &index, &ob, obmat, NULL); | sctx, params, ray_start, ray_normal, &dummy_ray_depth, loc, no, &index, &ob, obmat, NULL); | ||||
| if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) { | if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) { | ||||
| retval = SCE_SNAP_MODE_FACE; | retval = SCE_SNAP_MODE_FACE; | ||||
| } | } | ||||
| } | } | ||||
| if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT)) { | 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; | ||||
| float dist_px_tmp = *dist_px; | float dist_px_tmp = *dist_px; | ||||
| SnapData snapdata; | SnapData snapdata; | ||||
| copy_m4_m4(snapdata.pmat, rv3d->persmat); | copy_m4_m4(snapdata.pmat, rv3d->persmat); | ||||
| snapdata.win_size[0] = ar->winx; | snapdata.win_size[0] = ar->winx; | ||||
| snapdata.win_size[1] = ar->winy; | snapdata.win_size[1] = ar->winy; | ||||
| copy_v2_v2(snapdata.mval, mval); | copy_v2_v2(snapdata.mval, mval); | ||||
| Show All 37 Lines | if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | | ||||
| elem = snapObjectsRay(sctx, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat); | elem = snapObjectsRay(sctx, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat); | ||||
| if (elem) { | if (elem) { | ||||
| retval = elem; | retval = elem; | ||||
| } | } | ||||
| if ((retval == SCE_SNAP_MODE_EDGE) && | if ((retval == SCE_SNAP_MODE_EDGE) && | ||||
| (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE_MIDPOINT))) { | (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE_MIDPOINT | | ||||
| SCE_SNAP_MODE_EDGE_PERPENDICULAR))) { | |||||
| elem = snap_mesh_edge_verts_mixed( | elem = snap_mesh_edge_verts_mixed( | ||||
| sctx, &snapdata, ob, obmat, *dist_px, &dist_px_tmp, loc, no, &index); | sctx, &snapdata, ob, obmat, *dist_px, prev_co, &dist_px_tmp, loc, no, &index); | ||||
| } | } | ||||
| if (elem) { | if (elem) { | ||||
| retval = elem; | retval = elem; | ||||
| } | } | ||||
| retval &= snap_to_flag; | retval &= snap_to_flag; | ||||
| *dist_px = dist_px_tmp; | *dist_px = dist_px_tmp; | ||||
| Show All 18 Lines | static short transform_snap_context_project_view3d_mixed_impl( | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, | short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, | ||||
| const unsigned short snap_to, | const unsigned short snap_to, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float mval[2], | const float mval[2], | ||||
| const float prev_co[3], | |||||
| float *dist_px, | float *dist_px, | ||||
| float r_loc[3], | float r_loc[3], | ||||
| float r_no[3], | float r_no[3], | ||||
| int *r_index, | int *r_index, | ||||
| Object **r_ob, | Object **r_ob, | ||||
| float r_obmat[4][4]) | float r_obmat[4][4]) | ||||
| { | { | ||||
| return transform_snap_context_project_view3d_mixed_impl( | return transform_snap_context_project_view3d_mixed_impl( | ||||
| sctx, snap_to, params, mval, dist_px, r_loc, r_no, r_index, r_ob, r_obmat) != 0; | sctx, snap_to, params, mval, prev_co, dist_px, r_loc, r_no, r_index, r_ob, r_obmat) != | ||||
| 0; | |||||
| } | } | ||||
| /** | /** | ||||
| * Convenience function for performing snapping. | * Convenience function for performing snapping. | ||||
| * | * | ||||
| * Given a 2D region value, snap to vert/edge/face. | * Given a 2D region value, snap to vert/edge/face. | ||||
| * | * | ||||
| * \param sctx: Snap context. | * \param sctx: Snap context. | ||||
| * \param mval: Screenspace coordinate. | * \param mval: Screenspace coordinate. | ||||
| * \param prev_co: Coordinate for perpendicular point calculation. | |||||
campbellbarton: Should mention it can be NULL. | |||||
| * \param dist_px: Maximum distance to snap (in pixels). | * \param dist_px: Maximum distance to snap (in pixels). | ||||
| * \param r_co: hit location. | * \param r_co: hit location. | ||||
| * \param r_no: hit normal (optional). | * \param r_no: hit normal (optional). | ||||
| * \return Snap success | * \return Snap success | ||||
| */ | */ | ||||
| bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx, | bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx, | ||||
| const unsigned short snap_to, | const unsigned short snap_to, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float mval[2], | const float mval[2], | ||||
| const float prev_co[3], | |||||
| float *dist_px, | float *dist_px, | ||||
| float r_loc[3], | float r_loc[3], | ||||
| float r_no[3]) | float r_no[3]) | ||||
| { | { | ||||
| return ED_transform_snap_object_project_view3d_ex( | return ED_transform_snap_object_project_view3d_ex( | ||||
| sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL) != 0; | sctx, snap_to, params, mval, prev_co, dist_px, r_loc, r_no, NULL, NULL, NULL) != 0; | ||||
| } | } | ||||
| /** | /** | ||||
| * see: #ED_transform_snap_object_project_ray_all | * see: #ED_transform_snap_object_project_ray_all | ||||
| */ | */ | ||||
| bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx, | bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float mval[2], | const float mval[2], | ||||
| Show All 22 Lines | |||||
Should mention it can be NULL.