[Bf-blender-cvs] [013eee7ec62] temp_bmesh_multires: * The dyntopo remesher is now a bit smarter about avoiding certain degenerate cases that produce lots of bad geometry (and also bad PBVHs that slows down the whole mesh). + A very small amount of surface smoothing is now applied by dyntopo. + The recursive functions that expand the region considered by dyntopo now ignore "front face only" for depths less then 5. + The number of edges dyntopo can split or collapse in one run has been cut in half to 4k. - This limit is also now dynamically adjusted by a measure of how skinny the edges are.
Joseph Eagar
noreply at git.blender.org
Thu Apr 29 04:19:15 CEST 2021
Commit: 013eee7ec62ebb39f28f0f949e1e0ccd8e5d07ef
Author: Joseph Eagar
Date: Wed Apr 28 19:11:23 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rB013eee7ec62ebb39f28f0f949e1e0ccd8e5d07ef
* The dyntopo remesher is now a bit smarter about avoiding
certain degenerate cases that produce lots of bad geometry (and
also bad PBVHs that slows down the whole mesh).
+ A very small amount of surface smoothing is now applied by dyntopo.
+ The recursive functions that expand the region considered by dyntopo
now ignore "front face only" for depths less then 5.
+ The number of edges dyntopo can split or collapse in one run has been cut in
half to 4k.
- This limit is also now dynamically adjusted by a measure
of how skinny the edges are.
===================================================================
M source/blender/blenkernel/intern/pbvh_bmesh.c
===================================================================
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index a6052390d7b..69e982f83fe 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -50,6 +50,7 @@ Topology rake:
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "PIL_time.h"
+#include "atomic_ops.h"
#include "BKE_DerivedMesh.h"
#include "BKE_ccg.h"
@@ -60,7 +61,7 @@ Topology rake:
#include "bmesh.h"
#include "pbvh_intern.h"
-#define DYNTOPO_MAX_ITER 8192
+#define DYNTOPO_MAX_ITER 4096
#define DYNTOPO_USE_HEAP
@@ -72,6 +73,24 @@ Topology rake:
/* Avoid skinny faces */
#define USE_EDGEQUEUE_EVEN_SUBDIV
+
+/* How much longer we need to be to consider for subdividing
+ * (avoids subdividing faces which are only *slightly* skinny) */
+#define EVEN_EDGELEN_THRESHOLD 1.2f
+/* How much the limit increases per recursion
+ * (avoids performing subdivisions too far away). */
+#define EVEN_GENERATION_SCALE 1.1f
+
+//recursion depth to start applying front face test
+#define DEPTH_START_LIMIT 5
+
+//#define FANCY_EDGE_WEIGHTS
+#define SKINNY_EDGE_FIX
+
+//slightly relax geometry by this factor along surface tangents
+//to improve convergence of remesher
+#define DYNTOPO_SAFE_SMOOTH_FAC 0.05f
+
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
# include "BKE_global.h"
#endif
@@ -174,6 +193,46 @@ static void pbvh_bmesh_verify(PBVH *pbvh);
} \
((void)0)
+ATTR_NO_OPT void surface_smooth_v_safe(BMVert *v)
+{
+ float co[3];
+ float tan[3];
+ float tot = 0.0;
+
+ zero_v3(co);
+
+ // this is a manual edge walk
+
+ BMEdge *e = v->e;
+ if (!e) {
+ return;
+ }
+
+ do {
+ BMVert *v2 = e->v1 == v ? e->v2 : e->v1;
+
+ sub_v3_v3v3(tan, v2->co, v->co);
+ float d = dot_v3v3(tan, v->no);
+
+ madd_v3_v3fl(tan, v->no, -d * 0.99f);
+ add_v3_v3(co, tan);
+ tot += 1.0f;
+ e = v == e->v1 ? e->v1_disk_link.next : e->v2_disk_link.next;
+ } while (e != v->e);
+
+ if (tot == 0.0f) {
+ return;
+ }
+
+ mul_v3_fl(co, 1.0f / tot);
+ float x = v->co[0], y = v->co[1], z = v->co[2];
+
+ //conflicts here should be pretty rare.
+ atomic_cas_float(&v->co[0], x, x + co[0] * DYNTOPO_SAFE_SMOOTH_FAC);
+ atomic_cas_float(&v->co[1], y, y + co[1] * DYNTOPO_SAFE_SMOOTH_FAC);
+ atomic_cas_float(&v->co[2], z, z + co[2] * DYNTOPO_SAFE_SMOOTH_FAC);
+}
+
static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3])
{
e_tri[0] = BM_edge_create(bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE);
@@ -610,12 +669,13 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
if (v_example) {
v->head.hflag = v_example->head.hflag;
- CustomData_bmesh_copy_data(&pbvh->bm->vdata, &pbvh->bm->vdata, v_example->head.data, &v->head.data);
+ CustomData_bmesh_copy_data(
+ &pbvh->bm->vdata, &pbvh->bm->vdata, v_example->head.data, &v->head.data);
/* This value is logged below */
copy_v3_v3(v->no, no);
- //keep MDynTopoVert copied from v_example as-is
+ // keep MDynTopoVert copied from v_example as-is
}
else {
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
@@ -958,7 +1018,11 @@ static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
int f_node_index_prev = DYNTOPO_NODE_NONE;
PBVHNode *v_node = pbvh_bmesh_node_from_vert(pbvh, v);
- BLI_table_gset_remove(v_node->bm_unique_verts, v, NULL);
+
+ if (v_node) {
+ BLI_table_gset_remove(v_node->bm_unique_verts, v, NULL);
+ }
+
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
/* Have to check each neighboring face's node */
@@ -1090,19 +1154,23 @@ typedef struct {
int cd_vert_mask_offset;
int cd_vert_node_offset;
int cd_face_node_offset;
+ float avg_elen;
+ float max_elen;
+ float min_elen;
+ float totedge;
} EdgeQueueContext;
BLI_INLINE float calc_weighted_edge_split(EdgeQueueContext *eq_ctx, BMVert *v1, BMVert *v2)
{
-#if 0
+#ifdef FANCY_EDGE_WEIGHTS
float l = len_squared_v3v3(v1->co, v2->co);
- float n;
-
- n = (float)(BM_vert_edge_count(v1) + BM_vert_edge_count(v2)) * 0.5f;
- n = MAX2(n - 6.0f, 1.0f);
+ float val = (float)BM_vert_edge_count(v1) + (float)BM_vert_edge_count(v2);
+ val = MAX2(val * 0.5 - 6.0f, 1.0f);
+ val = powf(val, 0.5);
+ l *= val;
- return l * (n);
-#elif 1 // penalize 4-valence verts
+ return l;
+#elif 0 // penalize 4-valence verts
float l = len_squared_v3v3(v1->co, v2->co);
if (BM_vert_edge_count(v1) == 4 || BM_vert_edge_count(v2) == 4) {
l *= 0.25f;
@@ -1116,16 +1184,13 @@ BLI_INLINE float calc_weighted_edge_split(EdgeQueueContext *eq_ctx, BMVert *v1,
BLI_INLINE float calc_weighted_edge_collapse(EdgeQueueContext *eq_ctx, BMVert *v1, BMVert *v2)
{
-#if 0
+#ifdef FANCY_EDGE_WEIGHTS
float l = len_squared_v3v3(v1->co, v2->co);
- float n;
-
- n = (float)(BM_vert_edge_count(v1) + BM_vert_edge_count(v2)) * 0.5f;
- n = MAX2(n - 5.0f, 1.0f);
+ float val = (float)BM_vert_edge_count(v1) + (float)BM_vert_edge_count(v2);
+ val = MAX2(val*0.5 - 6.0f, 1.0f);
+ val = powf(val, 0.5);
+ l /= val;
- return l * (n*n*4.0f);
-#elif 1 // penalize 4-valence verts
- float l = len_squared_v3v3(v1->co, v2->co);
// if (BM_vert_edge_count(v1) == 4 || BM_vert_edge_count(v2) == 4) {
// l *= 0.25f;
//}
@@ -1620,6 +1685,13 @@ static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, float priorit
(check_mask(eq_ctx, e->v1) || check_mask(eq_ctx, e->v2))) &&
!(BM_elem_flag_test_bool(e->v1, BM_ELEM_HIDDEN) ||
BM_elem_flag_test_bool(e->v2, BM_ELEM_HIDDEN))) {
+
+ float dis = len_v3v3(e->v1->co, e->v2->co);
+ eq_ctx->avg_elen += dis;
+ eq_ctx->max_elen = MAX2(eq_ctx->max_elen, dis);
+ eq_ctx->min_elen = MIN2(eq_ctx->min_elen, dis);
+ eq_ctx->totedge += 1.0f;
+
BMVert **pair = BLI_mempool_alloc(eq_ctx->pool);
pair[0] = e->v1;
pair[1] = e->v2;
@@ -1653,12 +1725,12 @@ static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx, BMEdge *e)
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
static void long_edge_queue_edge_add_recursive(
- EdgeQueueContext *eq_ctx, BMLoop *l_edge, BMLoop *l_end, const float len_sq, float limit_len)
+ EdgeQueueContext *eq_ctx, BMLoop *l_edge, BMLoop *l_end, const float len_sq, float limit_len, int depth)
{
BLI_assert(len_sq > square_f(limit_len));
# ifdef USE_EDGEQUEUE_FRONTFACE
- if (eq_ctx->q->use_view_normal) {
+ if (depth > DEPTH_START_LIMIT && eq_ctx->q->use_view_normal) {
if (dot_v3v3(l_edge->f->no, eq_ctx->q->view_normal) < 0.0f) {
return;
}
@@ -1678,13 +1750,6 @@ static void long_edge_queue_edge_add_recursive(
}
if ((l_edge->radial_next != l_edge)) {
- /* How much longer we need to be to consider for subdividing
- * (avoids subdividing faces which are only *slightly* skinny) */
-# define EVEN_EDGELEN_THRESHOLD 1.2f
- /* How much the limit increases per recursion
- * (avoids performing subdivisions too far away). */
-# define EVEN_GENERATION_SCALE 1.6f
-
const float len_sq_cmp = len_sq * EVEN_EDGELEN_THRESHOLD;
limit_len *= EVEN_GENERATION_SCALE;
@@ -1698,13 +1763,10 @@ static void long_edge_queue_edge_add_recursive(
if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) {
// edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other);
long_edge_queue_edge_add_recursive(
- eq_ctx, l_adjacent[i]->radial_next, l_adjacent[i], len_sq_other, limit_len);
+ eq_ctx, l_adjacent[i]->radial_next, l_adjacent[i], len_sq_other, limit_len, depth+1);
}
}
} while ((l_iter = l_iter->radial_next) != l_end);
-
-# undef EVEN_EDGELEN_THRESHOLD
-# undef EVEN_GENERATION_SCALE
}
}
#endif /* USE_EDGEQUEUE_EVEN_SUBDIV */
@@ -1722,10 +1784,10 @@ static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx, BMEdge *e)
}
}
-static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f)
+static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f, bool ignore_frontface)
{
#ifdef USE_EDGEQUEUE_FRONTFACE
- if (eq_ctx->q->use_view_normal) {
+ if (!ignore_frontface && eq_ctx->q->use_view_normal) {
if (dot_v3v3(f->no, eq_ctx->q->view_normal) < 0.0f) {
return;
}
@@ -1741,7 +1803,7 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f)
const float len_sq = BM_edge_calc_length_squared(l_iter->e);
if (len_sq > eq_ctx->q->limit_len_squared) {
long_edge_queue_edge_add_recursive(
- eq_ctx, l_iter->radial_next, l_iter, len_sq, eq_ctx->q->limit_len);
+ eq_ctx, l_iter->radial_next, l_iter, len_sq, eq_ctx->q->limit_len, DEPTH_START_LIMIT+1);//ignore_frontface ? 0 : DEPTH_START_LIMIT+1);
}
#else
long_edge_queue_edge_add(eq_ctx, l_iter->e);
@@ -1772,8 +1834,13 @@ static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f)
}
}
-static void long_edge_queue_edge_add_recursive_2(
- EdgeQueueThreadData *tdata, BMLoop *l_edge, BMLoop *l_end, const float len_sq, float limit_len)
+
+static void short_edge_queue_edge_add_recursive_2(EdgeQueueThreadData *tdata,
+ BMLoop *l_edge,
+ BMLoop *l_end,
+ const float len_sq,
+ float limit_len,
+ int depth)
{
BLI_assert(len_sq > square_f(limit_len));
@@ -1782,7 +1849,7 @@ static void long_edge_queue_edge_add_recursive_2(
}
#ifdef USE_EDGEQUEUE_FRONTFACE
- if (tdata->eq_ctx->q->use_view_normal) {
+ if (depth > DEPTH_START_LIMIT && tdata->eq_ctx->q->use_view_normal) {
if (dot_v3v3(l_edge->f->no, tdata->eq_ctx->q->view_normal) < 0.0f) {
return;
}
@@ -1797,13 +1864,58 @@ static void long_edge_queue_edge_add_recursive_2(
}
if ((l_edge->radial_next != l_edge)) {
- /* How much longer we need to be to consider for subdividing
- * (avoids subdividing faces which are only *slightly* skinny) */
-#define EVEN_EDGELEN_THRESHOLD 1.2f
- /* How much the limit increases per recursion
- * (avoids performing
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list