Как я могу получить матрицу обратной привязки из FBX SDK 2018 года? - PullRequest
0 голосов
/ 21 декабря 2018

Я пишу инструмент для извлечения необходимых данных из файла .fbx для записи в пользовательский файл и загрузки в игровой движок.У меня есть сетки, суставы и скелетные анимации, которые работают и отображаются правильно, но я не могу заставить его работать, когда я включаю скиннинг.

Я отображаю скелетные анимации путем рекурсивного преобразования исходной точки черезКлючевой кадр костяного дерева трансформируется и рисует линии между ними:

Скелетная анимация

Я почти уверен, что логически сузил его до неправильного получения матрицы поз обратной привязки связыванияиз файла, поскольку скелетная анимация выглядит точной.

Вот так я получаю позу обратного связывания:

            // Find the joint associated with this cluster
      FbxCluster *fbx_cluster = fbx_skin->GetCluster(i_cluster);
      std::string joint_name = fbx_cluster->GetLink()->GetName();
      auto joint = std::find(model.m_skeleton.m_joints.begin(), model.m_skeleton.m_joints.end(), joint_name);

      FbxAMatrix transform_matrix;
      FbxAMatrix transform_link_matrix;
      FbxAMatrix parent_transform_link_matrix;

        // Calculate bind pose matrix, which is the starting transformation matrix
      fbx_cluster->GetTransformMatrix(transform_matrix);
      fbx_cluster->GetTransformLinkMatrix(transform_link_matrix);

      const FbxVector4 lT = fbx_cluster->GetLink()->GetGeometricTranslation(FbxNode::eSourcePivot);
      const FbxVector4 lR = fbx_cluster->GetLink()->GetGeometricRotation(FbxNode::eSourcePivot);
      const FbxVector4 lS = fbx_cluster->GetLink()->GetGeometricScaling(FbxNode::eSourcePivot);

      FbxAMatrix geom(lT, lR, lS);

      joint->m_jointNode = fbx_cluster->GetLink();
      joint->m_inverseBindPose = transform_link_matrix.Inverse() * transform_matrix * geom;
      joint->m_isBindPoseSet = true;

Согласно различным онлайн-статьям, "transform_matrix" и "geom"Существуют ли они для совместимости с другим программным обеспечением и, как правило, представляют собой просто матрицу идентификации, и я подтвердил, что это именно такПоэтому я в основном вызываю GetTransformLinkMatrix и инвертирую его.Затем для соединений, у которых нет кластера, связанного с ним, я делаю это:

  // If the joint didn't have a cluster, it wasn't a part of binding, and therefore
  // doesn't have an inverse bind pose. We have to make one here
if (!joint.m_isBindPoseSet) {
  joint.m_isBindPoseSet = true;
  joint.m_globalBindPoseMatrix = joint.m_jointNode->EvaluateLocalTransform().Inverse() * model.m_skeleton.m_joints[joint.m_parentIndex].m_inverseBindPoseMatrix;
}

То есть, просто получая локальное преобразование соединения и умножая его на обратную позицию связывания его родителя.Я пробовал это с 3 различными анимированными ригами, и ни одна из них не работает.Вот пример того, как это выглядит:

Скиннинг

Мне кажется, что я провел много исследований по этому вопросу, но я не знаю, чтонеправильно.Я использую DirectX 11, если это вообще актуально.Я также использую fbx-файлы, экспортированные из Maya, созданные некоторыми друзьями-художниками.(И один файл майя, который я нашел в интернете, который я сам экспортировал).Заранее спасибо!

1 Ответ

0 голосов
/ 21 декабря 2018

Попробуйте это:

FbxAMatrix inverse_bindpose = joint->EvaluateGlobalTransform().Inverse();
...