diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-11-19 10:12:20 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-11-19 14:52:17 +0300 |
commit | 9c044b4773a9e4b610b515cd369197a7c3e38f62 (patch) | |
tree | f8cff236fc8a846e6bb687e9b0588e94e65392f0 /source/blender/bmesh | |
parent | 93fb07fbd55afcaac15e96b93892e65341bb92c4 (diff) |
BMesh: new API call to collapse an edge
Existing collapse functions were strict regarding the number of verts sharing an edge.
BM_edge_collapse allows any edge to be passed in without first having to manipulate geometry.
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.c | 98 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.h | 4 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mods.c | 10 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mods.h | 3 |
4 files changed, 115 insertions, 0 deletions
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 618407ba5b6..a018c11999c 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1856,6 +1856,104 @@ BMEdge *bmesh_jekv( } /** + * \brief Join Vert Kill Edge (JVKE) + * + * Collapse an edge, merging surrounding data. + * + * Unlike #BM_vert_collapse_edge & #bmesh_jekv which only handle 2 valence verts, + * this can handle any number of connected edges/faces. + * + * <pre> + * Before: -> After: + * +-+-+-+ +-+-+-+ + * | | | | | \ / | + * +-+-+-+ +--+--+ + * | | | | | / \ | + * +-+-+-+ +-+-+-+ + * </pre> + */ +BMVert *bmesh_jvke( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool check_edge_double, + const bool kill_degenerate_faces) +{ + BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *); + BMVert *v_target = BM_edge_other_vert(e_kill, v_kill); + + BLI_assert(BM_vert_in_edge(e_kill, v_kill)); + + if (e_kill->l) { + BMLoop *l_kill, *l_first, *l_kill_next; + l_kill = l_first = e_kill->l; + do { + /* relink loops and fix vertex pointer */ + if (l_kill->next->v == v_kill) { + l_kill->next->v = v_target; + } + + l_kill->next->prev = l_kill->prev; + l_kill->prev->next = l_kill->next; + if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) { + BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next; + } + + /* fix len attribute of face */ + l_kill->f->len--; + if (kill_degenerate_faces) { + if (l_kill->f->len < 3) { + BLI_SMALLSTACK_PUSH(faces_degenerate, l_kill->f); + } + } + l_kill_next = l_kill->radial_next; + + bm_kill_only_loop(bm, l_kill); + + } while ((l_kill = l_kill_next) != l_first); + + e_kill->l = NULL; + } + + BM_edge_kill(bm, e_kill); + BM_CHECK_ELEMENT(v_kill); + BM_CHECK_ELEMENT(v_target); + + if (v_target->e && v_kill->e) { + /* inline BM_vert_splice(bm, v_target, v_kill); */ + BMEdge *e; + while ((e = v_kill->e)) { + BMEdge *e_target; + + if (check_edge_double) { + e_target = BM_edge_exists(v_target, BM_edge_other_vert(e, v_kill)); + } + + bmesh_edge_vert_swap(e, v_target, v_kill); + BLI_assert(e->v1 != e->v2); + + if (check_edge_double) { + if (e_target) { + BM_edge_splice(bm, e_target, e); + } + } + } + } + + if (kill_degenerate_faces) { + BMFace *f_kill; + while ((f_kill = BLI_SMALLSTACK_POP(faces_degenerate))) { + BM_face_kill(bm, f_kill); + } + } + + if (do_del) { + BLI_assert(v_kill->e == NULL); + bm_kill_only_vert(bm, v_kill); + } + + return v_target; +} + +/** * \brief Join Face Kill Edge (JFKE) * * Takes two faces joined by a single 2-manifold edge and fuses them together. diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index d6d5a4d7296..a18d96824b7 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -100,6 +100,10 @@ BMEdge *bmesh_jekv( BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool check_edge_splice, const bool kill_degenerate_faces); +BMVert *bmesh_jvke( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool check_edge_double, + const bool kill_degenerate_faces); 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); diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 66be8e0e757..cde231b4494 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -1117,6 +1117,16 @@ BMEdge *BM_vert_collapse_edge( #undef DO_V_INTERP /** + * Collapse and edge into a single vertex. + */ +BMVert *BM_edge_collapse( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool kill_degenerate_faces) +{ + return bmesh_jvke(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); +} + +/** * \brief Edge Split * * <pre> diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h index 1b826b1e0b2..142568e6e1a 100644 --- a/source/blender/bmesh/intern/bmesh_mods.h +++ b/source/blender/bmesh/intern/bmesh_mods.h @@ -59,6 +59,9 @@ BMEdge *BM_vert_collapse_edge( BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces); +BMVert *BM_edge_collapse( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool kill_degenerate_faces); BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent); |