From bb860070185f6ed4d06593feae2095aeb45d7a23 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 4 Nov 2022 21:38:15 +1100 Subject: Fix T102232: bridge edge loop crash Many connected edge loops could result in two edge loops sharing vertices. This is more of a workaround, the reason for two edge loops sharing vertices could be prevented some other way. Add this check since it's a straightforward solution, furthered investigation noted as a TODO. --- source/blender/bmesh/operators/bmo_bridge.c | 122 +++++++++++++++++----------- 1 file changed, 76 insertions(+), 46 deletions(-) (limited to 'source/blender/bmesh/operators/bmo_bridge.c') diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c index 8240fbc53c1..b6520fb48b3 100644 --- a/source/blender/bmesh/operators/bmo_bridge.c +++ b/source/blender/bmesh/operators/bmo_bridge.c @@ -14,6 +14,13 @@ #include "intern/bmesh_operators_private.h" /* own include */ +/** + * TODO(@campbellbarton): Many connected edge loops can cause an error attempting + * to create faces with duplicate vertices. While this needs to be investigated, + * it's simple enough to check for this case, see: T102232. + */ +#define USE_DUPLICATE_FACE_VERT_CHECK + #define EDGE_MARK 4 #define EDGE_OUT 8 #define FACE_OUT 16 @@ -386,61 +393,84 @@ static void bridge_loop_pair(BMesh *bm, f_example = l_a ? l_a->f : (l_b ? l_b->f : NULL); if (v_b != v_b_next) { - BMVert *v_arr[4] = {v_b, v_b_next, v_a_next, v_a}; - f = BM_face_exists(v_arr, 4); - if (f == NULL) { - /* copy if loop data if its is missing on one ring */ - f = BM_face_create_verts(bm, v_arr, 4, NULL, BM_CREATE_NOP, true); - - l_iter = BM_FACE_FIRST_LOOP(f); - if (l_b) { - BM_elem_attrs_copy(bm, bm, l_b, l_iter); - } - l_iter = l_iter->next; - if (l_b_next) { - BM_elem_attrs_copy(bm, bm, l_b_next, l_iter); - } - l_iter = l_iter->next; - if (l_a_next) { - BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); - } - l_iter = l_iter->next; - if (l_a) { - BM_elem_attrs_copy(bm, bm, l_a, l_iter); +#ifdef USE_DUPLICATE_FACE_VERT_CHECK /* Only check for duplicates between loops. */ + BLI_assert((v_b != v_b_next) && (v_a_next != v_a)); + if (UNLIKELY(ELEM(v_b, v_a_next, v_a) || ELEM(v_b_next, v_a_next, v_a))) { + f = NULL; + } + else +#endif + { + BMVert *v_arr[4] = {v_b, v_b_next, v_a_next, v_a}; + f = BM_face_exists(v_arr, 4); + if (f == NULL) { + /* copy if loop data if its is missing on one ring */ + f = BM_face_create_verts(bm, v_arr, 4, NULL, BM_CREATE_NOP, true); + + l_iter = BM_FACE_FIRST_LOOP(f); + if (l_b) { + BM_elem_attrs_copy(bm, bm, l_b, l_iter); + } + l_iter = l_iter->next; + if (l_b_next) { + BM_elem_attrs_copy(bm, bm, l_b_next, l_iter); + } + l_iter = l_iter->next; + if (l_a_next) { + BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); + } + l_iter = l_iter->next; + if (l_a) { + BM_elem_attrs_copy(bm, bm, l_a, l_iter); + } } } } else { - BMVert *v_arr[3] = {v_b, v_a_next, v_a}; - f = BM_face_exists(v_arr, 3); - if (f == NULL) { - /* fan-fill a triangle */ - f = BM_face_create_verts(bm, v_arr, 3, NULL, BM_CREATE_NOP, true); - - l_iter = BM_FACE_FIRST_LOOP(f); - if (l_b) { - BM_elem_attrs_copy(bm, bm, l_b, l_iter); - } - l_iter = l_iter->next; - if (l_a_next) { - BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); - } - l_iter = l_iter->next; - if (l_a) { - BM_elem_attrs_copy(bm, bm, l_a, l_iter); +#ifdef USE_DUPLICATE_FACE_VERT_CHECK /* Only check for duplicates between loops. */ + BLI_assert(v_a_next != v_a); + if (UNLIKELY(ELEM(v_b, v_a_next, v_a))) { + f = NULL; + } + else +#endif + { + BMVert *v_arr[3] = {v_b, v_a_next, v_a}; + f = BM_face_exists(v_arr, 3); + if (f == NULL) { + /* fan-fill a triangle */ + f = BM_face_create_verts(bm, v_arr, 3, NULL, BM_CREATE_NOP, true); + + l_iter = BM_FACE_FIRST_LOOP(f); + if (l_b) { + BM_elem_attrs_copy(bm, bm, l_b, l_iter); + } + l_iter = l_iter->next; + if (l_a_next) { + BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); + } + l_iter = l_iter->next; + if (l_a) { + BM_elem_attrs_copy(bm, bm, l_a, l_iter); + } } } } - if (f_example && (f_example != f)) { - BM_elem_attrs_copy(bm, bm, f_example, f); - } - BMO_face_flag_enable(bm, f, FACE_OUT); - BM_elem_flag_enable(f, BM_ELEM_TAG); +#ifdef USE_DUPLICATE_FACE_VERT_CHECK + if (f != NULL) +#endif + { + if (f_example && (f_example != f)) { + BM_elem_attrs_copy(bm, bm, f_example, f); + } + BMO_face_flag_enable(bm, f, FACE_OUT); + BM_elem_flag_enable(f, BM_ELEM_TAG); - /* tag all edges of the face, untag the loop edges after */ - if (use_edgeout) { - bm_face_edges_tag_out(bm, f); + /* tag all edges of the face, untag the loop edges after */ + if (use_edgeout) { + bm_face_edges_tag_out(bm, f); + } } if (el_a_next == el_a_first) { -- cgit v1.2.3