From 3a74d188b0b71500323a5fa04548b01092374281 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 18 Nov 2015 16:03:28 -0800 Subject: [PATCH] AnimSkeleton: Added default poses --- libraries/animation/src/AnimSkeleton.cpp | 77 +++++++++++++++++++----- libraries/animation/src/AnimSkeleton.h | 9 +++ 2 files changed, 71 insertions(+), 15 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 7ec8db1490..f6c5ce09db 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -70,6 +70,14 @@ const AnimPose& AnimSkeleton::getRelativeBindPose(int jointIndex) const { return _relativeBindPoses[jointIndex]; } +const AnimPose& AnimSkeleton::getRelativeDefaultPose(int jointIndex) const { + return _relativeDefaultPoses[jointIndex]; +} + +const AnimPose& AnimSkeleton::getAbsoluteDefaultPose(int jointIndex) const { + return _absoluteDefaultPoses[jointIndex]; +} + int AnimSkeleton::getParentIndex(int jointIndex) const { return _joints[jointIndex].parentIndex; } @@ -93,14 +101,31 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _absoluteBindPoses.reserve(joints.size()); _relativeBindPoses.reserve(joints.size()); + // build a chache of default poses + _absoluteDefaultPoses.reserve(joints.size()); + _relativeDefaultPoses.reserve(joints.size()); + // iterate over FBXJoints and extract the bind pose information. for (size_t i = 0; i < joints.size(); i++) { + + // build relative and absolute default poses + glm::mat4 rotTransform = glm::mat4_cast(_joints[i].preRotation * _joints[i].rotation * _joints[i].postRotation); + glm::mat4 relDefaultMat = glm::translate(_joints[i].translation) * _joints[i].preTransform * rotTransform * _joints[i].postTransform; + AnimPose relDefaultPose(relDefaultMat); + _relativeDefaultPoses.push_back(relDefaultPose); + int parentIndex = getParentIndex(i); + if (parentIndex >= 0) { + _absoluteDefaultPoses.push_back(_absoluteDefaultPoses[parentIndex] * relDefaultPose); + } else { + _absoluteDefaultPoses.push_back(relDefaultPose); + } + + // build relative and absolute bind poses if (_joints[i].bindTransformFoundInCluster) { // Use the FBXJoint::bindTransform, which is absolute model coordinates // i.e. not relative to it's parent. AnimPose absoluteBindPose(_joints[i].bindTransform); _absoluteBindPoses.push_back(absoluteBindPose); - int parentIndex = getParentIndex(i); if (parentIndex >= 0) { AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse(); _relativeBindPoses.push_back(inverseParentAbsoluteBindPose * absoluteBindPose); @@ -108,39 +133,40 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _relativeBindPoses.push_back(absoluteBindPose); } } else { - // use FBXJoint's local transform, instead - glm::mat4 rotTransform = glm::mat4_cast(_joints[i].preRotation * _joints[i].rotation * _joints[i].postRotation); - glm::mat4 relBindMat = glm::translate(_joints[i].translation) * _joints[i].preTransform * rotTransform * _joints[i].postTransform; - AnimPose relBindPose(relBindMat); - _relativeBindPoses.push_back(relBindPose); - - int parentIndex = getParentIndex(i); + // use default transform instead + _relativeBindPoses.push_back(relDefaultPose); if (parentIndex >= 0) { - _absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relBindPose); + _absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relDefaultPose); } else { - _absoluteBindPoses.push_back(relBindPose); + _absoluteBindPoses.push_back(relDefaultPose); } } } // now we want to normalize scale from geometryOffset to all poses. // This will ensure our bone translations will be in meters, even if the model was authored with some other unit of mesure. - for (auto& absPose : _absoluteBindPoses) { + normalizeScale(geometryOffset, _relativeBindPoses, _absoluteBindPoses); + normalizeScale(geometryOffset, _relativeDefaultPoses, _absoluteDefaultPoses); +} + +void AnimSkeleton::normalizeScale(const AnimPose& geometryOffset, AnimPoseVec& relPoses, AnimPoseVec& absPoses) const { + for (auto& absPose : absPoses) { absPose.trans = (geometryOffset * absPose).trans; - absPose.scale = vec3(1, 1, 1); } // re-compute relative poses based on the modified absolute poses. - for (size_t i = 0; i < _relativeBindPoses.size(); i++) { + for (size_t i = 0; i < relPoses.size(); i++) { int parentIndex = getParentIndex(i); if (parentIndex >= 0) { - _relativeBindPoses[i] = _absoluteBindPoses[parentIndex].inverse() * _absoluteBindPoses[i]; + relPoses[i] = absPoses[parentIndex].inverse() * absPoses[i]; } else { - _relativeBindPoses[i] = _absoluteBindPoses[i]; + relPoses[i] = absPoses[i]; } } } +#define DUMP_FBX_JOINTS + #ifndef NDEBUG void AnimSkeleton::dump() const { qCDebug(animation) << "["; @@ -150,6 +176,25 @@ void AnimSkeleton::dump() const { qCDebug(animation) << " name =" << getJointName(i); qCDebug(animation) << " absBindPose =" << getAbsoluteBindPose(i); qCDebug(animation) << " relBindPose =" << getRelativeBindPose(i); + qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i); + qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i); +#ifdef DUMP_FBX_JOINTS + qCDebug(animation) << " isFree =" << _joints[i].isFree; + qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage; + qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex; + qCDebug(animation) << " translation =" << _joints[i].translation; + qCDebug(animation) << " preTransform =" << _joints[i].preTransform; + qCDebug(animation) << " preRotation =" << _joints[i].preRotation; + qCDebug(animation) << " rotation =" << _joints[i].rotation; + qCDebug(animation) << " postRotation =" << _joints[i].postRotation; + qCDebug(animation) << " postTransform =" << _joints[i].postTransform; + qCDebug(animation) << " transform =" << _joints[i].transform; + qCDebug(animation) << " rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax; + qCDebug(animation) << " inverseDefaultRotation" << _joints[i].inverseDefaultRotation; + qCDebug(animation) << " inverseBindRotation" << _joints[i].inverseBindRotation; + qCDebug(animation) << " bindTransform" << _joints[i].bindTransform; + qCDebug(animation) << " isSkeletonJoint" << _joints[i].isSkeletonJoint; +#endif if (getParentIndex(i) >= 0) { qCDebug(animation) << " parent =" << getJointName(getParentIndex(i)); } @@ -166,6 +211,8 @@ void AnimSkeleton::dump(const AnimPoseVec& poses) const { qCDebug(animation) << " name =" << getJointName(i); qCDebug(animation) << " absBindPose =" << getAbsoluteBindPose(i); qCDebug(animation) << " relBindPose =" << getRelativeBindPose(i); + qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i); + qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i); qCDebug(animation) << " pose =" << poses[i]; if (getParentIndex(i) >= 0) { qCDebug(animation) << " parent =" << getJointName(getParentIndex(i)); diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index ebf6bfa3d6..7c57096280 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -38,6 +38,12 @@ public: const AnimPose& getRelativeBindPose(int jointIndex) const; const AnimPoseVec& getRelativeBindPoses() const { return _relativeBindPoses; } + // the default poses are the orientations of the joints on frame 0. + const AnimPose& getRelativeDefaultPose(int jointIndex) const; + const AnimPoseVec& getRelativeDefaultPoses() const { return _relativeDefaultPoses; } + const AnimPose& getAbsoluteDefaultPose(int jointIndex) const; + const AnimPoseVec& getAbsoluteDefaultPoses() const { return _absoluteDefaultPoses; } + int getParentIndex(int jointIndex) const; AnimPose getAbsolutePose(int jointIndex, const AnimPoseVec& poses) const; @@ -49,10 +55,13 @@ public: protected: void buildSkeletonFromJoints(const std::vector& joints, const AnimPose& geometryOffset); + void normalizeScale(const AnimPose& geometryOffset, AnimPoseVec& relPoses, AnimPoseVec& absPoses) const; std::vector _joints; AnimPoseVec _absoluteBindPoses; AnimPoseVec _relativeBindPoses; + AnimPoseVec _relativeDefaultPoses; + AnimPoseVec _absoluteDefaultPoses; // no copies AnimSkeleton(const AnimSkeleton&) = delete;