[Bf-blender-cvs] [bde54e127ea] temp_bmesh_multires: Sculpt dyntopo: Smooth improvements and bug fixes

Joseph Eagar noreply at git.blender.org
Tue Aug 24 07:55:29 CEST 2021


Commit: bde54e127eace4bc865044673beb21e9034bad60
Author: Joseph Eagar
Date:   Mon Aug 23 21:06:10 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rBbde54e127eace4bc865044673beb21e9034bad60

Sculpt dyntopo: Smooth improvements and bug fixes

* Added an option to weight smooth by face areas
* Dyntopo now caches face areas in a CD_PROP_FLOAT layer
* Dyntopo also caches number of edges around verts inside of
  MDynTopoVert.  To avoid increasing the struct size flag was
  made a short.
* Cleanup mode (dissolves 3/4-valence verts) now piggybacks on
  subdivide code to build list of verts; this is much faster.

===================================================================

M	release/scripts/startup/bl_ui/properties_paint_common.py
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/dyntopo.c
M	source/blender/blenkernel/intern/paint.c
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/blenkernel/intern/pbvh_bmesh.c
M	source/blender/blenkernel/intern/pbvh_intern.h
M	source/blender/editors/sculpt_paint/paint_mask.c
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_dyntopo.c
M	source/blender/editors/sculpt_paint/sculpt_smooth.c
M	source/blender/editors/sculpt_paint/sculpt_undo.c
M	source/blender/makesdna/DNA_brush_enums.h
M	source/blender/makesdna/DNA_meshdata_types.h
M	source/blender/makesrna/intern/rna_brush.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 1b71dae5e35..1043e8af1dc 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -567,6 +567,8 @@ def brush_settings(layout, context, brush, popover=False):
                 slider=True,
             )
 
+            box.prop(brush, "use_weighted_smooth")
+
             box.prop(brush, "use_custom_auto_smooth_spacing", text="Custom Spacing")
             if brush.use_custom_auto_smooth_spacing:
                UnifiedPaintPanel.prop_unified(
@@ -812,7 +814,9 @@ def brush_settings(layout, context, brush, popover=False):
 
         elif sculpt_tool == 'SMOOTH':
             col = layout.column()
+            col.prop(brush, "use_weighted_smooth")
             col.prop(brush, "smooth_deform_type")
+
             if brush.smooth_deform_type == 'SURFACE':
                 col.prop(brush, "surface_smooth_shape_preservation")
                 col.prop(brush, "surface_smooth_current_vertex")
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index db091a8b878..2b829e8f569 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -533,6 +533,7 @@ typedef struct SculptSession {
   int cd_face_node_offset;
   int cd_vcol_offset;
   int cd_faceset_offset;
+  int cd_face_areas;
 
   bool bm_smooth_shading;
   /* Undo/redo log for dynamic topology sculpting */
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 05837f8f847..0b2e288cfb5 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -209,7 +209,11 @@ typedef enum {
   PBVH_Delete = 1 << 15,
   PBVH_UpdateCurvatureDir = 1 << 16,
   PBVH_UpdateTris = 1 << 17,
-  PBVH_RebuildNodeVerts = 1 << 18
+  PBVH_RebuildNodeVerts = 1 << 18,
+
+  /* tri areas are not guaranteed to be up to date, tools should
+     update all nodes on first step of brush*/
+  PBVH_UpdateTriAreas = 1 << 19
 } PBVHNodeFlags;
 
 typedef struct PBVHFrustumPlanes {
@@ -263,11 +267,13 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
                           const int cd_vert_node_offset,
                           const int cd_face_node_offset,
                           const int cd_dyn_vert,
+                          const int cd_face_areas,
                           bool fast_draw);
 void BKE_pbvh_update_offsets(PBVH *pbvh,
                              const int cd_vert_node_offset,
                              const int cd_face_node_offset,
-                             const int cd_dyn_vert);
+                             const int cd_dyn_vert,
+                             const int cd_face_areas);
 void BKE_pbvh_free(PBVH *pbvh);
 
 /** update original data, only data whose r_** parameters are passed in will be updated*/
@@ -436,6 +442,18 @@ bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
                                           void *mask_cb_data);
 /* Node Access */
 
+void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node);
+
+// updates boundaries and valences for whole mesh
+void BKE_pbvh_bmesh_on_mesh_change(PBVH *pbvh);
+bool BKE_pbvh_bmesh_check_valence(PBVH *pbvh, SculptVertRef vertex);
+void BKE_pbvh_bmesh_update_valence(int cd_dyn_vert, SculptVertRef vertex);
+void BKE_pbvh_bmesh_update_all_valence(PBVH *pbvh);
+void BKE_pbvh_bmesh_flag_all_disk_sort(PBVH *pbvh);
+bool BKE_pbvh_bmesh_mark_update_valence(PBVH *pbvh, SculptVertRef vertex);
+
+void BKE_pbvh_node_mark_update_tri_area(PBVHNode *node);
+void BKE_pbvh_update_all_tri_areas(PBVH *pbvh);
 void BKE_pbvh_node_mark_update(PBVHNode *node);
 void BKE_pbvh_node_mark_update_mask(PBVHNode *node);
 void BKE_pbvh_node_mark_update_color(PBVHNode *node);
@@ -751,6 +769,8 @@ void BKE_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, struc
 
 PBVHNode *BKE_pbvh_get_node_leaf_safe(PBVH *pbvh, int i);
 
+void BKE_pbvh_get_vert_face_areas(PBVH *pbvh, SculptVertRef vertex, float *r_areas, int valence);
+
 #if 0
 typedef enum {
   SCULPT_TEXTURE_UV = 1 << 0,  // per-uv
diff --git a/source/blender/blenkernel/intern/dyntopo.c b/source/blender/blenkernel/intern/dyntopo.c
index da3e42e629d..023cb324346 100644
--- a/source/blender/blenkernel/intern/dyntopo.c
+++ b/source/blender/blenkernel/intern/dyntopo.c
@@ -32,6 +32,8 @@
 
 #include <stdio.h>
 
+#define DYNVERT_VALENCE_TEMP (1 << 14)
+
 //#define USE_NEW_SPLIT
 #define DYNVERT_ALL_BOUNDARY (DYNVERT_BOUNDARY | DYNVERT_FSET_BOUNDARY)
 
@@ -162,6 +164,7 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v)
   if (!e) {
     return;
   }
+
   pbvh_check_vert_boundary(pbvh, v);
 
   const int cd_dyn_vert = pbvh->cd_dyn_vert;
