diff options
Diffstat (limited to 'source/blender/bmesh/operators/bmo_connect.c')
-rw-r--r-- | source/blender/bmesh/operators/bmo_connect.c | 93 |
1 files changed, 63 insertions, 30 deletions
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index 4cf6e82fc8e..0213329118c 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -36,54 +36,68 @@ #include "intern/bmesh_operators_private.h" /* own include */ #define VERT_INPUT 1 + #define EDGE_OUT 1 -#define FACE_TAG 2 +/* Edge spans 2 VERT_INPUT's, its a nop, + * but include in "edges.out" */ +#define EDGE_OUT_ADJ 2 + +#define FACE_TAG 2 +#define FACE_EXCLUDE 4 static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenerate) { - BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, f->len); + const unsigned pair_split_max = f->len / 2; + BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, pair_split_max); STACK_DECLARE(loops_split); - BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, f->len); + BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, pair_split_max); STACK_DECLARE(verts_pair); - BMIter liter; - BMFace *f_new; - BMLoop *l; - BMLoop *l_last; + BMLoop *l_tag_prev = NULL, *l_tag_first = NULL; + BMLoop *l_iter, *l_first; unsigned int i; - STACK_INIT(loops_split, f->len); - STACK_INIT(verts_pair, f->len); + STACK_INIT(loops_split, pair_split_max); + STACK_INIT(verts_pair, pair_split_max); - l_last = NULL; - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - if (BMO_elem_flag_test(bm, l->v, VERT_INPUT)) { - if (!l_last) { - l_last = l; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BMO_elem_flag_test(bm, l_iter->v, VERT_INPUT) && + /* ensure this vertex isnt part of a contiguous group */ + ((BMO_elem_flag_test(bm, l_iter->prev->v, VERT_INPUT) == 0) || + (BMO_elem_flag_test(bm, l_iter->next->v, VERT_INPUT) == 0))) + { + if (!l_tag_prev) { + l_tag_prev = l_tag_first = l_iter; continue; } - if (!BM_loop_is_adjacent(l_last, l)) { + if (!BM_loop_is_adjacent(l_tag_prev, l_iter)) { BMEdge *e; - e = BM_edge_exists(l_last->v, l->v); + e = BM_edge_exists(l_tag_prev->v, l_iter->v); if (e == NULL || !BMO_elem_flag_test(bm, e, EDGE_OUT)) { BMLoop **l_pair = STACK_PUSH_RET(loops_split); - l_pair[0] = l_last; - l_pair[1] = l; + l_pair[0] = l_tag_prev; + l_pair[1] = l_iter; } } - l_last = l; + + l_tag_prev = l_iter; } - } + } while ((l_iter = l_iter->next) != l_first); if (STACK_SIZE(loops_split) == 0) { return 0; } - if (STACK_SIZE(loops_split) > 1) { + if (!BM_loop_is_adjacent(l_tag_first, l_tag_prev) && + /* ensure we don't add the same pair twice */ + (((loops_split[0][0] == l_tag_first) && + (loops_split[0][1] == l_tag_prev)) == 0)) + { BMLoop **l_pair = STACK_PUSH_RET(loops_split); - l_pair[0] = loops_split[STACK_SIZE(loops_split) - 2][1]; - l_pair[1] = loops_split[0][0]; + l_pair[0] = l_tag_first; + l_pair[1] = l_tag_prev; } if (check_degenerate) { @@ -105,6 +119,7 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera } for (i = 0; i < STACK_SIZE(verts_pair); i++) { + BMFace *f_new; BMLoop *l_new; BMLoop *l_a, *l_b; @@ -134,7 +149,6 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) { BMOIter siter; - BMIter iter; BMVert *v; BMFace *f; const bool check_degenerate = BMO_slot_bool_get(op->slots_in, "check_degenerate"); @@ -142,16 +156,35 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) BLI_LINKSTACK_INIT(faces); + /* tag so we won't touch ever (typically hidden faces) */ + BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces_exclude", BM_FACE, FACE_EXCLUDE); + /* add all faces connected to verts */ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { + BMIter iter; + BMLoop *l_iter; + BMO_elem_flag_enable(bm, v, VERT_INPUT); - BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { - if (!BMO_elem_flag_test(bm, f, FACE_TAG)) { - BMO_elem_flag_enable(bm, f, FACE_TAG); - if (f->len > 3) { - BLI_LINKSTACK_PUSH(faces, f); + BM_ITER_ELEM (l_iter, &iter, v, BM_LOOPS_OF_VERT) { + f = l_iter->f; + if (!BMO_elem_flag_test(bm, f, FACE_EXCLUDE)) { + if (!BMO_elem_flag_test(bm, f, FACE_TAG)) { + BMO_elem_flag_enable(bm, f, FACE_TAG); + if (f->len > 3) { + BLI_LINKSTACK_PUSH(faces, f); + } } } + + /* flag edges even if these are not newly created + * this way cut-pairs that include co-linear edges will get + * predictable output. */ + if (BMO_elem_flag_test(bm, l_iter->prev->v, VERT_INPUT)) { + BMO_elem_flag_enable(bm, l_iter->prev->e, EDGE_OUT_ADJ); + } + if (BMO_elem_flag_test(bm, l_iter->next->v, VERT_INPUT)) { + BMO_elem_flag_enable(bm, l_iter->e, EDGE_OUT_ADJ); + } } } @@ -164,5 +197,5 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) BLI_LINKSTACK_FREE(faces); - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT | EDGE_OUT_ADJ); } |