diff options
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operator_api.h | 1 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.c | 49 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.h | 4 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate.h | 2 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate_dissolve.c | 54 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 31 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_mesh.c | 1 |
7 files changed, 133 insertions, 9 deletions
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 917b9a9dcf9..3f7fb7b257d 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -303,6 +303,7 @@ typedef enum { BMO_DELIM_MATERIAL = 1 << 1, BMO_DELIM_SEAM = 1 << 2, BMO_DELIM_SHARP = 1 << 3, + BMO_DELIM_UV = 1 << 4, } BMO_Delimit; void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 9bc45025456..4fbba5af733 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -38,6 +38,8 @@ #include "BLI_linklist.h" #include "BLI_stackdefines.h" +#include "BKE_customdata.h" + #include "bmesh.h" #include "intern/bmesh_private.h" @@ -1039,6 +1041,53 @@ bool BM_edge_is_convex(const BMEdge *e) return true; } +/** + * Returms true when loop customdata is contiguous. + */ +bool BM_edge_is_contiguous_loop_cd( + const BMEdge *e, + const int cd_loop_type, const int cd_loop_offset) +{ + BLI_assert(cd_loop_offset != -1); + + if (e->l && e->l->radial_next != e->l) { + const BMLoop *l_base_v1 = e->l; + const BMLoop *l_base_v2 = e->l->next; + const void *l_base_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_base_v1, cd_loop_offset); + const void *l_base_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_base_v2, cd_loop_offset); + const BMLoop *l_iter = e->l->radial_next; + do { + const BMLoop *l_iter_v1; + const BMLoop *l_iter_v2; + const void *l_iter_cd_v1; + const void *l_iter_cd_v2; + + if (l_iter->v == l_base_v1->v) { + l_iter_v1 = l_iter; + l_iter_v2 = l_iter->next; + } + else { + l_iter_v1 = l_iter->next; + l_iter_v2 = l_iter; + } + BLI_assert((l_iter_v1->v == l_base_v1->v) && + (l_iter_v2->v == l_base_v2->v)); + + l_iter_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_iter_v1, cd_loop_offset); + l_iter_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_iter_v2, cd_loop_offset); + + + if ((CustomData_data_equals(cd_loop_type, l_base_cd_v1, l_iter_cd_v1) == 0) || + (CustomData_data_equals(cd_loop_type, l_base_cd_v2, l_iter_cd_v2) == 0)) + { + return false; + } + + } while ((l_iter = l_iter->radial_next) != e->l); + } + return true; +} + bool BM_vert_is_boundary(const BMVert *v) { if (v->e) { diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index f0a348db16a..d66bd00c2fc 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -91,6 +91,10 @@ bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNUL 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(); +bool BM_edge_is_contiguous_loop_cd( + const BMEdge *e, + const int cd_loop_type, const int cd_loop_offset) + 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); diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index 1efa829c60d..17b55be52dc 100644 --- a/source/blender/bmesh/tools/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -34,7 +34,7 @@ void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations); void BM_mesh_decimate_dissolve_ex( BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit, + BMO_Delimit delimit, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len, const short oflag_out); diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 8a14291d3bc..986e4643201 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -32,6 +32,8 @@ #include "BLI_math.h" #include "BLI_heap.h" +#include "BKE_customdata.h" + #include "bmesh.h" #include "bmesh_decimate.h" /* own include */ @@ -59,7 +61,32 @@ static float bm_vert_edge_face_angle(BMVert *v) #undef ANGLE_TO_UNIT } -static float bm_edge_calc_dissolve_error(const BMEdge *e, const BMO_Delimit delimit) +struct DelimitData { + int cd_loop_type; + int cd_loop_size; + int cd_loop_offset; + int cd_loop_offset_end; +}; + +static bool bm_edge_is_contiguous_loop_cd_all( + const BMEdge *e, const struct DelimitData *delimit_data) +{ + int cd_loop_offset; + for (cd_loop_offset = delimit_data->cd_loop_offset; + cd_loop_offset < delimit_data->cd_loop_offset_end; + cd_loop_offset += delimit_data->cd_loop_size) + { + if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, cd_loop_offset) == false) { + return false; + } + } + + return true; +} + +static float bm_edge_calc_dissolve_error( + const BMEdge *e, const BMO_Delimit delimit, + const struct DelimitData *delimit_data) { const bool is_contig = BM_edge_is_contiguous(e); float angle; @@ -92,6 +119,11 @@ static float bm_edge_calc_dissolve_error(const BMEdge *e, const BMO_Delimit deli goto fail; } + if ((delimit & BMO_DELIM_UV) && + (bm_edge_is_contiguous_loop_cd_all(e, delimit_data) == 0)) { + goto fail; + } + angle = BM_edge_calc_face_angle(e); if (is_contig == false) { angle = (float)M_PI - angle; @@ -106,16 +138,30 @@ fail: void BM_mesh_decimate_dissolve_ex( BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit, + BMO_Delimit delimit, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len, const short oflag_out) { + struct DelimitData delimit_data = {0}; const int eheap_table_len = do_dissolve_boundaries ? einput_len : max_ii(einput_len, vinput_len); void *_heap_table = MEM_mallocN(sizeof(HeapNode *) * eheap_table_len, __func__); int i; + if (delimit & BMO_DELIM_UV) { + const int layer_len = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV); + if (layer_len == 0) { + delimit &= ~BMO_DELIM_UV; + } + else { + delimit_data.cd_loop_type = CD_MLOOPUV; + delimit_data.cd_loop_size = CustomData_sizeof(delimit_data.cd_loop_type); + delimit_data.cd_loop_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, 0); + delimit_data.cd_loop_offset_end = delimit_data.cd_loop_size * layer_len; + } + } + /* --- first edges --- */ if (1) { BMEdge **earray; @@ -140,7 +186,7 @@ void BM_mesh_decimate_dissolve_ex( /* build heap */ for (i = 0; i < einput_len; i++) { BMEdge *e = einput_arr[i]; - const float cost = bm_edge_calc_dissolve_error(e, delimit); + const float cost = bm_edge_calc_dissolve_error(e, delimit, &delimit_data); eheap_table[i] = BLI_heap_insert(eheap, cost, e); BM_elem_index_set(e, i); /* set dirty */ } @@ -176,7 +222,7 @@ void BM_mesh_decimate_dissolve_ex( do { const int j = BM_elem_index_get(l_iter->e); if (j != -1 && eheap_table[j]) { - const float cost = bm_edge_calc_dissolve_error(l_iter->e, delimit); + const float cost = bm_edge_calc_dissolve_error(l_iter->e, delimit, &delimit_data); BLI_heap_remove(eheap, eheap_table[j]); eheap_table[j] = BLI_heap_insert(eheap, cost, l_iter->e); } diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index bf32008ee45..4abd0df7ce5 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2336,6 +2336,11 @@ bool EDBM_select_interior_faces(BMEditMesh *em) /************************ Select Linked Operator *************************/ +struct DelimitData { + int cd_loop_type; + int cd_loop_offset; +}; + static void select_linked_delimit_default(bContext *C, wmOperator *op) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "delimit"); @@ -2353,7 +2358,9 @@ static void select_linked_delimit_default(bContext *C, wmOperator *op) } -static bool select_linked_delimit_test(BMEdge *e, int delimit) +static bool select_linked_delimit_test( + BMEdge *e, int delimit, + const struct DelimitData *delimit_data) { BLI_assert(delimit); @@ -2387,22 +2394,38 @@ static bool select_linked_delimit_test(BMEdge *e, int delimit) } } + if (delimit & BMO_DELIM_UV) { + if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, delimit_data->cd_loop_offset) == 0) { + return true; + } + } + return false; } -static void select_linked_delimit_begin(BMEditMesh *em, const int delimit) +static void select_linked_delimit_begin(BMEditMesh *em, int delimit) { + struct DelimitData delimit_data = {0}; + BMesh *bm = em->bm; BMIter iter; BMEdge *e; + if (delimit & BMO_DELIM_UV) { + delimit_data.cd_loop_type = CD_MLOOPUV; + delimit_data.cd_loop_offset = CustomData_get_offset(&bm->ldata, delimit_data.cd_loop_type); + if (delimit_data.cd_loop_offset == -1) { + delimit &= ~BMO_DELIM_UV; + } + } + /* grr, shouldn't need to alloc BMO flags here */ BM_mesh_elem_toolflags_ensure(bm); if (em->selectmode == SCE_SELECT_FACE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { const bool is_walk_ok = ( - (select_linked_delimit_test(e, delimit) == false)); + (select_linked_delimit_test(e, delimit, &delimit_data) == false)); BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); } @@ -2412,7 +2435,7 @@ static void select_linked_delimit_begin(BMEditMesh *em, const int delimit) BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { const bool is_walk_ok = ( BM_elem_flag_test(e, BM_ELEM_SELECT) || - (select_linked_delimit_test(e, delimit) == false)); + (select_linked_delimit_test(e, delimit, &delimit_data) == false)); BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); } diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index b5eb1a265b5..9b25fbbaca3 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -56,6 +56,7 @@ EnumPropertyItem mesh_delimit_mode_items[] = { {BMO_DELIM_MATERIAL, "MATERIAL", 0, "Material", "Delimit by face material"}, {BMO_DELIM_SEAM, "SEAM", 0, "Seam", "Delimit by edge seams"}, {BMO_DELIM_SHARP, "SHARP", 0, "Sharp", "Delimit by sharp edges"}, + {BMO_DELIM_UV, "UV", 0, "UVs", "Delimit by UV coordinates"}, {0, NULL, 0, NULL, NULL}, }; |