Blender V4.3
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_matrix.hh"
22#include "BLI_math_vector.h"
24#include "BLI_task.h"
25
26#include "BLT_translation.hh"
27
28#include "BKE_brush.hh"
29#include "BKE_context.hh"
30#include "BKE_layer.hh"
31#include "BKE_mesh.hh"
32#include "BKE_modifier.hh"
33#include "BKE_object_types.hh"
34#include "BKE_paint.hh"
35#include "BKE_pbvh_api.hh"
36
37#include "WM_api.hh"
38#include "WM_types.hh"
39
40#include "ED_screen.hh"
41#include "ED_sculpt.hh"
42#include "ED_view3d.hh"
43
44#include "mesh_brush_common.hh"
45#include "paint_intern.hh"
46#include "sculpt_automask.hh"
47#include "sculpt_boundary.hh"
48#include "sculpt_cloth.hh"
49#include "sculpt_face_set.hh"
50#include "sculpt_intern.hh"
51#include "sculpt_smooth.hh"
52#include "sculpt_undo.hh"
53
54#include "RNA_access.hh"
55#include "RNA_define.hh"
56#include "RNA_prototypes.hh"
57
58#include "UI_interface.hh"
59#include "UI_resources.hh"
60
61#include "bmesh.hh"
62
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
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);
165 UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
166
167 float3 co;
168
169 if (vc.rv3d && SCULPT_stroke_get_location(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 if (BKE_brush_use_locked_size(scene, brush)) {
177 vc, co, float(BKE_brush_size_get(scene, brush) * area_normal_radius));
178 }
179 else {
180 radius = BKE_brush_unprojected_radius_get(scene, brush) * area_normal_radius;
181 }
182 }
183 else {
184 radius = paint_calc_object_space_radius(vc, co, float(ups->size) * area_normal_radius);
185 }
186
187 const float radius_sq = math::square(radius);
188
189 IndexMaskMemory memory;
190 const IndexMask node_mask = bke::pbvh::search_nodes(
191 pbvh, memory, [&](const bke::pbvh::Node &node) {
192 return !node_fully_masked_or_hidden(node) && node_in_sphere(node, co, radius_sq, true);
193 });
194
195 const std::optional<float3> area_normal = calc_area_normal(*depsgraph, *brush, ob, node_mask);
196 if (BKE_paint_brush_for_read(&sd.paint) && area_normal) {
197 ss.filter_cache->initial_normal = *area_normal;
199 }
200 else {
202 }
203
204 /* Update last stroke location */
205
206 mul_m4_v3(ob.object_to_world().ptr(), co);
207
210 ups->last_stroke_valid = true;
211 }
212 else {
213 /* Use last normal. */
215 }
216
217 /* Update view normal */
218 float3x3 mat;
219 float3 viewDir{0.0f, 0.0f, 1.0f};
220 if (vc.rv3d) {
221 invert_m4_m4(ob.runtime->world_to_object.ptr(), ob.object_to_world().ptr());
222 copy_m3_m4(mat.ptr(), vc.rv3d->viewinv);
223 mul_m3_v3(mat.ptr(), viewDir);
224 copy_m3_m4(mat.ptr(), ob.world_to_object().ptr());
225 mul_m3_v3(mat.ptr(), viewDir);
227 }
228}
229
230enum class MeshFilterType {
231 Smooth = 0,
232 Scale = 1,
233 Inflate = 2,
234 Sphere = 3,
235 Random = 4,
236 Relax = 5,
237 RelaxFaceSets = 6,
238 SurfaceSmooth = 7,
239 Sharpen = 8,
240 EnhanceDetails = 9,
242};
243
245 {int(MeshFilterType::Smooth), "SMOOTH", 0, "Smooth", "Smooth mesh"},
246 {int(MeshFilterType::Scale), "SCALE", 0, "Scale", "Scale mesh"},
247 {int(MeshFilterType::Inflate), "INFLATE", 0, "Inflate", "Inflate mesh"},
248 {int(MeshFilterType::Sphere), "SPHERE", 0, "Sphere", "Morph into sphere"},
249 {int(MeshFilterType::Random), "RANDOM", 0, "Random", "Randomize vertex positions"},
250 {int(MeshFilterType::Relax), "RELAX", 0, "Relax", "Relax mesh"},
252 "RELAX_FACE_SETS",
253 0,
254 "Relax Face Sets",
255 "Smooth the edges of all the Face Sets"},
257 "SURFACE_SMOOTH",
258 0,
259 "Surface Smooth",
260 "Smooth the surface of the mesh, preserving the volume"},
261 {int(MeshFilterType::Sharpen), "SHARPEN", 0, "Sharpen", "Sharpen the cavities of the mesh"},
263 "ENHANCE_DETAILS",
264 0,
265 "Enhance Details",
266 "Enhance the high frequency surface detail"},
268 "ERASE_DISPLACEMENT",
269 0,
270 "Erase Displacement",
271 "Deletes the displacement of the Multires Modifier"},
272 {0, nullptr, 0, nullptr, nullptr},
273};
274
280
282 {MESH_FILTER_DEFORM_X, "X", 0, "X", "Deform in the X axis"},
283 {MESH_FILTER_DEFORM_Y, "Y", 0, "Y", "Deform in the Y axis"},
284 {MESH_FILTER_DEFORM_Z, "Z", 0, "Z", "Deform in the Z axis"},
285 {0, nullptr, 0, nullptr, nullptr},
286};
287
290 "LOCAL",
291 0,
292 "Local",
293 "Use the local axis to limit the displacement"},
295 "WORLD",
296 0,
297 "World",
298 "Use the global axis to limit the displacement"},
300 "VIEW",
301 0,
302 "View",
303 "Use the view axis to limit the displacement"},
304 {0, nullptr, 0, nullptr, nullptr},
305};
306
317
326
328 const float min,
329 const float max)
330{
331 for (float &factor : factors) {
332 factor = std::clamp(factor, min, max);
333 }
334}
335
336static void calc_smooth_filter(const Depsgraph &depsgraph,
337 const Sculpt &sd,
338 const float strength,
339 Object &object,
340 const IndexMask &node_mask)
341{
342 struct LocalData {
343 Vector<float> factors;
344 Vector<float3> positions;
345 Vector<Vector<int>> vert_neighbors;
346 Vector<float3> new_positions;
347 Vector<float3> translations;
348 };
349 SculptSession &ss = *object.sculpt;
350 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
351 switch (pbvh.type()) {
353 Mesh &mesh = *static_cast<Mesh *>(object.data);
354 const MeshAttributeData attribute_data(mesh.attributes());
355 const PositionDeformData position_data(depsgraph, object);
356 const OffsetIndices faces = mesh.faces();
357 const Span<int> corner_verts = mesh.corner_verts();
358 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
361 node_mask.foreach_index(GrainSize(1), [&](const int i) {
362 LocalData &tls = all_tls.local();
363 const Span<int> verts = nodes[i].verts();
364 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
365 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
366
367 tls.factors.resize(verts.size());
368 const MutableSpan<float> factors = tls.factors;
370 attribute_data.hide_vert, attribute_data.mask, verts, factors);
372 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
373 scale_factors(factors, strength);
374 clamp_factors(factors, -1.0f, 1.0f);
375
376 tls.vert_neighbors.resize(verts.size());
377 MutableSpan<Vector<int>> neighbors = tls.vert_neighbors;
379 corner_verts,
380 vert_to_face_map,
382 attribute_data.hide_poly,
383 verts,
384 neighbors);
385 tls.new_positions.resize(verts.size());
386 const MutableSpan<float3> new_positions = tls.new_positions;
388 position_data.eval, verts, neighbors, new_positions);
389
390 tls.translations.resize(verts.size());
391 const MutableSpan<float3> translations = tls.translations;
392 translations_from_new_positions(new_positions, orig_data.positions, translations);
393 scale_translations(translations, factors);
394 reset_translations_to_original(translations, positions, orig_data.positions);
395
397 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
398 position_data.deform(translations, verts);
399 });
400 break;
401 }
403 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
404 const OffsetIndices faces = base_mesh.faces();
405 const Span<int> corner_verts = base_mesh.corner_verts();
406
407 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
410 node_mask.foreach_index(GrainSize(1), [&](const int i) {
411 LocalData &tls = all_tls.local();
412 const Span<int> grids = nodes[i].grids();
413 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
414 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
415
416 tls.factors.resize(positions.size());
417 const MutableSpan<float> factors = tls.factors;
418 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
420 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
421 scale_factors(factors, strength);
422 clamp_factors(factors, -1.0f, 1.0f);
423
424 tls.new_positions.resize(positions.size());
425 const MutableSpan<float3> new_positions = tls.new_positions;
427 faces, corner_verts, ss.vertex_info.boundary, subdiv_ccg, grids, new_positions);
428
429 tls.translations.resize(positions.size());
430 const MutableSpan<float3> translations = tls.translations;
431 translations_from_new_positions(new_positions, orig_data.positions, translations);
432 scale_translations(translations, factors);
433 reset_translations_to_original(translations, positions, orig_data.positions);
434
436 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
437 apply_translations(translations, grids, subdiv_ccg);
438 });
439 break;
440 }
442 BMesh &bm = *ss.bm;
445 node_mask.foreach_index(GrainSize(1), [&](const int i) {
446 LocalData &tls = all_tls.local();
448 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
449 Array<float3> orig_positions(verts.size());
450 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
451
452 tls.factors.resize(verts.size());
453 const MutableSpan<float> factors = tls.factors;
456 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
457 scale_factors(factors, strength);
458 clamp_factors(factors, -1.0f, 1.0f);
459
460 tls.new_positions.resize(verts.size());
461 const MutableSpan<float3> new_positions = tls.new_positions;
463
464 tls.translations.resize(verts.size());
465 const MutableSpan<float3> translations = tls.translations;
466 translations_from_new_positions(new_positions, orig_positions, translations);
467 scale_translations(translations, factors);
468 reset_translations_to_original(translations, positions, orig_positions);
469
471 clip_and_lock_translations(sd, ss, orig_positions, translations);
472 apply_translations(translations, verts);
473 });
474 break;
475 }
476 }
477}
478
479static void calc_inflate_filter(const Depsgraph &depsgraph,
480 const Sculpt &sd,
481 const float strength,
482 Object &object,
483 const IndexMask &node_mask)
484{
485 struct LocalData {
486 Vector<float> factors;
487 Vector<float3> positions;
488 Vector<float3> translations;
489 };
490 SculptSession &ss = *object.sculpt;
491 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
492 switch (pbvh.type()) {
494 Mesh &mesh = *static_cast<Mesh *>(object.data);
495 bke::AttributeAccessor attributes = mesh.attributes();
496 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
497 const VArraySpan mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
498 const PositionDeformData position_data(depsgraph, object);
501 node_mask.foreach_index(GrainSize(1), [&](const int i) {
502 LocalData &tls = all_tls.local();
503 const Span<int> verts = nodes[i].verts();
504 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
505 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
506
507 tls.factors.resize(verts.size());
508 const MutableSpan<float> factors = tls.factors;
509 fill_factor_from_hide_and_mask(hide_vert, mask, verts, factors);
511 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
512 scale_factors(factors, strength);
513
514 tls.translations.resize(verts.size());
515 const MutableSpan<float3> translations = tls.translations;
516 translations.copy_from(orig_data.normals);
517 scale_translations(translations, factors);
518 reset_translations_to_original(translations, positions, orig_data.positions);
519
521 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
522 position_data.deform(translations, verts);
523 });
524 break;
525 }
527 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
530 node_mask.foreach_index(GrainSize(1), [&](const int i) {
531 LocalData &tls = all_tls.local();
532 const Span<int> grids = nodes[i].grids();
533 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
534 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
535
536 tls.factors.resize(positions.size());
537 const MutableSpan<float> factors = tls.factors;
538 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
540 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
541 scale_factors(factors, strength);
542
543 tls.translations.resize(positions.size());
544 const MutableSpan<float3> translations = tls.translations;
545 translations.copy_from(orig_data.normals);
546 scale_translations(translations, factors);
547 reset_translations_to_original(translations, positions, orig_data.positions);
548
550 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
551 apply_translations(translations, grids, subdiv_ccg);
552 });
553 break;
554 }
556 BMesh &bm = *ss.bm;
559 node_mask.foreach_index(GrainSize(1), [&](const int i) {
560 LocalData &tls = all_tls.local();
562 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
563 Array<float3> orig_positions(verts.size());
564 Array<float3> orig_normals(verts.size());
565 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
566
567 tls.factors.resize(verts.size());
568 const MutableSpan<float> factors = tls.factors;
571 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
572 scale_factors(factors, strength);
573
574 tls.translations.resize(verts.size());
575 const MutableSpan<float3> translations = tls.translations;
576 translations.copy_from(orig_normals);
577 scale_translations(translations, factors);
578 reset_translations_to_original(translations, positions, orig_positions);
579
581 clip_and_lock_translations(sd, ss, orig_positions, translations);
582 apply_translations(translations, verts);
583 });
584 break;
585 }
586 }
587}
588
589static void calc_scale_filter(const Depsgraph &depsgraph,
590 const Sculpt &sd,
591 const float strength,
592 Object &object,
593 const IndexMask &node_mask)
594{
595 struct LocalData {
596 Vector<float> factors;
597 Vector<float3> positions;
598 Vector<float3> translations;
599 };
600 SculptSession &ss = *object.sculpt;
601 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
602 switch (pbvh.type()) {
604 Mesh &mesh = *static_cast<Mesh *>(object.data);
605 MeshAttributeData attribute_data(mesh.attributes());
606 const PositionDeformData position_data(depsgraph, object);
609 node_mask.foreach_index(GrainSize(1), [&](const int i) {
610 LocalData &tls = all_tls.local();
611 const Span<int> verts = nodes[i].verts();
612 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
613 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
614
615 tls.factors.resize(verts.size());
616 const MutableSpan<float> factors = tls.factors;
618 attribute_data.hide_vert, attribute_data.mask, verts, factors);
620 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
621 scale_factors(factors, strength);
622
623 tls.translations.resize(verts.size());
624 const MutableSpan<float3> translations = tls.translations;
625 translations.copy_from(orig_data.positions);
626 scale_translations(translations, factors);
627 reset_translations_to_original(translations, positions, orig_data.positions);
628
630 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
631 position_data.deform(translations, verts);
632 });
633 break;
634 }
636 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
639 node_mask.foreach_index(GrainSize(1), [&](const int i) {
640 LocalData &tls = all_tls.local();
641 const Span<int> grids = nodes[i].grids();
642 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
643 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
644
645 tls.factors.resize(positions.size());
646 const MutableSpan<float> factors = tls.factors;
647 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
649 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
650 scale_factors(factors, strength);
651
652 tls.translations.resize(positions.size());
653 const MutableSpan<float3> translations = tls.translations;
654 translations.copy_from(orig_data.positions);
655 scale_translations(translations, factors);
656 reset_translations_to_original(translations, positions, orig_data.positions);
657
659 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
660 apply_translations(translations, grids, subdiv_ccg);
661 });
662 break;
663 }
665 BMesh &bm = *ss.bm;
668 node_mask.foreach_index(GrainSize(1), [&](const int i) {
669 LocalData &tls = all_tls.local();
671 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
672 Array<float3> orig_positions(verts.size());
673 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
674
675 tls.factors.resize(verts.size());
676 const MutableSpan<float> factors = tls.factors;
679 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
680 scale_factors(factors, strength);
681
682 tls.translations.resize(positions.size());
683 const MutableSpan<float3> translations = tls.translations;
684 translations.copy_from(orig_positions);
685 scale_translations(translations, factors);
686 reset_translations_to_original(translations, positions, orig_positions);
687
689 clip_and_lock_translations(sd, ss, orig_positions, translations);
690 apply_translations(translations, verts);
691 });
692 break;
693 }
694 }
695}
696
698 const Span<float> factors,
699 const MutableSpan<float3> translations)
700{
701 for (const int i : positions.index_range()) {
702 float3x3 transform = float3x3::identity();
703 if (factors[i] > 0.0f) {
704 scale_m3_fl(transform.ptr(), 1.0f - factors[i]);
705 }
706 else {
707 scale_m3_fl(transform.ptr(), 1.0f + factors[i]);
708 }
709 translations[i] = math::midpoint(math::normalize(positions[i]) * math::abs(factors[i]),
710 transform * positions[i] - positions[i]);
711 }
712}
713
714static void calc_sphere_filter(const Depsgraph &depsgraph,
715 const Sculpt &sd,
716 const float strength,
717 Object &object,
718 const IndexMask &node_mask)
719{
720 struct LocalData {
721 Vector<float> factors;
722 Vector<float3> positions;
723 Vector<float3> translations;
724 };
725 SculptSession &ss = *object.sculpt;
726 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
727 switch (pbvh.type()) {
729 Mesh &mesh = *static_cast<Mesh *>(object.data);
730 const PositionDeformData position_data(depsgraph, object);
731 const MeshAttributeData attribute_data(mesh.attributes());
734 node_mask.foreach_index(GrainSize(1), [&](const int i) {
735 LocalData &tls = all_tls.local();
736 const Span<int> verts = nodes[i].verts();
737 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
738 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
739
740 tls.factors.resize(verts.size());
741 const MutableSpan<float> factors = tls.factors;
743 attribute_data.hide_vert, attribute_data.mask, verts, factors);
745 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
746 scale_factors(factors, strength);
747
748 tls.translations.resize(verts.size());
749 const MutableSpan<float3> translations = tls.translations;
750 calc_sphere_translations(orig_data.positions, factors, translations);
751 reset_translations_to_original(translations, positions, orig_data.positions);
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 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
768
769 tls.factors.resize(positions.size());
770 const MutableSpan<float> factors = tls.factors;
771 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
773 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
774 scale_factors(factors, strength);
775
776 tls.translations.resize(positions.size());
777 const MutableSpan<float3> translations = tls.translations;
778 calc_sphere_translations(orig_data.positions, factors, translations);
779 reset_translations_to_original(translations, positions, orig_data.positions);
780
782 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
783 apply_translations(translations, grids, subdiv_ccg);
784 });
785 break;
786 }
788 BMesh &bm = *ss.bm;
791 node_mask.foreach_index(GrainSize(1), [&](const int i) {
792 LocalData &tls = all_tls.local();
794 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
795 Array<float3> orig_positions(verts.size());
796 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
797
798 tls.factors.resize(verts.size());
799 const MutableSpan<float> factors = tls.factors;
802 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
803 scale_factors(factors, strength);
804
805 tls.translations.resize(positions.size());
806 const MutableSpan<float3> translations = tls.translations;
807 calc_sphere_translations(orig_positions, factors, translations);
808 reset_translations_to_original(translations, positions, orig_positions);
809
811 clip_and_lock_translations(sd, ss, orig_positions, translations);
812 apply_translations(translations, verts);
813 });
814 break;
815 }
816 }
817}
818
819BLI_NOINLINE static void randomize_factors(const Span<float3> positions,
820 const int seed,
821 const MutableSpan<float> factors)
822{
823 BLI_assert(positions.size() == factors.size());
824 for (const int i : positions.index_range()) {
825 const uint *hash_co = (const uint *)&positions[i];
826 const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^ BLI_hash_int_2d(hash_co[2], seed);
827 factors[i] *= (hash * (1.0f / float(0xFFFFFFFF)) - 0.5f);
828 }
829}
830
831static void calc_random_filter(const Depsgraph &depsgraph,
832 const Sculpt &sd,
833 const float strength,
834 Object &object,
835 const IndexMask &node_mask)
836{
837 struct LocalData {
838 Vector<float> factors;
839 Vector<float3> positions;
840 Vector<float3> translations;
841 };
842 SculptSession &ss = *object.sculpt;
843 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
844 switch (pbvh.type()) {
846 Mesh &mesh = *static_cast<Mesh *>(object.data);
847 const MeshAttributeData attribute_data(mesh.attributes());
848 const PositionDeformData position_data(depsgraph, object);
851 node_mask.foreach_index(GrainSize(1), [&](const int i) {
852 LocalData &tls = all_tls.local();
853 const Span<int> verts = nodes[i].verts();
854 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
855 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
856
857 tls.factors.resize(verts.size());
858 const MutableSpan<float> factors = tls.factors;
860 attribute_data.hide_vert, attribute_data.mask, verts, factors);
862 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
863 scale_factors(factors, strength);
864
865 randomize_factors(orig_data.positions, ss.filter_cache->random_seed, factors);
866 tls.translations.resize(verts.size());
867 const MutableSpan<float3> translations = tls.translations;
868 translations.copy_from(orig_data.normals);
869 scale_translations(translations, factors);
870 reset_translations_to_original(translations, positions, orig_data.positions);
871
873 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
874 position_data.deform(translations, verts);
875 });
876 break;
877 }
879 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
882 node_mask.foreach_index(GrainSize(1), [&](const int i) {
883 LocalData &tls = all_tls.local();
884 const Span<int> grids = nodes[i].grids();
885 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
886 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
887
888 tls.factors.resize(positions.size());
889 const MutableSpan<float> factors = tls.factors;
890 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
892 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
893 scale_factors(factors, strength);
894
895 randomize_factors(orig_data.positions, ss.filter_cache->random_seed, factors);
896 tls.translations.resize(positions.size());
897 const MutableSpan<float3> translations = tls.translations;
898 translations.copy_from(orig_data.normals);
899 scale_translations(translations, factors);
900 reset_translations_to_original(translations, positions, orig_data.positions);
901
903 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
904 apply_translations(translations, grids, subdiv_ccg);
905 });
906 break;
907 }
909 BMesh &bm = *ss.bm;
912 node_mask.foreach_index(GrainSize(1), [&](const int i) {
913 LocalData &tls = all_tls.local();
915 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
916 Array<float3> orig_positions(verts.size());
917 Array<float3> orig_normals(verts.size());
918 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
919
920 tls.factors.resize(verts.size());
921 const MutableSpan<float> factors = tls.factors;
924 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
925 scale_factors(factors, strength);
926
927 randomize_factors(orig_positions, ss.filter_cache->random_seed, factors);
928 tls.translations.resize(positions.size());
929 const MutableSpan<float3> translations = tls.translations;
930 translations.copy_from(orig_normals);
931 scale_translations(translations, factors);
932 reset_translations_to_original(translations, positions, orig_positions);
933
935 clip_and_lock_translations(sd, ss, orig_positions, translations);
936 apply_translations(translations, verts);
937 });
938 break;
939 }
940 }
941}
942
943static void calc_relax_filter(const Depsgraph &depsgraph,
944 const Sculpt &sd,
945 const float strength,
946 Object &object,
947 const IndexMask &node_mask)
948{
949 SculptSession &ss = *object.sculpt;
950 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
952 switch (pbvh.type()) {
953 struct LocalData {
954 Vector<float> factors;
955 Vector<Vector<int>> vert_neighbors;
956 Vector<float3> translations;
957 };
959 Mesh &mesh = *static_cast<Mesh *>(object.data);
960 const PositionDeformData position_data(depsgraph, object);
961 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
962 const OffsetIndices faces = mesh.faces();
963 const Span<int> corner_verts = mesh.corner_verts();
964 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
965 const MeshAttributeData attribute_data(mesh.attributes());
968 node_mask.foreach_index(GrainSize(1), [&](const int i) {
969 LocalData &tls = all_tls.local();
970 const Span<int> verts = nodes[i].verts();
971
972 tls.factors.resize(verts.size());
973 const MutableSpan<float> factors = tls.factors;
975 attribute_data.hide_vert, attribute_data.mask, verts, factors);
977 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
978 scale_factors(factors, strength);
979 clamp_factors(factors, 0.0f, 1.0f);
980
981 tls.translations.resize(verts.size());
982 const MutableSpan<float3> translations = tls.translations;
984 vert_normals,
985 faces,
986 corner_verts,
987 vert_to_face_map,
989 attribute_data.face_sets,
990 attribute_data.hide_poly,
991 false,
992 verts,
993 factors,
994 tls.vert_neighbors,
995 translations);
996
998 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
999 position_data.deform(translations, verts);
1000 });
1001 break;
1002 }
1004 struct LocalData {
1005 Vector<float> factors;
1006 Vector<float3> positions;
1007 Vector<Vector<SubdivCCGCoord>> vert_neighbors;
1008 Vector<float3> translations;
1009 };
1010 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
1011 const OffsetIndices faces = base_mesh.faces();
1012 const Span<int> corner_verts = base_mesh.corner_verts();
1013 const GroupedSpan<int> vert_to_face_map = base_mesh.vert_to_face_map();
1014 const bke::AttributeAccessor attributes = base_mesh.attributes();
1015 const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set",
1017 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1020 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1021 LocalData &tls = all_tls.local();
1022 const Span<int> grids = nodes[i].grids();
1023 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1024
1025 tls.factors.resize(positions.size());
1026 const MutableSpan<float> factors = tls.factors;
1027 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1029 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1030 scale_factors(factors, strength);
1031 clamp_factors(factors, 0.0f, 1.0f);
1032
1033 tls.translations.resize(positions.size());
1034 const MutableSpan<float3> translations = tls.translations;
1036 faces,
1037 corner_verts,
1038 face_sets,
1039 vert_to_face_map,
1041 grids,
1042 false,
1043 factors,
1044 tls.vert_neighbors,
1045 translations);
1046
1048 clip_and_lock_translations(sd, ss, positions, translations);
1049 apply_translations(translations, grids, subdiv_ccg);
1050 });
1051 break;
1052 }
1054 struct LocalData {
1055 Vector<float> factors;
1056 Vector<float3> positions;
1057 Vector<Vector<BMVert *>> vert_neighbors;
1058 Vector<float3> translations;
1059 };
1060 BMesh &bm = *ss.bm;
1061 const int face_set_offset = CustomData_get_offset_named(
1062 &bm.pdata, CD_PROP_INT32, ".sculpt_face_set");
1063
1066 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1067 LocalData &tls = all_tls.local();
1069 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1070
1071 tls.factors.resize(verts.size());
1072 const MutableSpan<float> factors = tls.factors;
1075 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1076 scale_factors(factors, strength);
1077 clamp_factors(factors, 0.0f, 1.0f);
1078
1079 tls.translations.resize(verts.size());
1080 const MutableSpan<float3> translations = tls.translations;
1082 verts, positions, face_set_offset, false, factors, tls.vert_neighbors, translations);
1083
1085 clip_and_lock_translations(sd, ss, positions, translations);
1086 apply_translations(translations, verts);
1087 });
1088 break;
1089 }
1090 }
1091}
1092
1093static void calc_relax_face_sets_filter(const Depsgraph &depsgraph,
1094 const Sculpt &sd,
1095 const float strength,
1096 Object &object,
1097 const IndexMask &node_mask)
1098{
1099 SculptSession &ss = *object.sculpt;
1100 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1101 bke::pbvh::update_normals(depsgraph, object, pbvh);
1102
1103 /* When using the relax face sets meshes filter, each 3 iterations, do a whole mesh relax to
1104 * smooth the contents of the Face Set. This produces better results as the relax operation is no
1105 * completely focused on the boundaries. */
1106 const bool relax_face_sets = !(ss.filter_cache->iteration_count % 3 == 0);
1107
1108 switch (pbvh.type()) {
1109 case bke::pbvh::Type::Mesh: {
1110 struct LocalData {
1111 Vector<float> factors;
1112 Vector<float3> positions;
1113 Vector<Vector<int>> vert_neighbors;
1114 Vector<float3> translations;
1115 };
1116 Mesh &mesh = *static_cast<Mesh *>(object.data);
1117 const PositionDeformData position_data(depsgraph, object);
1118 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
1119 const OffsetIndices faces = mesh.faces();
1120 const Span<int> corner_verts = mesh.corner_verts();
1121 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1122 const MeshAttributeData attribute_data(mesh.attributes());
1125 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1126 LocalData &tls = all_tls.local();
1127 const Span<int> verts = nodes[i].verts();
1128
1129 tls.factors.resize(verts.size());
1130 const MutableSpan<float> factors = tls.factors;
1132 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1134 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1135 scale_factors(factors, strength);
1136 clamp_factors(factors, 0.0f, 1.0f);
1137
1139 vert_to_face_map, attribute_data.face_sets, relax_face_sets, verts, factors);
1140
1141 tls.translations.resize(verts.size());
1142 const MutableSpan<float3> translations = tls.translations;
1144 vert_normals,
1145 faces,
1146 corner_verts,
1147 vert_to_face_map,
1149 attribute_data.face_sets,
1150 attribute_data.hide_poly,
1151 relax_face_sets,
1152 verts,
1153 factors,
1154 tls.vert_neighbors,
1155 translations);
1156
1158 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1159 position_data.deform(translations, verts);
1160 });
1161 break;
1162 }
1164 struct LocalData {
1165 Vector<float> factors;
1166 Vector<float3> positions;
1167 Vector<Vector<SubdivCCGCoord>> vert_neighbors;
1168 Vector<float3> translations;
1169 };
1170 const Mesh &base_mesh = *static_cast<const Mesh *>(object.data);
1171 const OffsetIndices faces = base_mesh.faces();
1172 const Span<int> corner_verts = base_mesh.corner_verts();
1173 const GroupedSpan<int> vert_to_face_map = base_mesh.vert_to_face_map();
1174 const bke::AttributeAccessor attributes = base_mesh.attributes();
1175 const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set",
1177
1178 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1181 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1182 LocalData &tls = all_tls.local();
1183 const Span<int> grids = nodes[i].grids();
1184 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1185
1186 tls.factors.resize(positions.size());
1187 const MutableSpan<float> factors = tls.factors;
1188 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1190 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1191 scale_factors(factors, strength);
1192 clamp_factors(factors, 0.0f, 1.0f);
1193
1195 corner_verts,
1196 vert_to_face_map,
1197 face_sets,
1198 subdiv_ccg,
1199 relax_face_sets,
1200 grids,
1201 factors);
1202
1203 tls.translations.resize(positions.size());
1204 const MutableSpan<float3> translations = tls.translations;
1206 faces,
1207 corner_verts,
1208 face_sets,
1209 vert_to_face_map,
1211 grids,
1212 relax_face_sets,
1213 factors,
1214 tls.vert_neighbors,
1215 translations);
1216
1218 clip_and_lock_translations(sd, ss, positions, translations);
1219 apply_translations(translations, grids, subdiv_ccg);
1220 });
1221 break;
1222 }
1224 struct LocalData {
1225 Vector<float> factors;
1226 Vector<float3> positions;
1227 Vector<Vector<BMVert *>> vert_neighbors;
1228 Vector<float3> translations;
1229 };
1230 BMesh &bm = *ss.bm;
1231 const int face_set_offset = CustomData_get_offset_named(
1232 &bm.pdata, CD_PROP_INT32, ".sculpt_face_set");
1235 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1236 LocalData &tls = all_tls.local();
1238 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1239
1240 tls.factors.resize(verts.size());
1241 const MutableSpan<float> factors = tls.factors;
1244 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1245 scale_factors(factors, strength);
1246 clamp_factors(factors, 0.0f, 1.0f);
1247
1249 face_set_offset, relax_face_sets, verts, factors);
1250
1251 tls.translations.resize(verts.size());
1252 const MutableSpan<float3> translations = tls.translations;
1254 positions,
1255 face_set_offset,
1256 relax_face_sets,
1257 factors,
1258 tls.vert_neighbors,
1259 translations);
1260
1262 clip_and_lock_translations(sd, ss, positions, translations);
1263 apply_translations(translations, verts);
1264 });
1265 break;
1266 }
1267 }
1268}
1269
1270static void calc_surface_smooth_filter(const Depsgraph &depsgraph,
1271 const Sculpt &sd,
1272 const float strength,
1273 Object &object,
1274 const IndexMask &node_mask)
1275{
1276 struct LocalData {
1277 Vector<float> factors;
1278 Vector<float3> positions;
1279 Vector<Vector<int>> vert_neighbors;
1280 Vector<float3> average_positions;
1281 Vector<float3> laplacian_disp;
1282 Vector<float3> translations;
1283 };
1284 SculptSession &ss = *object.sculpt;
1285 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1286 const float alpha = ss.filter_cache->surface_smooth_shape_preservation;
1288 const MutableSpan<float3> all_laplacian_disp = ss.filter_cache->surface_smooth_laplacian_disp;
1289 switch (pbvh.type()) {
1290 case bke::pbvh::Type::Mesh: {
1291 Mesh &mesh = *static_cast<Mesh *>(object.data);
1292 const MeshAttributeData attribute_data(mesh.attributes());
1293 const PositionDeformData position_data(depsgraph, object);
1294 const OffsetIndices faces = mesh.faces();
1295 const Span<int> corner_verts = mesh.corner_verts();
1296 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1299 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1300 LocalData &tls = all_tls.local();
1301 const Span<int> verts = nodes[i].verts();
1302 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
1303 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
1304
1305 tls.factors.resize(verts.size());
1306 const MutableSpan<float> factors = tls.factors;
1308 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1310 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1311 scale_factors(factors, strength);
1312 clamp_factors(factors, 0.0f, 1.0f);
1313
1314 tls.vert_neighbors.reinitialize(verts.size());
1315 calc_vert_neighbors(faces,
1316 corner_verts,
1317 vert_to_face_map,
1318 attribute_data.hide_poly,
1319 verts,
1320 tls.vert_neighbors);
1321
1322 tls.average_positions.reinitialize(verts.size());
1323 const MutableSpan<float3> average_positions = tls.average_positions;
1325 position_data.eval, verts, tls.vert_neighbors, average_positions);
1326
1327 tls.laplacian_disp.reinitialize(verts.size());
1328 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
1329 tls.translations.reinitialize(verts.size());
1330 const MutableSpan<float3> translations = tls.translations;
1332 orig_data.positions,
1333 average_positions,
1334 alpha,
1335 laplacian_disp,
1336 translations);
1337 scale_translations(translations, factors);
1338
1339 scatter_data_mesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
1340
1342 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1343 position_data.deform(translations, verts);
1344 });
1345 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1346 LocalData &tls = all_tls.local();
1347 const Span<int> verts = nodes[i].verts();
1348
1349 tls.factors.resize(verts.size());
1350 const MutableSpan<float> factors = tls.factors;
1352 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1354 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1355 scale_factors(factors, strength);
1356 clamp_factors(factors, 0.0f, 1.0f);
1357
1358 const MutableSpan<float3> laplacian_disp = gather_data_mesh(
1359 all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
1360
1361 tls.vert_neighbors.resize(verts.size());
1362 calc_vert_neighbors(faces,
1363 corner_verts,
1364 vert_to_face_map,
1365 attribute_data.hide_poly,
1366 verts,
1367 tls.vert_neighbors);
1368
1369 tls.average_positions.resize(verts.size());
1370 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
1372 all_laplacian_disp.as_span(), verts, tls.vert_neighbors, average_laplacian_disps);
1373
1374 tls.translations.resize(verts.size());
1375 const MutableSpan<float3> translations = tls.translations;
1377 laplacian_disp, average_laplacian_disps, beta, translations);
1378 scale_translations(translations, factors);
1379
1381 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1382 position_data.deform(translations, verts);
1383 });
1384 break;
1385 }
1387 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1390 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1391 LocalData &tls = all_tls.local();
1392 const Span<int> grids = nodes[i].grids();
1393 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1394 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
1395
1396 tls.factors.resize(positions.size());
1397 const MutableSpan<float> factors = tls.factors;
1398 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1400 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1401 scale_factors(factors, strength);
1402 clamp_factors(factors, 0.0f, 1.0f);
1403
1404 tls.average_positions.resize(positions.size());
1405 const MutableSpan<float3> average_positions = tls.average_positions;
1407 subdiv_ccg, subdiv_ccg.positions.as_span(), grids, average_positions);
1408
1409 tls.laplacian_disp.resize(positions.size());
1410 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
1411 tls.translations.resize(positions.size());
1412 const MutableSpan<float3> translations = tls.translations;
1414 orig_data.positions,
1415 average_positions,
1416 alpha,
1417 laplacian_disp,
1418 translations);
1419 scale_translations(translations, factors);
1420
1421 scatter_data_grids(subdiv_ccg, laplacian_disp.as_span(), grids, all_laplacian_disp);
1422
1424 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
1425 apply_translations(translations, grids, subdiv_ccg);
1426 });
1427 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1428 LocalData &tls = all_tls.local();
1429 const Span<int> grids = nodes[i].grids();
1430 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
1431
1432 tls.factors.resize(orig_data.positions.size());
1433 const MutableSpan<float> factors = tls.factors;
1434 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1436 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1437 scale_factors(factors, strength);
1438 clamp_factors(factors, 0.0f, 1.0f);
1439
1440 const MutableSpan<float3> laplacian_disp = gather_data_grids(
1441 subdiv_ccg, all_laplacian_disp.as_span(), grids, tls.laplacian_disp);
1442
1443 tls.average_positions.resize(orig_data.positions.size());
1444 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
1446 subdiv_ccg, all_laplacian_disp.as_span(), grids, average_laplacian_disps);
1447
1448 tls.translations.resize(orig_data.positions.size());
1449 const MutableSpan<float3> translations = tls.translations;
1451 laplacian_disp, average_laplacian_disps, beta, translations);
1452 scale_translations(translations, factors);
1453
1455 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
1456 apply_translations(translations, grids, subdiv_ccg);
1457 });
1458 break;
1459 }
1461 BMesh &bm = *ss.bm;
1464 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1465 LocalData &tls = all_tls.local();
1467 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1468 Array<float3> orig_positions(verts.size());
1469 Array<float3> orig_normals(verts.size());
1470 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
1471
1472 tls.factors.resize(verts.size());
1473 const MutableSpan<float> factors = tls.factors;
1476 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1477 scale_factors(factors, strength);
1478 clamp_factors(factors, 0.0f, 1.0f);
1479
1480 tls.average_positions.resize(verts.size());
1481 const MutableSpan<float3> average_positions = tls.average_positions;
1483
1484 tls.laplacian_disp.resize(verts.size());
1485 const MutableSpan<float3> laplacian_disp = tls.laplacian_disp;
1486 tls.translations.resize(verts.size());
1487 const MutableSpan<float3> translations = tls.translations;
1489 positions, orig_positions, average_positions, alpha, laplacian_disp, translations);
1490 scale_translations(translations, factors);
1491
1492 scatter_data_bmesh(laplacian_disp.as_span(), verts, all_laplacian_disp);
1493
1495 clip_and_lock_translations(sd, ss, orig_positions, translations);
1496 apply_translations(translations, verts);
1497 });
1498 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1499 LocalData &tls = all_tls.local();
1501 Array<float3> orig_positions(verts.size());
1502 Array<float3> orig_normals(verts.size());
1503 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
1504
1505 tls.factors.resize(verts.size());
1506 const MutableSpan<float> factors = tls.factors;
1509 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1510 scale_factors(factors, strength);
1511 clamp_factors(factors, 0.0f, 1.0f);
1512
1513 const MutableSpan<float3> laplacian_disp = gather_data_bmesh(
1514 all_laplacian_disp.as_span(), verts, tls.laplacian_disp);
1515
1516 tls.average_positions.resize(verts.size());
1517 const MutableSpan<float3> average_laplacian_disps = tls.average_positions;
1518 smooth::average_data_bmesh(all_laplacian_disp.as_span(), verts, average_laplacian_disps);
1519
1520 tls.translations.resize(verts.size());
1521 const MutableSpan<float3> translations = tls.translations;
1523 laplacian_disp, average_laplacian_disps, beta, translations);
1524 scale_translations(translations, factors);
1525
1527 clip_and_lock_translations(sd, ss, orig_positions, translations);
1528 apply_translations(translations, verts);
1529 });
1530 break;
1531 }
1532 }
1533}
1534
1536 const Span<float3> positions,
1537 const Span<float3> smooth_positions,
1538 const Span<float> sharpen_factors,
1539 const Span<float3> detail_directions,
1540 const MutableSpan<float3> translations)
1541{
1542 for (const int i : positions.index_range()) {
1543 float3 disp_avg = smooth_positions[i] - positions[i];
1544 disp_avg = disp_avg * filter_cache.sharpen_smooth_ratio * pow2f(sharpen_factors[i]);
1545 translations[i] += disp_avg;
1546 /* Intensify details. */
1547 if (filter_cache.sharpen_intensify_detail_strength > 0.0f) {
1548 float3 detail_strength = detail_directions[i];
1549 translations[i] += detail_strength * -filter_cache.sharpen_intensify_detail_strength *
1550 sharpen_factors[i];
1551 }
1552 }
1553}
1554
1555static void calc_sharpen_filter(const Depsgraph &depsgraph,
1556 const Sculpt &sd,
1557 const float strength,
1558 Object &object,
1559 const IndexMask &node_mask)
1560{
1561 struct LocalData {
1562 Vector<float> factors;
1563 Vector<float3> positions;
1564 Vector<Vector<int>> vert_neighbors;
1565 Vector<float3> smooth_positions;
1566 Vector<float> sharpen_factors;
1567 Vector<float3> detail_directions;
1568 Vector<float3> translations;
1569 };
1570 SculptSession &ss = *object.sculpt;
1571 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1572 switch (pbvh.type()) {
1573 case bke::pbvh::Type::Mesh: {
1574 Mesh &mesh = *static_cast<Mesh *>(object.data);
1575 const MeshAttributeData attribute_data(mesh.attributes());
1576 const PositionDeformData position_data(depsgraph, object);
1577
1578 const OffsetIndices faces = mesh.faces();
1579 const Span<int> corner_verts = mesh.corner_verts();
1580 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1583 node_mask.foreach_index(GrainSize(1), [&](const int node_index) {
1584 LocalData &tls = all_tls.local();
1585 const Span<int> verts = nodes[node_index].verts();
1586 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
1587
1588 tls.factors.resize(verts.size());
1589 const MutableSpan<float> factors = tls.factors;
1591 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1593 object,
1594 ss.filter_cache->automasking.get(),
1595 nodes[node_index],
1596 verts,
1597 factors);
1598 scale_factors(factors, strength);
1599
1600 /* This filter can't work at full strength as it needs multiple iterations to reach a
1601 * stable state. */
1602 clamp_factors(factors, 0.0f, 0.5f);
1603
1604 tls.vert_neighbors.resize(verts.size());
1605 const MutableSpan<Vector<int>> neighbors = tls.vert_neighbors;
1607 faces, corner_verts, vert_to_face_map, attribute_data.hide_poly, verts, neighbors);
1608
1609 tls.smooth_positions.resize(verts.size());
1610 const MutableSpan<float3> smooth_positions = tls.smooth_positions;
1612 position_data.eval, verts, neighbors, smooth_positions);
1613
1614 const Span<float> sharpen_factors = gather_data_mesh(
1615 ss.filter_cache->sharpen_factor.as_span(), verts, tls.sharpen_factors);
1616
1617 tls.translations.resize(verts.size());
1618 const MutableSpan<float3> translations = tls.translations;
1619 for (const int i : verts.index_range()) {
1620 const int vert = verts[i];
1621 const float3 &position = position_data.eval[vert];
1622
1623 float3 disp_sharpen(0.0f);
1624 for (const int neighbor : neighbors[i]) {
1625 float3 disp_n = position_data.eval[neighbor] - position;
1626 disp_n *= ss.filter_cache->sharpen_factor[neighbor];
1627 disp_sharpen += disp_n;
1628 }
1629
1630 disp_sharpen *= (1.0f - sharpen_factors[i]);
1631 translations[i] = disp_sharpen;
1632 }
1633
1634 const Span<float3> detail_directions = gather_data_mesh(
1635 ss.filter_cache->detail_directions.as_span(), verts, tls.detail_directions);
1636
1638 positions,
1639 smooth_positions,
1640 sharpen_factors,
1641 detail_directions,
1642 translations);
1643 scale_translations(translations, factors);
1644
1646 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1647 position_data.deform(translations, verts);
1648 });
1649 break;
1650 }
1652 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1653 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1654 MutableSpan<float3> vert_positions = subdiv_ccg.positions;
1655
1658 node_mask.foreach_index(GrainSize(1), [&](const int node_index) {
1659 LocalData &tls = all_tls.local();
1660 const Span<int> grids = nodes[node_index].grids();
1661 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1662
1663 tls.factors.resize(positions.size());
1664 const MutableSpan<float> factors = tls.factors;
1665 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1667 object,
1668 ss.filter_cache->automasking.get(),
1669 nodes[node_index],
1670 grids,
1671 factors);
1672 scale_factors(factors, strength);
1673
1674 /* This filter can't work at full strength as it needs multiple iterations to reach a
1675 * stable state. */
1676 clamp_factors(factors, 0.0f, 0.5f);
1677
1678 tls.vert_neighbors.resize(positions.size());
1679
1680 tls.smooth_positions.resize(positions.size());
1681 const MutableSpan<float3> smooth_positions = tls.smooth_positions;
1683 subdiv_ccg, subdiv_ccg.positions.as_span(), grids, smooth_positions);
1684
1685 const Span<float> sharpen_factors = gather_data_grids(
1686 subdiv_ccg, ss.filter_cache->sharpen_factor.as_span(), grids, tls.sharpen_factors);
1687
1688 tls.translations.resize(positions.size());
1689 const MutableSpan<float3> translations = tls.translations;
1690 for (const int i : grids.index_range()) {
1691 const int node_verts_start = i * key.grid_area;
1692 const int grid = grids[i];
1693 for (const short y : IndexRange(key.grid_size)) {
1694 for (const short x : IndexRange(key.grid_size)) {
1695 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
1696 const int node_vert = node_verts_start + offset;
1697
1698 const float3 &position = positions[node_vert];
1699
1700 float3 disp_sharpen(0.0f);
1701 SubdivCCGNeighbors neighbors;
1703 subdiv_ccg, SubdivCCGCoord{grid, x, y}, false, neighbors);
1704 for (const SubdivCCGCoord neighbor : neighbors.coords) {
1705 float3 disp_n = vert_positions[neighbor.to_index(key)] - position;
1706 disp_n *= ss.filter_cache->sharpen_factor[neighbor.to_index(key)];
1707 disp_sharpen += disp_n;
1708 }
1709
1710 disp_sharpen *= (1.0f - sharpen_factors[node_vert]);
1711 translations[node_vert] = disp_sharpen;
1712 }
1713 }
1714 }
1715
1716 const Span<float3> detail_directions = gather_data_grids(
1717 subdiv_ccg,
1719 grids,
1720 tls.detail_directions);
1721
1723 positions,
1724 smooth_positions,
1725 sharpen_factors,
1726 detail_directions,
1727 translations);
1728 scale_translations(translations, factors);
1729
1731 clip_and_lock_translations(sd, ss, positions, translations);
1732 apply_translations(translations, grids, subdiv_ccg);
1733 });
1734 break;
1735 }
1737 BMesh &bm = *ss.bm;
1741 node_mask.foreach_index(GrainSize(1), [&](const int node_index) {
1742 LocalData &tls = all_tls.local();
1743 const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[node_index]);
1744 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1745
1746 tls.factors.resize(verts.size());
1747 const MutableSpan<float> factors = tls.factors;
1750 object,
1751 ss.filter_cache->automasking.get(),
1752 nodes[node_index],
1753 verts,
1754 factors);
1755 scale_factors(factors, strength);
1756
1757 /* This filter can't work at full strength as it needs multiple iterations to reach a
1758 * stable state. */
1759 clamp_factors(factors, 0.0f, 0.5f);
1760
1761 tls.smooth_positions.resize(verts.size());
1762 const MutableSpan<float3> smooth_positions = tls.smooth_positions;
1764
1765 const Span<float> sharpen_factors = gather_data_bmesh(
1766 ss.filter_cache->sharpen_factor.as_span(), verts, tls.sharpen_factors);
1767
1768 tls.translations.resize(verts.size());
1769 const MutableSpan<float3> translations = tls.translations;
1770
1771 Vector<BMVert *, 64> neighbors;
1772
1773 int i = 0;
1774 for (BMVert *vert : verts) {
1775 const float3 position = vert->co;
1776
1777 float3 disp_sharpen(0.0f);
1778 for (const BMVert *neighbor : vert_neighbors_get_bmesh(*vert, neighbors)) {
1779 float3 disp_n = float3(neighbor->co) - position;
1780 disp_n *= ss.filter_cache->sharpen_factor[BM_elem_index_get(neighbor)];
1781 disp_sharpen += disp_n;
1782 }
1783
1784 disp_sharpen *= (1.0f - sharpen_factors[i]);
1785 translations[i] = disp_sharpen;
1786 i++;
1787 }
1788
1789 const Span<float3> detail_directions = gather_data_bmesh(
1790 ss.filter_cache->detail_directions.as_span(), verts, tls.detail_directions);
1791
1793 positions,
1794 smooth_positions,
1795 sharpen_factors,
1796 detail_directions,
1797 translations);
1798 scale_translations(translations, factors);
1799
1801 clip_and_lock_translations(sd, ss, positions, translations);
1802 apply_translations(translations, verts);
1803 });
1804 break;
1805 }
1806 }
1807}
1808
1809static void calc_enhance_details_filter(const Depsgraph &depsgraph,
1810 const Sculpt &sd,
1811 const float strength,
1812 Object &object,
1813 const IndexMask &node_mask)
1814{
1815 const float final_strength = -std::abs(strength);
1816 struct LocalData {
1817 Vector<float> factors;
1818 Vector<float3> positions;
1819 Vector<float3> translations;
1820 };
1821 SculptSession &ss = *object.sculpt;
1822 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1823 switch (pbvh.type()) {
1824 case bke::pbvh::Type::Mesh: {
1825 Mesh &mesh = *static_cast<Mesh *>(object.data);
1826 const MeshAttributeData attribute_data(mesh.attributes());
1827 const PositionDeformData position_data(depsgraph, object);
1830 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1831 LocalData &tls = all_tls.local();
1832 const Span<int> verts = nodes[i].verts();
1833 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
1834 const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]);
1835
1836 tls.factors.resize(verts.size());
1837 const MutableSpan<float> factors = tls.factors;
1839 attribute_data.hide_vert, attribute_data.mask, verts, factors);
1841 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1842 scale_factors(factors, final_strength);
1843
1844 const MutableSpan translations = gather_data_mesh(
1846 scale_translations(translations, factors);
1847 reset_translations_to_original(translations, positions, orig_data.positions);
1848
1850 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
1851 position_data.deform(translations, verts);
1852 });
1853 break;
1854 }
1856 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1859 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1860 LocalData &tls = all_tls.local();
1861 const Span<int> grids = nodes[i].grids();
1862 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1863 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
1864
1865 tls.factors.resize(positions.size());
1866 const MutableSpan<float> factors = tls.factors;
1867 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1869 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1870 scale_factors(factors, final_strength);
1871
1872 const MutableSpan translations = gather_data_grids(
1873 subdiv_ccg, ss.filter_cache->detail_directions.as_span(), grids, tls.translations);
1874 scale_translations(translations, factors);
1875 reset_translations_to_original(translations, positions, orig_data.positions);
1876
1878 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
1879 apply_translations(translations, grids, subdiv_ccg);
1880 });
1881 break;
1882 }
1884 BMesh &bm = *ss.bm;
1887 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1888 LocalData &tls = all_tls.local();
1890 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1891 Array<float3> orig_positions(verts.size());
1892 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {});
1893
1894 tls.factors.resize(verts.size());
1895 const MutableSpan<float> factors = tls.factors;
1898 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors);
1899 scale_factors(factors, final_strength);
1900
1901 const MutableSpan<float3> translations = gather_data_bmesh(
1903 scale_translations(translations, factors);
1904 reset_translations_to_original(translations, positions, orig_positions);
1905
1907 clip_and_lock_translations(sd, ss, orig_positions, translations);
1908 apply_translations(translations, verts);
1909 });
1910 break;
1911 }
1912 }
1913}
1914
1915static void calc_erase_displacement_filter(const Depsgraph &depsgraph,
1916 const Sculpt &sd,
1917 const float strength,
1918 Object &object,
1919 const IndexMask &node_mask)
1920{
1921 struct LocalData {
1922 Vector<float> factors;
1923 Vector<float3> positions;
1924 Vector<float3> new_positions;
1925 Vector<float3> translations;
1926 };
1927 SculptSession &ss = *object.sculpt;
1928 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1929 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1932 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1933 LocalData &tls = all_tls.local();
1934 const Span<int> grids = nodes[i].grids();
1935 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1936 const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]);
1937
1938 tls.factors.resize(positions.size());
1939 const MutableSpan<float> factors = tls.factors;
1940 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
1942 depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors);
1943 scale_factors(factors, strength);
1944 clamp_factors(factors, -1.0f, 1.0f);
1945
1946 const MutableSpan<float3> new_positions = gather_data_grids(
1947 subdiv_ccg, ss.filter_cache->limit_surface_co.as_span(), grids, tls.new_positions);
1948 tls.translations.resize(positions.size());
1949 const MutableSpan<float3> translations = tls.translations;
1950 translations_from_new_positions(new_positions, orig_data.positions, translations);
1951 scale_translations(translations, factors);
1952 reset_translations_to_original(translations, positions, orig_data.positions);
1953
1955 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
1956 apply_translations(translations, grids, subdiv_ccg);
1957 });
1958}
1959
1961 const float shape_preservation,
1962 const float current_vertex_displacement)
1963{
1964 SculptSession &ss = *object.sculpt;
1965 const int totvert = SCULPT_vertex_count_get(object);
1966 filter::Cache *filter_cache = ss.filter_cache;
1967
1968 filter_cache->surface_smooth_laplacian_disp.reinitialize(totvert);
1969 filter_cache->surface_smooth_shape_preservation = shape_preservation;
1970 filter_cache->surface_smooth_current_vertex = current_vertex_displacement;
1971}
1972
1973static void calc_limit_surface_positions(const Object &object, MutableSpan<float3> limit_positions)
1974{
1975 const SculptSession &ss = *object.sculpt;
1976 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1977 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1978
1979 threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 512, [&](const IndexRange range) {
1980 for (const int grid : range) {
1981 MutableSpan grid_dst = limit_positions.slice(bke::ccg::grid_range(key, grid));
1982 BKE_subdiv_ccg_eval_limit_positions(subdiv_ccg, key, grid, grid_dst);
1983 }
1984 });
1985}
1986
1987static void mesh_filter_sharpen_init(const Depsgraph &depsgraph,
1988 const Object &object,
1989 const float smooth_ratio,
1990 const float intensify_detail_strength,
1991 const int curvature_smooth_iterations,
1992 filter::Cache &filter_cache)
1993{
1994 const SculptSession &ss = *object.sculpt;
1995 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1996 const IndexMask &node_mask = filter_cache.node_mask;
1997 const int totvert = SCULPT_vertex_count_get(object);
1998
1999 filter_cache.sharpen_smooth_ratio = smooth_ratio;
2000 filter_cache.sharpen_intensify_detail_strength = intensify_detail_strength;
2001 filter_cache.sharpen_curvature_smooth_iterations = curvature_smooth_iterations;
2002 filter_cache.sharpen_factor.reinitialize(totvert);
2003 filter_cache.detail_directions.reinitialize(totvert);
2004 MutableSpan<float3> detail_directions = filter_cache.detail_directions;
2005 MutableSpan<float> sharpen_factors = filter_cache.sharpen_factor;
2006
2007 calc_smooth_translations(depsgraph, object, node_mask, filter_cache.detail_directions);
2008
2009 for (int i = 0; i < totvert; i++) {
2010 sharpen_factors[i] = math::length(detail_directions[i]);
2011 }
2012
2013 float max_factor = 0.0f;
2014 for (int i = 0; i < totvert; i++) {
2015 if (sharpen_factors[i] > max_factor) {
2016 max_factor = sharpen_factors[i];
2017 }
2018 }
2019
2020 max_factor = 1.0f / max_factor;
2021 for (int i = 0; i < totvert; i++) {
2022 sharpen_factors[i] *= max_factor;
2023 sharpen_factors[i] = 1.0f - pow2f(1.0f - sharpen_factors[i]);
2024 }
2025
2026 /* Smooth the calculated factors and directions to remove high frequency detail. */
2027 struct LocalData {
2028 Vector<Vector<int>> vert_neighbors;
2029 Vector<float3> smooth_directions;
2030 Vector<float> smooth_factors;
2031 };
2033 for ([[maybe_unused]] const int _ : IndexRange(filter_cache.sharpen_curvature_smooth_iterations))
2034 {
2035 switch (pbvh.type()) {
2036 case bke::pbvh::Type::Mesh: {
2037 Mesh &mesh = *static_cast<Mesh *>(object.data);
2038 const OffsetIndices faces = mesh.faces();
2039 const Span<int> corner_verts = mesh.corner_verts();
2040 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
2042 const MeshAttributeData attribute_data(mesh.attributes());
2043 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2044 LocalData &tls = all_tls.local();
2045 const Span<int> verts = nodes[i].verts();
2046
2047 tls.vert_neighbors.resize(verts.size());
2048 const MutableSpan<Vector<int>> neighbors = tls.vert_neighbors;
2050 faces, corner_verts, vert_to_face_map, attribute_data.hide_poly, verts, neighbors);
2051
2052 tls.smooth_directions.resize(verts.size());
2054 verts,
2055 neighbors,
2056 tls.smooth_directions.as_mutable_span());
2057 scatter_data_mesh(tls.smooth_directions.as_span(), verts, detail_directions);
2058
2059 tls.smooth_factors.resize(verts.size());
2061 sharpen_factors.as_span(), verts, neighbors, tls.smooth_factors.as_mutable_span());
2062 scatter_data_mesh(tls.smooth_factors.as_span(), verts, sharpen_factors);
2063 });
2064 break;
2065 }
2067 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
2068 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
2070 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2071 LocalData &tls = all_tls.local();
2072 const Span<int> grids = nodes[i].grids();
2073 const int grid_verts_num = grids.size() * key.grid_area;
2074
2075 tls.smooth_directions.resize(grid_verts_num);
2076 smooth::average_data_grids(subdiv_ccg,
2077 detail_directions.as_span(),
2078 grids,
2079 tls.smooth_directions.as_mutable_span());
2081 subdiv_ccg, tls.smooth_directions.as_span(), grids, detail_directions);
2082
2083 tls.smooth_factors.resize(grid_verts_num);
2085 subdiv_ccg, sharpen_factors.as_span(), grids, tls.smooth_factors.as_mutable_span());
2086 scatter_data_grids(subdiv_ccg, tls.smooth_factors.as_span(), grids, sharpen_factors);
2087 });
2088 break;
2089 }
2092 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2093 LocalData &tls = all_tls.local();
2095 &const_cast<bke::pbvh::BMeshNode &>(nodes[i]));
2096
2097 tls.smooth_directions.resize(verts.size());
2099 detail_directions.as_span(), verts, tls.smooth_directions.as_mutable_span());
2100 scatter_data_bmesh(tls.smooth_directions.as_span(), verts, detail_directions);
2101
2102 tls.smooth_factors.resize(verts.size());
2104 sharpen_factors.as_span(), verts, tls.smooth_factors.as_mutable_span());
2105 scatter_data_bmesh(tls.smooth_factors.as_span(), verts, sharpen_factors);
2106 });
2107 break;
2108 }
2109 }
2110}
2111
2112enum {
2115};
2116
2117wmKeyMap *modal_keymap(wmKeyConfig *keyconf)
2118{
2119 static const EnumPropertyItem modal_items[] = {
2120 {FILTER_MESH_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
2121 {FILTER_MESH_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
2122 {0, nullptr, 0, nullptr, nullptr},
2123 };
2124
2125 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Mesh Filter Modal Map");
2126
2127 /* This function is called for each space-type, only needs to add map once. */
2128 if (keymap && keymap->modal_items) {
2129 return nullptr;
2130 }
2131
2132 keymap = WM_modalkeymap_ensure(keyconf, "Mesh Filter Modal Map", modal_items);
2133
2134 WM_modalkeymap_assign(keymap, "SCULPT_OT_mesh_filter");
2135
2136 return keymap;
2137}
2138
2140{
2141 WorkspaceStatus status(C);
2142 status.item(IFACE_("Confirm"), ICON_EVENT_RETURN);
2143 status.item(IFACE_("Cancel"), ICON_EVENT_ESC, ICON_MOUSE_RMB);
2144}
2145
2147{
2148 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
2150 SculptSession &ss = *ob.sculpt;
2151 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
2152 const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
2153 const float strength = RNA_float_get(op->ptr, "strength");
2154
2156
2157 const IndexMask &node_mask = ss.filter_cache->node_mask;
2158 switch (filter_type) {
2159 case MeshFilterType::Smooth:
2160 calc_smooth_filter(depsgraph, sd, strength, ob, node_mask);
2161 break;
2162 case MeshFilterType::Scale:
2163 calc_scale_filter(depsgraph, sd, strength, ob, node_mask);
2164 break;
2165 case MeshFilterType::Inflate:
2166 calc_inflate_filter(depsgraph, sd, strength, ob, node_mask);
2167 break;
2168 case MeshFilterType::Sphere:
2169 calc_sphere_filter(depsgraph, sd, strength, ob, node_mask);
2170 break;
2171 case MeshFilterType::Random:
2172 calc_random_filter(depsgraph, sd, strength, ob, node_mask);
2173 break;
2174 case MeshFilterType::Relax:
2175 calc_relax_filter(depsgraph, sd, strength, ob, node_mask);
2176 break;
2177 case MeshFilterType::RelaxFaceSets:
2178 calc_relax_face_sets_filter(depsgraph, sd, strength, ob, node_mask);
2179 break;
2180 case MeshFilterType::SurfaceSmooth:
2181 calc_surface_smooth_filter(depsgraph, sd, strength, ob, node_mask);
2182 break;
2183 case MeshFilterType::Sharpen:
2184 calc_sharpen_filter(depsgraph, sd, strength, ob, node_mask);
2185 break;
2186 case MeshFilterType::EnhanceDetails:
2187 calc_enhance_details_filter(depsgraph, sd, strength, ob, node_mask);
2188 break;
2189 case MeshFilterType::EraseDisplacement:
2190 calc_erase_displacement_filter(depsgraph, sd, strength, ob, node_mask);
2191 break;
2192 }
2193
2195 pbvh.tag_positions_changed(node_mask);
2196
2198
2201}
2202
2204 SculptSession &ss,
2205 float2 prev_press_mouse,
2206 float2 mouse)
2207{
2208 const float len = prev_press_mouse[0] - mouse[0];
2209
2210 float filter_strength = ss.filter_cache->start_filter_strength * -len * 0.001f * UI_SCALE_FAC;
2211 RNA_float_set(op->ptr, "strength", filter_strength);
2212}
2214{
2215 /* Event history is only stored for smooth and relax filters. */
2216 if (!RNA_collection_length(op->ptr, "event_history")) {
2218 return;
2219 }
2220
2222 SculptSession &ss = *ob.sculpt;
2223 float2 start_mouse;
2224 bool first = true;
2225 float initial_strength = ss.filter_cache->start_filter_strength;
2226
2227 RNA_BEGIN (op->ptr, item, "event_history") {
2228 float2 mouse;
2229 RNA_float_get_array(&item, "mouse_event", mouse);
2230
2231 if (first) {
2232 first = false;
2233 start_mouse = mouse;
2234 continue;
2235 }
2236
2237 sculpt_mesh_update_strength(op, ss, start_mouse, mouse);
2239 }
2240 RNA_END;
2241
2242 RNA_float_set(op->ptr, "strength", initial_strength);
2243}
2244
2246{
2248 SculptSession &ss = *ob.sculpt;
2249
2250 MEM_delete(ss.filter_cache);
2251 ss.filter_cache = nullptr;
2253}
2254
2256 wmOperator *op,
2257 const MeshFilterType filter_type)
2258{
2259 float initial_strength = ss.filter_cache->start_filter_strength;
2260 /* Don't update strength property if we're storing an event history. */
2261 if (sculpt_mesh_filter_is_continuous(filter_type)) {
2262 RNA_float_set(op->ptr, "strength", initial_strength);
2263 }
2264
2265 return OPERATOR_FINISHED;
2266}
2267
2269{
2270 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
2272 SculptSession *ss = ob.sculpt;
2274
2275 if (!ss || !pbvh) {
2276 return;
2277 }
2278
2280
2282}
2283
2284static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
2285{
2287 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
2288 SculptSession &ss = *ob.sculpt;
2289 const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
2290
2293
2294 if (event->type == EVT_MODAL_MAP) {
2295 int ret = OPERATOR_FINISHED;
2296 switch (event->val) {
2299 undo::push_end_ex(ob, true);
2301 break;
2302
2304 ret = sculpt_mesh_filter_confirm(ss, op, filter_type);
2305 undo::push_end_ex(ob, false);
2306 break;
2307 }
2308
2310 ED_workspace_status_text(C, nullptr); /* Clear status bar */
2312
2313 return ret;
2314 }
2315
2316 if (event->type != MOUSEMOVE) {
2318 }
2319
2320 /* NOTE: some filter types are continuous, for these we store an
2321 * event history in RNA for continuous.
2322 * This way the user can tweak the last operator properties
2323 * or repeat the op and get expected results. */
2324 if (sculpt_mesh_filter_is_continuous(filter_type)) {
2325 if (RNA_collection_length(op->ptr, "event_history") == 0) {
2326 /* First entry is the start mouse position, event->prev_press_xy. */
2327 PointerRNA startptr;
2328 RNA_collection_add(op->ptr, "event_history", &startptr);
2329
2330 float2 mouse_start(float(event->prev_press_xy[0]), float(event->prev_press_xy[1]));
2331 RNA_float_set_array(&startptr, "mouse_event", mouse_start);
2332 }
2333
2334 PointerRNA itemptr;
2335 RNA_collection_add(op->ptr, "event_history", &itemptr);
2336
2337 float2 mouse(float(event->xy[0]), float(event->xy[1]));
2338 RNA_float_set_array(&itemptr, "mouse_event", mouse);
2339 RNA_float_set(&itemptr, "pressure", WM_event_tablet_data(event, nullptr, nullptr));
2340 }
2341
2342 float2 prev_mval(float(event->prev_press_xy[0]), float(event->prev_press_xy[1]));
2343 float2 mval(float(event->xy[0]), float(event->xy[1]));
2344
2345 sculpt_mesh_update_strength(op, ss, prev_mval, mval);
2346
2348
2350
2352}
2353
2354static void sculpt_filter_specific_init(const Depsgraph &depsgraph,
2355 const MeshFilterType filter_type,
2356 wmOperator *op,
2357 Object &object)
2358{
2359 SculptSession &ss = *object.sculpt;
2360 switch (filter_type) {
2361 case MeshFilterType::SurfaceSmooth: {
2363 RNA_float_get(op->ptr, "surface_smooth_shape_preservation"),
2364 RNA_float_get(op->ptr, "surface_smooth_current_vertex"));
2365 break;
2366 }
2367 case MeshFilterType::Sharpen: {
2369 object,
2370 RNA_float_get(op->ptr, "sharpen_smooth_ratio"),
2371 RNA_float_get(op->ptr, "sharpen_intensify_detail_strength"),
2372 RNA_int_get(op->ptr, "sharpen_curvature_smooth_iterations"),
2373 *ss.filter_cache);
2374 break;
2375 }
2376 case MeshFilterType::EnhanceDetails: {
2380 break;
2381 }
2382 case MeshFilterType::EraseDisplacement: {
2385 break;
2386 }
2387 default:
2388 break;
2389 }
2390}
2391
2392/* Returns OPERATOR_PASS_THROUGH on success. */
2394{
2395 const Scene &scene = *CTX_data_scene(C);
2397 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
2398 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
2399
2400 const View3D *v3d = CTX_wm_view3d(C);
2401 const Base *base = CTX_data_active_base(C);
2402 if (!BKE_base_is_visible(v3d, base)) {
2403 return OPERATOR_CANCELLED;
2404 }
2405
2406 int mval[2];
2407 RNA_int_get_array(op->ptr, "start_mouse", mval);
2408
2409 const MeshFilterType filter_type = MeshFilterType(RNA_enum_get(op->ptr, "type"));
2410 const bool use_automasking = auto_mask::is_enabled(sd, ob, nullptr);
2411 const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type) || use_automasking;
2412
2414
2416 return OPERATOR_CANCELLED;
2417 }
2418
2419 SculptSession &ss = *ob.sculpt;
2420
2421 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
2422 if (filter_type == MeshFilterType::EraseDisplacement && pbvh.type() != bke::pbvh::Type::Grids) {
2423 return OPERATOR_CANCELLED;
2424 }
2425
2426 const eMeshFilterDeformAxis deform_axis = eMeshFilterDeformAxis(
2427 RNA_enum_get(op->ptr, "deform_axis"));
2428
2429 if (deform_axis == 0) {
2430 /* All axis are disabled, so the filter is not going to produce any deformation. */
2431 return OPERATOR_CANCELLED;
2432 }
2433
2434 float2 mval_fl{float(mval[0]), float(mval[1])};
2435 if (use_automasking) {
2436 /* Update the active face set manually as the paint cursor is not enabled when using the
2437 * Mesh Filter Tool. */
2439 SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
2440 }
2441
2443 if (needs_topology_info) {
2445 }
2446
2447 undo::push_begin(scene, ob, op);
2448
2449 cache_init(C,
2450 ob,
2451 sd,
2453 mval_fl,
2454 RNA_float_get(op->ptr, "area_normal_radius"),
2455 RNA_float_get(op->ptr, "strength"));
2456
2457 filter::Cache *filter_cache = ss.filter_cache;
2458 filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
2459 filter_cache->automasking = auto_mask::cache_init(*depsgraph, sd, ob);
2460
2461 sculpt_filter_specific_init(*depsgraph, filter_type, op, ob);
2462
2463 ss.filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
2464 ss.filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
2465 ss.filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
2466
2467 ss.filter_cache->orientation = FilterOrientation(RNA_enum_get(op->ptr, "orientation"));
2468
2469 return OPERATOR_PASS_THROUGH;
2470}
2471
2472static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2473{
2474 RNA_int_set_array(op->ptr, "start_mouse", event->mval);
2475 int ret = sculpt_mesh_filter_start(C, op);
2476
2477 if (ret == OPERATOR_PASS_THROUGH) {
2480 }
2481
2482 return ret;
2483}
2484
2486{
2487 int ret = sculpt_mesh_filter_start(C, op);
2488
2489 if (ret == OPERATOR_PASS_THROUGH) {
2490 int iterations = RNA_int_get(op->ptr, "iteration_count");
2491
2492 for (int i = 0; i < iterations; i++) {
2494 }
2495
2497
2498 return OPERATOR_FINISHED;
2499 }
2500
2501 return ret;
2502}
2503
2505{
2507 ot->srna, "start_mouse", 2, nullptr, 0, 1 << 14, "Starting Mouse", "", 0, 1 << 14);
2508
2510 "area_normal_radius",
2511 0.25,
2512 0.001,
2513 5.0,
2514 "Normal Radius",
2515 "Radius used for calculating area normal on initial click,\nin percentage "
2516 "of brush radius",
2517 0.01,
2518 1.0);
2520 ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
2522 "iteration_count",
2523 1,
2524 1,
2525 10000,
2526 "Repeat",
2527 "How many times to repeat the filter",
2528 1,
2529 100);
2530
2531 /* Smooth filter requires entire event history. */
2533 ot->srna, "event_history", &RNA_OperatorStrokeElement, "", "");
2535}
2536
2537static void sculpt_mesh_ui_exec(bContext * /*C*/, wmOperator *op)
2538{
2539 uiLayout *layout = op->layout;
2540
2541 uiItemR(layout, op->ptr, "strength", UI_ITEM_NONE, nullptr, ICON_NONE);
2542 uiItemR(layout, op->ptr, "iteration_count", UI_ITEM_NONE, nullptr, ICON_NONE);
2543 uiItemR(layout, op->ptr, "orientation", UI_ITEM_NONE, nullptr, ICON_NONE);
2544 layout = uiLayoutRow(layout, true);
2545 uiItemR(layout, op->ptr, "deform_axis", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
2546}
2547
2549{
2550 ot->name = "Filter Mesh";
2551 ot->idname = "SCULPT_OT_mesh_filter";
2552 ot->description = "Applies a filter to modify the current mesh";
2553
2559
2560 /* Doesn't seem to actually be called?
2561 * Check `sculpt_mesh_filter_modal` to see where it's really called. */
2563
2566
2568
2570 "type",
2572 int(MeshFilterType::Inflate),
2573 "Filter Type",
2574 "Operation that is going to be applied to the mesh");
2577 "deform_axis",
2580 "Deform Axis",
2581 "Apply the deformation in the selected axis");
2583 "orientation",
2585 int(FilterOrientation::Local),
2586 "Orientation",
2587 "Orientation of the axis to limit the filter displacement");
2588
2589 /* Surface Smooth Mesh Filter properties. */
2591 "surface_smooth_shape_preservation",
2592 0.5f,
2593 0.0f,
2594 1.0f,
2595 "Shape Preservation",
2596 "How much of the original shape is preserved when smoothing",
2597 0.0f,
2598 1.0f);
2600 "surface_smooth_current_vertex",
2601 0.5f,
2602 0.0f,
2603 1.0f,
2604 "Per Vertex Displacement",
2605 "How much the position of each individual vertex influences the final result",
2606 0.0f,
2607 1.0f);
2609 "sharpen_smooth_ratio",
2610 0.35f,
2611 0.0f,
2612 1.0f,
2613 "Smooth Ratio",
2614 "How much smoothing is applied to polished surfaces",
2615 0.0f,
2616 1.0f);
2617
2619 "sharpen_intensify_detail_strength",
2620 0.0f,
2621 0.0f,
2622 10.0f,
2623 "Intensify Details",
2624 "How much creases and valleys are intensified",
2625 0.0f,
2626 1.0f);
2627
2629 "sharpen_curvature_smooth_iterations",
2630 0,
2631 0,
2632 10,
2633 "Curvature Smooth Iterations",
2634 "How much smooth the resulting shape is, ignoring high frequency details",
2635 0,
2636 10);
2637}
2638
2639} // namespace blender::ed::sculpt_paint::filter
float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1133
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1075
bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
Definition brush.cc:1083
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:341
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:654
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2601
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:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_NOINLINE
BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
Definition BLI_hash.h:55
MINLINE float pow2f(float x)
void mul_m3_v3(const float M[3][3], float r[3])
void scale_m3_fl(float R[3][3], float scale)
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_OPERATOR_DEFAULT
#define IFACE_(msgid)
@ CD_PROP_INT32
#define UI_SCALE_FAC
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:966
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a vector
#define RNA_BEGIN(sptr, itemptr, propname)
#define RNA_END
PropertyFlag
Definition RNA_types.hh:201
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_HIDDEN
Definition RNA_types.hh:239
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
#define UI_ITEM_NONE
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_EXPAND
@ OPTYPE_BLOCKING
Definition WM_types.hh:164
@ OPTYPE_DEPENDS_ON_CURSOR
Definition WM_types.hh:198
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
@ OPTYPE_GRAB_CURSOR_X
Definition WM_types.hh:170
#define BM_elem_index_get(ele)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
#define BM_VERT
static unsigned long seed
Definition btSoftBody.h:39
AttributeSet attributes
void item(std::string text, int icon1, int icon2=0)
Definition area.cc:908
Span< T > as_span() const
Definition BLI_array.hh:232
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr Span< T > as_span() const
Definition BLI_span.hh:662
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:726
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
void resize(const int64_t new_size)
void tag_positions_changed(const IndexMask &node_mask)
Definition pbvh.cc:549
Span< NodeT > nodes() const
void deform(MutableSpan< float3 > translations, Span< int > verts) const
Definition sculpt.cc:7139
void foreach_index(Fn &&fn) const
const Depsgraph * depsgraph
int len
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static float verts[][3]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
IndexMask search_nodes(const Tree &pbvh, IndexMaskMemory &memory, FunctionRef< bool(const Node &)> filter_fn)
Definition pbvh.cc:2647
void update_normals(const Depsgraph &depsgraph, Object &object_orig, Tree &pbvh)
Definition pbvh.cc:1058
void update_bounds(const Depsgraph &depsgraph, const Object &object, Tree &pbvh)
Definition pbvh.cc:1183
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2502
void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, const bke::pbvh::GridsNode &node, Span< int > grids, MutableSpan< float > factors)
std::unique_ptr< Cache > cache_init(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob)
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br)
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, const bke::pbvh::MeshNode &node, Span< int > verts, MutableSpan< float > factors)
void ensure_boundary_info(Object &object)
Definition sculpt.cc:5770
static BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
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 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)
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)
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 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 int sculpt_mesh_filter_start(bContext *C, wmOperator *op)
static void sculpt_mesh_filter_cancel(bContext *C, wmOperator *)
static EnumPropertyItem prop_mesh_filter_orientation_items[]
static int sculpt_mesh_filter_exec(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)
void SCULPT_OT_mesh_filter(wmOperatorType *ot)
static bool sculpt_mesh_filter_needs_pmap(MeshFilterType filter_type)
static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
static EnumPropertyItem prop_mesh_filter_deform_axis_items[]
static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static BLI_NOINLINE void randomize_factors(const Span< float3 > positions, const int seed, const MutableSpan< float > factors)
static void sculpt_mesh_update_status_bar(bContext *C, wmOperator *)
static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op)
void register_operator_props(wmOperatorType *ot)
static int sculpt_mesh_filter_confirm(SculptSession &ss, wmOperator *op, const MeshFilterType filter_type)
static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, const IndexMask &node_mask)
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, Vector< Vector< SubdivCCGCoord > > &neighbors, const MutableSpan< float3 > translations)
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 Span< Vector< int > > vert_neighbors, const MutableSpan< T > dst)
void neighbor_position_average_interior_bmesh(const Set< BMVert *, 0 > &verts, const MutableSpan< float3 > new_positions)
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, Vector< Vector< int > > &neighbors, 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, Vector< Vector< BMVert * > > &neighbors, const MutableSpan< float3 > translations)
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 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:1014
void push_begin(const Scene &scene, Object &ob, const wmOperator *op)
void push_end_ex(Object &ob, const bool use_nested_undo)
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:2326
void scatter_data_bmesh(Span< T > node_data, const Set< BMVert *, 0 > &verts, MutableSpan< T > dst)
Definition sculpt.cc:6148
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6054
void gather_data_grids(const SubdivCCG &subdiv_ccg, Span< T > src, Span< int > grids, MutableSpan< T > node_data)
Definition sculpt.cc:6092
void 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, MutableSpan< Vector< int > > result)
Definition sculpt.cc:7385
bool node_fully_masked_or_hidden(const bke::pbvh::Node &node)
Definition sculpt.cc:2315
void gather_data_bmesh(Span< T > src, const Set< BMVert *, 0 > &verts, MutableSpan< T > node_data)
Definition sculpt.cc:6108
void flush_update_done(const bContext *C, Object &ob, UpdateType update_type)
Definition sculpt.cc:5055
void reset_translations_to_original(MutableSpan< float3 > translations, Span< float3 > positions, Span< float3 > orig_positions)
Definition sculpt.cc:6946
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:7210
void flush_update_step(bContext *C, UpdateType update_type)
Definition sculpt.cc:4960
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:7227
void translations_from_new_positions(Span< float3 > new_positions, Span< int > verts, Span< float3 > old_positions, MutableSpan< float3 > translations)
Definition sculpt.cc:7257
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7022
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6122
std::optional< float3 > calc_area_normal(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, const IndexMask &node_mask)
Definition sculpt.cc:1848
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6958
OrigPositionData orig_position_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, Vector< BMVert *, 64 > &r_neighbors)
Definition sculpt.cc:389
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6082
void calc_vert_neighbors(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, Span< bool > hide_poly, Span< int > verts, MutableSpan< Vector< int > > result)
Definition sculpt.cc:7330
OrigPositionData orig_position_data_get_grids(const Object &object, const bke::pbvh::GridsNode &node)
void scatter_data_grids(const SubdivCCG &subdiv_ccg, Span< T > node_data, Span< int > grids, MutableSpan< T > dst)
Definition sculpt.cc:6132
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:95
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
#define hash
Definition noise.c: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_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mval[2], bool use_sampled_normal)
Definition sculpt.cc:4580
bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mval[2], bool force_original)
Definition sculpt.cc:4732
void SCULPT_vertex_random_access_ensure(Object &object)
Definition sculpt.cc:144
bool SCULPT_mode_poll(bContext *C)
Definition sculpt.cc:3560
int SCULPT_vertex_count_get(const Object &object)
Definition sculpt.cc:153
#define min(a, b)
Definition sort.c:32
CustomData pdata
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]
blender::float3 last_normal
Definition BKE_paint.hh:511
BMLog * bm_log
Definition BKE_paint.hh:402
blender::ed::sculpt_paint::filter::Cache * filter_cache
Definition BKE_paint.hh:428
SculptVertexInfo vertex_info
Definition BKE_paint.hh:458
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::BitVector boundary
Definition BKE_paint.hh:351
blender::Vector< SubdivCCGCoord, 256 > coords
blender::Array< blender::float3 > positions
RegionView3D * rv3d
Definition ED_view3d.hh:76
const c_style_mat & ptr() const
std::unique_ptr< auto_mask::Cache > automasking
short val
Definition WM_types.hh:724
int xy[2]
Definition WM_types.hh:726
int mval[2]
Definition WM_types.hh:728
int prev_press_xy[2]
Definition WM_types.hh:795
short type
Definition WM_types.hh:722
const void * modal_items
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
ccl_device_inline float beta(float x, float y)
Definition util/math.h:833
void WM_cursor_modal_set(wmWindow *win, int val)
void WM_cursor_modal_restore(wmWindow *win)
@ WM_CURSOR_EW_SCROLL
Definition wm_cursors.hh:53
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:4125
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:933
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:960