[Bf-blender-cvs] [c5ab67e8144] temp-sculpt-cavity-mask: temp-sculpt-cavity-mask: Reuse cavity mask across strokes

Joseph Eagar noreply at git.blender.org
Fri Sep 23 03:38:46 CEST 2022


Commit: c5ab67e8144fc40360a617d03a62a6e640c1eefc
Author: Joseph Eagar
Date:   Thu Sep 22 18:37:00 2022 -0700
Branches: temp-sculpt-cavity-mask
https://developer.blender.org/rBc5ab67e8144fc40360a617d03a62a6e640c1eefc

temp-sculpt-cavity-mask: Reuse cavity mask across strokes

* Cavity mask cache can now be reused across strokes.
  This is done by hashing the automasking settings to see
  if anything's changed.  Note: reuse only happens for
  sculpt tools that don't modify the mesh (e.g. paint).

* Cavity cache uses new attribute API.

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

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/intern/paint.cc
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_automasking.cc
M	source/blender/editors/sculpt_paint/sculpt_expand.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h

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

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index c41f5f68c17..b2750059f46 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -558,6 +558,9 @@ typedef struct SculptAttributePointers {
   /* BMesh */
   SculptAttribute *dyntopo_node_id_vertex;
   SculptAttribute *dyntopo_node_id_face;
+
+  SculptAttribute *stroke_id;
+  SculptAttribute *cavity;
 } SculptAttributePointers;
 
 typedef struct SculptSession {
@@ -750,8 +753,8 @@ typedef struct SculptSession {
   char *last_paint_canvas_key;
 
   int stroke_id;
-
-  CavityMaskData *cavity;
+  int last_automasking_settings_hash;
+  int last_cavity_stroke_id;
 } SculptSession;
 
 void BKE_sculptsession_free(struct Object *ob);
diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc
index bdd851bca1d..4cfbfd7a0c5 100644
--- a/source/blender/blenkernel/intern/paint.cc
+++ b/source/blender/blenkernel/intern/paint.cc
@@ -1535,7 +1535,6 @@ 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);
 
     MEM_freeN(ss);
 
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index c5a7d8dae98..3679f026502 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -3365,6 +3365,8 @@ static void do_brush_action(Sculpt *sd,
       /* Initialize auto-masking cache. */
       if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
         ss->cache->automasking = SCULPT_automasking_cache_init(sd, brush, ob);
+        ss->last_automasking_settings_hash = SCULPT_automasking_settings_hash(
+            ob, ss->cache->automasking);
       }
       /* Initialize surface smooth cache. */
       if ((brush->sculpt_tool == SCULPT_TOOL_SMOOTH) &&
@@ -3547,6 +3549,11 @@ static void do_brush_action(Sculpt *sd,
     SCULPT_bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor);
   }
 
+  if (!SCULPT_tool_can_reuse_cavity_mask(brush->sculpt_tool) || (ss->cache->supports_gravity && sd->gravity_factor > 0.0f)) {
+    /* Clear cavity mask cache. */
+    ss->last_automasking_settings_hash = 0;
+  }
+
   /* The cloth brush adds the gravity as a regular force and it is processed in the solver. */
   if (ss->cache->supports_gravity && !ELEM(brush->sculpt_tool,
                                            SCULPT_TOOL_CLOTH,
@@ -6005,4 +6012,16 @@ void SCULPT_fake_neighbors_free(Object *ob)
   sculpt_pose_fake_neighbors_free(ss);
 }
 
+void SCULPT_stroke_id_ensure(Object *ob)
+{
+  SculptSession *ss = ob->sculpt;
+
+  if (!ss->attrs.stroke_id) {
+    SculptAttributeParams params = {0};
+
+    ss->attrs.stroke_id = BKE_sculpt_attribute_ensure(
+        ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, SCULPT_ATTRIBUTE_NAME(stroke_id), &params);
+  }
+}
+
 /** \} */
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.cc b/source/blender/editors/sculpt_paint/sculpt_automasking.cc
index c0aadd49b3a..809796f1af3 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc
@@ -114,6 +114,11 @@ static int sculpt_automasking_mode_effective_bits(const Sculpt *sculpt, const Br
                  BRUSH_AUTOMASKING_CAVITY_NORMAL);
       flags |= brush->automasking_flags;
     }
+    else if (sculpt->automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
+      flags &= ~(BRUSH_AUTOMASKING_CAVITY_ALL | BRUSH_AUTOMASKING_CAVITY_USE_CURVE |
+                 BRUSH_AUTOMASKING_CAVITY_NORMAL);
+      flags |= sculpt->automasking_flags;
+    }
 
     return flags;
   }
