AnimSkeleton more accurate bind pose generation.

This commit is contained in:
Anthony J. Thibault 2015-08-24 16:19:16 -07:00
parent 9457794d9e
commit 5a73aef1f8
3 changed files with 34 additions and 48 deletions

View file

@ -43,7 +43,10 @@ AnimPose::operator glm::mat4() const {
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
}
//#define TRUST_BIND_TRANSFORM
static const mat4 IDENTITY = mat4();
static bool matrixIsIdentity(const glm::mat4& m) {
return m == IDENTITY;
}
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
_joints = joints;
@ -51,58 +54,37 @@ AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
// build a cache of bind poses
_absoluteBindPoses.reserve(joints.size());
_relativeBindPoses.reserve(joints.size());
for (size_t i = 0; i < joints.size(); i++) {
/*
// AJT: dump the skeleton, because wtf.
qCDebug(animation) << getJointName(i);
qCDebug(animation) << " isFree =" << _joints[i].isFree;
qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage;
qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex;
qCDebug(animation) << " boneRadius =" << _joints[i].boneRadius;
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;
*/
#ifdef TRUST_BIND_TRANSFORM
// trust FBXJoint::bindTransform (which is wrong for joints NOT bound to anything)
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);
if (_joints[i].bindTransformIsValid) {
// 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);
} else {
_relativeBindPoses.push_back(absoluteBindPose);
}
} else {
_relativeBindPoses.push_back(absoluteBindPose);
}
#else
// trust FBXJoint's local transforms (which is not really the bind pose, but the default pose in the fbx)
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);
// 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);
if (parentIndex >= 0) {
_absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relBindPose);
} else {
_absoluteBindPoses.push_back(relBindPose);
int parentIndex = getParentIndex(i);
if (parentIndex >= 0) {
_absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relBindPose);
} else {
_absoluteBindPoses.push_back(relBindPose);
}
}
#endif
}
}
int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
for (size_t i = 0; i < _joints.size(); i++) {
if (_joints[i].name == jointName) {

View file

@ -2307,7 +2307,9 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
break;
}
}
joint.bindTransformIsValid = false;
geometry.joints.append(joint);
geometry.jointIndices.insert(model.name, geometry.joints.size());
@ -2535,7 +2537,8 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
FBXJoint& joint = geometry.joints[fbxCluster.jointIndex];
joint.inverseBindRotation = glm::inverse(extractRotation(cluster.transformLink));
joint.bindTransform = cluster.transformLink;
joint.bindTransformIsValid = true;
// update the bind pose extents
glm::vec3 bindTranslation = extractTranslation(geometry.offset * joint.bindTransform);
geometry.bindExtents.addPoint(bindTranslation);

View file

@ -84,6 +84,7 @@ public:
glm::mat4 bindTransform;
QString name;
bool isSkeletonJoint;
bool bindTransformIsValid;
};