diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-05-05 00:11:31 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-05-05 00:22:35 +0300 |
commit | 22bbd1c51219aafb40adb3e9a206f660a621fd70 (patch) | |
tree | 379fd0b62591041ada3e53bb8f287b3c4aba31e6 /source/blender/bmesh | |
parent | e59bd19fa75e65b794e4c67bdcfb8d13867900f9 (diff) |
BMesh: improve rip tool /w mon-manifold verts
Can now rip from multiple fans (mixed single faces or larger regions)
Also add BM_vert_is_manifold_region which only checks if a vert has disconnected fans.
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.c | 99 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.h | 3 |
2 files changed, 102 insertions, 0 deletions
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 031fc68e66f..63e36178e0f 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -917,6 +917,105 @@ bool BM_vert_is_manifold(const BMVert *v) return (loop_num == loop_num_region); } +#define LOOP_VISIT _FLAG_WALK +#define EDGE_VISIT _FLAG_WALK + +static int bm_loop_region_count__recursive(BMEdge *e, BMVert *v) +{ + BMLoop *l_iter, *l_first; + int count = 0; + + BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); + BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT); + + l_iter = l_first = e->l; + do { + if (l_iter->v == v) { + BMEdge *e_other = l_iter->prev->e; + if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { + BM_ELEM_API_FLAG_ENABLE(l_iter, LOOP_VISIT); + count += 1; + } + if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) { + count += bm_loop_region_count__recursive(e_other, v); + } + } + else if (l_iter->next->v == v) { + BMEdge *e_other = l_iter->next->e; + if (!BM_ELEM_API_FLAG_TEST(l_iter->next, LOOP_VISIT)) { + BM_ELEM_API_FLAG_ENABLE(l_iter->next, LOOP_VISIT); + count += 1; + } + if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) { + count += bm_loop_region_count__recursive(e_other, v); + } + } + else { + BLI_assert(0); + } + } while ((l_iter = l_iter->radial_next) != l_first); + + return count; +} + +static int bm_loop_region_count__clear(BMLoop *l) +{ + int count = 0; + BMEdge *e_iter, *e_first; + + /* clear flags */ + e_iter = e_first = l->e; + do { + BM_ELEM_API_FLAG_DISABLE(e_iter, EDGE_VISIT); + if (e_iter->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e_iter->l; + do { + if (l_iter->v == l->v) { + BM_ELEM_API_FLAG_DISABLE(l_iter, LOOP_VISIT); + count += 1; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first); + + return count; +} + +/** + * The number of loops connected to this loop (not including disconnected regions). + */ +int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) +{ + const int count = bm_loop_region_count__recursive(l->e, l->v); + const int count_total = bm_loop_region_count__clear(l); + if (r_loop_total) { + *r_loop_total = count_total; + } + return count; +} + +#undef LOOP_VISIT +#undef EDGE_VISIT + +int BM_loop_region_loops_count(BMLoop *l) +{ + return BM_loop_region_loops_count_ex(l, NULL); +} + +/** + * A version of #BM_vert_is_manifold + * which only checks if we're connected to multiple isolated regions. + */ +bool BM_vert_is_manifold_region(const BMVert *v) +{ + BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v); + int count, count_total; + + count = BM_loop_region_loops_count_ex(l_first, &count_total); + return (count == count_total); +} + /** * Check if the edge is convex or concave * (depends on face winding) diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index e4f7c78bdc1..f0a348db16a 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -85,12 +85,15 @@ bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_is_manifold_region(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); |