From c1d72876527b69ed822a51f820aa5c8e4509cd6b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 9 Sep 2015 12:24:32 -0700 Subject: [PATCH] AnimController node now takes absolute rotation vars, instead of relative. --- libraries/animation/src/AnimController.cpp | 52 +++++++++++++++++++--- libraries/animation/src/AnimSkeleton.cpp | 8 ++++ libraries/animation/src/AnimSkeleton.h | 2 + libraries/animation/src/Rig.cpp | 6 +-- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/libraries/animation/src/AnimController.cpp b/libraries/animation/src/AnimController.cpp index d6edef57b5..6cf95da26b 100644 --- a/libraries/animation/src/AnimController.cpp +++ b/libraries/animation/src/AnimController.cpp @@ -34,8 +34,22 @@ const AnimPoseVec& AnimController::evaluate(const AnimVariantMap& animVars, floa jointVar.hasPerformedJointLookup = true; } if (jointVar.jointIndex >= 0) { - AnimPose pose(animVars.lookup(jointVar.var, glm::mat4())); - _poses[jointVar.jointIndex] = pose; + + // jointVar is an absolute rotation, if it is not set we will use the bindPose as our default value + AnimPose defaultPose = _skeleton->getAbsoluteBindPose(jointVar.jointIndex); + glm::quat absRot = animVars.lookup(jointVar.var, defaultPose.rot); + + // because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose + // here we use the bind pose + int parentIndex = _skeleton->getParentIndex(jointVar.jointIndex); + glm::quat parentAbsRot; + if (parentIndex >= 0) { + parentAbsRot = _skeleton->getAbsoluteBindPose(parentIndex).rot; + } + + // convert from absolute to relative + glm::quat relRot = glm::inverse(parentAbsRot) * absRot; + _poses[jointVar.jointIndex] = AnimPose(defaultPose.scale, relRot, defaultPose.trans); } } @@ -56,13 +70,39 @@ const AnimPoseVec& AnimController::overlay(const AnimVariantMap& animVars, float } if (jointVar.jointIndex >= 0) { - AnimPose pose; + + AnimPose defaultPose; + glm::quat absRot; + glm::quat parentAbsRot; if (jointVar.jointIndex <= (int)underPoses.size()) { - pose = AnimPose(animVars.lookup(jointVar.var, underPoses[jointVar.jointIndex])); + + // jointVar is an absolute rotation, if it is not set we will use the underPose as our default value + defaultPose = _skeleton->getAbsolutePose(jointVar.jointIndex, underPoses); + absRot = animVars.lookup(jointVar.var, defaultPose.rot); + + // because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose. + int parentIndex = _skeleton->getParentIndex(jointVar.jointIndex); + if (parentIndex >= 0) { + parentAbsRot = _skeleton->getAbsolutePose(parentIndex, underPoses).rot; + } + } else { - pose = AnimPose(animVars.lookup(jointVar.var, AnimPose::identity)); + + // jointVar is an absolute rotation, if it is not set we will use the bindPose as our default value + defaultPose = _skeleton->getAbsoluteBindPose(jointVar.jointIndex); + absRot = animVars.lookup(jointVar.var, defaultPose.rot); + + // because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose + // here we use the bind pose + int parentIndex = _skeleton->getParentIndex(jointVar.jointIndex); + if (parentIndex >= 0) { + parentAbsRot = _skeleton->getAbsoluteBindPose(parentIndex).rot; + } } - _poses[jointVar.jointIndex] = pose; + + // convert from absolute to relative + glm::quat relRot = glm::inverse(parentAbsRot) * absRot; + _poses[jointVar.jointIndex] = AnimPose(defaultPose.scale, relRot, defaultPose.trans); } } diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index a112eb648d..c6bae37edd 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -105,6 +105,14 @@ const QString& AnimSkeleton::getJointName(int jointIndex) const { return _joints[jointIndex].name; } +AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& poses) const { + if (jointIndex < 0) { + return AnimPose::identity; + } else { + return getAbsolutePose(_joints[jointIndex].parentIndex, poses) * poses[jointIndex]; + } +} + void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, const AnimPose& geometryOffset) { _joints = joints; diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index e1976d929b..056d8fbd9b 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -64,6 +64,8 @@ public: int getParentIndex(int jointIndex) const; + AnimPose getAbsolutePose(int jointIndex, const AnimPoseVec& poses) const; + #ifndef NDEBUG void dump() const; void dump(const AnimPoseVec& poses) const; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 2dae075454..5e39f334c5 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -956,12 +956,10 @@ void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, floa glm::vec3 xAxis(1.0f, 0.0f, 0.0f); glm::vec3 yAxis(0.0f, 1.0f, 0.0f); glm::vec3 zAxis(0.0f, 0.0f, 1.0f); - glm::quat rot = (glm::angleAxis(-RADIANS_PER_DEGREE * leanSideways, zAxis) * + glm::quat absRot = (glm::angleAxis(-RADIANS_PER_DEGREE * leanSideways, zAxis) * glm::angleAxis(-RADIANS_PER_DEGREE * leanForward, xAxis) * glm::angleAxis(RADIANS_PER_DEGREE * torsoTwist, yAxis)); - AnimPose pose = _animSkeleton->getRelativeBindPose(index); - pose.rot = rot; - _animVars.set("lean", static_cast(pose)); + _animVars.set("lean", absRot); } else if (!_enableAnimGraph) { auto& parentState = _jointStates[_jointStates[index].getParentIndex()];