[Bf-blender-cvs] [2f6562fee87] temp-sculpt-cavity-mask: Sculpt: Cavity automasking mode.

Joseph Eagar noreply at git.blender.org
Sat Jun 4 04:05:55 CEST 2022


Commit: 2f6562fee8716e6aab2df04a66e6a30960df1a9c
Author: Joseph Eagar
Date:   Fri Jun 3 19:02:30 2022 -0700
Branches: temp-sculpt-cavity-mask
https://developer.blender.org/rB2f6562fee8716e6aab2df04a66e6a30960df1a9c

Sculpt: Cavity automasking mode.

Implements cavity automasking.  Note that
this is a tad bit different from the sculpt-dev
branch implementation:

* It uses the word "cavity"  I actually came up with
  this idea on my own and, for reasons that escape
  me today, decided to call it "concavity."
* The cavity factor works a bit differently.  It's
  no longer non-linear and functions as a simple
  scale around 0.5f.
* Boundary propegation steps blurs the cavity
  mask.

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

M	release/scripts/startup/bl_ui/properties_paint_common.py
M	release/scripts/startup/bl_ui/space_view3d.py
M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/blenkernel/intern/brush.c
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/editors/sculpt_paint/sculpt_automasking.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/editors/sculpt_paint/sculpt_paint_color.c
M	source/blender/makesdna/DNA_brush_enums.h
M	source/blender/makesdna/DNA_brush_types.h
M	source/blender/makesrna/intern/rna_brush.c
M	source/blender/makesrna/intern/rna_sculpt_paint.c

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

diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 5a9a8882bd9..a37c6814424 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -944,6 +944,14 @@ def brush_settings_advanced(layout, context, brush, popover=False):
         # boundary edges/face sets automasking
         col.prop(brush, "use_automasking_boundary_edges", text="Mesh Boundary")
         col.prop(brush, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
+        col.prop(brush, "use_automasking_cavity", text="Cavity Masking")
+
+        col.separator()
+
+        if brush.use_automasking_cavity:
+            col.prop(brush, "invert_automasking_cavity", text="Invert Cavity")
+            col.prop(brush, "automasking_cavity_factor", text="Cavity Factor")
+
         col.prop(brush, "automasking_boundary_edges_propagation_steps")
 
         layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 80ea33f8a75..32a9ecb210d 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -5450,6 +5450,8 @@ class VIEW3D_MT_sculpt_automasking_pie(Menu):
         pie.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
         pie.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
         pie.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
+        pie.prop(sculpt, "use_automasking_cavity", text="Cavity")
+        pie.prop(sculpt, "invert_automasking_cavity", text="Invert Cavity")
 
 
 class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 892dc9a1e42..c3c7685cd7a 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -971,6 +971,15 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
         col.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
         col.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
         col.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
+        col.prop(sculpt, "use_automasking_cavity", text="Cavity Masking")
+
+        col.separator()
+
+        if sculpt.use_automasking_cavity:
+            col.prop(sculpt, "invert_automasking_cavity", text="Invert Cavity")
+            col.prop(sculpt.brush, "automasking_cavity_factor", text="Cavity Factor")
+
+        col.prop(sculpt.brush, "automasking_boundary_edges_propagation_steps")
 
 
 class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel):
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 083d5af063a..a514646b1f3 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1698,6 +1698,8 @@ void BKE_brush_sculpt_reset(Brush *br)
    * assign this so logic below can remain the same. */
   br->alpha = 0.5f;
 
+  br->automasking_cavity_factor = 0.5f;
+
   /* Brush settings */
   switch (br->sculpt_tool) {
     case SCULPT_TOOL_DRAW_SHARP:
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 76d12cc1109..18bc0565433 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -3021,6 +3021,12 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
     }
   }
 
