AnimSkeleton: Added default poses

This commit is contained in:
Anthony J. Thibault 2015-11-18 16:03:28 -08:00
parent 5ffef7f41a
commit 3a74d188b0
2 changed files with 71 additions and 15 deletions

View file

@ -70,6 +70,14 @@ const AnimPose& AnimSkeleton::getRelativeBindPose(int jointIndex) const {
return _relativeBindPoses[jointIndex];
}
const AnimPose& AnimSkeleton::getRelativeDefaultPose(int jointIndex) const {
return _relativeDefaultPoses[jointIndex];
}
const AnimPose& AnimSkeleton::getAbsoluteDefaultPose(int jointIndex) const {
return _absoluteDefaultPoses[jointIndex];
}
int AnimSkeleton::getParentIndex(int jointIndex) const {
return _joints[jointIndex].parentIndex;
}
@ -93,14 +101,31 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints,
_absoluteBindPoses.reserve(joints.size());
_relativeBindPoses.reserve(joints.size());
// build a chache of default poses
_absoluteDefaultPoses.reserve(joints.size());
_relativeDefaultPoses.reserve(joints.size());
// iterate over FBXJoints and extract the bind pose information.
for (size_t i = 0; i < joints.size(); i++) {
// build relative and absolute default poses
glm::mat4 rotTransform = glm::mat4_cast(_joints[i].preRotation * _joints[i].rotation * _joints[i].postRotation);
glm::mat4 relDefaultMat = glm::translate(_joints[i].translation) * _joints[i].preTransform * rotTransform * _joints[i].postTransform;
AnimPose relDefaultPose(relDefaultMat);
_relativeDefaultPoses.push_back(relDefaultPose);
int parentIndex = getParentIndex(i);
if (parentIndex >= 0) {
_absoluteDefaultPoses.push_back(_absoluteDefaultPoses[parentIndex] * relDefaultPose);
} else {
_absoluteDefaultPoses.push_back(relDefaultPose);
}
// build relative and absolute bind poses
if (_joints[i].bindTransformFoundInCluster) {
// Use the FBXJoint::bindTransform, which is absolute model coordinates
// i.e. not relative to it's parent.
AnimPose absoluteBindPose(_joints[i].bindTransform);
_absoluteBindPoses.push_back(absoluteBindPose);
int parentIndex = getParentIndex(i);
if (parentIndex >= 0) {
AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse();
_relativeBindPoses.push_back(inverseParentAbsoluteBindPose * absoluteBindPose);
@ -108,39 +133,40 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints,
_relativeBindPoses.push_back(absoluteBindPose);
}
} else {
// use FBXJoint's local transform, instead
glm::mat4 rotTransform = glm::mat4_cast(_joints[i].preRotation * _joints[i].rotation * _joints[i].postRotation);
glm::mat4 relBindMat = glm::translate(_joints[i].translation) * _joints[i].preTransform * rotTransform * _joints[i].postTransform;
AnimPose relBindPose(relBindMat);
_relativeBindPoses.push_back(relBindPose);
int parentIndex = getParentIndex(i);
// use default transform instead
_relativeBindPoses.push_back(relDefaultPose);
if (parentIndex >= 0) {
_absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relBindPose);
_absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relDefaultPose);
} else {
_absoluteBindPoses.push_back(relBindPose);
_absoluteBindPoses.push_back(relDefaultPose);
}
}
}
// now we want to normalize scale from geometryOffset to all poses.
// This will ensure our bone translations will be in meters, even if the model was authored with some other unit of mesure.
for (auto& absPose : _absoluteBindPoses) {
normalizeScale(geometryOffset, _relativeBindPoses, _absoluteBindPoses);
normalizeScale(geometryOffset, _relativeDefaultPoses, _absoluteDefaultPoses);
}
void AnimSkeleton::normalizeScale(const AnimPose& geometryOffset, AnimPoseVec& relPoses, AnimPoseVec& absPoses) const {
for (auto& absPose : absPoses) {
absPose.trans = (geometryOffset * absPose).trans;
absPose.scale = vec3(1, 1, 1);
}
// re-compute relative poses based on the modified absolute poses.
for (size_t i = 0; i < _relativeBindPoses.size(); i++) {
for (size_t i = 0; i < relPoses.size(); i++) {
int parentIndex = getParentIndex(i);
if (parentIndex >= 0) {
_relativeBindPoses[i] = _absoluteBindPoses[parentIndex].inverse() * _absoluteBindPoses[i];
relPoses[i] = absPoses[parentIndex].inverse() * absPoses[i];
} else {
_relativeBindPoses[i] = _absoluteBindPoses[i];
relPoses[i] = absPoses[i];
}
}
}
#define DUMP_FBX_JOINTS
#ifndef NDEBUG
void AnimSkeleton::dump() const {
qCDebug(animation) << "[";
@ -150,6 +176,25 @@ void AnimSkeleton::dump() const {
qCDebug(animation) << " name =" << getJointName(i);
qCDebug(animation) << " absBindPose =" << getAbsoluteBindPose(i);
qCDebug(animation) << " relBindPose =" << getRelativeBindPose(i);
qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i);
qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i);
#ifdef DUMP_FBX_JOINTS
qCDebug(animation) << " isFree =" << _joints[i].isFree;
qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage;
qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex;
qCDebug(animation) << " translation =" << _joints[i].translation;
qCDebug(animation) << " preTransform =" << _joints[i].preTransform;
qCDebug(animation) << " preRotation =" << _joints[i].preRotation;
qCDebug(animation) << " rotation =" << _joints[i].rotation;
qCDebug(animation) << " postRotation =" << _joints[i].postRotation;
qCDebug(animation) << " postTransform =" << _joints[i].postTransform;
qCDebug(animation) << " transform =" << _joints[i].transform;
qCDebug(animation) << " rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax;
qCDebug(animation) << " inverseDefaultRotation" << _joints[i].inverseDefaultRotation;
qCDebug(animation) << " inverseBindRotation" << _joints[i].inverseBindRotation;
qCDebug(animation) << " bindTransform" << _joints[i].bindTransform;
qCDebug(animation) << " isSkeletonJoint" << _joints[i].isSkeletonJoint;
#endif
if (getParentIndex(i) >= 0) {
qCDebug(animation) << " parent =" << getJointName(getParentIndex(i));
}
@ -166,6 +211,8 @@ void AnimSkeleton::dump(const AnimPoseVec& poses) const {
qCDebug(animation) << " name =" << getJointName(i);
qCDebug(animation) << " absBindPose =" << getAbsoluteBindPose(i);
qCDebug(animation) << " relBindPose =" << getRelativeBindPose(i);
qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i);
qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i);
qCDebug(animation) << " pose =" << poses[i];
if (getParentIndex(i) >= 0) {
qCDebug(animation) << " parent =" << getJointName(getParentIndex(i));

View file

@ -38,6 +38,12 @@ public:
const AnimPose& getRelativeBindPose(int jointIndex) const;
const AnimPoseVec& getRelativeBindPoses() const { return _relativeBindPoses; }
// the default poses are the orientations of the joints on frame 0.
const AnimPose& getRelativeDefaultPose(int jointIndex) const;
const AnimPoseVec& getRelativeDefaultPoses() const { return _relativeDefaultPoses; }
const AnimPose& getAbsoluteDefaultPose(int jointIndex) const;
const AnimPoseVec& getAbsoluteDefaultPoses() const { return _absoluteDefaultPoses; }
int getParentIndex(int jointIndex) const;
AnimPose getAbsolutePose(int jointIndex, const AnimPoseVec& poses) const;
@ -49,10 +55,13 @@ public:
protected:
void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset);
void normalizeScale(const AnimPose& geometryOffset, AnimPoseVec& relPoses, AnimPoseVec& absPoses) const;
std::vector<FBXJoint> _joints;
AnimPoseVec _absoluteBindPoses;
AnimPoseVec _relativeBindPoses;
AnimPoseVec _relativeDefaultPoses;
AnimPoseVec _absoluteDefaultPoses;
// no copies
AnimSkeleton(const AnimSkeleton&) = delete;