Сетка вращается и рвется после применения скелетной анимации - PullRequest
0 голосов
/ 03 апреля 2019

Я пытаюсь реализовать скелетную анимацию, используя OpenGL и C ++. Кроме того, порядок матрицы является главным по столбцу (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 прохода для обновления матриц скина.

Сначала интерполируйте два кадра и сохраните в матрице скинов. Сустав сортируется по его идентификатору в порядке возрастания.

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


Очевидно, что я делаю что-то не так, но сам не могу понять.

Можете ли вы, ребята, посоветовать мне?

...