Blender  V3.3
sculpt_filter_mesh.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_blenlib.h"
11 #include "BLI_hash.h"
12 #include "BLI_math.h"
13 #include "BLI_task.h"
14 
15 #include "DNA_mesh_types.h"
16 #include "DNA_meshdata_types.h"
17 
18 #include "BKE_brush.h"
19 #include "BKE_context.h"
20 #include "BKE_mesh.h"
21 #include "BKE_mesh_mapping.h"
22 #include "BKE_object.h"
23 #include "BKE_paint.h"
24 #include "BKE_pbvh.h"
25 #include "BKE_scene.h"
26 
27 #include "DEG_depsgraph.h"
28 
29 #include "WM_api.h"
30 #include "WM_message.h"
31 #include "WM_toolsystem.h"
32 #include "WM_types.h"
33 
34 #include "ED_object.h"
35 #include "ED_screen.h"
36 #include "ED_sculpt.h"
37 #include "ED_view3d.h"
38 #include "paint_intern.h"
39 #include "sculpt_intern.h"
40 
41 #include "RNA_access.h"
42 #include "RNA_define.h"
43 
44 #include "UI_interface.h"
45 
46 #include "bmesh.h"
47 
48 #include <math.h>
49 #include <stdlib.h>
50 
51 void SCULPT_filter_to_orientation_space(float r_v[3], struct FilterCache *filter_cache)
52 {
53  switch (filter_cache->orientation) {
55  /* Do nothing, Sculpt Mode already works in object space. */
56  break;
58  mul_mat3_m4_v3(filter_cache->obmat, r_v);
59  break;
61  mul_mat3_m4_v3(filter_cache->obmat, r_v);
62  mul_mat3_m4_v3(filter_cache->viewmat, r_v);
63  break;
64  }
65 }
66 
67 void SCULPT_filter_to_object_space(float r_v[3], struct FilterCache *filter_cache)
68 {
69  switch (filter_cache->orientation) {
71  /* Do nothing, Sculpt Mode already works in object space. */
72  break;
74  mul_mat3_m4_v3(filter_cache->obmat_inv, r_v);
75  break;
77  mul_mat3_m4_v3(filter_cache->viewmat_inv, r_v);
78  mul_mat3_m4_v3(filter_cache->obmat_inv, r_v);
79  break;
80  }
81 }
82 
83 void SCULPT_filter_zero_disabled_axis_components(float r_v[3], struct FilterCache *filter_cache)
84 {
85  SCULPT_filter_to_orientation_space(r_v, filter_cache);
86  for (int axis = 0; axis < 3; axis++) {
87  if (!filter_cache->enabled_force_axis[axis]) {
88  r_v[axis] = 0.0f;
89  }
90  }
91  SCULPT_filter_to_object_space(r_v, filter_cache);
92 }
93 
94 static void filter_cache_init_task_cb(void *__restrict userdata,
95  const int i,
96  const TaskParallelTLS *__restrict UNUSED(tls))
97 {
98  SculptThreadedTaskData *data = userdata;
99  PBVHNode *node = data->nodes[i];
100 
101  SCULPT_undo_push_node(data->ob, node, data->filter_undo_type);
102 }
103 
104 void SCULPT_filter_cache_init(bContext *C, Object *ob, Sculpt *sd, const int undo_type)
105 {
106  SculptSession *ss = ob->sculpt;
107  PBVH *pbvh = ob->sculpt->pbvh;
108 
109  ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
110 
111  ss->filter_cache->random_seed = rand();
112 
113  if (undo_type == SCULPT_UNDO_COLOR) {
115  }
116 
117  const float center[3] = {0.0f};
118  SculptSearchSphereData search_data = {
119  .original = true,
120  .center = center,
121  .radius_squared = FLT_MAX,
122  .ignore_fully_ineffective = true,
123 
124  };
127  &search_data,
128  &ss->filter_cache->nodes,
129  &ss->filter_cache->totnode);
130 
131  for (int i = 0; i < ss->filter_cache->totnode; i++) {
133  }
134 
135  /* mesh->runtime.subdiv_ccg is not available. Updating of the normals is done during drawing.
136  * Filters can't use normals in multires. */
137  if (BKE_pbvh_type(ss->pbvh) != PBVH_GRIDS) {
139  }
140 
142  .sd = sd,
143  .ob = ob,
144  .nodes = ss->filter_cache->nodes,
145  .filter_undo_type = undo_type,
146  };
147 
148  TaskParallelSettings settings;
151  0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
152 
153  /* Setup orientation matrices. */
154  copy_m4_m4(ss->filter_cache->obmat, ob->obmat);
156 
158  ViewContext vc;
162 }
163 
165 {
166  if (ss->filter_cache->cloth_sim) {
168  }
169  if (ss->filter_cache->automasking) {
171  }
183 }
184 
185 typedef enum eSculptMeshFilterType {
198 
200  {MESH_FILTER_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth mesh"},
201  {MESH_FILTER_SCALE, "SCALE", 0, "Scale", "Scale mesh"},
202  {MESH_FILTER_INFLATE, "INFLATE", 0, "Inflate", "Inflate mesh"},
203  {MESH_FILTER_SPHERE, "SPHERE", 0, "Sphere", "Morph into sphere"},
204  {MESH_FILTER_RANDOM, "RANDOM", 0, "Random", "Randomize vertex positions"},
205  {MESH_FILTER_RELAX, "RELAX", 0, "Relax", "Relax mesh"},
207  "RELAX_FACE_SETS",
208  0,
209  "Relax Face Sets",
210  "Smooth the edges of all the Face Sets"},
212  "SURFACE_SMOOTH",
213  0,
214  "Surface Smooth",
215  "Smooth the surface of the mesh, preserving the volume"},
216  {MESH_FILTER_SHARPEN, "SHARPEN", 0, "Sharpen", "Sharpen the cavities of the mesh"},
218  "ENHANCE_DETAILS",
219  0,
220  "Enhance Details",
221  "Enhance the high frequency surface detail"},
223  "ERASE_DISCPLACEMENT",
224  0,
225  "Erase Displacement",
226  "Deletes the displacement of the Multires Modifier"},
227  {0, NULL, 0, NULL, NULL},
228 };
229 
230 typedef enum eMeshFilterDeformAxis {
235 
237  {MESH_FILTER_DEFORM_X, "X", 0, "X", "Deform in the X axis"},
238  {MESH_FILTER_DEFORM_Y, "Y", 0, "Y", "Deform in the Y axis"},
239  {MESH_FILTER_DEFORM_Z, "Z", 0, "Z", "Deform in the Z axis"},
240  {0, NULL, 0, NULL, NULL},
241 };
242 
245  "LOCAL",
246  0,
247  "Local",
248  "Use the local axis to limit the displacement"},
250  "WORLD",
251  0,
252  "World",
253  "Use the global axis to limit the displacement"},
255  "VIEW",
256  0,
257  "View",
258  "Use the view axis to limit the displacement"},
259  {0, NULL, 0, NULL, NULL},
260 };
261 
263 {
264  return ELEM(filter_type,
271 }
272 
273 static void mesh_filter_task_cb(void *__restrict userdata,
274  const int i,
275  const TaskParallelTLS *__restrict UNUSED(tls))
276 {
277  SculptThreadedTaskData *data = userdata;
278  SculptSession *ss = data->ob->sculpt;
279  PBVHNode *node = data->nodes[i];
280 
281  const eSculptMeshFilterType filter_type = data->filter_type;
282 
283  SculptOrigVertData orig_data;
284  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i], SCULPT_UNDO_COORDS);
285 
286  /* When using the relax face sets meshes filter,
287  * each 3 iterations, do a whole mesh relax to smooth the contents of the Face Set. */
288  /* This produces better results as the relax operation is no completely focused on the
289  * boundaries. */
290  const bool relax_face_sets = !(ss->filter_cache->iteration_count % 3 == 0);
291 
292  PBVHVertexIter vd;
294  SCULPT_orig_vert_data_update(&orig_data, &vd);
295  float orig_co[3], val[3], avg[3], disp[3], disp2[3], transform[3][3], final_pos[3];
296  float fade = vd.mask ? *vd.mask : 0.0f;
297  fade = 1.0f - fade;
298  fade *= data->filter_strength;
300 
301  if (fade == 0.0f && filter_type != MESH_FILTER_SURFACE_SMOOTH) {
302  /* Surface Smooth can't skip the loop for this vertex as it needs to calculate its
303  * laplacian_disp. This value is accessed from the vertex neighbors when deforming the
304  * vertices, so it is needed for all vertices even if they are not going to be displaced.
305  */
306  continue;
307  }
308 
310  copy_v3_v3(orig_co, vd.co);
311  }
312  else {
313  copy_v3_v3(orig_co, orig_data.co);
314  }
315 
316  if (filter_type == MESH_FILTER_RELAX_FACE_SETS) {
317  if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
318  continue;
319  }
320  }
321 
322  switch (filter_type) {
323  case MESH_FILTER_SMOOTH:
324  fade = clamp_f(fade, -1.0f, 1.0f);
326  sub_v3_v3v3(val, avg, orig_co);
327  madd_v3_v3v3fl(val, orig_co, val, fade);
328  sub_v3_v3v3(disp, val, orig_co);
329  break;
330  case MESH_FILTER_INFLATE:
331  mul_v3_v3fl(disp, orig_data.no, fade);
332  break;
333  case MESH_FILTER_SCALE:
335  scale_m3_fl(transform, 1.0f + fade);
336  copy_v3_v3(val, orig_co);
337  mul_m3_v3(transform, val);
338  sub_v3_v3v3(disp, val, orig_co);
339  break;
340  case MESH_FILTER_SPHERE:
341  normalize_v3_v3(disp, orig_co);
342  if (fade > 0.0f) {
343  mul_v3_v3fl(disp, disp, fade);
344  }
345  else {
346  mul_v3_v3fl(disp, disp, -fade);
347  }
348 
350  if (fade > 0.0f) {
351  scale_m3_fl(transform, 1.0f - fade);
352  }
353  else {
354  scale_m3_fl(transform, 1.0f + fade);
355  }
356  copy_v3_v3(val, orig_co);
357  mul_m3_v3(transform, val);
358  sub_v3_v3v3(disp2, val, orig_co);
359 
360  mid_v3_v3v3(disp, disp, disp2);
361  break;
362  case MESH_FILTER_RANDOM: {
363  float normal[3];
364  copy_v3_v3(normal, orig_data.no);
365  /* Index is not unique for multires, so hash by vertex coordinates. */
366  const uint *hash_co = (const uint *)orig_co;
367  const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^
368  BLI_hash_int_2d(hash_co[2], ss->filter_cache->random_seed);
369  mul_v3_fl(normal, hash * (1.0f / (float)0xFFFFFFFF) - 0.5f);
370  mul_v3_v3fl(disp, normal, fade);
371  break;
372  }
373  case MESH_FILTER_RELAX: {
374  SCULPT_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), false, val);
375  sub_v3_v3v3(disp, val, vd.co);
376  break;
377  }
379  SCULPT_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), relax_face_sets, val);
380  sub_v3_v3v3(disp, val, vd.co);
381  break;
382  }
385  disp,
386  vd.co,
388  vd.index,
389  orig_data.co,
391  break;
392  }
393  case MESH_FILTER_SHARPEN: {
394  const float smooth_ratio = ss->filter_cache->sharpen_smooth_ratio;
395 
396  /* This filter can't work at full strength as it needs multiple iterations to reach a
397  * stable state. */
398  fade = clamp_f(fade, 0.0f, 0.5f);
399  float disp_sharpen[3] = {0.0f, 0.0f, 0.0f};
400 
403  float disp_n[3];
404  sub_v3_v3v3(
405  disp_n, SCULPT_vertex_co_get(ss, ni.index), SCULPT_vertex_co_get(ss, vd.index));
406  mul_v3_fl(disp_n, ss->filter_cache->sharpen_factor[ni.index]);
407  add_v3_v3(disp_sharpen, disp_n);
408  }
410 
411  mul_v3_fl(disp_sharpen, 1.0f - ss->filter_cache->sharpen_factor[vd.index]);
412 
413  float disp_avg[3];
414  float avg_co[3];
415  SCULPT_neighbor_coords_average(ss, avg_co, vd.index);
416  sub_v3_v3v3(disp_avg, avg_co, vd.co);
417  mul_v3_v3fl(
418  disp_avg, disp_avg, smooth_ratio * pow2f(ss->filter_cache->sharpen_factor[vd.index]));
419  add_v3_v3v3(disp, disp_avg, disp_sharpen);
420 
421  /* Intensify details. */
423  float detail_strength[3];
424  copy_v3_v3(detail_strength, ss->filter_cache->detail_directions[vd.index]);
425  madd_v3_v3fl(disp,
426  detail_strength,
429  }
430  break;
431  }
432 
435  } break;
437  fade = clamp_f(fade, -1.0f, 1.0f);
438  sub_v3_v3v3(disp, ss->filter_cache->limit_surface_co[vd.index], orig_co);
439  mul_v3_fl(disp, fade);
440  break;
441  }
442  }
443 
445  for (int it = 0; it < 3; it++) {
446  if (!ss->filter_cache->enabled_axis[it]) {
447  disp[it] = 0.0f;
448  }
449  }
451 
453  madd_v3_v3v3fl(final_pos, vd.co, disp, clamp_f(fade, 0.0f, 1.0f));
454  }
455  else {
456  add_v3_v3v3(final_pos, orig_co, disp);
457  }
458  copy_v3_v3(vd.co, final_pos);
459  if (vd.mvert) {
461  }
462  }
464 
466 }
467 
469 {
470  const int totvert = SCULPT_vertex_count_get(ss);
471  FilterCache *filter_cache = ss->filter_cache;
472 
473  filter_cache->detail_directions = MEM_malloc_arrayN(
474  totvert, sizeof(float[3]), "detail directions");
475  for (int i = 0; i < totvert; i++) {
476  float avg[3];
477  SCULPT_neighbor_coords_average(ss, avg, i);
478  sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i));
479  }
480 }
481 
483  const float shape_preservation,
484  const float current_vertex_displacement)
485 {
486  const int totvert = SCULPT_vertex_count_get(ss);
487  FilterCache *filter_cache = ss->filter_cache;
488 
490  totvert, sizeof(float[3]), "surface smooth displacement");
491  filter_cache->surface_smooth_shape_preservation = shape_preservation;
492  filter_cache->surface_smooth_current_vertex = current_vertex_displacement;
493 }
494 
496 {
497  const int totvert = SCULPT_vertex_count_get(ss);
498  FilterCache *filter_cache = ss->filter_cache;
499 
500  filter_cache->limit_surface_co = MEM_malloc_arrayN(
501  totvert, sizeof(float[3]), "limit surface co");
502  for (int i = 0; i < totvert; i++) {
503  SCULPT_vertex_limit_surface_get(ss, i, filter_cache->limit_surface_co[i]);
504  }
505 }
506 
508  const float smooth_ratio,
509  const float intensify_detail_strength,
510  const int curvature_smooth_iterations)
511 {
512  const int totvert = SCULPT_vertex_count_get(ss);
513  FilterCache *filter_cache = ss->filter_cache;
514 
515  filter_cache->sharpen_smooth_ratio = smooth_ratio;
516  filter_cache->sharpen_intensify_detail_strength = intensify_detail_strength;
517  filter_cache->sharpen_curvature_smooth_iterations = curvature_smooth_iterations;
518  filter_cache->sharpen_factor = MEM_malloc_arrayN(totvert, sizeof(float), "sharpen factor");
519  filter_cache->detail_directions = MEM_malloc_arrayN(
520  totvert, sizeof(float[3]), "sharpen detail direction");
521 
522  for (int i = 0; i < totvert; i++) {
523  float avg[3];
524  SCULPT_neighbor_coords_average(ss, avg, i);
525  sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i));
526  filter_cache->sharpen_factor[i] = len_v3(filter_cache->detail_directions[i]);
527  }
528 
529  float max_factor = 0.0f;
530  for (int i = 0; i < totvert; i++) {
531  if (filter_cache->sharpen_factor[i] > max_factor) {
532  max_factor = filter_cache->sharpen_factor[i];
533  }
534  }
535 
536  max_factor = 1.0f / max_factor;
537  for (int i = 0; i < totvert; i++) {
538  filter_cache->sharpen_factor[i] *= max_factor;
539  filter_cache->sharpen_factor[i] = 1.0f - pow2f(1.0f - filter_cache->sharpen_factor[i]);
540  }
541 
542  /* Smooth the calculated factors and directions to remove high frequency detail. */
543  for (int smooth_iterations = 0;
544  smooth_iterations < filter_cache->sharpen_curvature_smooth_iterations;
545  smooth_iterations++) {
546  for (int i = 0; i < totvert; i++) {
547  float direction_avg[3] = {0.0f, 0.0f, 0.0f};
548  float sharpen_avg = 0;
549  int total = 0;
550 
553  add_v3_v3(direction_avg, filter_cache->detail_directions[ni.index]);
554  sharpen_avg += filter_cache->sharpen_factor[ni.index];
555  total++;
556  }
558 
559  if (total > 0) {
560  mul_v3_v3fl(filter_cache->detail_directions[i], direction_avg, 1.0f / total);
561  filter_cache->sharpen_factor[i] = sharpen_avg / total;
562  }
563  }
564  }
565 }
566 
568  void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
569 {
570  SculptThreadedTaskData *data = userdata;
571  SculptSession *ss = data->ob->sculpt;
572  PBVHNode *node = data->nodes[i];
573  PBVHVertexIter vd;
574 
576  float fade = vd.mask ? *vd.mask : 0.0f;
577  fade = 1.0f - fade;
578  fade *= data->filter_strength;
580  if (fade == 0.0f) {
581  continue;
582  }
583 
585  vd.co,
587  vd.index,
589  clamp_f(fade, 0.0f, 1.0f));
590  }
592 }
593 
594 static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
595 {
598  SculptSession *ss = ob->sculpt;
600  eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type");
601  float filter_strength = RNA_float_get(op->ptr, "strength");
602 
603  if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
607  return OPERATOR_FINISHED;
608  }
609 
610  if (event->type != MOUSEMOVE) {
611  return OPERATOR_RUNNING_MODAL;
612  }
613 
614  const float len = event->prev_press_xy[0] - event->xy[0];
615  filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
616 
618 
619  bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type);
620  BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, false);
621 
623  .sd = sd,
624  .ob = ob,
625  .nodes = ss->filter_cache->nodes,
626  .filter_type = filter_type,
627  .filter_strength = filter_strength,
628  };
629 
630  TaskParallelSettings settings;
633 
634  if (filter_type == MESH_FILTER_SURFACE_SMOOTH) {
636  ss->filter_cache->totnode,
637  &data,
639  &settings);
640  }
641 
643 
644  if (ss->deform_modifiers_active || ss->shapekey_active) {
645  SCULPT_flush_stroke_deform(sd, ob, true);
646  }
647 
648  /* The relax mesh filter needs the updated normals of the modified mesh after each iteration. */
651  }
652 
654 
655  return OPERATOR_RUNNING_MODAL;
656 }
657 
658 static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
659 {
663  SculptSession *ss = ob->sculpt;
664 
665  const eMeshFilterDeformAxis deform_axis = RNA_enum_get(op->ptr, "deform_axis");
666  const eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type");
667  const bool use_automasking = SCULPT_is_automasking_enabled(sd, ss, NULL);
668  const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type) || use_automasking;
669 
670  if (deform_axis == 0) {
671  /* All axis are disabled, so the filter is not going to produce any deformation. */
672  return OPERATOR_CANCELLED;
673  }
674 
675  if (use_automasking) {
676  /* Update the active face set manually as the paint cursor is not enabled when using the Mesh
677  * Filter Tool. */
678  float mval_fl[2] = {UNPACK2(event->mval)};
680  SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
681  }
682 
684  BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_topology_info, false, false);
685  if (needs_topology_info) {
687  }
688 
689  SCULPT_undo_push_begin(ob, "Mesh Filter");
690 
692 
693  FilterCache *filter_cache = ss->filter_cache;
694  filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
695  filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
696 
697  switch (filter_type) {
699  const float shape_preservation = RNA_float_get(op->ptr, "surface_smooth_shape_preservation");
700  const float current_vertex_displacement = RNA_float_get(op->ptr,
701  "surface_smooth_current_vertex");
702  mesh_filter_surface_smooth_init(ss, shape_preservation, current_vertex_displacement);
703  break;
704  }
705  case MESH_FILTER_SHARPEN: {
706  const float smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio");
707  const float intensify_detail_strength = RNA_float_get(op->ptr,
708  "sharpen_intensify_detail_strength");
709  const int curvature_smooth_iterations = RNA_int_get(op->ptr,
710  "sharpen_curvature_smooth_iterations");
712  ss, smooth_ratio, intensify_detail_strength, curvature_smooth_iterations);
713  break;
714  }
717  break;
718  }
721  break;
722  }
723  default:
724  break;
725  }
726 
727  ss->filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
728  ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
729  ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
730 
731  SculptFilterOrientation orientation = RNA_enum_get(op->ptr, "orientation");
732  ss->filter_cache->orientation = orientation;
733 
735  return OPERATOR_RUNNING_MODAL;
736 }
737 
739 {
740  /* Identifiers. */
741  ot->name = "Filter Mesh";
742  ot->idname = "SCULPT_OT_mesh_filter";
743  ot->description = "Applies a filter to modify the current mesh";
744 
745  /* API callbacks. */
749 
751 
752  /* RNA. */
754  "type",
757  "Filter Type",
758  "Operation that is going to be applied to the mesh");
760  ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
762  "deform_axis",
765  "Deform Axis",
766  "Apply the deformation in the selected axis");
768  "orientation",
771  "Orientation",
772  "Orientation of the axis to limit the filter displacement");
773 
774  /* Surface Smooth Mesh Filter properties. */
776  "surface_smooth_shape_preservation",
777  0.5f,
778  0.0f,
779  1.0f,
780  "Shape Preservation",
781  "How much of the original shape is preserved when smoothing",
782  0.0f,
783  1.0f);
785  "surface_smooth_current_vertex",
786  0.5f,
787  0.0f,
788  1.0f,
789  "Per Vertex Displacement",
790  "How much the position of each individual vertex influences the final result",
791  0.0f,
792  1.0f);
794  "sharpen_smooth_ratio",
795  0.35f,
796  0.0f,
797  1.0f,
798  "Smooth Ratio",
799  "How much smoothing is applied to polished surfaces",
800  0.0f,
801  1.0f);
802 
804  "sharpen_intensify_detail_strength",
805  0.0f,
806  0.0f,
807  10.0f,
808  "Intensify Details",
809  "How much creases and valleys are intensified",
810  0.0f,
811  1.0f);
812 
814  "sharpen_curvature_smooth_iterations",
815  0,
816  0,
817  10,
818  "Curvature Smooth Iterations",
819  "How much smooth the resulting shape is, ignoring high frequency details",
820  0,
821  10);
822 }
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct ToolSettings * CTX_data_tool_settings(const bContext *C)
Definition: context.c:1282
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 is_paint_tool)
Definition: paint.c:1914
#define SCULPT_FACE_SET_NONE
Definition: BKE_paint.h:267
A BVH for high poly meshes.
void BKE_pbvh_node_mark_update(PBVHNode *node)
Definition: pbvh.c:1869
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:439
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1798
void BKE_pbvh_node_mark_normals_update(PBVHNode *node)
Definition: pbvh.c:1911
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:509
void BKE_pbvh_vert_tag_update_normal(PBVH *pbvh, int index)
Definition: pbvh.c:1967
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:391
void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg)
Definition: pbvh.c:2813
@ PBVH_GRIDS
Definition: BKE_pbvh.h:235
void BKE_pbvh_ensure_node_loops(PBVH *pbvh)
Definition: pbvh.c:3280
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3211
void BKE_pbvh_search_gather(PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot)
Definition: pbvh.c:838
BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
Definition: BLI_hash.h:53
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:926
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void scale_m3_fl(float R[3][3], float scale)
Definition: math_matrix.c:2289
void mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:790
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
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 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:237
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:67
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
#define UNPACK2(a)
#define UNUSED(x)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ 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:25
#define UI_DPI_FAC
Definition: UI_interface.h:305
@ KM_RELEASE
Definition: WM_types.h:268
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
OperationNode * node
const Depsgraph * depsgraph
int len
Definition: draw_manager.c:108
IconTextureDrawCall normal
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fabsf(x)
Definition: metal/compat.h:219
#define hash
Definition: noise.c:153
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: noise.h:15
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
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:3836
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:3806
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:3597
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:3783
const float * SCULPT_vertex_co_get(SculptSession *ss, int index)
Definition: sculpt.c:125
int SCULPT_vertex_count_get(SculptSession *ss)
Definition: sculpt.c:111
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
Definition: sculpt.c:1300
void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node, SculptUndoType type)
Definition: sculpt.c:1290
void SCULPT_boundary_info_ensure(Object *object)
Definition: sculpt.c:5848
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mval[2], bool use_sampled_normal)
Definition: sculpt.c:4835
bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index)
Definition: sculpt.c:662
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
Definition: sculpt.c:103
void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags)
Definition: sculpt.c:5212
bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
Definition: sculpt.c:2467
void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
Definition: sculpt.c:5144
void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3])
Definition: sculpt.c:218
bool SCULPT_mode_poll(bContext *C)
Definition: sculpt.c:3957
void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
Definition: sculpt.c:3719
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_relax_vertex(SculptSession *ss, PBVHVertexIter *vd, float factor, bool filter_boundary_face_sets, float *r_final_pos)
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:1545
void SCULPT_undo_push_end(struct Object *ob)
Definition: sculpt_undo.c:1575
#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_surface_smooth_laplacian_step(SculptSession *ss, float *disp, const float co[3], float(*laplacian_disp)[3], int v_index, const float origco[3], float alpha)
void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int index)
@ SCULPT_UPDATE_COORDS
Definition: sculpt_intern.h:45
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator)
SculptUndoNode * SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
Definition: sculpt_undo.c:1419
void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3], int index)
Definition: sculpt_smooth.c:49
void SCULPT_surface_smooth_displace_step(SculptSession *ss, float *co, float(*laplacian_disp)[3], int v_index, float beta, float fade)
@ SCULPT_UNDO_COORDS
@ SCULPT_UNDO_COLOR
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
float(* pre_smoothed_color)[4]
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:428
float * co
Definition: BKE_pbvh.h:430
float * mask
Definition: BKE_pbvh.h:433
float viewmat[4][4]
float viewinv[4][4]
const float * co
Definition: sculpt_intern.h:87
const float * no
Definition: sculpt_intern.h:88
struct SubdivCCG * subdiv_ccg
Definition: BKE_paint.h:547
struct KeyBlock * shapekey_active
Definition: BKE_paint.h:505
struct FilterCache * filter_cache
Definition: BKE_paint.h:564
struct PBVH * pbvh
Definition: BKE_paint.h:550
bool deform_modifiers_active
Definition: BKE_paint.h:555
struct RegionView3D * rv3d
Definition: ED_view3d.h:72
short val
Definition: WM_types.h:680
int mval[2]
Definition: WM_types.h:684
short type
Definition: WM_types.h:678
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
struct PointerRNA * ptr
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ MOUSEMOVE
@ LEFTMOUSE
wmOperatorType * ot
Definition: wm_files.c:3479