Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/sculpt_paint')
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_automasking.c118
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_color.c26
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c74
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h31
6 files changed, 150 insertions, 121 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 8a9d1bba92c..4e15728b081 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -2506,7 +2506,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
avg *= 1.0f - mask;
/* Auto-masking. */
- avg *= SCULPT_automasking_factor_get(ss, vertex_index);
+ avg *= SCULPT_automasking_factor_get(cache->automasking, ss, vertex_index);
return avg;
}
@@ -3908,7 +3908,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
mul_v3_fl(final_disp, 1.0f - *vd.mask);
}
- mul_v3_fl(final_disp, SCULPT_automasking_factor_get(ss, vd.index));
+ mul_v3_fl(final_disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index));
copy_v3_v3(proxy[vd.i], final_disp);
@@ -5760,7 +5760,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
- SCULPT_automasking_init(sd, ob);
+ ss->cache->automasking = SCULPT_automasking_cache_init(sd, brush, ob);
}
}
@@ -7764,7 +7764,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
}
if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
- SCULPT_automasking_end(ob);
+ SCULPT_automasking_cache_free(ss->cache->automasking);
}
BKE_pbvh_node_color_buffer_free(ss->pbvh);
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c
index 241f1167316..f2fc1bcb3c9 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.c
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c
@@ -62,16 +62,30 @@
#include <math.h>
#include <stdlib.h>
+AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss)
+{
+ if (ss->cache) {
+ return ss->cache->automasking;
+ }
+ else if (ss->filter_cache) {
+ return ss->filter_cache->automasking;
+ }
+ return NULL;
+}
+
bool SCULPT_is_automasking_mode_enabled(const Sculpt *sd,
const Brush *br,
const eAutomasking_flag mode)
{
- return br->automasking_flags & mode || sd->automasking_flags & mode;
+ if (br) {
+ return br->automasking_flags & mode || sd->automasking_flags & mode;
+ }
+ return sd->automasking_flags & mode;
}
bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, const Brush *br)
{
- if (SCULPT_stroke_is_dynamic_topology(ss, br)) {
+ if (br && SCULPT_stroke_is_dynamic_topology(ss, br)) {
return false;
}
if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_TOPOLOGY)) {
@@ -91,10 +105,13 @@ bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, co
static int sculpt_automasking_mode_effective_bits(const Sculpt *sculpt, const Brush *brush)
{
- return sculpt->automasking_flags | brush->automasking_flags;
+ if (brush) {
+ return sculpt->automasking_flags | brush->automasking_flags;
+ }
+ return sculpt->automasking_flags;
}
-static bool SCULPT_automasking_needs_cache(const Sculpt *sd, const Brush *brush)
+static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush *brush)
{
const int automasking_flags = sculpt_automasking_mode_effective_bits(sd, brush);
@@ -102,39 +119,39 @@ static bool SCULPT_automasking_needs_cache(const Sculpt *sd, const Brush *brush)
return true;
}
if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
- return brush->automasking_boundary_edges_propagation_steps != 1;
+ return brush && brush->automasking_boundary_edges_propagation_steps != 1;
}
if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) {
- return brush->automasking_boundary_edges_propagation_steps != 1;
+ return brush && brush->automasking_boundary_edges_propagation_steps != 1;
}
return false;
}
-float SCULPT_automasking_factor_get(SculptSession *ss, int vert)
+float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
{
- if (!ss->cache) {
+ if (!automasking) {
return 1.0f;
}
/* If the cache is initialized with valid info, use the cache. This is used when the
* 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 (ss->cache->automask_factor) {
- return ss->cache->automask_factor[vert];
+ if (automasking->factor) {
+ return automasking->factor[vert];
}
- if (ss->cache->automask_settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
- if (!SCULPT_vertex_has_face_set(ss, vert, ss->cache->automask_settings.initial_face_set)) {
+ if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
+ if (!SCULPT_vertex_has_face_set(ss, vert, automasking->settings.initial_face_set)) {
return 0.0f;
}
}
- if (ss->cache->automask_settings.flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
+ if (automasking->settings.flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
if (SCULPT_vertex_is_boundary(ss, vert)) {
return 0.0f;
}
}
- if (ss->cache->automask_settings.flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) {
+ if (automasking->settings.flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) {
if (!SCULPT_vertex_has_unique_face_set(ss, vert)) {
return 0.0f;
}
@@ -143,12 +160,14 @@ float SCULPT_automasking_factor_get(SculptSession *ss, int vert)
return 1.0f;
}
-void SCULPT_automasking_end(Object *ob)
+void SCULPT_automasking_cache_free(AutomaskingCache *automasking)
{
- SculptSession *ss = ob->sculpt;
- if (ss->cache && ss->cache->automask_factor) {
- MEM_freeN(ss->cache->automask_factor);
+ if (!automasking) {
+ return;
}
+
+ MEM_SAFE_FREE(automasking->factor);
+ MEM_SAFE_FREE(automasking);
}
static bool sculpt_automasking_is_constrained_by_radius(Brush *br)
@@ -189,10 +208,6 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
- return NULL;
- }
-
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
BLI_assert(!"Topology masking: pmap missing");
return NULL;
@@ -200,19 +215,20 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au
const int totvert = SCULPT_vertex_count_get(ss);
for (int i = 0; i < totvert; i++) {
- ss->cache->automask_factor[i] = 0.0f;
+ automask_factor[i] = 0.0f;
}
/* Flood fill automask to connected vertices. Limited to vertices inside
* the brush radius if the tool requires it. */
SculptFloodFill flood;
SCULPT_floodfill_init(ss, &flood);
- SCULPT_floodfill_add_active(sd, ob, ss, &flood, ss->cache->radius);
+ const float radius = ss->cache ? ss->cache->radius : FLT_MAX;
+ SCULPT_floodfill_add_active(sd, ob, ss, &flood, radius);
AutomaskFloodFillData fdata = {
.automask_factor = automask_factor,
- .radius = ss->cache->radius,
- .use_radius = sculpt_automasking_is_constrained_by_radius(brush),
+ .radius = radius,
+ .use_radius = ss->cache && sculpt_automasking_is_constrained_by_radius(brush),
.symm = SCULPT_mesh_symmetry_xyz_get(ob),
};
copy_v3_v3(fdata.location, SCULPT_active_vertex_co_get(ss));
@@ -306,58 +322,60 @@ float *SCULPT_boundary_automasking_init(Object *ob,
return automask_factor;
}
-static void SCULPT_stroke_automasking_settings_update(SculptSession *ss, Sculpt *sd, Brush *brush)
+static void SCULPT_automasking_cache_settings_update(AutomaskingCache *automasking,
+ SculptSession *ss,
+ Sculpt *sd,
+ Brush *brush)
{
- BLI_assert(ss->cache);
-
- ss->cache->automask_settings.flags = sculpt_automasking_mode_effective_bits(sd, brush);
- ss->cache->automask_settings.initial_face_set = SCULPT_active_face_set_get(ss);
+ automasking->settings.flags = sculpt_automasking_mode_effective_bits(sd, brush);
+ automasking->settings.initial_face_set = SCULPT_active_face_set_get(ss);
}
-void SCULPT_automasking_init(Sculpt *sd, Object *ob)
+AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob)
{
SculptSession *ss = ob->sculpt;
- Brush *brush = BKE_paint_brush(&sd->paint);
const int totvert = SCULPT_vertex_count_get(ss);
if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
- return;
+ return NULL;
}
- SCULPT_stroke_automasking_settings_update(ss, sd, brush);
+ AutomaskingCache *automasking = MEM_callocN(sizeof(AutomaskingCache), "automasking cache");
+ SCULPT_automasking_cache_settings_update(automasking, ss, sd, brush);
SCULPT_boundary_info_ensure(ob);
- if (!SCULPT_automasking_needs_cache(sd, brush)) {
- return;
+ if (!SCULPT_automasking_needs_factors_cache(sd, brush)) {
+ return automasking;
}
- ss->cache->automask_factor = MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor");
-
+ automasking->factor = MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor");
for (int i = 0; i < totvert; i++) {
- ss->cache->automask_factor[i] = 1.0f;
+ automasking->factor[i] = 1.0f;
}
+ const int boundary_propagation_steps = brush ?
+ brush->automasking_boundary_edges_propagation_steps :
+ 1;
+
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) {
SCULPT_vertex_random_access_ensure(ss);
- SCULPT_topology_automasking_init(sd, ob, ss->cache->automask_factor);
+ SCULPT_topology_automasking_init(sd, ob, automasking->factor);
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) {
SCULPT_vertex_random_access_ensure(ss);
- sculpt_face_sets_automasking_init(sd, ob, ss->cache->automask_factor);
+ sculpt_face_sets_automasking_init(sd, ob, automasking->factor);
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
SCULPT_vertex_random_access_ensure(ss);
- SCULPT_boundary_automasking_init(ob,
- AUTOMASK_INIT_BOUNDARY_EDGES,
- brush->automasking_boundary_edges_propagation_steps,
- ss->cache->automask_factor);
+ SCULPT_boundary_automasking_init(
+ ob, AUTOMASK_INIT_BOUNDARY_EDGES, boundary_propagation_steps, automasking->factor);
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
SCULPT_vertex_random_access_ensure(ss);
- SCULPT_boundary_automasking_init(ob,
- AUTOMASK_INIT_BOUNDARY_FACE_SETS,
- brush->automasking_boundary_edges_propagation_steps,
- ss->cache->automask_factor);
+ SCULPT_boundary_automasking_init(
+ ob, AUTOMASK_INIT_BOUNDARY_FACE_SETS, boundary_propagation_steps, automasking->factor);
}
+
+ return automasking;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 84d156122f3..efd80eef0cb 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -723,6 +723,8 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
return;
}
+ AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss);
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
float sim_location[3];
@@ -743,7 +745,7 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor);
const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) *
- SCULPT_automasking_factor_get(ss, vd.index);
+ SCULPT_automasking_factor_get(automasking, ss, vd.index);
madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v);
madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v);
@@ -775,6 +777,9 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
Brush *brush,
SculptClothSimulation *cloth_sim)
{
+
+ AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss);
+
for (int constraint_it = 0; constraint_it < CLOTH_SIMULATION_ITERATIONS; constraint_it++) {
for (int i = 0; i < cloth_sim->tot_length_constraints; i++) {
const SculptClothLengthConstraint *constraint = &cloth_sim->length_constraints[i];
@@ -807,9 +812,9 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
mul_v3_v3fl(correction_vector_half, correction_vector, 0.5f);
const float mask_v1 = (1.0f - SCULPT_vertex_mask_get(ss, v1)) *
- SCULPT_automasking_factor_get(ss, v1);
+ SCULPT_automasking_factor_get(automasking, ss, v1);
const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2)) *
- SCULPT_automasking_factor_get(ss, v2);
+ SCULPT_automasking_factor_get(automasking, ss, v2);
float sim_location[3];
cloth_brush_simulation_location_get(ss, brush, sim_location);
@@ -1354,6 +1359,7 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
{
float fade = vd.mask ? *vd.mask : 0.0f;
+ fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
fade = 1.0f - fade;
float force[3] = {0.0f, 0.0f, 0.0f};
float disp[3], temp[3], transform[3][3];
@@ -1498,6 +1504,8 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_undo_push_begin("Cloth filter");
SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
+ ss->filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
+
const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass");
const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping");
const bool use_collisions = RNA_boolean_get(op->ptr, "use_collisions");
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
index 89af836d095..07986bbb032 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
@@ -119,6 +119,10 @@ static void color_filter_task_cb(void *__restrict userdata,
float fade = vd.mask ? *vd.mask : 0.0f;
fade = 1.0f - fade;
fade *= data->filter_strength;
+ fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
+ if (fade == 0.0f) {
+ continue;
+ }
copy_v3_v3(orig_color, orig_data.col);
@@ -255,7 +259,7 @@ static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_RUNNING_MODAL;
}
-static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *ob = CTX_data_active_object(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
@@ -263,6 +267,17 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
int mode = RNA_enum_get(op->ptr, "type");
PBVH *pbvh = ob->sculpt->pbvh;
+ const bool use_automasking = SCULPT_is_automasking_enabled(sd, ss, NULL);
+ if (use_automasking) {
+ /* Update the active face set manually as the paint cursor is not enabled when using the Mesh
+ * Filter Tool. */
+ float mouse[2];
+ SculptCursorGeometryInfo sgi;
+ mouse[0] = event->mval[0];
+ mouse[1] = event->mval[1];
+ SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
+ }
+
/* Disable for multires and dyntopo for now */
if (!ss->pbvh) {
return OPERATOR_CANCELLED;
@@ -282,14 +297,17 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
/* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of
* earlier steps modifying the data. */
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- bool needs_pmap = mode == COLOR_FILTER_SMOOTH;
- BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, true);
+ const bool needs_topology_info = mode == COLOR_FILTER_SMOOTH || use_automasking;
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_topology_info, false, true);
- if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_pmap && !ob->sculpt->pmap) {
+ if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_topology_info && !ob->sculpt->pmap) {
return OPERATOR_CANCELLED;
}
SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COLOR);
+ FilterCache *filter_cache = ss->filter_cache;
+ filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
+ filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index c2e90638994..349e492a496 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -179,12 +179,14 @@ void SCULPT_filter_cache_free(SculptSession *ss)
if (ss->filter_cache->cloth_sim) {
SCULPT_cloth_simulation_free(ss->filter_cache->cloth_sim);
}
+ if (ss->filter_cache->automasking) {
+ SCULPT_automasking_cache_free(ss->filter_cache->automasking);
+ }
MEM_SAFE_FREE(ss->filter_cache->nodes);
MEM_SAFE_FREE(ss->filter_cache->mask_update_it);
MEM_SAFE_FREE(ss->filter_cache->prev_mask);
MEM_SAFE_FREE(ss->filter_cache->normal_factor);
MEM_SAFE_FREE(ss->filter_cache->prev_face_set);
- MEM_SAFE_FREE(ss->filter_cache->automask);
MEM_SAFE_FREE(ss->filter_cache->surface_smooth_laplacian_disp);
MEM_SAFE_FREE(ss->filter_cache->sharpen_factor);
MEM_SAFE_FREE(ss->filter_cache->detail_directions);
@@ -269,15 +271,15 @@ static EnumPropertyItem prop_mesh_filter_orientation_items[] = {
{0, NULL, 0, NULL, NULL},
};
-static bool sculpt_mesh_filter_needs_pmap(eSculptMeshFilterType filter_type, bool use_face_sets)
+static bool sculpt_mesh_filter_needs_pmap(eSculptMeshFilterType filter_type)
{
- return use_face_sets || ELEM(filter_type,
- MESH_FILTER_SMOOTH,
- MESH_FILTER_RELAX,
- MESH_FILTER_RELAX_FACE_SETS,
- MESH_FILTER_SURFACE_SMOOTH,
- MESH_FILTER_ENHANCE_DETAILS,
- MESH_FILTER_SHARPEN);
+ return ELEM(filter_type,
+ MESH_FILTER_SMOOTH,
+ MESH_FILTER_RELAX,
+ MESH_FILTER_RELAX_FACE_SETS,
+ MESH_FILTER_SURFACE_SMOOTH,
+ MESH_FILTER_ENHANCE_DETAILS,
+ MESH_FILTER_SHARPEN);
}
static void mesh_filter_task_cb(void *__restrict userdata,
@@ -307,33 +309,16 @@ static void mesh_filter_task_cb(void *__restrict userdata,
float fade = vd.mask ? *vd.mask : 0.0f;
fade = 1.0f - fade;
fade *= data->filter_strength;
+ fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
- if (fade == 0.0f) {
+ if (fade == 0.0f && filter_type != MESH_FILTER_SURFACE_SMOOTH) {
+ /* Surface Smooth can't skip the loop for this vertex as it needs to calculate its
+ * laplacian_disp. This value is accessed from the vertex neighbors when deforming the
+ * vertices, so it is needed for all vertices even if they are not going to be displaced.
+ */
continue;
}
- if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) {
- if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) {
- /* Surface Smooth can't skip the loop for this vertex as it needs to calculate its
- * laplacian_disp. This value is accessed from the vertex neighbors when deforming the
- * vertices, so it is needed for all vertices even if they are not going to be displaced.
- */
- if (filter_type == MESH_FILTER_SURFACE_SMOOTH) {
- fade = 0.0f;
- }
- else {
- continue;
- }
- }
- /* Skip the edges of the face set when relaxing or smoothing.
- * There is a relax face set option to relax the boundaries independently. */
- if (filter_type == MESH_FILTER_RELAX) {
- if (!SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
- continue;
- }
- }
- }
-
if (ELEM(filter_type, MESH_FILTER_RELAX, MESH_FILTER_RELAX_FACE_SETS)) {
copy_v3_v3(orig_co, vd.co);
}
@@ -606,16 +591,11 @@ static void mesh_filter_surface_smooth_displace_task_cb(
float fade = vd.mask ? *vd.mask : 0.0f;
fade = 1.0f - fade;
fade *= data->filter_strength;
+ fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
if (fade == 0.0f) {
continue;
}
- if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) {
- if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) {
- continue;
- }
- }
-
SCULPT_surface_smooth_displace_step(ss,
vd.co,
ss->filter_cache->surface_smooth_laplacian_disp,
@@ -634,7 +614,6 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type");
float filter_strength = RNA_float_get(op->ptr, "strength");
- const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
SCULPT_filter_cache_free(ss);
@@ -652,7 +631,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
SCULPT_vertex_random_access_ensure(ss);
- bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets);
+ bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type);
BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, false);
SculptThreadedTaskData data = {
@@ -700,15 +679,15 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
const eMeshFilterDeformAxis deform_axis = RNA_enum_get(op->ptr, "deform_axis");
const eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type");
- const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
- const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets);
+ const bool use_automasking = SCULPT_is_automasking_enabled(sd, ss, NULL);
+ const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type) || use_automasking;
if (deform_axis == 0) {
/* All axis are disabled, so the filter is not going to produce any deformation. */
return OPERATOR_CANCELLED;
}
- if (use_face_sets) {
+ if (use_automasking) {
/* Update the active face set manually as the paint cursor is not enabled when using the Mesh
* Filter Tool. */
float mouse[2];
@@ -729,8 +708,8 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
FilterCache *filter_cache = ss->filter_cache;
- filter_cache->active_face_set = use_face_sets ? SCULPT_active_face_set_get(ss) :
- SCULPT_FACE_SET_NONE;
+ filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
+ filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
switch (filter_type) {
case MESH_FILTER_SURFACE_SMOOTH: {
@@ -808,11 +787,6 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
SCULPT_FILTER_ORIENTATION_LOCAL,
"Orientation",
"Orientation of the axis to limit the filter displacement");
- ot->prop = RNA_def_boolean(ot->srna,
- "use_face_sets",
- false,
- "Use Face Sets",
- "Apply the filter only to the Face Mask under the cursor");
/* Surface Smooth Mesh Filter properties. */
RNA_def_float(ot->srna,
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 6cdaafb548c..1fddfc7d6db 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -36,6 +36,7 @@
#include "BKE_paint.h"
#include "BKE_pbvh.h"
+struct AutomaskingCache;
struct KeyBlock;
struct Object;
struct SculptPoseIKChainSegment;
@@ -329,10 +330,16 @@ enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob);
void SCULPT_pbvh_clear(Object *ob);
/* Automasking. */
-float SCULPT_automasking_factor_get(SculptSession *ss, int vert);
+float SCULPT_automasking_factor_get(struct AutomaskingCache *automasking,
+ SculptSession *ss,
+ int vert);
-void SCULPT_automasking_init(Sculpt *sd, Object *ob);
-void SCULPT_automasking_end(Object *ob);
+/* Returns the automasking cache depending on the active tool. Used for code that can run both for
+ * brushes and filter. */
+struct AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss);
+
+struct AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob);
+void SCULPT_automasking_cache_free(struct AutomaskingCache *automasking);
bool SCULPT_is_automasking_mode_enabled(const Sculpt *sd,
const Brush *br,
@@ -826,6 +833,13 @@ typedef struct AutomaskingSettings {
int initial_face_set;
} AutomaskingSettings;
+typedef struct AutomaskingCache {
+ AutomaskingSettings settings;
+ /* Precomputed automask factor indexed by vertex, owned by the automasking system and initialized
+ * in SCULPT_automasking_cache_init when needed. */
+ float *factor;
+} AutomaskingCache;
+
typedef struct StrokeCache {
/* Invariants */
float initial_radius;
@@ -966,10 +980,7 @@ typedef struct StrokeCache {
float gravity_direction[3];
/* Automasking. */
- AutomaskingSettings automask_settings;
- /* Precomputed automask factor indexed by vertex, owned by the automasking system and initialized
- * in SCULPT_automasking_init when needed. */
- float *automask_factor;
+ AutomaskingCache *automasking;
float stroke_local_mat[4][4];
float multiplane_scrape_angle;
@@ -1041,13 +1052,13 @@ typedef struct FilterCache {
float *prev_mask;
float mask_expand_initial_co[3];
- /* Used to prevent undesired results on certain mesh filters. */
- float *automask;
-
int new_face_set;
int *prev_face_set;
int active_face_set;
+
+ /* Automasking. */
+ AutomaskingCache *automasking;
} FilterCache;
void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,