From 217145f4c562c78785715d8068cd9179cd162b93 Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 22 Feb 2019 17:16:50 -0800 Subject: [PATCH] This pr addresses two issues related to avatars that have parents joints above their hip joints. First on the IK side this prevents parent joints from being included in the accumulators in AnimInverseKinematics. Second in AnimClip the boneLengthScale now takes into account translation and scale on these extra parent joints. --- libraries/animation/src/AnimClip.cpp | 41 ++++++++++++++++++- .../animation/src/AnimInverseKinematics.cpp | 6 +-- libraries/animation/src/AnimSkeleton.cpp | 3 ++ libraries/animation/src/AnimSkeleton.h | 2 + 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index a35e0237d0..109be27b58 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -151,12 +151,49 @@ void AnimClip::copyFromNetworkAnim() { const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex]; float boneLengthScale = 1.0f; const float EPSILON = 0.0001f; - if (fabsf(glm::length(animZeroTrans)) > EPSILON) { - boneLengthScale = glm::length(avatarDefaultPose.trans()) / glm::length(animZeroTrans); + + const int avatarHipsParentIndex = avatarSkeleton->getParentIndex(avatarSkeleton->nameToJointIndex("Hips")); + if (avatarJointIndex == avatarSkeleton->nameToJointIndex("Hips") && (avatarHipsParentIndex >= 0)) { + + const AnimPose& animHipsAbsoluteDefaultPose = animSkeleton.getAbsoluteDefaultPose(animSkeleton.nameToJointIndex("Hips")); + const AnimPose& avatarHipsAbsoluteDefaultPose = avatarSkeleton->getAbsoluteDefaultPose(avatarSkeleton->nameToJointIndex("Hips")); + const AnimPose& avatarHipsParentAbsoluteDefaultPose = avatarSkeleton->getAbsoluteDefaultPose(avatarHipsParentIndex); + + // the get the units and the heights for the animation and the avatar + const float animationUnitScale = extractScale(animModel.offset).y; + const float avatarUnitScale = extractScale(avatarSkeleton->getGeometryOffset()).y; + const float avatarHeightInMeters = avatarUnitScale * avatarHipsAbsoluteDefaultPose.trans().y; + const float animHeightInMeters = animationUnitScale * animHipsAbsoluteDefaultPose.trans().y; + + // get the parent scales for the avatar and the animation + const float avatarHipsParentScale = avatarHipsParentAbsoluteDefaultPose.scale().y; + float animHipsParentScale = 1.0f; + const int animHipsParentIndex = animSkeleton.getParentIndex(animSkeleton.nameToJointIndex("Hips")); + // also, check to see if the animation hips have a scaled parent. + if (animHipsParentIndex >= 0) { + const AnimPose& animationHipsParentAbsoluteDefaultPose = animSkeleton.getAbsoluteDefaultPose(animHipsParentIndex); + animHipsParentScale = animationHipsParentAbsoluteDefaultPose.scale().y; + } + + // compute the ratios for the units, the heights in meters, and the parent scales + if ((fabsf(animHeightInMeters) > EPSILON) && (animationUnitScale > EPSILON) && (animHipsParentScale > EPSILON)) { + const float avatarToAnimationHeightRatio = avatarHeightInMeters / animHeightInMeters; + const float unitsRatio = 1.0f / (avatarUnitScale / animationUnitScale); + const float parentScaleRatio = 1.0f / (avatarHipsParentScale / animHipsParentScale); + + boneLengthScale = avatarToAnimationHeightRatio * unitsRatio * parentScaleRatio; + } + } else { + + if (fabsf(glm::length(animZeroTrans)) > EPSILON) { + boneLengthScale = glm::length(avatarDefaultPose.trans()) / glm::length(animZeroTrans); + } } + AnimPose animTransPose = AnimPose(glm::vec3(1.0f), glm::quat(), avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans)); _anim[frame][avatarJointIndex] = animTransPose * animPreRotPose * animRotPose * animPostRotPose; + } } } diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index d710e9d8ff..8da2ddde3e 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -298,10 +298,8 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector< } // harvest accumulated rotations and apply the average - for (int i = 0; i < (int)_relativePoses.size(); ++i) { - if (i == _hipsIndex) { - continue; // don't apply accumulators to hips - } + // don't apply accumulators to hips, or parents of hips + for (int i = (_hipsIndex+1); i < (int)_relativePoses.size(); ++i) { if (_rotationAccumulators[i].size() > 0) { _relativePoses[i].rot() = _rotationAccumulators[i].getAverage(); _rotationAccumulators[i].clear(); diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 03e3ac6ebd..f7b5fa8c83 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -17,6 +17,9 @@ #include "AnimationLogging.h" AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { + + _geometryOffset = hfmModel.offset; + // convert to std::vector of joints std::vector joints; joints.reserve(hfmModel.joints.size()); diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index 0eefbf973e..dcb35ac9cb 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -36,6 +36,7 @@ public: const AnimPoseVec& getRelativeDefaultPoses() const { return _relativeDefaultPoses; } const AnimPose& getAbsoluteDefaultPose(int jointIndex) const; const AnimPoseVec& getAbsoluteDefaultPoses() const { return _absoluteDefaultPoses; } + const glm::mat4& getGeometryOffset() const { return _geometryOffset; } // get pre transform which should include FBX pre potations const AnimPose& getPreRotationPose(int jointIndex) const; @@ -83,6 +84,7 @@ protected: std::vector _mirrorMap; QHash _jointIndicesByName; std::vector> _clusterBindMatrixOriginalValues; + glm::mat4 _geometryOffset; // no copies AnimSkeleton(const AnimSkeleton&) = delete;