mirror of
https://github.com/lubosz/overte.git
synced 2025-04-14 04:26:18 +02:00
Merge pull request #15046 from amantley/bugRootHips
Bug Fix for the Hips not translating correctly when Hips and Root have the same location
This commit is contained in:
commit
e955c02e07
4 changed files with 43 additions and 10 deletions
|
@ -123,6 +123,42 @@ void AnimClip::copyFromNetworkAnim() {
|
|||
const int animFrameCount = animModel.animationFrames.size();
|
||||
_anim.resize(animFrameCount);
|
||||
|
||||
// find the size scale factor for translation in the animation.
|
||||
const int avatarHipsParentIndex = avatarSkeleton->getParentIndex(avatarSkeleton->nameToJointIndex("Hips"));
|
||||
const int animHipsParentIndex = animSkeleton.getParentIndex(animSkeleton.nameToJointIndex("Hips"));
|
||||
const AnimPose& avatarHipsAbsoluteDefaultPose = avatarSkeleton->getAbsoluteDefaultPose(avatarSkeleton->nameToJointIndex("Hips"));
|
||||
const AnimPose& animHipsAbsoluteDefaultPose = animSkeleton.getAbsoluteDefaultPose(animSkeleton.nameToJointIndex("Hips"));
|
||||
|
||||
// the get the units and the heights for the animation and the avatar
|
||||
const float avatarUnitScale = extractScale(avatarSkeleton->getGeometryOffset()).y;
|
||||
const float animationUnitScale = extractScale(animModel.offset).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
|
||||
float avatarHipsParentScale = 1.0f;
|
||||
if (avatarHipsParentIndex >= 0) {
|
||||
const AnimPose& avatarHipsParentAbsoluteDefaultPose = avatarSkeleton->getAbsoluteDefaultPose(avatarHipsParentIndex);
|
||||
avatarHipsParentScale = avatarHipsParentAbsoluteDefaultPose.scale().y;
|
||||
}
|
||||
float animHipsParentScale = 1.0f;
|
||||
if (animHipsParentIndex >= 0) {
|
||||
const AnimPose& animationHipsParentAbsoluteDefaultPose = animSkeleton.getAbsoluteDefaultPose(animHipsParentIndex);
|
||||
animHipsParentScale = animationHipsParentAbsoluteDefaultPose.scale().y;
|
||||
}
|
||||
|
||||
const float EPSILON = 0.0001f;
|
||||
float boneLengthScale = 1.0f;
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
for (int frame = 0; frame < animFrameCount; frame++) {
|
||||
const HFMAnimationFrame& animFrame = animModel.animationFrames[frame];
|
||||
|
||||
|
@ -162,7 +198,6 @@ void AnimClip::copyFromNetworkAnim() {
|
|||
avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations);
|
||||
|
||||
_anim[frame].reserve(avatarJointCount);
|
||||
|
||||
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
||||
const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex);
|
||||
|
||||
|
@ -177,11 +212,6 @@ void AnimClip::copyFromNetworkAnim() {
|
|||
|
||||
// retarget translation from animation to avatar
|
||||
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);
|
||||
}
|
||||
relativeTranslation = avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans);
|
||||
} else {
|
||||
// This joint is NOT in the animation at all.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
@ -84,6 +85,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;
|
||||
|
|
Loading…
Reference in a new issue