diff options
-rw-r--r-- | source/blender/bmesh/bmesh_class.h | 3 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_convert_mesh.c | 44 |
2 files changed, 35 insertions, 12 deletions
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 65f3d8bbad3..7cbad1ed069 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -373,7 +373,8 @@ enum { BM_ELEM_DRAW = (1 << 5), /* edge display */ /* spare tag, assumed dirty, use define in each function to name based on use */ - // _BM_ELEM_TAG_ALT = (1 << 6), // UNUSED + BM_ELEM_TAG_ALT = (1 << 6), + /** * For low level internal API tagging, * since tools may want to tag verts and not have functions clobber them. diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 5e2eca13f90..7270763c4e4 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -306,6 +306,24 @@ static bool bmesh_test_dist_add(BMVert *v0, return false; } +static bool bmesh_test_loose_edge(BMEdge *edge) +{ + /* Actual loose edge. */ + if (edge->l == NULL) { + return true; + } + + /* Loose edge due to hidden adjacent faces. */ + BMIter iter; + BMFace *face; + BM_ITER_ELEM (face, &iter, edge, BM_FACES_OF_EDGE) { + if (BM_elem_flag_test(face, BM_ELEM_HIDDEN) == 0) { + return false; + } + } + return true; +} + /** * \param mtx: Measure distance in this space. * \param dists: Store the closest connected distance to selected vertices. @@ -319,6 +337,9 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, BLI_LINKSTACK_DECLARE(queue, BMEdge *); /* any BM_ELEM_TAG'd edge is in 'queue_next', so we don't add in twice */ + const int tag_queued = BM_ELEM_TAG; + const int tag_loose = BM_ELEM_TAG_ALT; + BLI_LINKSTACK_DECLARE(queue_next, BMEdge *); BLI_LINKSTACK_INIT(queue); @@ -366,7 +387,8 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, if (dists[i1] != FLT_MAX || dists[i2] != FLT_MAX) { BLI_LINKSTACK_PUSH(queue, e); } - BM_elem_flag_disable(e, BM_ELEM_TAG); + BM_elem_flag_disable(e, tag_queued); + BM_elem_flag_set(e, tag_loose, bmesh_test_loose_edge(e)); } } @@ -379,7 +401,7 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, int i1 = BM_elem_index_get(v1); int i2 = BM_elem_index_get(v2); - if (e->l == NULL || (dists[i1] == FLT_MAX || dists[i2] == FLT_MAX)) { + if (BM_elem_flag_test(e, tag_loose) || (dists[i1] == FLT_MAX || dists[i2] == FLT_MAX)) { /* Propagate along edge from vertex with smallest to largest distance. */ if (dists[i1] > dists[i2]) { SWAP(int, i1, i2); @@ -392,16 +414,16 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, BMEdge *e_other; BMIter eiter; BM_ITER_ELEM (e_other, &eiter, v2, BM_EDGES_OF_VERT) { - if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 && - (e->l == NULL || e_other->l == NULL)) { - BM_elem_flag_enable(e_other, BM_ELEM_TAG); + if (e_other != e && BM_elem_flag_test(e_other, tag_queued) == 0 && + (BM_elem_flag_test(e, tag_loose) || BM_elem_flag_test(e_other, tag_loose))) { + BM_elem_flag_enable(e_other, tag_queued); BLI_LINKSTACK_PUSH(queue_next, e_other); } } } } - if (e->l != NULL) { + if (!BM_elem_flag_test(e, tag_loose)) { /* Propagate across edge to vertices in adjacent faces. */ BMLoop *l; BMIter liter; @@ -417,10 +439,10 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, BMEdge *e_other; BMIter eiter; BM_ITER_ELEM (e_other, &eiter, v_other, BM_EDGES_OF_VERT) { - if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 && - (e_other->l == NULL || + if (e_other != e && BM_elem_flag_test(e_other, tag_queued) == 0 && + (BM_elem_flag_test(e_other, tag_loose) || dists[BM_elem_index_get(BM_edge_other_vert(e_other, v_other))] != FLT_MAX)) { - BM_elem_flag_enable(e_other, BM_ELEM_TAG); + BM_elem_flag_enable(e_other, tag_queued); BLI_LINKSTACK_PUSH(queue_next, e_other); } } @@ -434,13 +456,13 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, for (LinkNode *lnk = queue_next; lnk; lnk = lnk->next) { BMEdge *e_link = lnk->link; - BM_elem_flag_disable(e_link, BM_ELEM_TAG); + BM_elem_flag_disable(e_link, tag_queued); } BLI_LINKSTACK_SWAP(queue, queue_next); /* None should be tagged now since 'queue_next' is empty. */ - BLI_assert(BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, BM_ELEM_TAG, true) == 0); + BLI_assert(BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, tag_queued, true) == 0); } while (BLI_LINKSTACK_SIZE(queue)); BLI_LINKSTACK_FREE(queue); |