+  if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "automasking_cavity_factor")) {
+    LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
+      brush->automasking_cavity_factor = 0.5f;
+    }
+  }
+
   /**
    * Versioning code until next subversion bump goes here.
    *
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c
index d7a2a18504c..4358abad81e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.c
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c
@@ -84,6 +84,10 @@ bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, co
   if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
     return true;
   }
+  if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_CAVITY)) {
+    return true;
+  }
+
   return false;
 }
 
@@ -102,15 +106,66 @@ static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush
   if (automasking_flags & BRUSH_AUTOMASKING_TOPOLOGY) {
     return true;
   }
-  if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
-    return brush && brush->automasking_boundary_edges_propagation_steps != 1;
-  }
-  if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) {
+  if (automasking_flags & (BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS |
+                           BRUSH_AUTOMASKING_BOUNDARY_EDGES | BRUSH_AUTOMASKING_CAVITY)) {
     return brush && brush->automasking_boundary_edges_propagation_steps != 1;
   }
   return false;
 }
 
+float SCULPT_calc_cavity(SculptSession *ss, const int vertex)
+{
+  SculptVertexNeighborIter ni;
+  const float *co = SCULPT_vertex_co_get(ss, vertex);
+  float avg[3];
+  float elen = 0.0f;
+  float e_num = 0.0f;
+
+  zero_v3(avg);
+
+  SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
+    const float *co2 = SCULPT_vertex_co_get(ss, ni.index);
+
+    elen += len_v3v3(co, co2);
+    e_num += 1.0f;
+    add_v3_v3(avg, co2);
+  }
+  SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+  if (e_num == 0.0f) {
+    return 0.0f;
+  }
+
+  mul_v3_fl(avg, 1.0f / (float)e_num);
+  elen /= e_num;
+
+  float no[3];
+
+  SCULPT_vertex_normal_get(ss, vertex, no);
+
+  sub_v3_v3(avg, co);
+
+  /* Use distance to plane. */
+  float factor = dot_v3v3(avg, no) / elen;
+
+  return factor;
+}
+
+static float sculpt_automasking_cavity_factor(AutomaskingCache *automasking,
+                                              SculptSession *ss,
+                                              int vert)
+{
+  float factor = SCULPT_calc_cavity(ss, vert);
+  float sign = signf(factor);
+
+  factor = fabsf(factor) * automasking->settings.cavity_factor * 50.0f;
+
+  factor = factor * sign * 0.5f + 0.5f;
+  CLAMP(factor, 0.0f, 1.0f);
+
+  return (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_INVERT) ? 1.0f - factor : factor;
+}
+
 float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
 {
   if (!automasking) {
@@ -141,6 +196,10 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession
     }
   }
 
+  if (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY) {
+    return sculpt_automasking_cavity_factor(automasking, ss, vert);
+  }
+
   return 1.0f;
 }
 
@@ -247,6 +306,76 @@ static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *a
   return automask_factor;
 }
 
+static float *sculpt_cavity_automasking_init(Sculpt *sd,
+                                             Object *ob,
+                                             AutomaskingCache *automasking,
+                                             float *automask_factor,
+                                             int boundary_propagation_steps)
+{
+  SculptSession *ss = ob->sculpt;
+  Brush *brush = BKE_paint_brush(&sd->paint);
+  float *factor = automask_factor, *scratch;
+
+  if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
+    return NULL;
+  }
+
+  if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
+    BLI_assert_msg(0, "Cavity mask automasking: pmap missing");
+    return NULL;
+  }
+
+  int tot_vert = SCULPT_vertex_count_get(ss);
+
+  /* Prepare a few scratch arrays for blur if necassary. */
+  if (boundary_propagation_steps > 1) {
+    factor = MEM_malloc_arrayN(tot_vert, sizeof(float), __func__);
+    scratch = MEM_malloc_arrayN(tot_vert, sizeof(float), __func__);
+
+    for (int i = 0; i < tot_vert; i++) {
+      factor[i] = scratch[i] = 1.0f;
+    }
+  }
+
+  for (int i = 0; i < tot_vert; i++) {
+    factor[i] *= sculpt_automasking_cavity_factor(automasking, ss, i);
+  }
+
+  /* Blur. */
+  for (int iteration = 0; iteration < boundary_propagation_steps - 1; iteration++) {
+    SWAP(float *, factor, scratch);
+
+    for (int i = 0; i < tot_vert; i++) {
+      SculptVertexNeighborIter ni;
+      float sum = 0.0f;
+      int tot = 0;
+
+      SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+        sum += scratch[ni.index];
+        tot++;
+      }
+      SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+      if (tot) {
+        sum /= tot;
+      }
+
+      factor[i] = (sum + factor[i]) * 0.5f;
+    }
+  }
+
+  if (boundary_propagation_steps > 1) {
+    for (int i = 0; i < tot_vert; i++) {
+      automask_factor[i] *= factor[i];
+    }
+
+    MEM_SAFE_FREE(factor);
+    MEM_SAFE_FREE(scratch);
+  }
+
+  return automask_factor;
+}
+
 #define EDGE_DISTANCE_INF -1
 
 float *SCULPT_boundary_automasking_init(Object *ob,
@@ -315,6 +444,7 @@ static void SCULPT_automasking_cache_settings_update(AutomaskingCache *automaski
 {
   automasking->settings.flags = sculpt_automasking_mode_effective_bits(sd, brush);
   automasking->settings.initial_face_set = SCULPT_active_face_set_get(ss);
+  automasking->settings.cavity_factor = brush->automasking_cavity_factor;
 }
 
 AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob)
@@ -352,6 +482,12 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
     sculpt_face_sets_automasking_init(sd, ob, automasking->factor);
   }
 
+  if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_CAVITY)) {
+    SCULPT_vertex_random_access_ensure(ss);
+    sculpt_cavity_automasking_init(
+        sd, ob, automasking, automasking->factor, boundary_propagation_steps);
+  }
+
   if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
     SCULPT_vertex_random_access_ensure(ss);
     SCULPT_boundary_automaski

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list