added the const argument to the AnimSkeleton constructor that allows the offset rotations to be passed in

This commit is contained in:
amantley 2018-11-01 13:33:03 -07:00
parent f1d9ab76b4
commit 64d8fa6875
6 changed files with 36 additions and 26 deletions

View file

@ -84,7 +84,8 @@ void ScriptableAvatar::update(float deltatime) {
// Run animation
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) {
if (!_animSkeleton) {
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getGeometry());
QMap<int, glm::quat> jointRotationOffsets;
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getGeometry(), jointRotationOffsets);
}
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {

View file

@ -102,7 +102,8 @@ 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();
AnimSkeleton animSkeleton(geom);
QMap<int, glm::quat> jointRotationOffsets;
AnimSkeleton animSkeleton(geom, jointRotationOffsets);
const auto animJointCount = animSkeleton.getNumJoints();
const auto skeletonJointCount = _skeleton->getNumJoints();
std::vector<int> jointMap;

View file

@ -16,21 +16,20 @@
#include "AnimationLogging.h"
AnimSkeleton::AnimSkeleton(const FBXGeometry& fbxGeometry) {
AnimSkeleton::AnimSkeleton(const FBXGeometry& fbxGeometry, const QMap<int, glm::quat> jointOffsets) {
// convert to std::vector of joints
std::vector<FBXJoint> joints;
joints.reserve(fbxGeometry.joints.size());
_avatarTPoseOffsets.reserve(fbxGeometry.joints.size());
AnimPose identity(glm::quat(), glm::vec3());
//_avatarTPoseOffsets.reserve(_jointsSize);
for (auto& joint : fbxGeometry.joints) {
joints.push_back(joint);
_avatarTPoseOffsets.push_back(identity);
//_avatarTPoseOffsets.push_back(AnimPose(glm::quat(), glm::vec3()));
}
buildSkeletonFromJoints(joints);
/*
//add offsets for spine2 and the neck
_avatarTPoseOffsets[nameToJointIndex("Spine2")] = AnimPose(glm::quat(-0.707107f, 0.0f, 0.0f, 0.707107f), glm::vec3());
_avatarTPoseOffsets[nameToJointIndex("Neck")] = AnimPose(glm::quat(0.0f, 0.707107f, 0.0f, 0.707107f), glm::vec3());
// add offsets for spine2 and the neck
// _avatarTPoseOffsets[nameToJointIndex("Spine2")] = AnimPose(glm::quat(-0.707107f, 0.0f, 0.0f, 0.707107f), glm::vec3());
// _avatarTPoseOffsets[nameToJointIndex("Neck")] = AnimPose(glm::quat(0.0f, 0.707107f, 0.0f, 0.707107f), glm::vec3());
for (int i = 0; i < (int)fbxGeometry.meshes.size(); i++) {
const FBXMesh& mesh = fbxGeometry.meshes.at(i);
@ -40,16 +39,19 @@ AnimSkeleton::AnimSkeleton(const FBXGeometry& fbxGeometry) {
// AJT: mutate bind pose! this allows us to oreint the skeleton back into the authored orientaiton before
// rendering, with no runtime overhead.
// this works if clusters match joints one for one.
//cluster.inverseBindMatrix = (glm::mat4)_avatarTPoseOffsets[cluster.jointIndex].inverse() * cluster.inverseBindMatrix;
cluster.inverseBindTransform.evalFromRawMatrix(cluster.inverseBindMatrix);
if (jointOffsets.contains(j)) {
AnimPose localOffset(jointOffsets[j], glm::vec3());
cluster.inverseBindMatrix = (glm::mat4)localOffset.inverse() * cluster.inverseBindMatrix;
cluster.inverseBindTransform.evalFromRawMatrix(cluster.inverseBindMatrix);
}
}
}
*/
buildSkeletonFromJoints(joints, jointOffsets);
}
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
buildSkeletonFromJoints(joints);
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints, const QMap<int, glm::quat> jointOffsets) {
buildSkeletonFromJoints(joints, jointOffsets);
}
int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
@ -188,7 +190,7 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const {
}
}
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints) {
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints, const QMap<int, glm::quat> jointOffsets) {
_joints = joints;
_jointsSize = (int)joints.size();
// build a cache of bind poses
@ -218,9 +220,14 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
// remember the inverse bind pose already has the offset added into it. the total effect is offset^-1 * relDefPose * offset.
// this gives us the correct transform for the joint that has been put in t-pose with an offset rotation.
//relDefaultPose = relDefaultPose * _avatarTPoseOffsets[i];
//if (parentIndex >= 0) {
// relDefaultPose = _avatarTPoseOffsets[parentIndex].inverse() * AnimPose(glm::quat(), relDefaultPose.trans()) * _avatarTPoseOffsets[parentIndex] * AnimPose(relDefaultPose.rot(), glm::vec3());
//}
if (jointOffsets.contains(i)) {
AnimPose localOffset(jointOffsets[i], glm::vec3());
relDefaultPose = relDefaultPose * localOffset;
if ((parentIndex >= 0) && jointOffsets.contains(parentIndex)) {
AnimPose localParentOffset(jointOffsets[parentIndex], glm::vec3());
relDefaultPose = localParentOffset.inverse() * AnimPose(glm::quat(), relDefaultPose.trans()) * localParentOffset * AnimPose(relDefaultPose.rot(), glm::vec3());
}
}
_relativeDefaultPoses.push_back(relDefaultPose);

View file

@ -23,8 +23,8 @@ public:
using Pointer = std::shared_ptr<AnimSkeleton>;
using ConstPointer = std::shared_ptr<const AnimSkeleton>;
explicit AnimSkeleton(const FBXGeometry& fbxGeometry);
explicit AnimSkeleton(const std::vector<FBXJoint>& joints);
explicit AnimSkeleton(const FBXGeometry& fbxGeometry, const QMap<int, glm::quat> jointOffsets);
explicit AnimSkeleton(const std::vector<FBXJoint>& joints, const QMap<int, glm::quat> jointOffsets);
int nameToJointIndex(const QString& jointName) const;
const QString& getJointName(int jointIndex) const;
int getNumJoints() const;
@ -64,7 +64,7 @@ public:
std::vector<int> lookUpJointIndices(const std::vector<QString>& jointNames) const;
protected:
void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints);
void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints, const QMap<int, glm::quat> jointOffsets);
std::vector<FBXJoint> _joints;
AnimPoseVec _avatarTPoseOffsets;

