Blender V5.0
sculpt_pose.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
10#include "BLI_math_geom.h"
11#include "BLI_math_matrix.h"
12#include "BLI_math_matrix.hh"
13#include "BLI_math_rotation.h"
14#include "BLI_math_vector.h"
15#include "BLI_math_vector.hh"
16
17#include "DNA_brush_types.h"
18#include "DNA_object_types.h"
19
20#include "BKE_brush.hh"
21#include "BKE_ccg.hh"
22#include "BKE_colortools.hh"
23#include "BKE_mesh.hh"
24#include "BKE_paint.hh"
25#include "BKE_paint_bvh.hh"
26
27#include "mesh_brush_common.hh"
28#include "paint_intern.hh"
29#include "sculpt_automask.hh"
30#include "sculpt_cloth.hh"
31#include "sculpt_face_set.hh"
32#include "sculpt_flood_fill.hh"
33#include "sculpt_hide.hh"
34#include "sculpt_intern.hh"
35#include "sculpt_pose.hh"
36#include "sculpt_smooth.hh"
37
38#include "bmesh.hh"
39
40#include <cmath>
41
43
44static void solve_ik_chain(IKChain &ik_chain, const float3 &initial_target, const bool use_anchor)
45{
46 MutableSpan<IKChainSegment> segments = ik_chain.segments;
47
48 /* Set the initial target. */
49 float3 target = initial_target;
50
51 /* Solve the positions and rotations of all segments in the chain. */
52 for (const int i : segments.index_range()) {
53 /* Calculate the rotation to orientate the segment to the target from its initial state. */
54 float3 current_orientation = math::normalize(target - segments[i].orig);
55 float3 initial_orientation = math::normalize(segments[i].initial_head -
56 segments[i].initial_orig);
57 rotation_between_vecs_to_quat(segments[i].rot, initial_orientation, current_orientation);
58
59 /* Rotate the segment by calculating a new head position. */
60 float3 current_head_position = segments[i].orig + current_orientation * segments[i].len;
61
62 /* Move the origin of the segment towards the target. */
63 float3 current_origin_position = target - current_head_position;
64
65 /* Store the new head and origin positions to the segment. */
66 segments[i].head = current_head_position;
67 segments[i].orig += current_origin_position;
68
69 /* Use the origin of this segment as target for the next segment in the chain. */
70 target = segments[i].orig;
71 }
72
73 /* Move back the whole chain to preserve the anchor point. */
74 if (use_anchor) {
75 float3 anchor_diff = segments.last().initial_orig - segments.last().orig;
76 for (const int i : segments.index_range()) {
77 segments[i].orig += anchor_diff;
78 segments[i].head += anchor_diff;
79 }
80 }
81}
82
83static void solve_roll_chain(IKChain &ik_chain, const Brush &brush, const float roll)
84{
85 MutableSpan<IKChainSegment> segments = ik_chain.segments;
86
87 for (const int i : segments.index_range()) {
88 float3 initial_orientation = math::normalize(segments[i].initial_head -
89 segments[i].initial_orig);
90 float initial_rotation[4];
91 float current_rotation[4];
92
93 /* Calculate the current roll angle using the brush curve. */
94 float current_roll = roll * BKE_brush_curve_strength(&brush, i, segments.size());
95
96 axis_angle_normalized_to_quat(initial_rotation, initial_orientation, 0.0f);
97 axis_angle_normalized_to_quat(current_rotation, initial_orientation, current_roll);
98
99 /* Store the difference of the rotations in the segment rotation. */
100 rotation_between_quats_to_quat(segments[i].rot, current_rotation, initial_rotation);
101 }
102}
103
104static void solve_translate_chain(IKChain &ik_chain, const float delta[3])
105{
106 for (IKChainSegment &segment : ik_chain.segments) {
107 /* Move the origin and head of each segment by delta. */
108 add_v3_v3v3(segment.head, segment.initial_head, delta);
109 add_v3_v3v3(segment.orig, segment.initial_orig, delta);
110
111 /* Reset the segment rotation. */
112 unit_qt(segment.rot);
113 }
114}
115
116static void solve_scale_chain(IKChain &ik_chain, const float scale[3])
117{
118 for (IKChainSegment &segment : ik_chain.segments) {
119 /* Assign the scale to each segment. */
120 copy_v3_v3(segment.scale, scale);
121 }
122}
123
131
133 const IKChainSegment &segment,
134 const MutableSpan<float3> translations)
135{
136 BLI_assert(positions.size() == translations.size());
137 for (const int i : positions.index_range()) {
138 float3 position = positions[i];
139 const ePaintSymmetryAreas symm_area = SCULPT_get_vertex_symm_area(position);
140 position = math::transform_point(segment.pivot_mat_inv[int(symm_area)], position);
141 position = math::transform_point(segment.trans_mat[int(symm_area)], position);
142 position = math::transform_point(segment.pivot_mat[int(symm_area)], position);
143 translations[i] = position - positions[i];
144 }
145}
146
148{
149 BLI_assert(a.size() == b.size());
150 for (const int i : a.index_range()) {
151 a[i] += b[i];
152 }
153}
154
155static void calc_mesh(const Depsgraph &depsgraph,
156 const Sculpt &sd,
157 const Brush &brush,
158 const MeshAttributeData &attribute_data,
159 const bke::pbvh::MeshNode &node,
160 Object &object,
161 BrushLocalData &tls,
162 const PositionDeformData &position_data)
163{
164 SculptSession &ss = *object.sculpt;
165 const StrokeCache &cache = *ss.cache;
166
167 const Span<int> verts = node.verts();
168 const Span<float3> positions = gather_data_mesh(position_data.eval, verts, tls.positions);
169 const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
170
171 tls.factors.resize(verts.size());
172 const MutableSpan<float> factors = tls.factors;
173 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
174 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
175
176 tls.translations.resize(verts.size());
177 const MutableSpan<float3> translations = tls.translations;
178 translations.fill(float3(0));
179
180 tls.segment_weights.resize(verts.size());
181 tls.segment_translations.resize(verts.size());
182 const MutableSpan<float> segment_weights = tls.segment_weights;
183 const MutableSpan<float3> segment_translations = tls.segment_translations;
184
185 for (const IKChainSegment &segment : cache.pose_ik_chain->segments) {
186 calc_segment_translations(orig_data.positions, segment, segment_translations);
187 gather_data_mesh(segment.weights.as_span(), verts, segment_weights);
188 scale_translations(segment_translations, segment_weights);
189 add_arrays(translations, segment_translations);
190 }
191 scale_translations(translations, factors);
192
193 switch (eBrushDeformTarget(brush.deform_target)) {
195 reset_translations_to_original(translations, positions, orig_data.positions);
196 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
197 position_data.deform(translations, verts);
198 break;
200 add_arrays(translations, orig_data.positions);
202 translations.as_span(), verts, cache.cloth_sim->deformation_pos.as_mutable_span());
203 break;
204 }
205}
206
207static void calc_grids(const Depsgraph &depsgraph,
208 const Sculpt &sd,
209 const Brush &brush,
210 const bke::pbvh::GridsNode &node,
211 Object &object,
212 BrushLocalData &tls)
213{
214 SculptSession &ss = *object.sculpt;
215 const StrokeCache &cache = *ss.cache;
216 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
217
218 const Span<int> grids = node.grids();
219 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
220 const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
221
222 tls.factors.resize(positions.size());
223 const MutableSpan<float> factors = tls.factors;
224 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
225 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
226
227 tls.translations.resize(positions.size());
228 const MutableSpan<float3> translations = tls.translations;
229 translations.fill(float3(0));
230
231 tls.segment_weights.resize(positions.size());
232 tls.segment_translations.resize(positions.size());
233 const MutableSpan<float> segment_weights = tls.segment_weights;
234 const MutableSpan<float3> segment_translations = tls.segment_translations;
235
236 for (const IKChainSegment &segment : cache.pose_ik_chain->segments) {
237 calc_segment_translations(orig_data.positions, segment, segment_translations);
238 gather_data_grids(subdiv_ccg, segment.weights.as_span(), grids, segment_weights);
239 scale_translations(segment_translations, segment_weights);
240 add_arrays(translations, segment_translations);
241 }
242 scale_translations(translations, factors);
243
244 switch (eBrushDeformTarget(brush.deform_target)) {
246 reset_translations_to_original(translations, positions, orig_data.positions);
247 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
248 apply_translations(translations, grids, subdiv_ccg);
249 break;
251 add_arrays(translations, orig_data.positions);
252 scatter_data_grids(subdiv_ccg,
253 translations.as_span(),
254 grids,
255 cache.cloth_sim->deformation_pos.as_mutable_span());
256 break;
257 }
258}
259
260static void calc_bmesh(const Depsgraph &depsgraph,
261 const Sculpt &sd,
262 const Brush &brush,
264 Object &object,
265 BrushLocalData &tls)
266{
267 SculptSession &ss = *object.sculpt;
268 const StrokeCache &cache = *ss.cache;
269
271 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
272 Array<float3> orig_positions(verts.size());
273 Array<float3> orig_normals(verts.size());
274 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
275
276 tls.factors.resize(verts.size());
277 const MutableSpan<float> factors = tls.factors;
279 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
280
281 tls.translations.resize(verts.size());
282 const MutableSpan<float3> translations = tls.translations;
283 translations.fill(float3(0));
284
285 tls.segment_weights.resize(verts.size());
286 tls.segment_translations.resize(verts.size());
287 const MutableSpan<float> segment_weights = tls.segment_weights;
288 const MutableSpan<float3> segment_translations = tls.segment_translations;
289
290 for (const IKChainSegment &segment : cache.pose_ik_chain->segments) {
291 calc_segment_translations(orig_positions, segment, segment_translations);
292 gather_data_bmesh(segment.weights.as_span(), verts, segment_weights);
293 scale_translations(segment_translations, segment_weights);
294 add_arrays(translations, segment_translations);
295 }
296 scale_translations(translations, factors);
297
298 switch (eBrushDeformTarget(brush.deform_target)) {
300 reset_translations_to_original(translations, positions, orig_positions);
301 clip_and_lock_translations(sd, ss, orig_positions, translations);
302 apply_translations(translations, verts);
303 break;
305 add_arrays(translations, orig_positions);
307 translations.as_span(), verts, cache.cloth_sim->deformation_pos.as_mutable_span());
308 break;
309 }
310}
311
316 {
317 PoseGrowFactorData joined;
318 joined.pos_avg = a.pos_avg + b.pos_avg;
319 joined.pos_count = a.pos_count + b.pos_count;
320 return joined;
321 }
322};
323
330
331BLI_NOINLINE static void add_fake_neighbors(const Span<int> fake_neighbors,
332 const Span<int> verts,
333 const Span<int> orig_neighbor_data,
334 MutableSpan<int> neighbor_offsets,
335 Vector<int> &neighbor_data_with_fake)
336{
337 const OffsetIndices<int> offsets(neighbor_offsets);
338 for (const int i : verts.index_range()) {
339 const Span<int> orig_neighbors = orig_neighbor_data.slice(offsets[i]);
340
341 /* Modify the offsets in-place after using them to slice the current neighbor data. */
342 neighbor_offsets[i] = neighbor_data_with_fake.size();
343 neighbor_data_with_fake.extend(orig_neighbors);
344 const int neighbor = fake_neighbors[verts[i]];
345 if (neighbor != FAKE_NEIGHBOR_NONE) {
346 neighbor_data_with_fake.append(neighbor);
347 }
348 }
349 neighbor_offsets.last() = neighbor_data_with_fake.size();
350}
351
353 const float3 &pose_initial_position,
354 const Span<float3> vert_positions,
356 const Span<int> corner_verts,
357 const GroupedSpan<int> vert_to_face_map,
358 const Span<bool> hide_vert,
359 const Span<bool> hide_poly,
360 const Span<int> fake_neighbors,
361 const Span<float> prev_mask,
362 const bke::pbvh::MeshNode &node,
364 const MutableSpan<float> pose_factor,
365 PoseGrowFactorData &gftd)
366{
367 const Span<int> verts = hide::node_visible_verts(node, hide_vert, tls.vert_indices);
368
370 corner_verts,
371 vert_to_face_map,
372 hide_poly,
373 verts,
375 tls.neighbor_data);
376 if (!fake_neighbors.is_empty()) {
377 add_fake_neighbors(fake_neighbors,
378 verts,
379 tls.neighbor_data,
382 }
383 const GroupedSpan<int> neighbors(tls.neighbor_offsets.as_span(),
384 fake_neighbors.is_empty() ?
385 tls.neighbor_data.as_span() :
387
388 for (const int i : verts.index_range()) {
389 const int vert = verts[i];
390
391 float max = 0.0f;
392 for (const int neighbor : neighbors[i]) {
393 max = std::max(max, prev_mask[neighbor]);
394 }
395
396 if (max > prev_mask[vert]) {
397 const float3 &position = vert_positions[verts[i]];
398 pose_factor[vert] = max;
399 if (SCULPT_check_vertex_pivot_symmetry(position, pose_initial_position, symm)) {
400 gftd.pos_avg += position;
401 gftd.pos_count++;
402 }
403 }
404 }
405}
406
408 const float3 &pose_initial_position,
409 const SubdivCCG &subdiv_ccg,
410 const Span<int> fake_neighbors,
411 const Span<float> prev_mask,
412 const bke::pbvh::GridsNode &node,
413 const MutableSpan<float> pose_factor,
414 PoseGrowFactorData &gftd)
415{
416 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
417 const Span<float3> positions = subdiv_ccg.positions;
418 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
419 const Span<int> grids = node.grids();
420
421 for (const int i : grids.index_range()) {
422 const int grid = grids[i];
423 const IndexRange grid_range = bke::ccg::grid_range(key, grid);
424 for (const short y : IndexRange(key.grid_size)) {
425 for (const short x : IndexRange(key.grid_size)) {
426 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
427 if (!grid_hidden.is_empty() && grid_hidden[grid][offset]) {
428 continue;
429 }
430 const int vert = grid_range[offset];
431
432 SubdivCCGNeighbors neighbors;
434 subdiv_ccg, SubdivCCGCoord{grid, x, y}, false, neighbors);
435
436 float max = 0.0f;
437 for (const SubdivCCGCoord neighbor : neighbors.coords) {
438 max = std::max(max, prev_mask[neighbor.to_index(key)]);
439 }
440 if (!fake_neighbors.is_empty()) {
441 if (fake_neighbors[vert] != FAKE_NEIGHBOR_NONE) {
442 max = std::max(max, prev_mask[fake_neighbors[vert]]);
443 }
444 }
445
446 if (max > prev_mask[vert]) {
447 const float3 &position = positions[vert];
448 pose_factor[vert] = max;
449 if (SCULPT_check_vertex_pivot_symmetry(position, pose_initial_position, symm)) {
450 gftd.pos_avg += position;
451 gftd.pos_count++;
452 }
453 }
454 }
455 }
456 }
457}
458
460 const float3 &pose_initial_position,
461 const Span<int> fake_neighbors,
462 const Span<float> prev_mask,
464 const MutableSpan<float> pose_factor,
465 PoseGrowFactorData &gftd)
466{
468
469 BMeshNeighborVerts neighbors;
470
471 for (BMVert *bm_vert : verts) {
472 const int vert = BM_elem_index_get(bm_vert);
473
474 float max = 0.0f;
475 for (const BMVert *neighbor : vert_neighbors_get_bmesh(*bm_vert, neighbors)) {
476 max = std::max(max, prev_mask[BM_elem_index_get(neighbor)]);
477 }
478 if (!fake_neighbors.is_empty()) {
479 if (fake_neighbors[vert] != FAKE_NEIGHBOR_NONE) {
480 max = std::max(max, prev_mask[fake_neighbors[vert]]);
481 }
482 }
483
484 if (max > prev_mask[vert]) {
485 const float3 position = bm_vert->co;
486 pose_factor[vert] = max;
487 if (SCULPT_check_vertex_pivot_symmetry(position, pose_initial_position, symm)) {
488 gftd.pos_avg += position;
489 gftd.pos_count++;
490 }
491 }
492 }
493}
494
495/* Grow the factor until its boundary is near to the offset pose origin or outside the target
496 * distance. */
497static void grow_pose_factor(const Depsgraph &depsgraph,
498 Object &ob,
499 SculptSession &ss,
500 float pose_origin[3],
501 float pose_target[3],
502 float max_len,
503 float *r_pose_origin,
504 MutableSpan<float> pose_factor)
505{
508
509 IndexMaskMemory memory;
510 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
511 const Span<int> fake_neighbors = ss.fake_neighbors.fake_neighbor_index;
512
513 bool grow_next_iteration = true;
514 float prev_len = FLT_MAX;
516 while (grow_next_iteration) {
517 prev_mask.as_mutable_span().copy_from(pose_factor);
518
521 switch (pbvh.type()) {
524 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
525 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
526 const OffsetIndices faces = mesh.faces();
527 const Span<int> corner_verts = mesh.corner_verts();
528 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
529 const bke::AttributeAccessor attributes = mesh.attributes();
530 const VArraySpan<bool> hide_vert = *attributes.lookup<bool>(".hide_vert",
532 const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly",
535 node_mask.index_range(),
536 1,
538 [&](const IndexRange range, PoseGrowFactorData gftd) {
539 GrowFactorLocalData &tls = all_tls.local();
540 node_mask.slice(range).foreach_index([&](const int i) {
541 grow_factors_mesh(symm,
542 pose_target,
543 vert_positions,
544 faces,
545 corner_verts,
546 vert_to_face_map,
547 hide_vert,
548 hide_poly,
549 fake_neighbors,
550 prev_mask,
551 nodes[i],
552 tls,
553 pose_factor,
554 gftd);
555 });
556 return gftd;
557 },
559 break;
560 }
563 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
565 node_mask.index_range(),
566 1,
568 [&](const IndexRange range, PoseGrowFactorData gftd) {
569 node_mask.slice(range).foreach_index([&](const int i) {
570 grow_factors_grids(symm,
571 pose_target,
572 subdiv_ccg,
573 fake_neighbors,
574 prev_mask,
575 nodes[i],
576 pose_factor,
577 gftd);
578 });
579 return gftd;
580 },
582 break;
583 }
587 node_mask.index_range(),
588 1,
590 [&](const IndexRange range, PoseGrowFactorData gftd) {
591 node_mask.slice(range).foreach_index([&](const int i) {
592 grow_factors_bmesh(
593 symm, pose_target, fake_neighbors, prev_mask, nodes[i], pose_factor, gftd);
594 });
595 return gftd;
596 },
598 break;
599 }
600 }
601
602 if (gftd.pos_count != 0) {
603 gftd.pos_avg /= float(gftd.pos_count);
604 if (pose_origin) {
605 /* Test with pose origin. Used when growing the factors to compensate the Origin Offset. */
606 /* Stop when the factor's avg_pos starts moving away from the origin instead of getting
607 * closer to it. */
608 float len = math::distance(gftd.pos_avg, float3(pose_origin));
609 if (len < prev_len) {
610 prev_len = len;
611 grow_next_iteration = true;
612 }
613 else {
614 grow_next_iteration = false;
615 pose_factor.copy_from(prev_mask);
616 }
617 }
618 else {
619 /* Test with length. Used to calculate the origin positions of the IK chain. */
620 /* Stops when the factors have grown enough to generate a new segment origin. */
621 float len = math::distance(gftd.pos_avg, float3(pose_target));
622 if (len < max_len) {
623 prev_len = len;
624 grow_next_iteration = true;
625 }
626 else {
627 grow_next_iteration = false;
628 if (r_pose_origin) {
629 copy_v3_v3(r_pose_origin, gftd.pos_avg);
630 }
631 pose_factor.copy_from(prev_mask);
632 }
633 }
634 }
635 else {
636 if (r_pose_origin) {
637 copy_v3_v3(r_pose_origin, pose_target);
638 }
639 grow_next_iteration = false;
640 }
641 }
642}
643
644static bool vert_inside_brush_radius(const float3 &vertex,
645 const float3 &br_co,
646 float radius,
647 char symm)
648{
649 for (char i = 0; i <= symm; ++i) {
650 if (is_symmetry_iteration_valid(i, symm)) {
651 const float3 location = symmetry_flip(br_co, ePaintSymmetryFlags(i));
652 if (math::distance(location, vertex) < radius) {
653 return true;
654 }
655 }
656 }
657 return false;
658}
659
664static void calc_pose_origin_and_factor_mesh(const Depsgraph &depsgraph,
665 Object &object,
666 SculptSession &ss,
667 const float3 &initial_location,
668 float radius,
669 float3 &r_pose_origin,
670 MutableSpan<float> r_pose_factor)
671{
672 BLI_assert(!r_pose_factor.is_empty());
673
674 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
675 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
676 const Span<float3> positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object);
677
678 /* Calculate the pose rotation point based on the boundaries of the brush factor. */
680 flood.add_initial(find_symm_verts_mesh(depsgraph, object, ss.active_vert_index(), radius));
681
682 const int symm = SCULPT_mesh_symmetry_xyz_get(object);
683
684 int tot_co = 0;
685 float3 pose_origin(0);
686 float3 fallback_floodfill_origin = initial_location;
687 flood.execute(object, vert_to_face_map, [&](int /*from_v*/, int to_v) {
688 r_pose_factor[to_v] = 1.0f;
689
690 const float3 co = positions_eval[to_v];
691 if (math::distance_squared(initial_location, fallback_floodfill_origin) <
692 math::distance_squared(initial_location, co))
693 {
694 fallback_floodfill_origin = co;
695 }
696
697 if (vert_inside_brush_radius(co, initial_location, radius, symm)) {
698 return true;
699 }
700
701 if (SCULPT_check_vertex_pivot_symmetry(co, initial_location, symm)) {
702 pose_origin += co;
703 tot_co++;
704 }
705
706 return false;
707 });
708
709 if (tot_co > 0) {
710 r_pose_origin = pose_origin / float(tot_co);
711 }
712 else {
713 r_pose_origin = fallback_floodfill_origin;
714 }
715}
716
718 SculptSession &ss,
719 const float3 &initial_location,
720 float radius,
721 float3 &r_pose_origin,
722 MutableSpan<float> r_pose_factor)
723{
724 BLI_assert(!r_pose_factor.is_empty());
725
726 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
727
728 const Span<float3> positions = subdiv_ccg.positions;
729 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
730 /* Calculate the pose rotation point based on the boundaries of the brush factor. */
732 flood.add_initial(key, find_symm_verts_grids(object, ss.active_vert_index(), radius));
733
734 const int symm = SCULPT_mesh_symmetry_xyz_get(object);
735
736 int tot_co = 0;
737 float3 pose_origin(0);
738 float3 fallback_floodfill_origin = initial_location;
739 flood.execute(
740 object, subdiv_ccg, [&](SubdivCCGCoord /*from_v*/, SubdivCCGCoord to_v, bool is_duplicate) {
741 const int to_v_i = to_v.to_index(key);
742
743 r_pose_factor[to_v_i] = 1.0f;
744
745 const float3 &co = positions[to_v_i];
746 if (math::distance_squared(initial_location, fallback_floodfill_origin) <
747 math::distance_squared(initial_location, co))
748 {
749 fallback_floodfill_origin = co;
750 }
751
752 if (vert_inside_brush_radius(co, initial_location, radius, symm)) {
753 return true;
754 }
755
756 if (SCULPT_check_vertex_pivot_symmetry(co, initial_location, symm)) {
757 if (!is_duplicate) {
758 pose_origin += co;
759 tot_co++;
760 }
761 }
762
763 return false;
764 });
765
766 if (tot_co > 0) {
767 r_pose_origin = pose_origin / float(tot_co);
768 }
769 else {
770 r_pose_origin = fallback_floodfill_origin;
771 }
772}
773
775 SculptSession &ss,
776 const float3 &initial_location,
777 float radius,
778 float3 &r_pose_origin,
779 MutableSpan<float> r_pose_factor)
780{
781 BLI_assert(!r_pose_factor.is_empty());
783
784 /* Calculate the pose rotation point based on the boundaries of the brush factor. */
787 flood.add_initial(*ss.bm, find_symm_verts_bmesh(object, ss.active_vert_index(), radius));
788
789 const int symm = SCULPT_mesh_symmetry_xyz_get(object);
790
791 int tot_co = 0;
792 float3 pose_origin(0);
793 float3 fallback_floodfill_origin = initial_location;
794 flood.execute(object, [&](BMVert * /*from_v*/, BMVert *to_v) {
795 const int to_v_i = BM_elem_index_get(to_v);
796 r_pose_factor[to_v_i] = 1.0f;
797
798 const float3 co = to_v->co;
799 if (math::distance_squared(initial_location, fallback_floodfill_origin) <
800 math::distance_squared(initial_location, co))
801 {
802 fallback_floodfill_origin = co;
803 }
804
805 if (vert_inside_brush_radius(co, initial_location, radius, symm)) {
806 return true;
807 }
808
809 if (SCULPT_check_vertex_pivot_symmetry(co, initial_location, symm)) {
810 pose_origin += co;
811 tot_co++;
812 }
813
814 return false;
815 });
816
817 if (tot_co > 0) {
818 r_pose_origin = pose_origin / float(tot_co);
819 }
820 else {
821 r_pose_origin = fallback_floodfill_origin;
822 }
823}
824
825static void calc_pose_data(const Depsgraph &depsgraph,
826 Object &object,
827 SculptSession &ss,
828 const float3 &initial_location,
829 float radius,
830 float pose_offset,
831 float3 &r_pose_origin,
832 MutableSpan<float> r_pose_factor)
833{
834 BLI_assert(!r_pose_factor.is_empty());
835
836 float3 pose_origin;
837 switch (bke::object::pbvh_get(object)->type()) {
840 depsgraph, object, ss, initial_location, radius, pose_origin, r_pose_factor);
841 break;
844 object, ss, initial_location, radius, pose_origin, r_pose_factor);
845 break;
848 object, ss, initial_location, radius, pose_origin, r_pose_factor);
849 break;
850 }
851
852 /* Offset the pose origin. */
853 const float3 pose_dir = math::normalize(pose_origin - initial_location);
854 pose_origin += pose_dir * radius * pose_offset;
855 r_pose_origin = pose_origin;
856
857 /* Do the initial grow of the factors to get the first segment of the chain with Origin Offset.
858 */
859 if (pose_offset != 0.0f) {
860 grow_pose_factor(depsgraph, object, ss, pose_origin, pose_origin, 0, nullptr, r_pose_factor);
861 }
862}
863
864/* Init the IK chain with empty weights. */
865static std::unique_ptr<IKChain> ik_chain_new(const int totsegments, const int totverts)
866{
867 std::unique_ptr<IKChain> ik_chain = std::make_unique<IKChain>();
868 ik_chain->segments.reinitialize(totsegments);
869 for (IKChainSegment &segment : ik_chain->segments) {
870 segment.weights = Array<float>(totverts, 0.0f);
871 }
872 return ik_chain;
873}
874
875/* Init the origin/head pairs of all the segments from the calculated origins. */
876static void ik_chain_origin_heads_init(IKChain &ik_chain, const float3 &initial_location)
877{
878 float3 origin;
879 float3 head;
880 for (const int i : ik_chain.segments.index_range()) {
881 if (i == 0) {
882 head = initial_location;
883 origin = ik_chain.segments[i].orig;
884 }
885 else {
886 head = ik_chain.segments[i - 1].orig;
887 origin = ik_chain.segments[i].orig;
888 }
889 ik_chain.segments[i].orig = origin;
890 ik_chain.segments[i].initial_orig = origin;
891 ik_chain.segments[i].head = head;
892 ik_chain.segments[i].initial_head = head;
893 ik_chain.segments[i].len = math::distance(head, origin);
894 ik_chain.segments[i].scale = float3(1.0f);
895 }
896}
897
898static int brush_num_effective_segments(const Brush &brush)
899{
900 /* Scaling multiple segments at the same time is not supported as the IK solver can't handle
901 * changes in the segment's length. It will also required a better weight distribution to avoid
902 * artifacts in the areas affected by multiple segments. */
903 if (ELEM(brush.pose_deform_type,
906 {
907 return 1;
908 }
909 return brush.pose_ik_segments;
910}
911
912static std::unique_ptr<IKChain> ik_chain_init_topology(const Depsgraph &depsgraph,
913 Object &object,
914 SculptSession &ss,
915 const Brush &brush,
916 const float3 &initial_location,
917 const float radius)
918{
919
920 const float chain_segment_len = radius * (1.0f + brush.pose_offset);
921
922 const int totvert = SCULPT_vertex_count_get(object);
923 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
924
925 int nearest_vertex_index = -1;
926 /* TODO: How should this function handle not being able to find the nearest vert? */
927 switch (pbvh.type()) {
929 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
930 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, object);
931 const bke::AttributeAccessor attributes = mesh.attributes();
932 VArraySpan<bool> hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
933 std::optional<int> nearest = nearest_vert_calc_mesh(pbvh,
934 vert_positions,
935 hide_vert,
936 initial_location,
937 std::numeric_limits<float>::max(),
938 true);
939 nearest_vertex_index = *nearest;
940 break;
941 }
943 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
944 const std::optional<SubdivCCGCoord> nearest = nearest_vert_calc_grids(
945 pbvh, subdiv_ccg, initial_location, std::numeric_limits<float>::max(), true);
946 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
947 nearest_vertex_index = nearest->to_index(key);
948 break;
949 }
951 const std::optional<BMVert *> nearest = nearest_vert_calc_bmesh(
952 pbvh, initial_location, std::numeric_limits<float>::max(), false);
953 nearest_vertex_index = BM_elem_index_get(*nearest);
954 break;
955 }
956 }
957
958 /* Init the buffers used to keep track of the changes in the pose factors as more segments are
959 * added to the IK chain. */
960
961 /* This stores the whole pose factors values as they grow through the mesh. */
962 Array<float> pose_factor_grow(totvert, 0.0f);
963
964 /* This stores the previous status of the factors when growing a new iteration. */
965 Array<float> pose_factor_grow_prev(totvert, 0.0f);
966
967 pose_factor_grow[nearest_vertex_index] = 1.0f;
968
969 const int tot_segments = brush_num_effective_segments(brush);
970 std::unique_ptr<IKChain> ik_chain = ik_chain_new(tot_segments, totvert);
971
972 /* Calculate the first segment in the chain using the brush radius and the pose origin offset. */
974 object,
975 ss,
976 initial_location,
977 radius,
978 brush.pose_offset,
979 ik_chain->segments[0].orig,
980 pose_factor_grow);
981
982 float3 next_chain_segment_target = ik_chain->segments[0].orig;
983
984 /* Init the weights of this segment and store the status of the pose factors to start calculating
985 * new segment origins. */
986 for (int j = 0; j < totvert; j++) {
987 ik_chain->segments[0].weights[j] = pose_factor_grow[j];
988 pose_factor_grow_prev[j] = pose_factor_grow[j];
989 }
990
991 /* Calculate the next segments in the chain growing the pose factors. */
992 for (const int i : ik_chain->segments.index_range().drop_front(1)) {
993
994 /* Grow the factors to get the new segment origin. */
996 object,
997 ss,
998 nullptr,
999 next_chain_segment_target,
1000 chain_segment_len,
1001 ik_chain->segments[i].orig,
1002 pose_factor_grow);
1003 next_chain_segment_target = ik_chain->segments[i].orig;
1004
1005 /* Create the weights for this segment from the difference between the previous grow factor
1006 * iteration an the current iteration. */
1007 for (int j = 0; j < totvert; j++) {
1008 ik_chain->segments[i].weights[j] = pose_factor_grow[j] - pose_factor_grow_prev[j];
1009 /* Store the current grow factor status for the next iteration. */
1010 pose_factor_grow_prev[j] = pose_factor_grow[j];
1011 }
1012 }
1013
1014 ik_chain_origin_heads_init(*ik_chain, initial_location);
1015
1016 return ik_chain;
1017}
1018
1019static std::unique_ptr<IKChain> ik_chain_init_face_sets_mesh(const Depsgraph &depsgraph,
1020 Object &object,
1021 SculptSession &ss,
1022 const Brush &brush,
1023 const float radius)
1024{
1025 struct SegmentData {
1026 int vert;
1027 int face_set;
1028 };
1029
1030 Mesh &mesh = *static_cast<Mesh *>(object.data);
1031 Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, object);
1032 const OffsetIndices faces = mesh.faces();
1033 const Span<int> corner_verts = mesh.corner_verts();
1034 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1035 const bke::AttributeAccessor attributes = mesh.attributes();
1036 const VArraySpan<bool> hide_vert = *attributes.lookup<bool>(".hide_vert",
1038 const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
1039 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
1040 ".sculpt_face_set", bke::AttrDomain::Face, 0);
1041
1042 std::unique_ptr<IKChain> ik_chain = ik_chain_new(brush_num_effective_segments(brush),
1043 vert_positions.size());
1044
1045 /* Each vertex can only be assigned to one face set. */
1046 BitVector<> is_weighted(vert_positions.size());
1047 Set<int> visited_face_sets;
1048
1049 SegmentData current_data = {std::get<int>(ss.active_vert()), SCULPT_FACE_SET_NONE};
1050
1051 const int symm = SCULPT_mesh_symmetry_xyz_get(object);
1052 Vector<int> neighbors;
1053 for (const int i : ik_chain->segments.index_range()) {
1054 const bool is_first_iteration = i == 0;
1055
1056 flood_fill::FillDataMesh flood_fill(vert_positions.size(),
1058 flood_fill.add_initial(find_symm_verts_mesh(depsgraph, object, current_data.vert, radius));
1059
1060 visited_face_sets.add(current_data.face_set);
1061
1062 MutableSpan<float> pose_factor = ik_chain->segments[i].weights;
1063 std::optional<SegmentData> next_segment_data;
1064
1065 float3 face_set_boundary_accum(0);
1066 int face_set_boundary_count = 0;
1067
1068 float3 fallback_accum(0);
1069 int fallback_count = 0;
1070
1071 const float3 &pose_initial_co = vert_positions[current_data.vert];
1072 flood_fill.execute(object, vert_to_face_map, [&](int /*from_v*/, int to_v) {
1073 const float3 &to_v_position = vert_positions[to_v];
1074 const bool symmetry_check = SCULPT_check_vertex_pivot_symmetry(
1075 to_v_position, pose_initial_co, symm);
1076
1077 /* First iteration. Continue expanding using topology until a vertex is outside the brush
1078 * radius to determine the first face set. */
1079 if (current_data.face_set == SCULPT_FACE_SET_NONE) {
1080
1081 pose_factor[to_v] = 1.0f;
1082 is_weighted[to_v].set();
1083
1084 if (vert_inside_brush_radius(to_v_position, pose_initial_co, radius, symm)) {
1085 const int visited_face_set = face_set::vert_face_set_get(
1086 vert_to_face_map, face_sets, to_v);
1087 visited_face_sets.add(visited_face_set);
1088 }
1089 else if (symmetry_check) {
1090 current_data.face_set = face_set::vert_face_set_get(vert_to_face_map, face_sets, to_v);
1091 visited_face_sets.add(current_data.face_set);
1092 }
1093 return true;
1094 }
1095
1096 /* We already have a current face set, so we can start checking the face sets of the
1097 * vertices. */
1098 /* In the first iteration we need to check all face sets we already visited as the flood
1099 * fill may still not be finished in some of them. */
1100 bool is_vertex_valid = false;
1101 if (is_first_iteration) {
1102 for (const int visited_face_set : visited_face_sets) {
1103 is_vertex_valid |= face_set::vert_has_face_set(
1104 vert_to_face_map, face_sets, to_v, visited_face_set);
1105 }
1106 }
1107 else {
1108 is_vertex_valid = face_set::vert_has_face_set(
1109 vert_to_face_map, face_sets, to_v, current_data.face_set);
1110 }
1111
1112 if (!is_vertex_valid) {
1113 return false;
1114 }
1115
1116 bool visit_next = false;
1117 if (!is_weighted[to_v]) {
1118 pose_factor[to_v] = 1.0f;
1119 is_weighted[to_v].set();
1120 visit_next = true;
1121 }
1122
1123 /* Fallback origin accumulation. */
1124 if (symmetry_check) {
1125 fallback_accum += to_v_position;
1126 fallback_count++;
1127 }
1128
1129 if (!symmetry_check || face_set::vert_has_unique_face_set(vert_to_face_map, face_sets, to_v))
1130 {
1131 return visit_next;
1132 }
1133
1134 /* We only add coordinates for calculating the origin when it is possible to go from this
1135 * vertex to another vertex in a valid face set for the next iteration. */
1136 bool count_as_boundary = false;
1137
1138 for (const int neighbor_idx : vert_neighbors_get_mesh(
1139 faces, corner_verts, vert_to_face_map, hide_poly, to_v, neighbors))
1140 {
1141 const int next_face_set_candidate = face_set::vert_face_set_get(
1142 vert_to_face_map, face_sets, neighbor_idx);
1143
1144 /* Check if we can get a valid face set for the next iteration from this neighbor. */
1145 if (face_set::vert_has_unique_face_set(vert_to_face_map, face_sets, neighbor_idx) &&
1146 !visited_face_sets.contains(next_face_set_candidate))
1147 {
1148 if (!next_segment_data) {
1149 next_segment_data = {neighbor_idx, next_face_set_candidate};
1150 }
1151 count_as_boundary = true;
1152 }
1153 }
1154
1155 /* Origin accumulation. */
1156 if (count_as_boundary) {
1157 face_set_boundary_accum += to_v_position;
1158 face_set_boundary_count++;
1159 }
1160 return visit_next;
1161 });
1162
1163 if (face_set_boundary_count > 0) {
1164 ik_chain->segments[i].orig = face_set_boundary_accum / float(face_set_boundary_count);
1165 }
1166 else if (fallback_count > 0) {
1167 ik_chain->segments[i].orig = fallback_accum / float(fallback_count);
1168 }
1169 else {
1170 ik_chain->segments[i].orig = float3(0);
1171 }
1172
1173 current_data = *next_segment_data;
1174 }
1175
1176 ik_chain_origin_heads_init(*ik_chain, vert_positions[std::get<int>(ss.active_vert())]);
1177
1178 return ik_chain;
1179}
1180
1181static std::unique_ptr<IKChain> ik_chain_init_face_sets_grids(Object &object,
1182 SculptSession &ss,
1183 const Brush &brush,
1184 const float radius)
1185{
1186 struct SegmentData {
1187 int vert;
1188 int face_set;
1189 };
1190
1191 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
1192 const OffsetIndices<int> faces = mesh.faces();
1193 const Span<int> corner_verts = mesh.corner_verts();
1194 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1195 const bke::AttributeAccessor attributes = mesh.attributes();
1196 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
1197 ".sculpt_face_set", bke::AttrDomain::Face, 0);
1198
1199 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1200 const Span<float3> positions = subdiv_ccg.positions;
1201 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1202 const int grids_num = ss.subdiv_ccg->grids_num * key.grid_area;
1203
1204 std::unique_ptr<IKChain> ik_chain = ik_chain_new(brush_num_effective_segments(brush), grids_num);
1205
1206 /* Each vertex can only be assigned to one face set. */
1207 BitVector<> is_weighted(grids_num);
1208 Set<int> visited_face_sets;
1209
1210 SegmentData current_data = {ss.active_vert_index(), SCULPT_FACE_SET_NONE};
1211
1212 const int symm = SCULPT_mesh_symmetry_xyz_get(object);
1213 SubdivCCGNeighbors neighbors;
1214 for (const int i : ik_chain->segments.index_range()) {
1215 const bool is_first_iteration = i == 0;
1216
1218 flood_fill.add_initial(key, find_symm_verts_grids(object, current_data.vert, radius));
1219
1220 visited_face_sets.add(current_data.face_set);
1221
1222 MutableSpan<float> pose_factor = ik_chain->segments[i].weights;
1223 std::optional<SegmentData> next_segment_data;
1224
1225 float3 face_set_boundary_accum(0);
1226 int face_set_boundary_count = 0;
1227
1228 float3 fallback_accum(0);
1229 int fallback_count = 0;
1230
1231 const float3 &pose_initial_co = positions[current_data.vert];
1232 flood_fill.execute(
1233 object,
1234 subdiv_ccg,
1235 [&](SubdivCCGCoord /*from_v*/, SubdivCCGCoord to_v, bool is_duplicate) {
1236 const int to_v_i = to_v.to_index(key);
1237
1238 const float3 to_v_position = positions[to_v_i];
1239 const bool symmetry_check = SCULPT_check_vertex_pivot_symmetry(
1240 to_v_position, pose_initial_co, symm) &&
1241 !is_duplicate;
1242
1243 /* First iteration. Continue expanding using topology until a vertex is outside the brush
1244 * radius to determine the first face set. */
1245 if (current_data.face_set == SCULPT_FACE_SET_NONE) {
1246
1247 pose_factor[to_v_i] = 1.0f;
1248 is_weighted[to_v_i].set();
1249
1250 if (vert_inside_brush_radius(to_v_position, pose_initial_co, radius, symm)) {
1251 const int visited_face_set = face_set::vert_face_set_get(
1252 subdiv_ccg, face_sets, to_v.grid_index);
1253 visited_face_sets.add(visited_face_set);
1254 }
1255 else if (symmetry_check) {
1256 current_data.face_set = face_set::vert_face_set_get(
1257 subdiv_ccg, face_sets, to_v.grid_index);
1258 visited_face_sets.add(current_data.face_set);
1259 }
1260 return true;
1261 }
1262
1263 /* We already have a current face set, so we can start checking the face sets of the
1264 * vertices. */
1265 /* In the first iteration we need to check all face sets we already visited as the flood
1266 * fill may still not be finished in some of them. */
1267 bool is_vertex_valid = false;
1268 if (is_first_iteration) {
1269 for (const int visited_face_set : visited_face_sets) {
1270 is_vertex_valid |= face_set::vert_has_face_set(
1271 subdiv_ccg, face_sets, to_v.grid_index, visited_face_set);
1272 }
1273 }
1274 else {
1275 is_vertex_valid = face_set::vert_has_face_set(
1276 subdiv_ccg, face_sets, to_v.grid_index, current_data.face_set);
1277 }
1278
1279 if (!is_vertex_valid) {
1280 return false;
1281 }
1282
1283 bool visit_next = false;
1284 if (!is_weighted[to_v_i]) {
1285 pose_factor[to_v_i] = 1.0f;
1286 is_weighted[to_v_i].set();
1287 visit_next = true;
1288 }
1289
1290 /* Fallback origin accumulation. */
1291 if (symmetry_check) {
1292 fallback_accum += to_v_position;
1293 fallback_count++;
1294 }
1295
1296 if (!symmetry_check ||
1298 faces, corner_verts, vert_to_face_map, face_sets, subdiv_ccg, to_v))
1299 {
1300 return visit_next;
1301 }
1302
1303 /* We only add coordinates for calculating the origin when it is possible to go from this
1304 * vertex to another vertex in a valid face set for the next iteration. */
1305 bool count_as_boundary = false;
1306
1307 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, to_v, false, neighbors);
1308 for (const SubdivCCGCoord neighbor : neighbors.coords) {
1309 const int next_face_set_candidate = face_set::vert_face_set_get(
1310 subdiv_ccg, face_sets, neighbor.grid_index);
1311
1312 /* Check if we can get a valid face set for the next iteration from this neighbor. */
1314 faces, corner_verts, vert_to_face_map, face_sets, subdiv_ccg, neighbor) &&
1315 !visited_face_sets.contains(next_face_set_candidate))
1316 {
1317 if (!next_segment_data) {
1318 next_segment_data = {neighbor.to_index(key), next_face_set_candidate};
1319 }
1320 count_as_boundary = true;
1321 }
1322 }
1323
1324 /* Origin accumulation. */
1325 if (count_as_boundary) {
1326 face_set_boundary_accum += to_v_position;
1327 face_set_boundary_count++;
1328 }
1329 return visit_next;
1330 });
1331
1332 if (face_set_boundary_count > 0) {
1333 ik_chain->segments[i].orig = face_set_boundary_accum / float(face_set_boundary_count);
1334 }
1335 else if (fallback_count > 0) {
1336 ik_chain->segments[i].orig = fallback_accum / float(fallback_count);
1337 }
1338 else {
1339 ik_chain->segments[i].orig = float3(0);
1340 }
1341
1342 current_data = *next_segment_data;
1343 }
1344
1345 ik_chain_origin_heads_init(*ik_chain, positions[ss.active_vert_index()]);
1346
1347 return ik_chain;
1348}
1349
1350static std::unique_ptr<IKChain> ik_chain_init_face_sets_bmesh(Object &object,
1351 SculptSession &ss,
1352 const Brush &brush,
1353 const float radius)
1354{
1355 struct SegmentData {
1356 BMVert *vert;
1357 int face_set;
1358 };
1359
1360 const int verts_num = BM_mesh_elem_count(ss.bm, BM_VERT);
1361 const int face_set_offset = CustomData_get_offset_named(
1362 &ss.bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
1363 std::unique_ptr<IKChain> ik_chain = ik_chain_new(brush_num_effective_segments(brush), verts_num);
1364
1365 /* Each vertex can only be assigned to one face set. */
1366 BitVector<> is_weighted(verts_num);
1367 Set<int> visited_face_sets;
1368
1369 SegmentData current_data = {std::get<BMVert *>(ss.active_vert()), SCULPT_FACE_SET_NONE};
1370
1371 const int symm = SCULPT_mesh_symmetry_xyz_get(object);
1372 BMeshNeighborVerts neighbors;
1373 for (const int i : ik_chain->segments.index_range()) {
1374 const bool is_first_iteration = i == 0;
1375
1377 flood_fill.add_initial(
1378 *ss.bm, find_symm_verts_bmesh(object, BM_elem_index_get(current_data.vert), radius));
1379
1380 visited_face_sets.add(current_data.face_set);
1381
1382 MutableSpan<float> pose_factor = ik_chain->segments[i].weights;
1383 std::optional<SegmentData> next_segment_data;
1384
1385 float3 face_set_boundary_accum(0);
1386 int face_set_boundary_count = 0;
1387
1388 float3 fallback_accum(0);
1389 int fallback_count = 0;
1390
1391 const float3 pose_initial_co = current_data.vert->co;
1392 flood_fill.execute(object, [&](BMVert * /*from_v*/, BMVert *to_v) {
1393 const int to_v_i = BM_elem_index_get(to_v);
1394
1395 const float3 to_v_position = to_v->co;
1396 const bool symmetry_check = SCULPT_check_vertex_pivot_symmetry(
1397 to_v_position, pose_initial_co, symm);
1398
1399 /* First iteration. Continue expanding using topology until a vertex is outside the brush
1400 * radius to determine the first face set. */
1401 if (current_data.face_set == SCULPT_FACE_SET_NONE) {
1402
1403 pose_factor[to_v_i] = 1.0f;
1404 is_weighted[to_v_i].set();
1405
1406 if (vert_inside_brush_radius(to_v_position, pose_initial_co, radius, symm)) {
1407 const int visited_face_set = face_set::vert_face_set_get(face_set_offset, *to_v);
1408 visited_face_sets.add(visited_face_set);
1409 }
1410 else if (symmetry_check) {
1411 current_data.face_set = face_set::vert_face_set_get(face_set_offset, *to_v);
1412 visited_face_sets.add(current_data.face_set);
1413 }
1414 return true;
1415 }
1416
1417 /* We already have a current face set, so we can start checking the face sets of the
1418 * vertices. */
1419 /* In the first iteration we need to check all face sets we already visited as the flood
1420 * fill may still not be finished in some of them. */
1421 bool is_vertex_valid = false;
1422 if (is_first_iteration) {
1423 for (const int visited_face_set : visited_face_sets) {
1424 is_vertex_valid |= face_set::vert_has_face_set(face_set_offset, *to_v, visited_face_set);
1425 }
1426 }
1427 else {
1428 is_vertex_valid = face_set::vert_has_face_set(
1429 face_set_offset, *to_v, current_data.face_set);
1430 }
1431
1432 if (!is_vertex_valid) {
1433 return false;
1434 }
1435
1436 bool visit_next = false;
1437 if (!is_weighted[to_v_i]) {
1438 pose_factor[to_v_i] = 1.0f;
1439 is_weighted[to_v_i].set();
1440 visit_next = true;
1441 }
1442
1443 /* Fallback origin accumulation. */
1444 if (symmetry_check) {
1445 fallback_accum += to_v_position;
1446 fallback_count++;
1447 }
1448
1449 if (!symmetry_check || face_set::vert_has_unique_face_set(face_set_offset, *to_v)) {
1450 return visit_next;
1451 }
1452
1453 /* We only add coordinates for calculating the origin when it is possible to go from this
1454 * vertex to another vertex in a valid face set for the next iteration. */
1455 bool count_as_boundary = false;
1456
1457 for (BMVert *neighbor : vert_neighbors_get_bmesh(*to_v, neighbors)) {
1458 const int next_face_set_candidate = face_set::vert_face_set_get(face_set_offset,
1459 *neighbor);
1460
1461 /* Check if we can get a valid face set for the next iteration from this neighbor. */
1462 if (face_set::vert_has_unique_face_set(face_set_offset, *neighbor) &&
1463 !visited_face_sets.contains(next_face_set_candidate))
1464 {
1465 if (!next_segment_data) {
1466 next_segment_data = {neighbor, next_face_set_candidate};
1467 }
1468 count_as_boundary = true;
1469 }
1470 }
1471
1472 /* Origin accumulation. */
1473 if (count_as_boundary) {
1474 face_set_boundary_accum += to_v_position;
1475 face_set_boundary_count++;
1476 }
1477 return visit_next;
1478 });
1479
1480 if (face_set_boundary_count > 0) {
1481 ik_chain->segments[i].orig = face_set_boundary_accum / float(face_set_boundary_count);
1482 }
1483 else if (fallback_count > 0) {
1484 ik_chain->segments[i].orig = fallback_accum / float(fallback_count);
1485 }
1486 else {
1487 ik_chain->segments[i].orig = float3(0);
1488 }
1489
1490 current_data = *next_segment_data;
1491 }
1492
1493 ik_chain_origin_heads_init(*ik_chain, std::get<BMVert *>(ss.active_vert())->co);
1494
1495 return ik_chain;
1496}
1497
1498static std::unique_ptr<IKChain> ik_chain_init_face_sets(const Depsgraph &depsgraph,
1499 Object &object,
1500 SculptSession &ss,
1501 const Brush &brush,
1502 const float radius)
1503{
1504 switch (bke::object::pbvh_get(object)->type()) {
1506 return ik_chain_init_face_sets_mesh(depsgraph, object, ss, brush, radius);
1508 return ik_chain_init_face_sets_grids(object, ss, brush, radius);
1510 return ik_chain_init_face_sets_bmesh(object, ss, brush, radius);
1511 }
1512
1514 return nullptr;
1515}
1516
1517static std::optional<float3> calc_average_face_set_center(const Depsgraph &depsgraph,
1518 Object &object,
1519 const Span<int> floodfill_step,
1520 const int active_face_set,
1521 const int target_face_set)
1522{
1523 int count = 0;
1524 float3 sum(0.0f);
1525
1526 switch (bke::object::pbvh_get(object)->type()) {
1527 case bke::pbvh::Type::Mesh: {
1528 const Mesh &mesh = *static_cast<Mesh *>(object.data);
1529 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1530 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, object);
1531 const bke::AttributeAccessor attributes = mesh.attributes();
1532 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
1533 ".sculpt_face_set", bke::AttrDomain::Face, 0);
1534
1535 for (const int vert : vert_positions.index_range()) {
1536 if (floodfill_step[vert] != 0 &&
1537 face_set::vert_has_face_set(vert_to_face_map, face_sets, vert, active_face_set) &&
1538 face_set::vert_has_face_set(vert_to_face_map, face_sets, vert, target_face_set))
1539 {
1540 sum += vert_positions[vert];
1541 count++;
1542 }
1543 }
1544 break;
1545 }
1547 const SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
1548 const Span<float3> positions = subdiv_ccg.positions;
1549
1550 const Mesh &mesh = *static_cast<Mesh *>(object.data);
1551 const bke::AttributeAccessor attributes = mesh.attributes();
1552 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
1553 ".sculpt_face_set", bke::AttrDomain::Face, 0);
1554
1555 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1556 for (const int grid : IndexRange(subdiv_ccg.grids_num)) {
1557 for (const int index : bke::ccg::grid_range(key, grid)) {
1558 if (floodfill_step[index] != 0 &&
1559 face_set::vert_has_face_set(subdiv_ccg, face_sets, grid, active_face_set) &&
1560 face_set::vert_has_face_set(subdiv_ccg, face_sets, grid, target_face_set))
1561 {
1562 sum += positions[index];
1563 count++;
1564 }
1565 }
1566 }
1567 break;
1568 }
1571 BMesh &bm = *object.sculpt->bm;
1572 const int face_set_offset = CustomData_get_offset_named(
1573 &bm.pdata, CD_PROP_INT32, ".sculpt_face_set");
1574 for (const int vert : IndexRange(BM_mesh_elem_count(&bm, BM_VERT))) {
1575 const BMVert *bm_vert = BM_vert_at_index(&bm, vert);
1576 if (floodfill_step[vert] != 0 &&
1577 face_set::vert_has_face_set(face_set_offset, *bm_vert, active_face_set) &&
1578 face_set::vert_has_face_set(face_set_offset, *bm_vert, target_face_set))
1579 {
1580 sum += bm_vert->co;
1581 count++;
1582 }
1583 }
1584
1585 break;
1586 }
1587 }
1588
1589 if (count != 0) {
1590 return sum / float(count);
1591 }
1592
1593 return std::nullopt;
1594}
1595
1596static std::unique_ptr<IKChain> ik_chain_init_face_sets_fk_mesh(const Depsgraph &depsgraph,
1597 Object &object,
1598 SculptSession &ss,
1599 const float radius,
1600 const float3 &initial_location)
1601{
1602 const Mesh &mesh = *static_cast<Mesh *>(object.data);
1603 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1604 const bke::AttributeAccessor attributes = mesh.attributes();
1605 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
1606 ".sculpt_face_set", bke::AttrDomain::Face, 0);
1607
1608 std::unique_ptr<IKChain> ik_chain = ik_chain_new(1, mesh.verts_num);
1609
1610 const int active_vert = std::get<int>(ss.active_vert());
1611
1612 const int active_face_set = face_set::active_face_set_get(object);
1613
1614 Set<int> visited_face_sets;
1615 Array<int> floodfill_step(mesh.verts_num);
1616 floodfill_step[active_vert] = 1;
1617
1618 int masked_face_set = SCULPT_FACE_SET_NONE;
1619 int target_face_set = SCULPT_FACE_SET_NONE;
1620 int masked_face_set_it = 0;
1622 step_floodfill.add_initial(active_vert);
1623 step_floodfill.execute(object, vert_to_face_map, [&](int from_v, int to_v) {
1624 floodfill_step[to_v] = floodfill_step[from_v] + 1;
1625
1626 const int to_face_set = face_set::vert_face_set_get(vert_to_face_map, face_sets, to_v);
1627 if (!visited_face_sets.contains(to_face_set)) {
1628 if (face_set::vert_has_unique_face_set(vert_to_face_map, face_sets, to_v) &&
1629 !face_set::vert_has_unique_face_set(vert_to_face_map, face_sets, from_v) &&
1630 face_set::vert_has_face_set(vert_to_face_map, face_sets, from_v, to_face_set))
1631 {
1632
1633 visited_face_sets.add(to_face_set);
1634
1635 if (floodfill_step[to_v] >= masked_face_set_it) {
1636 masked_face_set = to_face_set;
1637 masked_face_set_it = floodfill_step[to_v];
1638 }
1639
1640 if (target_face_set == SCULPT_FACE_SET_NONE) {
1641 target_face_set = to_face_set;
1642 }
1643 }
1644 }
1645
1646 return face_set::vert_has_face_set(vert_to_face_map, face_sets, to_v, active_face_set);
1647 });
1648
1649 const std::optional<float3> origin = calc_average_face_set_center(
1650 depsgraph, object, floodfill_step, active_face_set, masked_face_set);
1651 ik_chain->segments[0].orig = origin.value_or(float3(0));
1652
1653 std::optional<float3> head = std::nullopt;
1654 if (target_face_set != masked_face_set) {
1656 depsgraph, object, floodfill_step, active_face_set, target_face_set);
1657 }
1658
1659 ik_chain->segments[0].head = head.value_or(initial_location);
1660 ik_chain->grab_delta_offset = ik_chain->segments[0].head - initial_location;
1661
1662 flood_fill::FillDataMesh weight_floodfill(mesh.verts_num, ss.fake_neighbors.fake_neighbor_index);
1663 weight_floodfill.add_initial(find_symm_verts_mesh(depsgraph, object, active_vert, radius));
1664 MutableSpan<float> fk_weights = ik_chain->segments[0].weights;
1665 weight_floodfill.execute(object, vert_to_face_map, [&](int /*from_v*/, int to_v) {
1666 fk_weights[to_v] = 1.0f;
1667 return !face_set::vert_has_face_set(vert_to_face_map, face_sets, to_v, masked_face_set);
1668 });
1669
1670 ik_chain_origin_heads_init(*ik_chain, ik_chain->segments[0].head);
1671 return ik_chain;
1672}
1673
1674static std::unique_ptr<IKChain> ik_chain_init_face_sets_fk_grids(const Depsgraph &depsgraph,
1675 Object &object,
1676 SculptSession &ss,
1677 const float radius,
1678 const float3 &initial_location)
1679{
1680 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
1681 const OffsetIndices<int> faces = mesh.faces();
1682 const Span<int> corner_verts = mesh.corner_verts();
1683 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
1684 const bke::AttributeAccessor attributes = mesh.attributes();
1685 const VArraySpan face_sets = *attributes.lookup_or_default<int>(
1686 ".sculpt_face_set", bke::AttrDomain::Face, 0);
1687
1688 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1689 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1690 const Span<int> grid_to_face_map = subdiv_ccg.grid_to_face_map;
1691 const int grids_num = ss.subdiv_ccg->grids_num * key.grid_area;
1692
1693 std::unique_ptr<IKChain> ik_chain = ik_chain_new(1, grids_num);
1694
1695 const int active_vert_index = ss.active_vert_index();
1696
1697 const int active_face_set = face_set::active_face_set_get(object);
1698
1699 Set<int> visited_face_sets;
1700 Array<int> floodfill_step(grids_num);
1701 floodfill_step[active_vert_index] = 1;
1702
1703 int masked_face_set = SCULPT_FACE_SET_NONE;
1704 int target_face_set = SCULPT_FACE_SET_NONE;
1705 int masked_face_set_it = 0;
1706 flood_fill::FillDataGrids step_floodfill(grids_num, ss.fake_neighbors.fake_neighbor_index);
1707 step_floodfill.add_initial(SubdivCCGCoord::from_index(key, active_vert_index));
1708 step_floodfill.execute(
1709 object, subdiv_ccg, [&](SubdivCCGCoord from_v, SubdivCCGCoord to_v, bool is_duplicate) {
1710 const int from_v_i = from_v.to_index(key);
1711 const int to_v_i = to_v.to_index(key);
1712
1713 if (!is_duplicate) {
1714 floodfill_step[to_v_i] = floodfill_step[from_v_i] + 1;
1715 }
1716 else {
1717 floodfill_step[to_v_i] = floodfill_step[from_v_i];
1718 }
1719
1720 const int to_face_set = face_sets[grid_to_face_map[to_v.grid_index]];
1721 if (!visited_face_sets.contains(to_face_set)) {
1723 faces, corner_verts, vert_to_face_map, face_sets, subdiv_ccg, to_v) &&
1725 faces, corner_verts, vert_to_face_map, face_sets, subdiv_ccg, from_v) &&
1726 face_set::vert_has_face_set(subdiv_ccg, face_sets, from_v.grid_index, to_face_set))
1727 {
1728
1729 visited_face_sets.add(to_face_set);
1730
1731 if (floodfill_step[to_v_i] >= masked_face_set_it) {
1732 masked_face_set = to_face_set;
1733 masked_face_set_it = floodfill_step[to_v_i];
1734 }
1735
1736 if (target_face_set == SCULPT_FACE_SET_NONE) {
1737 target_face_set = to_face_set;
1738 }
1739 }
1740 }
1741
1743 subdiv_ccg, face_sets, to_v.grid_index, active_face_set);
1744 });
1745
1746 const std::optional<float3> origin = calc_average_face_set_center(
1747 depsgraph, object, floodfill_step, active_face_set, masked_face_set);
1748 ik_chain->segments[0].orig = origin.value_or(float3(0));
1749
1750 std::optional<float3> head = std::nullopt;
1751 if (target_face_set != masked_face_set) {
1753 depsgraph, object, floodfill_step, active_face_set, target_face_set);
1754 }
1755
1756 ik_chain->segments[0].head = head.value_or(initial_location);
1757 ik_chain->grab_delta_offset = ik_chain->segments[0].head - initial_location;
1758
1759 flood_fill::FillDataGrids weight_floodfill(grids_num, ss.fake_neighbors.fake_neighbor_index);
1760 weight_floodfill.add_initial(key, find_symm_verts_grids(object, active_vert_index, radius));
1761 MutableSpan<float> fk_weights = ik_chain->segments[0].weights;
1762 weight_floodfill.execute(
1763 object,
1764 subdiv_ccg,
1765 [&](SubdivCCGCoord /*from_v*/, SubdivCCGCoord to_v, bool /*is_duplicate*/) {
1766 int to_v_i = to_v.to_index(key);
1767
1768 fk_weights[to_v_i] = 1.0f;
1770 subdiv_ccg, face_sets, to_v.grid_index, masked_face_set);
1771 });
1772
1773 ik_chain_origin_heads_init(*ik_chain, ik_chain->segments[0].head);
1774 return ik_chain;
1775}
1776
1777static std::unique_ptr<IKChain> ik_chain_init_face_sets_fk_bmesh(const Depsgraph &depsgraph,
1778 Object &object,
1779 SculptSession &ss,
1780 const float radius,
1781 const float3 &initial_location)
1782{
1784
1785 BMesh &bm = *ss.bm;
1786 const int face_set_offset = CustomData_get_offset_named(
1787 &bm.pdata, CD_PROP_INT32, ".sculpt_face_set");
1788 const int verts_num = BM_mesh_elem_count(&bm, BM_VERT);
1789
1790 std::unique_ptr<IKChain> ik_chain = ik_chain_new(1, verts_num);
1791
1792 BMVert *active_vert = std::get<BMVert *>(ss.active_vert());
1793 const int active_vert_index = BM_elem_index_get(active_vert);
1794
1795 const int active_face_set = face_set::active_face_set_get(object);
1796
1797 Set<int> visited_face_sets;
1798 Array<int> floodfill_step(verts_num);
1799 floodfill_step[active_vert_index] = 1;
1800
1801 int masked_face_set = SCULPT_FACE_SET_NONE;
1802 int target_face_set = SCULPT_FACE_SET_NONE;
1803 int masked_face_set_it = 0;
1804 flood_fill::FillDataBMesh step_floodfill(verts_num, ss.fake_neighbors.fake_neighbor_index);
1805 step_floodfill.add_initial(active_vert);
1806 step_floodfill.execute(object, [&](BMVert *from_v, BMVert *to_v) {
1807 const int from_v_i = BM_elem_index_get(from_v);
1808 const int to_v_i = BM_elem_index_get(to_v);
1809
1810 floodfill_step[to_v_i] = floodfill_step[from_v_i] + 1;
1811
1812 const int to_face_set = face_set::vert_face_set_get(face_set_offset, *to_v);
1813 if (!visited_face_sets.contains(to_face_set)) {
1814 if (face_set::vert_has_unique_face_set(face_set_offset, *to_v) &&
1815 !face_set::vert_has_unique_face_set(face_set_offset, *from_v) &&
1816 face_set::vert_has_face_set(face_set_offset, *from_v, to_face_set))
1817 {
1818
1819 visited_face_sets.add(to_face_set);
1820
1821 if (floodfill_step[to_v_i] >= masked_face_set_it) {
1822 masked_face_set = to_face_set;
1823 masked_face_set_it = floodfill_step[to_v_i];
1824 }
1825
1826 if (target_face_set == SCULPT_FACE_SET_NONE) {
1827 target_face_set = to_face_set;
1828 }
1829 }
1830 }
1831
1832 return face_set::vert_has_face_set(face_set_offset, *to_v, active_face_set);
1833 });
1834
1835 const std::optional<float3> origin = calc_average_face_set_center(
1836 depsgraph, object, floodfill_step, active_face_set, masked_face_set);
1837 ik_chain->segments[0].orig = origin.value_or(float3(0));
1838
1839 std::optional<float3> head = std::nullopt;
1840 if (target_face_set != masked_face_set) {
1842 depsgraph, object, floodfill_step, active_face_set, target_face_set);
1843 }
1844
1845 ik_chain->segments[0].head = head.value_or(initial_location);
1846 ik_chain->grab_delta_offset = ik_chain->segments[0].head - initial_location;
1847
1848 flood_fill::FillDataBMesh weight_floodfill(verts_num, ss.fake_neighbors.fake_neighbor_index);
1849 weight_floodfill.add_initial(
1850 *ss.bm, find_symm_verts_bmesh(object, BM_elem_index_get(active_vert), radius));
1851 MutableSpan<float> fk_weights = ik_chain->segments[0].weights;
1852 weight_floodfill.execute(object, [&](BMVert * /*from_v*/, BMVert *to_v) {
1853 int to_v_i = BM_elem_index_get(to_v);
1854
1855 fk_weights[to_v_i] = 1.0f;
1856 return !face_set::vert_has_face_set(face_set_offset, *to_v, masked_face_set);
1857 });
1858
1859 ik_chain_origin_heads_init(*ik_chain, ik_chain->segments[0].head);
1860 return ik_chain;
1861}
1862
1863static std::unique_ptr<IKChain> ik_chain_init_face_sets_fk(const Depsgraph &depsgraph,
1864 Object &object,
1865 SculptSession &ss,
1866 const float radius,
1867 const float3 &initial_location)
1868{
1869 switch (bke::object::pbvh_get(object)->type()) {
1871 return ik_chain_init_face_sets_fk_mesh(depsgraph, object, ss, radius, initial_location);
1873 return ik_chain_init_face_sets_fk_grids(depsgraph, object, ss, radius, initial_location);
1875 return ik_chain_init_face_sets_fk_bmesh(depsgraph, object, ss, radius, initial_location);
1876 }
1878 return nullptr;
1879}
1880
1881static std::unique_ptr<IKChain> ik_chain_init(const Depsgraph &depsgraph,
1882 Object &ob,
1883 SculptSession &ss,
1884 const Brush &brush,
1885 const float3 &initial_location,
1886 const float radius)
1887{
1888 std::unique_ptr<IKChain> ik_chain;
1889
1890 const bool use_fake_neighbors = !(brush.flag2 & BRUSH_USE_CONNECTED_ONLY);
1891
1892 if (use_fake_neighbors) {
1894 }
1895 else {
1897 }
1898
1899 switch (brush.pose_origin_type) {
1901 ik_chain = ik_chain_init_topology(depsgraph, ob, ss, brush, initial_location, radius);
1902 break;
1904 ik_chain = ik_chain_init_face_sets(depsgraph, ob, ss, brush, radius);
1905 break;
1907 ik_chain = ik_chain_init_face_sets_fk(depsgraph, ob, ss, radius, initial_location);
1908 break;
1909 }
1910
1911 return ik_chain;
1912}
1913
1914static void pose_brush_init(const Depsgraph &depsgraph,
1915 Object &ob,
1916 SculptSession &ss,
1917 const Brush &brush)
1918{
1919 /* Init the IK chain that is going to be used to deform the vertices. */
1921 depsgraph, ob, ss, brush, ss.cache->location, ss.cache->radius);
1922
1923 /* Smooth the weights of each segment for cleaner deformation. */
1924 for (IKChainSegment &segment : ss.cache->pose_ik_chain->segments) {
1925 smooth::blur_geometry_data_array(ob, brush.pose_smooth_iterations, segment.weights);
1926 }
1927}
1928
1929std::unique_ptr<SculptPoseIKChainPreview> preview_ik_chain_init(const Depsgraph &depsgraph,
1930 Object &ob,
1931 SculptSession &ss,
1932 const Brush &brush,
1933 const float3 &initial_location,
1934 const float radius)
1935{
1936 const IKChain chain = *ik_chain_init(depsgraph, ob, ss, brush, initial_location, radius);
1937 std::unique_ptr<SculptPoseIKChainPreview> preview = std::make_unique<SculptPoseIKChainPreview>();
1938
1939 preview->initial_head_coords.reinitialize(chain.segments.size());
1940 preview->initial_orig_coords.reinitialize(chain.segments.size());
1941 for (const int i : chain.segments.index_range()) {
1942 preview->initial_head_coords[i] = chain.segments[i].initial_head;
1943 preview->initial_orig_coords[i] = chain.segments[i].initial_orig;
1944 }
1945
1946 return preview;
1947}
1948
1950{
1951 IKChain &ik_chain = *ss.cache->pose_ik_chain;
1953 solve_translate_chain(ik_chain, ss.cache->grab_delta);
1954}
1955
1956/* Calculate a scale factor based on the grab delta. */
1957static float calc_scale_from_grab_delta(SculptSession &ss, const float3 &ik_target)
1958{
1959 IKChain &ik_chain = *ss.cache->pose_ik_chain;
1960 const float3 segment_dir = math::normalize(ik_chain.segments[0].initial_head -
1961 ik_chain.segments[0].initial_orig);
1962 float4 plane;
1963 plane_from_point_normal_v3(plane, ik_chain.segments[0].initial_head, segment_dir);
1964 const float segment_len = ik_chain.segments[0].len;
1965 return segment_len / (segment_len - dist_signed_to_plane_v3(ik_target, plane));
1966}
1967
1968static void calc_scale_deform(SculptSession &ss, const Brush &brush)
1969{
1970 IKChain &ik_chain = *ss.cache->pose_ik_chain;
1971
1972 float3 ik_target = ss.cache->location + ss.cache->grab_delta;
1973
1974 /* Solve the IK for the first segment to include rotation as part of scale if enabled. */
1975 if (!(brush.flag2 & BRUSH_POSE_USE_LOCK_ROTATION)) {
1976 solve_ik_chain(ik_chain, ik_target, brush.flag2 & BRUSH_POSE_IK_ANCHORED);
1977 }
1978
1979 float3 scale(calc_scale_from_grab_delta(ss, ik_target));
1980
1981 /* Write the scale into the segments. */
1982 solve_scale_chain(ik_chain, scale);
1983}
1984
1985static void calc_twist_deform(SculptSession &ss, const Brush &brush)
1986{
1987 IKChain &ik_chain = *ss.cache->pose_ik_chain;
1988
1989 /* Calculate the maximum roll. 0.02 radians per pixel works fine. */
1990 float roll = (ss.cache->initial_mouse[0] - ss.cache->mouse[0]) * ss.cache->bstrength * 0.02f;
1992 solve_roll_chain(ik_chain, brush, roll);
1993}
1994
1995static void calc_rotate_deform(SculptSession &ss, const Brush &brush)
1996{
1997 IKChain &ik_chain = *ss.cache->pose_ik_chain;
1998
1999 /* Calculate the IK target. */
2000 float3 ik_target = ss.cache->location + ss.cache->grab_delta + ik_chain.grab_delta_offset;
2001
2002 /* Solve the IK positions. */
2003 solve_ik_chain(ik_chain, ik_target, brush.flag2 & BRUSH_POSE_IK_ANCHORED);
2004}
2005
2006static void calc_rotate_twist_deform(SculptSession &ss, const Brush &brush)
2007{
2008 if (ss.cache->invert) {
2009 calc_twist_deform(ss, brush);
2010 }
2011 else {
2012 calc_rotate_deform(ss, brush);
2013 }
2014}
2015
2017{
2018 if (ss.cache->invert) {
2020 }
2021 else {
2022 calc_scale_deform(ss, brush);
2023 }
2024}
2025
2026static void calc_squash_stretch_deform(SculptSession &ss, const Brush & /*brush*/)
2027{
2028 IKChain &ik_chain = *ss.cache->pose_ik_chain;
2029
2030 float3 ik_target = ss.cache->location + ss.cache->grab_delta;
2031
2032 float3 scale;
2033 scale[2] = calc_scale_from_grab_delta(ss, ik_target);
2034 scale[0] = scale[1] = sqrtf(1.0f / scale[2]);
2035
2036 /* Write the scale into the segments. */
2037 solve_scale_chain(ik_chain, scale);
2038}
2039
2040static void align_pivot_local_space(float r_mat[4][4],
2042 ePaintSymmetryAreas symm_area,
2043 IKChainSegment *segment,
2044 const float3 &grab_location)
2045{
2046 const float3 symm_head = SCULPT_flip_v3_by_symm_area(
2047 segment->head, symm, symm_area, grab_location);
2048 const float3 symm_orig = SCULPT_flip_v3_by_symm_area(
2049 segment->orig, symm, symm_area, grab_location);
2050
2051 float3 segment_origin_head = math::normalize(symm_head - symm_orig);
2052
2053 copy_v3_v3(r_mat[2], segment_origin_head);
2054 ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]);
2055}
2056
2057void do_pose_brush(const Depsgraph &depsgraph,
2058 const Sculpt &sd,
2059 Object &ob,
2060 const IndexMask &node_mask)
2061{
2062 SculptSession &ss = *ob.sculpt;
2064 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
2066
2067 if (!ss.cache->pose_ik_chain) {
2068 pose_brush_init(depsgraph, ob, ss, brush);
2069 }
2070
2071 /* The pose brush applies all enabled symmetry axis in a single iteration, so the rest can be
2072 * ignored. */
2073 if (ss.cache->mirror_symmetry_pass != 0) {
2074 return;
2075 }
2076
2077 IKChain &ik_chain = *ss.cache->pose_ik_chain;
2078
2079 switch (brush.pose_deform_type) {
2081 calc_rotate_twist_deform(ss, brush);
2082 break;
2084 calc_scale_translate_deform(ss, brush);
2085 break;
2087 calc_squash_stretch_deform(ss, brush);
2088 break;
2089 }
2090
2091 /* Flip the segment chain in all symmetry axis and calculate the transform matrices for each
2092 * possible combination. */
2093 /* This can be optimized by skipping the calculation of matrices where the symmetry is not
2094 * enabled. */
2095 for (int symm_it = 0; symm_it < PAINT_SYMM_AREAS; symm_it++) {
2096 for (const int i : ik_chain.segments.index_range()) {
2097 ePaintSymmetryAreas symm_area = ePaintSymmetryAreas(symm_it);
2098
2099 float symm_rot[4];
2100 copy_qt_qt(symm_rot, ik_chain.segments[i].rot);
2101
2102 /* Flip the origins and rotation quats of each segment. */
2103 SCULPT_flip_quat_by_symm_area(symm_rot, symm, symm_area, ss.cache->orig_grab_location);
2105 ik_chain.segments[i].orig, symm, symm_area, ss.cache->orig_grab_location);
2106 float3 symm_initial_orig = SCULPT_flip_v3_by_symm_area(
2107 ik_chain.segments[i].initial_orig, symm, symm_area, ss.cache->orig_grab_location);
2108
2109 float pivot_local_space[4][4];
2110 unit_m4(pivot_local_space);
2111
2112 /* Align the segment pivot local space to the Z axis. */
2114 align_pivot_local_space(pivot_local_space,
2115 symm,
2116 symm_area,
2117 &ik_chain.segments[i],
2119 unit_m4(ik_chain.segments[i].trans_mat[symm_it].ptr());
2120 }
2121 else {
2122 quat_to_mat4(ik_chain.segments[i].trans_mat[symm_it].ptr(), symm_rot);
2123 }
2124
2125 /* Apply segment scale to the transform. */
2126 for (int scale_i = 0; scale_i < 3; scale_i++) {
2127 mul_v3_fl(ik_chain.segments[i].trans_mat[symm_it][scale_i],
2128 ik_chain.segments[i].scale[scale_i]);
2129 }
2130
2131 translate_m4(ik_chain.segments[i].trans_mat[symm_it].ptr(),
2132 symm_orig[0] - symm_initial_orig[0],
2133 symm_orig[1] - symm_initial_orig[1],
2134 symm_orig[2] - symm_initial_orig[2]);
2135
2136 unit_m4(ik_chain.segments[i].pivot_mat[symm_it].ptr());
2138 ik_chain.segments[i].pivot_mat[symm_it].ptr(), symm_orig[0], symm_orig[1], symm_orig[2]);
2139 mul_m4_m4_post(ik_chain.segments[i].pivot_mat[symm_it].ptr(), pivot_local_space);
2140
2141 invert_m4_m4(ik_chain.segments[i].pivot_mat_inv[symm_it].ptr(),
2142 ik_chain.segments[i].pivot_mat[symm_it].ptr());
2143 }
2144 }
2145
2147 switch (pbvh.type()) {
2148 case bke::pbvh::Type::Mesh: {
2149 Mesh &mesh = *static_cast<Mesh *>(ob.data);
2150 const MeshAttributeData attribute_data(mesh);
2152 const PositionDeformData position_data(depsgraph, ob);
2153 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2154 BrushLocalData &tls = all_tls.local();
2155 calc_mesh(depsgraph, sd, brush, attribute_data, nodes[i], ob, tls, position_data);
2156 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
2157 });
2158 break;
2159 }
2161 SubdivCCG &subdiv_ccg = *ob.sculpt->subdiv_ccg;
2162 MutableSpan<float3> positions = subdiv_ccg.positions;
2164 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2165 BrushLocalData &tls = all_tls.local();
2166 calc_grids(depsgraph, sd, brush, nodes[i], ob, tls);
2167 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
2168 });
2169 break;
2170 }
2173 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2174 BrushLocalData &tls = all_tls.local();
2175 calc_bmesh(depsgraph, sd, brush, nodes[i], ob, tls);
2177 });
2178 break;
2179 }
2180 }
2181 pbvh.tag_positions_changed(node_mask);
2183}
2184
2185} // namespace blender::ed::sculpt_paint::pose
float BKE_brush_curve_strength(eBrushCurvePreset preset, const CurveMapping *cumap, float distance, float brush_radius)
Definition brush.cc:1577
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
Definition BKE_ccg.hh:73
void BKE_curvemapping_init(CurveMapping *cumap)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
#define PAINT_SYMM_AREAS
Definition BKE_paint.hh:115
ePaintSymmetryAreas
Definition BKE_paint.hh:108
#define SCULPT_FACE_SET_NONE
Definition BKE_paint.hh:324
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:650
A BVH for high poly meshes.
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_NOINLINE
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition math_geom.cc:217
float dist_signed_to_plane_v3(const float p[3], const float plane[4])
Definition math_geom.cc:495
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_m4_m4_post(float R[4][4], const float B[4][4])
void unit_m4(float m[4][4])
void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4])
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
void quat_to_mat4(float m[4][4], const float q[4])
void unit_qt(float q[4])
void axis_angle_normalized_to_quat(float r[4], const float axis[3], float angle)
void copy_qt_qt(float q[4], const float a[4])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3])
#define ELEM(...)
eBrushDeformTarget
@ BRUSH_DEFORM_TARGET_CLOTH_SIM
@ BRUSH_DEFORM_TARGET_GEOMETRY
@ BRUSH_POSE_DEFORM_SQUASH_STRETCH
@ BRUSH_POSE_DEFORM_ROTATE_TWIST
@ BRUSH_POSE_DEFORM_SCALE_TRASLATE
@ BRUSH_USE_CONNECTED_ONLY
@ BRUSH_POSE_USE_LOCK_ROTATION
@ BRUSH_POSE_IK_ANCHORED
@ BRUSH_POSE_ORIGIN_FACE_SETS_FK
@ BRUSH_POSE_ORIGIN_TOPOLOGY
@ BRUSH_POSE_ORIGIN_FACE_SETS
@ CD_PROP_INT32
Object is a sort of wrapper for general info.
ePaintSymmetryFlags
#define BM_elem_index_get(ele)
BMesh * bm
int BM_mesh_elem_count(BMesh *bm, const char htype)
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
#define BM_VERT
BPy_StructRNA * depsgraph
static T sum(const btAlignedObjectArray< T > &items)
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:248
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr bool is_empty() const
Definition BLI_span.hh:509
constexpr void fill(const T &value) const
Definition BLI_span.hh:517
constexpr Span< T > as_span() const
Definition BLI_span.hh:661
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
constexpr T & last(const int64_t n=0) const
Definition BLI_span.hh:689
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
constexpr bool is_empty() const
Definition BLI_span.hh:260
int64_t size() const
void append(const T &value)
void extend(Span< T > array)
Span< T > as_span() const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
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
nullptr float
#define rot(x, k)
static float verts[][3]
VecBase< float, 3 > float3
int count
static char faces[256]
IndexRange grid_range(const int grid_area, const int grid)
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
Definition pbvh.cc:2628
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
void update_node_bounds_grids(int grid_area, Span< float3 > positions, GridsNode &node)
Definition pbvh.cc:1283
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:1040
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)
int vert_face_set_get(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert)
Definition sculpt.cc:230
bool vert_has_unique_face_set(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, int vert)
Definition sculpt.cc:292
bool vert_has_face_set(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert, const int face_set)
Definition sculpt.cc:252
int active_face_set_get(const Object &object)
Definition sculpt.cc:196
Span< int > node_visible_verts(const bke::pbvh::MeshNode &node, const Span< bool > hide_vert, Vector< int > &indices)
void do_pose_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
static void grow_factors_bmesh(const ePaintSymmetryFlags symm, const float3 &pose_initial_position, const Span< int > fake_neighbors, const Span< float > prev_mask, bke::pbvh::BMeshNode &node, const MutableSpan< float > pose_factor, PoseGrowFactorData &gftd)
static std::unique_ptr< IKChain > ik_chain_init(const Depsgraph &depsgraph, Object &ob, SculptSession &ss, const Brush &brush, const float3 &initial_location, const float radius)
static BLI_NOINLINE void add_fake_neighbors(const Span< int > fake_neighbors, const Span< int > verts, const Span< int > orig_neighbor_data, MutableSpan< int > neighbor_offsets, Vector< int > &neighbor_data_with_fake)
static void solve_roll_chain(IKChain &ik_chain, const Brush &brush, const float roll)
static void calc_squash_stretch_deform(SculptSession &ss, const Brush &)
static std::unique_ptr< IKChain > ik_chain_init_face_sets(const Depsgraph &depsgraph, Object &object, SculptSession &ss, const Brush &brush, const float radius)
static void solve_translate_chain(IKChain &ik_chain, const float delta[3])
static void calc_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const MeshAttributeData &attribute_data, const bke::pbvh::MeshNode &node, Object &object, BrushLocalData &tls, const PositionDeformData &position_data)
static void grow_factors_grids(const ePaintSymmetryFlags symm, const float3 &pose_initial_position, const SubdivCCG &subdiv_ccg, const Span< int > fake_neighbors, const Span< float > prev_mask, const bke::pbvh::GridsNode &node, const MutableSpan< float > pose_factor, PoseGrowFactorData &gftd)
static BLI_NOINLINE void calc_segment_translations(const Span< float3 > positions, const IKChainSegment &segment, const MutableSpan< float3 > translations)
static void calc_rotate_deform(SculptSession &ss, const Brush &brush)
static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const bke::pbvh::GridsNode &node, Object &object, BrushLocalData &tls)
static bool vert_inside_brush_radius(const float3 &vertex, const float3 &br_co, float radius, char symm)
static int brush_num_effective_segments(const Brush &brush)
static std::unique_ptr< IKChain > ik_chain_init_face_sets_grids(Object &object, SculptSession &ss, const Brush &brush, const float radius)
static std::unique_ptr< IKChain > ik_chain_init_face_sets_fk_bmesh(const Depsgraph &depsgraph, Object &object, SculptSession &ss, const float radius, const float3 &initial_location)
static std::unique_ptr< IKChain > ik_chain_init_face_sets_fk(const Depsgraph &depsgraph, Object &object, SculptSession &ss, const float radius, const float3 &initial_location)
static float calc_scale_from_grab_delta(SculptSession &ss, const float3 &ik_target)
static void sculpt_pose_do_translate_deform(SculptSession &ss, const Brush &brush)
static void calc_scale_translate_deform(SculptSession &ss, const Brush &brush)
static void ik_chain_origin_heads_init(IKChain &ik_chain, const float3 &initial_location)
static std::unique_ptr< IKChain > ik_chain_init_face_sets_fk_mesh(const Depsgraph &depsgraph, Object &object, SculptSession &ss, const float radius, const float3 &initial_location)
static void calc_pose_origin_and_factor_bmesh(Object &object, SculptSession &ss, const float3 &initial_location, float radius, float3 &r_pose_origin, MutableSpan< float > r_pose_factor)
static void calc_twist_deform(SculptSession &ss, const Brush &brush)
static void calc_scale_deform(SculptSession &ss, const Brush &brush)
static std::unique_ptr< IKChain > ik_chain_init_face_sets_fk_grids(const Depsgraph &depsgraph, Object &object, SculptSession &ss, const float radius, const float3 &initial_location)
static std::unique_ptr< IKChain > ik_chain_new(const int totsegments, const int totverts)
static void calc_pose_origin_and_factor_mesh(const Depsgraph &depsgraph, Object &object, SculptSession &ss, const float3 &initial_location, float radius, float3 &r_pose_origin, MutableSpan< float > r_pose_factor)
static std::optional< float3 > calc_average_face_set_center(const Depsgraph &depsgraph, Object &object, const Span< int > floodfill_step, const int active_face_set, const int target_face_set)
static std::unique_ptr< IKChain > ik_chain_init_face_sets_bmesh(Object &object, SculptSession &ss, const Brush &brush, const float radius)
static BLI_NOINLINE void add_arrays(const MutableSpan< float3 > a, const Span< float3 > b)
static void calc_rotate_twist_deform(SculptSession &ss, const Brush &brush)
static void solve_scale_chain(IKChain &ik_chain, const float scale[3])
static std::unique_ptr< IKChain > ik_chain_init_face_sets_mesh(const Depsgraph &depsgraph, Object &object, SculptSession &ss, const Brush &brush, const float radius)
static void align_pivot_local_space(float r_mat[4][4], ePaintSymmetryFlags symm, ePaintSymmetryAreas symm_area, IKChainSegment *segment, const float3 &grab_location)
static void grow_factors_mesh(const ePaintSymmetryFlags symm, const float3 &pose_initial_position, const Span< float3 > vert_positions, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const Span< bool > hide_vert, const Span< bool > hide_poly, const Span< int > fake_neighbors, const Span< float > prev_mask, const bke::pbvh::MeshNode &node, GrowFactorLocalData &tls, const MutableSpan< float > pose_factor, PoseGrowFactorData &gftd)
static void solve_ik_chain(IKChain &ik_chain, const float3 &initial_target, const bool use_anchor)
static void grow_pose_factor(const Depsgraph &depsgraph, Object &ob, SculptSession &ss, float pose_origin[3], float pose_target[3], float max_len, float *r_pose_origin, MutableSpan< float > pose_factor)
static std::unique_ptr< IKChain > ik_chain_init_topology(const Depsgraph &depsgraph, Object &object, SculptSession &ss, const Brush &brush, const float3 &initial_location, const float radius)
static void calc_pose_origin_and_factor_grids(Object &object, SculptSession &ss, const float3 &initial_location, float radius, float3 &r_pose_origin, MutableSpan< float > r_pose_factor)
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, bke::pbvh::BMeshNode &node, Object &object, BrushLocalData &tls)
static void calc_pose_data(const Depsgraph &depsgraph, Object &object, SculptSession &ss, const float3 &initial_location, float radius, float pose_offset, float3 &r_pose_origin, MutableSpan< float > r_pose_factor)
std::unique_ptr< SculptPoseIKChainPreview > preview_ik_chain_init(const Depsgraph &depsgraph, Object &ob, SculptSession &ss, const Brush &brush, const float3 &initial_location, const float radius)
static void pose_brush_init(const Depsgraph &depsgraph, Object &ob, SculptSession &ss, const Brush &brush)
void blur_geometry_data_array(const Object &object, const int iterations, const MutableSpan< float > data)
void fill_factor_from_hide_and_mask(Span< bool > hide_vert, Span< float > mask, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6823
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
void scatter_data_bmesh(Span< T > node_data, const Set< BMVert *, 0 > &verts, MutableSpan< T > dst)
Definition sculpt.cc:6461
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6367
void gather_data_grids(const SubdivCCG &subdiv_ccg, Span< T > src, Span< int > grids, MutableSpan< T > node_data)
Definition sculpt.cc:6405
void vert_random_access_ensure(Object &object)
Definition sculpt.cc:141
std::optional< int > nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh, const Span< float3 > vert_positions, const Span< bool > hide_vert, const float3 &location, const float max_distance, const bool use_original)
Definition sculpt.cc:592
Vector< int > find_symm_verts_grids(const Object &object, const int original_vert, const float max_distance)
GroupedSpan< int > calc_vert_neighbors(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, Span< bool > hide_poly, Span< int > verts, Vector< int > &r_offset_data, Vector< int > &r_data)
Definition sculpt.cc:7597
Vector< BMVert *, 64 > BMeshNeighborVerts
void gather_data_bmesh(Span< T > src, const Set< BMVert *, 0 > &verts, MutableSpan< T > node_data)
Definition sculpt.cc:6421
void reset_translations_to_original(MutableSpan< float3 > translations, Span< float3 > positions, Span< float3 > orig_positions)
Definition sculpt.cc:7249
float3 symmetry_flip(const float3 &src, const ePaintSymmetryFlags symm)
void orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
Definition sculpt.cc:7495
Vector< int > find_symm_verts_mesh(const Depsgraph &depsgraph, const Object &object, const int original_vert, const float max_distance)
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 scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6435
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, BMeshNeighborVerts &r_neighbors)
Definition sculpt.cc:387
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:7268
OrigPositionData orig_position_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6395
OrigPositionData orig_position_data_get_grids(const Object &object, const bke::pbvh::GridsNode &node)
std::optional< BMVert * > nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh, const float3 &location, const float max_distance, const bool use_original)
Definition sculpt.cc:693
std::optional< SubdivCCGCoord > nearest_vert_calc_grids(const bke::pbvh::Tree &pbvh, const SubdivCCG &subdiv_ccg, const float3 &location, const float max_distance, const bool use_original)
Definition sculpt.cc:639
Span< int > vert_neighbors_get_mesh(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face, const Span< bool > hide_poly, const int vert, Vector< int > &r_neighbors)
Definition sculpt.cc:429
void scatter_data_grids(const SubdivCCG &subdiv_ccg, Span< T > node_data, Span< int > grids, MutableSpan< T > dst)
Definition sculpt.cc:6445
Vector< int > find_symm_verts_bmesh(const Object &object, const int original_vert, const float max_distance)
bool is_symmetry_iteration_valid(const char i, const char symm)
T distance(const T &a, const T &b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:151
VecBase< float, 4 > float4
VecBase< float, 3 > float3
#define sqrtf
ePaintSymmetryFlags SCULPT_mesh_symmetry_xyz_get(const Object &object)
Definition sculpt.cc:184
Span< int > SCULPT_fake_neighbors_ensure(const Depsgraph &depsgraph, Object &ob, const float max_dist)
Definition sculpt.cc:6098
float3 SCULPT_flip_v3_by_symm_area(const float3 &vector, const ePaintSymmetryFlags symm, const ePaintSymmetryAreas symmarea, const float3 &pivot)
Definition sculpt.cc:2868
int SCULPT_vertex_count_get(const Object &object)
Definition sculpt.cc:151
void SCULPT_fake_neighbors_free(Object &ob)
Definition sculpt.cc:6120
bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
Definition sculpt.cc:548
ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3])
Definition sculpt.cc:2825
void SCULPT_flip_quat_by_symm_area(float quat[4], const ePaintSymmetryFlags symm, const ePaintSymmetryAreas symmarea, const float pivot[3])
Definition sculpt.cc:2889
#define FAKE_NEIGHBOR_NONE
#define FLT_MAX
Definition stdcycles.h:14
float co[3]
CustomData pdata
int pose_deform_type
int pose_smooth_iterations
struct CurveMapping * curve_distance_falloff
int pose_ik_segments
float disconnected_distance_max
int deform_target
float pose_offset
int pose_origin_type
int grid_size
Definition BKE_ccg.hh:33
int grid_area
Definition BKE_ccg.hh:35
struct SculptSession * sculpt
blender::Array< int > fake_neighbor_index
Definition BKE_paint.hh:349
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:417
BMLog * bm_log
Definition BKE_paint.hh:392
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
ActiveVert active_vert() const
Definition paint.cc:2367
int active_vert_index() const
Definition paint.cc:2377
SculptFakeNeighbors fake_neighbors
Definition BKE_paint.hh:463
int to_index(const CCGKey &key) const
static SubdivCCGCoord from_index(const CCGKey &key, int index)
SubdivCCGNeighborCoords coords
blender::BitGroupVector grid_hidden
blender::Array< blender::float3 > positions
std::unique_ptr< pose::IKChain > pose_ik_chain
std::unique_ptr< auto_mask::Cache > automasking
std::unique_ptr< cloth::SimulationData > cloth_sim
void execute(Object &object, FunctionRef< bool(BMVert *from_v, BMVert *to_v)> func)
void execute(Object &object, const SubdivCCG &subdiv_ccg, FunctionRef< bool(SubdivCCGCoord from_v, SubdivCCGCoord to_v, bool is_duplicate)> func)
void execute(Object &object, GroupedSpan< int > vert_to_face_map, FunctionRef< bool(int from_v, int to_v)> func)
static PoseGrowFactorData join(const PoseGrowFactorData &a, const PoseGrowFactorData &b)
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint len