我正在尝试使用OpenGL和C ++实现骨骼动画。 而且,矩阵顺序是column-major(glm)。
我的Joint
是这样的:
struct Joint {
u8 id;
u8 parentId;
mat4 invBindPose;
}
具体来说,Joint::invBindPose
来自FBX,使用以下代码行:
FbxAMatrix transformLinkMatrix{};
cluster->GetTransformLinkMatrix(transformLinkMatrix);
FbxAMatrix transformMatrix{};
cluster->GetTransformMatrix(transformMatrix);
// FbxAMatrix->glm::mat4
joint.invBindPose = makeMat4(transformLinkMatrix.Inverse() * transformMatrix);
这是棘手的部分,我正在努力。我正在使用3次更新皮肤矩阵。
首先,插值两帧并存储到皮肤矩阵中。关节按其ID升序排序。
for (u8 i = 0; i < jointCount; ++i) {
// track stores keys and joint id that affects.
auto track = mCurrAnimation->track(i); // here, find track by joint id.
auto& currKey = track->key[mCurrKeyIndex];
auto& nextKey = track->key[mNextKeyIndex];
// interpolate translation(vector3)
auto t = glm::mix(currKey.t, nextKey.t, alpha);
// spherically interpolate rotation(quaternion)
auto q = glm::slerp(currKey.q, nextKey.q, alpha);
// compose translation, rotation, scaling
mat4 transform = Math::compose(t, q, vec3{1.0});
mSkinMatrices[i] = transform;
}
第二,乘以父变换
// root joint is at 0 -> no need to calculate?
for (u8 i = 1; i < jointCount; ++i) {
const auto parentId = mSkeleton->joints[i].parentId;
mSkinMatrices[i] = mSkinMatrices[i] * mSkinMatrices[parentId];
}
第三乘以反向绑定姿势
for (u8 i = 0; i < jointCount; ++i) {
auto& joint = mSkeleton->joints[i];
mSkinMatrice[i] = joint.invBindPose * mSkinMatrices[i];
}
有关更多详细信息,我使用这些代码行从FBX获取密钥:
const auto transform = node->EvaluateLocalTransform(time);
key.t = makeVec3(transform.GetT()); // FbxVector4->glm::vec3
key.q = makeQuat(trasnform.GetQ()); // FbxQuaterion->glm::quat
但是当我使用那个mSkinMatrices
进行顶点蒙皮时,那个网格变得撕裂并旋转了:
很明显,我做错了事,但我自己找不到。
你们能建议我吗?