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