summaryrefslogtreecommitdiff
path: root/indra/newview/gltf/llgltfloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/gltf/llgltfloader.cpp')
-rw-r--r--indra/newview/gltf/llgltfloader.cpp110
1 files changed, 86 insertions, 24 deletions
diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp
index 236c75a125..1f8733f4ff 100644
--- a/indra/newview/gltf/llgltfloader.cpp
+++ b/indra/newview/gltf/llgltfloader.cpp
@@ -155,6 +155,12 @@ bool LLGLTFLoader::parseMeshes()
mTransform.setIdentity();
+ for (auto& node : mGLTFAsset.mNodes)
+ {
+ // Make node matrix valid for correct transformation
+ node.makeMatrixValid();
+ }
+
// Populate the joints from skins first.
// There's not many skins - and you can pretty easily iterate through the nodes from that.
for (auto& skin : mGLTFAsset.mSkins)
@@ -162,12 +168,6 @@ bool LLGLTFLoader::parseMeshes()
populateJointFromSkin(skin);
}
- for (auto& node : mGLTFAsset.mNodes)
- {
- // Make node matrix valid for correct transformation
- node.makeMatrixValid();
- }
-
// Track how many times each mesh name has been used
std::map<std::string, S32> mesh_name_counts;
@@ -218,17 +218,21 @@ bool LLGLTFLoader::parseMeshes()
mesh_scale *= transformation;
transformation = mesh_scale;
- // "Bind Shape Matrix" is supposed to transform the geometry of the skinned mesh
- // into the coordinate space of the joints.
- // In GLTF, this matrix is omitted, and it is assumed that this transform is either
- // premultiplied with the mesh data, or postmultiplied to the inverse bind matrices.
- //
- // TODO: This appers to be missing rotation when joints rotate the model
- // or inverted bind matrices are missing inherited rotation
- // (based of values the 'bento shoes' mesh might be missing 90 degrees horizontaly
- // prior to skinning)
- pModel->mSkinInfo.mBindShapeMatrix.loadu(mesh_scale);
- LL_INFOS("GLTF_DEBUG") << "Model: " << pModel->mLabel << " mBindShapeMatrix: " << pModel->mSkinInfo.mBindShapeMatrix << LL_ENDL;
+ if (node.mSkin >= 0)
+ {
+ // "Bind Shape Matrix" is supposed to transform the geometry of the skinned mesh
+ // into the coordinate space of the joints.
+ // In GLTF, this matrix is omitted, and it is assumed that this transform is either
+ // premultiplied with the mesh data, or postmultiplied to the inverse bind matrices.
+ //
+ // TODO: There appears to be missing rotation when joints rotate the model
+ // or inverted bind matrices are missing inherited rotation
+ // (based of values the 'bento shoes' mesh might be missing 90 degrees horizontaly
+ // prior to skinning)
+
+ pModel->mSkinInfo.mBindShapeMatrix.loadu(mesh_scale);
+ LL_INFOS("GLTF_DEBUG") << "Model: " << pModel->mLabel << " mBindShapeMatrix: " << pModel->mSkinInfo.mBindShapeMatrix << LL_ENDL;
+ }
if (transformation.determinant() < 0)
{ // negative scales are not supported
@@ -256,7 +260,7 @@ bool LLGLTFLoader::parseMeshes()
return true;
}
-void LLGLTFLoader::computeCombinedNodeTransform(const LL::GLTF::Asset& asset, S32 node_index, glm::mat4& combined_transform)
+void LLGLTFLoader::computeCombinedNodeTransform(const LL::GLTF::Asset& asset, S32 node_index, glm::mat4& combined_transform) const
{
if (node_index < 0 || node_index >= static_cast<S32>(asset.mNodes.size()))
{
@@ -342,7 +346,6 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
// Process joint name and idnex
S32 joint = gltf_skin.mJoints[i];
LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint];
- jointNode.makeMatrixValid();
std::string legal_name(jointNode.mName);
if (mJointMap.find(legal_name) == mJointMap.end())
@@ -688,7 +691,6 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
continue;
}
LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint];
- jointNode.makeMatrixValid();
std::string legal_name(jointNode.mName);
if (mJointMap.find(legal_name) != mJointMap.end())
@@ -723,8 +725,15 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
// Get the original joint node and use its matrix directly
S32 joint = gltf_skin.mJoints[i];
LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint];
- jointNode.makeMatrixValid();
- LLMatrix4 original_joint_transform(glm::value_ptr(jointNode.mMatrix));
+ glm::mat4 joint_mat = jointNode.mMatrix;
+ S32 root_joint = findValidRootJoint(joint, gltf_skin); // skeleton can have multiple real roots
+ if (root_joint == joint)
+ {
+ // This is very likely incomplete in some way.
+ // Root shouldn't be the only one to need full coordinate fix
+ joint_mat = coord_system_rotation * joint_mat;
+ }
+ LLMatrix4 original_joint_transform(glm::value_ptr(joint_mat));
LL_INFOS("GLTF_DEBUG") << "mAlternateBindMatrix name: " << legal_name << " val: " << original_joint_transform << LL_ENDL;
skin_info.mAlternateBindMatrix.push_back(LLMatrix4a(original_joint_transform));
@@ -771,8 +780,6 @@ void LLGLTFLoader::populateJointFromSkin(const LL::GLTF::Skin& skin)
continue;
}
- jointNode.makeMatrixValid();
-
// Debug: Log original joint matrix
glm::mat4 gltf_joint_matrix = jointNode.mMatrix;
LL_INFOS("GLTF_DEBUG") << "Joint '" << legal_name << "' original matrix:" << LL_ENDL;
@@ -801,6 +808,61 @@ void LLGLTFLoader::populateJointFromSkin(const LL::GLTF::Skin& skin)
}
}
+S32 LLGLTFLoader::findValidRootJoint(S32 source_joint, const LL::GLTF::Skin& gltf_skin) const
+{
+ S32 root_joint = 0;
+ S32 found_joint = source_joint;
+ S32 size = (S32)gltf_skin.mJoints.size();
+ do
+ {
+ root_joint = found_joint;
+ for (S32 i = 0; i < size; i++)
+ {
+ S32 joint = gltf_skin.mJoints[i];
+ const LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint];
+
+ if (mJointMap.find(jointNode.mName) != mJointMap.end())
+ {
+ std::vector<S32>::const_iterator it = std::find(jointNode.mChildren.begin(), jointNode.mChildren.end(), root_joint);
+ if (it != jointNode.mChildren.end())
+ {
+ found_joint = joint;
+ break;
+ }
+ }
+ }
+ } while (root_joint != found_joint);
+
+ return root_joint;
+}
+
+S32 LLGLTFLoader::findGLTFRootJoint(const LL::GLTF::Skin& gltf_skin) const
+{
+ S32 root_joint = 0;
+ S32 found_joint = 0;
+ S32 size = (S32)gltf_skin.mJoints.size();
+ do
+ {
+ root_joint = found_joint;
+ for (S32 i = 0; i < size; i++)
+ {
+ S32 joint = gltf_skin.mJoints[i];
+ const LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint];
+ std::vector<S32>::const_iterator it = std::find(jointNode.mChildren.begin(), jointNode.mChildren.end(), root_joint);
+ if (it != jointNode.mChildren.end())
+ {
+ found_joint = joint;
+ break;
+ }
+ }
+ } while (root_joint != found_joint);
+
+ LL_INFOS("GLTF_DEBUG") << "mJointList name: ";
+ const LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[root_joint];
+ LL_CONT << jointNode.mName << " index: " << root_joint << LL_ENDL;
+ return root_joint;
+}
+
bool LLGLTFLoader::parseMaterials()
{
if (!mGltfLoaded) return false;