@@ -348,23 +353,54 @@ static void sculpt_calc_blurred_cavity(SculptSession *ss,
 
   factor_sum = sculpt_cavity_calc_factor(ss, automasking, factor_sum);
 
-  int index = BKE_pbvh_vertex_to_index(ss->pbvh, vertex);
+  *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.cavity) = factor_sum;
+  *(int *)SCULPT_vertex_attr_get(vertex, ss->attrs.stroke_id) = automasking->cavity_stroke_id;
+}
+
+int SCULPT_automasking_settings_hash(Object *ob, AutomaskingCache *automasking)
+{
+  SculptSession *ss = ob->sculpt;
+
+  int hash;
+  int totvert = SCULPT_vertex_count_get(ss);
+
+  hash = BLI_hash_int(automasking->settings.flags);
+  hash = BLI_hash_int_2d(hash, totvert);
+
+  if (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
+    hash = BLI_hash_int_2d(hash, automasking->settings.cavity_blur_steps);
+    hash = BLI_hash_int_2d(hash, (int)(automasking->settings.cavity_factor * 5000.0f));
+
+    if (automasking->settings.cavity_curve) {
+      CurveMap *cm = automasking->settings.cavity_curve->cm;
 
-  ss->cavity[index].factor = factor_sum;
-  ss->cavity[index].stroke_id = ss->stroke_id;
+      for (int i = 0; i < cm->totpoint; i++) {
+        hash = BLI_hash_int_2d(hash, (int)(cm->curve[i].x * 5000.0f));
+        hash = BLI_hash_int_2d(hash, (int)(cm->curve[i].y * 5000.0f));
+        hash = BLI_hash_int_2d(hash, (int)cm->curve[i].flag);
+        hash = BLI_hash_int_2d(hash, (int)cm->curve[i].shorty);
+      }
+    }
+  }
+
+  if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
+    hash = BLI_hash_int_2d(hash, automasking->settings.initial_face_set);
+  }
+
+  return hash;
 }
 
 static float sculpt_automasking_cavity_factor(AutomaskingCache *automasking,
                                               SculptSession *ss,
                                               PBVHVertRef vertex)
 {
-  int index = BKE_pbvh_vertex_to_index(ss->pbvh, vertex);
+  int stroke_id = *(int *)SCULPT_vertex_attr_get(vertex, ss->attrs.stroke_id);
 
-  if (ss->cavity[index].stroke_id != ss->stroke_id) {
+  if (stroke_id != automasking->cavity_stroke_id) {
     sculpt_calc_blurred_cavity(ss, automasking, automasking->settings.cavity_blur_steps, vertex);
   }
 
-  float factor = ss->cavity[index].factor;
+  float factor = *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.cavity);
   bool inverted = automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_INVERTED;
 
   if ((automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) &&
@@ -540,17 +576,6 @@ static void sculpt_cavity_automasking_init(Sculpt *sd, Object *ob, AutomaskingCa
     BLI_assert_msg(0, "Cavity mask automasking: pmap missing");
     return;
   }
-
-  int tot_vert = SCULPT_vertex_count_get(ss);
-
-  if (!ss->cavity) {
-    ss->cavity = static_cast<CavityMaskData *>(
-        MEM_malloc_arrayN(tot_vert, sizeof(CavityMaskData), __func__));
-
-    for (int i = 0; i < tot_vert; i++) {
-      ss->cavity[i].stroke_id = -1;
-    }
-  }
 }
 
 #define EDGE_DISTANCE_INF -1
@@ -640,17 +665,20 @@ static void SCULPT_automasking_cache_settings_update(AutomaskingCache *automaski
   }
 }
 
+bool SCULPT_tool_can_reuse_cavity_mask(int sculpt_tool)
+{
+  return ELEM(sculpt_tool,
+              SCULPT_TOOL_PAINT,
+              SCULPT_TOOL_SMEAR,
+              SCULPT_TOOL_MASK,
+              SCULPT_TOOL_DRAW_FACE_SETS);
+}
+
 AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob)
 {
   SculptSession *ss = ob->sculpt;
   const int totvert = SCULPT_vertex_count_get(ss);
 
-  if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_CAVITY_ALL) &&
-      SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_CAVITY_USE_CURVE)) {
-    BKE_curvemapping_init(brush->automasking_cavity_curve);
-    BKE_curvemapping_init(sd->automasking_cavity_curve);
-  }
-
   if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
     return nullptr;
   }
@@ -661,8 +689,32 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
   SCULPT_boundary_info_ensure(ob);
 
   if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_CAVITY_ALL)) {
-    SCULPT_vertex_random_access_ensure(ss);
-    sculpt_cavity_automasking_init(sd, ob, automasking);
+    if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_CAVITY_USE_CURVE)) {
+      BKE_curvemapping_init(brush->automasking_cavity_curve);
+      BKE_curvemapping_init(sd->automasking_cavity_curve);
+    }
+
+    SCULPT_stroke_id_ensure(ob);
+    automasking->cavity_stroke_id = ss->stroke_id;
+
+    if (!ss->attrs.cavity) {
+      SculptAttributeParams params = {0};
+      ss->attrs.cavity = BKE_sculpt_attribute_ensure(
+          ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, SCULPT_ATTRIBUTE_NAME(cavity), &params);
+    }
+    /* Can we reuse the previous stroke's cavity mask? */
+    else if (brush && SCULPT_tool_can_reuse_cavity_mask(brush->sculpt_tool)) {
+      int hash = SCULPT_automasking_settings_hash(ob, automasking);
+
+      if (hash == ss->last_automasking_settings_hash) {
+        automasking->cavity_stroke_id = ss->last_automasking_settings_hash;
+        automasking->can_reuse_cavity = true;
+      }
+    }
+
+    if (!automasking->can_reuse_cavity) {
+      ss->last_cavity_stroke_id = ss->stroke_id;
+    }
   }
 
   if (!SCULPT_automasking_needs_factors_cache(sd, brush)) {
@@ -703,6 +755,10 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
     SCULPT_boundary_automasking_init(
         ob, AUTOMASK_INIT_BOUNDARY_FACE_SETS, boundary_propagation_steps);
   }
+  if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_CAVITY_ALL)) {
+    SCULPT_vertex_random_access_ensure(ss);
+    sculpt_cavity_automasking_init(sd, ob, automasking);
+  }
 
   return automasking;
 }
diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c
index 72b0b3a97fe..ef2b0b5959d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_expand.c
@@ -2102,6 +2102,8 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
   SculptSession *ss = ob->sculpt;
   Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
 
+  ss->stroke_id++;
+
   /* Create and configure the Expand Cache. */
   ss->expand_cache = MEM_callocN(sizeof(ExpandCache), "expand cache");
   sculpt_expand_cache_initial_config_set(C, op, ss->expand_cache);
diff --git a/so

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list