fix: gltf mesh wrong bone and invertBindMatrix transformations

This commit is contained in:
Jan 2024-05-12 16:42:44 +02:00
parent 17dee65337
commit 9979275f8c
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C

View File

@ -5,6 +5,7 @@
#include "XModel/Gltf/GltfConstants.h" #include "XModel/Gltf/GltfConstants.h"
#include "XModel/Gltf/JsonGltf.h" #include "XModel/Gltf/JsonGltf.h"
#include <Eigen>
#include <format> #include <format>
using namespace gltf; using namespace gltf;
@ -222,20 +223,27 @@ namespace
JsonNode boneNode; JsonNode boneNode;
const auto& bone = xmodel.m_bones[boneIndex]; const auto& bone = xmodel.m_bones[boneIndex];
Vector3f translation(bone.globalOffset[0], bone.globalOffset[2], -bone.globalOffset[1]); Eigen::Vector3f translation(bone.globalOffset[0], bone.globalOffset[2], -bone.globalOffset[1]);
Quaternion32 rotation(bone.globalRotation.m_x, bone.globalRotation.m_z, -bone.globalRotation.m_y, bone.globalRotation.m_w); Eigen::Quaternionf rotation(bone.globalRotation.m_w, bone.globalRotation.m_x, bone.globalRotation.m_z, -bone.globalRotation.m_y);
if (bone.parentIndex >= 0) if (bone.parentIndex >= 0)
{ {
const auto& parentBone = xmodel.m_bones[bone.parentIndex]; const auto& parentBone = xmodel.m_bones[bone.parentIndex];
translation -= Vector3f(parentBone.globalOffset[0], parentBone.globalOffset[2], -parentBone.globalOffset[1]); const auto inverseParentRotation =
rotation /= Quaternion32( Eigen::Quaternionf(
parentBone.globalRotation.m_x, parentBone.globalRotation.m_z, -parentBone.globalRotation.m_y, parentBone.globalRotation.m_w); parentBone.globalRotation.m_w, parentBone.globalRotation.m_x, parentBone.globalRotation.m_z, -parentBone.globalRotation.m_y)
.normalized()
.inverse()
.normalized();
translation -= Eigen::Vector3f(parentBone.globalOffset[0], parentBone.globalOffset[2], -parentBone.globalOffset[1]);
translation = inverseParentRotation * translation;
rotation = inverseParentRotation * rotation;
} }
rotation.Normalize(); rotation.normalize();
boneNode.name = bone.name; boneNode.name = bone.name;
boneNode.translation = std::to_array({translation.x(), translation.y(), translation.z()}); boneNode.translation = std::to_array({translation.x(), translation.y(), translation.z()});
boneNode.rotation = std::to_array({rotation.m_x, rotation.m_y, rotation.m_z, rotation.m_w}); boneNode.rotation = std::to_array({rotation.x(), rotation.y(), rotation.z(), rotation.w()});
std::vector<unsigned> children; std::vector<unsigned> children;
for (auto maybeChildIndex = 0u; maybeChildIndex < boneCount; maybeChildIndex++) for (auto maybeChildIndex = 0u; maybeChildIndex < boneCount; maybeChildIndex++)
@ -267,6 +275,7 @@ namespace
skin.joints.emplace_back(boneIndex + m_first_bone_node); skin.joints.emplace_back(boneIndex + m_first_bone_node);
skin.inverseBindMatrices = m_inverse_bind_matrices_accessor; skin.inverseBindMatrices = m_inverse_bind_matrices_accessor;
skin.skeleton = m_first_bone_node;
gltf.skins->emplace_back(std::move(skin)); gltf.skins->emplace_back(std::move(skin));
} }
@ -511,29 +520,29 @@ namespace
auto* inverseBindMatrixData = reinterpret_cast<float*>(&bufferData[currentBufferOffset]); auto* inverseBindMatrixData = reinterpret_cast<float*>(&bufferData[currentBufferOffset]);
for (const auto& bone : xmodel.m_bones) for (const auto& bone : xmodel.m_bones)
{ {
Matrix32 inverseBindMatrix; const auto translation = Eigen::Translation3f(bone.globalOffset[0], bone.globalOffset[2], -bone.globalOffset[1]);
inverseBindMatrix.m_data[0][3] = -bone.globalOffset[0]; const auto rotation =
inverseBindMatrix.m_data[1][3] = -bone.globalOffset[2]; Eigen::Quaternionf(bone.globalRotation.m_w, bone.globalRotation.m_x, bone.globalRotation.m_z, -bone.globalRotation.m_y);
inverseBindMatrix.m_data[2][3] = bone.globalOffset[1];
// In-memory = row major const auto inverseBindMatrix = (translation * rotation).matrix().inverse();
// gltf = column major
inverseBindMatrixData[0] = inverseBindMatrix.m_data[0][0]; // GLTF matrix is column major
inverseBindMatrixData[1] = inverseBindMatrix.m_data[1][0]; inverseBindMatrixData[0] = inverseBindMatrix(0, 0);
inverseBindMatrixData[2] = inverseBindMatrix.m_data[2][0]; inverseBindMatrixData[1] = inverseBindMatrix(1, 0);
inverseBindMatrixData[3] = inverseBindMatrix.m_data[3][0]; inverseBindMatrixData[2] = inverseBindMatrix(2, 0);
inverseBindMatrixData[4] = inverseBindMatrix.m_data[0][1]; inverseBindMatrixData[3] = inverseBindMatrix(3, 0);
inverseBindMatrixData[5] = inverseBindMatrix.m_data[1][1]; inverseBindMatrixData[4] = inverseBindMatrix(0, 1);
inverseBindMatrixData[6] = inverseBindMatrix.m_data[2][1]; inverseBindMatrixData[5] = inverseBindMatrix(1, 1);
inverseBindMatrixData[7] = inverseBindMatrix.m_data[3][1]; inverseBindMatrixData[6] = inverseBindMatrix(2, 1);
inverseBindMatrixData[8] = inverseBindMatrix.m_data[0][2]; inverseBindMatrixData[7] = inverseBindMatrix(3, 1);
inverseBindMatrixData[9] = inverseBindMatrix.m_data[1][2]; inverseBindMatrixData[8] = inverseBindMatrix(0, 2);
inverseBindMatrixData[10] = inverseBindMatrix.m_data[2][2]; inverseBindMatrixData[9] = inverseBindMatrix(1, 2);
inverseBindMatrixData[11] = inverseBindMatrix.m_data[3][2]; inverseBindMatrixData[10] = inverseBindMatrix(2, 2);
inverseBindMatrixData[12] = inverseBindMatrix.m_data[0][3]; inverseBindMatrixData[11] = inverseBindMatrix(3, 2);
inverseBindMatrixData[13] = inverseBindMatrix.m_data[1][3]; inverseBindMatrixData[12] = inverseBindMatrix(0, 3);
inverseBindMatrixData[14] = inverseBindMatrix.m_data[2][3]; inverseBindMatrixData[13] = inverseBindMatrix(1, 3);
inverseBindMatrixData[15] = inverseBindMatrix.m_data[3][3]; inverseBindMatrixData[14] = inverseBindMatrix(2, 3);
inverseBindMatrixData[15] = inverseBindMatrix(3, 3);
inverseBindMatrixData += 16u; inverseBindMatrixData += 16u;
} }