[Bf-blender-cvs] [371708737a6] temp-sculpt-cavity-mask: temp-sculpt-cavity-mask: Add caching

Joseph Eagar noreply at git.blender.org
Sun Jun 5 02:57:21 CEST 2022


Commit: 371708737a63a5e11a16e34ffed18da1afc74051
Author: Joseph Eagar
Date:   Sat Jun 4 17:46:27 2022 -0700
Branches: temp-sculpt-cavity-mask
https://developer.blender.org/rB371708737a63a5e11a16e34ffed18da1afc74051

temp-sculpt-cavity-mask: Add caching

Cavity masking now builds and caches values on demand.  It
does this by using two temporary attributes:
one for the final cavity mask and another for a stroke id.
The stroke id attribute is used to detect when verts need
to recalulate their cavity mask value; its values are compared
to a global stroke id that's generated at the beginning of each
stroke.

Notes:
* Cavity mask blurring now happens with a breadth-first walk
  per-vertex.
* The "attributes" are currently just simple arrays inside
  of the Sculpt struct; later on they'll use the planned
  sculpt temporary attribute api.
* I wasn't able to find a small-buffer-optimized queue class,
  so the queue logic is all manual (it uses a blender::Vector).
* sculpt_automasking.c is now compiled with C++.

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

M	release/scripts/addons
M	release/scripts/addons_contrib
M	release/scripts/startup/bl_ui/properties_paint_common.py
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/intern/paint.c
M	source/blender/editors/sculpt_paint/CMakeLists.txt
M	source/blender/editors/sculpt_paint/sculpt.c
R071	source/blender/editors/sculpt_paint/sculpt_automasking.c	source/blender/editors/sculpt_paint/sculpt_automasking.cc
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/makesdna/DNA_brush_types.h
M	source/blender/makesrna/intern/rna_brush.c
M	source/tools

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

diff --git a/release/scripts/addons b/release/scripts/addons
index bcb71eea69a..6a318b22d14 160000
--- a/release/scripts/addons
+++ b/release/scripts/addons
@@ -1 +1 @@
-Subproject commit bcb71eea69a7b83c44112a5872ccd67cae96ec6f
+Subproject commit 6a318b22d143f675ad489171a2b9aa56d9a6c1b6
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
index 61efd17f87b..9406de5f312 160000
--- a/release/scripts/addons_contrib
+++ b/release/scripts/addons_contrib
@@ -1 +1 @@
-Subproject commit 61efd17f87b45c3049091127a5619219f9d2a821
+Subproject commit 9406de5f31254c0c608ba8785fd3dcad12dcd7c4
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index a37c6814424..2ed0f33753b 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -951,6 +951,7 @@ def brush_settings_advanced(layout, context, brush, popover=False):
         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_cavity_blur_steps", text="Cavity Blur")
 
         col.prop(brush, "automasking_boundary_edges_propagation_steps")
 
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index a47e4a24f75..e3260c3f67a 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -659,6 +659,10 @@ typedef struct SculptSession {
    */
   char *last_paint_canvas_key;
 
+  int stroke_id;
+
+  float *cavity_factor;
+  int *cavity_stroke_id;
 } SculptSession;
 
 void BKE_sculptsession_free(struct Object *ob);
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index bb499f24c07..cfbcbe35338 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1514,6 +1514,8 @@ void BKE_sculptsession_free(Object *ob)
     BKE_sculptsession_free_vwpaint_data(ob->sculpt);
 
     MEM_SAFE_FREE(ss->last_paint_canvas_key);
