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.cpp79
1 files changed, 73 insertions, 6 deletions
diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp
index 50ce075d65..e495abfe75 100644
--- a/indra/newview/gltf/llgltfloader.cpp
+++ b/indra/newview/gltf/llgltfloader.cpp
@@ -225,8 +225,6 @@ void LLGLTFLoader::addModelToScene(
{
// remove unused/redundant vertices
model->remapVolumeFaces();
- // remove unused/redundant weights and joints
- model->remapSkinWeightsAndJoints();
mModelList.push_back(model);
@@ -821,21 +819,25 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
&& vertices[i].weights.x > 0.f)
{
weight_list.push_back(LLModel::JointWeight(vertices[i].joints.x, vertices[i].weights.x));
+ gltf_joint_index_use[vertices[i].joints.x]++;
}
if (gltf_joint_index_use[vertices[i].joints.y] >= 0
&& vertices[i].weights.y > 0.f)
{
weight_list.push_back(LLModel::JointWeight(vertices[i].joints.y, vertices[i].weights.y));
+ gltf_joint_index_use[vertices[i].joints.y]++;
}
if (gltf_joint_index_use[vertices[i].joints.z] >= 0
&& vertices[i].weights.z > 0.f)
{
weight_list.push_back(LLModel::JointWeight(vertices[i].joints.z, vertices[i].weights.z));
+ gltf_joint_index_use[vertices[i].joints.z]++;
}
if (gltf_joint_index_use[vertices[i].joints.w] >= 0
&& vertices[i].weights.w > 0.f)
{
weight_list.push_back(LLModel::JointWeight(vertices[i].joints.w, vertices[i].weights.w));
+ gltf_joint_index_use[vertices[i].joints.w]++;
}
std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater());
@@ -1022,14 +1024,23 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
{
LL::GLTF::Skin& gltf_skin = mGLTFAsset.mSkins[skinIdx];
LLMeshSkinInfo& skin_info = pModel->mSkinInfo;
+ S32 valid_joints_count = mValidJointsCount[skinIdx];
+ std::vector<S32> gltfindex_to_joitindex_map;
size_t jointCnt = gltf_skin.mJoints.size();
+ gltfindex_to_joitindex_map.resize(jointCnt);
S32 replacement_index = 0;
+ S32 stripped_valid_joints = 0;
for (size_t i = 0; i < jointCnt; ++i)
{
// Process joint name and idnex
S32 joint = gltf_skin.mJoints[i];
+ if (gltf_joint_index_use[i] < 0)
+ {
+ // unsupported (-1) joint, drop it
+ continue;
+ }
LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint];
std::string legal_name(jointNode.mName);
@@ -1037,10 +1048,28 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
{
legal_name = mJointMap[legal_name];
}
- // else thanks to gltf_joint_index_usage any illegal
- // joint should have zero uses.
- // Add them anyway to preserve order, remapSkinWeightsAndJoints
- // will sort them out later
+ else
+ {
+ llassert(false); // should have been stopped by gltf_joint_index_use[i] == -1
+ continue;
+ }
+
+ if (valid_joints_count > LL_MAX_JOINTS_PER_MESH_OBJECT
+ && gltf_joint_index_use[i] == 0
+ && legal_name != "mPelvis")
+ {
+ // Unused (0) joint
+ // It's perfectly valid to have more joints than is in use
+ // Ex: sandals that make your legs digitigrade despite not skining to
+ // knees or the like.
+ // But if model is over limid, drop extras sans pelvis.
+ // Keeping 'pelvis' is a workaround to keep preview whole.
+ // Todo: consider improving this, either take as much as possible or
+ // ensure common parents/roots are included
+ continue;
+ }
+
+ gltfindex_to_joitindex_map[i] = replacement_index++;
skin_info.mJointNames.push_back(legal_name);
skin_info.mJointNums.push_back(-1);
@@ -1050,6 +1079,28 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
skin_info.mAlternateBindMatrix.push_back(mAlternateBindMatrices[skinIdx][i]);
}
+
+ if (skin_info.mInvBindMatrix.size() > LL_MAX_JOINTS_PER_MESH_OBJECT)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Too many jonts in " << pModel->mLabel
+ << " Count: " << (S32)skin_info.mInvBindMatrix.size()
+ << " Limit:" << (S32)LL_MAX_JOINTS_PER_MESH_OBJECT << LL_ENDL;
+ LLSD args;
+ args["Message"] = "ModelTooManyJoint";
+ args["MODEL_NAME"] = pModel->mLabel;
+ args["JOINT_COUNT"] = (S32)skin_info.mInvBindMatrix.size();
+ args["MAX"] = (S32)LL_MAX_JOINTS_PER_MESH_OBJECT;
+ mWarningsArray.append(args);
+ }
+
+ // Remap indices for pModel->mSkinWeights
+ for (auto& weights : pModel->mSkinWeights)
+ {
+ for (auto& weight : weights.second)
+ {
+ weight.mJointIdx = gltfindex_to_joitindex_map[weight.mJointIdx];
+ }
+ }
}
return true;
@@ -1075,6 +1126,7 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
{
mInverseBindMatrices.resize(skin_idx + 1);
mAlternateBindMatrices.resize(skin_idx + 1);
+ mValidJointsCount.resize(skin_idx + 1, 0);
}
// fill up joints related data
@@ -1095,6 +1147,7 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
{
data.mName = mJointMap[jointNode.mName];
data.mIsValidViewerJoint = true;
+ mValidJointsCount[skin_idx]++;
}
else
{
@@ -1111,6 +1164,20 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
}
}
+ if (mValidJointsCount[skin_idx] > LL_MAX_JOINTS_PER_MESH_OBJECT)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Too many jonts, will strip unused joints"
+ << " Count: " << mValidJointsCount[skin_idx]
+ << " Limit:" << (S32)LL_MAX_JOINTS_PER_MESH_OBJECT << LL_ENDL;
+
+ LLSD args;
+ args["Message"] = "SkinJointsOverLimit";
+ args["SKIN_INDEX"] = (S32)skin_idx;
+ args["JOINT_COUNT"] = mValidJointsCount[skin_idx];
+ args["MAX"] = (S32)LL_MAX_JOINTS_PER_MESH_OBJECT;
+ mWarningsArray.append(args);
+ }
+
// Go over viewer joints and build overrides
glm::mat4 ident(1.0);
for (auto &viewer_data : mViewerJointData)