#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
+ #include "DNA_mask_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
+ #include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
-#include "DNA_particle_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
}
}
- /* 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, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
- DEG_OPCODE_POSE_IK_SOLVER))
- {
- return;
- }
-
- /* Operation node for evaluating/running IK Solver. */
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
- DEPSOP_TYPE_SIM, 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, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
- DEPSOP_TYPE_SIM, 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)
-void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
--{
- bArmature *arm = (bArmature *)ob->data;
-
- /* 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...
- */
- build_animdata(&arm->id);
-
- /* Rebuild pose if not up to date. */
- if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
- BKE_pose_rebuild_ex(ob, arm, false);
- /* 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);
- }
- }
-
- /* Make sure pose is up-to-date with armature updates. */
- add_operation_node(&arm->id,
- DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_EXEC,
- NULL,
- DEG_OPCODE_PLACEHOLDER,
- "Armature Eval");
-
-- /**
- * 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...
- * Particle Systems Nodes
- * ======================
-- *
- * 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.
- * There are two types of nodes associated with representing
- * particle systems:
- * 1) Component (EVAL_PARTICLES) - This is the particle-system
- * evaluation context for an object. It acts as the container
- * for all the nodes associated with a particular set of particle
- * systems.
- * 2) Particle System Eval Operation - This operation node acts as a
- * blackbox evaluation step for one particle system referenced by
- * the particle systems stack. All dependencies link to this operation.
-- */
-
- /* pose eval context */
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_INIT, function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_INIT);
-
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_POST, function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_DONE);
-
- /* bones */
- for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- /* node for bone eval */
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_INIT, NULL, // XXX: BKE_pose_eval_bone_local
- DEG_OPCODE_BONE_LOCAL);
-
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_EXEC, function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), // XXX: BKE_pose_eval_bone_pose
- DEG_OPCODE_BONE_POSE_PARENT);
-
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_OUT, NULL, /* NOTE: dedicated noop for easier relationship construction */
- DEG_OPCODE_BONE_READY);
-
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_POST, function_bind(BKE_pose_bone_done, _1, pchan),
- DEG_OPCODE_BONE_DONE);
-
- /* constraints */
- if (pchan->constraints.first != NULL) {
- build_pose_constraints(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...
- */
- for (bConstraint *con = (bConstraint *)pchan->constraints.first; con; con = con->next) {
- 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;
- 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);
- }
--
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_pose_eval_proxy_copy, _1, ob),
- DEG_OPCODE_POSE_INIT);
- /* component for all particle systems */
- ComponentDepsNode *psys_comp = add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
--
- for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first;
- pchan != NULL;
- pchan = pchan->next)
- {
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_INIT, NULL,
- DEG_OPCODE_BONE_LOCAL);
- /* particle systems */
- LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
- ParticleSettings *part = psys->part;
--
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_EXEC, NULL,
- DEG_OPCODE_BONE_READY);
- /* particle settings */
- // XXX: what if this is used more than once!
- build_animdata(&part->id);
--
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_POST, NULL,
- DEG_OPCODE_BONE_DONE);
- /* this particle system */
- // TODO: for now, this will just be a placeholder "ubereval" node
- add_operation_node(psys_comp,
- DEPSOP_TYPE_EXEC, function_bind(BKE_particle_system_eval,
- _1,
- scene,
- ob,
- psys),
- DEG_OPCODE_PSYS_EVAL,
- psys->name);
-- }
--
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_POST,
- NULL,
- DEG_OPCODE_POSE_DONE);
- /* pointcache */
- // TODO...
--}
--
/* Shapekeys */
void DepsgraphNodeBuilder::build_shapekeys(Key *key)
{
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
+ #include "DNA_mask_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
+ #include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
-#include "DNA_particle_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
}
}
- /* IK Solver Eval Steps */
- void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
- bPoseChannel *pchan,
- bConstraint *con,
- RootPChanMap *root_map)
-void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
--{
- bKinematicConstraint *data = (bKinematicConstraint *)con->data;
-
- /* attach owner to IK Solver too
- * - assume that owner is always part of chain
- * - see notes on direction of rel below...
- */
- bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
- OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER);
-
- /* IK target */
- // XXX: this should get handled as part of the constraint code
- if (data->tar != NULL) {
- /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
- * we create dependency between target object and pose eval component.
- *
- * This way we ensuring the whole subtree is updated from scratch without
- * need of intermediate matricies. This is an overkill, but good enough for
- * testing IK solver.
- */
- // FIXME: geometry targets...
- ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
- /* TODO(sergey): This is only for until granular update stores intermediate result. */
- if (data->tar != ob) {
- /* different armature - can just read the results */
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget);
- add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
- }
- else {
- /* same armature - we'll use the ready state only, just in case this bone is in the chain we're solving */
- OperationKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE);
- add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
- }
- }
- else if (ELEM(data->tar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) {
- /* vertex group target */
- /* NOTE: for now, we don't need to represent vertex groups separately... */
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
-
- if (data->tar->type == OB_MESH) {
- OperationDepsNode *node2 = find_operation_node(target_key);
- if (node2 != NULL) {
- node2->customdata_mask |= CD_MASK_MDEFORMVERT;
- }
- }
- }
- else {
- /* Standard Object Target */
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
- }
-
- if ((data->tar == ob) && (data->subtarget[0])) {
- /* Prevent target's constraints from linking to anything from same
- * chain that it controls.
- */
- root_map->add_bone(data->subtarget, rootchan->name);
- }
- }
-
- /* Pole Target */
- // XXX: this should get handled as part of the constraint code
- if (data->poletar != NULL) {
- if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
- // XXX: same armature issues - ready vs done?
- ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_BONE, data->polesubtarget);
- add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
- }
- else if (ELEM(data->poletar->type, OB_MESH, OB_LATTICE) && (data->polesubtarget[0])) {
- /* vertex group target */
- /* NOTE: for now, we don't need to represent vertex groups separately... */
- ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
-
- if (data->poletar->type == OB_MESH) {
- OperationDepsNode *node2 = find_operation_node(target_key);
- if (node2 != NULL) {
- node2->customdata_mask |= CD_MASK_MDEFORMVERT;
- }
- }
- }
- else {
- ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
- }
- }
-
- DEG_DEBUG_PRINTF("\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n",
- pchan->name, data->tar->id.name, data->subtarget, data->rootbone);
-
- bPoseChannel *parchan = pchan;
- /* exclude tip from chain? */
- if (!(data->flag & CONSTRAINT_IK_TIP)) {
- OperationKey tip_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
- parchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(solver_key, tip_transforms_key,
- DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
- parchan = pchan->parent;
- }
-
- root_map->add_bone(parchan->name, rootchan->name);
-
- OperationKey parchan_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
- parchan->name, DEG_OPCODE_BONE_READY);
- add_relation(parchan_transforms_key, solver_key,
- DEPSREL_TYPE_TRANSFORM, "IK Solver Owner");
-
- /* Walk to the chain's root */
- //size_t segcount = 0;
- int segcount = 0;
-
- while (parchan) {
- /* Make IK-solver dependent on this bone's result,
- * since it can only run after the standard results
- * of the bone are know. Validate links step on the
- * bone will ensure that users of this bone only
- * grab the result with IK solver results...
- */
- if (parchan != pchan) {
- OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
- add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Parent");
-
- OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
- }
- else {
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
- }
- parchan->flag |= POSE_DONE;
-
-
- root_map->add_bone(parchan->name, rootchan->name);
-
- /* continue up chain, until we reach target number of items... */
- DEG_DEBUG_PRINTF(" %d = %s\n", segcount, parchan->name);
- segcount++;
- if ((segcount == data->rootbone) || (segcount > 255)) break; /* 255 is weak */
- TimeSourceKey time_src_key;
- OperationKey obdata_ubereval_key(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEG_OPCODE_GEOMETRY_UBEREVAL);
--
- parchan = parchan->parent;
- }
- /* particle systems */
- LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
- ParticleSettings *part = psys->part;
--
- OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
- }
- /* particle settings */
- build_animdata(&part->id);
--
- /* Spline IK Eval Steps */
- void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
- bPoseChannel *pchan,
- bConstraint *con,
- RootPChanMap *root_map)
- {
- bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
- bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
- OperationKey transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
- /* this particle system */
- OperationKey psys_key(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name);
--
- /* attach owner to IK Solver too
- * - assume that owner is always part of chain
- * - see notes on direction of rel below...
- */
- add_relation(transforms_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Owner");
- /* XXX: if particle system is later re-enabled, we must do full rebuild? */
- if (!psys_check_enabled(ob, psys, G.is_rendering))
- continue;
--
- /* attach path dependency to solver */
- if (data->tar) {
- /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
- * we create dependency between target object and pose eval component.
- * See IK pose for a bit more information.
- /* TODO(sergey): Are all particle systems depends on time?
- * Hair without dynamics i.e.
-- */
- // TODO: the bigggest point here is that we need the curve PATH and not just the general geometry...
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
- ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, "[Curve.Path -> Spline IK] DepsRel");
- }
-
- pchan->flag |= POSE_DONE;
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Result");
-
- root_map->add_bone(pchan->name, rootchan->name);
-
- /* Walk to the chain's root */
- //size_t segcount = 0;
- int segcount = 0;
- add_relation(time_src_key, psys_key,
- DEPSREL_TYPE_TIME,
- "TimeSrc -> PSys");
--
- for (bPoseChannel *parchan = pchan->parent; parchan; parchan = parchan->parent) {
- /* Make Spline IK solver dependent on this bone's result,
- * since it can only run after the standard results
- * of the bone are know. Validate links step on the
- * bone will ensure that users of this bone only
- * grab the result with IK solver results...
- /* TODO(sergey): Currently particle update is just a placeholder,
- * hook it to the ubereval node so particle system is getting updated
- * on playback.
-- */
- if (parchan != pchan) {
- OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
- add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Update");
- add_relation(psys_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_OPERATION,
- "PSys -> UberEval");
--
- OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
-#if 0
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- LINKLIST_FOREACH (ParticleTarget *, pt, &psys->targets) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
-- }
- parchan->flag |= POSE_DONE;
-
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Result");
-
- root_map->add_bone(parchan->name, rootchan->name);
-
- /* continue up chain, until we reach target number of items... */
- segcount++;
- if ((segcount == data->chainlen) || (segcount > 255)) break; /* 255 is weak */
- }
-
- OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
- }
-
- /* Pose/Armature Bones Graph */
- void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
- {
- /* Armature-Data */
- bArmature *arm = (bArmature *)ob->data;
-
- // TODO: selection status?
-
- /* attach links between pose operations */
- OperationKey init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
- OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
-
- add_relation(init_key, flush_key, DEPSREL_TYPE_COMPONENT_ORDER, "[Pose Init -> Pose Cleanup]");
-
- /* Make sure pose is up-to-date with armature updates. */
- OperationKey armature_key(&arm->id,
- DEPSNODE_TYPE_PARAMETERS,
- DEG_OPCODE_PLACEHOLDER,
- "Armature Eval");
- add_relation(armature_key, init_key, DEPSREL_TYPE_COMPONENT_ORDER, "Data dependency");
-
- if (needs_animdata_node(&ob->id)) {
- ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation");
- }
-
- /* 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)
- *
- * - We build relations for these before the dependencies
- * between ops in the same component as it is necessary
- * to check whether such bones are in the same IK chain
- * (or else we get weird issues with either in-chain
- * references, or with bones being parented to IK'd bones)
- *
- * 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...
- */
- RootPChanMap root_map;
- bool pose_depends_on_local_transform = false;
- for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (bConstraint *con = (bConstraint *)pchan->constraints.first; con; con = con->next) {
- switch (con->type) {
- case CONSTRAINT_TYPE_KINEMATIC:
- build_ik_pose(ob, pchan, con, &root_map);
- pose_depends_on_local_transform = true;
- break;
-
- case CONSTRAINT_TYPE_SPLINEIK:
- build_splineik_pose(ob, pchan, con, &root_map);
- pose_depends_on_local_transform = true;
- break;
--
- /* Constraints which needs world's matrix for transform.
- * TODO(sergey): More constraints here?
- */
- case CONSTRAINT_TYPE_ROTLIKE:
- case CONSTRAINT_TYPE_SIZELIKE:
- case CONSTRAINT_TYPE_LOCLIKE:
- case CONSTRAINT_TYPE_TRANSLIKE:
- /* TODO(sergey): Add used space check. */
- pose_depends_on_local_transform = true;
- break;
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
--
- default:
- break;
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- LINKLIST_FOREACH (GroupObject *, go, &part->dup_group->gobject) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
-- }
-- }
- }
- //root_map.print_debug();
-
- if (pose_depends_on_local_transform) {
- /* TODO(sergey): Once partial updates are possible use relation between
- * object transform and solver itself in it's build function.
- */
- ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- ComponentKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(local_transform_key, pose_key, DEPSREL_TYPE_TRANSFORM, "Local Transforms");
- }
-
-
- /* links between operations for each bone */
- for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey bone_pose_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
- OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
-
- pchan->flag &= ~POSE_DONE;
-#endif
--
- /* pose init to bone local */
- add_relation(init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "PoseEval Source-Bone Link");
- /* collisions */
- if (part->type != PART_HAIR) {
- add_collision_relations(psys_key, scene, ob, part->collision_group, ob->lay, true, "Particle Collision");
- }
--
- /* local to pose parenting operation */
- add_relation(bone_local_key, bone_pose_key, DEPSREL_TYPE_OPERATION, "Bone Local - PoseSpace Link");
- /* effectors */
- add_forcefield_relations(psys_key, scene, ob, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
--
- /* parent relation */
- if (pchan->parent != NULL) {
- eDepsOperation_Code parent_key_opcode;
- /* boids */
- if (part->boids) {
- LINKLIST_FOREACH (BoidState *, state, &part->boids->states) {
- LINKLIST_FOREACH (BoidRule *, rule, &state->rules) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid)
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- else if (rule->type == eBoidRuleType_FollowLeader)
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
--
- /* NOTE: this difference in handling allows us to prevent lockups while ensuring correct poses for separate chains */
- if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
- parent_key_opcode = DEG_OPCODE_BONE_READY;
- }
- else {
- parent_key_opcode = DEG_OPCODE_BONE_DONE;
- if (ruleob) {
- ComponentKey ruleob_key(&ruleob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(ruleob_key, psys_key, DEPSREL_TYPE_TRANSFORM, "Boid Rule");
- }
- }
-- }
-
- OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
- add_relation(parent_key, bone_pose_key, DEPSREL_TYPE_TRANSFORM, "[Parent Bone -> Child Bone]");
-- }
-
- /* constraints */
- if (pchan->constraints.first != NULL) {
- /* constraints stack and constraint dependencies */
- build_constraints(scene, &ob->id, DEPSNODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
-
- /* pose -> constraints */
- OperationKey constraints_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
- add_relation(bone_pose_key, constraints_key, DEPSREL_TYPE_OPERATION, "Constraints Stack");
--
- /* constraints -> ready */
- // TODO: when constraint stack is exploded, this step should occur before the first IK solver
- add_relation(constraints_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Constraints -> Ready");
- }
- else {
- /* pose -> ready */
- add_relation(bone_pose_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Pose -> Ready");
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- ComponentKey dup_ob_key(&part->dup_ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(dup_ob_key,
- psys_key,
- DEPSREL_TYPE_TRANSFORM,
- "Particle Object Visualization");
-- }
-
- /* bone ready -> done
- * NOTE: For bones without IK, this is all that's needed.
- * For IK chains however, an additional rel is created from IK to done,
- * with transitive reduction removing this one...
- */
- add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
-
- /* assume that all bones must be done for the pose to be ready (for deformers) */
- add_relation(bone_done_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
-- }
- }
--
- void DepsgraphRelationBuilder::build_proxy_rig(Object *ob)
- {
- OperationKey pose_init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
- OperationKey pose_done_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first;
- pchan != NULL;
- pchan = pchan->next)
- {
- OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(pose_init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "Pose Init -> Bone Local");
- add_relation(bone_local_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Local -> Ready");
- add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
- add_relation(bone_done_key, pose_done_key, DEPSREL_TYPE_OPERATION, "Bone Done -> Pose Done");
- }
- /* Particle depends on the object transform, so that channel is to be ready
- * first.
- *
- * TODO(sergey): This relation should be altered once real granular update
- * is implemented.
- */
- ComponentKey transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(transform_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_GEOMETRY_EVAL,
- "Partcile Eval");
-
- /* pointcache */
- // TODO...
--}
--
/* Shapekeys */
void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
{
/* Function to draw an Image on an empty Object */
- static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
+ static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4], StereoViews sview)
{
Image *ima = ob->data;
- ImBuf *ibuf;
- ImageUser iuser = *ob->iuser;
- /* Support multi-view */
- if (ima && (sview == STEREO_RIGHT_ID)) {
- iuser.multiview_eye = sview;
- iuser.flag |= IMA_SHOW_STEREO;
- BKE_image_multiview_index(ima, &iuser);
- }
+ const float ob_alpha = ob->col[3];
+ float width, height;
- ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ int bindcode = 0;
- if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
- IMB_rect_from_float(ibuf);
- }
+ if (ima) {
++ ImageUser iuser = *ob->iuser;
++
++ /* Support multi-view */
++ if (ima && (sview == STEREO_RIGHT_ID)) {
++ iuser.multiview_eye = sview;
++ iuser.flag |= IMA_SHOW_STEREO;
++ BKE_image_multiview_index(ima, &iuser);
++ }
+
- int ima_x, ima_y;
+ if (ob_alpha > 0.0f) {
- bindcode = GPU_verify_image(ima, ob->iuser, GL_TEXTURE_2D, 0, false, false, false);
++ bindcode = GPU_verify_image(ima, &iuser, GL_TEXTURE_2D, 0, false, false, false);
+ /* don't bother drawing the image if alpha = 0 */
+ }
- /* Get the buffer dimensions so we can fallback to fake ones */
- if (ibuf && ibuf->rect) {
- ima_x = ibuf->x;
- ima_y = ibuf->y;
+ int w, h;
- BKE_image_get_size(ima, ob->iuser, &w, &h);
++ BKE_image_get_size(ima, &iuser, &w, &h);
+ width = w;
+ height = h;
}
else {
- ima_x = 1;
- ima_y = 1;
+ /* if no image, make it a 1x1 empty square, honor scale & offset */
+ width = height = 1.0f;
}
- float sca_x = 1.0f;
- float sca_y = 1.0f;
+ const float aspect = height / width;
- /* Get the image aspect even if the buffer is invalid */
- if (ima) {
- if (ima->aspx > ima->aspy) {
- sca_y = ima->aspy / ima->aspx;
- }
- else if (ima->aspx < ima->aspy) {
- sca_x = ima->aspx / ima->aspy;
- }
- }
+ float left = ob->ima_ofs[0];
+ float right = ob->ima_ofs[0] + ob->empty_drawsize;
+ float top = ob->ima_ofs[1] + ob->empty_drawsize * aspect;
+ float bottom = ob->ima_ofs[1];
- /* Calculate the scale center based on object's origin */
- float ofs_x = ob->ima_ofs[0] * ima_x;
- float ofs_y = ob->ima_ofs[1] * ima_y;
+ bool use_blend = false;
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ if (bindcode) {
+ use_blend = ob_alpha < 1.0f || BKE_image_has_alpha(ima);
- /* Calculate Image scale */
- float scale = ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y);
+ if (use_blend) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- /* Set the object scale */
- glScalef(scale * sca_x, scale * sca_y, 1.0f);
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
+ immUniform1f("alpha", ob_alpha);
+ immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
- if (ibuf && ibuf->rect) {
- const bool use_clip = (U.glalphaclip != 1.0f);
- int zoomfilter = (U.gameflags & USER_DISABLE_MIPMAP) ? GL_NEAREST : GL_LINEAR;
- /* Setup GL params */
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ immBegin(GL_TRIANGLE_FAN, 4);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, left, bottom);
- if (use_clip) {
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, U.glalphaclip);
- }
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, right, bottom);
- /* Use the object color and alpha */
- glColor4fv(ob->col);
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, right, top);
- /* Draw the Image on the screen */
- glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect);
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, left, top);
+ immEnd();
- glDisable(GL_BLEND);
+ immUnbindProgram();
- if (use_clip) {
- glDisable(GL_ALPHA_TEST);
- glAlphaFunc(GL_ALWAYS, 0.0f);
- }
+ glBindTexture(GL_TEXTURE_2D, 0); /* necessary? */
}
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
+ /* Draw the image outline */
+ glLineWidth(1.5f);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ const bool picking = dflag & DRAW_CONSTCOLOR;
+ if (picking) {
+ /* TODO: deal with picking separately, use this function just to draw */
+ immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY);
+ if (use_blend) {
+ glDisable(GL_BLEND);
+ }
+
+ imm_draw_line_box(pos, left, bottom, right, top);
}
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(ob_wire_col);
+ glEnable(GL_LINE_SMOOTH);
- /* Calculate the outline vertex positions */
- glBegin(GL_LINE_LOOP);
- glVertex2f(ofs_x, ofs_y);
- glVertex2f(ofs_x + ima_x, ofs_y);
- glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
- glVertex2f(ofs_x, ofs_y + ima_y);
- glEnd();
+ if (!use_blend) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- /* Reset GL settings */
- glPopMatrix();
+ imm_draw_line_box(pos, left, bottom, right, top);
+
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ }
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ immUnbindProgram();
}
static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4])
case OB_EMPTY:
if (!render_override) {
if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
- draw_empty_image(ob, dflag, ob_wire_col);
+ draw_empty_image(ob, dflag, ob_wire_col, v3d->multiview_eye);
}
else {
- drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype);
+ drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, ob_wire_col);
}
}
break;
case OB_EMPTY:
if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
/* CONSTCOLOR == no wire outline */
- draw_empty_image(ob, DRAW_CONSTCOLOR, NULL);
+ draw_empty_image(ob, DRAW_CONSTCOLOR, NULL, v3d->multiview_eye);
}
else {
- drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype);
+ drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, NULL); /* TODO: use proper color */
}
break;
}