Blender V5.0
sculpt_filter_mesh.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8#include "sculpt_filter.hh" // TODO- Move this function's initialization to a separate file
9
10#include <fmt/format.h>
11
13
14#include "MEM_guardedalloc.h"
15
17#include "BLI_hash.h"
18#include "BLI_index_range.hh"
19#include "BLI_math_base.hh"
20#include "BLI_math_matrix.h"
21#include "BLI_math_vector.h"
22#include "BLI_math_vector.hh"
24
25#include "BLT_translation.hh"
26
27#include "BKE_brush.hh"
28#include "BKE_context.hh"
29#include "BKE_layer.hh"
30#include "BKE_mesh.hh"
31#include "BKE_modifier.hh"
32#include "BKE_object_types.hh"
33#include "BKE_paint.hh"
34#include "BKE_paint_bvh.hh"
35#include "BKE_paint_types.hh"
36
37#include "WM_api.hh"
38#include "WM_types.hh"
39
40#include "ED_screen.hh"
41#include "ED_sculpt.hh"
42#include "ED_view3d.hh"
43
44#include "mesh_brush_common.hh"
45#include "paint_intern.hh"
46#include "sculpt_automask.hh"
47#include "sculpt_boundary.hh"
48#include "sculpt_cloth.hh"
49#include "sculpt_face_set.hh"
50#include "sculpt_intern.hh"
51#include "sculpt_smooth.hh"
52#include "sculpt_undo.hh"
53
54#include "RNA_access.hh"
55#include "RNA_define.hh"
56#include "RNA_prototypes.hh"
57
59#include "UI_resources.hh"
60
61#include "bmesh.hh"
62
63#include <algorithm>
64#include <cmath>
65#include <cstdlib>
66
68
70{
71 switch (filter_cache.orientation) {
73 return float3x3::identity();
75 return float3x3(filter_cache.obmat);
77 return float3x3(filter_cache.obmat * filter_cache.viewmat);
78 }
80 return float3x3::identity();
81}
82
84{
85 switch (filter_cache.orientation) {
87 return float3x3::identity();
89 return float3x3(filter_cache.obmat_inv);
91 return float3x3(filter_cache.viewmat_inv * filter_cache.obmat_inv);
92 }
94 return float3x3::identity();
95}
96
98 const MutableSpan<float3> vectors)
99{
100 if (filter_cache.enabled_axis[0] && filter_cache.enabled_axis[1] && filter_cache.enabled_axis[2])
101 {
102 return;
103 }
104
105 if (filter_cache.orientation == FilterOrientation::Local) {
106 for (const int i : vectors.index_range()) {
107 for (int axis = 0; axis < 3; axis++) {
108 if (!filter_cache.enabled_axis[axis]) {
109 vectors[i][axis] = 0.0f;
110 }
111 }
112 }
113 }
114
115 const float3x3 local_to_orientation = to_orientation_space(filter_cache);
116 const float3x3 orientation_to_object = to_object_space(filter_cache);
117 for (const int i : vectors.index_range()) {
118 float3 vector = local_to_orientation * vectors[i];
119 for (int axis = 0; axis < 3; axis++) {
120 if (!filter_cache.enabled_axis[axis]) {
121 vector[axis] = 0.0f;
122 }
123 }
124 vectors[i] = orientation_to_object * vector;
125 }
126}
127
128Cache::~Cache() = default;
129
131 Object &ob,
132 Sculpt &sd,
133 const undo::Type undo_type,
134 const float mval_fl[2],
135 float area_normal_radius,
136 float start_strength)
137{
138 SculptSession &ss = *ob.sculpt;
141
142 ss.filter_cache = MEM_new<filter::Cache>(__func__);
143 ss.filter_cache->start_filter_strength = start_strength;
144 ss.filter_cache->random_seed = rand();
145
147 pbvh, ss.filter_cache->node_mask_memory, [&](const bke::pbvh::Node &node) {
148 return !node_fully_masked_or_hidden(node);
149 });
150
151 undo::push_nodes(*depsgraph, ob, ss.filter_cache->node_mask, undo_type);
152
153 /* Setup orientation matrices. */
154 copy_m4_m4(ss.filter_cache->obmat.ptr(), ob.object_to_world().ptr());
155 invert_m4_m4(ss.filter_cache->obmat_inv.ptr(), ob.object_to_world().ptr());
156
158
159 ss.filter_cache->vc = vc;
160 if (vc.rv3d) {
163 }
164
166 bke::PaintRuntime *paint_runtime = sd.paint.runtime;
167
168 float3 co;
169
170 if (vc.rv3d && stroke_get_location_bvh(C, co, mval_fl, false)) {
171 /* Get radius from brush. */
172 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
173
174 float radius;
175 if (brush) {
176 radius = object_space_radius_get(vc, sd.paint, *brush, co, area_normal_radius);
177 }
178 else {
180 vc, co, float(ups->size / 2.0f) * area_normal_radius);
181 }
182
183 const float radius_sq = math::square(radius);
184
185 IndexMaskMemory memory;
186 const IndexMask node_mask = bke::pbvh::search_nodes(
187 pbvh, memory, [&](const bke::pbvh::Node &node) {
188 return !node_fully_masked_or_hidden(node) && node_in_sphere(node, co, radius_sq, true);
189 });
190
191 const std::optional<float3> area_normal = calc_area_normal(*depsgraph, *brush, ob, node_mask);
192 if (BKE_paint_brush_for_read(&sd.paint) && area_normal) {
193 ss.filter_cache->initial_normal = *area_normal;
195 }
196 else {
198 }
199
200 /* Update last stroke location */
201
202 mul_m4_v3(ob.object_to_world().ptr(), co);
203
204 add_v3_v3(paint_runtime->average_stroke_accum, co);
205 paint_runtime->average_stroke_counter++;
206 paint_runtime->last_stroke_valid = true;
207 }
208 else {
209 /* Use last normal. */
211 }
212
213 /* Update view normal */
214 float3x3 mat;
215 float3 viewDir{0.0f, 0.0f, 1.0f};
216 if (vc.rv3d) {
217 invert_m4_m4(ob.runtime->world_to_object.ptr(), ob.object_to_world().ptr());
218 copy_m3_m4(mat.ptr(), vc.rv3d->viewinv);
219 mul_m3_v3(mat.ptr(), viewDir);
220 copy_m3_m4(mat.ptr(), ob.world_to_object().ptr());
221 mul_m3_v3(mat.ptr(), viewDir);
223 }
224}
225
239
241 {int(MeshFilterType::Smooth), "SMOOTH", 0, "Smooth", "Smooth mesh"},
242 {int(MeshFilterType::Scale), "SCALE", 0, "Scale", "Scale mesh"},
243 {int(MeshFilterType::Inflate), "INFLATE", 0, "Inflate", "Inflate mesh"},
244 {int(MeshFilterType::Sphere), "SPHERE", 0, "Sphere", "Morph into sphere"},
245 {int(MeshFilterType::Random), "RANDOM", 0, "Random", "Randomize vertex positions"},
246 {int(MeshFilterType::Relax), "RELAX", 0, "Relax", "Relax mesh"},
248 "RELAX_FACE_SETS",
249 0,
250 "Relax Face Sets",
251 "Smooth the edges of all the Face Sets"},
253 "SURFACE_SMOOTH",
254 0,
255 "Surface Smooth",
256 "Smooth the surface of the mesh, preserving the volume"},
257 {int(MeshFilterType::Sharpen), "SHARPEN", 0, "Sharpen", "Sharpen the cavities of the mesh"},
259 "ENHANCE_DETAILS",
260 0,
261 "Enhance Details",
262 "Enhance the high frequency surface detail"},
264 "ERASE_DISPLACEMENT",
265 0,
266 "Erase Displacement",
267 "Deletes the displacement of the Multires Modifier"},
268 {0, nullptr, 0, nullptr, nullptr},
269};
270
276
278 {MESH_FILTER_DEFORM_X, "X", 0, "X", "Deform in the X axis"},
279 {MESH_FILTER_DEFORM_Y, "Y", 0, "Y", "Deform in the Y axis"},
280 {MESH_FILTER_DEFORM_Z, "Z", 0, "Z", "Deform in the Z axis"},
281 {0, nullptr, 0, nullptr, nullptr},
282};
283
286 "LOCAL",
287 0,
288 "Local",
289 "Use the local axis to limit the displacement"},
291 "WORLD",
292 0,
293 "World",
294 "Use the global axis to limit the displacement"},
296 "VIEW",
297 0,
298 "View",
299 "Use the view axis to limit the displacement"},
300 {0, nullptr, 0, nullptr, nullptr},
301};
302
313
322
324 const float min,
325 const float max)
326{
327 for (float &factor : factors) {
328 factor = std::clamp(factor, min, max);
329 }
330}
331
332static void calc_smooth_filter(const Depsgraph &depsgraph,
333 const Sculpt &sd,
334 const float strength,
335 Object &object,
336 const IndexMask &node_mask,
337 const bool use_original_position)
338{
339 struct LocalData {
340 Vector<float> factors;
341 Vector<float3> positions;
342 Vector<int> neighbor_offsets;
343 Vector<int> neighbor_data;
344 Vector<float3> new_positions;
345 Vector<float3> translations;
346 };
347 SculptSession &ss = *object.sculpt;
348 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
349 switch (pbvh.type()) {
351 Mesh &mesh = *static_cast<Mesh *>(object.data);
352 const MeshAttributeData attribute_data(mesh);
353 const PositionDeformData position_data(depsgraph, object);
354 const OffsetIndices faces = mesh.faces();
355 const Span<int> corner_verts = mesh.corner_verts();
356 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
359 node_mask.foreach_index(GrainSize(1), [&](const int i) {
360 LocalData &tls = all_tls.local();
361 const Span<int> verts = nodes[i].verts();
362 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
363 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
364
365 tls.factors.resize(verts.size());
366 const MutableSpan<float> factors = tls.factors;
368 attribute_data.hide_vert, attribute_data.mask, verts, factors);
370 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
371 scale_factors(factors, strength);
372 clamp_factors(factors, -1.0f, 1.0f);
373
375 corner_verts,
376 vert_to_face_map,
378 attribute_data.hide_poly,
379 verts,
380 tls.neighbor_offsets,
381 tls.neighbor_data);
382
383 tls.new_positions.resize(verts.size());
384 const MutableSpan<float3> new_positions = tls.new_positions;
386 position_data.eval, verts, neighbors, new_positions);
387
388 tls.translations.resize(verts.size());
389 const MutableSpan<float3> translations = tls.translations;
390 if (use_original_position) {
391 translations_from_new_positions(new_positions, orig_data.positions, translations);
392 }
393 else {
394 translations_from_new_positions(new_positions, positions, translations);
395 }
396 scale_translations(translations, factors);
397 if (use_original_position) {
398 reset_translations_to_original(translations, positions, orig_data.positions);
399 }
400
402 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
403 position_data.deform(translations, verts);
404 });
405 break;
406 }
408 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
409 const OffsetIndices faces = base_mesh.faces();
410 const Span<int> corner_verts = base_mesh.corner_verts();
411
412 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
415 node_mask.foreach_index(GrainSize(1), [&](const int i) {
416 LocalData &tls = all_tls.local();
417 const Span<int> grids = nodes[i].grids();
418 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
419 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
420
421 tls.factors.resize(positions.size());
422 const MutableSpan<float> factors = tls.factors;
423 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
425 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
426 scale_factors(factors, strength);
427 clamp_factors(factors, -1.0f, 1.0f);
428
429 tls.new_positions.resize(positions.size());
430 const MutableSpan<float3> new_positions = tls.new_positions;
432 faces, corner_verts, ss.vertex_info.boundary, subdiv_ccg, grids, new_positions);
433
434 tls.translations.resize(positions.size());
435 const MutableSpan<float3> translations = tls.translations;
436 if (use_original_position) {
437 translations_from_new_positions(new_positions, orig_data.positions, translations);
438 }
439 else {
440 translations_from_new_positions(new_positions, positions, translations);
441 }
442 scale_translations(translations, factors);
443 if (use_original_position) {
444 reset_translations_to_original(translations, positions, orig_data.positions);
445 }
446
448 clip_and_lock_translations(sd, ss, positions, translations);
449 apply_translations(translations, grids, subdiv_ccg);
450 });
451 break;
452 }
454 BMesh &bm = *ss.bm;
457 node_mask.foreach_index(GrainSize(1), [&](const int i) {
458 LocalData &tls = all_tls.local();
460 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
461 Array<float3> orig_positions(verts.size());
462 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
463
464 tls.factors.resize(verts.size());
465 const MutableSpan<float> factors = tls.factors;
468 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
469 scale_factors(factors, strength);
470 clamp_factors(factors, -1.0f, 1.0f);
471
472 tls.new_positions.resize(verts.size());
473 const MutableSpan<float3> new_positions = tls.new_positions;
475
476 tls.translations.resize(verts.size());
477 const MutableSpan<float3> translations = tls.translations;
478 if (use_original_position) {
479 translations_from_new_positions(new_positions, orig_positions, translations);
480 }
481 else {
482 translations_from_new_positions(new_positions, positions, translations);
483 }
484 scale_translations(translations, factors);
485 if (use_original_position) {
486 reset_translations_to_original(translations, positions, orig_positions);
487 }
488
490 clip_and_lock_translations(sd, ss, positions, translations);
491 apply_translations(translations, verts);
492 });
493 break;
494 }
495 }
496}
497
498static void calc_inflate_filter(const Depsgraph &depsgraph,
499 const Sculpt &sd,
500 const float strength,
501 Object &object,
502 const IndexMask &node_mask)
503{
504 struct LocalData {
505 Vector<float> factors;
506 Vector<float3> positions;
507 Vector<float3> translations;
508 };
509 SculptSession &ss = *object.sculpt;
510 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
511 switch (pbvh.type()) {
513 Mesh &mesh = *static_cast<Mesh *>(object.data);
514 bke::AttributeAccessor attributes = mesh.attributes();
515 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
516 const VArraySpan mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
517 const PositionDeformData position_data(depsgraph, object);
520 node_mask.foreach_index(GrainSize(1), [&](const int i) {
521 LocalData &tls = all_tls.local();
522 const Span<int> verts = nodes[i].verts();
523 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
524
525 tls.factors.resize(verts.size());
526 const MutableSpan<float> factors = tls.factors;
527 fill_factor_from_hide_and_mask(hide_vert, mask, verts, factors);
529 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
530 scale_factors(factors, strength);
531
532 tls.translations.resize(verts.size());
533 const MutableSpan<float3> translations = tls.translations;
534 translations.copy_from(orig_data.normals);
535 scale_translations(translations, factors);
536
538 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
539 position_data.deform(translations, verts);
540 });
541 break;
542 }
544 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
547 node_mask.foreach_index(GrainSize(1), [&](const int i) {
548 LocalData &tls = all_tls.local();
549 const Span<int> grids = nodes[i].grids();
550 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
551 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
552
553 tls.factors.resize(positions.size());
554 const MutableSpan<float> factors = tls.factors;
555 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
557 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
558 scale_factors(factors, strength);
559
560 tls.translations.resize(positions.size());
561 const MutableSpan<float3> translations = tls.translations;
562 translations.copy_from(orig_data.normals);
563 scale_translations(translations, factors);
564
566 clip_and_lock_translations(sd, ss, positions, translations);
567 apply_translations(translations, grids, subdiv_ccg);
568 });
569 break;
570 }
572 BMesh &bm = *ss.bm;
575 node_mask.foreach_index(GrainSize(1), [&](const int i) {
576 LocalData &tls = all_tls.local();
578 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
579 Array<float3> orig_positions(verts.size());
580 Array<float3> orig_normals(verts.size());
581 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
582
583 tls.factors.resize(verts.size());
584 const MutableSpan<float> factors = tls.factors;
587 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
588 scale_factors(factors, strength);
589
590 tls.translations.resize(verts.size());
591 const MutableSpan<float3> translations = tls.translations;
592 translations.copy_from(orig_normals);
593 scale_translations(translations, factors);
594
596 clip_and_lock_translations(sd, ss, positions, translations);
597 apply_translations(translations, verts);
598 });
599 break;
600 }
601 }
602}
603
604static void calc_scale_filter(const Depsgraph &depsgraph,
605 const Sculpt &sd,
606 const float strength,
607 Object &object,
608 const IndexMask &node_mask)
609{
610 struct LocalData {
611 Vector<float> factors;
612 Vector<float3> positions;
613 Vector<float3> translations;
614 };
615 SculptSession &ss = *object.sculpt;
616 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
617 switch (pbvh.type()) {
619 Mesh &mesh = *static_cast<Mesh *>(object.data);
620 const MeshAttributeData attribute_data(mesh);
621 const PositionDeformData position_data(depsgraph, object);
624 node_mask.foreach_index(GrainSize(1), [&](const int i) {
625 LocalData &tls = all_tls.local();
626 const Span<int> verts = nodes[i].verts();
627 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
628
629 tls.factors.resize(verts.size());
630 const MutableSpan<float> factors = tls.factors;
632 attribute_data.hide_vert, attribute_data.mask, verts, factors);
634 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
635 scale_factors(factors, strength);
636
637 tls.translations.resize(verts.size());
638 const MutableSpan<float3> translations = tls.translations;
639 translations.copy_from(orig_data.positions);
640 scale_translations(translations, factors);
641
643 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
644 position_data.deform(translations, verts);
645 });
646 break;
647 }
649 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
652 node_mask.foreach_index(GrainSize(1), [&](const int i) {
653 LocalData &tls = all_tls.local();
654 const Span<int> grids = nodes[i].grids();
655 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
656 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
657
658 tls.factors.resize(positions.size());
659 const MutableSpan<float> factors = tls.factors;
660 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
662 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
663 scale_factors(factors, strength);
664
665 tls.translations.resize(positions.size());
666 const MutableSpan<float3> translations = tls.translations;
667 translations.copy_from(orig_data.positions);
668 scale_translations(translations, factors);
669
671 clip_and_lock_translations(sd, ss, positions, translations);
672 apply_translations(translations, grids, subdiv_ccg);
673 });
674 break;
675 }
677 BMesh &bm = *ss.bm;
680 node_mask.foreach_index(GrainSize(1), [&](const int i) {
681 LocalData &tls = all_tls.local();
683 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
684 Array<float3> orig_positions(verts.size());
685 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
686
687 tls.factors.resize(verts.size());
688 const MutableSpan<float> factors = tls.factors;
691 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
692 scale_factors(factors, strength);
693
694 tls.translations.resize(positions.size());
695 const MutableSpan<float3> translations = tls.translations;
696 translations.copy_from(orig_positions);
697 scale_translations(translations, factors);
698
700 clip_and_lock_translations(sd, ss, positions, translations);
701 apply_translations(translations, verts);
702 });
703 break;
704 }
705 }
706}
707
709 const Span<float> factors,
710 const MutableSpan<float3> translations)
711{
712 for (const int i : positions.index_range()) {
713 translations[i] = math::midpoint(math::normalize(positions[i]), -positions[i]) *
714 math::abs(factors[i]);
715 }
716}
717
718static void calc_sphere_filter(const Depsgraph &depsgraph,
719 const Sculpt &sd,
720 const float strength,
721 Object &object,
722 const IndexMask &node_mask)
723{
724 struct LocalData {
725 Vector<float> factors;
726 Vector<float3> positions;
727 Vector<float3> translations;
728 };
729 SculptSession &ss = *object.sculpt;
730 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
731 switch (pbvh.type()) {
733 Mesh &mesh = *static_cast<Mesh *>(object.data);
734 const PositionDeformData position_data(depsgraph, object);
735 const MeshAttributeData attribute_data(mesh);
738 node_mask.foreach_index(GrainSize(1), [&](const int i) {
739 LocalData &tls = all_tls.local();
740 const Span<int> verts = nodes[i].verts();
741 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
742
743 tls.factors.resize(verts.size());
744 const MutableSpan<float> factors = tls.factors;
746 attribute_data.hide_vert, attribute_data.mask, verts, factors);
748 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
749 scale_factors(factors, strength);
750
751 tls.translations.resize(verts.size());
752 const MutableSpan<float3> translations = tls.translations;
753 calc_sphere_translations(positions, factors, translations);
754
756 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
757 position_data.deform(translations, verts);
758 });
759 break;
760 }
762 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
765 node_mask.foreach_index(GrainSize(1), [&](const int i) {
766 LocalData &tls = all_tls.local();
767 const Span<int> grids = nodes[i].grids();
768 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
769
770 tls.factors.resize(positions.size());
771 const MutableSpan<float> factors = tls.factors;
772 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
774 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
775 scale_factors(factors, strength);
776
777 tls.translations.resize(positions.size());
778 const MutableSpan<float3> translations = tls.translations;
779 calc_sphere_translations(positions, factors, translations);
780
782 clip_and_lock_translations(sd, ss, positions, translations);
783 apply_translations(translations, grids, subdiv_ccg);
784 });
785 break;
786 }
788 BMesh &bm = *ss.bm;
791 node_mask.foreach_index(GrainSize(1), [&](const int i) {
792 LocalData &tls = all_tls.local();
794 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
795
796 tls.factors.resize(verts.size());
797 const MutableSpan<float> factors = tls.factors;
800 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
801 scale_factors(factors, strength);
802
803 tls.translations.resize(verts.size());
804 const MutableSpan<float3> translations = tls.translations;
805 calc_sphere_translations(positions, factors, translations);
806
808 clip_and_lock_translations(sd, ss, positions, translations);
809 apply_translations(translations, verts);
810 });
811 break;
812 }
813 }
814}
815
816BLI_NOINLINE static void randomize_factors(const Span<float3> positions,
817 const int seed,
818 const MutableSpan<float> factors)
819{
820 BLI_assert(positions.size() == factors.size());
821 for (const int i : positions.index_range()) {
822 const uint *hash_co = (const uint *)&positions[i];
823 const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^ BLI_hash_int_2d(hash_co[2], seed);
824 factors[i] *= (hash * (1.0f / float(0xFFFFFFFF)) - 0.5f);
825 }
826}
827
828static void calc_random_filter(const Depsgraph &depsgraph,
829 const Sculpt &sd,
830 const float strength,
831 Object &object,
832 const IndexMask &node_mask)
833{
834 struct LocalData {
835 Vector<float> factors;
836 Vector<float3> positions;
837 Vector<float3> translations;
838 };
839 SculptSession &ss = *object.sculpt;
840 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
841 switch (pbvh.type()) {
843 Mesh &mesh = *static_cast<Mesh *>(object.data);
844 const MeshAttributeData attribute_data(mesh);
845 const PositionDeformData position_data(depsgraph, object);
848 node_mask.foreach_index(GrainSize(1), [&](const int i) {
849 LocalData &tls = all_tls.local();
850 const Span<int> verts = nodes[i].verts();
851 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
852 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
853
854 tls.factors.resize(verts.size());
855 const MutableSpan<float> factors = tls.factors;
857 attribute_data.hide_vert, attribute_data.mask, verts, factors);
859 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
860 scale_factors(factors, strength);
861
862 randomize_factors(positions, ss.filter_cache->random_seed, factors);
863 tls.translations.resize(verts.size());
864 const MutableSpan<float3> translations = tls.translations;
865 translations.copy_from(orig_data.normals);
866 scale_translations(translations, factors);
867
869 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
870 position_data.deform(translations, verts);
871 });
872 break;
873 }
875 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
878 node_mask.foreach_index(GrainSize(1), [&](const int i) {
879 LocalData &tls = all_tls.local();
880 const Span<int> grids = nodes[i].grids();
881 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
882 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
883
884 tls.factors.resize(positions.size());
885 const MutableSpan<float> factors = tls.factors;
886 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
888 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
889 scale_factors(factors, strength);
890
891 randomize_factors(positions, ss.filter_cache->random_seed, factors);
892 tls.translations.resize(positions.size());
893 const MutableSpan<float3> translations = tls.translations;
894 translations.copy_from(orig_data.normals);
895 scale_translations(translations, factors);
896
898 clip_and_lock_translations(sd, ss, positions, translations);
899 apply_translations(translations, grids, subdiv_ccg);
900 });
901 break;
902 }
904 BMesh &bm = *ss.bm;
907 node_mask.foreach_index(GrainSize(1), [&](const int i) {
908 LocalData &tls = all_tls.local();
910 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
911 Array<float3> orig_positions(verts.size());
912 Array<float3> orig_normals(verts.size());
913 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
914
915 tls.factors.resize(verts.size());
916 const MutableSpan<float> factors = tls.factors;
919 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
920 scale_factors(factors, strength);
921
922 randomize_factors(positions, ss.filter_cache->random_seed, factors);
923 tls.translations.resize(verts.size());
924 const MutableSpan<float3> translations = tls.translations;
925 translations.copy_from(orig_normals);
926 scale_translations(translations, factors);
927
929 clip_and_lock_translations(sd, ss, positions, translations);
930 apply_translations(translations, verts);
931 });
932 break;
933 }
934 }
935}
936
937static void calc_relax_filter(const Depsgraph &depsgraph,
938 const Sculpt &sd,
939 const float strength,
940 Object &object,
941 const IndexMask &node_mask)
942{
943 SculptSession &ss = *object.sculpt;
944 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
946 switch (pbvh.type()) {
947 struct LocalData {
948 Vector<float> factors;
949 Vector<float3> translations;
950 };
952 Mesh &mesh = *static_cast<Mesh *>(object.data);
953 const PositionDeformData position_data(depsgraph, object);
954 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
955 const OffsetIndices faces = mesh.faces();
956 const Span<int> corner_verts = mesh.corner_verts();
957 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
958 const MeshAttributeData attribute_data(mesh);
961 node_mask.foreach_index(GrainSize(1), [&](const int i) {
962 LocalData &tls = all_tls.local();
963 const Span<int> verts = nodes[i].verts();
964
965 tls.factors.resize(verts.size());
966 const MutableSpan<float> factors = tls.factors;
968 attribute_data.hide_vert, attribute_data.mask, verts, factors);
970 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
971 scale_factors(factors, strength);
972 clamp_factors(factors, 0.0f, 1.0f);
973
974 tls.translations.resize(verts.size());
975 const MutableSpan<float3> translations = tls.translations;
977 vert_normals,
978 faces,
979 corner_verts,
980 vert_to_face_map,
982 attribute_data.face_sets,
983 attribute_data.hide_poly,
984 false,
985 verts,
986 factors,
987 translations);
988
990 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
991 position_data.deform(translations, verts);
992 });
993 break;
994 }
996 struct LocalData {
997 Vector<float> factors;
998 Vector<float3> positions;
999 Vector<float3> translations;
1000 };
1001 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
1002 const OffsetIndices faces = base_mesh.faces();
1003 const Span<int> corner_verts = base_mesh.corner_verts();
1004 const GroupedSpan<int> vert_to_face_map = base_mesh.vert_to_face_map();
1005 const bke::AttributeAccessor attributes = base_mesh.attributes();
1006 const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set",
1008 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1011 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1012 LocalData &tls = all_tls.local();
1013 const Span<int> grids = nodes[i].grids();
1014 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1015
1016 tls.factors.resize(positions.size());
1017 const MutableSpan<float> factors = tls.factors;
1018 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1020 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1021 scale_factors(factors, strength);
1022 clamp_factors(factors, 0.0f, 1.0f);
1023
1024 tls.translations.resize(positions.size());
1025 const MutableSpan<float3> translations = tls.translations;
1027 faces,
1028 corner_verts,
1029 face_sets,
1030 vert_to_face_map,
1032 grids,
1033 false,
1034 factors,
1035 translations);
1036
1038 clip_and_lock_translations(sd, ss, positions, translations);
1039 apply_translations(translations, grids, subdiv_ccg);
1040 });
1041 break;
1042 }
1044 struct LocalData {
1045 Vector<float> factors;
1046 Vector<float3> positions;
1047 Vector<float3> translations;
1048 };
1049 BMesh &bm = *ss.bm;
1050 const int face_set_offset = CustomData_get_offset_named(
1051 &bm.pdata, CD_PROP_INT32, ".sculpt_face_set");
1052
1055 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1056 LocalData &tls = all_tls.local();
1058 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1059
1060 tls.factors.resize(verts.size());
1061 const MutableSpan<float> factors = tls.factors;
1064 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1065 scale_factors(factors, strength);
1066 clamp_factors(factors, 0.0f, 1.0f);
1067
1068 tls.translations.resize(verts.size());
1069 const MutableSpan<float3> translations = tls.translations;
1071 verts, positions, face_set_offset, false, factors, translations);
1072
1074 clip_and_lock_translations(sd, ss, positions, translations);
1075 apply_translations(translations, verts);
1076 });
1077 break;
1078 }
1079 }
1080}
1081
1082static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
1083 const Sculpt &sd,
1084 const float strength,
1085 Object &object,
1086 const IndexMask &node_mask)
1087{
1088 SculptSession &ss = *object.sculpt;
1089 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1090 bke::pbvh::update_normals(depsgraph, object, pbvh);
1091
1092 /* When using the relax face sets meshes filter, each 3 iterations, do a whole mesh relax to
1093 * smooth the contents of the Face Set. This produces better results as the relax operation is no
1094 * completely focused on the boundaries. */
1095 const bool relax_face_sets = !(ss.filter_cache->iteration_count % 3 == 0);
1096
1097 switch (pbvh.type()) {
1098 case bke::pbvh::Type::Mesh: {
1099 struct LocalData {
1100 Vector<float> factors;
1101 Vector<float3> positions;
1102 Vector<float3> translations;
1103 };
1104 Mesh &mesh = *static_cast<Mesh *>(object.data);
1105 const PositionDeformData position_data(depsgraph, object);
1106 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
1107 const OffsetIndices faces = mesh.faces();
1108 const Span<int> corner_verts = mesh.corner_verts();
1109 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1110 const MeshAttributeData attribute_data(mesh);
1113 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1114 LocalData &tls = all_tls.local();
1115 const Span<int> verts = nodes[i].verts();
1116
1117 tls.factors.resize(verts.size());
1118 const MutableSpan<float> factors = tls.factors;
1120 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1122 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1123 scale_factors(factors, strength);
1124 clamp_factors(factors, 0.0f, 1.0f);
1125
1127 vert_to_face_map, attribute_data.face_sets, relax_face_sets, verts, factors);
1128
1129 tls.translations.resize(verts.size());
1130 const MutableSpan<float3> translations = tls.translations;
1131 smooth::calc_relaxed_translations_faces(position_data.eval,
1132 vert_normals,
1133 faces,
1134 corner_verts,
1135 vert_to_face_map,
1137 attribute_data.face_sets,
1138 attribute_data.hide_poly,
1139 relax_face_sets,
1140 verts,
1141 factors,
1142 translations);
1143
1145 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1146 position_data.deform(translations, verts);
1147 });
1148 break;
1149 }
1151 struct LocalData {
1152 Vector<float> factors;
1153 Vector<float3> positions;
1154 Vector<float3> translations;
1155 };
1156 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
1157 const OffsetIndices faces = base_mesh.faces();
1158 const Span<int> corner_verts = base_mesh.corner_verts();
1159 const GroupedSpan<int> vert_to_face_map = base_mesh.vert_to_face_map();
1160 const bke::AttributeAccessor attributes = base_mesh.attributes();
1161 const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set",
1163
1164 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1167 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1168 LocalData &tls = all_tls.local();
1169 const Span<int> grids = nodes[i].grids();
1170 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1171
1172 tls.factors.resize(positions.size());
1173 const MutableSpan<float> factors = tls.factors;
1174 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1176 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1177 scale_factors(factors, strength);
1178 clamp_factors(factors, 0.0f, 1.0f);
1179
1181 corner_verts,
1182 vert_to_face_map,
1183 face_sets,
1184 subdiv_ccg,
1185 relax_face_sets,
1186 grids,
1187 factors);
1188
1189 tls.translations.resize(positions.size());
1190 const MutableSpan<float3> translations = tls.translations;
1192 faces,
1193 corner_verts,
1194 face_sets,
1195 vert_to_face_map,
1197 grids,
1198 relax_face_sets,
1199 factors,
1200 translations);
1201
1203 clip_and_lock_translations(sd, ss, positions, translations);
1204 apply_translations(translations, grids, subdiv_ccg);
1205 });
1206 break;
1207 }
1209 struct LocalData {
1210 Vector<float> factors;
1211 Vector<float3> positions;
1212 Vector<float3> translations;
1213 };
1214 BMesh &bm = *ss.bm;
1215 const int face_set_offset = CustomData_get_offset_named(
1216 &bm.pdata, CD_PROP_INT32, ".sculpt_face_set");
1219 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1220 LocalData &tls = all_tls.local();
1222 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1223
1224 tls.factors.resize(verts.size());
1225 const MutableSpan<float> factors = tls.factors;
1228 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1229 scale_factors(factors, strength);
1230 clamp_factors(factors, 0.0f, 1.0f);
1231
1233 face_set_offset, relax_face_sets, verts, factors);
1234
1235 tls.translations.resize(verts.size());
1236 const MutableSpan<float3> translations = tls.translations;
1238 verts, positions, face_set_offset, relax_face_sets, factors, translations);
1239
1241 clip_and_lock_translations(sd, ss, positions, translations);
1242 apply_translations(translations, verts);
1243 });
1244 break;
1245 }
1246 }
1247}
1248
1249static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
1250 const Sculpt &sd,
1251 const float strength,
1252 Object &object,
1253 const IndexMask &node_mask)
1254{
1255 struct LocalData {
1256 Vector<float> factors;
1257 Vector<float3> positions;
1258 Vector<int> neighbor_offsets;
1259 Vector<int> neighbor_data;
1260 Vector<float3> average_positions;
1261 Vector<float3> laplacian_disp;
1262 Vector<float3> translations;
1263 };
1264 SculptSession &ss = *object.sculpt;
1265 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1266 const float alpha = ss.filter_cache->surface_smooth_shape_preservation;
1268 const MutableSpan<float3> all_laplacian_disp = ss.filter_cache->surface_smooth_laplacian_disp;
1269 switch (pbvh.type()) {
1270 case bke::pbvh::Type::Mesh: {
1271 Mesh &mesh = *static_cast<Mesh *>(object.data);
1272 const MeshAttributeData attribute_data(mesh);
1273 const PositionDeformData position_data(depsgraph, object);
1274 const OffsetIndices faces = mesh.faces();
1275 const Span<int> corner_verts = mesh.corner_verts();
1276 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1279 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1280 LocalData &tls = all_tls.local();
1281 const Span<int> verts = nodes[i].verts();
1282 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
1283 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
1284
1285 tls.factors.resize(verts.size());
1286 const MutableSpan<float> factors = tls.factors;
1288 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1290 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1291 scale_factors(factors, strength);
1292 clamp_factors(factors, 0.0f, 1.0f);
1293
1294 const GroupedSpan<int> neighbors = calc_vert_neighbors(faces,
1295 corner_verts,
1296 vert_to_face_map,
1297 attribute_data.hide_poly,
1298 verts,
1299 tls.neighbor_offsets,
1300 tls.neighbor_data);
1301
1302 tls.average_positions.reinitialize(verts.size());
1303 const MutableSpan<float3> average_positions = tls.average_positions;
1305 position_data.eval, verts, neighbors, average_positions);
1306
1307 tls.laplacian_disp.reinitialize(verts.size());
1308 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
1309 tls.translations.reinitialize(verts.size());
1310 const MutableSpan<float3> translations = tls.translations;
1312 orig_data.positions,
1313 average_positions,
1314 alpha,
1315 laplacian_disp,
1316 translations);
1317 scale_translations(translations, factors);
1318
1319 scatter_data_mesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
1320
1322 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1323 position_data.deform(translations, verts);
1324 });
1325 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1326 LocalData &tls = all_tls.local();
1327 const Span<int> verts = nodes[i].verts();
1328
1329 tls.factors.resize(verts.size());
1330 const MutableSpan<float> factors = tls.factors;
1332 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1334 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1335 scale_factors(factors, strength);
1336 clamp_factors(factors, 0.0f, 1.0f);
1337
1338 const MutableSpan<float3> laplacian_disp = gather_data_mesh(
1339 all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
1340
1341 const GroupedSpan<int> neighbors = calc_vert_neighbors(faces,
1342 corner_verts,
1343 vert_to_face_map,
1344 attribute_data.hide_poly,
1345 verts,
1346 tls.neighbor_offsets,
1347 tls.neighbor_data);
1348
1349 tls.average_positions.resize(verts.size());
1350 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
1352 all_laplacian_disp.as_span(), verts, neighbors, average_laplacian_disps);
1353
1354 tls.translations.resize(verts.size());
1355 const MutableSpan<float3> translations = tls.translations;
1357 laplacian_disp, average_laplacian_disps, beta, translations);
1358 scale_translations(translations, factors);
1359
1361 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1362 position_data.deform(translations, verts);
1363 });
1364 break;
1365 }
1367 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1370 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1371 LocalData &tls = all_tls.local();
1372 const Span<int> grids = nodes[i].grids();
1373 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1374 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
1375
1376 tls.factors.resize(positions.size());
1377 const MutableSpan<float> factors = tls.factors;
1378 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1380 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1381 scale_factors(factors, strength);
1382 clamp_factors(factors, 0.0f, 1.0f);
1383
1384 tls.average_positions.resize(positions.size());
1385 const MutableSpan<float3> average_positions = tls.average_positions;
1387 subdiv_ccg, subdiv_ccg.positions.as_span(), grids, average_positions);
1388
1389 tls.laplacian_disp.resize(positions.size());
1390 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
1391 tls.translations.resize(positions.size());
1392 const MutableSpan<float3> translations = tls.translations;
1394 orig_data.positions,
1395 average_positions,
1396 alpha,
1397 laplacian_disp,
1398 translations);
1399 scale_translations(translations, factors);
1400
1401 scatter_data_grids(subdiv_ccg, laplacian_disp.as_span(), grids, all_laplacian_disp);
1402
1404 clip_and_lock_translations(sd, ss, positions, translations);
1405 apply_translations(translations, grids, subdiv_ccg);
1406 });
1407 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1408 LocalData &tls = all_tls.local();
1409 const Span<int> grids = nodes[i].grids();
1410 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1411
1412 tls.factors.resize(positions.size());
1413 const MutableSpan<float> factors = tls.factors;
1414 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1416 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1417 scale_factors(factors, strength);
1418 clamp_factors(factors, 0.0f, 1.0f);
1419
1420 const MutableSpan<float3> laplacian_disp = gather_data_grids(
1421 subdiv_ccg, all_laplacian_disp.as_span(), grids, tls.laplacian_disp);
1422
1423 tls.average_positions.resize(positions.size());
1424 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
1426 subdiv_ccg, all_laplacian_disp.as_span(), grids, average_laplacian_disps);
1427
1428 tls.translations.resize(positions.size());
1429 const MutableSpan<float3> translations = tls.translations;
1431 laplacian_disp, average_laplacian_disps, beta, translations);
1432 scale_translations(translations, factors);
1433
1435 clip_and_lock_translations(sd, ss, positions, translations);
1436 apply_translations(translations, grids, subdiv_ccg);
1437 });
1438 break;
1439 }
1441 BMesh &bm = *ss.bm;
1444 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1445 LocalData &tls = all_tls.local();
1447 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1448 Array<float3> orig_positions(verts.size());
1449 Array<float3> orig_normals(verts.size());
1450 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
1451
1452 tls.factors.resize(verts.size());
1453 const MutableSpan<float> factors = tls.factors;
1456 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1457 scale_factors(factors, strength);
1458 clamp_factors(factors, 0.0f, 1.0f);
1459
1460 tls.average_positions.resize(verts.size());
1461 const MutableSpan<float3> average_positions = tls.average_positions;
1463
1464 tls.laplacian_disp.resize(verts.size());
1465 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
1466 tls.translations.resize(verts.size());
1467 const MutableSpan<float3> translations = tls.translations;
1469 positions, orig_positions, average_positions, alpha, laplacian_disp, translations);
1470 scale_translations(translations, factors);
1471
1472 scatter_data_bmesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
1473
1475 clip_and_lock_translations(sd, ss, positions, translations);
1476 apply_translations(translations, verts);
1477 });
1478 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1479 LocalData &tls = all_tls.local();
1481 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1482
1483 tls.factors.resize(verts.size());
1484 const MutableSpan<float> factors = tls.factors;
1487 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1488 scale_factors(factors, strength);
1489 clamp_factors(factors, 0.0f, 1.0f);
1490
1491 const MutableSpan<float3> laplacian_disp = gather_data_bmesh(
1492 all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
1493
1494 tls.average_positions.resize(verts.size());
1495 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
1496 smooth::average_data_bmesh(all_laplacian_disp.as_span(), verts, average_laplacian_disps);
1497
1498 tls.translations.resize(verts.size());
1499 const MutableSpan<float3> translations = tls.translations;
1501 laplacian_disp, average_laplacian_disps, beta, translations);
1502 scale_translations(translations, factors);
1503
1505 clip_and_lock_translations(sd, ss, positions, translations);
1506 apply_translations(translations, verts);
1507 });
1508 break;
1509 }
1510 }
1511}
1512
1514 const Span<float3> positions,
1515 const Span<float3> smooth_positions,
1516 const Span<float> sharpen_factors,
1517 const Span<float3> detail_directions,
1518 const MutableSpan<float3> translations)
1519{
1520 for (const int i : positions.index_range()) {
1521 float3 disp_avg = smooth_positions[i] - positions[i];
1522 disp_avg = disp_avg * filter_cache.sharpen_smooth_ratio * pow2f(sharpen_factors[i]);
1523 translations[i] += disp_avg;
1524 /* Intensify details. */
1525 if (filter_cache.sharpen_intensify_detail_strength > 0.0f) {
1526 float3 detail_strength = detail_directions[i];
1527 translations[i] += detail_strength * -filter_cache.sharpen_intensify_detail_strength *
1528 sharpen_factors[i];
1529 }
1530 }
1531}
1532
1533static void calc_sharpen_filter(const Depsgraph &depsgraph,
1534 const Sculpt &sd,
1535 const float strength,
1536 Object &object,
1537 const IndexMask &node_mask)
1538{
1539 struct LocalData {
1540 Vector<float> factors;
1541 Vector<float3> positions;
1542 Vector<int> neighbor_offsets;
1543 Vector<int> neighbor_data;
1544 Vector<float3> smooth_positions;
1545 Vector<float> sharpen_factors;
1546 Vector<float3> detail_directions;
1547 Vector<float3> translations;
1548 };
1549 SculptSession &ss = *object.sculpt;
1550 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1551 switch (pbvh.type()) {
1552 case bke::pbvh::Type::Mesh: {
1553 Mesh &mesh = *static_cast<Mesh *>(object.data);
1554 const MeshAttributeData attribute_data(mesh);
1555 const PositionDeformData position_data(depsgraph, object);
1556
1557 const OffsetIndices faces = mesh.faces();
1558 const Span<int> corner_verts = mesh.corner_verts();
1559 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1562 node_mask.foreach_index(GrainSize(1), [&](const int node_index) {
1563 LocalData &tls = all_tls.local();
1564 const Span<int> verts = nodes[node_index].verts();
1565 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
1566
1567 tls.factors.resize(verts.size());
1568 const MutableSpan<float> factors = tls.factors;
1570 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1572 object,
1573 ss.filter_cache->automasking.get(),
1574 nodes[node_index],
1575 verts,
1576 factors);
1577 scale_factors(factors, strength);
1578
1579 /* This filter can't work at full strength as it needs multiple iterations to reach a
1580 * stable state. */
1581 clamp_factors(factors, 0.0f, 0.5f);
1582
1583 const GroupedSpan<int> neighbors = calc_vert_neighbors(faces,
1584 corner_verts,
1585 vert_to_face_map,
1586 attribute_data.hide_poly,
1587 verts,
1588 tls.neighbor_offsets,
1589 tls.neighbor_data);
1590
1591 tls.smooth_positions.resize(verts.size());
1592 const MutableSpan<float3> smooth_positions = tls.smooth_positions;
1594 position_data.eval, verts, neighbors, smooth_positions);
1595
1596 const Span<float> sharpen_factors = gather_data_mesh(
1597 ss.filter_cache->sharpen_factor.as_span(), verts, tls.sharpen_factors);
1598
1599 tls.translations.resize(verts.size());
1600 const MutableSpan<float3> translations = tls.translations;
1601 for (const int i : verts.index_range()) {
1602 const int vert = verts[i];
1603 const float3 &position = position_data.eval[vert];
1604
1605 float3 disp_sharpen(0.0f);
1606 for (const int neighbor : neighbors[i]) {
1607 float3 disp_n = position_data.eval[neighbor] - position;
1608 disp_n *= ss.filter_cache->sharpen_factor[neighbor];
1609 disp_sharpen += disp_n;
1610 }
1611
1612 disp_sharpen *= (1.0f - sharpen_factors[i]);
1613 translations[i] = disp_sharpen;
1614 }
1615
1616 const Span<float3> detail_directions = gather_data_mesh(
1617 ss.filter_cache->detail_directions.as_span(), verts, tls.detail_directions);
1618
1620 positions,
1621 smooth_positions,
1622 sharpen_factors,
1623 detail_directions,
1624 translations);
1625 scale_translations(translations, factors);
1626
1628 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1629 position_data.deform(translations, verts);
1630 });
1631 break;
1632 }
1634 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1635 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1636 MutableSpan<float3> vert_positions = subdiv_ccg.positions;
1637
1640 node_mask.foreach_index(GrainSize(1), [&](const int node_index) {
1641 LocalData &tls = all_tls.local();
1642 const Span<int> grids = nodes[node_index].grids();
1643 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1644
1645 tls.factors.resize(positions.size());
1646 const MutableSpan<float> factors = tls.factors;
1647 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1649 object,
1650 ss.filter_cache->automasking.get(),
1651 nodes[node_index],
1652 grids,
1653 factors);
1654 scale_factors(factors, strength);
1655
1656 /* This filter can't work at full strength as it needs multiple iterations to reach a
1657 * stable state. */
1658 clamp_factors(factors, 0.0f, 0.5f);
1659
1660 tls.smooth_positions.resize(positions.size());
1661 const MutableSpan<float3> smooth_positions = tls.smooth_positions;
1663 subdiv_ccg, subdiv_ccg.positions.as_span(), grids, smooth_positions);
1664
1665 const Span<float> sharpen_factors = gather_data_grids(
1666 subdiv_ccg, ss.filter_cache->sharpen_factor.as_span(), grids, tls.sharpen_factors);
1667
1668 tls.translations.resize(positions.size());
1669 const MutableSpan<float3> translations = tls.translations;
1670 for (const int i : grids.index_range()) {
1671 const int node_verts_start = i * key.grid_area;
1672 const int grid = grids[i];
1673 for (const short y : IndexRange(key.grid_size)) {
1674 for (const short x : IndexRange(key.grid_size)) {
1675 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
1676 const int node_vert = node_verts_start + offset;
1677
1678 const float3 &position = positions[node_vert];
1679
1680 float3 disp_sharpen(0.0f);
1681 SubdivCCGNeighbors neighbors;
1683 subdiv_ccg, SubdivCCGCoord{grid, x, y}, false, neighbors);
1684 for (const SubdivCCGCoord neighbor : neighbors.coords) {
1685 float3 disp_n = vert_positions[neighbor.to_index(key)] - position;
1686 disp_n *= ss.filter_cache->sharpen_factor[neighbor.to_index(key)];
1687 disp_sharpen += disp_n;
1688 }
1689
1690 disp_sharpen *= (1.0f - sharpen_factors[node_vert]);
1691 translations[node_vert] = disp_sharpen;
1692 }
1693 }
1694 }
1695
1696 const Span<float3> detail_directions = gather_data_grids(
1697 subdiv_ccg,
1698 ss.filter_cache->detail_directions.as_span(),
1699 grids,
1700 tls.detail_directions);
1701
1703 positions,
1704 smooth_positions,
1705 sharpen_factors,
1706 detail_directions,
1707 translations);
1708 scale_translations(translations, factors);
1709
1711 clip_and_lock_translations(sd, ss, positions, translations);
1712 apply_translations(translations, grids, subdiv_ccg);
1713 });
1714 break;
1715 }
1717 BMesh &bm = *ss.bm;
1721 node_mask.foreach_index(GrainSize(1), [&](const int node_index) {
1722 LocalData &tls = all_tls.local();
1724 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1725
1726 tls.factors.resize(verts.size());
1727 const MutableSpan<float> factors = tls.factors;
1730 object,
1731 ss.filter_cache->automasking.get(),
1732 nodes[node_index],
1733 verts,
1734 factors);
1735 scale_factors(factors, strength);
1736
1737 /* This filter can't work at full strength as it needs multiple iterations to reach a
1738 * stable state. */
1739 clamp_factors(factors, 0.0f, 0.5f);
1740
1741 tls.smooth_positions.resize(verts.size());
1742 const MutableSpan<float3> smooth_positions = tls.smooth_positions;
1744
1745 const Span<float> sharpen_factors = gather_data_bmesh(
1746 ss.filter_cache->sharpen_factor.as_span(), verts, tls.sharpen_factors);
1747
1748 tls.translations.resize(verts.size());
1749 const MutableSpan<float3> translations = tls.translations;
1750
1751 BMeshNeighborVerts neighbors;
1752
1753 int i = 0;
1754 for (BMVert *vert : verts) {
1755 const float3 position = vert->co;
1756
1757 float3 disp_sharpen(0.0f);
1758 for (const BMVert *neighbor : vert_neighbors_get_bmesh(*vert, neighbors)) {
1759 float3 disp_n = float3(neighbor->co) - position;
1760 disp_n *= ss.filter_cache->sharpen_factor[BM_elem_index_get(neighbor)];
1761 disp_sharpen += disp_n;
1762 }
1763
1764 disp_sharpen *= (1.0f - sharpen_factors[i]);
1765 translations[i] = disp_sharpen;
1766 i++;
1767 }
1768
1769 const Span<float3> detail_directions = gather_data_bmesh(
1770 ss.filter_cache->detail_directions.as_span(), verts, tls.detail_directions);
1771
1773 positions,
1774 smooth_positions,
1775 sharpen_factors,
1776 detail_directions,
1777 translations);
1778 scale_translations(translations, factors);
1779
1781 clip_and_lock_translations(sd, ss, positions, translations);
1782 apply_translations(translations, verts);
1783 });
1784 break;
1785 }
1786 }
1787}
1788
1789static void calc_enhance_details_filter(const Depsgraph &depsgraph,
1790 const Sculpt &sd,
1791 const float strength,
1792 Object &object,
1793 const IndexMask &node_mask)
1794{
1795 const float final_strength = -std::abs(strength);
1796 struct LocalData {
1797 Vector<float> factors;
1798 Vector<float3> positions;
1799 Vector<float3> translations;
1800 };
1801 SculptSession &ss = *object.sculpt;
1802 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1803 switch (pbvh.type()) {
1804 case bke::pbvh::Type::Mesh: {
1805 Mesh &mesh = *static_cast<Mesh *>(object.data);
1806 const MeshAttributeData attribute_data(mesh);
1807 const PositionDeformData position_data(depsgraph, object);
1810 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1811 LocalData &tls = all_tls.local();
1812 const Span<int> verts = nodes[i].verts();
1813
1814 tls.factors.resize(verts.size());
1815 const MutableSpan<float> factors = tls.factors;
1817 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1819 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1820 scale_factors(factors, final_strength);
1821
1822 const MutableSpan translations = gather_data_mesh(
1823 ss.filter_cache->detail_directions.as_span(), verts, tls.translations);
1824 scale_translations(translations, factors);
1825
1827 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1828 position_data.deform(translations, verts);
1829 });
1830 break;
1831 }
1833 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1836 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1837 LocalData &tls = all_tls.local();
1838 const Span<int> grids = nodes[i].grids();
1839 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1840
1841 tls.factors.resize(positions.size());
1842 const MutableSpan<float> factors = tls.factors;
1843 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1845 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1846 scale_factors(factors, final_strength);
1847
1848 const MutableSpan translations = gather_data_grids(
1849 subdiv_ccg, ss.filter_cache->detail_directions.as_span(), grids, tls.translations);
1850 scale_translations(translations, factors);
1851
1853 clip_and_lock_translations(sd, ss, positions, translations);
1854 apply_translations(translations, grids, subdiv_ccg);
1855 });
1856 break;
1857 }
1859 BMesh &bm = *ss.bm;
1862 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1863 LocalData &tls = all_tls.local();
1865 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1866
1867 tls.factors.resize(verts.size());
1868 const MutableSpan<float> factors = tls.factors;
1871 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1872 scale_factors(factors, final_strength);
1873
1874 const MutableSpan<float3> translations = gather_data_bmesh(
1875 ss.filter_cache->detail_directions.as_span(), verts, tls.translations);
1876 scale_translations(translations, factors);
1877
1879 clip_and_lock_translations(sd, ss, positions, translations);
1880 apply_translations(translations, verts);
1881 });
1882 break;
1883 }
1884 }
1885}
1886
1887static void calc_erase_displacement_filter(const Depsgraph &depsgraph,
1888 const Sculpt &sd,
1889 const float strength,
1890 Object &object,
1891 const IndexMask &node_mask)
1892{
1893 struct LocalData {
1894 Vector<float> factors;
1895 Vector<float3> positions;
1896 Vector<float3> new_positions;
1897 Vector<float3> translations;
1898 };
1899 SculptSession &ss = *object.sculpt;
1900 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1901 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1904 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1905 LocalData &tls = all_tls.local();
1906 const Span<int> grids = nodes[i].grids();
1907 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1908
1909 tls.factors.resize(positions.size());
1910 const MutableSpan<float> factors = tls.factors;
1911 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1913 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1914 scale_factors(factors, strength);
1915 clamp_factors(factors, -1.0f, 1.0f);
1916
1917 const MutableSpan<float3> new_positions = gather_data_grids(
1918 subdiv_ccg, ss.filter_cache->limit_surface_co.as_span(), grids, tls.new_positions);
1919 tls.translations.resize(positions.size());
1920 const MutableSpan<float3> translations = tls.translations;
1921 translations_from_new_positions(new_positions, positions, translations);
1922 scale_translations(translations, factors);
1923
1925 clip_and_lock_translations(sd, ss, positions, translations);
1926 apply_translations(translations, grids, subdiv_ccg);
1927 });
1928}
1929
1931 const float shape_preservation,
1932 const float current_vertex_displacement)
1933{
1934 SculptSession &ss = *object.sculpt;
1935 const int totvert = SCULPT_vertex_count_get(object);
1936 filter::Cache *filter_cache = ss.filter_cache;
1937
1938 filter_cache->surface_smooth_laplacian_disp.reinitialize(totvert);
1939 filter_cache->surface_smooth_laplacian_disp.fill(float3(0.0f));
1940 filter_cache->surface_smooth_shape_preservation = shape_preservation;
1941 filter_cache->surface_smooth_current_vertex = current_vertex_displacement;
1942}
1943
1944static void calc_limit_surface_positions(const Object &object, MutableSpan<float3> limit_positions)
1945{
1946 const SculptSession &ss = *object.sculpt;
1947 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1948 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1949
1950 threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 512, [&](const IndexRange range) {
1951 for (const int grid : range) {
1952 MutableSpan grid_dst = limit_positions.slice(bke::ccg::grid_range(key, grid));
1953 BKE_subdiv_ccg_eval_limit_positions(subdiv_ccg, key, grid, grid_dst);
1954 }
1955 });
1956}
1957
1958static void mesh_filter_sharpen_init(const Depsgraph &depsgraph,
1959 const Object &object,
1960 const float smooth_ratio,
1961 const float intensify_detail_strength,
1962 const int curvature_smooth_iterations,
1963 filter::Cache &filter_cache)
1964{
1965 const SculptSession &ss = *object.sculpt;
1966 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1967 const IndexMask &node_mask = filter_cache.node_mask;
1968 const int totvert = SCULPT_vertex_count_get(object);
1969
1970 filter_cache.sharpen_smooth_ratio = smooth_ratio;
1971 filter_cache.sharpen_intensify_detail_strength = intensify_detail_strength;
1972 filter_cache.sharpen_curvature_smooth_iterations = curvature_smooth_iterations;
1973 filter_cache.sharpen_factor.reinitialize(totvert);
1974 filter_cache.detail_directions.reinitialize(totvert);
1975 MutableSpan<float3> detail_directions = filter_cache.detail_directions;
1976 MutableSpan<float> sharpen_factors = filter_cache.sharpen_factor;
1977
1978 calc_smooth_translations(depsgraph, object, node_mask, filter_cache.detail_directions);
1979
1980 for (int i = 0; i < totvert; i++) {
1981 sharpen_factors[i] = math::length(detail_directions[i]);
1982 }
1983
1984 float max_factor = 0.0f;
1985 for (int i = 0; i < totvert; i++) {
1986 max_factor = std::max(sharpen_factors[i], max_factor);
1987 }
1988
1989 max_factor = math::safe_rcp(max_factor);
1990 for (int i = 0; i < totvert; i++) {
1991 sharpen_factors[i] *= max_factor;
1992 sharpen_factors[i] = 1.0f - pow2f(1.0f - sharpen_factors[i]);
1993 }
1994
1995 /* Smooth the calculated factors and directions to remove high frequency detail. */
1996 struct LocalData {
1997 Vector<int> neighbor_offsets;
1998 Vector<int> neighbor_data;
1999 Vector<float3> smooth_directions;
2000 Vector<float> smooth_factors;
2001 };
2003 for ([[maybe_unused]] const int _ : IndexRange(filter_cache.sharpen_curvature_smooth_iterations))
2004 {
2005 switch (pbvh.type()) {
2006 case bke::pbvh::Type::Mesh: {
2007 Mesh &mesh = *static_cast<Mesh *>(object.data);
2008 const OffsetIndices faces = mesh.faces();
2009 const Span<int> corner_verts = mesh.corner_verts();
2010 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
2012 const MeshAttributeData attribute_data(mesh);
2013 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2014 LocalData &tls = all_tls.local();
2015 const Span<int> verts = nodes[i].verts();
2016
2017 const GroupedSpan<int> neighbors = calc_vert_neighbors(faces,
2018 corner_verts,
2019 vert_to_face_map,
2020 attribute_data.hide_poly,
2021 verts,
2022 tls.neighbor_offsets,
2023 tls.neighbor_data);
2024
2025 tls.smooth_directions.resize(verts.size());
2027 verts,
2028 neighbors,
2029 tls.smooth_directions.as_mutable_span());
2030 scatter_data_mesh(tls.smooth_directions.as_span(), verts, detail_directions);
2031
2032 tls.smooth_factors.resize(verts.size());
2034 sharpen_factors.as_span(), verts, neighbors, tls.smooth_factors.as_mutable_span());
2035 scatter_data_mesh(tls.smooth_factors.as_span(), verts, sharpen_factors);
2036 });
2037 break;
2038 }
2040 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
2041 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
2043 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2044 LocalData &tls = all_tls.local();
2045 const Span<int> grids = nodes[i].grids();
2046 const int grid_verts_num = grids.size() * key.grid_area;
2047
2048 tls.smooth_directions.resize(grid_verts_num);
2049 smooth::average_data_grids(subdiv_ccg,
2050 detail_directions.as_span(),
2051 grids,
2052 tls.smooth_directions.as_mutable_span());
2054 subdiv_ccg, tls.smooth_directions.as_span(), grids, detail_directions);
2055
2056 tls.smooth_factors.resize(grid_verts_num);
2058 subdiv_ccg, sharpen_factors.as_span(), grids, tls.smooth_factors.as_mutable_span());
2059 scatter_data_grids(subdiv_ccg, tls.smooth_factors.as_span(), grids, sharpen_factors);
2060 });
2061 break;
2062 }
2065 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2066 LocalData &tls = all_tls.local();
2068 &const_cast<bke::pbvh::BMeshNode &>(nodes[i]));
2069
2070 tls.smooth_directions.resize(verts.size());
2072 detail_directions.as_span(), verts, tls.smooth_directions.as_mutable_span());
2073 scatter_data_bmesh(tls.smooth_directions.as_span(), verts, detail_directions);
2074
2075 tls.smooth_factors.resize(verts.size());
2077 sharpen_factors.as_span(), verts, tls.smooth_factors.as_mutable_span());
2078 scatter_data_bmesh(tls.smooth_factors.as_span(), verts, sharpen_factors);
2079 });
2080 break;
2081 }
2082 }
2083}
2084
2085enum {
2088};
2089
2091{
2092 static const EnumPropertyItem modal_items[] = {
2093 {FILTER_MESH_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
2094 {FILTER_MESH_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
2095 {0, nullptr, 0, nullptr, nullptr},
2096 };
2097
2098 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Mesh Filter Modal Map");
2099
2100 /* This function is called for each space-type, only needs to add map once. */
2101 if (keymap && keymap->modal_items) {
2102 return nullptr;
2103 }
2104
2105 keymap = WM_modalkeymap_ensure(keyconf, "Mesh Filter Modal Map", modal_items);
2106
2107 WM_modalkeymap_assign(keymap, "SCULPT_OT_mesh_filter");
2108
2109 return keymap;
2110}
2111
2113{
2115 status.item(IFACE_("Confirm"), ICON_EVENT_RETURN);
2116 status.item(IFACE_("Cancel"), ICON_EVENT_ESC, ICON_MOUSE_RMB);
2117}
2118
2119static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op, bool is_replay = false)
2120{
2121 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
2123 SculptSession &ss = *ob.sculpt;
2124 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
2125 const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
2126 const float strength = RNA_float_get(op->ptr, "strength");
2127
2129
2130 const IndexMask &node_mask = ss.filter_cache->node_mask;
2131 if (auto_mask::is_enabled(sd, ob, nullptr) && ss.filter_cache->automasking &&
2133 {
2134 ss.filter_cache->automasking->calc_cavity_factor(depsgraph, ob, node_mask);
2135 }
2136 switch (filter_type) {
2139 sd,
2140 strength,
2141 ob,
2142 node_mask,
2143 is_replay && ss.filter_cache->iteration_count == 0);
2144 break;
2146 calc_scale_filter(depsgraph, sd, strength, ob, node_mask);
2147 break;
2149 calc_inflate_filter(depsgraph, sd, strength, ob, node_mask);
2150 break;
2152 calc_sphere_filter(depsgraph, sd, strength, ob, node_mask);
2153 break;
2155 calc_random_filter(depsgraph, sd, strength, ob, node_mask);
2156 break;
2158 calc_relax_filter(depsgraph, sd, strength, ob, node_mask);
2159 break;
2161 calc_relax_face_sets_filter(depsgraph, sd, strength, ob, node_mask);
2162 break;
2164 calc_surface_smooth_filter(depsgraph, sd, strength, ob, node_mask);
2165 break;
2167 calc_sharpen_filter(depsgraph, sd, strength, ob, node_mask);
2168 break;
2170 calc_enhance_details_filter(depsgraph, sd, strength, ob, node_mask);
2171 break;
2173 calc_erase_displacement_filter(depsgraph, sd, strength, ob, node_mask);
2174 break;
2175 }
2176
2178 pbvh.tag_positions_changed(node_mask);
2179 pbvh.update_bounds(depsgraph, ob);
2180
2182
2184}
2185
2187 SculptSession &ss,
2188 float2 prev_press_mouse,
2189 float2 mouse)
2190{
2191 const float len = prev_press_mouse[0] - mouse[0];
2192
2193 float filter_strength = ss.filter_cache->start_filter_strength * -len * 0.001f * UI_SCALE_FAC;
2194 RNA_float_set(op->ptr, "strength", filter_strength);
2195}
2197{
2198 /* Event history is only stored for smooth and relax filters. */
2199 if (!RNA_collection_length(op->ptr, "event_history")) {
2201 return;
2202 }
2203
2205 SculptSession &ss = *ob.sculpt;
2206 float2 start_mouse;
2207 bool first = true;
2208 float initial_strength = ss.filter_cache->start_filter_strength;
2209
2210 RNA_BEGIN (op->ptr, item, "event_history") {
2211 float2 mouse;
2212 RNA_float_get_array(&item, "mouse_event", mouse);
2213
2214 if (first) {
2215 first = false;
2216 start_mouse = mouse;
2217 continue;
2218 }
2219
2220 sculpt_mesh_update_strength(op, ss, start_mouse, mouse);
2221 sculpt_mesh_filter_apply(C, op, true);
2222 }
2223 RNA_END;
2224
2225 RNA_float_set(op->ptr, "strength", initial_strength);
2226}
2227
2229{
2231 SculptSession &ss = *ob.sculpt;
2232
2233 MEM_delete(ss.filter_cache);
2234 ss.filter_cache = nullptr;
2236}
2237
2239 wmOperator *op,
2240 const MeshFilterType filter_type)
2241{
2242 float initial_strength = ss.filter_cache->start_filter_strength;
2243 /* Don't update strength property if we're storing an event history. */
2244 if (sculpt_mesh_filter_is_continuous(filter_type)) {
2245 RNA_float_set(op->ptr, "strength", initial_strength);
2246 }
2247
2248 return OPERATOR_FINISHED;
2249}
2250
2252{
2253 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
2255 SculptSession *ss = ob.sculpt;
2257
2258 if (!ss || !pbvh) {
2259 return;
2260 }
2261
2264 pbvh->update_bounds(depsgraph, ob);
2265}
2266
2268{
2271 SculptSession &ss = *ob.sculpt;
2272 const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
2273
2276
2277 if (event->type == EVT_MODAL_MAP) {
2279 switch (event->val) {
2282 undo::push_end_ex(ob, true);
2284 break;
2285
2287 ret = sculpt_mesh_filter_confirm(ss, op, filter_type);
2288 undo::push_end_ex(ob, false);
2289 break;
2290 }
2291
2293 ED_workspace_status_text(C, nullptr); /* Clear status bar */
2295
2296 return ret;
2297 }
2298
2299 if (event->type != MOUSEMOVE) {
2301 }
2302
2303 /* NOTE: some filter types are continuous, for these we store an
2304 * event history in RNA for continuous.
2305 * This way the user can tweak the last operator properties
2306 * or repeat the op and get expected results. */
2307 if (sculpt_mesh_filter_is_continuous(filter_type)) {
2308 if (RNA_collection_length(op->ptr, "event_history") == 0) {
2309 /* First entry is the start mouse position, event->prev_press_xy. */
2310 PointerRNA startptr;
2311 RNA_collection_add(op->ptr, "event_history", &startptr);
2312
2313 float2 mouse_start(float(event->prev_press_xy[0]), float(event->prev_press_xy[1]));
2314 RNA_float_set_array(&startptr, "mouse_event", mouse_start);
2315 }
2316
2317 PointerRNA itemptr;
2318 RNA_collection_add(op->ptr, "event_history", &itemptr);
2319
2320 float2 mouse(float(event->xy[0]), float(event->xy[1]));
2321 RNA_float_set_array(&itemptr, "mouse_event", mouse);
2322 RNA_float_set(&itemptr, "pressure", WM_event_tablet_data(event, nullptr, nullptr));
2323 }
2324 else {
2326 }
2327
2328 float2 prev_mval(float(event->prev_press_xy[0]), float(event->prev_press_xy[1]));
2329 float2 mval(float(event->xy[0]), float(event->xy[1]));
2330
2331 sculpt_mesh_update_strength(op, ss, prev_mval, mval);
2332
2334
2336
2338}
2339
2340static void sculpt_filter_specific_init(const Depsgraph &depsgraph,
2341 const MeshFilterType filter_type,
2342 wmOperator *op,
2343 Object &object)
2344{
2345 SculptSession &ss = *object.sculpt;
2346 switch (filter_type) {
2349 RNA_float_get(op->ptr, "surface_smooth_shape_preservation"),
2350 RNA_float_get(op->ptr, "surface_smooth_current_vertex"));
2351 break;
2352 }
2355 object,
2356 RNA_float_get(op->ptr, "sharpen_smooth_ratio"),
2357 RNA_float_get(op->ptr, "sharpen_intensify_detail_strength"),
2358 RNA_int_get(op->ptr, "sharpen_curvature_smooth_iterations"),
2359 *ss.filter_cache);
2360 break;
2361 }
2363 ss.filter_cache->detail_directions.reinitialize(SCULPT_vertex_count_get(object));
2366 break;
2367 }
2369 ss.filter_cache->limit_surface_co.reinitialize(SCULPT_vertex_count_get(object));
2371 break;
2372 }
2373 default:
2374 break;
2375 }
2376}
2377
2378/* Returns OPERATOR_PASS_THROUGH on success. */
2380{
2381 const Scene &scene = *CTX_data_scene(C);
2385
2386 const View3D *v3d = CTX_wm_view3d(C);
2387 const Base *base = CTX_data_active_base(C);
2388 if (!BKE_base_is_visible(v3d, base)) {
2389 return OPERATOR_CANCELLED;
2390 }
2391
2392 int mval[2];
2393 RNA_int_get_array(op->ptr, "start_mouse", mval);
2394
2395 const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
2396 const bool use_automasking = auto_mask::is_enabled(sd, ob, nullptr);
2397 const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type) || use_automasking;
2398
2400
2402 return OPERATOR_CANCELLED;
2403 }
2404
2405 SculptSession &ss = *ob.sculpt;
2406
2407 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
2408 if (filter_type == MeshFilterType::EraseDisplacement && pbvh.type() != bke::pbvh::Type::Grids) {
2409 return OPERATOR_CANCELLED;
2410 }
2411
2412 const eMeshFilterDeformAxis deform_axis = eMeshFilterDeformAxis(
2413 RNA_enum_get(op->ptr, "deform_axis"));
2414
2415 if (deform_axis == 0) {
2416 /* All axis are disabled, so the filter is not going to produce any deformation. */
2417 return OPERATOR_CANCELLED;
2418 }
2419
2420 float2 mval_fl{float(mval[0]), float(mval[1])};
2421 if (use_automasking) {
2422 /* Update the active face set manually as the paint cursor is not enabled when using the
2423 * Mesh Filter Tool. */
2425 cursor_geometry_info_update(C, &cgi, mval_fl, false);
2426 }
2427
2429 if (needs_topology_info) {
2431 }
2432
2433 undo::push_begin(scene, ob, op);
2434
2435 cache_init(C,
2436 ob,
2437 sd,
2439 mval_fl,
2440 RNA_float_get(op->ptr, "area_normal_radius"),
2441 RNA_float_get(op->ptr, "strength"));
2442
2443 filter::Cache *filter_cache = ss.filter_cache;
2444 filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
2445 if (auto_mask::is_enabled(sd, ob, nullptr)) {
2447 }
2448
2449 sculpt_filter_specific_init(*depsgraph, filter_type, op, ob);
2450
2451 ss.filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
2452 ss.filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
2453 ss.filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
2454
2455 ss.filter_cache->orientation = FilterOrientation(RNA_enum_get(op->ptr, "orientation"));
2456
2457 return OPERATOR_PASS_THROUGH;
2458}
2459
2461 wmOperator *op,
2462 const wmEvent *event)
2463{
2464 RNA_int_set_array(op->ptr, "start_mouse", event->mval);
2466
2467 if (ret == OPERATOR_PASS_THROUGH) {
2470 }
2471
2472 return ret;
2473}
2474
2476{
2478
2479 if (ret == OPERATOR_PASS_THROUGH) {
2480 int iterations = RNA_int_get(op->ptr, "iteration_count");
2481
2482 for (int i = 0; i < iterations; i++) {
2484 }
2485
2488
2489 return OPERATOR_FINISHED;
2490 }
2491
2492 return ret;
2493}
2494
2496{
2498 ot->srna, "start_mouse", 2, nullptr, 0, 1 << 14, "Starting Mouse", "", 0, 1 << 14);
2499
2500 RNA_def_float(ot->srna,
2501 "area_normal_radius",
2502 0.25,
2503 0.001,
2504 5.0,
2505 "Normal Radius",
2506 "Radius used for calculating area normal on initial click,\nin percentage "
2507 "of brush radius",
2508 0.01,
2509 1.0);
2510 PropertyRNA *prop = RNA_def_float(
2511 ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
2513 RNA_def_int(ot->srna,
2514 "iteration_count",
2515 1,
2516 1,
2517 10000,
2518 "Repeat",
2519 "How many times to repeat the filter",
2520 1,
2521 100);
2522
2523 /* Smooth filter requires entire event history. */
2524 prop = RNA_def_collection_runtime(ot->srna, "event_history", &RNA_OperatorStrokeElement, "", "");
2526}
2527
2528static void sculpt_mesh_ui_exec(bContext * /*C*/, wmOperator *op)
2529{
2530 uiLayout *layout = op->layout;
2531
2532 layout->prop(op->ptr, "strength", UI_ITEM_NONE, std::nullopt, ICON_NONE);
2533 layout->prop(op->ptr, "iteration_count", UI_ITEM_NONE, std::nullopt, ICON_NONE);
2534 layout->prop(op->ptr, "orientation", UI_ITEM_NONE, std::nullopt, ICON_NONE);
2535 layout = &layout->row(true);
2536 layout->prop(op->ptr, "deform_axis", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
2537}
2538
2540{
2541 ot->name = "Filter Mesh";
2542 ot->idname = "SCULPT_OT_mesh_filter";
2543 ot->description = "Applies a filter to modify the current mesh";
2544
2545 ot->invoke = sculpt_mesh_filter_invoke;
2547 ot->poll = SCULPT_mode_poll;
2549 ot->ui = sculpt_mesh_ui_exec;
2550
2551 /* Doesn't seem to actually be called?
2552 * Check `sculpt_mesh_filter_modal` to see where it's really called. */
2553 ot->cancel = sculpt_mesh_filter_cancel;
2554
2557
2559
2560 ot->prop = RNA_def_enum(ot->srna,
2561 "type",
2564 "Filter Type",
2565 "Operation that is going to be applied to the mesh");
2567 RNA_def_enum_flag(ot->srna,
2568 "deform_axis",
2571 "Deform Axis",
2572 "Apply the deformation in the selected axis");
2573 RNA_def_enum(ot->srna,
2574 "orientation",
2577 "Orientation",
2578 "Orientation of the axis to limit the filter displacement");
2579
2580 /* Surface Smooth Mesh Filter properties. */
2581 RNA_def_float(ot->srna,
2582 "surface_smooth_shape_preservation",
2583 0.5f,
2584 0.0f,
2585 1.0f,
2586 "Shape Preservation",
2587 "How much of the original shape is preserved when smoothing",
2588 0.0f,
2589 1.0f);
2590 RNA_def_float(ot->srna,
2591 "surface_smooth_current_vertex",
2592 0.5f,
2593 0.0f,
2594 1.0f,
2595 "Per Vertex Displacement",
2596 "How much the position of each individual vertex influences the final result",
2597 0.0f,
2598 1.0f);
2599 RNA_def_float(ot->srna,
2600 "sharpen_smooth_ratio",
2601 0.35f,
2602 0.0f,
2603 1.0f,
2604 "Smooth Ratio",
2605 "How much smoothing is applied to polished surfaces",
2606 0.0f,
2607 1.0f);
2608
2609 RNA_def_float(ot->srna,
2610 "sharpen_intensify_detail_strength",
2611 0.0f,
2612 0.0f,
2613 10.0f,
2614 "Intensify Details",
2615 "How much creases and valleys are intensified",
2616 0.0f,
2617 1.0f);
2618
2619 RNA_def_int(ot->srna,
2620 "sharpen_curvature_smooth_iterations",
2621 0,
2622 0,
2623 10,
2624 "Curvature Smooth Iterations",
2625 "How much smooth the resulting shape is, ignoring high frequency details",
2626 0,
2627 10);
2628}
2629
2630} // namespace blender::ed::sculpt_paint::filter
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
Definition BKE_ccg.hh:73
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool BKE_base_is_visible(const View3D *v3d, const Base *base)
#define SCULPT_FACE_SET_NONE
Definition BKE_paint.hh:324
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:650
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2797
A BVH for high poly meshes.
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_NOINLINE
BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
Definition BLI_hash.h:51
MINLINE float pow2f(float x)
void mul_m3_v3(const float M[3][3], float r[3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
unsigned int uint
#define ELEM(...)
#define BLT_I18NCONTEXT_AMOUNT
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define IFACE_(msgid)
@ BRUSH_AUTOMASKING_CAVITY_ALL
@ CD_PROP_INT32
#define UI_SCALE_FAC
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:1024
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
Read Guarded memory(de)allocation.
#define RNA_BEGIN(sptr, itemptr, propname)
#define RNA_END
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
@ PROP_HIDDEN
Definition RNA_types.hh:338
#define C
Definition RandGen.cpp:29
@ UI_ITEM_R_EXPAND
#define UI_ITEM_NONE
@ OPTYPE_BLOCKING
Definition WM_types.hh:184
@ OPTYPE_DEPENDS_ON_CURSOR
Definition WM_types.hh:218
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
@ OPTYPE_GRAB_CURSOR_X
Definition WM_types.hh:190
#define BM_elem_index_get(ele)
BMesh * bm
BPy_StructRNA * depsgraph
static unsigned long seed
Definition btSoftBody.h:39
Span< T > as_span() const
Definition BLI_array.hh:243
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:419
AttributeSet attributes
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr Span< T > as_span() const
Definition BLI_span.hh:661
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
GAttributeReader lookup(const StringRef attribute_id) const
void tag_positions_changed(const IndexMask &node_mask)
Definition pbvh.cc:635
Span< NodeT > nodes() const
void update_bounds(const Depsgraph &depsgraph, const Object &object)
Definition pbvh.cc:1386
void foreach_index(Fn &&fn) const
nullptr float
static float verts[][3]
ccl_device_inline float beta(const float x, const float y)
Definition math_base.h:661
static char faces[256]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
IndexMask search_nodes(const Tree &pbvh, IndexMaskMemory &memory, FunctionRef< bool(const Node &)> filter_fn)
Definition pbvh.cc:2663
void update_normals(const Depsgraph &depsgraph, Object &object_orig, Tree &pbvh)
Definition pbvh.cc:1257
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:1059
Cache & filter_cache_ensure(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob)
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &automasking, const bke::pbvh::MeshNode &node, Span< int > verts, MutableSpan< float > factors)
void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache &automasking, const bke::pbvh::GridsNode &node, Span< int > grids, MutableSpan< float > factors)
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br)
void ensure_boundary_info(Object &object)
Definition sculpt.cc:6073
void filter_verts_with_unique_face_sets_mesh(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const bool unique, const Span< int > verts, const MutableSpan< float > factors)
void filter_verts_with_unique_face_sets_bmesh(int face_set_offset, const bool unique, const Set< BMVert *, 0 > &verts, const MutableSpan< float > factors)
void filter_verts_with_unique_face_sets_grids(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const SubdivCCG &subdiv_ccg, const bool unique, const Span< int > grids, const MutableSpan< float > factors)
static void calc_inflate_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
static wmOperatorStatus sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void sculpt_mesh_update_strength(wmOperator *op, SculptSession &ss, float2 prev_press_mouse, float2 mouse)
static EnumPropertyItem prop_mesh_filter_types[]
static void sculpt_mesh_filter_apply_with_history(bContext *C, wmOperator *op)
static void calc_sharpen_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
static void calc_random_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
static bool sculpt_mesh_filter_is_continuous(MeshFilterType type)
static BLI_NOINLINE void calc_sharpen_detail_translations(const filter::Cache &filter_cache, const Span< float3 > positions, const Span< float3 > smooth_positions, const Span< float > sharpen_factors, const Span< float3 > detail_directions, const MutableSpan< float3 > translations)
static void sculpt_filter_specific_init(const Depsgraph &depsgraph, const MeshFilterType filter_type, wmOperator *op, Object &object)
static void sculpt_mesh_filter_end(bContext *C)
static void calc_enhance_details_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
static void calc_smooth_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask, const bool use_original_position)
void zero_disabled_axis_components(const filter::Cache &filter_cache, MutableSpan< float3 > vectors)
static void calc_scale_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
static wmOperatorStatus sculpt_mesh_filter_confirm(SculptSession &ss, wmOperator *op, const MeshFilterType filter_type)
float3x3 to_orientation_space(const filter::Cache &filter_cache)
static void calc_sphere_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
void cache_init(bContext *C, Object &ob, Sculpt &sd, undo::Type undo_type, const float mval_fl[2], float area_normal_radius, float start_strength)
static void mesh_filter_sharpen_init(const Depsgraph &depsgraph, const Object &object, const float smooth_ratio, const float intensify_detail_strength, const int curvature_smooth_iterations, filter::Cache &filter_cache)
static BLI_NOINLINE void calc_sphere_translations(const Span< float3 > positions, const Span< float > factors, const MutableSpan< float3 > translations)
static void calc_relax_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
static wmOperatorStatus sculpt_mesh_filter_exec(bContext *C, wmOperator *op)
static void calc_erase_displacement_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
static BLI_NOINLINE void clamp_factors(const MutableSpan< float > factors, const float min, const float max)
static void sculpt_mesh_ui_exec(bContext *, wmOperator *op)
static void sculpt_mesh_filter_cancel(bContext *C, wmOperator *)
static EnumPropertyItem prop_mesh_filter_orientation_items[]
static wmOperatorStatus sculpt_mesh_filter_start(bContext *C, wmOperator *op)
static void calc_surface_smooth_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
static void mesh_filter_surface_smooth_init(Object &object, const float shape_preservation, const float current_vertex_displacement)
static void calc_limit_surface_positions(const Object &object, MutableSpan< float3 > limit_positions)
float3x3 to_object_space(const filter::Cache &filter_cache)
static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op, bool is_replay=false)
void SCULPT_OT_mesh_filter(wmOperatorType *ot)
static bool sculpt_mesh_filter_needs_pmap(MeshFilterType filter_type)
static EnumPropertyItem prop_mesh_filter_deform_axis_items[]
static BLI_NOINLINE void randomize_factors(const Span< float3 > positions, const int seed, const MutableSpan< float > factors)
wmKeyMap * modal_keymap(wmKeyConfig *keyconf)
static void sculpt_mesh_update_status_bar(bContext *C, wmOperator *)
void register_operator_props(wmOperatorType *ot)
static wmOperatorStatus sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
void average_data_bmesh(const Span< T > src, const Set< BMVert *, 0 > &verts, const MutableSpan< T > dst)
void neighbor_position_average_interior_grids(const OffsetIndices< int > faces, const Span< int > corner_verts, const BitSpan boundary_verts, const SubdivCCG &subdiv_ccg, const Span< int > grids, const MutableSpan< float3 > new_positions)
void neighbor_data_average_mesh_check_loose(const Span< T > src, const Span< int > verts, const GroupedSpan< int > vert_neighbors, const MutableSpan< T > dst)
void neighbor_position_average_interior_bmesh(const Set< BMVert *, 0 > &verts, const Span< float > factors, const MutableSpan< float3 > new_positions)
void surface_smooth_laplacian_step(const Span< float3 > positions, const Span< float3 > orig_positions, const Span< float3 > average_positions, const float alpha, MutableSpan< float3 > laplacian_disp, MutableSpan< float3 > translations)
void surface_smooth_displace_step(const Span< float3 > laplacian_disp, const Span< float3 > average_laplacian_disp, const float beta, const MutableSpan< float3 > translations)
void average_data_grids(const SubdivCCG &subdiv_ccg, const Span< T > src, const Span< int > grids, const MutableSpan< T > dst)
void calc_relaxed_translations_grids(const SubdivCCG &subdiv_ccg, const OffsetIndices< int > faces, const Span< int > corner_verts, const Span< int > face_sets, const GroupedSpan< int > vert_to_face_map, const BitSpan boundary_verts, const Span< int > grids, const bool filter_boundary_face_sets, const Span< float > factors, const MutableSpan< float3 > translations)
void calc_relaxed_translations_bmesh(const Set< BMVert *, 0 > &verts, const Span< float3 > positions, const int face_set_offset, const bool filter_boundary_face_sets, const Span< float > factors, const MutableSpan< float3 > translations)
void calc_relaxed_translations_faces(const Span< float3 > vert_positions, const Span< float3 > vert_normals, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const BitSpan boundary_verts, const Span< int > face_sets, const Span< bool > hide_poly, const bool filter_boundary_face_sets, const Span< int > verts, const Span< float > factors, const MutableSpan< float3 > translations)
void neighbor_position_average_bmesh(const Set< BMVert *, 0 > &verts, const MutableSpan< float3 > new_positions)
void push_nodes(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const Type type)
void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
Definition sculpt.cc:1031
void push_begin(const Scene &scene, Object &ob, const wmOperator *op)
void push_end_ex(Object &ob, const bool use_nested_undo)
bool stroke_get_location_bvh(bContext *C, float out[3], const float mval[2], const bool force_original)
Definition sculpt.cc:4940
void fill_factor_from_hide_and_mask(Span< bool > hide_vert, Span< float > mask, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6823
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
void calc_smooth_translations(const Depsgraph &depsgraph, const Object &object, const IndexMask &node_mask, const MutableSpan< float3 > translations)
bool node_in_sphere(const bke::pbvh::Node &node, const float3 &location, const float radius_sq, const bool original)
Definition sculpt.cc:2429
void scatter_data_bmesh(Span< T > node_data, const Set< BMVert *, 0 > &verts, MutableSpan< T > dst)
Definition sculpt.cc:6461
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6367
void gather_data_grids(const SubdivCCG &subdiv_ccg, Span< T > src, Span< int > grids, MutableSpan< T > node_data)
Definition sculpt.cc:6405
void vert_random_access_ensure(Object &object)
Definition sculpt.cc:141
GroupedSpan< int > calc_vert_neighbors(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, Span< bool > hide_poly, Span< int > verts, Vector< int > &r_offset_data, Vector< int > &r_data)
Definition sculpt.cc:7597
bool node_fully_masked_or_hidden(const bke::pbvh::Node &node)
Definition sculpt.cc:2418
Vector< BMVert *, 64 > BMeshNeighborVerts
void gather_data_bmesh(Span< T > src, const Set< BMVert *, 0 > &verts, MutableSpan< T > node_data)
Definition sculpt.cc:6421
void reset_translations_to_original(MutableSpan< float3 > translations, Span< float3 > positions, Span< float3 > orig_positions)
Definition sculpt.cc:7249
void orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
Definition sculpt.cc:7495
bool report_if_shape_key_is_locked(const Object &ob, ReportList *reports)
Definition sculpt.cc:127
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7512
void translations_from_new_positions(Span< float3 > new_positions, Span< int > verts, Span< float3 > old_positions, MutableSpan< float3 > translations)
Definition sculpt.cc:7542
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7335
bool cursor_geometry_info_update(bContext *C, CursorGeometryInfo *out, const float2 &mval, const bool use_sampled_normal)
Definition sculpt.cc:4685
void flush_update_done(const bContext *C, Object &ob, const UpdateType update_type)
Definition sculpt.cc:5146
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6435
std::optional< float3 > calc_area_normal(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, const IndexMask &node_mask)
Definition sculpt.cc:1833
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, BMeshNeighborVerts &r_neighbors)
Definition sculpt.cc:387
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:7268
OrigPositionData orig_position_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6395
OrigPositionData orig_position_data_get_grids(const Object &object, const bke::pbvh::GridsNode &node)
float object_space_radius_get(const ViewContext &vc, const Paint &paint, const Brush &brush, const float3 &location, const float scale_factor)
Definition sculpt.cc:114
void flush_update_step(const bContext *C, const UpdateType update_type)
Definition sculpt.cc:5098
void scatter_data_grids(const SubdivCCG &subdiv_ccg, Span< T > node_data, Span< int > grids, MutableSpan< T > dst)
Definition sculpt.cc:6445
GroupedSpan< int > calc_vert_neighbors_interior(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, BitSpan boundary_verts, Span< bool > hide_poly, Span< int > verts, Vector< int > &r_offset_data, Vector< int > &r_data)
Definition sculpt.cc:7739
T safe_rcp(const T &a)
T length(const VecBase< T, Size > &a)
T midpoint(const T &a, const T &b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T square(const T &a)
T abs(const T &a)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
VecBase< float, 2 > float2
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
#define hash
Definition noise_c.cc:154
float paint_calc_object_space_radius(const ViewContext &vc, const blender::float3 &center, float pixel_radius)
const int status
return ret
void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
int RNA_collection_length(PointerRNA *ptr, const char *name)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_int_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const int *default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_collection_runtime(StructOrFunctionRNA *cont_, const char *identifier, StructRNA *type, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum_flag(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
bool SCULPT_mode_poll(bContext *C)
Definition sculpt.cc:3677
int SCULPT_vertex_count_get(const Object &object)
Definition sculpt.cc:151
#define min(a, b)
Definition sort.cc:36
int grid_size
Definition BKE_ccg.hh:33
int grid_area
Definition BKE_ccg.hh:35
ObjectRuntimeHandle * runtime
struct SculptSession * sculpt
struct UnifiedPaintSettings unified_paint_settings
PaintRuntimeHandle * runtime
float viewmat[4][4]
float viewinv[4][4]
blender::float3 last_normal
Definition BKE_paint.hh:515
BMLog * bm_log
Definition BKE_paint.hh:392
blender::ed::sculpt_paint::filter::Cache * filter_cache
Definition BKE_paint.hh:418
SculptVertexInfo vertex_info
Definition BKE_paint.hh:462
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
blender::BitVector boundary
Definition BKE_paint.hh:334
int to_index(const CCGKey &key) const
SubdivCCGNeighborCoords coords
blender::Array< blender::float3 > positions
RegionView3D * rv3d
Definition ED_view3d.hh:80
const c_style_mat & ptr() const
blender::float3 average_stroke_accum
std::unique_ptr< auto_mask::Cache > automasking
uiLayout & row(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
wmEventType type
Definition WM_types.hh:757
short val
Definition WM_types.hh:759
int xy[2]
Definition WM_types.hh:761
int mval[2]
Definition WM_types.hh:763
int prev_press_xy[2]
Definition WM_types.hh:830
const void * modal_items
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint len
void WM_cursor_modal_set(wmWindow *win, int val)
void WM_cursor_modal_restore(wmWindow *win)
@ WM_CURSOR_EW_SCROLL
Definition wm_cursors.hh:54
float WM_event_tablet_data(const wmEvent *event, bool *r_pen_flip, float r_tilt[2])
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ EVT_MODAL_MAP
@ MOUSEMOVE
wmOperatorType * ot
Definition wm_files.cc:4237
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:932
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:959