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);
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
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()) {
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());
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());
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,
1718 ss.filter_cache->detail_directions.as_span(),
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();
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(
1845 ss.filter_cache->detail_directions.as_span(), verts, tls.translations);
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(
1902 ss.filter_cache->detail_directions.as_span(), verts, tls.translations);
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
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) {
2160 calc_smooth_filter(depsgraph, sd, strength, ob, node_mask);
2161 break;
2163 calc_scale_filter(depsgraph, sd, strength, ob, node_mask);
2164 break;
2166 calc_inflate_filter(depsgraph, sd, strength, ob, node_mask);
2167 break;
2169 calc_sphere_filter(depsgraph, sd, strength, ob, node_mask);
2170 break;
2172 calc_random_filter(depsgraph, sd, strength, ob, node_mask);
2173 break;
2175 calc_relax_filter(depsgraph, sd, strength, ob, node_mask);
2176 break;
2178 calc_relax_face_sets_filter(depsgraph, sd, strength, ob, node_mask);
2179 break;
2181 calc_surface_smooth_filter(depsgraph, sd, strength, ob, node_mask);
2182 break;
2184 calc_sharpen_filter(depsgraph, sd, strength, ob, node_mask);
2185 break;
2187 calc_enhance_details_filter(depsgraph, sd, strength, ob, node_mask);
2188 break;
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
2285{
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) {
2363 RNA_float_get(op->ptr, "surface_smooth_shape_preservation"),
2364 RNA_float_get(op->ptr, "surface_smooth_current_vertex"));
2365 break;
2366 }
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 }
2377 ss.filter_cache->detail_directions.reinitialize(SCULPT_vertex_count_get(object));
2380 break;
2381 }
2383 ss.filter_cache->limit_surface_co.reinitialize(SCULPT_vertex_count_get(object));
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);
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
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
2498
2499 return OPERATOR_FINISHED;
2500 }
2501
2502 return ret;
2503}
2504
2506{
2508 ot->srna, "start_mouse", 2, nullptr, 0, 1 << 14, "Starting Mouse", "", 0, 1 << 14);
2509
2510 RNA_def_float(ot->srna,
2511 "area_normal_radius",
2512 0.25,
2513 0.001,
2514 5.0,
2515 "Normal Radius",
2516 "Radius used for calculating area normal on initial click,\nin percentage "
2517 "of brush radius",
2518 0.01,
2519 1.0);
2521 ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
2522 RNA_def_int(ot->srna,
2523 "iteration_count",
2524 1,
2525 1,
2526 10000,
2527 "Repeat",
2528 "How many times to repeat the filter",
2529 1,
2530 100);
2531
2532 /* Smooth filter requires entire event history. */
2534 ot->srna, "event_history", &RNA_OperatorStrokeElement, "", "");
2536}
2537
2538static void sculpt_mesh_ui_exec(bContext * /*C*/, wmOperator *op)
2539{
2540 uiLayout *layout = op->layout;
2541
2542 uiItemR(layout, op->ptr, "strength", UI_ITEM_NONE, nullptr, ICON_NONE);
2543 uiItemR(layout, op->ptr, "iteration_count", UI_ITEM_NONE, nullptr, ICON_NONE);
2544 uiItemR(layout, op->ptr, "orientation", UI_ITEM_NONE, nullptr, ICON_NONE);
2545 layout = uiLayoutRow(layout, true);
2546 uiItemR(layout, op->ptr, "deform_axis", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
2547}
2548
2550{
2551 ot->name = "Filter Mesh";
2552 ot->idname = "SCULPT_OT_mesh_filter";
2553 ot->description = "Applies a filter to modify the current mesh";
2554
2555 ot->invoke = sculpt_mesh_filter_invoke;
2557 ot->poll = SCULPT_mode_poll;
2559 ot->ui = sculpt_mesh_ui_exec;
2560
2561 /* Doesn't seem to actually be called?
2562 * Check `sculpt_mesh_filter_modal` to see where it's really called. */
2563 ot->cancel = sculpt_mesh_filter_cancel;
2564
2567
2569
2570 ot->prop = RNA_def_enum(ot->srna,
2571 "type",
2574 "Filter Type",
2575 "Operation that is going to be applied to the mesh");
2577 RNA_def_enum_flag(ot->srna,
2578 "deform_axis",
2581 "Deform Axis",
2582 "Apply the deformation in the selected axis");
2583 RNA_def_enum(ot->srna,
2584 "orientation",
2587 "Orientation",
2588 "Orientation of the axis to limit the filter displacement");
2589
2590 /* Surface Smooth Mesh Filter properties. */
2591 RNA_def_float(ot->srna,
2592 "surface_smooth_shape_preservation",
2593 0.5f,
2594 0.0f,
2595 1.0f,
2596 "Shape Preservation",
2597 "How much of the original shape is preserved when smoothing",
2598 0.0f,
2599 1.0f);
2600 RNA_def_float(ot->srna,
2601 "surface_smooth_current_vertex",
2602 0.5f,
2603 0.0f,
2604 1.0f,
2605 "Per Vertex Displacement",
2606 "How much the position of each individual vertex influences the final result",
2607 0.0f,
2608 1.0f);
2609 RNA_def_float(ot->srna,
2610 "sharpen_smooth_ratio",
2611 0.35f,
2612 0.0f,
2613 1.0f,
2614 "Smooth Ratio",
2615 "How much smoothing is applied to polished surfaces",
2616 0.0f,
2617 1.0f);
2618
2619 RNA_def_float(ot->srna,
2620 "sharpen_intensify_detail_strength",
2621 0.0f,
2622 0.0f,
2623 10.0f,
2624 "Intensify Details",
2625 "How much creases and valleys are intensified",
2626 0.0f,
2627 1.0f);
2628
2629 RNA_def_int(ot->srna,
2630 "sharpen_curvature_smooth_iterations",
2631 0,
2632 0,
2633 10,
2634 "Curvature Smooth Iterations",
2635 "How much smooth the resulting shape is, ignoring high frequency details",
2636 0,
2637 10);
2638}
2639
2640} // 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.
#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
#define C
Definition RandGen.cpp:29
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
BPy_StructRNA * depsgraph
static unsigned long seed
Definition btSoftBody.h:39
Span< T > as_span() const
Definition BLI_array.hh:232
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
AttributeSet attributes
void resize(const int64_t new_size)
void item(std::string text, int icon1, int icon2=0)
Definition area.cc:908
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
GAttributeReader lookup(const StringRef attribute_id) const
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:7159
void foreach_index(Fn &&fn) const
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]
static char faces[256]
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:5784
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)
wmKeyMap * modal_keymap(wmKeyConfig *keyconf)
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:6162
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6068
void gather_data_grids(const SubdivCCG &subdiv_ccg, Span< T > src, Span< int > grids, MutableSpan< T > node_data)
Definition sculpt.cc:6106
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:7405
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:6122
void flush_update_done(const bContext *C, Object &ob, UpdateType update_type)
Definition sculpt.cc:5069
void reset_translations_to_original(MutableSpan< float3 > translations, Span< float3 > positions, Span< float3 > orig_positions)
Definition sculpt.cc:6966
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:7230
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:7247
void translations_from_new_positions(Span< float3 > new_positions, Span< int > verts, Span< float3 > old_positions, MutableSpan< float3 > translations)
Definition sculpt.cc:7277
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7042
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6136
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:6978
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:6096
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:7350
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:6146
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
VecBase< float, 2 > float2
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
int grid_size
Definition BKE_ccg.hh:33
int grid_area
Definition BKE_ccg.hh:35
ObjectRuntimeHandle * runtime
struct SculptSession * sculpt
float viewmat[4][4]
float viewinv[4][4]
struct ToolSettings * toolsettings
blender::float3 last_normal
Definition BKE_paint.hh: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
int to_index(const CCGKey &key) const
blender::Vector< SubdivCCGCoord, 256 > coords
blender::Array< blender::float3 > positions
struct UnifiedPaintSettings unified_paint_settings
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
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
float max
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