Blender V4.3
deg_builder_relations_rig.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12
13#include <cstdio>
14#include <cstdlib>
15#include <cstring> /* required for STREQ later on. */
16
17#include "MEM_guardedalloc.h"
18
19#include "BLI_blenlib.h"
20#include "BLI_utildefines.h"
21
22#include "DNA_action_types.h"
23#include "DNA_anim_types.h"
24#include "DNA_armature_types.h"
27#include "DNA_object_types.h"
28
29#include "BKE_action.hh"
30#include "BKE_armature.hh"
31#include "BKE_constraint.h"
32#include "BKE_lib_query.hh"
33
34#include "RNA_prototypes.hh"
35
36#include "DEG_depsgraph.hh"
38
46
49
50namespace blender::deg {
51
52/* IK Solver Eval Steps */
54 bPoseChannel *pchan,
55 bConstraint *con,
56 RootPChanMap *root_map)
57{
58 if ((con->flag & CONSTRAINT_DISABLE) != 0) {
59 /* Do not add disabled IK constraints to the relations. If these needs to be temporarily
60 * enabled, they will be added as temporary constraints during transform. */
61 return;
62 }
63
65 /* Attach owner to IK Solver to. */
66 bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
67 if (rootchan == nullptr) {
68 return;
69 }
70 OperationKey pchan_local_key(
71 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
73 OperationKey solver_key(
75 OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
76 /* If any of the constraint parameters are animated, connect the relation. Since there is only
77 * one Init IK node per armature, this link has quite high risk of spurious dependency cycles.
78 */
79 const bool is_itasc = (object->pose->iksolver == IKSOLVER_ITASC);
80 PointerRNA con_ptr = RNA_pointer_create(&object->id, &RNA_Constraint, con);
81 if (is_itasc || cache_->isAnyPropertyAnimated(&con_ptr)) {
82 add_relation(pchan_local_key, init_ik_key, "IK Constraint -> Init IK Tree");
83 }
84 add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
85 /* Never cleanup before solver is run. */
86 add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup", RELATION_FLAG_GODMODE);
87 /* The ITASC solver currently accesses the target transforms in init tree :(
88 * TODO: Fix ITASC and remove this.
89 */
90 OperationKey target_dependent_key = is_itasc ? init_ik_key : solver_key;
91 /* IK target */
92 /* TODO(sergey): This should get handled as part of the constraint code. */
93 if (data->tar != nullptr) {
94 /* Different object - requires its transform. */
95 if (data->tar != object) {
96 ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM);
97 add_relation(target_key, target_dependent_key, con->name);
98 /* Ensure target evaluated copy is ready by the time IK tree is built just in case. */
99 ComponentKey target_cow_key(&data->tar->id, NodeType::COPY_ON_EVAL);
100 add_relation(target_cow_key,
101 init_ik_key,
102 "IK Target Copy-on-Eval -> Init IK Tree",
104 }
105 /* Subtarget references: */
106 if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
107 /* Bone - use the final transformation. */
108 OperationKey target_key(
109 &data->tar->id, NodeType::BONE, data->subtarget, OperationCode::BONE_DONE);
110 add_relation(target_key, target_dependent_key, con->name);
111 }
112 else if (data->subtarget[0] && ELEM(data->tar->type, OB_MESH, OB_LATTICE)) {
113 /* Vertex group target. */
114 /* NOTE: for now, we don't need to represent vertex groups
115 * separately. */
116 ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY);
117 add_relation(target_key, target_dependent_key, con->name);
119 }
120 if (data->tar == object && data->subtarget[0]) {
121 /* Prevent target's constraints from linking to anything from same
122 * chain that it controls. */
123 root_map->add_bone(data->subtarget, rootchan->name);
124 }
125 }
126 /* Pole Target. */
127 /* TODO(sergey): This should get handled as part of the constraint code. */
128 if (data->poletar != nullptr) {
129 /* Different object - requires its transform. */
130 if (data->poletar != object) {
131 ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM);
132 add_relation(target_key, target_dependent_key, con->name);
133 /* Ensure target evaluated copy is ready by the time IK tree is built just in case. */
134 ComponentKey target_cow_key(&data->poletar->id, NodeType::COPY_ON_EVAL);
135 add_relation(target_cow_key,
136 init_ik_key,
137 "IK Target Copy-on-Eval -> Init IK Tree",
139 }
140 /* Subtarget references: */
141 if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
142 /* Bone - use the final transformation. */
143 OperationKey target_key(
144 &data->poletar->id, NodeType::BONE, data->polesubtarget, OperationCode::BONE_DONE);
145 add_relation(target_key, target_dependent_key, con->name);
146 }
147 else if (data->polesubtarget[0] && ELEM(data->poletar->type, OB_MESH, OB_LATTICE)) {
148 /* Vertex group target. */
149 /* NOTE: for now, we don't need to represent vertex groups
150 * separately. */
151 ComponentKey target_key(&data->poletar->id, NodeType::GEOMETRY);
152 add_relation(target_key, target_dependent_key, con->name);
154 }
155 }
156 DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
157 BUILD,
158 "\nStarting IK Build: pchan = %s, target = (%s, %s), "
159 "segcount = %d\n",
160 pchan->name,
161 data->tar ? data->tar->id.name : "nullptr",
162 data->subtarget,
163 data->rootbone);
164 bPoseChannel *parchan = pchan;
165 /* Exclude tip from chain if needed. */
166 if (!(data->flag & CONSTRAINT_IK_TIP)) {
167 parchan = pchan->parent;
168 }
169 root_map->add_bone(parchan->name, rootchan->name);
170 OperationKey parchan_transforms_key(
171 &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY);
172 add_relation(parchan_transforms_key, solver_key, "IK Solver Owner");
173 /* Walk to the chain's root. */
174 int segcount = 0;
175 while (parchan != nullptr) {
176 /* Make IK-solver dependent on this bone's result, since it can only run
177 * after the standard results of the bone are know. Validate links step
178 * on the bone will ensure that users of this bone only grab the result
179 * with IK solver results. */
180 if (parchan != pchan) {
181 OperationKey parent_key(
182 &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY);
183 add_relation(parent_key, solver_key, "IK Chain Parent");
184 OperationKey bone_done_key(
185 &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE);
186 add_relation(solver_key, bone_done_key, "IK Chain Result");
187 }
188 else {
189 OperationKey final_transforms_key(
190 &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE);
191 add_relation(solver_key, final_transforms_key, "IK Solver Result");
192 }
193 parchan->flag |= POSE_DONE;
194 root_map->add_bone(parchan->name, rootchan->name);
195 /* continue up chain, until we reach target number of items. */
196 DEG_DEBUG_PRINTF((::Depsgraph *)graph_, BUILD, " %d = %s\n", segcount, parchan->name);
197 /* TODO(sergey): This is an arbitrary value, which was just following
198 * old code convention. */
199 segcount++;
200 if ((segcount == data->rootbone) || (segcount > 255)) {
201 break;
202 }
203 parchan = parchan->parent;
204 }
205 OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
206 add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
207
208 /* Add relation when the root of this IK chain is influenced by another IK chain. */
209 build_inter_ik_chains(object, solver_key, rootchan, root_map);
210}
211
212/* Spline IK Eval Steps */
214 bPoseChannel *pchan,
215 bConstraint *con,
216 RootPChanMap *root_map)
217{
220 OperationKey transforms_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
222 OperationKey solver_key(
224 OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
225 /* Solver depends on initialization. */
226 add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
227 /* Never cleanup before solver is run. */
228 add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup");
229 /* Attach owner to IK Solver. */
230 add_relation(transforms_key, solver_key, "Spline IK Solver Owner", RELATION_FLAG_GODMODE);
231 /* Attach path dependency to solver. */
232 if (data->tar != nullptr) {
233 ComponentKey target_geometry_key(&data->tar->id, NodeType::GEOMETRY);
234 add_relation(target_geometry_key, solver_key, "Curve.Path -> Spline IK");
235 ComponentKey target_transform_key(&data->tar->id, NodeType::TRANSFORM);
236 add_relation(target_transform_key, solver_key, "Curve.Transform -> Spline IK");
238 }
239 pchan->flag |= POSE_DONE;
240 OperationKey final_transforms_key(
241 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
242 add_relation(solver_key, final_transforms_key, "Spline IK Result");
243 root_map->add_bone(pchan->name, rootchan->name);
244 /* Walk to the chain's root/ */
245 int segcount = 1;
246 for (bPoseChannel *parchan = pchan->parent; parchan != nullptr && segcount < data->chainlen;
247 parchan = parchan->parent, segcount++)
248 {
249 /* Make Spline IK solver dependent on this bone's result, since it can
250 * only run after the standard results of the bone are know. Validate
251 * links step on the bone will ensure that users of this bone only grab
252 * the result with IK solver results. */
253 OperationKey parent_key(&object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY);
254 add_relation(parent_key, solver_key, "Spline IK Solver Update");
255 OperationKey bone_done_key(
256 &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE);
257 add_relation(solver_key, bone_done_key, "Spline IK Solver Result");
258 parchan->flag |= POSE_DONE;
259 root_map->add_bone(parchan->name, rootchan->name);
260 }
261 OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
262 add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
263
264 /* Add relation when the root of this IK chain is influenced by another IK chain. */
265 build_inter_ik_chains(object, solver_key, rootchan, root_map);
266}
267
269 const OperationKey &solver_key,
270 const bPoseChannel *rootchan,
271 const RootPChanMap *root_map)
272{
273 bPoseChannel *deepest_root = nullptr;
274 const char *root_name = rootchan->name;
275
276 /* Find shared IK chain root. */
277 for (bPoseChannel *parchan = rootchan->parent; parchan; parchan = parchan->parent) {
278 if (!root_map->has_common_root(root_name, parchan->name)) {
279 break;
280 }
281 deepest_root = parchan;
282 }
283 if (deepest_root == nullptr) {
284 return;
285 }
286
287 OperationKey other_bone_key(
288 &object->id, NodeType::BONE, deepest_root->name, OperationCode::BONE_DONE);
289 add_relation(other_bone_key, solver_key, "IK Chain Overlap");
290}
291
292/* Pose/Armature Bones Graph */
294{
295 /* Armature-Data */
296 bArmature *armature = (bArmature *)object->data;
297 /* TODO: selection status? */
298 /* Attach links between pose operations. */
299 ComponentKey local_transform(&object->id, NodeType::TRANSFORM);
300 OperationKey pose_init_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
301 OperationKey pose_init_ik_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
302 OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
303 OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
304 add_relation(local_transform, pose_init_key, "Local Transform -> Pose Init");
305 add_relation(pose_init_key, pose_init_ik_key, "Pose Init -> Pose Init IK");
306 add_relation(pose_init_ik_key, pose_done_key, "Pose Init IK -> Pose Cleanup");
307 /* Make sure pose is up-to-date with armature updates. */
308 build_armature(armature);
310 add_relation(armature_key, pose_init_key, "Data dependency");
311 /* Run cleanup even when there are no bones. */
312 add_relation(pose_init_ik_key, pose_cleanup_key, "Init -> Cleanup");
313 /* Relation to the instance, so that instancer can use pose of this object. */
315 OperationKey{&object->id, NodeType::INSTANCING, OperationCode::INSTANCE},
316 "Transform -> Instance");
317
318 /* IK Solvers.
319 *
320 * - These require separate processing steps are pose-level to be executed
321 * between chains of bones (i.e. once the base transforms of a bunch of
322 * bones is done).
323 *
324 * - We build relations for these before the dependencies between operations
325 * in the same component as it is necessary to check whether such bones
326 * are in the same IK chain (or else we get weird issues with either
327 * in-chain references, or with bones being parented to IK'd bones).
328 *
329 * Unsolved Issues:
330 * - Care is needed to ensure that multi-headed trees work out the same as
331 * in ik-tree building
332 * - Animated chain-lengths are a problem. */
333 RootPChanMap root_map;
334 bool pose_depends_on_local_transform = false;
335 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
336 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*pchan);
337
338 LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
339 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*con);
340
341 switch (con->type) {
343 build_ik_pose(object, pchan, con, &root_map);
344 pose_depends_on_local_transform = true;
345 break;
347 build_splineik_pose(object, pchan, con, &root_map);
348 pose_depends_on_local_transform = true;
349 break;
350 /* Constraints which needs world's matrix for transform.
351 * TODO(sergey): More constraints here? */
356 /* TODO(sergey): Add used space check. */
357 pose_depends_on_local_transform = true;
358 break;
359 default:
360 break;
361 }
362 }
363 }
364 // root_map.print_debug();
365 if (pose_depends_on_local_transform) {
366 /* TODO(sergey): Once partial updates are possible use relation between
367 * object transform and solver itself in its build function. */
368 ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
369 ComponentKey local_transform_key(&object->id, NodeType::TRANSFORM);
370 add_relation(local_transform_key, pose_key, "Local Transforms");
371 }
372 /* Links between operations for each bone. */
373 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
374 const BuilderStack::ScopedEntry stack_entry = stack_.trace(*pchan);
375
376 build_idproperties(pchan->prop);
377 OperationKey bone_local_key(
378 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
379 OperationKey bone_pose_key(
380 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_POSE_PARENT);
381 OperationKey bone_ready_key(
382 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
383 OperationKey bone_done_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
384 pchan->flag &= ~POSE_DONE;
385 /* Pose init to bone local. */
386 add_relation(pose_init_key, bone_local_key, "Pose Init - Bone Local", RELATION_FLAG_GODMODE);
387 /* Local to pose parenting operation. */
388 add_relation(bone_local_key, bone_pose_key, "Bone Local - Bone Pose");
389 /* Parent relation. */
390 if (pchan->parent != nullptr) {
391 OperationCode parent_key_opcode;
392 /* NOTE: this difference in handling allows us to prevent lockups
393 * while ensuring correct poses for separate chains. */
394 if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
395 parent_key_opcode = OperationCode::BONE_READY;
396 }
397 else {
398 parent_key_opcode = OperationCode::BONE_DONE;
399 }
400
401 OperationKey parent_key(&object->id, NodeType::BONE, pchan->parent->name, parent_key_opcode);
402 add_relation(parent_key, bone_pose_key, "Parent Bone -> Child Bone");
403 }
404 /* Build constraints. */
405 if (pchan->constraints.first != nullptr) {
406 /* Build relations for indirectly linked objects. */
407 BuilderWalkUserData data;
408 data.builder = this;
409 BKE_constraints_id_loop(&pchan->constraints, constraint_walk, IDWALK_NOP, &data);
410 /* Constraints stack and constraint dependencies. */
411 build_constraints(&object->id, NodeType::BONE, pchan->name, &pchan->constraints, &root_map);
412 /* Pose -> constraints. */
413 OperationKey constraints_key(
414 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_CONSTRAINTS);
415 add_relation(bone_pose_key, constraints_key, "Pose -> Constraints Stack");
416 add_relation(bone_local_key, constraints_key, "Local -> Constraints Stack");
417 /* Constraints -> ready/ */
418 /* TODO(sergey): When constraint stack is exploded, this step should
419 * occur before the first IK solver. */
420 add_relation(constraints_key, bone_ready_key, "Constraints -> Ready");
421 }
422 else {
423 /* Pose -> Ready */
424 add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready");
425 }
426 /* Bone ready -> Bone done.
427 * NOTE: For bones without IK, this is all that's needed.
428 * For IK chains however, an additional rel is created from IK
429 * to done, with transitive reduction removing this one. */
430 add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
431 /* B-Bone shape is the real final step after Done if present. */
432 if (check_pchan_has_bbone(object, pchan)) {
433 OperationKey bone_segments_key(
434 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS);
435 /* B-Bone shape depends on the final position of the bone. */
436 add_relation(bone_done_key, bone_segments_key, "Done -> B-Bone Segments");
437 /* B-Bone shape depends on final position of handle bones. */
438 bPoseChannel *prev, *next;
439 BKE_pchan_bbone_handles_get(pchan, &prev, &next);
440 if (prev) {
442 /* Inheriting parent roll requires access to prev handle's B-Bone properties. */
443 if ((pchan->bone->bbone_flag & BBONE_ADD_PARENT_END_ROLL) != 0 &&
444 check_pchan_has_bbone_segments(object, prev))
445 {
447 }
448 OperationKey prev_key(&object->id, NodeType::BONE, prev->name, opcode);
449 add_relation(prev_key, bone_segments_key, "Prev Handle -> B-Bone Segments");
450 }
451 if (next) {
452 OperationKey next_key(&object->id, NodeType::BONE, next->name, OperationCode::BONE_DONE);
453 add_relation(next_key, bone_segments_key, "Next Handle -> B-Bone Segments");
454 }
455 /* Pose requires the B-Bone shape. */
457 bone_segments_key, pose_done_key, "PoseEval Result-Bone Link", RELATION_FLAG_GODMODE);
458 add_relation(bone_segments_key, pose_cleanup_key, "Cleanup dependency");
459 }
460 else {
461 /* Assume that all bones must be done for the pose to be ready
462 * (for deformers). */
463 add_relation(bone_done_key, pose_done_key, "PoseEval Result-Bone Link");
464
465 /* Bones must be traversed before cleanup. */
466 add_relation(bone_done_key, pose_cleanup_key, "Done -> Cleanup");
467
468 add_relation(bone_ready_key, pose_cleanup_key, "Ready -> Cleanup");
469 }
470 /* Custom shape. */
471 if (pchan->custom != nullptr) {
472 build_object(pchan->custom);
473 add_visibility_relation(&pchan->custom->id, &armature->id);
474 }
475 }
476}
477
478} // namespace blender::deg
Blender kernel action and pose functionality.
bPoseChannel * BKE_armature_ik_solver_find_root(bPoseChannel *pchan, bKinematicConstraint *data)
Definition armature.cc:3132
void BKE_pchan_bbone_handles_get(bPoseChannel *pchan, bPoseChannel **r_prev, bPoseChannel **r_next)
Definition armature.cc:1061
bPoseChannel * BKE_armature_splineik_solver_find_root(bPoseChannel *pchan, bSplineIKConstraint *data)
Definition armature.cc:3153
void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, const int flag, void *userdata)
@ IDWALK_NOP
#define LISTBASE_FOREACH(type, var, list)
#define ELEM(...)
@ DAG_EVAL_NEED_CURVE_PATH
@ IKSOLVER_ITASC
@ BBONE_ADD_PARENT_END_ROLL
@ CONSTRAINT_DISABLE
@ CONSTRAINT_IK_TIP
@ CONSTRAINT_TYPE_LOCLIKE
@ CONSTRAINT_TYPE_ROTLIKE
@ CONSTRAINT_TYPE_SPLINEIK
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_TRANSLIKE
@ CONSTRAINT_TYPE_SIZELIKE
#define CD_MASK_MDEFORMVERT
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_ARMATURE
@ OB_MESH
Read Guarded memory(de)allocation.
ScopedEntry trace(const Args &...args)
bool isAnyPropertyAnimated(const PointerRNA *ptr)
DepsgraphBuilderCache * cache_
Definition deg_builder.h:53
virtual bool check_pchan_has_bbone_segments(const Object *object, const bPoseChannel *pchan)
virtual bool check_pchan_has_bbone(const Object *object, const bPoseChannel *pchan)
virtual void build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map)
virtual void build_armature(bArmature *armature)
virtual void build_constraints(ID *id, NodeType component_type, const char *component_subdata, ListBase *constraints, RootPChanMap *root_map)
void add_customdata_mask(Object *object, const DEGCustomDataMeshMasks &customdata_masks)
void add_special_eval_flag(ID *id, uint32_t flag)
Relation * add_relation(const KeyFrom &key_from, const KeyTo &key_to, const char *description, int flags=0)
void add_visibility_relation(ID *id_from, ID *id_to)
virtual void build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map)
virtual void build_inter_ik_chains(Object *object, const OperationKey &solver_key, const bPoseChannel *rootchan, const RootPChanMap *root_map)
virtual void build_idproperties(IDProperty *id_property)
#define DEG_DEBUG_PRINTF(depsgraph, type,...)
Definition deg_debug.h:45
static ulong * next
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
struct bPoseChannel * parent
static DEGCustomDataMeshMasks MaskVert(const uint64_t vert_mask)
bool has_common_root(const char *bone1, const char *bone2) const
void add_bone(const char *bone, const char *root)