From 304315d181dba4f45093950b448608e1194e8bbd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 11 Mar 2017 23:21:37 +1100 Subject: BMesh: Fix BM_face_loop_separate_multi When the loop region passed in had no loops to edge-split from, it was assumed nothing needed to be done. This ignored the case where loops share a vertex without any shared edges. Now BM_face_loop_separate_multi behaves like BM_face_loop_separate. Fixed error where faces remained connected by verts in BM_mesh_separate_faces. --- source/blender/bmesh/intern/bmesh_core.c | 67 ++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 25 deletions(-) (limited to 'source/blender/bmesh/intern/bmesh_core.c') diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index d1178a198dc..68cacf55efe 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2692,10 +2692,12 @@ BMVert *bmesh_urmv_loop_multi( { BMVert *v_sep = larr[0]->v; BMVert *v_new; + int edges_len = 0; int i; - bool is_mixed_any = false; - - BLI_SMALLSTACK_DECLARE(edges, BMEdge *); + /* any edges not owned by 'larr' loops connected to 'v_sep'? */ + bool is_mixed_edge_any = false; + /* any loops not owned by 'larr' radially connected to 'larr' loop edges? */ + bool is_mixed_loop_any = false; #define LOOP_VISIT _FLAG_WALK #define EDGE_VISIT _FLAG_WALK @@ -2713,58 +2715,73 @@ BMVert *bmesh_urmv_loop_multi( * while doing a radial loop (where loops may be adjacent) */ BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT); BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT); - } - - for (i = 0; i < larr_len; i++) { - BMLoop *l_sep = larr[i]; BMLoop *loop_pair[2] = {l_sep, l_sep->prev}; - int j; - for (j = 0; j < ARRAY_SIZE(loop_pair); j++) { + for (int j = 0; j < ARRAY_SIZE(loop_pair); j++) { BMEdge *e = loop_pair[j]->e; if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) { - BMLoop *l_iter, *l_first; - bool is_mixed = false; - BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT); + edges_len += 1; + } + } + } - l_iter = l_first = e->l; + BMEdge **edges = BLI_array_alloca(edges, edges_len); + STACK_DECLARE(edges); + + STACK_INIT(edges, edges_len); + + { + BMEdge *e_first, *e_iter; + e_iter = e_first = v_sep->e; + do { + if (BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)) { + BMLoop *l_iter, *l_first; + bool is_mixed_loop = false; + + l_iter = l_first = e_iter->l; do { if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { - is_mixed = true; - is_mixed_any = true; + is_mixed_loop = true; break; } } while ((l_iter = l_iter->radial_next) != l_first); - if (is_mixed) { + if (is_mixed_loop) { /* ensure the first loop is one we don't own so we can do a quick check below * on the edge's loop-flag to see if the edge is mixed or not. */ - e->l = l_iter; + e_iter->l = l_iter; + + is_mixed_loop_any = true; } - BLI_SMALLSTACK_PUSH(edges, e); + + STACK_PUSH(edges, e_iter); + } else { + /* at least one edge attached isn't connected to our loops */ + is_mixed_edge_any = true; } - } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_sep)) != e_first); } - if (is_mixed_any == false) { + BLI_assert(edges_len == STACK_SIZE(edges)); + + if (is_mixed_loop_any == false && is_mixed_edge_any == false) { /* all loops in 'larr' are the sole owners of their edges. * nothing to split away from, this is a no-op */ v_new = v_sep; } else { - BMEdge *e; - - BLI_assert(!BLI_SMALLSTACK_IS_EMPTY(edges)); - v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP); - while ((e = BLI_SMALLSTACK_POP(edges))) { + + for (i = 0; i < STACK_SIZE(edges); i++) { + BMEdge *e = edges[i]; BMLoop *l_iter, *l_first, *l_next; BMEdge *e_new; /* disable so copied edge isn't left dirty (loop edges are cleared last too) */ BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); + /* will always be false when (is_mixed_loop_any == false) */ if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) { /* edge has some loops owned by us, some owned by other loops */ BMVert *e_new_v_pair[2]; -- cgit v1.2.3