AnimClip: read in translations from fbx file and pre-process them

Do the following things to the translations

  1. scale by the model offset, this should move the translations into the correct units (meters).
  2. compute the ratio between the bone length in the animation and the skeleton.
  3. subtract the anim translation from the first translation frame in the animation
     effectively turning it into a bind pose delta translation.
  4. apply bone length ratio to the resulting delta.
  5. set the final translation to be the skeleton rel bind pose + this scaled delta translation
This commit is contained in:
Anthony J. Thibault 2015-10-01 16:10:33 -07:00
parent 8bfd38ce7c
commit fe5ea471a1

View file

@ -135,29 +135,46 @@ void AnimClip::copyFromNetworkAnim() {
const int frameCount = geom.animationFrames.size();
const int skeletonJointCount = _skeleton->getNumJoints();
_anim.resize(frameCount);
for (int i = 0; i < frameCount; i++) {
const glm::vec3 offsetScale = extractScale(geom.offset);
for (int frame = 0; frame < frameCount; frame++) {
// init all joints in animation to bind pose
_anim[i].reserve(skeletonJointCount);
for (int j = 0; j < skeletonJointCount; j++) {
_anim[i].push_back(_skeleton->getRelativeBindPose(j));
// this will give us a resonable result for bones in the skeleton but not in the animation.
_anim[frame].reserve(skeletonJointCount);
for (int skeletonJoint = 0; skeletonJoint < skeletonJointCount; skeletonJoint++) {
_anim[frame].push_back(_skeleton->getRelativeBindPose(skeletonJoint));
}
// init over all joint animations
for (int j = 0; j < animJointCount; j++) {
int k = jointMap[j];
if (k >= 0 && k < skeletonJointCount) {
_anim[i][k].rot = _skeleton->getRelativeBindPose(k).rot * geom.animationFrames[i].rotations[j];
for (int animJoint = 0; animJoint < animJointCount; animJoint++) {
// TODO -- why does applying all the joint translations make a mutant?
if (animJoints[j].parentIndex == -1) {
_anim[i][k].trans = geom.animationFrames[i].translations[j] * extractScale(geom.offset);
} else {
_anim[i][k].trans = _skeleton->getRelativeBindPose(k).trans;
}
int skeletonJoint = jointMap[animJoint];
// skip joints that are in the animation but not in the skeleton.
if (skeletonJoint >= 0 && skeletonJoint < skeletonJointCount) {
const glm::vec3& fbxZeroTrans = geom.animationFrames[0].translations[animJoint] * offsetScale;
const AnimPose& relBindPose = _skeleton->getRelativeBindPose(skeletonJoint);
// used to adjust translation offsets, so large translation animatons on the reference skeleton
// will be adjusted when played on a skeleton with short limbs.
float limbLengthScale = fabs(glm::length(fbxZeroTrans)) <= 0.0001f ? 1.0f : (glm::length(relBindPose.trans) / glm::length(fbxZeroTrans));
AnimPose& pose = _anim[frame][skeletonJoint];
const FBXAnimationFrame& fbxAnimFrame = geom.animationFrames[frame];
// rotation in fbxAnimationFrame is a delta from a reference skeleton bind pose.
pose.rot = relBindPose.rot * fbxAnimFrame.rotations[animJoint];
// translation in fbxAnimationFrame is not a delta.
// convert it into a delta by subtracting from the first frame.
const glm::vec3& fbxTrans = fbxAnimFrame.translations[animJoint] * offsetScale;
pose.trans = relBindPose.trans + limbLengthScale * (fbxTrans - fbxZeroTrans);
}
}
}
_poses.resize(skeletonJointCount);
}