应用骨架动画后旋转并撕裂网格

时间:2019-04-03 18:21:34

标签: c++ opengl skeletal-animation

我正在尝试使用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

静态网格物体看起来像这样: static

但是当我使用那个mSkinMatrices进行顶点蒙皮时,那个网格变得撕裂并旋转了: skinned


很明显,我做错了事,但我自己找不到。

你们能建议我吗?

0 个答案:

没有答案