Blender V5.0
relax.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "DNA_brush_types.h"
8#include "DNA_mesh_types.h"
9
10#include "BKE_subdiv_ccg.hh"
11
13#include "BLI_task.hh"
14
21
22#include "bmesh.hh"
23
25
26inline namespace relax_cc {
27
28/* -------------------------------------------------------------------- */
31
36
41
46
47static void apply_positions_faces(const Sculpt &sd,
48 const Span<int> verts,
49 Object &object,
50 const MutableSpan<float3> translations,
51 const PositionDeformData &position_data)
52{
53 SculptSession &ss = *object.sculpt;
54 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
55 position_data.deform(translations, verts);
56}
57
58static void apply_positions_grids(const Sculpt &sd,
59 const Span<int> grids,
60 Object &object,
61 const Span<float3> positions,
62 const MutableSpan<float3> translations)
63{
64 SculptSession &ss = *object.sculpt;
65 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
66
67 clip_and_lock_translations(sd, ss, positions, translations);
68 apply_translations(translations, grids, subdiv_ccg);
69}
70
71static void apply_positions_bmesh(const Sculpt &sd,
73 Object &object,
74 const MutableSpan<float3> translations,
75 const Span<float3> positions)
76
77{
78 SculptSession &ss = *object.sculpt;
79
80 clip_and_lock_translations(sd, ss, positions, translations);
81 apply_translations(translations, verts);
82}
83
85
86/* -------------------------------------------------------------------- */
89
90static std::array<float, 4> iteration_strengths(const float strength, const int stroke_iteration)
91{
92 if (stroke_iteration % 3 == 0) {
93 return {strength, strength, strength, strength};
94 }
95
96 /* This operation needs a strength tweak as the relax deformation is too weak by default.
97 * We cap the strength at 1.0 to avoid ripping the mesh in cases where this modified value is
98 * too strong. */
99 const float modified_strength = std::min(strength * 1.5f, 1.0f);
100 return {modified_strength, modified_strength, strength, strength};
101}
102
103BLI_NOINLINE static void calc_factors_faces(const Depsgraph &depsgraph,
104 const Brush &brush,
105 const Span<float3> positions_eval,
106 const Span<float3> vert_normals,
107 const GroupedSpan<int> vert_to_face_map,
108 const MeshAttributeData &attribute_data,
109 const float strength,
110 const bool relax_face_sets,
111 const Object &object,
112 const bke::pbvh::MeshNode &node,
113 MeshLocalData &tls,
114 const MutableSpan<float> factors)
115{
116 const SculptSession &ss = *object.sculpt;
117 const StrokeCache &cache = *ss.cache;
118
119 const Span<int> verts = node.verts();
120
121 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
122 filter_region_clip_factors(ss, positions_eval, verts, factors);
123 if (brush.flag & BRUSH_FRONTFACE) {
124 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
125 }
126
127 tls.distances.resize(verts.size());
128 const MutableSpan<float> distances = tls.distances;
130 ss, positions_eval, verts, eBrushFalloffShape(brush.falloff_shape), distances);
131 filter_distances_with_radius(cache.radius, distances, factors);
132 apply_hardness_to_distances(cache, distances);
133 calc_brush_strength_factors(cache, brush, distances, factors);
134
135 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
136
137 scale_factors(factors, strength);
138
139 calc_brush_texture_factors(ss, brush, positions_eval, verts, factors);
140
142 vert_to_face_map, attribute_data.face_sets, relax_face_sets, verts, factors);
143}
144
145static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph,
146 const Sculpt &sd,
147 const Brush &brush,
148 Object &object,
149 const IndexMask &node_mask,
150 const float strength,
151 const bool relax_face_sets)
152{
153 const SculptSession &ss = *object.sculpt;
154 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
156 Mesh &mesh = *static_cast<Mesh *>(object.data);
157 const OffsetIndices faces = mesh.faces();
158 const Span<int> corner_verts = mesh.corner_verts();
159 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
160 const MeshAttributeData attribute_data(mesh);
161
162 const PositionDeformData position_data(depsgraph, object);
163 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
164
165 Array<int> node_offset_data;
166 const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
167 nodes, node_mask, node_offset_data);
168
169 Array<float3> translations(node_vert_offsets.total_size());
170 Array<float> factors(node_vert_offsets.total_size());
171
173 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
174 MeshLocalData &tls = all_tls.local();
176 brush,
177 position_data.eval,
178 vert_normals,
179 vert_to_face_map,
180 attribute_data,
181 strength,
182 relax_face_sets,
183 object,
184 nodes[i],
185 tls,
186 factors.as_mutable_span().slice(node_vert_offsets[pos]));
187 });
188
189 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
191 position_data.eval,
192 vert_normals,
193 faces,
194 corner_verts,
195 vert_to_face_map,
197 attribute_data.face_sets,
198 attribute_data.hide_poly,
199 relax_face_sets,
200 nodes[i].verts(),
201 factors.as_span().slice(node_vert_offsets[pos]),
202 translations.as_mutable_span().slice(node_vert_offsets[pos]));
203 });
204
205 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
207 nodes[i].verts(),
208 object,
209 translations.as_mutable_span().slice(node_vert_offsets[pos]),
210 position_data);
211 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
212 });
213 pbvh.tag_positions_changed(node_mask);
215}
216
217BLI_NOINLINE static void calc_factors_grids(const Depsgraph &depsgraph,
218 const Brush &brush,
220 const Span<int> corner_verts,
221 const GroupedSpan<int> vert_to_face_map,
222 const Span<int> face_sets,
223 const bke::pbvh::GridsNode &node,
224 const float strength,
225 const bool relax_face_sets,
226 Object &object,
227 GridLocalData &tls,
228 const MutableSpan<float3> positions,
229 const MutableSpan<float> factors)
230{
231 SculptSession &ss = *object.sculpt;
232 const StrokeCache &cache = *ss.cache;
233 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
234 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
235
236 const Span<int> grids = node.grids();
237 const int grid_verts_num = grids.size() * key.grid_area;
238
239 gather_data_grids(subdiv_ccg, subdiv_ccg.positions.as_span(), grids, positions);
240
241 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
242 filter_region_clip_factors(ss, positions, factors);
243 if (brush.flag & BRUSH_FRONTFACE) {
244 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
245 }
246
247 tls.distances.resize(grid_verts_num);
248 const MutableSpan<float> distances = tls.distances;
249 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
250 filter_distances_with_radius(cache.radius, distances, factors);
251 apply_hardness_to_distances(cache, distances);
252 calc_brush_strength_factors(cache, brush, distances, factors);
253
254 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
255
256 scale_factors(factors, strength);
257
258 calc_brush_texture_factors(ss, brush, positions, factors);
259
261 corner_verts,
262 vert_to_face_map,
263 face_sets,
264 subdiv_ccg,
265 relax_face_sets,
266 grids,
267 factors);
268}
269
270static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph,
271 const Sculpt &sd,
272 const Brush &brush,
273 Object &object,
274 const IndexMask &node_mask,
275 const float strength,
276 const bool relax_face_sets)
277{
278 const SculptSession &ss = *object.sculpt;
279 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
281 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
282 MutableSpan<float3> positions = subdiv_ccg.positions;
283 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
284
285 Mesh &mesh = *static_cast<Mesh *>(object.data);
286 const OffsetIndices faces = mesh.faces();
287 const Span<int> corner_verts = mesh.corner_verts();
288 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
289 const bke::AttributeAccessor attributes = mesh.attributes();
290 const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
291 const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
292
293 Array<int> node_offset_data;
294 const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
295 key, nodes, node_mask, node_offset_data);
296
297 Array<float3> current_positions(node_vert_offsets.total_size());
298 Array<float3> translations(node_vert_offsets.total_size());
299 Array<float> factors(node_vert_offsets.total_size());
300
302 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
303 GridLocalData &tls = all_tls.local();
305 brush,
306 faces,
307 corner_verts,
308 vert_to_face_map,
309 face_sets,
310 nodes[i],
311 strength,
312 relax_face_sets,
313 object,
314 tls,
315 current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
316 factors.as_mutable_span().slice(node_vert_offsets[pos]));
317 });
318
319 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
321 subdiv_ccg,
322 faces,
323 corner_verts,
324 face_sets,
325 vert_to_face_map,
327 nodes[i].grids(),
328 relax_face_sets,
329 factors.as_span().slice(node_vert_offsets[pos]),
330 translations.as_mutable_span().slice(node_vert_offsets[pos]));
331 });
332
333 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
335 nodes[i].grids(),
336 object,
337 current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
338 translations.as_mutable_span().slice(node_vert_offsets[pos]));
339 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
340 });
341 pbvh.tag_positions_changed(node_mask);
343}
344
345static void calc_factors_bmesh(const Depsgraph &depsgraph,
346 Object &object,
347 const Brush &brush,
348 const int face_set_offset,
350 const float strength,
351 const bool relax_face_sets,
352 BMeshLocalData &tls,
353 MutableSpan<float3> positions,
354 MutableSpan<float> factors)
355{
356 SculptSession &ss = *object.sculpt;
357 const StrokeCache &cache = *ss.cache;
358
360
361 gather_bmesh_positions(verts, positions);
362
364 filter_region_clip_factors(ss, positions, factors);
365 if (brush.flag & BRUSH_FRONTFACE) {
366 calc_front_face(cache.view_normal_symm, verts, factors);
367 }
368
369 tls.distances.resize(verts.size());
370 const MutableSpan<float> distances = tls.distances;
371 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
372 filter_distances_with_radius(cache.radius, distances, factors);
373 apply_hardness_to_distances(cache, distances);
374 calc_brush_strength_factors(cache, brush, distances, factors);
375
376 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
377
378 scale_factors(factors, strength);
379
380 calc_brush_texture_factors(ss, brush, positions, factors);
382 face_set_offset, relax_face_sets, verts, factors);
383}
384
385static void do_relax_face_sets_brush_bmesh(const Depsgraph &depsgraph,
386 const Sculpt &sd,
387 const Brush &brush,
388 Object &object,
389 const IndexMask &node_mask,
390 const float strength,
391 const bool relax_face_sets)
392{
393 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
395 Array<int> node_offset_data;
396 const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets_bmesh(
397 nodes, node_mask, node_offset_data);
398
399 const int face_set_offset = CustomData_get_offset_named(
400 &object.sculpt->bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
401
402 Array<float3> current_positions(node_vert_offsets.total_size());
403 Array<float3> translations(node_vert_offsets.total_size());
404 Array<float> factors(node_vert_offsets.total_size());
405
407 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
408 BMeshLocalData &tls = all_tls.local();
410 object,
411 brush,
412 face_set_offset,
413 nodes[i],
414 strength,
415 relax_face_sets,
416 tls,
417 current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
418 factors.as_mutable_span().slice(node_vert_offsets[pos]));
419 });
420
421 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
424 current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
425 face_set_offset,
426 relax_face_sets,
427 factors.as_span().slice(node_vert_offsets[pos]),
428 translations.as_mutable_span().slice(node_vert_offsets[pos]));
429 });
430
431 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
434 object,
435 translations.as_mutable_span().slice(node_vert_offsets[pos]),
436 current_positions.as_span().slice(node_vert_offsets[pos]));
438 });
439 pbvh.tag_positions_changed(node_mask);
441}
442
444
445/* -------------------------------------------------------------------- */
449 const Brush &brush,
450 const float strength,
451 const Object &object,
452 const MeshAttributeData &attribute_data,
453 const bke::pbvh::MeshNode &node,
454 MeshLocalData &tls,
455 const MutableSpan<float> factors)
456{
457 SculptSession &ss = *object.sculpt;
458 const StrokeCache &cache = *ss.cache;
459
460 const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
461 const Span<int> verts = node.verts();
462
463 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
464 filter_region_clip_factors(ss, orig_data.positions, factors);
465 if (brush.flag & BRUSH_FRONTFACE) {
466 calc_front_face(cache.view_normal_symm, orig_data.normals, factors);
467 }
468
469 tls.distances.resize(verts.size());
470 const MutableSpan<float> distances = tls.distances;
472 ss, orig_data.positions, eBrushFalloffShape(brush.falloff_shape), distances);
473 filter_distances_with_radius(cache.radius, distances, factors);
474 apply_hardness_to_distances(cache, distances);
475 calc_brush_strength_factors(cache, brush, distances, factors);
476
477 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
478
479 scale_factors(factors, strength);
480
481 calc_brush_texture_factors(ss, brush, orig_data.positions, factors);
482}
483
484static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph,
485 const Sculpt &sd,
486 const Brush &brush,
487 Object &object,
488 const IndexMask &node_mask,
489 const float strength)
490{
491 const SculptSession &ss = *object.sculpt;
492 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
494 Mesh &mesh = *static_cast<Mesh *>(object.data);
495 const OffsetIndices faces = mesh.faces();
496 const Span<int> corner_verts = mesh.corner_verts();
497 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
498 const MeshAttributeData attribute_data(mesh);
499 const PositionDeformData position_data(depsgraph, object);
500 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
501
502 Array<int> node_offset_data;
503 const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
504 nodes, node_mask, node_offset_data);
505
506 Array<float3> translations(node_vert_offsets.total_size());
507 Array<float> factors(node_vert_offsets.total_size());
508
510 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
511 MeshLocalData &tls = all_tls.local();
513 brush,
514 strength,
515 object,
516 attribute_data,
517 nodes[i],
518 tls,
519 factors.as_mutable_span().slice(node_vert_offsets[pos]));
520 });
521
522 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
524 position_data.eval,
525 vert_normals,
526 faces,
527 corner_verts,
528 vert_to_face_map,
530 attribute_data.face_sets,
531 attribute_data.hide_poly,
532 false,
533 nodes[i].verts(),
534 factors.as_span().slice(node_vert_offsets[pos]),
535 translations.as_mutable_span().slice(node_vert_offsets[pos]));
536 });
537
538 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
540 nodes[i].verts(),
541 object,
542 translations.as_mutable_span().slice(node_vert_offsets[pos]),
543 position_data);
544 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
545 });
546 pbvh.tag_positions_changed(node_mask);
548}
549
551 const Brush &brush,
552 const float strength,
553 const Object &object,
554 const bke::pbvh::GridsNode &node,
555 GridLocalData &tls,
556 const MutableSpan<float3> positions,
557 const MutableSpan<float> factors)
558{
559 const SculptSession &ss = *object.sculpt;
560 const StrokeCache &cache = *ss.cache;
561 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
562 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
563
564 const Span<int> grids = node.grids();
565 const int grid_verts_num = grids.size() * key.grid_area;
566
567 gather_data_grids(subdiv_ccg, subdiv_ccg.positions.as_span(), grids, positions);
568 const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
569
570 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
571 filter_region_clip_factors(ss, orig_data.positions, factors);
572 if (brush.flag & BRUSH_FRONTFACE) {
573 calc_front_face(cache.view_normal_symm, orig_data.normals, factors);
574 }
575
576 tls.distances.resize(grid_verts_num);
577 const MutableSpan<float> distances = tls.distances;
579 ss, orig_data.positions, eBrushFalloffShape(brush.falloff_shape), distances);
580 filter_distances_with_radius(cache.radius, distances, factors);
581 apply_hardness_to_distances(cache, distances);
582 calc_brush_strength_factors(cache, brush, distances, factors);
583
584 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
585
586 scale_factors(factors, strength);
587
588 calc_brush_texture_factors(ss, brush, orig_data.positions, factors);
589}
590
591static void do_topology_relax_brush_grids(const Depsgraph &depsgraph,
592 const Sculpt &sd,
593 const Brush &brush,
594 Object &object,
595 const IndexMask &node_mask,
596 const float strength)
597{
598 const SculptSession &ss = *object.sculpt;
599 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
601 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
602 MutableSpan<float3> positions = subdiv_ccg.positions;
603 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
604
605 Mesh &mesh = *static_cast<Mesh *>(object.data);
606 const OffsetIndices faces = mesh.faces();
607 const Span<int> corner_verts = mesh.corner_verts();
608 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
609 const bke::AttributeAccessor attributes = mesh.attributes();
610 const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
611 const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
612
613 Array<int> node_offset_data;
614 const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets(
615 key, nodes, node_mask, node_offset_data);
616
617 Array<float3> current_positions(node_vert_offsets.total_size());
618 Array<float3> translations(node_vert_offsets.total_size());
619 Array<float> factors(node_vert_offsets.total_size());
620
622 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
623 GridLocalData &tls = all_tls.local();
625 depsgraph,
626 brush,
627 strength,
628 object,
629 nodes[i],
630 tls,
631 current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
632 factors.as_mutable_span().slice(node_vert_offsets[pos]));
633 });
634
635 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
637 subdiv_ccg,
638 faces,
639 corner_verts,
640 face_sets,
641 vert_to_face_map,
643 nodes[i].grids(),
644 false,
645 factors.as_span().slice(node_vert_offsets[pos]),
646 translations.as_mutable_span().slice(node_vert_offsets[pos]));
647 });
648
649 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
651 nodes[i].grids(),
652 object,
653 current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
654 translations.as_mutable_span().slice(node_vert_offsets[pos]));
655 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
656 });
657 pbvh.tag_positions_changed(node_mask);
659}
660
661static void calc_topology_relax_factors_bmesh(const Depsgraph &depsgraph,
662 Object &object,
663 const Brush &brush,
665 const float strength,
666 BMeshLocalData &tls,
667 MutableSpan<float3> positions,
668 MutableSpan<float> factors)
669{
670 SculptSession &ss = *object.sculpt;
671 const StrokeCache &cache = *ss.cache;
672
674
675 Array<float3> orig_positions(verts.size());
676 Array<float3> orig_normals(verts.size());
677 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
678
679 gather_bmesh_positions(verts, positions);
680
682 filter_region_clip_factors(ss, orig_positions, factors);
683 if (brush.flag & BRUSH_FRONTFACE) {
684 calc_front_face(cache.view_normal_symm, orig_normals, factors);
685 }
686
687 tls.distances.resize(verts.size());
688 const MutableSpan<float> distances = tls.distances;
689 calc_brush_distances(ss, orig_positions, eBrushFalloffShape(brush.falloff_shape), distances);
690 filter_distances_with_radius(cache.radius, distances, factors);
691 apply_hardness_to_distances(cache, distances);
692 calc_brush_strength_factors(cache, brush, distances, factors);
693
694 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
695
696 scale_factors(factors, strength);
697
698 calc_brush_texture_factors(ss, brush, orig_positions, factors);
699}
700
701static void do_topology_relax_brush_bmesh(const Depsgraph &depsgraph,
702 const Sculpt &sd,
703 const Brush &brush,
704 Object &object,
705 const IndexMask &node_mask,
706 const float strength)
707{
708 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
710 const int face_set_offset = CustomData_get_offset_named(
711 &object.sculpt->bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
712
713 Array<int> node_offset_data;
714 const OffsetIndices<int> node_vert_offsets = create_node_vert_offsets_bmesh(
715 nodes, node_mask, node_offset_data);
716
717 Array<float3> current_positions(node_vert_offsets.total_size());
718 Array<float3> translations(node_vert_offsets.total_size());
719 Array<float> factors(node_vert_offsets.total_size());
720
722 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
723 BMeshLocalData &tls = all_tls.local();
725 depsgraph,
726 object,
727 brush,
728 nodes[i],
729 strength,
730 tls,
731 current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
732 factors.as_mutable_span().slice(node_vert_offsets[pos]));
733 });
734
735 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
738 current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
739 face_set_offset,
740 false,
741 factors.as_span().slice(node_vert_offsets[pos]),
742 translations.as_mutable_span().slice(node_vert_offsets[pos]));
743 });
744
745 node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
748 object,
749 translations.as_mutable_span().slice(node_vert_offsets[pos]),
750 current_positions.as_span().slice(node_vert_offsets[pos]));
752 });
753 pbvh.tag_positions_changed(node_mask);
755}
756
757
758} // namespace relax_cc
759
761 const Sculpt &sd,
762 Object &object,
763 const IndexMask &node_mask)
764{
765 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
766
768
769 const SculptSession &ss = *object.sculpt;
770 const std::array<float, 4> strengths = iteration_strengths(ss.cache->bstrength,
772
773 /* On every third step of the stroke, behave more similarly to the Topology Relax brush */
774 const bool relax_face_sets = !(ss.cache->iteration_count % 3 == 0);
775
776 for (const float strength : strengths) {
777 switch (bke::object::pbvh_get(object)->type()) {
780 depsgraph, sd, brush, object, node_mask, strength * strength, relax_face_sets);
781 break;
784 depsgraph, sd, brush, object, node_mask, strength * strength, relax_face_sets);
785 break;
788 depsgraph, sd, brush, object, node_mask, strength * strength, relax_face_sets);
789 break;
790 }
791 }
792}
793
794void do_topology_relax_brush(const Depsgraph &depsgraph,
795 const Sculpt &sd,
796 Object &object,
797 const IndexMask &node_mask)
798{
799 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
800 const SculptSession &ss = *object.sculpt;
801
803 return;
804 }
805
806 const float strength = ss.cache->bstrength;
807
809
810 for (int i = 0; i < 4; i++) {
811 switch (bke::object::pbvh_get(object)->type()) {
813 do_topology_relax_brush_mesh(depsgraph, sd, brush, object, node_mask, strength);
814 break;
816 do_topology_relax_brush_grids(depsgraph, sd, brush, object, node_mask, strength);
817 break;
819 do_topology_relax_brush_bmesh(depsgraph, sd, brush, object, node_mask, strength);
820 break;
821 }
822 }
823}
824} // namespace blender::ed::sculpt_paint::brushes
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:650
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)
#define BLI_NOINLINE
@ BRUSH_FRONTFACE
eBrushFalloffShape
@ CD_PROP_INT32
BPy_StructRNA * depsgraph
void resize(const int64_t new_size)
Span< T > as_span() const
Definition BLI_array.hh:243
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:248
constexpr int64_t size() const
Definition BLI_span.hh:252
GAttributeReader lookup(const StringRef attribute_id) const
void tag_positions_changed(const IndexMask &node_mask)
Definition pbvh.cc:635
Span< NodeT > nodes() const
void flush_bounds_to_parents()
Definition pbvh.cc:1306
void foreach_index(Fn &&fn) const
static float verts[][3]
uint pos
static char faces[256]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
void update_node_bounds_bmesh(BMeshNode &node)
Definition pbvh.cc:1294
void update_node_bounds_mesh(Span< float3 > positions, MeshNode &node)
Definition pbvh.cc:1274
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:1059
void update_node_bounds_grids(int grid_area, Span< float3 > positions, GridsNode &node)
Definition pbvh.cc:1283
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &automasking, const bke::pbvh::MeshNode &node, Span< int > verts, MutableSpan< float > factors)
void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache &automasking, const bke::pbvh::GridsNode &node, Span< int > grids, MutableSpan< float > factors)
void ensure_boundary_info(Object &object)
Definition sculpt.cc:6073
static BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
static BLI_NOINLINE void calc_topology_relax_factors_faces(const Depsgraph &depsgraph, const Brush &brush, const float strength, const Object &object, const MeshAttributeData &attribute_data, const bke::pbvh::MeshNode &node, MeshLocalData &tls, const MutableSpan< float > factors)
Definition relax.cc:448
static BLI_NOINLINE void calc_topology_relax_factors_grids(const Depsgraph &depsgraph, const Brush &brush, const float strength, const Object &object, const bke::pbvh::GridsNode &node, GridLocalData &tls, const MutableSpan< float3 > positions, const MutableSpan< float > factors)
Definition relax.cc:550
static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, const IndexMask &node_mask, const float strength)
Definition relax.cc:484
static void do_topology_relax_brush_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, const IndexMask &node_mask, const float strength)
Definition relax.cc:701
static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, const IndexMask &node_mask, const float strength, const bool relax_face_sets)
Definition relax.cc:270
static BLI_NOINLINE void calc_factors_faces(const Depsgraph &depsgraph, const Brush &brush, const Span< float3 > positions_eval, const Span< float3 > vert_normals, const GroupedSpan< int > vert_to_face_map, const MeshAttributeData &attribute_data, const float strength, const bool relax_face_sets, const Object &object, const bke::pbvh::MeshNode &node, MeshLocalData &tls, const MutableSpan< float > factors)
Definition relax.cc:103
static void apply_positions_grids(const Sculpt &sd, const Span< int > grids, Object &object, const Span< float3 > positions, const MutableSpan< float3 > translations)
Definition relax.cc:58
static void calc_topology_relax_factors_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, bke::pbvh::BMeshNode &node, const float strength, BMeshLocalData &tls, MutableSpan< float3 > positions, MutableSpan< float > factors)
Definition relax.cc:661
static void calc_factors_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const int face_set_offset, bke::pbvh::BMeshNode &node, const float strength, const bool relax_face_sets, BMeshLocalData &tls, MutableSpan< float3 > positions, MutableSpan< float > factors)
Definition relax.cc:345
static BLI_NOINLINE void calc_factors_grids(const Depsgraph &depsgraph, const Brush &brush, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const bke::pbvh::GridsNode &node, const float strength, const bool relax_face_sets, Object &object, GridLocalData &tls, const MutableSpan< float3 > positions, const MutableSpan< float > factors)
Definition relax.cc:217
static std::array< float, 4 > iteration_strengths(const float strength, const int stroke_iteration)
Definition relax.cc:90
static void apply_positions_faces(const Sculpt &sd, const Span< int > verts, Object &object, const MutableSpan< float3 > translations, const PositionDeformData &position_data)
Definition relax.cc:47
static void do_topology_relax_brush_grids(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, const IndexMask &node_mask, const float strength)
Definition relax.cc:591
static void apply_positions_bmesh(const Sculpt &sd, const Set< BMVert *, 0 > verts, Object &object, const MutableSpan< float3 > translations, const Span< float3 > positions)
Definition relax.cc:71
static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, const IndexMask &node_mask, const float strength, const bool relax_face_sets)
Definition relax.cc:145
static void do_relax_face_sets_brush_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, const IndexMask &node_mask, const float strength, const bool relax_face_sets)
Definition relax.cc:385
void do_topology_relax_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition relax.cc:794
void do_relax_face_sets_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition relax.cc:760
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)
void calc_relaxed_translations_grids(const SubdivCCG &subdiv_ccg, const OffsetIndices< int > faces, const Span< int > corner_verts, const Span< int > face_sets, const GroupedSpan< int > vert_to_face_map, const BitSpan boundary_verts, const Span< int > grids, const bool filter_boundary_face_sets, const Span< float > factors, const MutableSpan< float3 > translations)
void calc_relaxed_translations_bmesh(const Set< BMVert *, 0 > &verts, const Span< float3 > positions, const int face_set_offset, const bool filter_boundary_face_sets, const Span< float > factors, const MutableSpan< float3 > translations)
void calc_relaxed_translations_faces(const Span< float3 > vert_positions, const Span< float3 > vert_normals, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const BitSpan boundary_verts, const Span< int > face_sets, const Span< bool > hide_poly, const bool filter_boundary_face_sets, const Span< int > verts, const Span< float > factors, const MutableSpan< float3 > translations)
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6367
void calc_brush_strength_factors(const StrokeCache &cache, const Brush &brush, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:7183
void gather_data_grids(const SubdivCCG &subdiv_ccg, Span< T > src, Span< int > grids, MutableSpan< T > node_data)
Definition sculpt.cc:6405
void apply_hardness_to_distances(float radius, float hardness, MutableSpan< float > distances)
Definition sculpt.cc:7156
void filter_distances_with_radius(float radius, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:7105
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6972
void orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7512
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7335
void calc_brush_distances(const SculptSession &ss, Span< float3 > vert_positions, Span< int > vert, eBrushFalloffShape falloff_shape, MutableSpan< float > r_distances)
Definition sculpt.cc:7055
OffsetIndices< int > create_node_vert_offsets(Span< bke::pbvh::MeshNode > nodes, const IndexMask &node_mask, Array< int > &node_data)
Definition sculpt.cc:7563
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:7268
OrigPositionData orig_position_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void calc_brush_texture_factors(const SculptSession &ss, const Brush &brush, Span< float3 > vert_positions, Span< int > vert, MutableSpan< float > factors)
Definition sculpt.cc:7195
OrigPositionData orig_position_data_get_grids(const Object &object, const bke::pbvh::GridsNode &node)
void calc_front_face(const float3 &view_normal, Span< float3 > normals, MutableSpan< float > factors)
Definition sculpt.cc:6914
OffsetIndices< int > create_node_vert_offsets_bmesh(Span< bke::pbvh::BMeshNode > nodes, const IndexMask &node_mask, Array< int > &node_data)
Definition sculpt.cc:7585
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(const blender::ed::sculpt_paint::StrokeCache &cache)
Definition sculpt.cc:542
char falloff_shape
int grid_area
Definition BKE_ccg.hh:35
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:417
BMLog * bm_log
Definition BKE_paint.hh:392
SculptVertexInfo vertex_info
Definition BKE_paint.hh:462
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
blender::BitVector boundary
Definition BKE_paint.hh:334
blender::Array< blender::float3 > positions
std::unique_ptr< auto_mask::Cache > automasking
i
Definition text_draw.cc:230