diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt_smooth.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_smooth.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 2b93298ac4a..63fe8643628 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -195,6 +195,85 @@ void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index } } +static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + Sculpt *sd = data->sd; + const Brush *brush = data->brush; + + PBVHVertexIter vd; + + float bstrength = ss->cache->bstrength; + CLAMP(bstrength, -1.0f, 1.0f); + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, data->brush->falloff_shape); + + const int thread_id = BLI_task_parallel_thread_id(tls); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test_sq_fn(&test, vd.co)) { + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float disp[3]; + madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade); + SCULPT_clip(sd, ss, vd.co, disp); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } + } + } + BKE_pbvh_vertex_iter_end; +} + +static void SCULPT_enhance_details_brush(Sculpt *sd, + Object *ob, + PBVHNode **nodes, + const int totnode) +{ + SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + + SCULPT_vertex_random_access_ensure(ss); + SCULPT_boundary_info_ensure(ob); + + if (SCULPT_stroke_is_first_brush_step(ss->cache)) { + const int totvert = SCULPT_vertex_count_get(ss); + ss->cache->detail_directions = MEM_malloc_arrayN( + totvert, 3 * sizeof(float), "details directions"); + + for (int i = 0; i < totvert; i++) { + float avg[3]; + SCULPT_neighbor_coords_average(ss, avg, i); + sub_v3_v3v3(ss->cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i)); + } + } + + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, do_enhance_details_brush_task_cb_ex, &settings); +} + static void do_smooth_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls) @@ -300,7 +379,14 @@ void SCULPT_smooth(Sculpt *sd, void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; - SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false); + if (ss->cache->bstrength <= 0.0f) { + /* Invert mode, intensify details. */ + SCULPT_enhance_details_brush(sd, ob, nodes, totnode); + } + else { + /* Regular mode, smooth. */ + SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false); + } } /* HC Smooth Algorithm. */ |