BMesh: add UV delimit for select-linked, dissolve
This commit is contained in:
parent
05c4c2409e
commit
3aa4a0e787
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue