[Bf-blender-cvs] [966e4ba9aea] temp_bmesh_multires: Sculpt dyntopo: improved boundary smoothing

Joseph Eagar noreply at git.blender.org
Sat Aug 28 03:14:29 CEST 2021


Commit: 966e4ba9aea80ee6f13f515afd06d801346bddbd
Author: Joseph Eagar
Date:   Fri Aug 27 18:13:18 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rB966e4ba9aea80ee6f13f515afd06d801346bddbd

Sculpt dyntopo: improved boundary smoothing

It's kind of hackish mathematically.

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

M	release/scripts/startup/bl_ui/properties_paint_common.py
M	source/blender/editors/sculpt_paint/sculpt_boundary.c
M	source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/editors/sculpt_paint/sculpt_smooth.c

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

diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 8bdfab02afb..64d1c4c2caa 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -816,6 +816,8 @@ def brush_settings(layout, context, brush, popover=False):
 
         elif sculpt_tool == 'SMOOTH':
             col = layout.column()
+            col.prop(brush, "boundary_smooth_factor")
+
             col.prop(brush, "use_weighted_smooth")
             col.prop(brush, "preserve_faceset_boundary")
 
diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c
index 94fda663ac3..c77d9c92a2e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_boundary.c
+++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c
@@ -1913,7 +1913,7 @@ static void SCULPT_boundary_autosmooth(SculptSession *ss, SculptBoundary *bounda
         float sco[3];
 
         SCULPT_neighbor_coords_average_interior(
-            ss, sco, vd.vertex, ss->cache->brush->autosmooth_projection);
+            ss, sco, vd.vertex, ss->cache->brush->autosmooth_projection, NULL);
 
         float *co = SCULPT_brush_deform_target_vertex_co_get(
             ss, ss->cache->brush->deform_target, &vd);
@@ -1952,7 +1952,7 @@ static void SCULPT_boundary_build_smoothco(SculptSession *ss, SculptBoundary *bo
 
         float sco[3];
 
-        SCULPT_neighbor_coords_average_interior(ss, sco, vd.vertex, projection);
+        SCULPT_neighbor_coords_average_interior(ss, sco, vd.vertex, projection, NULL);
 
         float *co = SCULPT_brush_deform_target_vertex_co_get(
             ss, ss->cache->brush->deform_target, &vd);
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index 2521bcc3c26..e9d699d4f79 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -334,7 +334,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
     switch (filter_type) {
       case MESH_FILTER_SMOOTH:
         fade = clamp_f(fade, -1.0f, 1.0f);
-        SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, 0.0f);
+        SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, 0.0f, NULL);
         sub_v3_v3v3(val, avg, orig_co);
         madd_v3_v3v3fl(val, orig_co, val, fade);
         sub_v3_v3v3(disp, val, orig_co);
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index e5abca26c51..779b427bcea 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -641,7 +641,8 @@ void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], SculptVer
 void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
                                              float result[3],
                                              SculptVertRef index,
-                                             float projection);
+                                             float projection,
+                                             SculptCustomLayer *bound_scl);
 
 void SCULPT_smooth_vcol_boundary(
     Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength);
@@ -904,7 +905,7 @@ typedef struct SculptThreadedTaskData {
 
   float smooth_projection;
   float rake_projection;
-  SculptCustomLayer *scl;
+  SculptCustomLayer *scl, *scl2;
 } SculptThreadedTaskData;
 
 /*************** Brush testing declarations ****************/
@@ -1633,3 +1634,6 @@ void SCULPT_get_cotangents(SculptSession *ss,
 
 // call this in the main thread before any calls to SCULPT_get_cotangents
 void SCULPT_cotangents_begin(struct Object *ob, SculptSession *ss);
+
+// exponent to make boundary_smooth_factor more user-friendly
+#define BOUNDARY_SMOOTH_EXP 2.0
diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c
index 2b5e07eb861..894dda8f84a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_smooth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c
@@ -74,7 +74,8 @@
 void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
                                              float result[3],
                                              SculptVertRef vertex,
-                                             float projection)
+                                             float projection,
+                                             SculptCustomLayer *bound_scl)
 {
   float avg[3] = {0.0f, 0.0f, 0.0f};
   float total = 0.0f;
@@ -82,7 +83,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
   bool check_fsets = ss->cache->brush->flag2 & BRUSH_SMOOTH_PRESERVE_FACE_SETS;
 
   int bflag = SCULPT_BOUNDARY_MESH | SCULPT_BOUNDARY_SHARP;
-  float bound_smooth = ss->cache->brush->boundary_smooth_factor;
+  float bound_smooth = powf(ss->cache->brush->boundary_smooth_factor, BOUNDARY_SMOOTH_EXP);
 
   if (check_fsets) {
     bflag |= SCULPT_BOUNDARY_FACE_SET;
@@ -105,13 +106,23 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
     ctype |= SCULPT_CORNER_FACE_SET;
   }
 
-  if (weighted) {
+  bool have_bmesh = ss->bm;
+
+  if (weighted || bound_scl) {
     int val = SCULPT_vertex_valence_get(ss, vertex);
     areas = BLI_array_alloca(areas, val);
 
     BKE_pbvh_get_vert_face_areas(ss->pbvh, vertex, areas, val);
   }
 
+  float *b1 = NULL, btot = 0.0f, b1_orig;
+
+  if (bound_scl) {
+    b1 = SCULPT_temp_cdata_get(vertex, bound_scl);
+    b1_orig = *b1;
+    *b1 = 0.0f;
+  }
+
   SculptVertexNeighborIter ni;
   SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
     neighbor_count++;
@@ -142,6 +153,55 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
         ok = true;
       }
     }
+    else if (bound_scl) {
+      /*
+      simple boundary inflator using an ad-hoc diffusion-based pseudo-geodesic field
+
+      makes more rounded edges.
+      */
+      copy_v3_v3(tmp, SCULPT_vertex_co_get(ss, ni.vertex));
+      ok = true;
+
+      if (bound_scl) {
+        float len = len_v3v3(co, tmp);
+        float w2 = 1.0f;
+
+        float *b2 = SCULPT_temp_cdata_get(ni.vertex, bound_scl);
+        float b2_val = *b2 + len;
+
+        if (SCULPT_vertex_is_boundary(ss, ni.vertex, bflag)) {
+          w2 = 1000.0f;
+          b2_val = len;
+        }
+
+        *b1 += b2_val * w2;
+        btot += w2;
+
+        float no2[3];
+        SCULPT_vertex_normal_get(ss, ni.vertex, no2);
+
+        float radius = ss->cache->radius * 10.0f;
+
+        float th = radius - b1_orig;
+        th = MAX2(th, 0.0f);
+        th /= radius;
+
+#if 0
+        float *color = (float *)SCULPT_vertex_color_get(ss, ni.vertex);
+        color[0] = color[1] = color[2] = th;
+        color[3] = 1.0f;
+#endif
+
+        float fac = ss->cache->brush->boundary_smooth_factor;
+        fac = MIN2(fac * 4.0f, 1.0f);
+        fac = powf(fac, 0.2);
+        th *= fac;
+
+        sub_v3_v3(tmp, co);
+        madd_v3_v3fl(tmp, no2, th * dot_v3v3(no2, tmp));
+        add_v3_v3(tmp, co);
+      }
+    }
     else {
       /* Interior vertices use all neighbors. */
       copy_v3_v3(tmp, SCULPT_vertex_co_get(ss, ni.vertex));
@@ -166,6 +226,14 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
   }
   SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
 
+  if (btot != 0.0f) {
+    *b1 /= btot;
+    //*b1 += (b1_orig - *b1) * 0.95f;
+  }
+  else if (b1) {
+    *b1 = b1_orig;
+  }
+
   /* Do not modify corner vertices. */
   if (neighbor_count <= 2 && is_boundary) {
     copy_v3_v3(result, SCULPT_vertex_co_get(ss, vertex));
@@ -705,12 +773,13 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
     ctype |= SCULPT_CORNER_FACE_SET;
   }
 
-  if (weighted) {
+  if (weighted || ss->cache->brush->boundary_smooth_factor > 0.0f) {
     BKE_pbvh_check_tri_areas(ss->pbvh, data->nodes[n]);
   }
 
   bool modified = false;
-  const float bound_smooth = ss->cache->brush->boundary_smooth_factor;
+  const float bound_smooth = powf(ss->cache->brush->boundary_smooth_factor, BOUNDARY_SMOOTH_EXP);
+  SculptCustomLayer *bound_scl = data->scl2;
 
   BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
     if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
@@ -739,7 +808,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
         continue;
       }
 
-      SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, projection);
+      SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex, projection, bound_scl);
       sub_v3_v3v3(val, avg, vd.co);
       madd_v3_v3v3fl(val, vd.co, val, fade);
       SCULPT_clip(sd, ss, vd.co, val);
@@ -832,6 +901,12 @@ void SCULPT_smooth(Sculpt *sd,
   int iteration, count;
   float last;
 
+  if (SCULPT_stroke_is_first_brush_step(ss->cache) &&
+      ((ss->cache->brush->flag2 & BRUSH_SMOOTH_USE_AREA_WEIGHT) ||
+       ss->cache->brush->boundary_smooth_factor > 0.0f)) {
+    BKE_pbvh_update_all_tri_areas(ss->pbvh);
+  }
+
   CLAMP(bstrength, 0.0f, 1.0f);
 
   count = (int)(bstrength * max_iterations);
@@ -857,6 +932,17 @@ void SCULPT_smooth(Sculpt *sd,
   SCULPT_vertex_random_access_ensure(ss);
   SCULPT_boundary_info_ensure(ob);
 
+  SculptCustomLayer _scl, *bound_scl = NULL;
+
+  /* create temp layer for psuedo-geodesic field */
+  if (ss->cache->brush->boundary_smooth_factor > 0.0f) {
+    float bound_smooth = powf(ss->cache->brush->boundary_smooth_factor, BOUNDARY_SMOOTH_EXP);
+
+    bound_scl = &_scl;
+    SCULPT_temp_customlayer_ensure(ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "__smooth_bdist");
+    SCULPT_temp_customlayer_get(ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "__smooth_bdist", bound_scl);
+  }
+
 #ifdef PROXY_ADVANCED
   int datamask = PV_CO | PV_NEIGHBORS | PV_NO | PV_INDEX | PV_MASK;
   BKE_pbvh_ensure_proxyarrays(ss, ss->pbvh, nodes, totnode, datamask);
@@ -873,11 +959,12 @@ void SCULPT_smooth(Sculpt *sd,
                                    .smooth_mask = smooth_mask,
                                 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list