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.
This commit is contained in:
amantley 2019-02-22 17:16:50 -08:00
parent 72f198fe00
commit 217145f4c5
4 changed files with 46 additions and 6 deletions

View file

@ -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;
}
}
}

View file

@ -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();

View file

@ -17,6 +17,9 @@
#include "AnimationLogging.h"
AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
_geometryOffset = hfmModel.offset;
// convert to std::vector of joints
std::vector<HFMJoint> joints;
joints.reserve(hfmModel.joints.size());

View file

@ -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<int> _mirrorMap;
QHash<QString, int> _jointIndicesByName;
std::vector<std::vector<HFMCluster>> _clusterBindMatrixOriginalValues;
glm::mat4 _geometryOffset;
// no copies
AnimSkeleton(const AnimSkeleton&) = delete;