Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/include/ED_mesh.h1
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c99
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c5
-rw-r--r--source/blender/editors/transform/transform_convert_mesh_uv.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c2
7 files changed, 107 insertions, 6 deletions
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index b6a652bd3ab..26743a2bd08 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -139,6 +139,7 @@ struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm,
const struct Scene *scene,
bool uv_selected,
bool use_winding,
+ bool use_seams,
bool do_islands);
void BM_uv_element_map_free(struct UvElementMap *element_map);
struct UvElement *BM_uv_element_get(const struct UvElementMap *map,
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index a6a6b095c31..cca2aa11ac3 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -851,10 +851,99 @@ static void bm_uv_build_islands(UvElementMap *element_map,
MEM_SAFE_FREE(map);
}
+/* return true if `loop` has UV co-ordinates which match `luv_a` and `luv_b` */
+static bool loop_uv_match(BMLoop *loop, MLoopUV *luv_a, MLoopUV *luv_b, int cd_loop_uv_offset)
+{
+ MLoopUV *luv_c = BM_ELEM_CD_GET_VOID_P(loop, cd_loop_uv_offset);
+ MLoopUV *luv_d = BM_ELEM_CD_GET_VOID_P(loop->next, cd_loop_uv_offset);
+ return compare_v2v2(luv_a->uv, luv_c->uv, STD_UV_CONNECT_LIMIT) &&
+ compare_v2v2(luv_b->uv, luv_d->uv, STD_UV_CONNECT_LIMIT);
+}
+
+/* Given `anchor` and `edge`, return true if there are edges that fan between them that are
+ * seam-free. */
+static bool seam_connected_recursive(BMVert *anchor,
+ BMEdge *edge,
+ MLoopUV *luv_anchor,
+ MLoopUV *luv_fan,
+ BMLoop *needle,
+ GSet *visited,
+ int cd_loop_uv_offset)
+{
+ BLI_assert(edge->v1 == anchor || edge->v2 == anchor);
+ BLI_assert(needle->v == anchor || needle->next->v == anchor);
+
+ if (BM_elem_flag_test(edge, BM_ELEM_SEAM)) {
+ return false; /* Edge is a seam, don't traverse. */
+ }
+
+ if (!BLI_gset_add(visited, edge)) {
+ return false; /* Already visited. */
+ }
+
+ BMLoop *loop;
+ BMIter liter;
+ BM_ITER_ELEM (loop, &liter, edge, BM_LOOPS_OF_EDGE) {
+ if (loop->v == anchor) {
+ if (!loop_uv_match(loop, luv_anchor, luv_fan, cd_loop_uv_offset)) {
+ continue; /* `loop` is disjoint in UV space. */
+ }
+
+ if (loop->prev == needle) {
+ return true; /* Success. */
+ }
+
+ MLoopUV *luv_far = BM_ELEM_CD_GET_VOID_P(loop->prev, cd_loop_uv_offset);
+ if (seam_connected_recursive(
+ anchor, loop->prev->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) {
+ return true;
+ }
+ }
+ else {
+ BLI_assert(loop->next->v == anchor);
+ if (!loop_uv_match(loop, luv_fan, luv_anchor, cd_loop_uv_offset)) {
+ continue; /* `loop` is disjoint in UV space. */
+ }
+
+ if (loop->next == needle) {
+ return true; /* Success. */
+ }
+
+ MLoopUV *luv_far = BM_ELEM_CD_GET_VOID_P(loop->next->next, cd_loop_uv_offset);
+ if (seam_connected_recursive(
+ anchor, loop->next->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/* Given `loop_a` and `loop_b` originate from the same vertex and share a UV,
+ * return true if there are edges that fan between them that are seam-free.
+ * return false otherwise.
+ */
+static bool seam_connected(BMLoop *loop_a, BMLoop *loop_b, GSet *visited, int cd_loop_uv_offset)
+{
+ BLI_assert(loop_a && loop_b);
+ BLI_assert(loop_a != loop_b);
+ BLI_assert(loop_a->v == loop_b->v);
+
+ BLI_gset_clear(visited, NULL);
+
+ MLoopUV *luv_anchor = BM_ELEM_CD_GET_VOID_P(loop_a, cd_loop_uv_offset);
+ MLoopUV *luv_fan = BM_ELEM_CD_GET_VOID_P(loop_a->next, cd_loop_uv_offset);
+ const bool result = seam_connected_recursive(
+ loop_a->v, loop_a->e, luv_anchor, luv_fan, loop_b, visited, cd_loop_uv_offset);
+ return result;
+}
+
UvElementMap *BM_uv_element_map_create(BMesh *bm,
const Scene *scene,
const bool uv_selected,
const bool use_winding,
+ const bool use_seams,
const bool do_islands)
{
/* In uv sync selection, all UVs are visible. */
@@ -956,6 +1045,8 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
}
BLI_buffer_free(&tf_uv_buf);
+ GSet *seam_visited_gset = use_seams ? BLI_gset_ptr_new(__func__) : NULL;
+
/* For each BMVert, sort associated linked list into unique uvs. */
int ev_index;
BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, ev_index) {
@@ -1001,6 +1092,10 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
winding[BM_elem_index_get(v->l->f)];
}
+ if (connected && use_seams) {
+ connected = seam_connected(iterv->l, v->l, seam_visited_gset, cd_loop_uv_offset);
+ }
+
if (connected) {
if (lastv) {
lastv->next = next;
@@ -1026,6 +1121,10 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
element_map->vertex[ev_index] = newvlist;
}
+ if (seam_visited_gset) {
+ BLI_gset_free(seam_visited_gset, NULL);
+ seam_visited_gset = NULL;
+ }
MEM_SAFE_FREE(winding);
/* at this point, every UvElement in vert points to a UvElement sharing the same vertex.
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 8b9776cf94d..4739fa52674 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -686,9 +686,10 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
/* Winding was added to island detection in 5197aa04c6bd
* However the sculpt tools can flip faces, potentially creating orphaned islands.
* See T100132 */
- bool use_winding = false;
+ const bool use_winding = false;
+ const bool use_seams = true;
data->elementMap = BM_uv_element_map_create(
- bm, scene, false, use_winding, do_island_optimization);
+ bm, scene, false, use_winding, use_seams, do_island_optimization);
if (!data->elementMap) {
uv_sculpt_stroke_exit(C, op);
diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c
index f3bef2c283b..27f12137e3a 100644
--- a/source/blender/editors/transform/transform_convert_mesh_uv.c
+++ b/source/blender/editors/transform/transform_convert_mesh_uv.c
@@ -265,7 +265,7 @@ static void createTransUVs(bContext *C, TransInfo *t)
/* count */
if (is_island_center) {
/* create element map with island information */
- elementmap = BM_uv_element_map_create(em->bm, scene, true, false, true);
+ elementmap = BM_uv_element_map_create(em->bm, scene, true, false, true, true);
if (elementmap == NULL) {
continue;
}
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index c0dd7623ade..4cc2c6450df 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -535,7 +535,7 @@ static bool uvedit_uv_straighten(Scene *scene, BMesh *bm, eUVWeldAlign tool)
return false;
}
- UvElementMap *element_map = BM_uv_element_map_create(bm, scene, true, false, true);
+ UvElementMap *element_map = BM_uv_element_map_create(bm, scene, true, false, true, true);
if (element_map == NULL) {
return false;
}
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index cecf0ff7914..43c8620df1d 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -5384,7 +5384,7 @@ static void uv_isolate_selected_islands(const Scene *scene,
BLI_assert((scene->toolsettings->uv_flag & UV_SYNC_SELECTION) == 0);
BMFace *efa;
BMIter iter, liter;
- UvElementMap *elementmap = BM_uv_element_map_create(em->bm, scene, false, false, true);
+ UvElementMap *elementmap = BM_uv_element_map_create(em->bm, scene, false, false, true, true);
if (elementmap == NULL) {
return;
}
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index e89f99fc412..e19cc67bd16 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -1855,7 +1855,7 @@ static StitchState *stitch_init(bContext *C,
* for stitch this isn't useful behavior, see T86924. */
const int selectmode_orig = scene->toolsettings->selectmode;
scene->toolsettings->selectmode = SCE_SELECT_VERTEX;
- state->element_map = BM_uv_element_map_create(state->em->bm, scene, false, true, true);
+ state->element_map = BM_uv_element_map_create(state->em->bm, scene, false, true, true, true);
scene->toolsettings->selectmode = selectmode_orig;
if (!state->element_map) {