From 8f46b8a765525b90a6d0a300cf9de7497b4a8e47 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 23 Nov 2015 15:58:18 -0800 Subject: [PATCH] Added USE_PRE_ROT_FROM_ANIM option to AnimClip This will allow us in the future to pull preRotations from animations instead of the model skeleton. It is disabled by default because our current animations preRotations are not correct for the left hand. --- libraries/animation/src/AnimClip.cpp | 33 +++++++++++++++++----------- libraries/fbx/src/FBXReader.cpp | 7 ------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 582a55cd62..c90d2ae6ce 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -91,41 +91,48 @@ void AnimClip::copyFromNetworkAnim() { // build a mapping from animation joint indices to skeleton joint indices. // by matching joints with the same name. const FBXGeometry& geom = _networkAnim->getGeometry(); - const QVector& animJoints = geom.joints; + AnimSkeleton animSkeleton(geom); + const int animJointCount = animSkeleton.getNumJoints(); + const int skeletonJointCount = _skeleton->getNumJoints(); std::vector jointMap; - const int animJointCount = animJoints.count(); jointMap.reserve(animJointCount); for (int i = 0; i < animJointCount; i++) { - int skeletonJoint = _skeleton->nameToJointIndex(animJoints.at(i).name); + int skeletonJoint = _skeleton->nameToJointIndex(animSkeleton.getJointName(i)); if (skeletonJoint == -1) { - qCWarning(animation) << "animation contains joint =" << animJoints.at(i).name << " which is not in the skeleton, url =" << _url; + qCWarning(animation) << "animation contains joint =" << animSkeleton.getJointName(i) << " which is not in the skeleton, url =" << _url; } jointMap.push_back(skeletonJoint); } const int frameCount = geom.animationFrames.size(); - const int skeletonJointCount = _skeleton->getNumJoints(); _anim.resize(frameCount); for (int frame = 0; frame < frameCount; frame++) { - // init all joints in animation to bind pose - // this will give us a resonable result for bones in the skeleton but not in the animation. + // init all joints in animation to default pose + // this will give us a resonable result for bones in the model skeleton but not in the animation. _anim[frame].reserve(skeletonJointCount); for (int skeletonJoint = 0; skeletonJoint < skeletonJointCount; skeletonJoint++) { - _anim[frame].push_back(_skeleton->getRelativeBindPose(skeletonJoint)); + _anim[frame].push_back(_skeleton->getRelativeDefaultPose(skeletonJoint)); } for (int animJoint = 0; animJoint < animJointCount; animJoint++) { - 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]; - // AJT: TODO: use the actual preRotation not the bind pose here. - const AnimPose& jointOrientPose = _skeleton->getRelativeBindPose(skeletonJoint); +#ifdef USE_PRE_ROT_FROM_ANIM + // TODO: This is the correct way to apply the pre rotations from maya, however + // the current animation set has incorrect preRotations for the left wrist and thumb + // so it looks wrong if we enable this code. + glm::quat preRotation = animSkeleton.getPreRotation(animJoint); +#else + // TODO: This is legacy approach, this does not work when animations and models do not + // have the same set of pre rotations. For example when mixing maya models with blender animations. + glm::quat preRotation = _skeleton->getRelativeBindPose(skeletonJoint).rot; +#endif const AnimPose& relDefaultPose = _skeleton->getRelativeDefaultPose(skeletonJoint); // used to adjust translation offsets, so large translation animatons on the reference skeleton @@ -135,8 +142,8 @@ void AnimClip::copyFromNetworkAnim() { AnimPose& pose = _anim[frame][skeletonJoint]; const FBXAnimationFrame& fbxAnimFrame = geom.animationFrames[frame]; - // rotation in fbxAnimationFrame is a delta from its jointOrientPose (aka preRotation) - pose.rot = jointOrientPose.rot * fbxAnimFrame.rotations[animJoint]; + // rotation in fbxAnimationFrame is a delta from its preRotation. + pose.rot = preRotation * fbxAnimFrame.rotations[animJoint]; // translation in fbxAnimationFrame is not a delta. // convert it into a delta by subtracting from the first frame. diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2d2b2c4b0a..1be3bbb5f6 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -750,13 +750,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS model.preRotation = glm::quat(glm::radians(preRotation)); model.rotation = glm::quat(glm::radians(rotation)); model.postRotation = glm::quat(glm::radians(postRotation)); - - if (geometry.applicationName.startsWith("Blender")) { - // blender puts the jointOffset in the wrong place. - model.preRotation = model.rotation; - model.rotation = glm::quat(); - } - model.postTransform = glm::translate(-rotationPivot) * glm::translate(scaleOffset) * glm::translate(scalePivot) * glm::scale(scale) * glm::translate(-scalePivot); // NOTE: angles from the FBX file are in degrees