diff options
Diffstat (limited to 'source/blender/bmesh/tools/bmesh_intersect.c')
-rw-r--r-- | source/blender/bmesh/tools/bmesh_intersect.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index 4ca8364c312..c73b80d57f7 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -509,7 +509,7 @@ static bool bm_loop_filter_fn(const BMLoop *l, void *user_data) * Return true if we have any intersections. */ static void bm_isect_tri_tri( - struct ISectState *s, int a_index, int b_index, BMLoop **a, BMLoop **b) + struct ISectState *s, int a_index, int b_index, BMLoop **a, BMLoop **b, bool no_shared) { BMFace *f_a = (*a)->f; BMFace *f_b = (*b)->f; @@ -527,9 +527,16 @@ static void bm_isect_tri_tri( STACK_DECLARE(iv_ls_a); STACK_DECLARE(iv_ls_b); - if (UNLIKELY(ELEM(fv_a[0], UNPACK3(fv_b)) || ELEM(fv_a[1], UNPACK3(fv_b)) || - ELEM(fv_a[2], UNPACK3(fv_b)))) { - return; + if (no_shared) { + if (UNLIKELY(ELEM(fv_a[0], UNPACK3(fv_b)) || ELEM(fv_a[1], UNPACK3(fv_b)) || + ELEM(fv_a[2], UNPACK3(fv_b)))) { + return; + } + } + else { + if (UNLIKELY(BM_face_share_edge_check(f_a, f_b))) { + return; + } } STACK_INIT(iv_ls_a, ARRAY_SIZE(iv_ls_a)); @@ -564,11 +571,11 @@ static void bm_isect_tri_tri( for (i_b = 0; i_b < 3; i_b++) { if (len_squared_v3v3(fv_a[i_a]->co, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) { #ifdef USE_DUMP - if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT) == 0) { - printf(" ('VERT-VERT-A') %d, %d),\n", i_a, BM_elem_index_get(fv_a[i_a])); + if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT_A) == 0) { + printf(" ('VERT-VERT-A') %u, %d),\n", i_a, BM_elem_index_get(fv_a[i_a])); } - if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT) == 0) { - printf(" ('VERT-VERT-B') %d, %d),\n", i_b, BM_elem_index_get(fv_b[i_b])); + if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT_B) == 0) { + printf(" ('VERT-VERT-B') %u, %d),\n", i_b, BM_elem_index_get(fv_b[i_b])); } #endif STACK_PUSH_TEST_A(fv_a[i_a]); @@ -905,7 +912,7 @@ static int isect_bvhtree_point_v3(BVHTree *tree, const float **looptris, const f BLI_bvhtree_ray_cast(tree, co, dir, 0.0f, &hit, raycast_callback, &raycast_data); # ifdef USE_DUMP - printf("%s: Total intersections: %d\n", __func__, z_buffer.count); + printf("%s: Total intersections: %zu\n", __func__, z_buffer.count); # endif int num_isect; @@ -1082,6 +1089,12 @@ bool BM_mesh_intersect(BMesh *bm, tree_b = tree_a; } + /* For self intersection this can be useful, sometimes users generate geometry + * where surfaces that seem disconnected happen to share an edge. + * So when performing intersection calculation allow shared vertices, + * just not shared edges. See T75946. */ + const bool isect_tri_tri_no_shared = (boolean_mode != BMESH_ISECT_BOOLEAN_NONE); + int flag = BVH_OVERLAP_USE_THREADING | BVH_OVERLAP_RETURN_PAIRS; # ifdef DEBUG /* The overlap result must match that obtained in Release to succeed @@ -1103,7 +1116,8 @@ bool BM_mesh_intersect(BMesh *bm, overlap[i].indexA, overlap[i].indexB, looptris[overlap[i].indexA], - looptris[overlap[i].indexB]); + looptris[overlap[i].indexB], + isect_tri_tri_no_shared); # ifdef USE_DUMP printf(")),\n"); # endif @@ -1140,7 +1154,7 @@ bool BM_mesh_intersect(BMesh *bm, # ifdef USE_DUMP printf(" ((%d, %d), (", i_a, i_b); # endif - bm_isect_tri_tri(&s, i_a, i_b, looptris[i_a], looptris[i_b]); + bm_isect_tri_tri(&s, i_a, i_b, looptris[i_a], looptris[i_b], isect_tri_tri_no_shared); # ifdef USE_DUMP printf(")),\n"); # endif @@ -1179,7 +1193,7 @@ bool BM_mesh_intersect(BMesh *bm, } # ifdef USE_DUMP - printf("# SPLITTING EDGE: %d, %d\n", BM_elem_index_get(e), v_ls_base->list_len); + printf("# SPLITTING EDGE: %d, %u\n", BM_elem_index_get(e), v_ls_base->list_len); # endif /* intersect */ is_wire = BLI_gset_haskey(s.wire_edges, e); @@ -1258,6 +1272,13 @@ bool BM_mesh_intersect(BMesh *bm, continue; } + /* It's possible the vertex to dissolve is an edge on an existing face + * that doesn't divide the face, therefor the edges are not wire + * and shouldn't be handled here, see: T63787. */ + if (!BLI_gset_haskey(s.wire_edges, e_pair[0]) || !BLI_gset_haskey(s.wire_edges, e_pair[1])) { + continue; + } + v_a = BM_edge_other_vert(e_pair[0], v); v_b = BM_edge_other_vert(e_pair[1], v); |