Cleanup: Sculpt: Split mask and position smooth brushes

Previously they shared the same implementation with a check per vertex
for whether to smooth the mask or the positions. Though it adds a bit
of duplication for now, everything else becomes simpler if the brush
implementations are split.
This commit is contained in:
Hans Goudey 2023-12-28 14:19:30 -05:00
parent 97d0b52779
commit ac15db443f
4 changed files with 98 additions and 45 deletions

View File

@ -3569,10 +3569,10 @@ static void do_brush_action(Sculpt *sd,
{
if (brush->flag & BRUSH_INVERSE_SMOOTH_PRESSURE) {
smooth::do_smooth_brush(
sd, ob, nodes, brush->autosmooth_factor * (1.0f - ss->cache->pressure), false);
sd, ob, nodes, brush->autosmooth_factor * (1.0f - ss->cache->pressure));
}
else {
smooth::do_smooth_brush(sd, ob, nodes, brush->autosmooth_factor, false);
smooth::do_smooth_brush(sd, ob, nodes, brush->autosmooth_factor);
}
}

View File

@ -2715,7 +2715,7 @@ void SCULPT_do_mask_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
SCULPT_do_mask_brush_draw(sd, ob, nodes);
break;
case BRUSH_MASK_SMOOTH:
smooth::do_smooth_brush(sd, ob, nodes, ss->cache->bstrength, true);
smooth::do_smooth_mask_brush(sd, ob, nodes, ss->cache->bstrength);
break;
}
}

View File

@ -1523,9 +1523,10 @@ void neighbor_color_average(SculptSession *ss, float result[4], PBVHVertRef vert
*/
void neighbor_coords_average_interior(SculptSession *ss, float result[3], PBVHVertRef vertex);
void do_smooth_brush(
Sculpt *sd, Object *ob, blender::Span<PBVHNode *> nodes, float bstrength, bool smooth_mask);
void do_smooth_brush(Sculpt *sd, Object *ob, blender::Span<PBVHNode *> nodes);
void do_smooth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength);
void do_smooth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void do_smooth_mask_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength);
/* Surface Smooth Brush. */
@ -1542,7 +1543,7 @@ void surface_smooth_displace_step(SculptSession *ss,
PBVHVertRef vertex,
float beta,
float fade);
void do_surface_smooth_brush(Sculpt *sd, Object *ob, blender::Span<PBVHNode *> nodes);
void do_surface_smooth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
/* Slide/Relax */
void relax_vertex(SculptSession *ss,

View File

@ -253,13 +253,11 @@ static void enhance_details_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes
});
}
static void do_smooth_brush_task(Object *ob,
Sculpt *sd,
const Brush *brush,
const bool smooth_mask,
const SculptMaskWriteInfo mask_write,
float bstrength,
PBVHNode *node)
static void smooth_mask_node(Object *ob,
const Brush *brush,
const SculptMaskWriteInfo mask_write,
float bstrength,
PBVHNode *node)
{
SculptSession *ss = ob->sculpt;
@ -287,61 +285,115 @@ static void do_smooth_brush_task(Object *ob,
sqrtf(test.dist),
vd.no,
vd.fno,
smooth_mask ? 0.0f : vd.mask,
0.0f,
vd.vertex,
thread_id,
&automask_data);
if (smooth_mask) {
float val = neighbor_mask_average(ss, vd.vertex) - vd.mask;
val *= fade * bstrength;
float new_mask = vd.mask + val;
CLAMP(new_mask, 0.0f, 1.0f);
float val = neighbor_mask_average(ss, vd.vertex) - vd.mask;
val *= fade * bstrength;
float new_mask = vd.mask + val;
CLAMP(new_mask, 0.0f, 1.0f);
SCULPT_mask_vert_set(BKE_pbvh_type(ss->pbvh), mask_write, new_mask, vd);
}
else {
float avg[3], val[3];
neighbor_coords_average_interior(ss, avg, vd.vertex);
sub_v3_v3v3(val, avg, vd.co);
madd_v3_v3v3fl(val, vd.co, val, fade);
SCULPT_clip(sd, ss, vd.co, val);
if (vd.is_mesh) {
BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex);
SCULPT_mask_vert_set(BKE_pbvh_type(ss->pbvh), mask_write, new_mask, vd);
}
BKE_pbvh_vertex_iter_end;
}
void do_smooth_mask_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength)
{
SculptSession *ss = ob->sculpt;
const Brush *brush = BKE_paint_brush(&sd->paint);
const int max_iterations = 4;
const float fract = 1.0f / max_iterations;
CLAMP(bstrength, 0.0f, 1.0f);
const int count = int(bstrength * max_iterations);
const float last = max_iterations * (bstrength - count * fract);
SCULPT_vertex_random_access_ensure(ss);
SCULPT_boundary_info_ensure(ob);
SculptMaskWriteInfo mask_write = SCULPT_mask_get_for_write(ss);
for (const int iteration : IndexRange(count)) {
const float strength = (iteration != count) ? 1.0f : last;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
smooth_mask_node(ob, brush, mask_write, strength, nodes[i]);
}
});
}
}
static void smooth_position_node(
Object *ob, Sculpt *sd, const Brush *brush, float bstrength, PBVHNode *node)
{
SculptSession *ss = ob->sculpt;
PBVHVertexIter vd;
CLAMP(bstrength, 0.0f, 1.0f);
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(nullptr);
auto_mask::NodeData automask_data = auto_mask::node_begin(*ob, ss->cache->automasking, *node);
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
auto_mask::node_update(automask_data, vd);
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
vd.no,
vd.fno,
vd.mask,
vd.vertex,
thread_id,
&automask_data);
float avg[3], val[3];
neighbor_coords_average_interior(ss, avg, vd.vertex);
sub_v3_v3v3(val, avg, vd.co);
madd_v3_v3v3fl(val, vd.co, val, fade);
SCULPT_clip(sd, ss, vd.co, val);
if (vd.is_mesh) {
BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex);
}
}
BKE_pbvh_vertex_iter_end;
}
void do_smooth_brush(
Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength, const bool smooth_mask)
void do_smooth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
const Brush *brush = BKE_paint_brush(&sd->paint);
const int max_iterations = 4;
const float fract = 1.0f / max_iterations;
int iteration, count;
float last;
CLAMP(bstrength, 0.0f, 1.0f);
count = int(bstrength * max_iterations);
last = max_iterations * (bstrength - count * fract);
const int count = int(bstrength * max_iterations);
const float last = max_iterations * (bstrength - count * fract);
SCULPT_vertex_random_access_ensure(ss);
SCULPT_boundary_info_ensure(ob);
for (iteration = 0; iteration <= count; iteration++) {
for (const int iteration : IndexRange(count)) {
const float strength = (iteration != count) ? 1.0f : last;
SculptMaskWriteInfo mask_write;
if (smooth_mask) {
mask_write = SCULPT_mask_get_for_write(ss);
}
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
do_smooth_brush_task(ob, sd, brush, smooth_mask, mask_write, strength, nodes[i]);
smooth_position_node(ob, sd, brush, strength, nodes[i]);
}
});
}
@ -361,7 +413,7 @@ void do_smooth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
}
else {
/* Regular mode, smooth. */
do_smooth_brush(sd, ob, nodes, ss->cache->bstrength, false);
do_smooth_brush(sd, ob, nodes, ss->cache->bstrength);
}
}