BMesh: add ability not to delete vertex when collapsing
authorCampbell Barton <ideasman42@gmail.com>
Fri, 27 Jun 2014 10:11:23 +0000 (20:11 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 27 Jun 2014 10:28:02 +0000 (20:28 +1000)
source/blender/bmesh/intern/bmesh_core.c
source/blender/bmesh/intern/bmesh_core.h
source/blender/bmesh/intern/bmesh_mods.c
source/blender/bmesh/intern/bmesh_mods.h
source/blender/bmesh/operators/bmo_dissolve.c
source/blender/bmesh/tools/bmesh_decimate_dissolve.c
source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
source/blender/python/bmesh/bmesh_py_utils.c

index 812c223dcc400bed8ef955d05d427adce7a3318b..c4dc990918587a8efe6983bc6dcd77a80efa3023 100644 (file)
@@ -1657,7 +1657,8 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
  * faces with just 2 edges. It is up to the caller to decide what to do with
  * these faces.
  */
-BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool check_edge_double)
+BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+                   const bool do_del, const bool check_edge_double)
 {
        BMEdge *e_old;
        BMVert *v_old, *tv;
@@ -1668,6 +1669,8 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool check_e
        bool edok;
 #endif
 
+       BLI_assert(BM_vert_in_edge(e_kill, v_kill));
+
        if (BM_vert_in_edge(e_kill, v_kill) == 0) {
                return NULL;
        }
@@ -1759,7 +1762,12 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool check_e
                        bm_kill_only_edge(bm, e_kill);
 
                        /* deallocate vertex */
-                       bm_kill_only_vert(bm, v_kill);
+                       if (do_del) {
+                               bm_kill_only_vert(bm, v_kill);
+                       }
+                       else {
+                               v_kill->e = NULL;
+                       }
 
 #ifndef NDEBUG
                        /* Validate disk cycle lengths of v_old, tv are unchanged */
index 654698da3c6fc259e32ee096bcdd8ae139a51330..4a2b4b7feca4d0191f1bbd44a4c6a7836540dd26 100644 (file)
@@ -83,7 +83,8 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f,
                    );
 
 BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
-BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool check_edge_splice);
+BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+                   const bool do_del, const bool check_edge_splice);
 BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
 BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep);
 BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep);
index 60de592f9647d205561c1157ecf337be893bede0..2d7a2cf93d6bf604d8f1e273c1108ab6b8c49aef 100644 (file)
@@ -78,7 +78,7 @@ bool BM_vert_dissolve(BMesh *bm, BMVert *v)
                }
                else if (!v->e->l) {
                        if (len == 2) {
-                               return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL);
+                               return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
                        }
                        else {
                                /* used to kill the vertex here, but it may be connected to faces.
@@ -92,7 +92,7 @@ bool BM_vert_dissolve(BMesh *bm, BMVert *v)
        }
        else if (len == 2 && BM_vert_face_count(v) == 1) {
                /* boundary vertex on a face */
-               return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL);
+               return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
        }
        else {
                return BM_disk_dissolve(bm, v);
@@ -144,7 +144,7 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v)
                if (UNLIKELY(!BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, true))) {
                        return false;
                }
-               else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, false, true))) {
+               else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, true, false, true))) {
                        return false;
                }
 #endif
@@ -152,7 +152,7 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v)
        }
        else if (keepedge == NULL && len == 2) {
                /* collapse the vertex */
-               e = BM_vert_collapse_faces(bm, v->e, v, 1.0, true, true);
+               e = BM_vert_collapse_faces(bm, v->e, v, 1.0, true, true, true);
 
                if (!e) {
                        return false;
@@ -196,7 +196,7 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v)
 
                /* collapse the vertex */
                /* note, the baseedge can be a boundary of manifold, use this as join_faces arg */
-               e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, !BM_edge_is_boundary(baseedge), true);
+               e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, true, !BM_edge_is_boundary(baseedge), true);
 
                if (!e) {
                        return false;
@@ -440,7 +440,7 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
  * \returns The New Edge
  */
 BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
-                               const bool join_faces, const bool kill_degenerate_faces)
+                               const bool do_del, const bool join_faces, const bool kill_degenerate_faces)
 {
        BMEdge *e_new = NULL;
        BMVert *tv = BM_edge_other_vert(e_kill, v_kill);
@@ -513,7 +513,7 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float
                /* single face or no faces */
                /* same as BM_vert_collapse_edge() however we already
                 * have vars to perform this operation so don't call. */
-               e_new = bmesh_jekv(bm, e_kill, v_kill, true);
+               e_new = bmesh_jekv(bm, e_kill, v_kill, do_del, true);
                /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */
 
                if (e_new && kill_degenerate_faces) {
@@ -553,7 +553,7 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float
  * \return The New Edge
  */
 BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
-                              const bool kill_degenerate_faces)
+                              const bool do_del, const bool kill_degenerate_faces)
 {
        /* nice example implementation but we want loops to have their customdata
         * accounted for */
@@ -571,9 +571,7 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
                        BMVert *tv2 = BM_edge_other_vert(e2, v_kill);
                        if (tv2) {
                                /* only action, other calls here only get the edge to return */
-                               e_new = bmesh_jekv(bm, e_kill, v_kill);
-
-                               /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */
+                               e_new = bmesh_jekv(bm, e_kill, v_kill, do_del);
                        }
                }
        }
