From ac15db443f0991985ee0d27e960f06fcf85ed074 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 28 Dec 2023 14:19:30 -0500 Subject: [PATCH] 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. --- source/blender/editors/sculpt_paint/sculpt.cc | 4 +- .../sculpt_paint/sculpt_brush_types.cc | 2 +- .../editors/sculpt_paint/sculpt_intern.hh | 9 +- .../editors/sculpt_paint/sculpt_smooth.cc | 128 ++++++++++++------ 4 files changed, 98 insertions(+), 45 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 565f382f0d6..ee1fef293de 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -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); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_brush_types.cc b/source/blender/editors/sculpt_paint/sculpt_brush_types.cc index 76accadba48..e8bbf67fca6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_brush_types.cc +++ b/source/blender/editors/sculpt_paint/sculpt_brush_types.cc @@ -2715,7 +2715,7 @@ void SCULPT_do_mask_brush(Sculpt *sd, Object *ob, Span 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; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index 0f9d12ba39a..4d24713abf3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -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 nodes, float bstrength, bool smooth_mask); -void do_smooth_brush(Sculpt *sd, Object *ob, blender::Span nodes); +void do_smooth_brush(Sculpt *sd, Object *ob, Span nodes, float bstrength); +void do_smooth_brush(Sculpt *sd, Object *ob, Span nodes); + +void do_smooth_mask_brush(Sculpt *sd, Object *ob, Span 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 nodes); +void do_surface_smooth_brush(Sculpt *sd, Object *ob, Span nodes); /* Slide/Relax */ void relax_vertex(SculptSession *ss, diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.cc b/source/blender/editors/sculpt_paint/sculpt_smooth.cc index 91376b3f4c2..448a87d2c55 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.cc @@ -253,13 +253,11 @@ static void enhance_details_brush(Sculpt *sd, Object *ob, Span 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 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 nodes, float bstrength, const bool smooth_mask) +void do_smooth_brush(Sculpt *sd, Object *ob, Span 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 nodes) } else { /* Regular mode, smooth. */ - do_smooth_brush(sd, ob, nodes, ss->cache->bstrength, false); + do_smooth_brush(sd, ob, nodes, ss->cache->bstrength); } }