[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), ¶ms);
+ }
+}
+
/** \} */
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), ¶ms);
+ }
+ /* 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