diff options
author | Campbell Barton <ideasman42@gmail.com> | 2014-06-26 23:11:02 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2014-06-26 23:39:39 +0400 |
commit | 2aca720bff109861e2e617940f6e95076458ef71 (patch) | |
tree | eb1cb89ac2a84d4bee539922f2f865850dc54de7 /source/blender/bmesh/operators | |
parent | 8ef23145975b8d5501d8a0e2b4e7029b12aa803b (diff) |
Fix T40813: Dissolve verts with adjacent regions, removes the dividing edge
Diffstat (limited to 'source/blender/bmesh/operators')
-rw-r--r-- | source/blender/bmesh/operators/bmo_dissolve.c | 149 |
1 files changed, 54 insertions, 95 deletions
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 59a78033e04..36a936c6622 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -335,126 +335,85 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) } } -static bool test_extra_verts(BMesh *bm, BMVert *v) -{ - BMIter fiter, liter, eiter, fiter_sub; - BMFace *f; - BMLoop *l; - BMEdge *e; - - /* test faces around verts for verts that would be wrongly killed - * by dissolve faces. */ - BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) { - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) { - /* if an edge around a vert is a boundary edge, - * then dissolve faces won't destroy it. - * also if it forms a boundary with one - * of the face region */ - bool found = false; - BM_ITER_ELEM (e, &eiter, l->v, BM_EDGES_OF_VERT) { - BMFace *f_iter; - if (BM_edge_is_boundary(e)) { - found = true; - } - else { - BM_ITER_ELEM (f_iter, &fiter_sub, e, BM_FACES_OF_EDGE) { - if (!BMO_elem_flag_test(bm, f_iter, FACE_MARK)) { - found = true; - break; - } - } - } - if (found == true) { - break; - } - } - if (found == false) { - return false; - } - } - } - } - - return true; -} void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) { - BMIter iter, fiter; + BMOIter oiter; + BMIter iter; BMVert *v, *v_next; - BMFace *f; + BMEdge *e, *e_next; + BMFace *act_face = bm->act_face; const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split"); + BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) { + BMIter itersub; + + BMO_elem_flag_enable(bm, v, VERT_MARK | VERT_ISGC); + + BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) { + BMO_elem_flag_enable(bm, e, EDGE_ISGC); + } + } - BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_MARK); - if (use_face_split) { bm_face_split(bm, VERT_MARK); } - BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { - if (BMO_elem_flag_test(bm, v, VERT_MARK)) { - /* check if it's a two-valence ver */ - if (BM_vert_edge_count(v) == 2) { + BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) { + BMIter itersub; + BMLoop *l_first; + BM_ITER_ELEM (l_first, &itersub, v, BM_LOOPS_OF_VERT) { + BMLoop *l_iter; + l_iter = l_first; + do { + BMO_elem_flag_enable(bm, l_iter->v, VERT_ISGC); + BMO_elem_flag_enable(bm, l_iter->e, EDGE_ISGC); + } while ((l_iter = l_iter->next) != l_first); + } + } - /* collapse the ver */ - /* previously the faces were joined, but collapsing between 2 edges - * gives some advantage/difference in using vertex-dissolve over edge-dissolve */ -#if 0 - BM_vert_collapse_faces(bm, v->e, v, 1.0f, true, true); -#else - BM_vert_collapse_edge(bm, v->e, v, true); -#endif + BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) { + BMIter itersub; - continue; - } + if (BM_vert_edge_count(v) != 2) { + BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) { + BMFace *fa, *fb; + if (BM_edge_face_pair(e, &fa, &fb)) { + BMFace *f_new; - BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) { - BMO_elem_flag_enable(bm, f, FACE_MARK | FACE_ORIG); - } - - /* check if our additions to the input to face dissolve - * will destroy nonmarked vertices. */ - if (!test_extra_verts(bm, v)) { - BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) { - if (BMO_elem_flag_test(bm, f, FACE_ORIG)) { - BMO_elem_flag_disable(bm, f, FACE_MARK | FACE_ORIG); + /* join faces */ + f_new = BM_faces_join_pair(bm, fa, fb, e, false); + + /* maintain active face */ + if (act_face && bm->act_face == NULL) { + bm->act_face = f_new; } } } - else { - BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) { - BMO_elem_flag_disable(bm, f, FACE_ORIG); - } - } } } - BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_MARK); - if (BMO_error_occurred(bm)) { - const char *msg; - - BMO_error_get(bm, &msg, NULL); - BMO_error_clear(bm); - BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, msg); + /* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on) + * so do this in a separate pass instead. */ + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { + if ((e->l == NULL) && BMO_elem_flag_test(bm, e, EDGE_ISGC)) { + BM_edge_kill(bm, e); + } } - - /* clean up any remaining */ - /* note: don't use BM_ITER_MESH_MUTABLE here, even though vertices are removed (T37559) */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { + if ((v->e == NULL) && BMO_elem_flag_test(bm, v, VERT_ISGC)) { + BM_vert_kill(bm, v); + } + } + /* done with cleanup */ + + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { - if (!BM_vert_dissolve(bm, v)) { - BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL); - return; + if (BM_vert_edge_count(v) == 2) { + BM_vert_collapse_edge(bm, v->e, v, true); } -#ifdef DEBUG - /* workaround debug assert */ - iter.count = bm->totvert; -#endif } } - } /* Limited Dissolve */ |