@@ -582,7 +580,7 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
 #else
        /* with these args faces are never joined, same as above
         * but account for loop customdata */
-       return BM_vert_collapse_faces(bm, e_kill, v_kill, 1.0f, false, kill_degenerate_faces);
+       return BM_vert_collapse_faces(bm, e_kill, v_kill, 1.0f, do_del, false, kill_degenerate_faces);
 #endif
 }
 
index f3ed99230d7861d52ceadd4e0996753927fd0b78..7c81e6b750e09eab6286df38a638f76b02bab82e 100644 (file)
@@ -46,9 +46,9 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
                         BMLoop **r_l, BMEdge *example);
 
 BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
-                               const bool join_faces, const bool kill_degenerate_faces);
+                               const bool do_del, const bool join_faces, const bool kill_degenerate_faces);
 BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
-                              const bool kill_degenerate_faces);
+                              const bool do_del, const bool kill_degenerate_faces);
 
 
 BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent);
index 36a936c6622de2dd9d041021a7f94c863b94ce11..93296c51f8ecb73b9564024ae3edce0ff7ba23a8 100644 (file)
@@ -216,7 +216,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
                BM_ITER_MESH_MUTABLE (v, v_next, &viter, bm, BM_VERTS_OF_MESH) {
                        if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
                                if (BM_vert_edge_count(v) == 2) {
-                                       BM_vert_collapse_edge(bm, v->e, v, true);
+                                       BM_vert_collapse_edge(bm, v->e, v, true, true);
                                }
                        }
                }
@@ -328,7 +328,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
                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_edge_count(v) == 2) {
-                                       BM_vert_collapse_edge(bm, v->e, v, true);
+                                       BM_vert_collapse_edge(bm, v->e, v, true, true);
                                }
                        }
                }
@@ -410,7 +410,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
        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_edge_count(v) == 2) {
-                               BM_vert_collapse_edge(bm, v->e, v, true);
+                               BM_vert_collapse_edge(bm, v->e, v, true, true);
                        }
                }
        }
index 96af37f4400b2c3439cda6f9b0a56c1fea41d7d7..99cb68c025a1d734829dc20b17fa86afee0c6330 100644 (file)
@@ -237,7 +237,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool
                        if (LIKELY(v != NULL) &&
                            BM_vert_edge_count(v) == 2)
                        {
-                               BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */
+                               BM_vert_collapse_edge(bm, v->e, v, true, true);  /* join edges */
                        }
                }
        }
@@ -275,7 +275,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool
                        i = BM_elem_index_get(v);
 
                        if (BM_vert_edge_count(v) == 2) {
-                               e_new = BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */
+                               e_new = BM_vert_collapse_edge(bm, v->e, v, true, true);  /* join edges */
 
                                if (e_new) {
 
index ffc680817a7c47454c4fe8c6e8492a82c247317b..db60b3e15e1504d196e2716bba8ce20c8fd6d1d1 100644 (file)
@@ -119,7 +119,7 @@ static bool bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
        if (tot_edge == 2) {
                /* check for 2 wire verts only */
                if (tot_edge_wire == 2) {
-                       return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL);
+                       return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
                }
        }
        else if (tot_edge == 4) {
index 236d6badd55a02a7e05859f9cfc6e825564583dc..4f1ca568bb0866be8646751bf9932c320b0ca05d 100644 (file)
@@ -90,7 +90,7 @@ static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObjec
 
        bm = py_edge->bm;
 
-       e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, true);
+       e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, true, true);
 
        if (e_new) {
                return BPy_BMEdge_CreatePyObject(bm, e_new);
@@ -156,7 +156,7 @@ static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObje
 
        bm = py_edge->bm;
 
-       e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), do_join_faces, true);
+       e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), true, do_join_faces, true);
 
        if (e_new) {
                return BPy_BMEdge_CreatePyObject(bm, e_new);