/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2013 Blender Foundation. * All rights reserved. * * Original Author: Joshua Leung * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013) * * ***** END GPL LICENSE BLOCK ***** */ /** \file blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc * \ingroup depsgraph * * Methods for constructing depsgraph's nodes */ #include "intern/builder/deg_builder_nodes.h" #include #include #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" #include "BLI_blenlib.h" #include "BLI_string.h" extern "C" { #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_object_types.h" #include "BKE_action.h" #include "BKE_armature.h" } /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "intern/builder/deg_builder.h" #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.h" #include "intern/depsgraph_types.h" #include "intern/depsgraph_intern.h" #include "util/deg_util_foreach.h" namespace DEG { void DepsgraphNodeBuilder::build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan) { /* create node for constraint stack */ add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, function_bind(BKE_pose_constraints_evaluate, _1, scene, ob, pchan), DEG_OPCODE_BONE_CONSTRAINTS); } /* IK Solver Eval Steps */ void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con) { bKinematicConstraint *data = (bKinematicConstraint *)con->data; /* Find the chain's root. */ bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data); if (has_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER)) { return; } /* Operation node for evaluating/running IK Solver. */ add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan), DEG_OPCODE_POSE_IK_SOLVER); } /* Spline IK Eval Steps */ void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con) { bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; /* Find the chain's root. */ bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data); /* Operation node for evaluating/running Spline IK Solver. * Store the "root bone" of this chain in the solver, so it knows where to start. */ add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan), DEG_OPCODE_POSE_SPLINE_IK_SOLVER); } /* Pose/Armature Bones Graph */ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob) { bArmature *arm = (bArmature *)ob->data; OperationDepsNode *op_node; /* animation and/or drivers linking posebones to base-armature used to define them * NOTE: AnimData here is really used to control animated deform properties, * which ideally should be able to be unique across different instances. * Eventually, we need some type of proxy/isolation mechanism in-between here * to ensure that we can use same rig multiple times in same scene... */ if ((arm->id.tag & LIB_TAG_DOIT) == 0) { build_animdata(&arm->id); /* Make sure pose is up-to-date with armature updates. */ add_operation_node(&arm->id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PLACEHOLDER, "Armature Eval"); } /* Rebuild pose if not up to date. */ if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) { BKE_pose_rebuild(ob, arm); /* XXX: Without this animation gets lost in certain circumstances * after loading file. Need to investigate further since it does * not happen with simple scenes.. */ if (ob->adt) { ob->adt->recalc |= ADT_RECALC_ANIM; } } /* speed optimization for animation lookups */ if (ob->pose) { BKE_pose_channels_hash_make(ob->pose); if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { BKE_pose_update_constraint_flags(ob->pose); } } /** * Pose Rig Graph * ============== * * Pose Component: * - Mainly used for referencing Bone components. * - This is where the evaluation operations for init/exec/cleanup * (ik) solvers live, and are later hooked up (so that they can be * interleaved during runtime) with bone-operations they depend on/affect. * - init_pose_eval() and cleanup_pose_eval() are absolute first and last * steps of pose eval process. ALL bone operations must be performed * between these two... * * Bone Component: * - Used for representing each bone within the rig * - Acts to encapsulate the evaluation operations (base matrix + parenting, * and constraint stack) so that they can be easily found. * - Everything else which depends on bone-results hook up to the component only * so that we can redirect those to point at either the the post-IK/ * post-constraint/post-matrix steps, as needed. */ /* pose eval context */ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_INIT); op_node->set_as_entry(); op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_DONE); op_node->set_as_exit(); /* bones */ LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { /* node for bone eval */ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, DEG_OPCODE_BONE_LOCAL); op_node->set_as_entry(); add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), DEG_OPCODE_BONE_POSE_PARENT); add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, /* NOTE: dedicated noop for easier relationship construction */ DEG_OPCODE_BONE_READY); op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, function_bind(BKE_pose_bone_done, _1, pchan), DEG_OPCODE_BONE_DONE); op_node->set_as_exit(); /* constraints */ if (pchan->constraints.first != NULL) { build_pose_constraints(scene, ob, pchan); } /** * IK Solvers... * * - These require separate processing steps are pose-level * to be executed between chains of bones (i.e. once the * base transforms of a bunch of bones is done) * * Unsolved Issues: * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building * - Animated chain-lengths are a problem... */ LINKLIST_FOREACH (bConstraint *, con, &pchan->constraints) { switch (con->type) { case CONSTRAINT_TYPE_KINEMATIC: build_ik_pose(scene, ob, pchan, con); break; case CONSTRAINT_TYPE_SPLINEIK: build_splineik_pose(scene, ob, pchan, con); break; default: break; } } } } void DepsgraphNodeBuilder::build_proxy_rig(Object *ob) { ID *obdata = (ID *)ob->data; OperationDepsNode *op_node; build_animdata(obdata); BLI_assert(ob->pose != NULL); /* speed optimization for animation lookups */ BKE_pose_channels_hash_make(ob->pose); if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { BKE_pose_update_constraint_flags(ob->pose); } op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, function_bind(BKE_pose_eval_proxy_copy, _1, ob), DEG_OPCODE_POSE_INIT); op_node->set_as_entry(); LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, DEG_OPCODE_BONE_LOCAL); op_node->set_as_entry(); add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, DEG_OPCODE_BONE_READY); op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, DEG_OPCODE_BONE_DONE); op_node->set_as_exit(); } op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, NULL, DEG_OPCODE_POSE_DONE); op_node->set_as_exit(); } } // namespace DEG