+    MEM_SAFE_FREE(ss->cavity_factor);
+    MEM_SAFE_FREE(ss->cavity_stroke_id);
 
     MEM_freeN(ss);
 
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index dfd8f8b1bb9..bd1fb8476d5 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -57,7 +57,7 @@ set(SRC
   paint_vertex_weight_ops.c
   paint_vertex_weight_utils.c
   sculpt.c
-  sculpt_automasking.c
+  sculpt_automasking.cc
   sculpt_boundary.c
   sculpt_brush_types.c
   sculpt_cloth.c
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index d9209b65276..bcca01cc634 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4188,6 +4188,8 @@ static void sculpt_update_cache_invariants(
 
   ss->cache = cache;
 
+  cache->stroke_id = ss->stroke_id;
+
   /* Set scaling adjustment. */
   max_scale = 0.0f;
   for (int i = 0; i < 3; i++) {
@@ -5343,6 +5345,8 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
       SCULPT_undo_push_begin(ob, sculpt_tool_name(sd));
     }
 
+    ss->stroke_id++;
+
     return true;
   }
   return false;
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.cc
similarity index 71%
rename from source/blender/editors/sculpt_paint/sculpt_automasking.c
rename to source/blender/editors/sculpt_paint/sculpt_automasking.cc
index 4358abad81e..28ba6bc9ca5 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.c
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc
@@ -7,10 +7,14 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_array.hh"
 #include "BLI_blenlib.h"
 #include "BLI_hash.h"
+#include "BLI_index_range.hh"
 #include "BLI_math.h"
+#include "BLI_set.hh"
 #include "BLI_task.h"
+#include "BLI_vector.hh"
 
 #include "DNA_brush_types.h"
 #include "DNA_mesh_types.h"
@@ -46,6 +50,21 @@
 #include <math.h>
 #include <stdlib.h>
 
+/* Disable optimization for a function (for debugging use only!)*/
+#ifdef __clang__
+#  define ATTR_NO_OPT __attribute__((optnone))
+#elif defined(_MSC_VER)
+#  define ATTR_NO_OPT __pragma(optimize("", off))
+#elif defined(__GNUC__)
+#  define ATTR_NO_OPT __attribute__((optimize("O0")))
+#else
+#  define ATTR_NO_OPT
+#endif
+
+using blender::IndexRange;
+using blender::Set;
+using blender::Vector;
+
 AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss)
 {
   if (ss->cache) {
@@ -106,8 +125,8 @@ 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_FACE_SETS |
-                           BRUSH_AUTOMASKING_BOUNDARY_EDGES | BRUSH_AUTOMASKING_CAVITY)) {
+  if (automasking_flags &
+      (BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS | BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
     return brush && brush->automasking_boundary_edges_propagation_steps != 1;
   }
   return false;
@@ -151,9 +170,9 @@ float SCULPT_calc_cavity(SculptSession *ss, const int vertex)
   return factor;
 }
 
-static float sculpt_automasking_cavity_factor(AutomaskingCache *automasking,
-                                              SculptSession *ss,
-                                              int vert)
+ATTR_NO_OPT static float sculpt_automasking_cavity_factor_intern(SculptSession *ss,
+                                                                 AutomaskingCache *automasking,
+                                                                 int vert)
 {
   float factor = SCULPT_calc_cavity(ss, vert);
   float sign = signf(factor);
@@ -166,6 +185,127 @@ static float sculpt_automasking_cavity_factor(AutomaskingCache *automasking,
   return (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_INVERT) ? 1.0f - factor : factor;
 }
 
+struct CavityBlurVert {
+  int vertex;
+  float dist;
+  int depth;
+
+  CavityBlurVert(int vertex_, float dist_, int depth_)
+      : vertex(vertex_), dist(dist_), depth(depth_)
+  {
+  }
+
+  CavityBlurVert()
+  {
+  }
+
+  CavityBlurVert(const CavityBlurVert &b)
+  {
+    vertex = b.vertex;
+    dist = b.dist;
+    depth = b.depth;
+  }
+};
+
+ATTR_NO_OPT static void sculpt_calc_blurred_cavity(SculptSession *ss,
+                                                   AutomaskingCache *automasking,
+                                                   int steps,
+                                                   int vertex)
+{
+  if (steps == 0) {
+    ss->cavity_factor[vertex] = sculpt_automasking_cavity_factor_intern(ss, automasking, vertex);
+    ss->cavity_stroke_id[vertex] = ss->stroke_id;
+
+    return;
+  }
+
+  Vector<CavityBlurVert, 64> queue;
+  Set<int, 64> visit;
+
+  int start = 0, end = 0;
+
+  queue.resize(64);
+
+  CavityBlurVert initial(vertex, 0.0f, 0);
+
+  visit.add_new(vertex);
+  queue[0] = initial;
+  end = 1;
+
+  float f_sum = 0.0f;
+  int f_num = 0;
+
+  f_sum += sculpt_automasking_cavity_factor_intern(ss, automasking, vertex);
+  f_num++;
+
+  while (start != end) {
+    CavityBlurVert &blurvert = queue[start];
+    int v = blurvert.vertex;
+    start = (start + 1) % queue.size();
+
+    if (blurvert.depth >= steps) {
+      break;
+    }
+
+    SculptVertexNeighborIter ni;
+    SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v, ni) {
+      int v2 = ni.index;
+
+      if (visit.contains(v2)) {
+        continue;
+      }
+
+      float dist = len_v3v3(SCULPT_vertex_co_get(ss, v2), SCULPT_vertex_co_get(ss, v));
+
+      f_sum += sculpt_automasking_cavity_factor_intern(ss, automasking, v2);
+      f_num++;
+
+      visit.add_new(v2);
+      CavityBlurVert blurvert2(v2, dist, blurvert.depth + 1);
+
+      int nextend = (end + 1) % queue.size();
+
+      if (nextend == start) {
+        int oldsize = queue.size();
+
+        queue.resize(queue.size() << 1);
+
+        if (end < start) {
+          int n = oldsize - start;
+
+          for (int i = 0; i < n; i++) {
+            queue[queue.size() - n + i] = queue[i + start];
+          }
+
+          start = queue.size() - n;
+        }
+      }
+
+      queue[end] = blurvert2;
+      end = (end + 1) % queue.size();
+    }
+    SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+  }
+
+  if (f_num != 0.0f) {
+    f_sum /= f_num;
+  }
+
+  ss->cavity_factor[vertex] = f_sum;
+  ss->cavity_stroke_id[vertex] = ss->stroke_id;
+}
+
+ATTR_NO_OPT static float sculpt_automasking_cavity_factor(AutomaskingCache *automasking,
+                                                          SculptSession *ss,
+                                                          int vertex)
+{
+  if (ss->cavity_stroke_id[vertex] != ss->stroke_id) {
+    sculpt_calc_blurred_cavity(ss, automasking, automasking->settings.cavity_blur_steps, vertex);
+  }
+
+  return ss->cavity_factor[vertex];
+}
+
 float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
 {
   if (!automasking) {
@@ -175,7 +315,13 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession
    * automasking information can't be computed in real time per vertex and needs to be
    * initialized for the whole mesh when the stroke starts. */
   if (automasking->factor) {
-    return automasking->factor[vert];
+    float factor = automasking->factor[vert];
+
+    if (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY) {
+      factor *= sculpt_automasking_cavity_factor(automasking, ss, vert);
+    }
+
+    return factor;
   }
 
   if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
@@ -237,7 +383,7 @@ typedef struct AutomaskFloodFillData {
 static bool automask_floodfill_cb(
     SculptSession *ss, int from_v, int to_v, bool UNUSED(is_duplicate), void *userdata)
 {
-  AutomaskFloodFillData *data = userdata;
+  AutomaskFloodFillData *data = static_cast<AutomaskFloodFillData *>(userdata);
 
   data->aut

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list