Blender V4.5
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
36#include "WM_api.hh"
37#include "WM_types.hh"
38
39#include "ED_screen.hh"
40#include "ED_sculpt.hh"
41#include "ED_view3d.hh"
42
43#include "mesh_brush_common.hh"
44#include "paint_intern.hh"
45#include "sculpt_automask.hh"
46#include "sculpt_boundary.hh"
47#include "sculpt_cloth.hh"
48#include "sculpt_face_set.hh"
49#include "sculpt_intern.hh"
50#include "sculpt_smooth.hh"
51#include "sculpt_undo.hh"
52
53#include "RNA_access.hh"
54#include "RNA_define.hh"
55#include "RNA_prototypes.hh"
56
57#include "UI_interface.hh"
58#include "UI_resources.hh"
59
60#include "bmesh.hh"
61
62#include <algorithm>
63#include <cmath>
64#include <cstdlib>
65
67
69{
70 switch (filter_cache.orientation) {
72 return float3x3::identity();
74 return float3x3(filter_cache.obmat);
76 return float3x3(filter_cache.obmat * filter_cache.viewmat);
77 }
79 return float3x3::identity();
80}
81
83{
84 switch (filter_cache.orientation) {
86 return float3x3::identity();
88 return float3x3(filter_cache.obmat_inv);
90 return float3x3(filter_cache.viewmat_inv * filter_cache.obmat_inv);
91 }
93 return float3x3::identity();
94}
95
97 const MutableSpan<float3> vectors)
98{
99 if (filter_cache.enabled_axis[0] && filter_cache.enabled_axis[1] && filter_cache.enabled_axis[2])
100 {
101 return;
102 }
103
104 if (filter_cache.orientation == FilterOrientation::Local) {
105 for (const int i : vectors.index_range()) {
106 for (int axis = 0; axis < 3; axis++) {
107 if (!filter_cache.enabled_axis[axis]) {
108 vectors[i][axis] = 0.0f;
109 }
110 }
111 }
112 }
113
114 const float3x3 local_to_orientation = to_orientation_space(filter_cache);
115 const float3x3 orientation_to_object = to_object_space(filter_cache);
116 for (const int i : vectors.index_range()) {
117 float3 vector = local_to_orientation * vectors[i];
118 for (int axis = 0; axis < 3; axis++) {
119 if (!filter_cache.enabled_axis[axis]) {
120 vector[axis] = 0.0f;
121 }
122 }
123 vectors[i] = orientation_to_object * vector;
124 }
125}
126
127Cache::~Cache() = default;
128
130 Object &ob,
131 const Sculpt &sd,
132 const undo::Type undo_type,
133 const float mval_fl[2],
134 float area_normal_radius,
135 float start_strength)
136{
137 SculptSession &ss = *ob.sculpt;
140
141 ss.filter_cache = MEM_new<filter::Cache>(__func__);
142 ss.filter_cache->start_filter_strength = start_strength;
143 ss.filter_cache->random_seed = rand();
144
146 pbvh, ss.filter_cache->node_mask_memory, [&](const bke::pbvh::Node &node) {
147 return !node_fully_masked_or_hidden(node);
148 });
149
150 undo::push_nodes(*depsgraph, ob, ss.filter_cache->node_mask, undo_type);
151
152 /* Setup orientation matrices. */
153 copy_m4_m4(ss.filter_cache->obmat.ptr(), ob.object_to_world().ptr());
154 invert_m4_m4(ss.filter_cache->obmat_inv.ptr(), ob.object_to_world().ptr());
155
157
158 ss.filter_cache->vc = vc;
159 if (vc.rv3d) {
162 }
163
164 Scene *scene = CTX_data_scene(C);
166
167 float3 co;
168
169 if (vc.rv3d && stroke_get_location_bvh(C, co, mval_fl, false)) {
170 /* Get radius from brush. */
171 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
172
173 float radius;
174 if (brush) {
175 radius = object_space_radius_get(vc, *scene, *brush, co, area_normal_radius);
176 }
177 else {
178 radius = paint_calc_object_space_radius(vc, co, float(ups->size) * area_normal_radius);
179 }
180
181 const float radius_sq = math::square(radius);
182
183 IndexMaskMemory memory;
184 const IndexMask node_mask = bke::pbvh::search_nodes(
185 pbvh, memory, [&](const bke::pbvh::Node &node) {
186 return !node_fully_masked_or_hidden(node) && node_in_sphere(node, co, radius_sq, true);
187 });
188
189 const std::optional<float3> area_normal = calc_area_normal(*depsgraph, *brush, ob, node_mask);
190 if (BKE_paint_brush_for_read(&sd.paint) && area_normal) {
191 ss.filter_cache->initial_normal = *area_normal;
193 }
194 else {
196 }
197
198 /* Update last stroke location */
199
200 mul_m4_v3(ob.object_to_world().ptr(), co);
201
204 ups->last_stroke_valid = true;
205 }
206 else {
207 /* Use last normal. */
209 }
210
211 /* Update view normal */
212 float3x3 mat;
213 float3 viewDir{0.0f, 0.0f, 1.0f};
214 if (vc.rv3d) {
215 invert_m4_m4(ob.runtime->world_to_object.ptr(), ob.object_to_world().ptr());
216 copy_m3_m4(mat.ptr(), vc.rv3d->viewinv);
217 mul_m3_v3(mat.ptr(), viewDir);
218 copy_m3_m4(mat.ptr(), ob.world_to_object().ptr());
219 mul_m3_v3(mat.ptr(), viewDir);
221 }
222}
223
237
239 {int(MeshFilterType::Smooth), "SMOOTH", 0, "Smooth", "Smooth mesh"},
240 {int(MeshFilterType::Scale), "SCALE", 0, "Scale", "Scale mesh"},
241 {int(MeshFilterType::Inflate), "INFLATE", 0, "Inflate", "Inflate mesh"},
242 {int(MeshFilterType::Sphere), "SPHERE", 0, "Sphere", "Morph into sphere"},
243 {int(MeshFilterType::Random), "RANDOM", 0, "Random", "Randomize vertex positions"},
244 {int(MeshFilterType::Relax), "RELAX", 0, "Relax", "Relax mesh"},
246 "RELAX_FACE_SETS",
247 0,
248 "Relax Face Sets",
249 "Smooth the edges of all the Face Sets"},
251 "SURFACE_SMOOTH",
252 0,
253 "Surface Smooth",
254 "Smooth the surface of the mesh, preserving the volume"},
255 {int(MeshFilterType::Sharpen), "SHARPEN", 0, "Sharpen", "Sharpen the cavities of the mesh"},
257 "ENHANCE_DETAILS",
258 0,
259 "Enhance Details",
260 "Enhance the high frequency surface detail"},
262 "ERASE_DISPLACEMENT",
263 0,
264 "Erase Displacement",
265 "Deletes the displacement of the Multires Modifier"},
266 {0, nullptr, 0, nullptr, nullptr},
267};
268
274
276 {MESH_FILTER_DEFORM_X, "X", 0, "X", "Deform in the X axis"},
277 {MESH_FILTER_DEFORM_Y, "Y", 0, "Y", "Deform in the Y axis"},
278 {MESH_FILTER_DEFORM_Z, "Z", 0, "Z", "Deform in the Z axis"},
279 {0, nullptr, 0, nullptr, nullptr},
280};
281
284 "LOCAL",
285 0,
286 "Local",
287 "Use the local axis to limit the displacement"},
289 "WORLD",
290 0,
291 "World",
292 "Use the global axis to limit the displacement"},
294 "VIEW",
295 0,
296 "View",
297 "Use the view axis to limit the displacement"},
298 {0, nullptr, 0, nullptr, nullptr},
299};
300
311
320
322 const float min,
323 const float max)
324{
325 for (float &factor : factors) {
326 factor = std::clamp(factor, min, max);
327 }
328}
329
330static void calc_smooth_filter(const Depsgraph &depsgraph,
331 const Sculpt &sd,
332 const float strength,
333 Object &object,
334 const IndexMask &node_mask,
335 const bool use_original_position)
336{
337 struct LocalData {
338 Vector<float> factors;
339 Vector<float3> positions;
340 Vector<int> neighbor_offsets;
341 Vector<int> neighbor_data;
342 Vector<float3> new_positions;
343 Vector<float3> translations;
344 };
345 SculptSession &ss = *object.sculpt;
346 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
347 switch (pbvh.type()) {
349 Mesh &mesh = *static_cast<Mesh *>(object.data);
350 const MeshAttributeData attribute_data(mesh);
351 const PositionDeformData position_data(depsgraph, object);
352 const OffsetIndices faces = mesh.faces();
353 const Span<int> corner_verts = mesh.corner_verts();
354 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
357 node_mask.foreach_index(GrainSize(1), [&](const int i) {
358 LocalData &tls = all_tls.local();
359 const Span<int> verts = nodes[i].verts();
360 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
361 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
362
363 tls.factors.resize(verts.size());
364 const MutableSpan<float> factors = tls.factors;
366 attribute_data.hide_vert, attribute_data.mask, verts, factors);
368 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
369 scale_factors(factors, strength);
370 clamp_factors(factors, -1.0f, 1.0f);
371
373 corner_verts,
374 vert_to_face_map,
376 attribute_data.hide_poly,
377 verts,
378 tls.neighbor_offsets,
379 tls.neighbor_data);
380
381 tls.new_positions.resize(verts.size());
382 const MutableSpan<float3> new_positions = tls.new_positions;
384 position_data.eval, verts, neighbors, new_positions);
385
386 tls.translations.resize(verts.size());
387 const MutableSpan<float3> translations = tls.translations;
388 if (use_original_position) {
389 translations_from_new_positions(new_positions, orig_data.positions, translations);
390 }
391 else {
392 translations_from_new_positions(new_positions, positions, translations);
393 }
394 scale_translations(translations, factors);
395 if (use_original_position) {
396 reset_translations_to_original(translations, positions, orig_data.positions);
397 }
398
400 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
401 position_data.deform(translations, verts);
402 });
403 break;
404 }
406 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
407 const OffsetIndices faces = base_mesh.faces();
408 const Span<int> corner_verts = base_mesh.corner_verts();
409
410 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
413 node_mask.foreach_index(GrainSize(1), [&](const int i) {
414 LocalData &tls = all_tls.local();
415 const Span<int> grids = nodes[i].grids();
416 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
417 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
418
419 tls.factors.resize(positions.size());
420 const MutableSpan<float> factors = tls.factors;
421 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
423 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
424 scale_factors(factors, strength);
425 clamp_factors(factors, -1.0f, 1.0f);
426
427 tls.new_positions.resize(positions.size());
428 const MutableSpan<float3> new_positions = tls.new_positions;
430 faces, corner_verts, ss.vertex_info.boundary, subdiv_ccg, grids, new_positions);
431
432 tls.translations.resize(positions.size());
433 const MutableSpan<float3> translations = tls.translations;
434 if (use_original_position) {
435 translations_from_new_positions(new_positions, orig_data.positions, translations);
436 }
437 else {
438 translations_from_new_positions(new_positions, positions, translations);
439 }
440 scale_translations(translations, factors);
441 if (use_original_position) {
442 reset_translations_to_original(translations, positions, orig_data.positions);
443 }
444
446 clip_and_lock_translations(sd, ss, positions, translations);
447 apply_translations(translations, grids, subdiv_ccg);
448 });
449 break;
450 }
452 BMesh &bm = *ss.bm;
455 node_mask.foreach_index(GrainSize(1), [&](const int i) {
456 LocalData &tls = all_tls.local();
458 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
459 Array<float3> orig_positions(verts.size());
460 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
461
462 tls.factors.resize(verts.size());
463 const MutableSpan<float> factors = tls.factors;
466 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
467 scale_factors(factors, strength);
468 clamp_factors(factors, -1.0f, 1.0f);
469
470 tls.new_positions.resize(verts.size());
471 const MutableSpan<float3> new_positions = tls.new_positions;
473
474 tls.translations.resize(verts.size());
475 const MutableSpan<float3> translations = tls.translations;
476 if (use_original_position) {
477 translations_from_new_positions(new_positions, orig_positions, translations);
478 }
479 else {
480 translations_from_new_positions(new_positions, positions, translations);
481 }
482 scale_translations(translations, factors);
483 if (use_original_position) {
484 reset_translations_to_original(translations, positions, orig_positions);
485 }
486
488 clip_and_lock_translations(sd, ss, positions, translations);
489 apply_translations(translations, verts);
490 });
491 break;
492 }
493 }
494}
495
496static void calc_inflate_filter(const Depsgraph &depsgraph,
497 const Sculpt &sd,
498 const float strength,
499 Object &object,
500 const IndexMask &node_mask)
501{
502 struct LocalData {
503 Vector<float> factors;
504 Vector<float3> positions;
505 Vector<float3> translations;
506 };
507 SculptSession &ss = *object.sculpt;
508 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
509 switch (pbvh.type()) {
511 Mesh &mesh = *static_cast<Mesh *>(object.data);
512 bke::AttributeAccessor attributes = mesh.attributes();
513 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
514 const VArraySpan mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
515 const PositionDeformData position_data(depsgraph, object);
518 node_mask.foreach_index(GrainSize(1), [&](const int i) {
519 LocalData &tls = all_tls.local();
520 const Span<int> verts = nodes[i].verts();
521 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
522
523 tls.factors.resize(verts.size());
524 const MutableSpan<float> factors = tls.factors;
525 fill_factor_from_hide_and_mask(hide_vert, mask, verts, factors);
527 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
528 scale_factors(factors, strength);
529
530 tls.translations.resize(verts.size());
531 const MutableSpan<float3> translations = tls.translations;
532 translations.copy_from(orig_data.normals);
533 scale_translations(translations, factors);
534
536 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
537 position_data.deform(translations, verts);
538 });
539 break;
540 }
542 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
545 node_mask.foreach_index(GrainSize(1), [&](const int i) {
546 LocalData &tls = all_tls.local();
547 const Span<int> grids = nodes[i].grids();
548 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
549 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
550
551 tls.factors.resize(positions.size());
552 const MutableSpan<float> factors = tls.factors;
553 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
555 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
556 scale_factors(factors, strength);
557
558 tls.translations.resize(positions.size());
559 const MutableSpan<float3> translations = tls.translations;
560 translations.copy_from(orig_data.normals);
561 scale_translations(translations, factors);
562
564 clip_and_lock_translations(sd, ss, positions, translations);
565 apply_translations(translations, grids, subdiv_ccg);
566 });
567 break;
568 }
570 BMesh &bm = *ss.bm;
573 node_mask.foreach_index(GrainSize(1), [&](const int i) {
574 LocalData &tls = all_tls.local();
576 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
577 Array<float3> orig_positions(verts.size());
578 Array<float3> orig_normals(verts.size());
579 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
580
581 tls.factors.resize(verts.size());
582 const MutableSpan<float> factors = tls.factors;
585 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
586 scale_factors(factors, strength);
587
588 tls.translations.resize(verts.size());
589 const MutableSpan<float3> translations = tls.translations;
590 translations.copy_from(orig_normals);
591 scale_translations(translations, factors);
592
594 clip_and_lock_translations(sd, ss, positions, translations);
595 apply_translations(translations, verts);
596 });
597 break;
598 }
599 }
600}
601
602static void calc_scale_filter(const Depsgraph &depsgraph,
603 const Sculpt &sd,
604 const float strength,
605 Object &object,
606 const IndexMask &node_mask)
607{
608 struct LocalData {
609 Vector<float> factors;
610 Vector<float3> positions;
611 Vector<float3> translations;
612 };
613 SculptSession &ss = *object.sculpt;
614 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
615 switch (pbvh.type()) {
617 Mesh &mesh = *static_cast<Mesh *>(object.data);
618 const MeshAttributeData attribute_data(mesh);
619 const PositionDeformData position_data(depsgraph, object);
622 node_mask.foreach_index(GrainSize(1), [&](const int i) {
623 LocalData &tls = all_tls.local();
624 const Span<int> verts = nodes[i].verts();
625 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
626
627 tls.factors.resize(verts.size());
628 const MutableSpan<float> factors = tls.factors;
630 attribute_data.hide_vert, attribute_data.mask, verts, factors);
632 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
633 scale_factors(factors, strength);
634
635 tls.translations.resize(verts.size());
636 const MutableSpan<float3> translations = tls.translations;
637 translations.copy_from(orig_data.positions);
638 scale_translations(translations, factors);
639
641 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
642 position_data.deform(translations, verts);
643 });
644 break;
645 }
647 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
650 node_mask.foreach_index(GrainSize(1), [&](const int i) {
651 LocalData &tls = all_tls.local();
652 const Span<int> grids = nodes[i].grids();
653 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
654 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
655
656 tls.factors.resize(positions.size());
657 const MutableSpan<float> factors = tls.factors;
658 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
660 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
661 scale_factors(factors, strength);
662
663 tls.translations.resize(positions.size());
664 const MutableSpan<float3> translations = tls.translations;
665 translations.copy_from(orig_data.positions);
666 scale_translations(translations, factors);
667
669 clip_and_lock_translations(sd, ss, positions, translations);
670 apply_translations(translations, grids, subdiv_ccg);
671 });
672 break;
673 }
675 BMesh &bm = *ss.bm;
678 node_mask.foreach_index(GrainSize(1), [&](const int i) {
679 LocalData &tls = all_tls.local();
681 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
682 Array<float3> orig_positions(verts.size());
683 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
684
685 tls.factors.resize(verts.size());
686 const MutableSpan<float> factors = tls.factors;
689 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
690 scale_factors(factors, strength);
691
692 tls.translations.resize(positions.size());
693 const MutableSpan<float3> translations = tls.translations;
694 translations.copy_from(orig_positions);
695 scale_translations(translations, factors);
696
698 clip_and_lock_translations(sd, ss, positions, translations);
699 apply_translations(translations, verts);
700 });
701 break;
702 }
703 }
704}
705
707 const Span<float> factors,
708 const MutableSpan<float3> translations)
709{
710 for (const int i : positions.index_range()) {
711 translations[i] = math::midpoint(math::normalize(positions[i]), -positions[i]) *
712 math::abs(factors[i]);
713 }
714}
715
716static void calc_sphere_filter(const Depsgraph &depsgraph,
717 const Sculpt &sd,
718 const float strength,
719 Object &object,
720 const IndexMask &node_mask)
721{
722 struct LocalData {
723 Vector<float> factors;
724 Vector<float3> positions;
725 Vector<float3> translations;
726 };
727 SculptSession &ss = *object.sculpt;
728 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
729 switch (pbvh.type()) {
731 Mesh &mesh = *static_cast<Mesh *>(object.data);
732 const PositionDeformData position_data(depsgraph, object);
733 const MeshAttributeData attribute_data(mesh);
736 node_mask.foreach_index(GrainSize(1), [&](const int i) {
737 LocalData &tls = all_tls.local();
738 const Span<int> verts = nodes[i].verts();
739 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
740
741 tls.factors.resize(verts.size());
742 const MutableSpan<float> factors = tls.factors;
744 attribute_data.hide_vert, attribute_data.mask, verts, factors);
746 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
747 scale_factors(factors, strength);
748
749 tls.translations.resize(verts.size());
750 const MutableSpan<float3> translations = tls.translations;
751 calc_sphere_translations(positions, factors, translations);
752
754 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
755 position_data.deform(translations, verts);
756 });
757 break;
758 }
760 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
763 node_mask.foreach_index(GrainSize(1), [&](const int i) {
764 LocalData &tls = all_tls.local();
765 const Span<int> grids = nodes[i].grids();
766 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
767
768 tls.factors.resize(positions.size());
769 const MutableSpan<float> factors = tls.factors;
770 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
772 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
773 scale_factors(factors, strength);
774
775 tls.translations.resize(positions.size());
776 const MutableSpan<float3> translations = tls.translations;
777 calc_sphere_translations(positions, factors, translations);
778
780 clip_and_lock_translations(sd, ss, positions, translations);
781 apply_translations(translations, grids, subdiv_ccg);
782 });
783 break;
784 }
786 BMesh &bm = *ss.bm;
789 node_mask.foreach_index(GrainSize(1), [&](const int i) {
790 LocalData &tls = all_tls.local();
792 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
793
794 tls.factors.resize(verts.size());
795 const MutableSpan<float> factors = tls.factors;
798 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
799 scale_factors(factors, strength);
800
801 tls.translations.resize(verts.size());
802 const MutableSpan<float3> translations = tls.translations;
803 calc_sphere_translations(positions, factors, translations);
804
806 clip_and_lock_translations(sd, ss, positions, translations);
807 apply_translations(translations, verts);
808 });
809 break;
810 }
811 }
812}
813
814BLI_NOINLINE static void randomize_factors(const Span<float3> positions,
815 const int seed,
816 const MutableSpan<float> factors)
817{
818 BLI_assert(positions.size() == factors.size());
819 for (const int i : positions.index_range()) {
820 const uint *hash_co = (const uint *)&positions[i];
821 const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^ BLI_hash_int_2d(hash_co[2], seed);
822 factors[i] *= (hash * (1.0f / float(0xFFFFFFFF)) - 0.5f);
823 }
824}
825
826static void calc_random_filter(const Depsgraph &depsgraph,
827 const Sculpt &sd,
828 const float strength,
829 Object &object,
830 const IndexMask &node_mask)
831{
832 struct LocalData {
833 Vector<float> factors;
834 Vector<float3> positions;
835 Vector<float3> translations;
836 };
837 SculptSession &ss = *object.sculpt;
838 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
839 switch (pbvh.type()) {
841 Mesh &mesh = *static_cast<Mesh *>(object.data);
842 const MeshAttributeData attribute_data(mesh);
843 const PositionDeformData position_data(depsgraph, object);
846 node_mask.foreach_index(GrainSize(1), [&](const int i) {
847 LocalData &tls = all_tls.local();
848 const Span<int> verts = nodes[i].verts();
849 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
850 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
851
852 tls.factors.resize(verts.size());
853 const MutableSpan<float> factors = tls.factors;
855 attribute_data.hide_vert, attribute_data.mask, verts, factors);
857 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
858 scale_factors(factors, strength);
859
860 randomize_factors(positions, ss.filter_cache->random_seed, factors);
861 tls.translations.resize(verts.size());
862 const MutableSpan<float3> translations = tls.translations;
863 translations.copy_from(orig_data.normals);
864 scale_translations(translations, factors);
865
867 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
868 position_data.deform(translations, verts);
869 });
870 break;
871 }
873 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
876 node_mask.foreach_index(GrainSize(1), [&](const int i) {
877 LocalData &tls = all_tls.local();
878 const Span<int> grids = nodes[i].grids();
879 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
880 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
881
882 tls.factors.resize(positions.size());
883 const MutableSpan<float> factors = tls.factors;
884 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
886 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
887 scale_factors(factors, strength);
888
889 randomize_factors(positions, ss.filter_cache->random_seed, factors);
890 tls.translations.resize(positions.size());
891 const MutableSpan<float3> translations = tls.translations;
892 translations.copy_from(orig_data.normals);
893 scale_translations(translations, factors);
894
896 clip_and_lock_translations(sd, ss, positions, translations);
897 apply_translations(translations, grids, subdiv_ccg);
898 });
899 break;
900 }
902 BMesh &bm = *ss.bm;
905 node_mask.foreach_index(GrainSize(1), [&](const int i) {
906 LocalData &tls = all_tls.local();
908 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
909 Array<float3> orig_positions(verts.size());
910 Array<float3> orig_normals(verts.size());
911 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
912
913 tls.factors.resize(verts.size());
914 const MutableSpan<float> factors = tls.factors;
917 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
918 scale_factors(factors, strength);
919
920 randomize_factors(positions, ss.filter_cache->random_seed, factors);
921 tls.translations.resize(verts.size());
922 const MutableSpan<float3> translations = tls.translations;
923 translations.copy_from(orig_normals);
924 scale_translations(translations, factors);
925
927 clip_and_lock_translations(sd, ss, positions, translations);
928 apply_translations(translations, verts);
929 });
930 break;
931 }
932 }
933}
934
935static void calc_relax_filter(const Depsgraph &depsgraph,
936 const Sculpt &sd,
937 const float strength,
938 Object &object,
939 const IndexMask &node_mask)
940{
941 SculptSession &ss = *object.sculpt;
942 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
944 switch (pbvh.type()) {
945 struct LocalData {
946 Vector<float> factors;
947 Vector<float3> translations;
948 };
950 Mesh &mesh = *static_cast<Mesh *>(object.data);
951 const PositionDeformData position_data(depsgraph, object);
952 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
953 const OffsetIndices faces = mesh.faces();
954 const Span<int> corner_verts = mesh.corner_verts();
955 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
956 const MeshAttributeData attribute_data(mesh);
959 node_mask.foreach_index(GrainSize(1), [&](const int i) {
960 LocalData &tls = all_tls.local();
961 const Span<int> verts = nodes[i].verts();
962
963 tls.factors.resize(verts.size());
964 const MutableSpan<float> factors = tls.factors;
966 attribute_data.hide_vert, attribute_data.mask, verts, factors);
968 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
969 scale_factors(factors, strength);
970 clamp_factors(factors, 0.0f, 1.0f);
971
972 tls.translations.resize(verts.size());
973 const MutableSpan<float3> translations = tls.translations;
975 vert_normals,
976 faces,
977 corner_verts,
978 vert_to_face_map,
980 attribute_data.face_sets,
981 attribute_data.hide_poly,
982 false,
983 verts,
984 factors,
985 translations);
986
988 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
989 position_data.deform(translations, verts);
990 });
991 break;
992 }
994 struct LocalData {
995 Vector<float> factors;
996 Vector<float3> positions;
997 Vector<float3> translations;
998 };
999 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
1000 const OffsetIndices faces = base_mesh.faces();
1001 const Span<int> corner_verts = base_mesh.corner_verts();
1002 const GroupedSpan<int> vert_to_face_map = base_mesh.vert_to_face_map();
1003 const bke::AttributeAccessor attributes = base_mesh.attributes();
1004 const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set",
1006 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1009 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1010 LocalData &tls = all_tls.local();
1011 const Span<int> grids = nodes[i].grids();
1012 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1013
1014 tls.factors.resize(positions.size());
1015 const MutableSpan<float> factors = tls.factors;
1016 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1018 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1019 scale_factors(factors, strength);
1020 clamp_factors(factors, 0.0f, 1.0f);
1021
1022 tls.translations.resize(positions.size());
1023 const MutableSpan<float3> translations = tls.translations;
1025 faces,
1026 corner_verts,
1027 face_sets,
1028 vert_to_face_map,
1030 grids,
1031 false,
1032 factors,
1033 translations);
1034
1036 clip_and_lock_translations(sd, ss, positions, translations);
1037 apply_translations(translations, grids, subdiv_ccg);
1038 });
1039 break;
1040 }
1042 struct LocalData {
1043 Vector<float> factors;
1044 Vector<float3> positions;
1045 Vector<float3> translations;
1046 };
1047 BMesh &bm = *ss.bm;
1048 const int face_set_offset = CustomData_get_offset_named(
1049 &bm.pdata, CD_PROP_INT32, ".sculpt_face_set");
1050
1053 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1054 LocalData &tls = all_tls.local();
1056 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1057
1058 tls.factors.resize(verts.size());
1059 const MutableSpan<float> factors = tls.factors;
1062 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1063 scale_factors(factors, strength);
1064 clamp_factors(factors, 0.0f, 1.0f);
1065
1066 tls.translations.resize(verts.size());
1067 const MutableSpan<float3> translations = tls.translations;
1069 verts, positions, face_set_offset, false, factors, translations);
1070
1072 clip_and_lock_translations(sd, ss, positions, translations);
1073 apply_translations(translations, verts);
1074 });
1075 break;
1076 }
1077 }
1078}
1079
1080static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
1081 const Sculpt &sd,
1082 const float strength,
1083 Object &object,
1084 const IndexMask &node_mask)
1085{
1086 SculptSession &ss = *object.sculpt;
1087 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1088 bke::pbvh::update_normals(depsgraph, object, pbvh);
1089
1090 /* When using the relax face sets meshes filter, each 3 iterations, do a whole mesh relax to
1091 * smooth the contents of the Face Set. This produces better results as the relax operation is no
1092 * completely focused on the boundaries. */
1093 const bool relax_face_sets = !(ss.filter_cache->iteration_count % 3 == 0);
1094
1095 switch (pbvh.type()) {
1096 case bke::pbvh::Type::Mesh: {
1097 struct LocalData {
1098 Vector<float> factors;
1099 Vector<float3> positions;
1100 Vector<float3> translations;
1101 };
1102 Mesh &mesh = *static_cast<Mesh *>(object.data);
1103 const PositionDeformData position_data(depsgraph, object);
1104 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
1105 const OffsetIndices faces = mesh.faces();
1106 const Span<int> corner_verts = mesh.corner_verts();
1107 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1108 const MeshAttributeData attribute_data(mesh);
1111 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1112 LocalData &tls = all_tls.local();
1113 const Span<int> verts = nodes[i].verts();
1114
1115 tls.factors.resize(verts.size());
1116 const MutableSpan<float> factors = tls.factors;
1118 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1120 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1121 scale_factors(factors, strength);
1122 clamp_factors(factors, 0.0f, 1.0f);
1123
1125 vert_to_face_map, attribute_data.face_sets, relax_face_sets, verts, factors);
1126
1127 tls.translations.resize(verts.size());
1128 const MutableSpan<float3> translations = tls.translations;
1130 vert_normals,
1131 faces,
1132 corner_verts,
1133 vert_to_face_map,
1135 attribute_data.face_sets,
1136 attribute_data.hide_poly,
1137 relax_face_sets,
1138 verts,
1139 factors,
1140 translations);
1141
1143 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1144 position_data.deform(translations, verts);
1145 });
1146 break;
1147 }
1149 struct LocalData {
1150 Vector<float> factors;
1151 Vector<float3> positions;
1152 Vector<float3> translations;
1153 };
1154 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
1155 const OffsetIndices faces = base_mesh.faces();
1156 const Span<int> corner_verts = base_mesh.corner_verts();
1157 const GroupedSpan<int> vert_to_face_map = base_mesh.vert_to_face_map();
1158 const bke::AttributeAccessor attributes = base_mesh.attributes();
1159 const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set",
1161
1162 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1165 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1166 LocalData &tls = all_tls.local();
1167 const Span<int> grids = nodes[i].grids();
1168 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1169
1170 tls.factors.resize(positions.size());
1171 const MutableSpan<float> factors = tls.factors;
1172 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1174 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1175 scale_factors(factors, strength);
1176 clamp_factors(factors, 0.0f, 1.0f);
1177
1179 corner_verts,
1180 vert_to_face_map,
1181 face_sets,
1182 subdiv_ccg,
1183 relax_face_sets,
1184 grids,
1185 factors);
1186
1187 tls.translations.resize(positions.size());
1188 const MutableSpan<float3> translations = tls.translations;
1190 faces,
1191 corner_verts,
1192 face_sets,
1193 vert_to_face_map,
1195 grids,
1196 relax_face_sets,
1197 factors,
1198 translations);
1199
1201 clip_and_lock_translations(sd, ss, positions, translations);
1202 apply_translations(translations, grids, subdiv_ccg);
1203 });
1204 break;
1205 }
1207 struct LocalData {
1208 Vector<float> factors;
1209 Vector<float3> positions;
1210 Vector<float3> translations;
1211 };
1212 BMesh &bm = *ss.bm;
1213 const int face_set_offset = CustomData_get_offset_named(
1214 &bm.pdata, CD_PROP_INT32, ".sculpt_face_set");
1217 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1218 LocalData &tls = all_tls.local();
1220 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1221
1222 tls.factors.resize(verts.size());
1223 const MutableSpan<float> factors = tls.factors;
1226 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1227 scale_factors(factors, strength);
1228 clamp_factors(factors, 0.0f, 1.0f);
1229
1231 face_set_offset, relax_face_sets, verts, factors);
1232
1233 tls.translations.resize(verts.size());
1234 const MutableSpan<float3> translations = tls.translations;
1236 verts, positions, face_set_offset, relax_face_sets, factors, translations);
1237
1239 clip_and_lock_translations(sd, ss, positions, translations);
1240 apply_translations(translations, verts);
1241 });
1242 break;
1243 }
1244 }
1245}
1246
1247static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
1248 const Sculpt &sd,
1249 const float strength,
1250 Object &object,
1251 const IndexMask &node_mask)
1252{
1253 struct LocalData {
1254 Vector<float> factors;
1255 Vector<float3> positions;
1256 Vector<int> neighbor_offsets;
1257 Vector<int> neighbor_data;
1258 Vector<float3> average_positions;
1259 Vector<float3> laplacian_disp;
1260 Vector<float3> translations;
1261 };
1262 SculptSession &ss = *object.sculpt;
1263 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1264 const float alpha = ss.filter_cache->surface_smooth_shape_preservation;
1266 const MutableSpan<float3> all_laplacian_disp = ss.filter_cache->surface_smooth_laplacian_disp;
1267 switch (pbvh.type()) {
1268 case bke::pbvh::Type::Mesh: {
1269 Mesh &mesh = *static_cast<Mesh *>(object.data);
1270 const MeshAttributeData attribute_data(mesh);
1271 const PositionDeformData position_data(depsgraph, object);
1272 const OffsetIndices faces = mesh.faces();
1273 const Span<int> corner_verts = mesh.corner_verts();
1274 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1277 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1278 LocalData &tls = all_tls.local();
1279 const Span<int> verts = nodes[i].verts();
1280 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
1281 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
1282
1283 tls.factors.resize(verts.size());
1284 const MutableSpan<float> factors = tls.factors;
1286 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1288 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1289 scale_factors(factors, strength);
1290 clamp_factors(factors, 0.0f, 1.0f);
1291
1292 const GroupedSpan<int> neighbors = calc_vert_neighbors(faces,
1293 corner_verts,
1294 vert_to_face_map,
1295 attribute_data.hide_poly,
1296 verts,
1297 tls.neighbor_offsets,
1298 tls.neighbor_data);
1299
1300 tls.average_positions.reinitialize(verts.size());
1301 const MutableSpan<float3> average_positions = tls.average_positions;
1303 position_data.eval, verts, neighbors, average_positions);
1304
1305 tls.laplacian_disp.reinitialize(verts.size());
1306 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
1307 tls.translations.reinitialize(verts.size());
1308 const MutableSpan<float3> translations = tls.translations;
1310 orig_data.positions,
1311 average_positions,
1312 alpha,
1313 laplacian_disp,
1314 translations);
1315 scale_translations(translations, factors);
1316
1317 scatter_data_mesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
1318
1320 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1321 position_data.deform(translations, verts);
1322 });
1323 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1324 LocalData &tls = all_tls.local();
1325 const Span<int> verts = nodes[i].verts();
1326
1327 tls.factors.resize(verts.size());
1328 const MutableSpan<float> factors = tls.factors;
1330 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1332 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1333 scale_factors(factors, strength);
1334 clamp_factors(factors, 0.0f, 1.0f);
1335
1336 const MutableSpan<float3> laplacian_disp = gather_data_mesh(
1337 all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
1338
1339 const GroupedSpan<int> neighbors = calc_vert_neighbors(faces,
1340 corner_verts,
1341 vert_to_face_map,
1342 attribute_data.hide_poly,
1343 verts,
1344 tls.neighbor_offsets,
1345 tls.neighbor_data);
1346
1347 tls.average_positions.resize(verts.size());
1348 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
1350 all_laplacian_disp.as_span(), verts, neighbors, average_laplacian_disps);
1351
1352 tls.translations.resize(verts.size());
1353 const MutableSpan<float3> translations = tls.translations;
1355 laplacian_disp, average_laplacian_disps, beta, translations);
1356 scale_translations(translations, factors);
1357
1359 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1360 position_data.deform(translations, verts);
1361 });
1362 break;
1363 }
1365 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1368 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1369 LocalData &tls = all_tls.local();
1370 const Span<int> grids = nodes[i].grids();
1371 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1372 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
1373
1374 tls.factors.resize(positions.size());
1375 const MutableSpan<float> factors = tls.factors;
1376 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1378 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1379 scale_factors(factors, strength);
1380 clamp_factors(factors, 0.0f, 1.0f);
1381
1382 tls.average_positions.resize(positions.size());
1383 const MutableSpan<float3> average_positions = tls.average_positions;
1385 subdiv_ccg, subdiv_ccg.positions.as_span(), grids, average_positions);
1386
1387 tls.laplacian_disp.resize(positions.size());
1388 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
1389 tls.translations.resize(positions.size());
1390 const MutableSpan<float3> translations = tls.translations;
1392 orig_data.positions,
1393 average_positions,
1394 alpha,
1395 laplacian_disp,
1396 translations);
1397 scale_translations(translations, factors);
1398
1399 scatter_data_grids(subdiv_ccg, laplacian_disp.as_span(), grids, all_laplacian_disp);
1400
1402 clip_and_lock_translations(sd, ss, positions, translations);
1403 apply_translations(translations, grids, subdiv_ccg);
1404 });
1405 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1406 LocalData &tls = all_tls.local();
1407 const Span<int> grids = nodes[i].grids();
1408 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1409
1410 tls.factors.resize(positions.size());
1411 const MutableSpan<float> factors = tls.factors;
1412 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1414 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1415 scale_factors(factors, strength);
1416 clamp_factors(factors, 0.0f, 1.0f);
1417
1418 const MutableSpan<float3> laplacian_disp = gather_data_grids(
1419 subdiv_ccg, all_laplacian_disp.as_span(), grids, tls.laplacian_disp);
1420
1421 tls.average_positions.resize(positions.size());
1422 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
1424 subdiv_ccg, all_laplacian_disp.as_span(), grids, average_laplacian_disps);
1425
1426 tls.translations.resize(positions.size());
1427 const MutableSpan<float3> translations = tls.translations;
1429 laplacian_disp, average_laplacian_disps, beta, translations);
1430 scale_translations(translations, factors);
1431
1433 clip_and_lock_translations(sd, ss, positions, translations);
1434 apply_translations(translations, grids, subdiv_ccg);
1435 });
1436 break;
1437 }
1439 BMesh &bm = *ss.bm;
1442 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1443 LocalData &tls = all_tls.local();
1445 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1446 Array<float3> orig_positions(verts.size());
1447 Array<float3> orig_normals(verts.size());
1448 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
1449
1450 tls.factors.resize(verts.size());
1451 const MutableSpan<float> factors = tls.factors;
1454 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1455 scale_factors(factors, strength);
1456 clamp_factors(factors, 0.0f, 1.0f);
1457
1458 tls.average_positions.resize(verts.size());
1459 const MutableSpan<float3> average_positions = tls.average_positions;
1461
1462 tls.laplacian_disp.resize(verts.size());
1463 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
1464 tls.translations.resize(verts.size());
1465 const MutableSpan<float3> translations = tls.translations;
1467 positions, orig_positions, average_positions, alpha, laplacian_disp, translations);
1468 scale_translations(translations, factors);
1469
1470 scatter_data_bmesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
1471
1473 clip_and_lock_translations(sd, ss, positions, translations);
1474 apply_translations(translations, verts);
1475 });
1476 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1477 LocalData &tls = all_tls.local();
1479 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1480
1481 tls.factors.resize(verts.size());
1482 const MutableSpan<float> factors = tls.factors;
1485 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1486 scale_factors(factors, strength);
1487 clamp_factors(factors, 0.0f, 1.0f);
1488
1489 const MutableSpan<float3> laplacian_disp = gather_data_bmesh(
1490 all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
1491
1492 tls.average_positions.resize(verts.size());
1493 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
1494 smooth::average_data_bmesh(all_laplacian_disp.as_span(), verts, average_laplacian_disps);
1495
1496 tls.translations.resize(verts.size());
1497 const MutableSpan<float3> translations = tls.translations;
1499 laplacian_disp, average_laplacian_disps, beta, translations);
1500 scale_translations(translations, factors);
1501
1503 clip_and_lock_translations(sd, ss, positions, translations);
1504 apply_translations(translations, verts);
1505 });
1506 break;
1507 }
1508 }
1509}
1510
1512 const Span<float3> positions,
1513 const Span<float3> smooth_positions,
1514 const Span<float> sharpen_factors,
1515 const Span<float3> detail_directions,
1516 const MutableSpan<float3> translations)
1517{
1518 for (const int i : positions.index_range()) {
1519 float3 disp_avg = smooth_positions[i] - positions[i];
1520 disp_avg = disp_avg * filter_cache.sharpen_smooth_ratio * pow2f(sharpen_factors[i]);
1521 translations[i] += disp_avg;
1522 /* Intensify details. */
1523 if (filter_cache.sharpen_intensify_detail_strength > 0.0f) {
1524 float3 detail_strength = detail_directions[i];
1525 translations[i] += detail_strength * -filter_cache.sharpen_intensify_detail_strength *
1526 sharpen_factors[i];
1527 }
1528 }
1529}
1530
1531static void calc_sharpen_filter(const Depsgraph &depsgraph,
1532 const Sculpt &sd,
1533 const float strength,
1534 Object &object,
1535 const IndexMask &node_mask)
1536{
1537 struct LocalData {
1538 Vector<float> factors;
1539 Vector<float3> positions;
1540 Vector<int> neighbor_offsets;
1541 Vector<int> neighbor_data;
1542 Vector<float3> smooth_positions;
1543 Vector<float> sharpen_factors;
1544 Vector<float3> detail_directions;
1545 Vector<float3> translations;
1546 };
1547 SculptSession &ss = *object.sculpt;
1548 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1549 switch (pbvh.type()) {
1550 case bke::pbvh::Type::Mesh: {
1551 Mesh &mesh = *static_cast<Mesh *>(object.data);
1552 const MeshAttributeData attribute_data(mesh);
1553 const PositionDeformData position_data(depsgraph, object);
1554
1555 const OffsetIndices faces = mesh.faces();
1556 const Span<int> corner_verts = mesh.corner_verts();
1557 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1560 node_mask.foreach_index(GrainSize(1), [&](const int node_index) {
1561 LocalData &tls = all_tls.local();
1562 const Span<int> verts = nodes[node_index].verts();
1563 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
1564
1565 tls.factors.resize(verts.size());
1566 const MutableSpan<float> factors = tls.factors;
1568 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1570 object,
1571 ss.filter_cache->automasking.get(),
1572 nodes[node_index],
1573 verts,
1574 factors);
1575 scale_factors(factors, strength);
1576
1577 /* This filter can't work at full strength as it needs multiple iterations to reach a
1578 * stable state. */
1579 clamp_factors(factors, 0.0f, 0.5f);
1580
1581 const GroupedSpan<int> neighbors = calc_vert_neighbors(faces,
1582 corner_verts,
1583 vert_to_face_map,
1584 attribute_data.hide_poly,
1585 verts,
1586 tls.neighbor_offsets,
1587 tls.neighbor_data);
1588
1589 tls.smooth_positions.resize(verts.size());
1590 const MutableSpan<float3> smooth_positions = tls.smooth_positions;
1592 position_data.eval, verts, neighbors, smooth_positions);
1593
1594 const Span<float> sharpen_factors = gather_data_mesh(
1595 ss.filter_cache->sharpen_factor.as_span(), verts, tls.sharpen_factors);
1596
1597 tls.translations.resize(verts.size());
1598 const MutableSpan<float3> translations = tls.translations;
1599 for (const int i : verts.index_range()) {
1600 const int vert = verts[i];
1601 const float3 &position = position_data.eval[vert];
1602
1603 float3 disp_sharpen(0.0f);
1604 for (const int neighbor : neighbors[i]) {
1605 float3 disp_n = position_data.eval[neighbor] - position;
1606 disp_n *= ss.filter_cache->sharpen_factor[neighbor];
1607 disp_sharpen += disp_n;
1608 }
1609
1610 disp_sharpen *= (1.0f - sharpen_factors[i]);
1611 translations[i] = disp_sharpen;
1612 }
1613
1614 const Span<float3> detail_directions = gather_data_mesh(
1615 ss.filter_cache->detail_directions.as_span(), verts, tls.detail_directions);
1616
1618 positions,
1619 smooth_positions,
1620 sharpen_factors,
1621 detail_directions,
1622 translations);
1623 scale_translations(translations, factors);
1624
1626 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1627 position_data.deform(translations, verts);
1628 });
1629 break;
1630 }
1632 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1633 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1634 MutableSpan<float3> vert_positions = subdiv_ccg.positions;
1635
1638 node_mask.foreach_index(GrainSize(1), [&](const int node_index) {
1639 LocalData &tls = all_tls.local();
1640 const Span<int> grids = nodes[node_index].grids();
1641 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1642
1643 tls.factors.resize(positions.size());
1644 const MutableSpan<float> factors = tls.factors;
1645 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1647 object,
1648 ss.filter_cache->automasking.get(),
1649 nodes[node_index],
1650 grids,
1651 factors);
1652 scale_factors(factors, strength);
1653
1654 /* This filter can't work at full strength as it needs multiple iterations to reach a
1655 * stable state. */
1656 clamp_factors(factors, 0.0f, 0.5f);
1657
1658 tls.smooth_positions.resize(positions.size());
1659 const MutableSpan<float3> smooth_positions = tls.smooth_positions;
1661 subdiv_ccg, subdiv_ccg.positions.as_span(), grids, smooth_positions);
1662
1663 const Span<float> sharpen_factors = gather_data_grids(
1664 subdiv_ccg, ss.filter_cache->sharpen_factor.as_span(), grids, tls.sharpen_factors);
1665
1666 tls.translations.resize(positions.size());
1667 const MutableSpan<float3> translations = tls.translations;
1668 for (const int i : grids.index_range()) {
1669 const int node_verts_start = i * key.grid_area;
1670 const int grid = grids[i];
1671 for (const short y : IndexRange(key.grid_size)) {
1672 for (const short x : IndexRange(key.grid_size)) {
1673 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
1674 const int node_vert = node_verts_start + offset;
1675
1676 const float3 &position = positions[node_vert];
1677
1678 float3 disp_sharpen(0.0f);
1679 SubdivCCGNeighbors neighbors;
1681 subdiv_ccg, SubdivCCGCoord{grid, x, y}, false, neighbors);
1682 for (const SubdivCCGCoord neighbor : neighbors.coords) {
1683 float3 disp_n = vert_positions[neighbor.to_index(key)] - position;
1684 disp_n *= ss.filter_cache->sharpen_factor[neighbor.to_index(key)];
1685 disp_sharpen += disp_n;
1686 }
1687
1688 disp_sharpen *= (1.0f - sharpen_factors[node_vert]);
1689 translations[node_vert] = disp_sharpen;
1690 }
1691 }
1692 }
1693
1694 const Span<float3> detail_directions = gather_data_grids(
1695 subdiv_ccg,
1696 ss.filter_cache->detail_directions.as_span(),
1697 grids,
1698 tls.detail_directions);
1699
1701 positions,
1702 smooth_positions,
1703 sharpen_factors,
1704 detail_directions,
1705 translations);
1706 scale_translations(translations, factors);
1707
1709 clip_and_lock_translations(sd, ss, positions, translations);
1710 apply_translations(translations, grids, subdiv_ccg);
1711 });
1712 break;
1713 }
1715 BMesh &bm = *ss.bm;
1719 node_mask.foreach_index(GrainSize(1), [&](const int node_index) {
1720 LocalData &tls = all_tls.local();
1722 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1723
1724 tls.factors.resize(verts.size());
1725 const MutableSpan<float> factors = tls.factors;
1728 object,
1729 ss.filter_cache->automasking.get(),
1730 nodes[node_index],
1731 verts,
1732 factors);
1733 scale_factors(factors, strength);
1734
1735 /* This filter can't work at full strength as it needs multiple iterations to reach a
1736 * stable state. */
1737 clamp_factors(factors, 0.0f, 0.5f);
1738
1739 tls.smooth_positions.resize(verts.size());
1740 const MutableSpan<float3> smooth_positions = tls.smooth_positions;
1742
1743 const Span<float> sharpen_factors = gather_data_bmesh(
1744 ss.filter_cache->sharpen_factor.as_span(), verts, tls.sharpen_factors);
1745
1746 tls.translations.resize(verts.size());
1747 const MutableSpan<float3> translations = tls.translations;
1748
1749 BMeshNeighborVerts neighbors;
1750
1751 int i = 0;
1752 for (BMVert *vert : verts) {
1753 const float3 position = vert->co;
1754
1755 float3 disp_sharpen(0.0f);
1756 for (const BMVert *neighbor : vert_neighbors_get_bmesh(*vert, neighbors)) {
1757 float3 disp_n = float3(neighbor->co) - position;
1758 disp_n *= ss.filter_cache->sharpen_factor[BM_elem_index_get(neighbor)];
1759 disp_sharpen += disp_n;
1760 }
1761
1762 disp_sharpen *= (1.0f - sharpen_factors[i]);
1763 translations[i] = disp_sharpen;
1764 i++;
1765 }
1766
1767 const Span<float3> detail_directions = gather_data_bmesh(
1768 ss.filter_cache->detail_directions.as_span(), verts, tls.detail_directions);
1769
1771 positions,
1772 smooth_positions,
1773 sharpen_factors,
1774 detail_directions,
1775 translations);
1776 scale_translations(translations, factors);
1777
1779 clip_and_lock_translations(sd, ss, positions, translations);
1780 apply_translations(translations, verts);
1781 });
1782 break;
1783 }
1784 }
1785}
1786
1787static void calc_enhance_details_filter(const Depsgraph &depsgraph,
1788 const Sculpt &sd,
1789 const float strength,
1790 Object &object,
1791 const IndexMask &node_mask)
1792{
1793 const float final_strength = -std::abs(strength);
1794 struct LocalData {
1795 Vector<float> factors;
1796 Vector<float3> positions;
1797 Vector<float3> translations;
1798 };
1799 SculptSession &ss = *object.sculpt;
1800 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1801 switch (pbvh.type()) {
1802 case bke::pbvh::Type::Mesh: {
1803 Mesh &mesh = *static_cast<Mesh *>(object.data);
1804 const MeshAttributeData attribute_data(mesh);
1805 const PositionDeformData position_data(depsgraph, object);
1808 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1809 LocalData &tls = all_tls.local();
1810 const Span<int> verts = nodes[i].verts();
1811
1812 tls.factors.resize(verts.size());
1813 const MutableSpan<float> factors = tls.factors;
1815 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1817 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1818 scale_factors(factors, final_strength);
1819
1820 const MutableSpan translations = gather_data_mesh(
1821 ss.filter_cache->detail_directions.as_span(), verts, tls.translations);
1822 scale_translations(translations, factors);
1823
1825 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1826 position_data.deform(translations, verts);
1827 });
1828 break;
1829 }
1831 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1834 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1835 LocalData &tls = all_tls.local();
1836 const Span<int> grids = nodes[i].grids();
1837 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1838
1839 tls.factors.resize(positions.size());
1840 const MutableSpan<float> factors = tls.factors;
1841 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1843 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1844 scale_factors(factors, final_strength);
1845
1846 const MutableSpan translations = gather_data_grids(
1847 subdiv_ccg, ss.filter_cache->detail_directions.as_span(), grids, tls.translations);
1848 scale_translations(translations, factors);
1849
1851 clip_and_lock_translations(sd, ss, positions, translations);
1852 apply_translations(translations, grids, subdiv_ccg);
1853 });
1854 break;
1855 }
1857 BMesh &bm = *ss.bm;
1860 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1861 LocalData &tls = all_tls.local();
1863 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1864
1865 tls.factors.resize(verts.size());
1866 const MutableSpan<float> factors = tls.factors;
1869 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1870 scale_factors(factors, final_strength);
1871
1872 const MutableSpan<float3> translations = gather_data_bmesh(
1873 ss.filter_cache->detail_directions.as_span(), verts, tls.translations);
1874 scale_translations(translations, factors);
1875
1877 clip_and_lock_translations(sd, ss, positions, translations);
1878 apply_translations(translations, verts);
1879 });
1880 break;
1881 }
1882 }
1883}
1884
1885static void calc_erase_displacement_filter(const Depsgraph &depsgraph,
1886 const Sculpt &sd,
1887 const float strength,
1888 Object &object,
1889 const IndexMask &node_mask)
1890{
1891 struct LocalData {
1892 Vector<float> factors;
1893 Vector<float3> positions;
1894 Vector<float3> new_positions;
1895 Vector<float3> translations;
1896 };
1897 SculptSession &ss = *object.sculpt;
1898 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1899 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1902 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1903 LocalData &tls = all_tls.local();
1904 const Span<int> grids = nodes[i].grids();
1905 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1906
1907 tls.factors.resize(positions.size());
1908 const MutableSpan<float> factors = tls.factors;
1909 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1911 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1912 scale_factors(factors, strength);
1913 clamp_factors(factors, -1.0f, 1.0f);
1914
1915 const MutableSpan<float3> new_positions = gather_data_grids(
1916 subdiv_ccg, ss.filter_cache->limit_surface_co.as_span(), grids, tls.new_positions);
1917 tls.translations.resize(positions.size());
1918 const MutableSpan<float3> translations = tls.translations;
1919 translations_from_new_positions(new_positions, positions, translations);
1920 scale_translations(translations, factors);
1921
1923 clip_and_lock_translations(sd, ss, positions, translations);
1924 apply_translations(translations, grids, subdiv_ccg);
1925 });
1926}
1927
1929 const float shape_preservation,
1930 const float current_vertex_displacement)
1931{
1932 SculptSession &ss = *object.sculpt;
1933 const int totvert = SCULPT_vertex_count_get(object);
1934 filter::Cache *filter_cache = ss.filter_cache;
1935
1936 filter_cache->surface_smooth_laplacian_disp.reinitialize(totvert);
1937 filter_cache->surface_smooth_laplacian_disp.fill(float3(0.0f));
1938 filter_cache->surface_smooth_shape_preservation = shape_preservation;
1939 filter_cache->surface_smooth_current_vertex = current_vertex_displacement;
1940}
1941
1942static void calc_limit_surface_positions(const Object &object, MutableSpan<float3> limit_positions)
1943{
1944 const SculptSession &ss = *object.sculpt;
1945 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1946 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1947
1948 threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 512, [&](const IndexRange range) {
1949 for (const int grid : range) {
1950 MutableSpan grid_dst = limit_positions.slice(bke::ccg::grid_range(key, grid));
1951 BKE_subdiv_ccg_eval_limit_positions(subdiv_ccg, key, grid, grid_dst);
1952 }
1953 });
1954}
1955
1956static void mesh_filter_sharpen_init(const Depsgraph &depsgraph,
1957 const Object &object,
1958 const float smooth_ratio,
1959 const float intensify_detail_strength,
1960 const int curvature_smooth_iterations,
1961 filter::Cache &filter_cache)
1962{
1963 const SculptSession &ss = *object.sculpt;
1964 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1965 const IndexMask &node_mask = filter_cache.node_mask;
1966 const int totvert = SCULPT_vertex_count_get(object);
1967
1968 filter_cache.sharpen_smooth_ratio = smooth_ratio;
1969 filter_cache.sharpen_intensify_detail_strength = intensify_detail_strength;
1970 filter_cache.sharpen_curvature_smooth_iterations = curvature_smooth_iterations;
1971 filter_cache.sharpen_factor.reinitialize(totvert);
1972 filter_cache.detail_directions.reinitialize(totvert);
1973 MutableSpan<float3> detail_directions = filter_cache.detail_directions;
1974 MutableSpan<float> sharpen_factors = filter_cache.sharpen_factor;
1975
1976 calc_smooth_translations(depsgraph, object, node_mask, filter_cache.detail_directions);
1977
1978 for (int i = 0; i < totvert; i++) {
1979 sharpen_factors[i] = math::length(detail_directions[i]);
1980 }
1981
1982 float max_factor = 0.0f;
1983 for (int i = 0; i < totvert; i++) {
1984 max_factor = std::max(sharpen_factors[i], max_factor);
1985 }
1986
1987 max_factor = math::safe_rcp(max_factor);
1988 for (int i = 0; i < totvert; i++) {
1989 sharpen_factors[i] *= max_factor;
1990 sharpen_factors[i] = 1.0f - pow2f(1.0f - sharpen_factors[i]);
1991 }
1992
1993 /* Smooth the calculated factors and directions to remove high frequency detail. */
1994 struct LocalData {
1995 Vector<int> neighbor_offsets;
1996 Vector<int> neighbor_data;
1997 Vector<float3> smooth_directions;
1998 Vector<float> smooth_factors;
1999 };
2001 for ([[maybe_unused]] const int _ : IndexRange(filter_cache.sharpen_curvature_smooth_iterations))
2002 {
2003 switch (pbvh.type()) {
2004 case bke::pbvh::Type::Mesh: {
2005 Mesh &mesh = *static_cast<Mesh *>(object.data);
2006 const OffsetIndices faces = mesh.faces();
2007 const Span<int> corner_verts = mesh.corner_verts();
2008 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
2010 const MeshAttributeData attribute_data(mesh);
2011 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2012 LocalData &tls = all_tls.local();
2013 const Span<int> verts = nodes[i].verts();
2014
2015 const GroupedSpan<int> neighbors = calc_vert_neighbors(faces,
2016 corner_verts,
2017 vert_to_face_map,
2018 attribute_data.hide_poly,
2019 verts,
2020 tls.neighbor_offsets,
2021 tls.neighbor_data);
2022
2023 tls.smooth_directions.resize(verts.size());
2025 verts,
2026 neighbors,
2027 tls.smooth_directions.as_mutable_span());
2028 scatter_data_mesh(tls.smooth_directions.as_span(), verts, detail_directions);
2029
2030 tls.smooth_factors.resize(verts.size());
2032 sharpen_factors.as_span(), verts, neighbors, tls.smooth_factors.as_mutable_span());
2033 scatter_data_mesh(tls.smooth_factors.as_span(), verts, sharpen_factors);
2034 });
2035 break;
2036 }
2038 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
2039 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
2041 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2042 LocalData &tls = all_tls.local();
2043 const Span<int> grids = nodes[i].grids();
2044 const int grid_verts_num = grids.size() * key.grid_area;
2045
2046 tls.smooth_directions.resize(grid_verts_num);
2047 smooth::average_data_grids(subdiv_ccg,
2048 detail_directions.as_span(),
2049 grids,
2050 tls.smooth_directions.as_mutable_span());
2052 subdiv_ccg, tls.smooth_directions.as_span(), grids, detail_directions);
2053
2054 tls.smooth_factors.resize(grid_verts_num);
2056 subdiv_ccg, sharpen_factors.as_span(), grids, tls.smooth_factors.as_mutable_span());
2057 scatter_data_grids(subdiv_ccg, tls.smooth_factors.as_span(), grids, sharpen_factors);
2058 });
2059 break;
2060 }
2063 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2064 LocalData &tls = all_tls.local();
2066 &const_cast<bke::pbvh::BMeshNode &>(nodes[i]));
2067
2068 tls.smooth_directions.resize(verts.size());
2070 detail_directions.as_span(), verts, tls.smooth_directions.as_mutable_span());
2071 scatter_data_bmesh(tls.smooth_directions.as_span(), verts, detail_directions);
2072
2073 tls.smooth_factors.resize(verts.size());
2075 sharpen_factors.as_span(), verts, tls.smooth_factors.as_mutable_span());
2076 scatter_data_bmesh(tls.smooth_factors.as_span(), verts, sharpen_factors);
2077 });
2078 break;
2079 }
2080 }
2081}
2082
2083enum {
2086};
2087
2089{
2090 static const EnumPropertyItem modal_items[] = {
2091 {FILTER_MESH_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
2092 {FILTER_MESH_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
2093 {0, nullptr, 0, nullptr, nullptr},
2094 };
2095
2096 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Mesh Filter Modal Map");
2097
2098 /* This function is called for each space-type, only needs to add map once. */
2099 if (keymap && keymap->modal_items) {
2100 return nullptr;
2101 }
2102
2103 keymap = WM_modalkeymap_ensure(keyconf, "Mesh Filter Modal Map", modal_items);
2104
2105 WM_modalkeymap_assign(keymap, "SCULPT_OT_mesh_filter");
2106
2107 return keymap;
2108}
2109
2111{
2112 WorkspaceStatus status(C);
2113 status.item(IFACE_("Confirm"), ICON_EVENT_RETURN);
2114 status.item(IFACE_("Cancel"), ICON_EVENT_ESC, ICON_MOUSE_RMB);
2115}
2116
2117static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op, bool is_replay = false)
2118{
2119 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
2121 SculptSession &ss = *ob.sculpt;
2122 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
2123 const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
2124 const float strength = RNA_float_get(op->ptr, "strength");
2125
2127
2128 const IndexMask &node_mask = ss.filter_cache->node_mask;
2129 if (auto_mask::is_enabled(sd, ob, nullptr) && ss.filter_cache->automasking &&
2131 {
2132 ss.filter_cache->automasking->calc_cavity_factor(depsgraph, ob, node_mask);
2133 }
2134 switch (filter_type) {
2137 sd,
2138 strength,
2139 ob,
2140 node_mask,
2141 is_replay && ss.filter_cache->iteration_count == 0);
2142 break;
2144 calc_scale_filter(depsgraph, sd, strength, ob, node_mask);
2145 break;
2147 calc_inflate_filter(depsgraph, sd, strength, ob, node_mask);
2148 break;
2150 calc_sphere_filter(depsgraph, sd, strength, ob, node_mask);
2151 break;
2153 calc_random_filter(depsgraph, sd, strength, ob, node_mask);
2154 break;
2156 calc_relax_filter(depsgraph, sd, strength, ob, node_mask);
2157 break;
2159 calc_relax_face_sets_filter(depsgraph, sd, strength, ob, node_mask);
2160 break;
2162 calc_surface_smooth_filter(depsgraph, sd, strength, ob, node_mask);
2163 break;
2165 calc_sharpen_filter(depsgraph, sd, strength, ob, node_mask);
2166 break;
2168 calc_enhance_details_filter(depsgraph, sd, strength, ob, node_mask);
2169 break;
2171 calc_erase_displacement_filter(depsgraph, sd, strength, ob, node_mask);
2172 break;
2173 }
2174
2176 pbvh.tag_positions_changed(node_mask);
2177 pbvh.update_bounds(depsgraph, ob);
2178
2180
2182}
2183
2185 SculptSession &ss,
2186 float2 prev_press_mouse,
2187 float2 mouse)
2188{
2189 const float len = prev_press_mouse[0] - mouse[0];
2190
2191 float filter_strength = ss.filter_cache->start_filter_strength * -len * 0.001f * UI_SCALE_FAC;
2192 RNA_float_set(op->ptr, "strength", filter_strength);
2193}
2195{
2196 /* Event history is only stored for smooth and relax filters. */
2197 if (!RNA_collection_length(op->ptr, "event_history")) {
2199 return;
2200 }
2201
2203 SculptSession &ss = *ob.sculpt;
2204 float2 start_mouse;
2205 bool first = true;
2206 float initial_strength = ss.filter_cache->start_filter_strength;
2207
2208 RNA_BEGIN (op->ptr, item, "event_history") {
2209 float2 mouse;
2210 RNA_float_get_array(&item, "mouse_event", mouse);
2211
2212 if (first) {
2213 first = false;
2214 start_mouse = mouse;
2215 continue;
2216 }
2217
2218 sculpt_mesh_update_strength(op, ss, start_mouse, mouse);
2219 sculpt_mesh_filter_apply(C, op, true);
2220 }
2221 RNA_END;
2222
2223 RNA_float_set(op->ptr, "strength", initial_strength);
2224}
2225
2227{
2229 SculptSession &ss = *ob.sculpt;
2230
2231 MEM_delete(ss.filter_cache);
2232 ss.filter_cache = nullptr;
2234}
2235
2237 wmOperator *op,
2238 const MeshFilterType filter_type)
2239{
2240 float initial_strength = ss.filter_cache->start_filter_strength;
2241 /* Don't update strength property if we're storing an event history. */
2242 if (sculpt_mesh_filter_is_continuous(filter_type)) {
2243 RNA_float_set(op->ptr, "strength", initial_strength);
2244 }
2245
2246 return OPERATOR_FINISHED;
2247}
2248
2250{
2251 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
2253 SculptSession *ss = ob.sculpt;
2255
2256 if (!ss || !pbvh) {
2257 return;
2258 }
2259
2262 pbvh->update_bounds(depsgraph, ob);
2263}
2264
2266{
2269 SculptSession &ss = *ob.sculpt;
2270 const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
2271
2274
2275 if (event->type == EVT_MODAL_MAP) {
2277 switch (event->val) {
2280 undo::push_end_ex(ob, true);
2282 break;
2283
2285 ret = sculpt_mesh_filter_confirm(ss, op, filter_type);
2286 undo::push_end_ex(ob, false);
2287 break;
2288 }
2289
2291 ED_workspace_status_text(C, nullptr); /* Clear status bar */
2293
2294 return ret;
2295 }
2296
2297 if (event->type != MOUSEMOVE) {
2299 }
2300
2301 /* NOTE: some filter types are continuous, for these we store an
2302 * event history in RNA for continuous.
2303 * This way the user can tweak the last operator properties
2304 * or repeat the op and get expected results. */
2305 if (sculpt_mesh_filter_is_continuous(filter_type)) {
2306 if (RNA_collection_length(op->ptr, "event_history") == 0) {
2307 /* First entry is the start mouse position, event->prev_press_xy. */
2308 PointerRNA startptr;
2309 RNA_collection_add(op->ptr, "event_history", &startptr);
2310
2311 float2 mouse_start(float(event->prev_press_xy[0]), float(event->prev_press_xy[1]));
2312 RNA_float_set_array(&startptr, "mouse_event", mouse_start);
2313 }
2314
2315 PointerRNA itemptr;
2316 RNA_collection_add(op->ptr, "event_history", &itemptr);
2317
2318 float2 mouse(float(event->xy[0]), float(event->xy[1]));
2319 RNA_float_set_array(&itemptr, "mouse_event", mouse);
2320 RNA_float_set(&itemptr, "pressure", WM_event_tablet_data(event, nullptr, nullptr));
2321 }
2322 else {
2324 }
2325
2326 float2 prev_mval(float(event->prev_press_xy[0]), float(event->prev_press_xy[1]));
2327 float2 mval(float(event->xy[0]), float(event->xy[1]));
2328
2329 sculpt_mesh_update_strength(op, ss, prev_mval, mval);
2330
2332
2334
2336}
2337
2338static void sculpt_filter_specific_init(const Depsgraph &depsgraph,
2339 const MeshFilterType filter_type,
2340 wmOperator *op,
2341 Object &object)
2342{
2343 SculptSession &ss = *object.sculpt;
2344 switch (filter_type) {
2347 RNA_float_get(op->ptr, "surface_smooth_shape_preservation"),
2348 RNA_float_get(op->ptr, "surface_smooth_current_vertex"));
2349 break;
2350 }
2353 object,
2354 RNA_float_get(op->ptr, "sharpen_smooth_ratio"),
2355 RNA_float_get(op->ptr, "sharpen_intensify_detail_strength"),
2356 RNA_int_get(op->ptr, "sharpen_curvature_smooth_iterations"),
2357 *ss.filter_cache);
2358 break;
2359 }
2361 ss.filter_cache->detail_directions.reinitialize(SCULPT_vertex_count_get(object));
2364 break;
2365 }
2367 ss.filter_cache->limit_surface_co.reinitialize(SCULPT_vertex_count_get(object));
2369 break;
2370 }
2371 default:
2372 break;
2373 }
2374}
2375
2376/* Returns OPERATOR_PASS_THROUGH on success. */
2378{
2379 const Scene &scene = *CTX_data_scene(C);
2382 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
2383
2384 const View3D *v3d = CTX_wm_view3d(C);
2385 const Base *base = CTX_data_active_base(C);
2386 if (!BKE_base_is_visible(v3d, base)) {
2387 return OPERATOR_CANCELLED;
2388 }
2389
2390 int mval[2];
2391 RNA_int_get_array(op->ptr, "start_mouse", mval);
2392
2393 const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
2394 const bool use_automasking = auto_mask::is_enabled(sd, ob, nullptr);
2395 const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type) || use_automasking;
2396
2398
2400 return OPERATOR_CANCELLED;
2401 }
2402
2403 SculptSession &ss = *ob.sculpt;
2404
2405 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
2406 if (filter_type == MeshFilterType::EraseDisplacement && pbvh.type() != bke::pbvh::Type::Grids) {
2407 return OPERATOR_CANCELLED;
2408 }
2409
2410 const eMeshFilterDeformAxis deform_axis = eMeshFilterDeformAxis(
2411 RNA_enum_get(op->ptr, "deform_axis"));
2412
2413 if (deform_axis == 0) {
2414 /* All axis are disabled, so the filter is not going to produce any deformation. */
2415 return OPERATOR_CANCELLED;
2416 }
2417
2418 float2 mval_fl{float(mval[0]), float(mval[1])};
2419 if (use_automasking) {
2420 /* Update the active face set manually as the paint cursor is not enabled when using the
2421 * Mesh Filter Tool. */
2423 cursor_geometry_info_update(C, &cgi, mval_fl, false);
2424 }
2425
2427 if (needs_topology_info) {
2429 }
2430
2431 undo::push_begin(scene, ob, op);
2432
2433 cache_init(C,
2434 ob,
2435 sd,
2437 mval_fl,
2438 RNA_float_get(op->ptr, "area_normal_radius"),
2439 RNA_float_get(op->ptr, "strength"));
2440
2441 filter::Cache *filter_cache = ss.filter_cache;
2442 filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
2443 if (auto_mask::is_enabled(sd, ob, nullptr)) {
2445 }
2446
2447 sculpt_filter_specific_init(*depsgraph, filter_type, op, ob);
2448
2449 ss.filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
2450 ss.filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
2451 ss.filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
2452
2453 ss.filter_cache->orientation = FilterOrientation(RNA_enum_get(op->ptr, "orientation"));
2454
2455 return OPERATOR_PASS_THROUGH;
2456}
2457
2459 wmOperator *op,
2460 const wmEvent *event)
2461{
2462 RNA_int_set_array(op->ptr, "start_mouse", event->mval);
2464
2465 if (ret == OPERATOR_PASS_THROUGH) {
2468 }
2469
2470 return ret;
2471}
2472
2474{
2476
2477 if (ret == OPERATOR_PASS_THROUGH) {
2478 int iterations = RNA_int_get(op->ptr, "iteration_count");
2479
2480 for (int i = 0; i < iterations; i++) {
2482 }
2483
2486
2487 return OPERATOR_FINISHED;
2488 }
2489
2490 return ret;
2491}
2492
2494{
2496 ot->srna, "start_mouse", 2, nullptr, 0, 1 << 14, "Starting Mouse", "", 0, 1 << 14);
2497
2498 RNA_def_float(ot->srna,
2499 "area_normal_radius",
2500 0.25,
2501 0.001,
2502 5.0,
2503 "Normal Radius",
2504 "Radius used for calculating area normal on initial click,\nin percentage "
2505 "of brush radius",
2506 0.01,
2507 1.0);
2508 PropertyRNA *prop = RNA_def_float(
2509 ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
2511 RNA_def_int(ot->srna,
2512 "iteration_count",
2513 1,
2514 1,
2515 10000,
2516 "Repeat",
2517 "How many times to repeat the filter",
2518 1,
2519 100);
2520
2521 /* Smooth filter requires entire event history. */
2522 prop = RNA_def_collection_runtime(ot->srna, "event_history", &RNA_OperatorStrokeElement, "", "");
2524}
2525
2526static void sculpt_mesh_ui_exec(bContext * /*C*/, wmOperator *op)
2527{
2528 uiLayout *layout = op->layout;
2529
2530 layout->prop(op->ptr, "strength", UI_ITEM_NONE, std::nullopt, ICON_NONE);
2531 layout->prop(op->ptr, "iteration_count", UI_ITEM_NONE, std::nullopt, ICON_NONE);
2532 layout->prop(op->ptr, "orientation", UI_ITEM_NONE, std::nullopt, ICON_NONE);
2533 layout = &layout->row(true);
2534 layout->prop(op->ptr, "deform_axis", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
2535}
2536
2538{
2539 ot->name = "Filter Mesh";
2540 ot->idname = "SCULPT_OT_mesh_filter";
2541 ot->description = "Applies a filter to modify the current mesh";
2542
2543 ot->invoke = sculpt_mesh_filter_invoke;
2545 ot->poll = SCULPT_mode_poll;
2547 ot->ui = sculpt_mesh_ui_exec;
2548
2549 /* Doesn't seem to actually be called?
2550 * Check `sculpt_mesh_filter_modal` to see where it's really called. */
2551 ot->cancel = sculpt_mesh_filter_cancel;
2552
2555
2557
2558 ot->prop = RNA_def_enum(ot->srna,
2559 "type",
2562 "Filter Type",
2563 "Operation that is going to be applied to the mesh");
2565 RNA_def_enum_flag(ot->srna,
2566 "deform_axis",
2569 "Deform Axis",
2570 "Apply the deformation in the selected axis");
2571 RNA_def_enum(ot->srna,
2572 "orientation",
2575 "Orientation",
2576 "Orientation of the axis to limit the filter displacement");
2577
2578 /* Surface Smooth Mesh Filter properties. */
2579 RNA_def_float(ot->srna,
2580 "surface_smooth_shape_preservation",
2581 0.5f,
2582 0.0f,
2583 1.0f,
2584 "Shape Preservation",
2585 "How much of the original shape is preserved when smoothing",
2586 0.0f,
2587 1.0f);
2588 RNA_def_float(ot->srna,
2589 "surface_smooth_current_vertex",
2590 0.5f,
2591 0.0f,
2592 1.0f,
2593 "Per Vertex Displacement",
2594 "How much the position of each individual vertex influences the final result",
2595 0.0f,
2596 1.0f);
2597 RNA_def_float(ot->srna,
2598 "sharpen_smooth_ratio",
2599 0.35f,
2600 0.0f,
2601 1.0f,
2602 "Smooth Ratio",
2603 "How much smoothing is applied to polished surfaces",
2604 0.0f,
2605 1.0f);
2606
2607 RNA_def_float(ot->srna,
2608 "sharpen_intensify_detail_strength",
2609 0.0f,
2610 0.0f,
2611 10.0f,
2612 "Intensify Details",
2613 "How much creases and valleys are intensified",
2614 0.0f,
2615 1.0f);
2616
2617 RNA_def_int(ot->srna,
2618 "sharpen_curvature_smooth_iterations",
2619 0,
2620 0,
2621 10,
2622 "Curvature Smooth Iterations",
2623 "How much smooth the resulting shape is, ignoring high frequency details",
2624 0,
2625 10);
2626}
2627
2628} // 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:77
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:344
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:641
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2657
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:1040
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:330
@ PROP_HIDDEN
Definition RNA_types.hh:324
#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:232
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:398
AttributeSet attributes
void item(std::string text, int icon1, int icon2=0)
Definition area.cc:979
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:559
Span< NodeT > nodes() const
void update_bounds(const Depsgraph &depsgraph, const Object &object)
Definition pbvh.cc:1202
void deform(MutableSpan< float3 > translations, Span< int > verts) const
Definition sculpt.cc:7445
void foreach_index(Fn &&fn) const
static float verts[][3]
ccl_device_inline float beta(const float x, const float y)
Definition math_base.h:651
static char faces[256]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2912
IndexMask search_nodes(const Tree &pbvh, IndexMaskMemory &memory, FunctionRef< bool(const Node &)> filter_fn)
Definition pbvh.cc:2579
void update_normals(const Depsgraph &depsgraph, Object &object_orig, Tree &pbvh)
Definition pbvh.cc:1073
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2435
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:6059
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[]
void cache_init(bContext *C, Object &ob, const Sculpt &sd, undo::Type undo_type, const float mval_fl[2], float area_normal_radius, float start_strength)
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)
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:1032
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:4921
void fill_factor_from_hide_and_mask(Span< bool > hide_vert, Span< float > mask, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6809
float object_space_radius_get(const ViewContext &vc, const Scene &scene, const Brush &brush, const float3 &location, const float scale_factor)
Definition sculpt.cc:115
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:2410
void scatter_data_bmesh(Span< T > node_data, const Set< BMVert *, 0 > &verts, MutableSpan< T > dst)
Definition sculpt.cc:6447
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6353
void gather_data_grids(const SubdivCCG &subdiv_ccg, Span< T > src, Span< int > grids, MutableSpan< T > node_data)
Definition sculpt.cc:6391
void vert_random_access_ensure(Object &object)
Definition sculpt.cc:142
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:7607
bool node_fully_masked_or_hidden(const bke::pbvh::Node &node)
Definition sculpt.cc:2399
Vector< BMVert *, 64 > BMeshNeighborVerts
void gather_data_bmesh(Span< T > src, const Set< BMVert *, 0 > &verts, MutableSpan< T > node_data)
Definition sculpt.cc:6407
void reset_translations_to_original(MutableSpan< float3 > translations, Span< float3 > positions, Span< float3 > orig_positions)
Definition sculpt.cc:7232
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:7487
bool report_if_shape_key_is_locked(const Object &ob, ReportList *reports)
Definition sculpt.cc:128
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7504
void translations_from_new_positions(Span< float3 > new_positions, Span< int > verts, Span< float3 > old_positions, MutableSpan< float3 > translations)
Definition sculpt.cc:7534
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7318
bool cursor_geometry_info_update(bContext *C, CursorGeometryInfo *out, const float2 &mval, const bool use_sampled_normal)
Definition sculpt.cc:4664
void flush_update_done(const bContext *C, Object &ob, const UpdateType update_type)
Definition sculpt.cc:5131
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6421
std::optional< float3 > calc_area_normal(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, const IndexMask &node_mask)
Definition sculpt.cc:1814
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, BMeshNeighborVerts &r_neighbors)
Definition sculpt.cc:388
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:7251
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:6381
OrigPositionData orig_position_data_get_grids(const Object &object, const bke::pbvh::GridsNode &node)
void flush_update_step(const bContext *C, const UpdateType update_type)
Definition sculpt.cc:5083
void scatter_data_grids(const SubdivCCG &subdiv_ccg, Span< T > node_data, Span< int > grids, MutableSpan< T > dst)
Definition sculpt.cc:6431
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:7746
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)
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:3660
int SCULPT_vertex_count_get(const Object &object)
Definition sculpt.cc:152
#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
float viewmat[4][4]
float viewinv[4][4]
struct ToolSettings * toolsettings
blender::float3 last_normal
Definition BKE_paint.hh:535
BMLog * bm_log
Definition BKE_paint.hh:412
blender::ed::sculpt_paint::filter::Cache * filter_cache
Definition BKE_paint.hh:438
SculptVertexInfo vertex_info
Definition BKE_paint.hh:482
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:415
blender::BitVector boundary
Definition BKE_paint.hh:354
int to_index(const CCGKey &key) const
SubdivCCGNeighborCoords coords
blender::Array< blender::float3 > positions
struct UnifiedPaintSettings unified_paint_settings
RegionView3D * rv3d
Definition ED_view3d.hh:80
const c_style_mat & ptr() const
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:754
short val
Definition WM_types.hh:756
int xy[2]
Definition WM_types.hh:758
int mval[2]
Definition WM_types.hh:760
int prev_press_xy[2]
Definition WM_types.hh:827
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:4226
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:929
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:956