1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2020 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup edsculpt
22 */
23
24 #include "MEM_guardedalloc.h"
25
26 #include "BLI_blenlib.h"
27 #include "BLI_hash.h"
28 #include "BLI_math.h"
29 #include "BLI_task.h"
30
31 #include "DNA_mesh_types.h"
32 #include "DNA_meshdata_types.h"
33
34 #include "BKE_brush.h"
35 #include "BKE_context.h"
36 #include "BKE_mesh.h"
37 #include "BKE_mesh_mapping.h"
38 #include "BKE_object.h"
39 #include "BKE_paint.h"
40 #include "BKE_pbvh.h"
41 #include "BKE_scene.h"
42
43 #include "DEG_depsgraph.h"
44
45 #include "WM_api.h"
46 #include "WM_message.h"
47 #include "WM_toolsystem.h"
48 #include "WM_types.h"
49
50 #include "ED_object.h"
51 #include "ED_screen.h"
52 #include "ED_sculpt.h"
53 #include "ED_view3d.h"
54 #include "paint_intern.h"
55 #include "sculpt_intern.h"
56
57 #include "RNA_access.h"
58 #include "RNA_define.h"
59
60 #include "UI_interface.h"
61
62 #include "bmesh.h"
63
64 #include <math.h>
65 #include <stdlib.h>
66
67 /* Filter orientation utils. */
SCULPT_filter_to_orientation_space(float r_v[3],struct FilterCache * filter_cache)68 void SCULPT_filter_to_orientation_space(float r_v[3], struct FilterCache *filter_cache)
69 {
70 switch (filter_cache->orientation) {
71 case SCULPT_FILTER_ORIENTATION_LOCAL:
72 /* Do nothing, Sculpt Mode already works in object space. */
73 break;
74 case SCULPT_FILTER_ORIENTATION_WORLD:
75 mul_mat3_m4_v3(filter_cache->obmat, r_v);
76 break;
77 case SCULPT_FILTER_ORIENTATION_VIEW:
78 mul_mat3_m4_v3(filter_cache->obmat, r_v);
79 mul_mat3_m4_v3(filter_cache->viewmat, r_v);
80 break;
81 }
82 }
83
SCULPT_filter_to_object_space(float r_v[3],struct FilterCache * filter_cache)84 void SCULPT_filter_to_object_space(float r_v[3], struct FilterCache *filter_cache)
85 {
86 switch (filter_cache->orientation) {
87 case SCULPT_FILTER_ORIENTATION_LOCAL:
88 /* Do nothing, Sculpt Mode already works in object space. */
89 break;
90 case SCULPT_FILTER_ORIENTATION_WORLD:
91 mul_mat3_m4_v3(filter_cache->obmat_inv, r_v);
92 break;
93 case SCULPT_FILTER_ORIENTATION_VIEW:
94 mul_mat3_m4_v3(filter_cache->viewmat_inv, r_v);
95 mul_mat3_m4_v3(filter_cache->obmat_inv, r_v);
96 break;
97 }
98 }
99
SCULPT_filter_zero_disabled_axis_components(float r_v[3],struct FilterCache * filter_cache)100 void SCULPT_filter_zero_disabled_axis_components(float r_v[3], struct FilterCache *filter_cache)
101 {
102 SCULPT_filter_to_orientation_space(r_v, filter_cache);
103 for (int axis = 0; axis < 3; axis++) {
104 if (!filter_cache->enabled_force_axis[axis]) {
105 r_v[axis] = 0.0f;
106 }
107 }
108 SCULPT_filter_to_object_space(r_v, filter_cache);
109 }
110
filter_cache_init_task_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))111 static void filter_cache_init_task_cb(void *__restrict userdata,
112 const int i,
113 const TaskParallelTLS *__restrict UNUSED(tls))
114 {
115 SculptThreadedTaskData *data = userdata;
116 PBVHNode *node = data->nodes[i];
117
118 SCULPT_undo_push_node(data->ob, node, data->filter_undo_type);
119 }
120
SCULPT_filter_cache_init(bContext * C,Object * ob,Sculpt * sd,const int undo_type)121 void SCULPT_filter_cache_init(bContext *C, Object *ob, Sculpt *sd, const int undo_type)
122 {
123 SculptSession *ss = ob->sculpt;
124 PBVH *pbvh = ob->sculpt->pbvh;
125
126 ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
127
128 ss->filter_cache->random_seed = rand();
129
130 const float center[3] = {0.0f};
131 SculptSearchSphereData search_data = {
132 .original = true,
133 .center = center,
134 .radius_squared = FLT_MAX,
135 .ignore_fully_ineffective = true,
136
137 };
138 BKE_pbvh_search_gather(pbvh,
139 SCULPT_search_sphere_cb,
140 &search_data,
141 &ss->filter_cache->nodes,
142 &ss->filter_cache->totnode);
143
144 for (int i = 0; i < ss->filter_cache->totnode; i++) {
145 BKE_pbvh_node_mark_normals_update(ss->filter_cache->nodes[i]);
146 }
147
148 /* mesh->runtime.subdiv_ccg is not available. Updating of the normals is done during drawing.
149 * Filters can't use normals in multires. */
150 if (BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) {
151 BKE_pbvh_update_normals(ss->pbvh, NULL);
152 }
153
154 SculptThreadedTaskData data = {
155 .sd = sd,
156 .ob = ob,
157 .nodes = ss->filter_cache->nodes,
158 .filter_undo_type = undo_type,
159 };
160
161 TaskParallelSettings settings;
162 BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
163 BLI_task_parallel_range(
164 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
165
166 /* Setup orientation matrices. */
167 copy_m4_m4(ss->filter_cache->obmat, ob->obmat);
168 invert_m4_m4(ss->filter_cache->obmat_inv, ob->obmat);
169
170 Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
171 ViewContext vc;
172 ED_view3d_viewcontext_init(C, &vc, depsgraph);
173 copy_m4_m4(ss->filter_cache->viewmat, vc.rv3d->viewmat);
174 copy_m4_m4(ss->filter_cache->viewmat_inv, vc.rv3d->viewinv);
175 }
176
SCULPT_filter_cache_free(SculptSession * ss)177 void SCULPT_filter_cache_free(SculptSession *ss)
178 {
179 if (ss->filter_cache->cloth_sim) {
180 SCULPT_cloth_simulation_free(ss->filter_cache->cloth_sim);
181 }
182 if (ss->filter_cache->automasking) {
183 SCULPT_automasking_cache_free(ss->filter_cache->automasking);
184 }
185 MEM_SAFE_FREE(ss->filter_cache->nodes);
186 MEM_SAFE_FREE(ss->filter_cache->mask_update_it);
187 MEM_SAFE_FREE(ss->filter_cache->prev_mask);
188 MEM_SAFE_FREE(ss->filter_cache->normal_factor);
189 MEM_SAFE_FREE(ss->filter_cache->prev_face_set);
190 MEM_SAFE_FREE(ss->filter_cache->surface_smooth_laplacian_disp);
191 MEM_SAFE_FREE(ss->filter_cache->sharpen_factor);
192 MEM_SAFE_FREE(ss->filter_cache->detail_directions);
193 MEM_SAFE_FREE(ss->filter_cache->limit_surface_co);
194 MEM_SAFE_FREE(ss->filter_cache);
195 }
196
197 typedef enum eSculptMeshFilterType {
198 MESH_FILTER_SMOOTH = 0,
199 MESH_FILTER_SCALE = 1,
200 MESH_FILTER_INFLATE = 2,
201 MESH_FILTER_SPHERE = 3,
202 MESH_FILTER_RANDOM = 4,
203 MESH_FILTER_RELAX = 5,
204 MESH_FILTER_RELAX_FACE_SETS = 6,
205 MESH_FILTER_SURFACE_SMOOTH = 7,
206 MESH_FILTER_SHARPEN = 8,
207 MESH_FILTER_ENHANCE_DETAILS = 9,
208 MESH_FILTER_ERASE_DISPLACEMENT = 10,
209 } eSculptMeshFilterType;
210
211 static EnumPropertyItem prop_mesh_filter_types[] = {
212 {MESH_FILTER_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth mesh"},
213 {MESH_FILTER_SCALE, "SCALE", 0, "Scale", "Scale mesh"},
214 {MESH_FILTER_INFLATE, "INFLATE", 0, "Inflate", "Inflate mesh"},
215 {MESH_FILTER_SPHERE, "SPHERE", 0, "Sphere", "Morph into sphere"},
216 {MESH_FILTER_RANDOM, "RANDOM", 0, "Random", "Randomize vertex positions"},
217 {MESH_FILTER_RELAX, "RELAX", 0, "Relax", "Relax mesh"},
218 {MESH_FILTER_RELAX_FACE_SETS,
219 "RELAX_FACE_SETS",
220 0,
221 "Relax Face Sets",
222 "Smooth the edges of all the Face Sets"},
223 {MESH_FILTER_SURFACE_SMOOTH,
224 "SURFACE_SMOOTH",
225 0,
226 "Surface Smooth",
227 "Smooth the surface of the mesh, preserving the volume"},
228 {MESH_FILTER_SHARPEN, "SHARPEN", 0, "Sharpen", "Sharpen the cavities of the mesh"},
229 {MESH_FILTER_ENHANCE_DETAILS,
230 "ENHANCE_DETAILS",
231 0,
232 "Enhance Details",
233 "Enhance the high frequency surface detail"},
234 {MESH_FILTER_ERASE_DISPLACEMENT,
235 "ERASE_DISCPLACEMENT",
236 0,
237 "Erase Displacement",
238 "Deletes the displacement of the Multires Modifier"},
239 {0, NULL, 0, NULL, NULL},
240 };
241
242 typedef enum eMeshFilterDeformAxis {
243 MESH_FILTER_DEFORM_X = 1 << 0,
244 MESH_FILTER_DEFORM_Y = 1 << 1,
245 MESH_FILTER_DEFORM_Z = 1 << 2,
246 } eMeshFilterDeformAxis;
247
248 static EnumPropertyItem prop_mesh_filter_deform_axis_items[] = {
249 {MESH_FILTER_DEFORM_X, "X", 0, "X", "Deform in the X axis"},
250 {MESH_FILTER_DEFORM_Y, "Y", 0, "Y", "Deform in the Y axis"},
251 {MESH_FILTER_DEFORM_Z, "Z", 0, "Z", "Deform in the Z axis"},
252 {0, NULL, 0, NULL, NULL},
253 };
254
255 static EnumPropertyItem prop_mesh_filter_orientation_items[] = {
256 {SCULPT_FILTER_ORIENTATION_LOCAL,
257 "LOCAL",
258 0,
259 "Local",
260 "Use the local axis to limit the displacement"},
261 {SCULPT_FILTER_ORIENTATION_WORLD,
262 "WORLD",
263 0,
264 "World",
265 "Use the global axis to limit the displacement"},
266 {SCULPT_FILTER_ORIENTATION_VIEW,
267 "VIEW",
268 0,
269 "View",
270 "Use the view axis to limit the displacement"},
271 {0, NULL, 0, NULL, NULL},
272 };
273
sculpt_mesh_filter_needs_pmap(eSculptMeshFilterType filter_type)274 static bool sculpt_mesh_filter_needs_pmap(eSculptMeshFilterType filter_type)
275 {
276 return ELEM(filter_type,
277 MESH_FILTER_SMOOTH,
278 MESH_FILTER_RELAX,
279 MESH_FILTER_RELAX_FACE_SETS,
280 MESH_FILTER_SURFACE_SMOOTH,
281 MESH_FILTER_ENHANCE_DETAILS,
282 MESH_FILTER_SHARPEN);
283 }
284
mesh_filter_task_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))285 static void mesh_filter_task_cb(void *__restrict userdata,
286 const int i,
287 const TaskParallelTLS *__restrict UNUSED(tls))
288 {
289 SculptThreadedTaskData *data = userdata;
290 SculptSession *ss = data->ob->sculpt;
291 PBVHNode *node = data->nodes[i];
292
293 const eSculptMeshFilterType filter_type = data->filter_type;
294
295 SculptOrigVertData orig_data;
296 SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i]);
297
298 /* When using the relax face sets meshes filter,
299 * each 3 iterations, do a whole mesh relax to smooth the contents of the Face Set. */
300 /* This produces better results as the relax operation is no completely focused on the
301 * boundaries. */
302 const bool relax_face_sets = !(ss->filter_cache->iteration_count % 3 == 0);
303
304 PBVHVertexIter vd;
305 BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
306 {
307 SCULPT_orig_vert_data_update(&orig_data, &vd);
308 float orig_co[3], val[3], avg[3], normal[3], disp[3], disp2[3], transform[3][3], final_pos[3];
309 float fade = vd.mask ? *vd.mask : 0.0f;
310 fade = 1.0f - fade;
311 fade *= data->filter_strength;
312 fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
313
314 if (fade == 0.0f && filter_type != MESH_FILTER_SURFACE_SMOOTH) {
315 /* Surface Smooth can't skip the loop for this vertex as it needs to calculate its
316 * laplacian_disp. This value is accessed from the vertex neighbors when deforming the
317 * vertices, so it is needed for all vertices even if they are not going to be displaced.
318 */
319 continue;
320 }
321
322 if (ELEM(filter_type, MESH_FILTER_RELAX, MESH_FILTER_RELAX_FACE_SETS)) {
323 copy_v3_v3(orig_co, vd.co);
324 }
325 else {
326 copy_v3_v3(orig_co, orig_data.co);
327 }
328
329 if (filter_type == MESH_FILTER_RELAX_FACE_SETS) {
330 if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
331 continue;
332 }
333 }
334
335 switch (filter_type) {
336 case MESH_FILTER_SMOOTH:
337 fade = clamp_f(fade, -1.0f, 1.0f);
338 SCULPT_neighbor_coords_average_interior(ss, avg, vd.index);
339 sub_v3_v3v3(val, avg, orig_co);
340 madd_v3_v3v3fl(val, orig_co, val, fade);
341 sub_v3_v3v3(disp, val, orig_co);
342 break;
343 case MESH_FILTER_INFLATE:
344 normal_short_to_float_v3(normal, orig_data.no);
345 mul_v3_v3fl(disp, normal, fade);
346 break;
347 case MESH_FILTER_SCALE:
348 unit_m3(transform);
349 scale_m3_fl(transform, 1.0f + fade);
350 copy_v3_v3(val, orig_co);
351 mul_m3_v3(transform, val);
352 sub_v3_v3v3(disp, val, orig_co);
353 break;
354 case MESH_FILTER_SPHERE:
355 normalize_v3_v3(disp, orig_co);
356 if (fade > 0.0f) {
357 mul_v3_v3fl(disp, disp, fade);
358 }
359 else {
360 mul_v3_v3fl(disp, disp, -fade);
361 }
362
363 unit_m3(transform);
364 if (fade > 0.0f) {
365 scale_m3_fl(transform, 1.0f - fade);
366 }
367 else {
368 scale_m3_fl(transform, 1.0f + fade);
369 }
370 copy_v3_v3(val, orig_co);
371 mul_m3_v3(transform, val);
372 sub_v3_v3v3(disp2, val, orig_co);
373
374 mid_v3_v3v3(disp, disp, disp2);
375 break;
376 case MESH_FILTER_RANDOM: {
377 normal_short_to_float_v3(normal, orig_data.no);
378 /* Index is not unique for multires, so hash by vertex coordinates. */
379 const uint *hash_co = (const uint *)orig_co;
380 const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^
381 BLI_hash_int_2d(hash_co[2], ss->filter_cache->random_seed);
382 mul_v3_fl(normal, hash * (1.0f / (float)0xFFFFFFFF) - 0.5f);
383 mul_v3_v3fl(disp, normal, fade);
384 break;
385 }
386 case MESH_FILTER_RELAX: {
387 SCULPT_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), false, val);
388 sub_v3_v3v3(disp, val, vd.co);
389 break;
390 }
391 case MESH_FILTER_RELAX_FACE_SETS: {
392 SCULPT_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), relax_face_sets, val);
393 sub_v3_v3v3(disp, val, vd.co);
394 break;
395 }
396 case MESH_FILTER_SURFACE_SMOOTH: {
397 SCULPT_surface_smooth_laplacian_step(ss,
398 disp,
399 vd.co,
400 ss->filter_cache->surface_smooth_laplacian_disp,
401 vd.index,
402 orig_data.co,
403 ss->filter_cache->surface_smooth_shape_preservation);
404 break;
405 }
406 case MESH_FILTER_SHARPEN: {
407 const float smooth_ratio = ss->filter_cache->sharpen_smooth_ratio;
408
409 /* This filter can't work at full strength as it needs multiple iterations to reach a
410 * stable state. */
411 fade = clamp_f(fade, 0.0f, 0.5f);
412 float disp_sharpen[3] = {0.0f, 0.0f, 0.0f};
413
414 SculptVertexNeighborIter ni;
415 SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
416 float disp_n[3];
417 sub_v3_v3v3(
418 disp_n, SCULPT_vertex_co_get(ss, ni.index), SCULPT_vertex_co_get(ss, vd.index));
419 mul_v3_fl(disp_n, ss->filter_cache->sharpen_factor[ni.index]);
420 add_v3_v3(disp_sharpen, disp_n);
421 }
422 SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
423
424 mul_v3_fl(disp_sharpen, 1.0f - ss->filter_cache->sharpen_factor[vd.index]);
425
426 float disp_avg[3];
427 float avg_co[3];
428 SCULPT_neighbor_coords_average(ss, avg_co, vd.index);
429 sub_v3_v3v3(disp_avg, avg_co, vd.co);
430 mul_v3_v3fl(
431 disp_avg, disp_avg, smooth_ratio * pow2f(ss->filter_cache->sharpen_factor[vd.index]));
432 add_v3_v3v3(disp, disp_avg, disp_sharpen);
433
434 /* Intensify details. */
435 if (ss->filter_cache->sharpen_intensify_detail_strength > 0.0f) {
436 float detail_strength[3];
437 normal_short_to_float_v3(detail_strength, orig_data.no);
438 copy_v3_v3(detail_strength, ss->filter_cache->detail_directions[vd.index]);
439 madd_v3_v3fl(disp,
440 detail_strength,
441 -ss->filter_cache->sharpen_intensify_detail_strength *
442 ss->filter_cache->sharpen_factor[vd.index]);
443 }
444 break;
445 }
446
447 case MESH_FILTER_ENHANCE_DETAILS: {
448 mul_v3_v3fl(disp, ss->filter_cache->detail_directions[vd.index], -fabsf(fade));
449 } break;
450 case MESH_FILTER_ERASE_DISPLACEMENT: {
451 fade = clamp_f(fade, 0.0f, 1.0f);
452 sub_v3_v3v3(disp, ss->filter_cache->limit_surface_co[vd.index], orig_co);
453 mul_v3_fl(disp, fade);
454 break;
455 }
456 }
457
458 SCULPT_filter_to_orientation_space(disp, ss->filter_cache);
459 for (int it = 0; it < 3; it++) {
460 if (!ss->filter_cache->enabled_axis[it]) {
461 disp[it] = 0.0f;
462 }
463 }
464 SCULPT_filter_to_object_space(disp, ss->filter_cache);
465
466 if (ELEM(filter_type, MESH_FILTER_SURFACE_SMOOTH, MESH_FILTER_SHARPEN)) {
467 madd_v3_v3v3fl(final_pos, vd.co, disp, clamp_f(fade, 0.0f, 1.0f));
468 }
469 else {
470 add_v3_v3v3(final_pos, orig_co, disp);
471 }
472 copy_v3_v3(vd.co, final_pos);
473 if (vd.mvert) {
474 vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
475 }
476 }
477 BKE_pbvh_vertex_iter_end;
478
479 BKE_pbvh_node_mark_update(node);
480 }
481
mesh_filter_enhance_details_init_directions(SculptSession * ss)482 static void mesh_filter_enhance_details_init_directions(SculptSession *ss)
483 {
484 const int totvert = SCULPT_vertex_count_get(ss);
485 FilterCache *filter_cache = ss->filter_cache;
486
487 filter_cache->detail_directions = MEM_malloc_arrayN(
488 totvert, sizeof(float[3]), "detail directions");
489 for (int i = 0; i < totvert; i++) {
490 float avg[3];
491 SCULPT_neighbor_coords_average(ss, avg, i);
492 sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i));
493 }
494 }
495
mesh_filter_surface_smooth_init(SculptSession * ss,const float shape_preservation,const float current_vertex_displacement)496 static void mesh_filter_surface_smooth_init(SculptSession *ss,
497 const float shape_preservation,
498 const float current_vertex_displacement)
499 {
500 const int totvert = SCULPT_vertex_count_get(ss);
501 FilterCache *filter_cache = ss->filter_cache;
502
503 filter_cache->surface_smooth_laplacian_disp = MEM_malloc_arrayN(
504 totvert, sizeof(float[3]), "surface smooth displacement");
505 filter_cache->surface_smooth_shape_preservation = shape_preservation;
506 filter_cache->surface_smooth_current_vertex = current_vertex_displacement;
507 }
508
mesh_filter_init_limit_surface_co(SculptSession * ss)509 static void mesh_filter_init_limit_surface_co(SculptSession *ss)
510 {
511 const int totvert = SCULPT_vertex_count_get(ss);
512 FilterCache *filter_cache = ss->filter_cache;
513
514 filter_cache->limit_surface_co = MEM_malloc_arrayN(
515 sizeof(float[3]), totvert, "limit surface co");
516 for (int i = 0; i < totvert; i++) {
517 SCULPT_vertex_limit_surface_get(ss, i, filter_cache->limit_surface_co[i]);
518 }
519 }
520
mesh_filter_sharpen_init(SculptSession * ss,const float smooth_ratio,const float intensify_detail_strength,const int curvature_smooth_iterations)521 static void mesh_filter_sharpen_init(SculptSession *ss,
522 const float smooth_ratio,
523 const float intensify_detail_strength,
524 const int curvature_smooth_iterations)
525 {
526 const int totvert = SCULPT_vertex_count_get(ss);
527 FilterCache *filter_cache = ss->filter_cache;
528
529 filter_cache->sharpen_smooth_ratio = smooth_ratio;
530 filter_cache->sharpen_intensify_detail_strength = intensify_detail_strength;
531 filter_cache->sharpen_curvature_smooth_iterations = curvature_smooth_iterations;
532 filter_cache->sharpen_factor = MEM_malloc_arrayN(sizeof(float), totvert, "sharpen factor");
533 filter_cache->detail_directions = MEM_malloc_arrayN(
534 totvert, sizeof(float[3]), "sharpen detail direction");
535
536 for (int i = 0; i < totvert; i++) {
537 float avg[3];
538 SCULPT_neighbor_coords_average(ss, avg, i);
539 sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i));
540 filter_cache->sharpen_factor[i] = len_v3(filter_cache->detail_directions[i]);
541 }
542
543 float max_factor = 0.0f;
544 for (int i = 0; i < totvert; i++) {
545 if (filter_cache->sharpen_factor[i] > max_factor) {
546 max_factor = filter_cache->sharpen_factor[i];
547 }
548 }
549
550 max_factor = 1.0f / max_factor;
551 for (int i = 0; i < totvert; i++) {
552 filter_cache->sharpen_factor[i] *= max_factor;
553 filter_cache->sharpen_factor[i] = 1.0f - pow2f(1.0f - filter_cache->sharpen_factor[i]);
554 }
555
556 /* Smooth the calculated factors and directions to remove high frecuency detail. */
557 for (int smooth_iterations = 0;
558 smooth_iterations < filter_cache->sharpen_curvature_smooth_iterations;
559 smooth_iterations++) {
560 for (int i = 0; i < totvert; i++) {
561 float direction_avg[3] = {0.0f, 0.0f, 0.0f};
562 float sharpen_avg = 0;
563 int total = 0;
564
565 SculptVertexNeighborIter ni;
566 SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
567 add_v3_v3(direction_avg, filter_cache->detail_directions[ni.index]);
568 sharpen_avg += filter_cache->sharpen_factor[ni.index];
569 total++;
570 }
571 SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
572
573 if (total > 0) {
574 mul_v3_v3fl(filter_cache->detail_directions[i], direction_avg, 1.0f / total);
575 filter_cache->sharpen_factor[i] = sharpen_avg / total;
576 }
577 }
578 }
579 }
580
mesh_filter_surface_smooth_displace_task_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))581 static void mesh_filter_surface_smooth_displace_task_cb(
582 void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
583 {
584 SculptThreadedTaskData *data = userdata;
585 SculptSession *ss = data->ob->sculpt;
586 PBVHNode *node = data->nodes[i];
587 PBVHVertexIter vd;
588
589 BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
590 {
591 float fade = vd.mask ? *vd.mask : 0.0f;
592 fade = 1.0f - fade;
593 fade *= data->filter_strength;
594 fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
595 if (fade == 0.0f) {
596 continue;
597 }
598
599 SCULPT_surface_smooth_displace_step(ss,
600 vd.co,
601 ss->filter_cache->surface_smooth_laplacian_disp,
602 vd.index,
603 ss->filter_cache->surface_smooth_current_vertex,
604 clamp_f(fade, 0.0f, 1.0f));
605 }
606 BKE_pbvh_vertex_iter_end;
607 }
608
sculpt_mesh_filter_modal(bContext * C,wmOperator * op,const wmEvent * event)609 static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
610 {
611 Object *ob = CTX_data_active_object(C);
612 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
613 SculptSession *ss = ob->sculpt;
614 Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
615 eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type");
616 float filter_strength = RNA_float_get(op->ptr, "strength");
617
618 if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
619 SCULPT_filter_cache_free(ss);
620 SCULPT_undo_push_end();
621 SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
622 return OPERATOR_FINISHED;
623 }
624
625 if (event->type != MOUSEMOVE) {
626 return OPERATOR_RUNNING_MODAL;
627 }
628
629 const float len = event->prevclickx - event->x;
630 filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
631
632 SCULPT_vertex_random_access_ensure(ss);
633
634 bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type);
635 BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, false);
636
637 SculptThreadedTaskData data = {
638 .sd = sd,
639 .ob = ob,
640 .nodes = ss->filter_cache->nodes,
641 .filter_type = filter_type,
642 .filter_strength = filter_strength,
643 };
644
645 TaskParallelSettings settings;
646 BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
647 BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings);
648
649 if (filter_type == MESH_FILTER_SURFACE_SMOOTH) {
650 BLI_task_parallel_range(0,
651 ss->filter_cache->totnode,
652 &data,
653 mesh_filter_surface_smooth_displace_task_cb,
654 &settings);
655 }
656
657 ss->filter_cache->iteration_count++;
658
659 if (ss->deform_modifiers_active || ss->shapekey_active) {
660 SCULPT_flush_stroke_deform(sd, ob, true);
661 }
662
663 /* The relax mesh filter needs the updated normals of the modified mesh after each iteration. */
664 if (ELEM(MESH_FILTER_RELAX, MESH_FILTER_RELAX_FACE_SETS)) {
665 BKE_pbvh_update_normals(ss->pbvh, ss->subdiv_ccg);
666 }
667
668 SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
669
670 return OPERATOR_RUNNING_MODAL;
671 }
672
sculpt_mesh_filter_invoke(bContext * C,wmOperator * op,const wmEvent * event)673 static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
674 {
675 Object *ob = CTX_data_active_object(C);
676 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
677 Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
678 SculptSession *ss = ob->sculpt;
679
680 const eMeshFilterDeformAxis deform_axis = RNA_enum_get(op->ptr, "deform_axis");
681 const eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type");
682 const bool use_automasking = SCULPT_is_automasking_enabled(sd, ss, NULL);
683 const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type) || use_automasking;
684
685 if (deform_axis == 0) {
686 /* All axis are disabled, so the filter is not going to produce any deformation. */
687 return OPERATOR_CANCELLED;
688 }
689
690 if (use_automasking) {
691 /* Update the active face set manually as the paint cursor is not enabled when using the Mesh
692 * Filter Tool. */
693 float mouse[2];
694 SculptCursorGeometryInfo sgi;
695 mouse[0] = event->mval[0];
696 mouse[1] = event->mval[1];
697 SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
698 }
699
700 SCULPT_vertex_random_access_ensure(ss);
701 BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_topology_info, false, false);
702 if (needs_topology_info) {
703 SCULPT_boundary_info_ensure(ob);
704 }
705
706 SCULPT_undo_push_begin("Mesh Filter");
707
708 SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
709
710 FilterCache *filter_cache = ss->filter_cache;
711 filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
712 filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
713
714 switch (filter_type) {
715 case MESH_FILTER_SURFACE_SMOOTH: {
716 const float shape_preservation = RNA_float_get(op->ptr, "surface_smooth_shape_preservation");
717 const float current_vertex_displacement = RNA_float_get(op->ptr,
718 "surface_smooth_current_vertex");
719 mesh_filter_surface_smooth_init(ss, shape_preservation, current_vertex_displacement);
720 break;
721 }
722 case MESH_FILTER_SHARPEN: {
723 const float smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio");
724 const float intensify_detail_strength = RNA_float_get(op->ptr,
725 "sharpen_intensify_detail_strength");
726 const int curvature_smooth_iterations = RNA_int_get(op->ptr,
727 "sharpen_curvature_smooth_iterations");
728 mesh_filter_sharpen_init(
729 ss, smooth_ratio, intensify_detail_strength, curvature_smooth_iterations);
730 break;
731 }
732 case MESH_FILTER_ENHANCE_DETAILS: {
733 mesh_filter_enhance_details_init_directions(ss);
734 break;
735 }
736 case MESH_FILTER_ERASE_DISPLACEMENT: {
737 mesh_filter_init_limit_surface_co(ss);
738 break;
739 }
740 default:
741 break;
742 }
743
744 ss->filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
745 ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
746 ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
747
748 SculptFilterOrientation orientation = RNA_enum_get(op->ptr, "orientation");
749 ss->filter_cache->orientation = orientation;
750
751 WM_event_add_modal_handler(C, op);
752 return OPERATOR_RUNNING_MODAL;
753 }
754
SCULPT_OT_mesh_filter(struct wmOperatorType * ot)755 void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
756 {
757 /* Identifiers. */
758 ot->name = "Filter Mesh";
759 ot->idname = "SCULPT_OT_mesh_filter";
760 ot->description = "Applies a filter to modify the current mesh";
761
762 /* API callbacks. */
763 ot->invoke = sculpt_mesh_filter_invoke;
764 ot->modal = sculpt_mesh_filter_modal;
765 ot->poll = SCULPT_mode_poll;
766
767 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
768
769 /* RNA. */
770 RNA_def_enum(ot->srna,
771 "type",
772 prop_mesh_filter_types,
773 MESH_FILTER_INFLATE,
774 "Filter type",
775 "Operation that is going to be applied to the mesh");
776 RNA_def_float(
777 ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f);
778 RNA_def_enum_flag(ot->srna,
779 "deform_axis",
780 prop_mesh_filter_deform_axis_items,
781 MESH_FILTER_DEFORM_X | MESH_FILTER_DEFORM_Y | MESH_FILTER_DEFORM_Z,
782 "Deform axis",
783 "Apply the deformation in the selected axis");
784 RNA_def_enum(ot->srna,
785 "orientation",
786 prop_mesh_filter_orientation_items,
787 SCULPT_FILTER_ORIENTATION_LOCAL,
788 "Orientation",
789 "Orientation of the axis to limit the filter displacement");
790
791 /* Surface Smooth Mesh Filter properties. */
792 RNA_def_float(ot->srna,
793 "surface_smooth_shape_preservation",
794 0.5f,
795 0.0f,
796 1.0f,
797 "Shape Preservation",
798 "How much of the original shape is preserved when smoothing",
799 0.0f,
800 1.0f);
801 RNA_def_float(ot->srna,
802 "surface_smooth_current_vertex",
803 0.5f,
804 0.0f,
805 1.0f,
806 "Per Vertex Displacement",
807 "How much the position of each individual vertex influences the final result",
808 0.0f,
809 1.0f);
810 RNA_def_float(ot->srna,
811 "sharpen_smooth_ratio",
812 0.35f,
813 0.0f,
814 1.0f,
815 "Smooth Ratio",
816 "How much smoothing is applied to polished surfaces",
817 0.0f,
818 1.0f);
819
820 RNA_def_float(ot->srna,
821 "sharpen_intensify_detail_strength",
822 0.0f,
823 0.0f,
824 10.0f,
825 "Intensify Details",
826 "How much creases and valleys are intensified",
827 0.0f,
828 1.0f);
829
830 RNA_def_int(ot->srna,
831 "sharpen_curvature_smooth_iterations",
832 0,
833 0,
834 10,
835 "Curvature Smooth Iterations",
836 "How much smooth the resulting shape is, ignoring high frequency details",
837 0,
838 10);
839 }
840