View file

@ -267,7 +267,7 @@ void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOff
_rigToGeometryTransform = glm::inverse(_geometryToRigTransform);
setModelOffset(modelOffset);
_animSkeleton = std::make_shared<AnimSkeleton>(geometry);
_animSkeleton = std::make_shared<AnimSkeleton>(geometry,_jointRotationOffsets);
_internalPoseSet._relativePoses.clear();
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
@ -310,7 +310,7 @@ void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOff
void Rig::reset(const FBXGeometry& geometry) {
_geometryOffset = AnimPose(geometry.offset);
_invGeometryOffset = _geometryOffset.inverse();
_animSkeleton = std::make_shared<AnimSkeleton>(geometry);
_animSkeleton = std::make_shared<AnimSkeleton>(geometry, _jointRotationOffsets);
_internalPoseSet._relativePoses.clear();
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();

View file

@ -55,7 +55,8 @@ SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc
}
QByteArray blob = file.readAll();
std::unique_ptr<FBXGeometry> fbxGeometry(readFBX(blob, QVariantHash()));
std::unique_ptr<AnimSkeleton> skeleton(new AnimSkeleton(*fbxGeometry));
QMap<int, glm::quat> jointRotationOffsets;
std::unique_ptr<AnimSkeleton> skeleton(new AnimSkeleton(*fbxGeometry, jointRotationOffsets));
skeleton->dump(verbose);
}