Trying to wrap my head around skinning transforms for skeletal animations. Using assimp to parse model data and GLM as math library (right-handed)
Here's how I understand it, the order in which transforms are done:
// calculate translation/rotation/scaling (TRS) of each bone and concatenate it with its parent
foreach bone in boneList
MAT4_bone = calculate TRS-matrix based on time
MAT4_parent = get parent TRS-matrix of bone
MAT4_bone = MAT4_parent * MAT4_bone
// after, apply bone offset and inverse root matrix
// why is the inverse root matrix needed anyway?
MAT4_rootInvMatrix = the inverse of the root matrix of the scene
foreach bone in boneList
MAT4_bone = the (now) absolute TRS matrix of a bone
MAT4_offset = the bones offset matrix given by assimp
MAT4_final = MAT4_rootInvMatrix * MAT4_bone * MAT4_offset
As far as I can tell, each assimp nodes original mTransform is just discard and not used at all?
And in code:
void AnimationUpdater::Update(const Milliseconds elapsedTime)
{
for (AnimationInstance& animationInstance : mActiveAnimations)
{
const BoneIndex bonesBegin = animationInstance.mBoneRange.first;
const BoneIndex bonesEnd = animationInstance.mBoneRange.second;
// mBoneTransforms - the final skinning transforms
// root has no parent
// note: root is always front
Mat4& rootTransform = mBoneTransforms.at(bonesBegin);
rootTransform = animation.InterpolateBoneTransform(bonesBegin, elapsedTime);
// interpolate bone animations
// parens always appear before their children
const uint32_t numBones = bonesEnd - bonesBegin;
for (uint32_t boneOffset = 1; boneOffset < numBones; ++boneOffset)
{
const BoneIndex bone = bonesBegin + boneOffset;
const BoneIndex parentBone = animation.GetParentIndex(bone);
const Mat4& parentTransform = mBoneTransforms.at(parentBone);
Mat4& transform = mBoneTransforms.at(bone);
transform = parentTransform * animation.InterpolateBoneTransform(bone, elapsedTime);
}
const Mat4& rootInverseTransform = animation.GetInverseRootMatrix();
for (uint32_t boneOffset = 1; boneOffset < numBones; ++boneOffset)
{
const BoneIndex bone = bonesBegin + boneOffset;
const Mat4& boneOffsetTransform = animation.GetBoneOffsetTransform(bone);
Mat4& transform = mBoneTransforms.at(bone);
transform = rootInverseTransform * transform * boneOffsetTransform;
}
}
}
Yet it all looks like a tangled mess during rendering. Is there anything obvious I'm missing here?