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