bmesh edge dissolve: add option use_face_split (matching vertex dissolve option),
authorCampbell Barton <ideasman42@gmail.com>
Fri, 14 Jun 2013 02:30:40 +0000 (02:30 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 14 Jun 2013 02:30:40 +0000 (02:30 +0000)
useful to avoid odd shaped ngons surrounding dissolved edges.

source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/operators/bmo_dissolve.c
source/blender/editors/mesh/editmesh_tools.c

index 012cbccacc763f1d05139e1e4a39eb94b601d252..3958aa0ab7d201124005f049c5f5e83cbca160dd 100644 (file)
@@ -884,6 +884,7 @@ static BMOpDefine bmo_dissolve_edges_def = {
        /* slots_in */
        {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
         {"use_verts", BMO_OP_SLOT_BOOL},  /* dissolve verts left between only 2 edges. */
+        {"use_face_split", BMO_OP_SLOT_BOOL},
         {{'\0'}},
        },
        /* slots_out */
index 0f72a016e2f076b0fa770e06c1267701e9d16ed1..cca88a9eb47b2344876a7062e98693ea5975f78e 100644 (file)
 #define FACE_ORIG   2
 #define FACE_NEW    4
 #define EDGE_MARK   1
+#define EDGE_TAG    2
 
 #define VERT_MARK   1
+#define VERT_TAG    2
 
 static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
 {
@@ -73,6 +75,30 @@ static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
        return true;
 }
 
+static void bm_face_split(BMesh *bm, const short oflag)
+{
+       BMIter iter;
+       BMVert *v;
+
+       BMIter liter;
+       BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+               if (BMO_elem_flag_test(bm, v, oflag)) {
+                       if (BM_vert_edge_count(v) > 2) {
+                               BMLoop *l;
+                               BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+                                       if (l->f->len > 3) {
+                                               if (BMO_elem_flag_test(bm, l->next->v, oflag) == 0 &&
+                                                   BMO_elem_flag_test(bm, l->prev->v, oflag) == 0)
+                                               {
+                                                       BM_face_split(bm, l->f, l->next->v, l->prev->v, NULL, NULL, true);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
 void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
 {
        BMOIter oiter;
@@ -272,6 +298,28 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
        BMVert *v;
 
        const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
+       const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
+
+       if (use_face_split) {
+               BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_TAG);
+
+               BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+                       BMIter iter;
+                       int untag_count = 0;
+                       BM_ITER_ELEM(e, &iter, v, BM_EDGES_OF_VERT) {
+                               if (!BMO_elem_flag_test(bm, e, EDGE_TAG)) {
+                                       untag_count++;
+                               }
+                       }
+
+                       /* check that we have 2 edges remaining after dissolve */
+                       if (untag_count <= 2) {
+                               BMO_elem_flag_enable(bm, v, VERT_TAG);
+                       }
+               }
+
+               bm_face_split(bm, VERT_TAG);
+       }
 
        if (use_verts) {
                BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
@@ -366,23 +414,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
        BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_MARK);
        
        if (use_face_split) {
-               BMIter liter;
-               BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
-                       if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
-                               if (BM_vert_edge_count(v) > 2) {
-                                       BMLoop *l;
-                                       BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
-                                               if (l->f->len > 3) {
-                                                       if (BMO_elem_flag_test(bm, l->next->v, VERT_MARK) == 0 &&
-                                                               BMO_elem_flag_test(bm, l->prev->v, VERT_MARK) == 0)
-                                                       {
-                                                               BM_face_split(bm, l->f, l->next->v, l->prev->v, NULL, NULL, true);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
+               bm_face_split(bm, VERT_MARK);
        }
 
        BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
index 1f7690b9b4241fef4e5f209705e0815bb0f7a678..fa29a1e2ea8786304261d5a36b197d63d81d18f7 100644 (file)
@@ -2991,9 +2991,14 @@ static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op)
        BMEditMesh *em = BKE_editmesh_from_object(obedit);
 
        const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
+       const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
 
-       if (!EDBM_op_callf(em, op, "dissolve_edges edges=%he use_verts=%b", BM_ELEM_SELECT, use_verts))
+       if (!EDBM_op_callf(em, op,
+                          "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
+                          BM_ELEM_SELECT, use_verts, use_face_split))
+       {
                return OPERATOR_CANCELLED;
+       }
 
        EDBM_update_generic(em, true, true);
 
@@ -3015,6 +3020,8 @@ void MESH_OT_dissolve_edges(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        RNA_def_boolean(ot->srna, "use_verts", 0, "Dissolve Verts", "Dissolve remaining vertices");
+       RNA_def_boolean(ot->srna, "use_face_split", 0, "Face Split",
+                       "Split off face corners to maintain surrounding geometry");
 }
 
 static int edbm_dissolve_faces_exec(bContext *C, wmOperator *op)