@@ -172,7 +175,8 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v)
   do {
     BMVert *v2 = e->v1 == v ? e->v2 : e->v1;
 
-    pbvh_check_vert_boundary(pbvh, v2);
+    // can't check for boundary here, thread
+    // pbvh_check_vert_boundary(pbvh, v2);
 
     MDynTopoVert *mv2 = BKE_PBVH_DYNVERT(cd_dyn_vert, v2);
     const bool bound2 = mv2->flag & DYNVERT_ALL_BOUNDARY;
@@ -846,8 +850,40 @@ typedef struct {
   float max_elen;
   float min_elen;
   float totedge;
+  BMVert **val34_verts;
+  int val34_verts_tot;
+  int val34_verts_size;
 } EdgeQueueContext;
 
+static void edge_queue_insert_val34_vert(EdgeQueueContext *eq_ctx, BMVert *v)
+{
+  MDynTopoVert *mv = BKE_PBVH_DYNVERT(eq_ctx->cd_dyn_vert, v);
+  // prevent double adding
+
+  if (mv->flag & DYNVERT_VALENCE_TEMP) {
+    return;
+  }
+
+  mv->flag |= DYNVERT_VALENCE_TEMP;
+
+  eq_ctx->val34_verts_tot++;
+
+  if (eq_ctx->val34_verts_tot > eq_ctx->val34_verts_size) {
+    int size2 = 4 + eq_ctx->val34_verts_tot + (eq_ctx->val34_verts_tot >> 1);
+
+    if (eq_ctx->val34_verts) {
+      eq_ctx->val34_verts = MEM_reallocN(eq_ctx->val34_verts, sizeof(void *) * size2);
+    }
+    else {
+      eq_ctx->val34_verts = MEM_mallocN(sizeof(void *) * size2, "val34_verts");
+    }
+
+    eq_ctx->val34_verts_size = size2;
+  }
+
+  eq_ctx->val34_verts[eq_ctx->val34_verts_tot - 1] = v;
+}
+
 BLI_INLINE float maskcb_get(EdgeQueueContext *eq_ctx, BMEdge *e)
 {
   if (eq_ctx->mask_cb) {
@@ -1019,6 +1055,8 @@ typedef struct EdgeQueueThreadData {
   PBVH *pbvh;
   PBVHNode *node;
   BMEdge **edges;
+  BMVert **val34_verts;
+  int val34_verts_tot;
   EdgeQueueContext *eq_ctx;
   int totedge;
   int size;
@@ -1346,6 +1384,8 @@ static void long_edge_queue_edge_add_recursive_2(EdgeQueueThreadData *tdata,
   }
 }
 
+static int _long_edge_queue_task_cb_seed = 0;
+
 static void long_edge_queue_task_cb(void *__restrict userdata,
                                     const int n,
                                     const TaskParallelTLS *__restrict tls)
@@ -1353,6 +1393,9 @@ static void long_edge_queue_task_cb(void *__restrict userdata,
   EdgeQueueThreadData *tdata = ((EdgeQueueThreadData *)userdata) + n;
   PBVHNode *node = tdata->node;
   EdgeQueueContext *eq_ctx = tdata->eq_ctx;
+  RNG *rng = BLI_rng_new(_long_edge_queue_task_cb_seed++);  // I don't care if seed becomes mangled
+  BMVert **val34 = NULL;
+  BLI_array_declare(val34);
 
   BMFace *f;
   const int cd_dyn_vert = tdata->pbvh->cd_dyn_vert;
@@ -1381,9 +1424,23 @@ static void long_edge_queue_task_cb(void *__restrict userdata,
       BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
       BMLoop *l_iter = l_first;
       do {
+        MDynTopoVert *mv = BKE_PBVH_DYNVERT(eq_ctx->cd_dyn_vert, l_iter->v);
+
+        /*
+          If valence is not up to date, just add it to the list;
+          long_edge_queue_create will check and de-duplicate this for us.
+
+          Can't update valence in a thread after all.
+        */
+        if (mv->valence < 5 || (mv->flag & DYNVERT_NEED_VALENCE)) {
+          BLI_array_append(val34, l_iter->v);
+        }
+
         // try to improve convergence by applying a small amount of smoothing to topology,
         // but tangentially to surface.
-        surface_smooth_v_safe(tdata->pbvh, l_iter->v);
+        if (BLI_rng_get_float(rng) > 0.75) {
+          surface_smooth_v_safe(tdata->pbvh, l_iter->v);
+        }
 
 #ifdef USE_EDGEQUEUE_EVEN_SUBDIV
         float w = maskcb_get(eq_ctx, l_iter->e);
@@ -1405,6 +1462,11 @@ static void long_edge_queue_task_cb(void *__restrict userdata,
     }
   }
   TGSET_ITER_END
+
+  BLI_rng_free(rng);
+
+  tdata->val34_verts = val34;
+  tdata->val34_verts_tot = BLI_array_len(val34);
 }
 
 static void short_edge_queue_task_cb(void *__restrict userdata,
@@ -1573,17 +1635,25 @@ static bool check_face_is_tri(PBVH *pbvh, BMFace *f)
 
 static bool check_vert_fan_are_tris(PBVH *pbvh, BMVert *v)
 {
-  BMFace **fs = NULL;
-  BLI_array_staticdeclare(fs, 32);
-
   MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
+
   if (!(mv->flag & DYNVERT_NEED_TRIANGULATE)) {
     return true;
   }
 
+  BMFace **fs = NULL;
+  BLI_array_staticdeclare(fs, 32);
+
   BMIter iter;
   BMFace *f;
   BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+    BMLoop *l = f->l_first;
+
+    do {
+      MDynTopoVert *mv_l = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, l->v);
+
+      mv_l->flag |= DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT;
+    } while ((l = l->next) != f->l_first);
     BLI_array_append(fs, f);
   }
 
@@ -1598,6 +1668,34 @@ static bool check_vert_fan_are_tris(PBVH *pbvh, BMVert *v)
   return false;
 }
 
+static void edge_queue_init(EdgeQueueContext *eq_ctx,
+                            bool use_projected,
+                            bool use_frontface,
+                            const float center[3],
+                            const float view_normal[3],
+                            const float radius)
+{
+  if (use_projected) {
+    eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_circle;
+    eq_ctx->q->edge_queue_vert_in_range = edge_queue_vert_in_circle;
+    project_plane_normalized_v3_v3v3(eq_ctx->q->center_proj, center, view_normal);
+  }
+  else {
+    eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_sphere;
+    eq_ctx->q->edge_queue_vert_in_range = edge_queue_vert_in_sphere;
+  }
+
+  eq_ctx->q->center = center;
+  eq_ctx-

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list