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.
This commit is contained in:
Campbell Barton 2017-03-11 23:21:37 +11:00
parent ce155ad2f6
commit 304315d181
1 changed files with 51 additions and 34 deletions

View File

@ -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);
l_iter = l_first = e->l;
do {
if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
is_mixed = true;
is_mixed_any = true;
break;
}
} while ((l_iter = l_iter->radial_next) != l_first);
if (is_mixed) {
/* 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;
}
BLI_SMALLSTACK_PUSH(edges, e);
edges_len += 1;
}
}
}
if (is_mixed_any == false) {
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_loop = true;
break;
}
} while ((l_iter = l_iter->radial_next) != l_first);
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_iter->l = l_iter;
is_mixed_loop_any = true;
}
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);
}
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];