Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/sculpt_paint/sculpt_smooth.c
| Show First 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index) | ||||
| if (total > 0) { | if (total > 0) { | ||||
| mul_v4_v4fl(result, avg, 1.0f / (float)total); | mul_v4_v4fl(result, avg, 1.0f / (float)total); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v4_v4(result, SCULPT_vertex_color_get(ss, index)); | copy_v4_v4(result, SCULPT_vertex_color_get(ss, index)); | ||||
| } | } | ||||
| } | } | ||||
| static void do_smooth_mask_brush_task_cb_ex(void *__restrict userdata, | |||||
| const int n, | |||||
| const TaskParallelTLS *__restrict tls) | |||||
| { | |||||
| SculptThreadedTaskData *data = userdata; | |||||
| SculptSession *ss = data->ob->sculpt; | |||||
| const Brush *brush = data->brush; | |||||
| float bstrength = data->strength; | |||||
| 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, 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, 0.0f, vd.index, thread_id); | |||||
| float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; | |||||
| val *= fade * bstrength; | |||||
| *vd.mask += val; | |||||
| CLAMP(*vd.mask, 0.0f, 1.0f); | |||||
| if (vd.mvert) { | |||||
| vd.mvert->flag |= ME_VERT_PBVH_UPDATE; | |||||
| } | |||||
| } | |||||
| } | |||||
| BKE_pbvh_vertex_iter_end; | |||||
| } | |||||
| void SCULPT_do_smooth_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | |||||
| { | |||||
| SculptSession *ss = ob->sculpt; | |||||
| Brush *brush = BKE_paint_brush(&sd->paint); | |||||
| const int max_iterations = 4; | |||||
| int iteration, count; | |||||
| const float fract = 1.0f / max_iterations; | |||||
| float last; | |||||
| float bstrength = ss->cache->bstrength; | |||||
| CLAMP(bstrength, 0.0f, 1.0f); | |||||
sergey: const float bstrength = clamp_f(ss->cache->bstrength, 0.0f, 1.0f);
Can apply this all places… | |||||
| count = (int)(bstrength * max_iterations); | |||||
sergeyUnsubmitted Done Inline Actionshttps://wiki.blender.org/wiki/Style_Guide/C_Cpp#Variable_Scope Also unclear why to have explicit cast to int. sergey: https://wiki.blender.org/wiki/Style_Guide/C_Cpp#Variable_Scope
Also unclear why to have… | |||||
| last = max_iterations * (bstrength - count * fract); | |||||
| SCULPT_vertex_random_access_init(ss); | |||||
| for (iteration = 0; iteration <= count; iteration++) { | |||||
| const float strength = (iteration != count) ? 1.0f : last; | |||||
| SculptThreadedTaskData data = { | |||||
| .sd = sd, | |||||
| .ob = ob, | |||||
| .brush = brush, | |||||
| .nodes = nodes, | |||||
| .strength = strength, | |||||
| }; | |||||
| TaskParallelSettings settings; | |||||
| BKE_pbvh_parallel_range_settings(&settings, true, totnode); | |||||
| BLI_task_parallel_range(0, totnode, &data, do_smooth_mask_brush_task_cb_ex, &settings); | |||||
| } | |||||
| } | |||||
| static void do_smooth_brush_task_cb_ex(void *__restrict userdata, | static void do_smooth_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| Sculpt *sd = data->sd; | Sculpt *sd = data->sd; | ||||
| const Brush *brush = data->brush; | const Brush *brush = data->brush; | ||||
| const bool smooth_mask = data->smooth_mask; | |||||
| float bstrength = data->strength; | float bstrength = data->strength; | ||||
| PBVHVertexIter vd; | PBVHVertexIter vd; | ||||
| CLAMP(bstrength, 0.0f, 1.0f); | CLAMP(bstrength, 0.0f, 1.0f); | ||||
| SculptBrushTest test; | SculptBrushTest test; | ||||
| SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( | SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( | ||||
| ss, &test, data->brush->falloff_shape); | ss, &test, data->brush->falloff_shape); | ||||
| const int thread_id = BLI_task_parallel_thread_id(tls); | const int thread_id = BLI_task_parallel_thread_id(tls); | ||||
| BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) | BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) | ||||
| { | { | ||||
| if (sculpt_brush_test_sq_fn(&test, vd.co)) { | if (sculpt_brush_test_sq_fn(&test, vd.co)) { | ||||
| const float fade = bstrength * SCULPT_brush_strength_factor( | const float fade = bstrength * SCULPT_brush_strength_factor(ss, | ||||
| ss, | |||||
| brush, | brush, | ||||
| vd.co, | vd.co, | ||||
| sqrtf(test.dist), | sqrtf(test.dist), | ||||
| vd.no, | vd.no, | ||||
| vd.fno, | vd.fno, | ||||
| smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), | vd.mask ? *vd.mask : 0.0f, | ||||
| vd.index, | vd.index, | ||||
| thread_id); | thread_id); | ||||
| if (smooth_mask) { | |||||
| float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; | |||||
| val *= fade * bstrength; | |||||
| *vd.mask += val; | |||||
| CLAMP(*vd.mask, 0.0f, 1.0f); | |||||
| } | |||||
| else { | |||||
| float avg[3], val[3]; | float avg[3], val[3]; | ||||
| SCULPT_neighbor_coords_average(ss, avg, vd.index); | SCULPT_neighbor_coords_average(ss, avg, vd.index); | ||||
| sub_v3_v3v3(val, avg, vd.co); | sub_v3_v3v3(val, avg, vd.co); | ||||
| madd_v3_v3v3fl(val, vd.co, val, fade); | madd_v3_v3v3fl(val, vd.co, val, fade); | ||||
| SCULPT_clip(sd, ss, vd.co, val); | SCULPT_clip(sd, ss, vd.co, val); | ||||
| } | |||||
| if (vd.mvert) { | if (vd.mvert) { | ||||
| vd.mvert->flag |= ME_VERT_PBVH_UPDATE; | vd.mvert->flag |= ME_VERT_PBVH_UPDATE; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BKE_pbvh_vertex_iter_end; | BKE_pbvh_vertex_iter_end; | ||||
| } | } | ||||
| void SCULPT_smooth(Sculpt *sd, | void SCULPT_smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength) | ||||
| Object *ob, | |||||
| PBVHNode **nodes, | |||||
| const int totnode, | |||||
| float bstrength, | |||||
| const bool smooth_mask) | |||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| Brush *brush = BKE_paint_brush(&sd->paint); | Brush *brush = BKE_paint_brush(&sd->paint); | ||||
| const int max_iterations = 4; | const int max_iterations = 4; | ||||
| const float fract = 1.0f / max_iterations; | const float fract = 1.0f / max_iterations; | ||||
| PBVHType type = BKE_pbvh_type(ss->pbvh); | PBVHType type = BKE_pbvh_type(ss->pbvh); | ||||
| int iteration, count; | int iteration, count; | ||||
| Show All 15 Lines | void SCULPT_smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength) | ||||
| for (iteration = 0; iteration <= count; iteration++) { | for (iteration = 0; iteration <= count; iteration++) { | ||||
| const float strength = (iteration != count) ? 1.0f : last; | const float strength = (iteration != count) ? 1.0f : last; | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .smooth_mask = smooth_mask, | |||||
| .strength = strength, | .strength = strength, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | TaskParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, true, totnode); | BKE_pbvh_parallel_range_settings(&settings, true, totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_task_cb_ex, &settings); | BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| } | } | ||||
| void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false); | SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength); | ||||
| } | } | ||||
| /* HC Smooth Algorithm. */ | /* HC Smooth Algorithm. */ | ||||
| /* From: Improved Laplacian Smoothing of Noisy Surface Meshes */ | /* From: Improved Laplacian Smoothing of Noisy Surface Meshes */ | ||||
| void SCULPT_surface_smooth_laplacian_step(SculptSession *ss, | void SCULPT_surface_smooth_laplacian_step(SculptSession *ss, | ||||
| float *disp, | float *disp, | ||||
| const float co[3], | const float co[3], | ||||
| ▲ Show 20 Lines • Show All 154 Lines • Show Last 20 Lines | |||||
Can apply this all places of sculpting.
And not only for bstrength, but in other usages of CLAMP as well.