fix [#31235] Limited Dissolve problems
authorCampbell Barton <ideasman42@gmail.com>
Fri, 4 May 2012 15:02:02 +0000 (15:02 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 4 May 2012 15:02:02 +0000 (15:02 +0000)
this is in fact 2 bugs.
- unselected edges between 2 faces that were joined didnt get removed.
- in face mode, edges and verts at the boundary of the selection would get incorrectly dissolved.

also quiet float/double promotion warning.

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

index 8e7723fefdddc405e2a654110360d16491ec3135..ae1773af05eb1cb8502e9f0214d57c3845590ffe 100644 (file)
@@ -478,8 +478,8 @@ void dummy_exec(BMesh *bm, BMOperator *op)
 
 /* Limited Dissolve */
 
-#define UNIT_TO_ANGLE DEG2RADF(90.0)
-#define ANGLE_TO_UNIT (1.0 / UNIT_TO_ANGLE)
+#define UNIT_TO_ANGLE DEG2RADF(90.0f)
+#define ANGLE_TO_UNIT (1.0f / UNIT_TO_ANGLE)
 
 /* multiply vertex edge angle by face angle
  * this means we are not left with sharp corners between _almost_ planer faces
@@ -523,8 +523,17 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
                                                         sizeof(DissolveElemWeight), __func__);
        int i, tot_found;
 
+       BMIter iter;
+       BMEdge *e_iter;
+       BMEdge **earray;
+
        /* --- first edges --- */
 
+       /* wire -> tag */
+       BM_ITER_MESH(e_iter, &iter, bm, BM_EDGES_OF_MESH) {
+               BM_elem_flag_set(e_iter, BM_ELEM_TAG, BM_edge_is_wire(e_iter));
+       }
+
        /* go through and split edge */
        for (i = 0, tot_found = 0; i < einput->len; i++) {
                BMEdge *e = ((BMEdge **)einput->data.p)[i];
@@ -562,18 +571,6 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
                                }
                        }
                }
-
-               /* remove all edges/verts left behind from dissolving */
-               for (i = 0; i < einput->len; i++) {
-                       BMEdge *e = (BMEdge *)weight_elems[i].ele;
-                       if (BM_edge_is_wire(e)) {
-                               BMVert *v1 = e->v1;
-                               BMVert *v2 = e->v2;
-                               BM_edge_kill(bm, e);
-                               if (v1->e == NULL) BM_vert_kill(bm, v1);
-                               if (v2->e == NULL) BM_vert_kill(bm, v2);
-                       }
-               }
        }
 
        /* --- second verts --- */
@@ -612,4 +609,25 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
        }
 
        MEM_freeN(weight_elems);
+
+       /* --- cleanup --- */
+       earray = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, __func__);
+       BM_ITER_MESH_INDEX(e_iter, &iter, bm, BM_EDGES_OF_MESH, i) {
+               earray[i] = e_iter;
+       }
+       /* remove all edges/verts left behind from dissolving */
+       for (i = bm->totedge - 1; i != -1; i--) {
+               e_iter = earray[i];
+
+               if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) {
+                       /* edge has become wire */
+                       BMVert *v1 = e_iter->v1;
+                       BMVert *v2 = e_iter->v2;
+                       BM_edge_kill(bm, e_iter);
+                       if (v1->e == NULL) BM_vert_kill(bm, v1);
+                       if (v2->e == NULL) BM_vert_kill(bm, v2);
+               }
+       }
+
+       MEM_freeN(earray);
 }
index 524ee02933945a3c905adb82c3e41621c4b04559..96cfd95b96abae3e7d6b2bfbf9ab6ad07753086a 100644 (file)
@@ -3205,11 +3205,45 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
 {
        Object *obedit = CTX_data_edit_object(C);
        BMEditMesh *em = BMEdit_FromObject(obedit);
+       BMesh *bm = em->bm;
        float angle_limit = RNA_float_get(op->ptr, "angle_limit");
 
+       char dissolve_flag;
+
+       if (em->selectmode == SCE_SELECT_FACE) {
+               /* flush selection to tags and untag edges/verts with partially selected faces */
+               BMIter iter;
+               BMIter liter;
+
+               BMElem *ele;
+               BMFace *f;
+               BMLoop *l;
+
+               BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+                       BM_elem_flag_set(ele, BM_ELEM_TAG, BM_elem_flag_test(ele, BM_ELEM_SELECT));
+               }
+               BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+                       BM_elem_flag_set(ele, BM_ELEM_TAG, BM_elem_flag_test(ele, BM_ELEM_SELECT));
+               }
+
+               BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+                       if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+                               BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+                                       BM_elem_flag_disable(l->v, BM_ELEM_TAG);
+                                       BM_elem_flag_disable(l->e, BM_ELEM_TAG);
+                               }
+                       }
+               }
+
+               dissolve_flag = BM_ELEM_TAG;
+       }
+       else {
+               dissolve_flag = BM_ELEM_SELECT;
+       }
+
        if (!EDBM_op_callf(em, op,
                           "dissolve_limit edges=%he verts=%hv angle_limit=%f",
-                          BM_ELEM_SELECT, BM_ELEM_SELECT, angle_limit))
+                          dissolve_flag, dissolve_flag, angle_limit))
        {
                return OPERATOR_CANCELLED;
        }