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
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_dissolve.c124
1 files changed, 87 insertions, 37 deletions
diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
index 010245fa93d..d4bce75d08b 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
@@ -35,10 +35,21 @@
#define COST_INVALID FLT_MAX
+struct DelimitData;
+
+static bool bm_edge_is_delimiter(const BMEdge *e,
+ const BMO_Delimit delimit,
+ const struct DelimitData *delimit_data);
+static bool bm_vert_is_delimiter(const BMVert *v,
+ const BMO_Delimit delimit,
+ const struct DelimitData *delimit_data);
+
/* multiply vertex edge angle by face angle
* this means we are not left with sharp corners between _almost_ planer faces
* convert angles [0-PI/2] -> [0-1], multiply together, then convert back to radians. */
-static float bm_vert_edge_face_angle(BMVert *v)
+static float bm_vert_edge_face_angle(BMVert *v,
+ const BMO_Delimit delimit,
+ const struct DelimitData *delimit_data)
{
#define UNIT_TO_ANGLE DEG2RADF(90.0f)
#define ANGLE_TO_UNIT (1.0f / UNIT_TO_ANGLE)
@@ -46,12 +57,18 @@ static float bm_vert_edge_face_angle(BMVert *v)
const float angle = BM_vert_calc_edge_angle(v);
/* note: could be either edge, it doesn't matter */
if (v->e && BM_edge_is_manifold(v->e)) {
- return ((angle * ANGLE_TO_UNIT) * (BM_edge_calc_face_angle(v->e) * ANGLE_TO_UNIT)) *
- UNIT_TO_ANGLE;
- }
- else {
- return angle;
+ /* Checking delimited is important here,
+ * otherwise the boundary between two materials for e.g.
+ * will collapse if the faces on either side of the edge have a small angle.
+ *
+ * This way, delimiting edges are treated like boundary edges,
+ * the detail between two delimiting regions won't over-collapse. */
+ if (!bm_vert_is_delimiter(v, delimit, delimit_data)) {
+ return ((angle * ANGLE_TO_UNIT) * (BM_edge_calc_face_angle(v->e) * ANGLE_TO_UNIT)) *
+ UNIT_TO_ANGLE;
+ }
}
+ return angle;
#undef UNIT_TO_ANGLE
#undef ANGLE_TO_UNIT
@@ -79,44 +96,76 @@ static bool bm_edge_is_contiguous_loop_cd_all(const BMEdge *e,
return true;
}
-static float bm_edge_calc_dissolve_error(const BMEdge *e,
- const BMO_Delimit delimit,
- const struct DelimitData *delimit_data)
+static bool bm_edge_is_delimiter(const BMEdge *e,
+ const BMO_Delimit delimit,
+ const struct DelimitData *delimit_data)
{
- if (!BM_edge_is_manifold(e)) {
- goto fail;
- }
-
- if ((delimit & BMO_DELIM_SEAM) && (BM_elem_flag_test(e, BM_ELEM_SEAM))) {
- goto fail;
- }
+ /* Caller must ensure. */
+ BLI_assert(BM_edge_is_manifold(e));
- if ((delimit & BMO_DELIM_SHARP) && (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0)) {
- goto fail;
- }
-
- if ((delimit & BMO_DELIM_MATERIAL) && (e->l->f->mat_nr != e->l->radial_next->f->mat_nr)) {
- goto fail;
+ if (delimit != 0) {
+ if (delimit & BMO_DELIM_SEAM) {
+ if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
+ return true;
+ }
+ }
+ if (delimit & BMO_DELIM_SHARP) {
+ if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0) {
+ return true;
+ }
+ }
+ if (delimit & BMO_DELIM_MATERIAL) {
+ if (e->l->f->mat_nr != e->l->radial_next->f->mat_nr) {
+ return true;
+ }
+ }
+ if (delimit & BMO_DELIM_NORMAL) {
+ if (!BM_edge_is_contiguous(e)) {
+ return true;
+ }
+ }
+ if (delimit & BMO_DELIM_UV) {
+ if (bm_edge_is_contiguous_loop_cd_all(e, delimit_data) == 0) {
+ return true;
+ }
+ }
}
- const bool is_contig = BM_edge_is_contiguous(e);
+ return false;
+}
- if ((delimit & BMO_DELIM_NORMAL) && (is_contig == false)) {
- goto fail;
- }
+static bool bm_vert_is_delimiter(const BMVert *v,
+ const BMO_Delimit delimit,
+ const struct DelimitData *delimit_data)
+{
+ BLI_assert(v->e != NULL);
- if ((delimit & BMO_DELIM_UV) && (bm_edge_is_contiguous_loop_cd_all(e, delimit_data) == 0)) {
- goto fail;
+ if (delimit != 0) {
+ const BMEdge *e, *e_first;
+ e = e_first = v->e;
+ do {
+ if (BM_edge_is_manifold(e)) {
+ if (bm_edge_is_delimiter(e, delimit, delimit_data)) {
+ return true;
+ }
+ }
+ } while ((e = BM_DISK_EDGE_NEXT(e, v)) != e_first);
}
+ return false;
+}
- float angle_cos_neg = dot_v3v3(e->l->f->no, e->l->radial_next->f->no);
- if (is_contig) {
- angle_cos_neg *= -1;
+static float bm_edge_calc_dissolve_error(const BMEdge *e,
+ const BMO_Delimit delimit,
+ const struct DelimitData *delimit_data)
+{
+ if (BM_edge_is_manifold(e) && !bm_edge_is_delimiter(e, delimit, delimit_data)) {
+ float angle_cos_neg = dot_v3v3(e->l->f->no, e->l->radial_next->f->no);
+ if (BM_edge_is_contiguous(e)) {
+ angle_cos_neg *= -1;
+ }
+ return angle_cos_neg;
}
- return angle_cos_neg;
-
-fail:
return COST_INVALID;
}
@@ -411,7 +460,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm,
for (i = 0; i < vinput_len; i++) {
BMVert *v = vinput_arr[i];
if (LIKELY(v != NULL)) {
- const float cost = bm_vert_edge_face_angle(v);
+ const float cost = bm_vert_edge_face_angle(v, delimit, &delimit_data);
vheap_table[i] = BLI_heap_insert(vheap, cost, v);
BM_elem_index_set(v, i); /* set dirty */
}
@@ -452,7 +501,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm,
BM_ITER_ELEM (v_iter, &iter, e_new, BM_VERTS_OF_EDGE) {
const int j = BM_elem_index_get(v_iter);
if (j != -1 && vheap_table[j]) {
- const float cost = bm_vert_edge_face_angle(v_iter);
+ const float cost = bm_vert_edge_face_angle(v_iter, delimit, &delimit_data);
BLI_heap_node_value_update(vheap, vheap_table[j], cost);
}
}
@@ -472,7 +521,8 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm,
const int j = BM_elem_index_get(l_cycle_iter->v);
if (j != -1 && vheap_table[j] &&
(BLI_heap_node_value(vheap_table[j]) == COST_INVALID)) {
- const float cost = bm_vert_edge_face_angle(l_cycle_iter->v);
+ const float cost = bm_vert_edge_face_angle(
+ l_cycle_iter->v, delimit, &delimit_data);
BLI_heap_node_value_update(vheap, vheap_table[j], cost);
}
} while ((l_cycle_iter = l_cycle_iter->next) != l_cycle_first);