Blender  V2.93
sculpt_filter_mesh.c
Go to the documentation of this file.
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 
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. */
68 void SCULPT_filter_to_orientation_space(float r_v[3], struct FilterCache *filter_cache)
69 {
70  switch (filter_cache->orientation) {
72  /* Do nothing, Sculpt Mode already works in object space. */
73  break;
75  mul_mat3_m4_v3(filter_cache->obmat, r_v);
76  break;
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 
84 void SCULPT_filter_to_object_space(float r_v[3], struct FilterCache *filter_cache)
85 {
86  switch (filter_cache->orientation) {
88  /* Do nothing, Sculpt Mode already works in object space. */
89  break;
91  mul_mat3_m4_v3(filter_cache->obmat_inv, r_v);
92  break;
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 
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 
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 
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  };
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++) {
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) {
152  }
153 
155  .sd = sd,
156  .ob = ob,
157  .nodes = ss->filter_cache->nodes,
158  .filter_undo_type = undo_type,
159  };
160 
161  TaskParallelSettings settings;
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);
169 
171  ViewContext vc;
175 }
176 
178 {
179  if (ss->filter_cache->cloth_sim) {
181  }
182  if (ss->filter_cache->automasking) {
184  }
195 }
196 
197 typedef enum eSculptMeshFilterType {
210 
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"},
219  "RELAX_FACE_SETS",
220  0,
221  "Relax Face Sets",
222  "Smooth the edges of all the Face Sets"},
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"},
230  "ENHANCE_DETAILS",
231  0,
232  "Enhance Details",
233  "Enhance the high frequency surface detail"},
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 {
247 
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 
257  "LOCAL",
258  0,
259  "Local",
260  "Use the local axis to limit the displacement"},
262  "WORLD",
263  0,
264  "World",
265  "Use the global axis to limit the displacement"},
267  "VIEW",
268  0,
269  "View",
270  "Use the view axis to limit the displacement"},
271  {0, NULL, 0, NULL, NULL},
272 };
273 
275 {
276  return ELEM(filter_type,
283 }
284 
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;
306  SCULPT_orig_vert_data_update(&orig_data, &vd);
307  float orig_co[3], val[3], avg[3], normal[3], disp[3], disp2[3], transform[3][3], final_pos[3];
308  float fade = vd.mask ? *vd.mask : 0.0f;
309  fade = 1.0f - fade;
310  fade *= data->filter_strength;
312 
313  if (fade == 0.0f && filter_type != MESH_FILTER_SURFACE_SMOOTH) {
314  /* Surface Smooth can't skip the loop for this vertex as it needs to calculate its
315  * laplacian_disp. This value is accessed from the vertex neighbors when deforming the
316  * vertices, so it is needed for all vertices even if they are not going to be displaced.
317  */
318  continue;
319  }
320 
322  copy_v3_v3(orig_co, vd.co);
323  }
324  else {
325  copy_v3_v3(orig_co, orig_data.co);
326  }
327 
328  if (filter_type == MESH_FILTER_RELAX_FACE_SETS) {
329  if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
330  continue;
331  }
332  }
333 
334  switch (filter_type) {
335  case MESH_FILTER_SMOOTH:
336  fade = clamp_f(fade, -1.0f, 1.0f);
338  sub_v3_v3v3(val, avg, orig_co);
339  madd_v3_v3v3fl(val, orig_co, val, fade);
340  sub_v3_v3v3(disp, val, orig_co);
341  break;
342  case MESH_FILTER_INFLATE:
343  normal_short_to_float_v3(normal, orig_data.no);
344  mul_v3_v3fl(disp, normal, fade);
345  break;
346  case MESH_FILTER_SCALE:
348  scale_m3_fl(transform, 1.0f + fade);
349  copy_v3_v3(val, orig_co);
350  mul_m3_v3(transform, val);
351  sub_v3_v3v3(disp, val, orig_co);
352  break;
353  case MESH_FILTER_SPHERE:
354  normalize_v3_v3(disp, orig_co);
355  if (fade > 0.0f) {
356  mul_v3_v3fl(disp, disp, fade);
357  }
358  else {
359  mul_v3_v3fl(disp, disp, -fade);
360  }
361 
363  if (fade > 0.0f) {
364  scale_m3_fl(transform, 1.0f - fade);
365  }
366  else {
367  scale_m3_fl(transform, 1.0f + fade);
368  }
369  copy_v3_v3(val, orig_co);
370  mul_m3_v3(transform, val);
371  sub_v3_v3v3(disp2, val, orig_co);
372 
373  mid_v3_v3v3(disp, disp, disp2);
374  break;
375  case MESH_FILTER_RANDOM: {
376  normal_short_to_float_v3(normal, orig_data.no);
377  /* Index is not unique for multires, so hash by vertex coordinates. */
378  const uint *hash_co = (const uint *)orig_co;
379  const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^
380  BLI_hash_int_2d(hash_co[2], ss->filter_cache->random_seed);
381  mul_v3_fl(normal, hash * (1.0f / (float)0xFFFFFFFF) - 0.5f);
382  mul_v3_v3fl(disp, normal, fade);
383  break;
384  }
385  case MESH_FILTER_RELAX: {
386  SCULPT_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), false, val);
387  sub_v3_v3v3(disp, val, vd.co);
388  break;
389  }
391  SCULPT_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), relax_face_sets, val);
392  sub_v3_v3v3(disp, val, vd.co);
393  break;
394  }
397  disp,
398  vd.co,
400  vd.index,
401  orig_data.co,
403  break;
404  }
405  case MESH_FILTER_SHARPEN: {
406  const float smooth_ratio = ss->filter_cache->sharpen_smooth_ratio;
407 
408  /* This filter can't work at full strength as it needs multiple iterations to reach a
409  * stable state. */
410  fade = clamp_f(fade, 0.0f, 0.5f);
411  float disp_sharpen[3] = {0.0f, 0.0f, 0.0f};
412 
415  float disp_n[3];
416  sub_v3_v3v3(
417  disp_n, SCULPT_vertex_co_get(ss, ni.index), SCULPT_vertex_co_get(ss, vd.index));
418  mul_v3_fl(disp_n, ss->filter_cache->sharpen_factor[ni.index]);
419  add_v3_v3(disp_sharpen, disp_n);
420  }
422 
423  mul_v3_fl(disp_sharpen, 1.0f - ss->filter_cache->sharpen_factor[vd.index]);
424 
425  float disp_avg[3];
426  float avg_co[3];
427  SCULPT_neighbor_coords_average(ss, avg_co, vd.index);
428  sub_v3_v3v3(disp_avg, avg_co, vd.co);
429  mul_v3_v3fl(
430  disp_avg, disp_avg, smooth_ratio * pow2f(ss->filter_cache->sharpen_factor[vd.index]));
431  add_v3_v3v3(disp, disp_avg, disp_sharpen);
432 
433  /* Intensify details. */
435  float detail_strength[3];
436  normal_short_to_float_v3(detail_strength, orig_data.no);
437  copy_v3_v3(detail_strength, ss->filter_cache->detail_directions[vd.index]);
438  madd_v3_v3fl(disp,
439  detail_strength,
442  }
443  break;
444  }
445 
448  } break;
450  fade = clamp_f(fade, -1.0f, 1.0f);
451  sub_v3_v3v3(disp, ss->filter_cache->limit_surface_co[vd.index], orig_co);
452  mul_v3_fl(disp, fade);
453  break;
454  }
455  }
456 
458  for (int it = 0; it < 3; it++) {
459  if (!ss->filter_cache->enabled_axis[it]) {
460  disp[it] = 0.0f;
461  }
462  }
464 
466  madd_v3_v3v3fl(final_pos, vd.co, disp, clamp_f(fade, 0.0f, 1.0f));
467  }
468  else {
469  add_v3_v3v3(final_pos, orig_co, disp);
470  }
471  copy_v3_v3(vd.co, final_pos);
472  if (vd.mvert) {
474  }
475  }
477 
479 }
480 
482 {
483  const int totvert = SCULPT_vertex_count_get(ss);
484  FilterCache *filter_cache = ss->filter_cache;
485 
486  filter_cache->detail_directions = MEM_malloc_arrayN(
487  totvert, sizeof(float[3]), "detail directions");
488  for (int i = 0; i < totvert; i++) {
489  float avg[3];
490  SCULPT_neighbor_coords_average(ss, avg, i);
491  sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i));
492  }
493 }
494 
496  const float shape_preservation,
497  const float current_vertex_displacement)
498 {
499  const int totvert = SCULPT_vertex_count_get(ss);
500  FilterCache *filter_cache = ss->filter_cache;
501 
503  totvert, sizeof(float[3]), "surface smooth displacement");
504  filter_cache->surface_smooth_shape_preservation = shape_preservation;
505  filter_cache->surface_smooth_current_vertex = current_vertex_displacement;
506 }
507 
509 {
510  const int totvert = SCULPT_vertex_count_get(ss);
511  FilterCache *filter_cache = ss->filter_cache;
512 
513  filter_cache->limit_surface_co = MEM_malloc_arrayN(
514  sizeof(float[3]), totvert, "limit surface co");
515  for (int i = 0; i < totvert; i++) {
516  SCULPT_vertex_limit_surface_get(ss, i, filter_cache->limit_surface_co[i]);
517  }
518 }
519 
521  const float smooth_ratio,
522  const float intensify_detail_strength,
523  const int curvature_smooth_iterations)
524 {
525  const int totvert = SCULPT_vertex_count_get(ss);
526  FilterCache *filter_cache = ss->filter_cache;
527 
528  filter_cache->sharpen_smooth_ratio = smooth_ratio;
529  filter_cache->sharpen_intensify_detail_strength = intensify_detail_strength;
530  filter_cache->sharpen_curvature_smooth_iterations = curvature_smooth_iterations;
531  filter_cache->sharpen_factor = MEM_malloc_arrayN(sizeof(float), totvert, "sharpen factor");
532  filter_cache->detail_directions = MEM_malloc_arrayN(
533  totvert, sizeof(float[3]), "sharpen detail direction");
534 
535  for (int i = 0; i < totvert; i++) {
536  float avg[3];
537  SCULPT_neighbor_coords_average(ss, avg, i);
538  sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i));
539  filter_cache->sharpen_factor[i] = len_v3(filter_cache->detail_directions[i]);
540  }
541 
542  float max_factor = 0.0f;
543  for (int i = 0; i < totvert; i++) {
544  if (filter_cache->sharpen_factor[i] > max_factor) {
545  max_factor = filter_cache->sharpen_factor[i];
546  }
547  }
548 
549  max_factor = 1.0f / max_factor;
550  for (int i = 0; i < totvert; i++) {
551  filter_cache->sharpen_factor[i] *= max_factor;
552  filter_cache->sharpen_factor[i] = 1.0f - pow2f(1.0f - filter_cache->sharpen_factor[i]);
553  }
554 
555  /* Smooth the calculated factors and directions to remove high frequency detail. */
556  for (int smooth_iterations = 0;
557  smooth_iterations < filter_cache->sharpen_curvature_smooth_iterations;
558  smooth_iterations++) {
559  for (int i = 0; i < totvert; i++) {
560  float direction_avg[3] = {0.0f, 0.0f, 0.0f};
561  float sharpen_avg = 0;
562  int total = 0;
563 
566  add_v3_v3(direction_avg, filter_cache->detail_directions[ni.index]);
567  sharpen_avg += filter_cache->sharpen_factor[ni.index];
568  total++;
569  }
571 
572  if (total > 0) {
573  mul_v3_v3fl(filter_cache->detail_directions[i], direction_avg, 1.0f / total);
574  filter_cache->sharpen_factor[i] = sharpen_avg / total;
575  }
576  }
577  }
578 }
579 
581  void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
582 {
583  SculptThreadedTaskData *data = userdata;
584  SculptSession *ss = data->ob->sculpt;
585  PBVHNode *node = data->nodes[i];
586  PBVHVertexIter vd;
587 
589  float fade = vd.mask ? *vd.mask : 0.0f;
590  fade = 1.0f - fade;
591  fade *= data->filter_strength;
593  if (fade == 0.0f) {
594  continue;
595  }
596 
598  vd.co,
600  vd.index,
602  clamp_f(fade, 0.0f, 1.0f));
603  }
605 }
606 
607 static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
608 {
611  SculptSession *ss = ob->sculpt;
613  eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type");
614  float filter_strength = RNA_float_get(op->ptr, "strength");
615 
616  if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
620  return OPERATOR_FINISHED;
621  }
622 
623  if (event->type != MOUSEMOVE) {
624  return OPERATOR_RUNNING_MODAL;
625  }
626 
627  const float len = event->prevclickx - event->x;
628  filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
629 
631 
632  bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type);
633  BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, false);
634 
636  .sd = sd,
637  .ob = ob,
638  .nodes = ss->filter_cache->nodes,
639  .filter_type = filter_type,
640  .filter_strength = filter_strength,
641  };
642 
643  TaskParallelSettings settings;
646 
647  if (filter_type == MESH_FILTER_SURFACE_SMOOTH) {
649  ss->filter_cache->totnode,
650  &data,
652  &settings);
653  }
654 
656 
657  if (ss->deform_modifiers_active || ss->shapekey_active) {
658  SCULPT_flush_stroke_deform(sd, ob, true);
659  }
660 
661  /* The relax mesh filter needs the updated normals of the modified mesh after each iteration. */
664  }
665 
667 
668  return OPERATOR_RUNNING_MODAL;
669 }
670 
671 static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
672 {
676  SculptSession *ss = ob->sculpt;
677 
678  const eMeshFilterDeformAxis deform_axis = RNA_enum_get(op->ptr, "deform_axis");
679  const eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type");
680  const bool use_automasking = SCULPT_is_automasking_enabled(sd, ss, NULL);
681  const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type) || use_automasking;
682 
683  if (deform_axis == 0) {
684  /* All axis are disabled, so the filter is not going to produce any deformation. */
685  return OPERATOR_CANCELLED;
686  }
687 
688  if (use_automasking) {
689  /* Update the active face set manually as the paint cursor is not enabled when using the Mesh
690  * Filter Tool. */
691  float mouse[2];
693  mouse[0] = event->mval[0];
694  mouse[1] = event->mval[1];
695  SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
696  }
697 
699  BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_topology_info, false, false);
700  if (needs_topology_info) {
702  }
703 
704  SCULPT_undo_push_begin(ob, "Mesh Filter");
705 
707 
708  FilterCache *filter_cache = ss->filter_cache;
709  filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
710  filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
711 
712  switch (filter_type) {
714  const float shape_preservation = RNA_float_get(op->ptr, "surface_smooth_shape_preservation");
715  const float current_vertex_displacement = RNA_float_get(op->ptr,
716  "surface_smooth_current_vertex");
717  mesh_filter_surface_smooth_init(ss, shape_preservation, current_vertex_displacement);
718  break;
719  }
720  case MESH_FILTER_SHARPEN: {
721  const float smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio");
722  const float intensify_detail_strength = RNA_float_get(op->ptr,
723  "sharpen_intensify_detail_strength");
724  const int curvature_smooth_iterations = RNA_int_get(op->ptr,
725  "sharpen_curvature_smooth_iterations");
727  ss, smooth_ratio, intensify_detail_strength, curvature_smooth_iterations);
728  break;
729  }
732  break;
733  }
736  break;
737  }
738  default:
739  break;
740  }
741 
742  ss->filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
743  ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
744  ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
745 
746  SculptFilterOrientation orientation = RNA_enum_get(op->ptr, "orientation");
747  ss->filter_cache->orientation = orientation;
748 
750  return OPERATOR_RUNNING_MODAL;
751 }
752 
754 {
755  /* Identifiers. */
756  ot->name = "Filter Mesh";
757  ot->idname = "SCULPT_OT_mesh_filter";
758  ot->description = "Applies a filter to modify the current mesh";
759 
760  /* API callbacks. */
764 
766 
767  /* RNA. */
769  "type",
772  "Filter Type",
773  "Operation that is going to be applied to the mesh");
775  ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
777  "deform_axis",
780  "Deform Axis",
781  "Apply the deformation in the selected axis");
783  "orientation",
786  "Orientation",
787  "Orientation of the axis to limit the filter displacement");
788 
789  /* Surface Smooth Mesh Filter properties. */
791  "surface_smooth_shape_preservation",
792  0.5f,
793  0.0f,
794  1.0f,
795  "Shape Preservation",
796  "How much of the original shape is preserved when smoothing",
797  0.0f,
798  1.0f);
800  "surface_smooth_current_vertex",
801  0.5f,
802  0.0f,
803  1.0f,
804  "Per Vertex Displacement",
805  "How much the position of each individual vertex influences the final result",
806  0.0f,
807  1.0f);
809  "sharpen_smooth_ratio",
810  0.35f,
811  0.0f,
812  1.0f,
813  "Smooth Ratio",
814  "How much smoothing is applied to polished surfaces",
815  0.0f,
816  1.0f);
817 
819  "sharpen_intensify_detail_strength",
820  0.0f,
821  0.0f,
822  10.0f,
823  "Intensify Details",
824  "How much creases and valleys are intensified",
825  0.0f,
826  1.0f);
827 
829  "sharpen_curvature_smooth_iterations",
830  0,
831  0,
832  10,
833  "Curvature Smooth Iterations",
834  "How much smooth the resulting shape is, ignoring high frequency details",
835  0,
836  10);
837 }
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1401
struct ToolSettings * CTX_data_tool_settings(const bContext *C)
Definition: context.c:1208
General operations, lookup, etc. for blender objects.
void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph, struct Object *ob_orig, bool need_pmap, bool need_mask, bool need_colors)
Definition: paint.c:1817
#define SCULPT_FACE_SET_NONE
Definition: BKE_paint.h:230
A BVH for high poly meshes.
void BKE_pbvh_node_mark_update(PBVHNode *node)
Definition: pbvh.c:1732
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:384
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1661
void BKE_pbvh_node_mark_normals_update(PBVHNode *node)
Definition: pbvh.c:1764
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:457
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:335
void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg)
Definition: pbvh.c:2650
@ PBVH_GRIDS
Definition: BKE_pbvh.h:211
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3042
void BKE_pbvh_search_gather(PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot)
Definition: pbvh.c:843
BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
Definition: BLI_hash.h:67
MINLINE float pow2f(float x)
MINLINE float clamp_f(float value, float min, float max)
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
void scale_m3_fl(float R[3][3], float scale)
Definition: math_matrix.c:2301
void mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:794
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void normal_short_to_float_v3(float r[3], const short n[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:270
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:83
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
#define UNUSED(x)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
@ ME_VERT_PBVH_UPDATE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc, struct Depsgraph *depsgraph)
NSNotificationCenter * center
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition: RandGen.cpp:39
#define UI_DPI_FAC
Definition: UI_interface.h:309
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define KM_RELEASE
Definition: WM_types.h:243
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
OperationNode * node
const Depsgraph * depsgraph
IconTextureDrawCall normal
#define fabsf(x)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
#define hash
Definition: noise.c:169
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3825
PropertyRNA * RNA_def_enum_flag(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3795
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3585
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
const float * SCULPT_vertex_co_get(SculptSession *ss, int index)
Definition: sculpt.c:134
int SCULPT_vertex_count_get(SculptSession *ss)
Definition: sculpt.c:120
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
Definition: sculpt.c:1310
void SCULPT_boundary_info_ensure(Object *object)
Definition: sculpt.c:9039
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mouse[2], bool use_sampled_normal)
Definition: sculpt.c:7452
bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index)
Definition: sculpt.c:669
void SCULPT_relax_vertex(SculptSession *ss, PBVHVertexIter *vd, float factor, bool filter_boundary_face_sets, float *r_final_pos)
Definition: sculpt.c:3506
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
Definition: sculpt.c:112
void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags)
Definition: sculpt.c:7819
bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
Definition: sculpt.c:2561
void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
Definition: sculpt.c:7759
void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3])
Definition: sculpt.c:224
bool SCULPT_mode_poll(bContext *C)
Definition: sculpt.c:6601
void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
Definition: sculpt.c:6340
void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node)
Definition: sculpt.c:1300
void SCULPT_automasking_cache_free(AutomaskingCache *automasking)
float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
AutomaskingCache * SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob)
bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, const Brush *br)
void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim)
static void mesh_filter_task_cb(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
eSculptMeshFilterType
@ MESH_FILTER_ENHANCE_DETAILS
@ MESH_FILTER_SURFACE_SMOOTH
@ MESH_FILTER_INFLATE
@ MESH_FILTER_SMOOTH
@ MESH_FILTER_SCALE
@ MESH_FILTER_RELAX
@ MESH_FILTER_ERASE_DISPLACEMENT
@ MESH_FILTER_RANDOM
@ MESH_FILTER_SPHERE
@ MESH_FILTER_RELAX_FACE_SETS
@ MESH_FILTER_SHARPEN
void SCULPT_filter_zero_disabled_axis_components(float r_v[3], struct FilterCache *filter_cache)
void SCULPT_filter_to_orientation_space(float r_v[3], struct FilterCache *filter_cache)
static void mesh_filter_enhance_details_init_directions(SculptSession *ss)
static void mesh_filter_init_limit_surface_co(SculptSession *ss)
static EnumPropertyItem prop_mesh_filter_deform_axis_items[]
static void mesh_filter_surface_smooth_displace_task_cb(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
static EnumPropertyItem prop_mesh_filter_types[]
void SCULPT_filter_to_object_space(float r_v[3], struct FilterCache *filter_cache)
static bool sculpt_mesh_filter_needs_pmap(eSculptMeshFilterType filter_type)
static void mesh_filter_surface_smooth_init(SculptSession *ss, const float shape_preservation, const float current_vertex_displacement)
void SCULPT_filter_cache_init(bContext *C, Object *ob, Sculpt *sd, const int undo_type)
static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void filter_cache_init_task_cb(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
static void mesh_filter_sharpen_init(SculptSession *ss, const float smooth_ratio, const float intensify_detail_strength, const int curvature_smooth_iterations)
static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static EnumPropertyItem prop_mesh_filter_orientation_items[]
eMeshFilterDeformAxis
@ MESH_FILTER_DEFORM_X
@ MESH_FILTER_DEFORM_Y
@ MESH_FILTER_DEFORM_Z
void SCULPT_filter_cache_free(SculptSession *ss)
void SCULPT_undo_push_begin(struct Object *ob, const char *name)
Definition: sculpt_undo.c:1383
void SCULPT_surface_smooth_laplacian_step(SculptSession *ss, float *disp, const float co[3], float(*laplacian_disp)[3], const int v_index, const float origco[3], const float alpha)
#define SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator)
SculptFilterOrientation
@ SCULPT_FILTER_ORIENTATION_WORLD
@ SCULPT_FILTER_ORIENTATION_VIEW
@ SCULPT_FILTER_ORIENTATION_LOCAL
void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int index)
void SCULPT_surface_smooth_displace_step(SculptSession *ss, float *co, float(*laplacian_disp)[3], const int v_index, const float beta, const float fade)
@ SCULPT_UPDATE_COORDS
Definition: sculpt_intern.h:58
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator)
void SCULPT_undo_push_end(void)
Definition: sculpt_undo.c:1400
SculptUndoNode * SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
Definition: sculpt_undo.c:1292
void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3], int index)
Definition: sculpt_smooth.c:65
@ SCULPT_UNDO_COORDS
float surface_smooth_current_vertex
float(* detail_directions)[3]
float * prev_mask
int * mask_update_it
AutomaskingCache * automasking
SculptFilterOrientation orientation
float * normal_factor
int * prev_face_set
float viewmat_inv[4][4]
float * sharpen_factor
float viewmat[4][4]
int sharpen_curvature_smooth_iterations
float obmat[4][4]
float(* surface_smooth_laplacian_disp)[3]
bool enabled_axis[3]
float sharpen_smooth_ratio
PBVHNode ** nodes
float(* limit_surface_co)[3]
float sharpen_intensify_detail_strength
SculptClothSimulation * cloth_sim
float surface_smooth_shape_preservation
float obmat_inv[4][4]
bool enabled_force_axis[3]
float obmat[4][4]
struct SculptSession * sculpt
struct MVert * mvert
Definition: BKE_pbvh.h:372
float * co
Definition: BKE_pbvh.h:374
float * mask
Definition: BKE_pbvh.h:377
float viewmat[4][4]
float viewinv[4][4]
const float * co
const short * no
struct SubdivCCG * subdiv_ccg
Definition: BKE_paint.h:501
struct KeyBlock * shapekey_active
Definition: BKE_paint.h:468
struct FilterCache * filter_cache
Definition: BKE_paint.h:519
struct PBVH * pbvh
Definition: BKE_paint.h:504
bool deform_modifiers_active
Definition: BKE_paint.h:509
struct RegionView3D * rv3d
Definition: ED_view3d.h:83
short val
Definition: WM_types.h:579
short type
Definition: WM_types.h:577
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
struct PointerRNA * ptr
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: svm_noise.h:37
uint len
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ MOUSEMOVE
@ LEFTMOUSE
wmOperatorType * ot
Definition: wm_files.c:3156