diff options
author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2025-05-15 18:28:25 +0300 |
---|---|---|
committer | Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> | 2025-05-19 20:40:19 +0300 |
commit | 875a4180803aa6903bb13263a63e02b38552b742 (patch) | |
tree | d46ff70dc636f4385de54bf8929dc15851a577fa | |
parent | fdeef47611e7496ff5d5fb8f37e3b1f5240a8b14 (diff) |
#4080 Import GLTF skin data
-rw-r--r-- | indra/llprimitive/llmodelloader.cpp | 2 | ||||
-rw-r--r-- | indra/newview/gltf/llgltfloader.cpp | 85 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_model_preview.xml | 1 |
3 files changed, 82 insertions, 6 deletions
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index 7facd53a72..8f86b90b69 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -150,6 +150,8 @@ void LLModelLoader::run() { mWarningsArray.clear(); doLoadModel(); + // todo: we are inside of a thread, push this into main thread worker, + // not into doOnIdleOneTime that laks tread safety doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this)); } diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp index 11c1b05ee5..8d109b610c 100644 --- a/indra/newview/gltf/llgltfloader.cpp +++ b/indra/newview/gltf/llgltfloader.cpp @@ -142,7 +142,7 @@ bool LLGLTFLoader::parseMeshes() // 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) + for (auto& skin : mGLTFAsset.mSkins) { populateJointFromSkin(skin); } @@ -164,7 +164,7 @@ bool LLGLTFLoader::parseMeshes() coord_system_rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); // Gather bounds from all meshes - for (auto node : mGLTFAsset.mNodes) + for (auto &node : mGLTFAsset.mNodes) { auto meshidx = node.mMesh; if (meshidx >= 0 && meshidx < mGLTFAsset.mMeshes.size()) @@ -238,7 +238,7 @@ bool LLGLTFLoader::parseMeshes() } // Second pass: Process each node with the global scale and offset - for (auto node : mGLTFAsset.mNodes) + for (auto &node : mGLTFAsset.mNodes) { LLMatrix4 transformation; material_map mats; @@ -281,7 +281,7 @@ bool LLGLTFLoader::parseMeshes() transformation = mesh_scale; if (transformation.determinant() < 0) { // negative scales are not supported - LL_INFOS() << "Negative scale detected, unsupported post-normalization transform. domInstance_geometry: " + LL_INFOS("GLTF") << "Negative scale detected, unsupported post-normalization transform. domInstance_geometry: " << pModel->mLabel << LL_ENDL; LLSD args; args["Message"] = "NegativeScaleNormTrans"; @@ -292,6 +292,60 @@ bool LLGLTFLoader::parseMeshes() mScene[transformation].push_back(LLModelInstance(pModel, pModel->mLabel, transformation, mats)); stretch_extents(pModel, transformation); mTransform = saved_transform; + + S32 skin_index = node.mSkin; + if (skin_index >= 0 && mGLTFAsset.mSkins.size() > skin_index) + { + LL::GLTF::Skin& gltf_skin = mGLTFAsset.mSkins[skin_index]; + LLMeshSkinInfo& skin_info = pModel->mSkinInfo; + + size_t jointCnt = gltf_skin.mJoints.size(); + if (gltf_skin.mInverseBindMatrices >= 0 && jointCnt != gltf_skin.mInverseBindMatricesData.size()) + { + LL_INFOS("GLTF") << "Bind matrices count mismatch joints count" << LL_ENDL; + LLSD args; + args["Message"] = "InvBindCountMismatch"; + mWarningsArray.append(args); + } + + for (size_t i = 0; i < jointCnt; ++i) + { + // 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()) + { + legal_name = mJointMap[legal_name]; + } + skin_info.mJointNames.push_back(legal_name); + skin_info.mJointNums.push_back(-1); + + if (i < gltf_skin.mInverseBindMatricesData.size()) + { + // Process bind matrix + LL::GLTF::mat4 gltf_mat = gltf_skin.mInverseBindMatricesData[i]; + LLMatrix4 gltf_transform(glm::value_ptr(gltf_mat)); + skin_info.mInvBindMatrix.push_back(LLMatrix4a(gltf_transform)); + + LL_DEBUGS("GLTF") << "mInvBindMatrix name: " << legal_name << " val: " << gltf_transform << LL_ENDL; + + // Translate based of mJointList + gltf_transform.setTranslation(mJointList[legal_name].getTranslation()); + skin_info.mAlternateBindMatrix.push_back(LLMatrix4a(gltf_transform)); + } + } + + // "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. + LLMatrix4 bind_shape; + bind_shape.setIdentity(); + skin_info.mBindShapeMatrix.loadu(bind_shape); + } } else { @@ -560,10 +614,29 @@ void LLGLTFLoader::populateJointFromSkin(const LL::GLTF::Skin& skin) for (auto joint : skin.mJoints) { auto jointNode = mGLTFAsset.mNodes[joint]; + + std::string legal_name(jointNode.mName); + if (mJointMap.find(legal_name) != mJointMap.end()) + { + legal_name = mJointMap[legal_name]; + } + else + { + LL_INFOS("GLTF") << "Rigged to unrecognized joint name : " + << legal_name << LL_ENDL; + LLSD args; + args["Message"] = "UnrecognizedJoint"; + args["[NAME]"] = legal_name; + mWarningsArray.append(args); + } + jointNode.makeMatrixValid(); - mJointList[jointNode.mName] = LLMatrix4(glm::value_ptr(jointNode.mMatrix)); - mJointsFromNode.push_front(jointNode.mName); + LLMatrix4 gltf_transform = LLMatrix4(glm::value_ptr(jointNode.mMatrix)); + mJointList[legal_name] = gltf_transform; + mJointsFromNode.push_front(legal_name); + + LL_DEBUGS("GLTF") << "mJointList name: " << legal_name << " val: " << gltf_transform << LL_ENDL; } } diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index 90223fcda8..99c348c236 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -45,6 +45,7 @@ <string name="UnrecognizedJoint">Rigged to unrecognized joint name [NAME]</string> <string name="UnknownJoints">Skinning disabled due to [COUNT] unknown joints</string> <string name="ModelLoaded">Model [MODEL_NAME] loaded</string> + <string name="InvBindCountMismatch">Bind matrices count mismatch joints count</string> <string name="IncompleteTC">Texture coordinates data is not complete.</string> <string name="PositionNaN">Found NaN while loading position data from DAE-Model, invalid model.</string> |