Dissolve verts better cleans up two-edged faces, as much
authorJoseph Eagar <joeedh@gmail.com>
Sun, 15 Feb 2009 02:14:40 +0000 (02:14 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Sun, 15 Feb 2009 02:14:40 +0000 (02:14 +0000)
as it can.

Some design notes:

* BM_Dissolve_Disk is now more like a
  BM_Dissolve_Vert function (e.g. there's logic
  to remove verts if there's not surrounding faces).
  I kindof like this idea better (if we decide to
  go this way we should call it BM_Dissolve_Vert)
  but will have to discuss it further with Briggs.
  It seems more intuitive to have a "destroy this
  vert" function then a "just destroy it in this
  specific situation" function.

* Joining two two-edged faces does not work, so
  dissolve vert cannot clean all of them up.  Until
  this is fixed, I've added checks in the conversion
  code so at least things don't crash.

source/blender/bmesh/intern/bmesh_mods.c
source/blender/bmesh/intern/bmesh_to_editmesh.c
source/blender/bmesh/operators/dissolveops.c

index 8334876395c513c70acc222d05d2f684c5019446..05d9fb34efff0741c3b905bf7a3bee5c18099b19 100644 (file)
@@ -36,8 +36,6 @@
  *          |=========|             |=========|
  * 
  * 
- *  Returns -
- *     1 for success, 0 for failure.
  */
 #if 1
 void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
@@ -46,7 +44,14 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
        BMLoop *loop;
        int done, len;
 
-       if(BM_Nonmanifold_Vert(bm, v)) return;
+       if(BM_Nonmanifold_Vert(bm, v)) {
+               if (!v->edge) bmesh_kv(bm, v);
+               else if (!v->edge->loop) {
+                       bmesh_ke(bm, v->edge);
+                       bmesh_kv(bm, v);
+               }
+               return;
+       }
        
        if(v->edge){
                /*v->edge we keep, what else?*/
@@ -81,6 +86,9 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
                /*collapse the vertex*/
                BM_Collapse_Vert(bm, v->edge, v, 1.0, 0);
                BM_Join_Faces(bm, f, f2, NULL, 0, 0);
+       } else if (len == 1) {
+               bmesh_ke(bm, v->edge);
+               bmesh_kv(bm, v);
        }
 
        if(keepedge){
index 63a35a99fd47b5b97693abf03ee1326a5e1ad27a..090297c14d4c3a3d2d6ec602f8f9f96ec97a2819 100644 (file)
@@ -154,6 +154,7 @@ static EditFace *bmeshface_to_editface(BMesh *bm, EditMesh *em, BMFace *f, EditV
        }
 
        efa = addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);
+       if (!efa) return NULL;
 
        bmeshedge_to_editedge_internal(bm, em, f->loopbase->e, efa->e1);
        bmeshedge_to_editedge_internal(bm, em, ((BMLoop*)(f->loopbase->head.next))->e, efa->e2);
index 2846e2043aa20a838299863501c8f886020c2000..9d0e6907e390825ea7c4c1f4aeab0cd7139371fa 100644 (file)
@@ -28,38 +28,83 @@ void dissolveverts_exec(BMesh *bm, BMOperator *op)
        BMIter iter, liter, fiter;
        BMVert *v;
        BMFace *f, *f2;
-       BMEdge *e;
+       BMEdge *fe;
        BMLoop *l;
-       int i, found;
+       int found, found2, found3, len, oldlen=0;
        
        vinput = BMO_GetSlot(op, BMOP_DISVERTS_VERTIN);
 
        BMO_Flag_Buffer(bm, op, BMOP_DISVERTS_VERTIN, VERT_MARK);
-
-       for (v=BMIter_New(&iter, bm, BM_VERTS, NULL); v; v=BMIter_Step(&iter)) {
-               if (BMO_TestFlag(bm, v, VERT_MARK)) {
-                       BM_Dissolve_Disk(bm, v);
+       
+       found = 1;
+       while (found) {
+               found = 0;
+               len = 0;
+               for (v=BMIter_New(&iter, bm, BM_VERTS, NULL); v; v=BMIter_Step(&iter)) {
+                       if (BMO_TestFlag(bm, v, VERT_MARK)) {
+                               BM_Dissolve_Disk(bm, v);
+                               found = 1;
+                               len++;
+                       }
                }
-       }
 
-       /*clean up two-edged faces*/
-       for (f=BMIter_New(&iter, bm, BM_FACES, NULL); f; f=BMIter_Step(&iter)){
-               if (f->len == 2) {
-                       found = 0;
-                       l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
-                       for (; l; l=BMIter_Step(&liter)) {
-                               f2 = BMIter_New(&fiter, bm,
-                                               BM_FACES_OF_EDGE, l->e);
-                               for (; f2; f2=BMIter_Step(&fiter)) {
-                                       if (f2 != f) {
-                                               BM_Join_Faces(bm, f, f2, l->e, 
-                                                             1, 0);
-                                               found = 1;
-                                               break;
+
+               /*clean up two-edged faces*/
+               /*basic idea is to keep joining 2-edged faces until their
+                 gone.  this however relies on joining two 2-edged faces
+                 together to work, which doesn't.*/
+               found3 = 1;
+               while (found3) {
+                       found3 = 0;
+                       for (f=BMIter_New(&iter, bm, BM_FACES, NULL); f; f=BMIter_Step(&iter)){
+                               if (f->len == 2) {
+                                       //this design relies on join faces working
+                                       //with two-edged faces properly.
+                                       //commenting this line disables the
+                                       //outermost loop.
+                                       //found3 = 1;
+                                       found2 = 0;
+                                       l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+                                       fe = l->e;
+                                       for (; l; l=BMIter_Step(&liter)) {
+                                               f2 = BMIter_New(&fiter, bm,
+                                                               BM_FACES_OF_EDGE, l->e);
+                                               for (; f2; f2=BMIter_Step(&fiter)) {
+                                                       if (f2 != f) {
+                                                               BM_Join_Faces(bm, f, f2, l->e, 
+                                                                             1, 0);
+                                                               found2 = 1;
+                                                               break;
+                                                       }
+                                               }
+                                               if (found2) break;
+                                       }
+
+                                       if (!found2) {
+                                               bmesh_kf(bm, f);
+                                               bmesh_ke(bm, fe);
+                                       }
+                               } else if (f->len == 3) {
+                                       BMEdge *ed[3];
+                                       BMVert *vt[3];
+                                       BMLoop *lp[3];
+                                       int i=0;
+
+                                       /*check for duplicate edges*/
+                                       l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+                                       for (; l; l=BMIter_Step(&liter)) {
+                                               ed[i++] = l->e; 
+                                               lp[i++] = l;
+                                               vt[i++] = l->v;
+                                       }
+                                       if (vt[0] == vt[1] || vt[0] == vt[2]) {
+                                               i += 1;
                                        }
                                }
-                               if (found) break;
                        }
                }
+               if (oldlen == len) break;
+               oldlen = len;
        }
+
 }
\ No newline at end of file