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