From 08f6f5c697fce4ccbfba357ab9ce5af915dd0574 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 4 Jun 2025 20:57:10 +0300 Subject: #4214 Weights and Joints remap --- indra/llprimitive/llmodel.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'indra/llprimitive/llmodel.cpp') diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index c67dac2733..bc9f62b6c0 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -112,6 +112,93 @@ void LLModel::remapVolumeFaces() } } +void LLModel::remapSkinWeightsAndJoints() +{ + if (mSkinWeights.empty()) + { + return; + } + + mPosition.clear(); + + // Make a list of positions + std::set positions; + for (S32 i = 0; i < getNumVolumeFaces(); ++i) + { + for (S32 j = 0; j < mVolumeFaces[i].mNumVertices; ++j) + { + positions.emplace(mVolumeFaces[i].mPositions[j].getF32ptr()); + } + } + + // Build new list of weights and record used joints + weight_map replacement_weights; + std::vector joint_index_use_count; + size_t joint_count = mSkinInfo.mJointNames.size(); + joint_index_use_count.resize(joint_count, 0); + for (const LLVector3& pos : positions) + { + mPosition.push_back(pos); + auto found = mSkinWeights.find(pos); + if (found != mSkinWeights.end()) + { + replacement_weights[pos] = found->second; + + for (auto& weight : found->second) + { + if (joint_count > weight.mJointIdx) + { + joint_index_use_count[weight.mJointIdx]++; + } + } + } + } + + // go over joint data and remap joints + // prepare joint map + std::vector replacement_joint_names; + std::vector replacement_joint_nums; + LLMeshSkinInfo::matrix_list_t replacement_inv_bind; + LLMeshSkinInfo::matrix_list_t replacement_alt_bind; + std::vector index_map; + index_map.resize(joint_count); + S32 replacement_index = 0; + + for (S32 i = 0; i < joint_count; i++) + { + if (joint_index_use_count[i] > 0) + { + replacement_joint_names.push_back(mSkinInfo.mJointNames[i]); + replacement_joint_nums.push_back(mSkinInfo.mJointNums[i]); + replacement_inv_bind.push_back(mSkinInfo.mInvBindMatrix[i]); + replacement_alt_bind.push_back(mSkinInfo.mAlternateBindMatrix[i]); + index_map[i] = replacement_index++; + } + } + + // Apply new data + mSkinInfo.mJointNames.clear(); + mSkinInfo.mJointNames = replacement_joint_names; + mSkinInfo.mJointNums.clear(); + mSkinInfo.mJointNums = replacement_joint_nums; + mSkinInfo.mInvBindMatrix.clear(); + mSkinInfo.mInvBindMatrix = replacement_inv_bind; + mSkinInfo.mAlternateBindMatrix.clear(); + mSkinInfo.mAlternateBindMatrix = replacement_alt_bind; + + // remap weights + for (auto& weights : replacement_weights) + { + for (auto& weight : weights.second) + { + weight.mJointIdx = index_map[weight.mJointIdx]; + } + } + + mSkinWeights.clear(); + mSkinWeights = replacement_weights; +} + void LLModel::optimizeVolumeFaces() { for (S32 i = 0; i < getNumVolumeFaces(); ++i) -- cgit v1.2.3 From 98abff90a74536c9fa3a7c6d5078fc4b037c9c67 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Tue, 10 Jun 2025 23:14:25 +0300 Subject: #4248 Add safety checks to LLMeshSkinInfo::asLLSD() --- indra/llprimitive/llmodel.cpp | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'indra/llprimitive/llmodel.cpp') diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index bc9f62b6c0..6e45e9b1bf 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1804,13 +1804,21 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi { ret["joint_names"][i] = mJointNames[i]; - for (U32 j = 0; j < 4; j++) + if (i < mInvBindMatrix.size()) { - for (U32 k = 0; k < 4; k++) + for (U32 j = 0; j < 4; j++) { - ret["inverse_bind_matrix"][i][j*4+k] = mInvBindMatrix[i].mMatrix[j][k]; + for (U32 k = 0; k < 4; k++) + { + ret["inverse_bind_matrix"][i][j*4+k] = mInvBindMatrix[i].mMatrix[j][k]; + } } } + else + { + LL_WARNS("MESHSKININFO") << "Joint index " << i << " (" << mJointNames[i] << ") exceeds inverse bind matrix size " + << mInvBindMatrix.size() << LL_ENDL; + } } for (U32 i = 0; i < 4; i++) @@ -1821,17 +1829,25 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi } } - if ( include_joints && mAlternateBindMatrix.size() > 0 ) + if (include_joints && mAlternateBindMatrix.size() > 0) { for (U32 i = 0; i < mJointNames.size(); ++i) { - for (U32 j = 0; j < 4; j++) + if (i < mAlternateBindMatrix.size()) { - for (U32 k = 0; k < 4; k++) + for (U32 j = 0; j < 4; j++) { - ret["alt_inverse_bind_matrix"][i][j*4+k] = mAlternateBindMatrix[i].mMatrix[j][k]; + for (U32 k = 0; k < 4; k++) + { + ret["alt_inverse_bind_matrix"][i][j*4+k] = mAlternateBindMatrix[i].mMatrix[j][k]; + } } } + else + { + LL_WARNS("MESHSKININFO") << "Joint index " << i << " (" << mJointNames[i] << ") exceeds alternate bind matrix size " + << mAlternateBindMatrix.size() << LL_ENDL; + } } if (lock_scale_if_joint_position) -- cgit v1.2.3 From 5bc92322e974c6c1a0fcc7db0ebb6479ed486a0b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 18 Jun 2025 21:55:57 +0300 Subject: #4250 Crash uploading a dae model --- indra/llprimitive/llmodel.cpp | 48 +++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'indra/llprimitive/llmodel.cpp') diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 6e45e9b1bf..e47c0d8d07 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1804,21 +1804,23 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi { ret["joint_names"][i] = mJointNames[i]; - if (i < mInvBindMatrix.size()) - { - for (U32 j = 0; j < 4; j++) - { - for (U32 k = 0; k < 4; k++) - { - ret["inverse_bind_matrix"][i][j*4+k] = mInvBindMatrix[i].mMatrix[j][k]; - } - } - } - else + // For model to work at all there must be a matching bind matrix, + // so supply an indentity one if it isn't true + // Note: can build an actual bind matrix from joints + const LLMatrix4a& inv_bind = mInvBindMatrix.size() > i ? mInvBindMatrix[i] : LLMatrix4a::identity(); + if (i >= mInvBindMatrix.size()) { LL_WARNS("MESHSKININFO") << "Joint index " << i << " (" << mJointNames[i] << ") exceeds inverse bind matrix size " << mInvBindMatrix.size() << LL_ENDL; } + + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + ret["inverse_bind_matrix"][i][j * 4 + k] = inv_bind.mMatrix[j][k]; + } + } } for (U32 i = 0; i < 4; i++) @@ -1829,25 +1831,27 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi } } + // optional 'joint overrides' if (include_joints && mAlternateBindMatrix.size() > 0) { for (U32 i = 0; i < mJointNames.size(); ++i) { - if (i < mAlternateBindMatrix.size()) - { - for (U32 j = 0; j < 4; j++) - { - for (U32 k = 0; k < 4; k++) - { - ret["alt_inverse_bind_matrix"][i][j*4+k] = mAlternateBindMatrix[i].mMatrix[j][k]; - } - } - } - else + // If there is not enough to match mJointNames, + // either supply no alternate matrixes at all or supply + // replacements + const LLMatrix4a& alt_bind = mAlternateBindMatrix.size() > i ? mAlternateBindMatrix[i] : LLMatrix4a::identity(); + if (i >= mAlternateBindMatrix.size()) { LL_WARNS("MESHSKININFO") << "Joint index " << i << " (" << mJointNames[i] << ") exceeds alternate bind matrix size " << mAlternateBindMatrix.size() << LL_ENDL; } + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + ret["alt_inverse_bind_matrix"][i][j * 4 + k] = alt_bind.mMatrix[j][k]; + } + } } if (lock_scale_if_joint_position) -- cgit v1.2.3 From f5320302d4b81825b1037ca0074a65ad9eac14ac Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 19 Jun 2025 19:20:35 +0300 Subject: #4214 Revert and remake "weights remap" This reverts commits fe10a83f69bb26eb581e143fb99c1250c355938b and 08f6f5c697fce4ccbfba357ab9ce5af915dd0574.. --- indra/llprimitive/llmodel.cpp | 87 ------------------------------------------- 1 file changed, 87 deletions(-) (limited to 'indra/llprimitive/llmodel.cpp') diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index e47c0d8d07..3d31cfbb7f 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -112,93 +112,6 @@ void LLModel::remapVolumeFaces() } } -void LLModel::remapSkinWeightsAndJoints() -{ - if (mSkinWeights.empty()) - { - return; - } - - mPosition.clear(); - - // Make a list of positions - std::set positions; - for (S32 i = 0; i < getNumVolumeFaces(); ++i) - { - for (S32 j = 0; j < mVolumeFaces[i].mNumVertices; ++j) - { - positions.emplace(mVolumeFaces[i].mPositions[j].getF32ptr()); - } - } - - // Build new list of weights and record used joints - weight_map replacement_weights; - std::vector joint_index_use_count; - size_t joint_count = mSkinInfo.mJointNames.size(); - joint_index_use_count.resize(joint_count, 0); - for (const LLVector3& pos : positions) - { - mPosition.push_back(pos); - auto found = mSkinWeights.find(pos); - if (found != mSkinWeights.end()) - { - replacement_weights[pos] = found->second; - - for (auto& weight : found->second) - { - if (joint_count > weight.mJointIdx) - { - joint_index_use_count[weight.mJointIdx]++; - } - } - } - } - - // go over joint data and remap joints - // prepare joint map - std::vector replacement_joint_names; - std::vector replacement_joint_nums; - LLMeshSkinInfo::matrix_list_t replacement_inv_bind; - LLMeshSkinInfo::matrix_list_t replacement_alt_bind; - std::vector index_map; - index_map.resize(joint_count); - S32 replacement_index = 0; - - for (S32 i = 0; i < joint_count; i++) - { - if (joint_index_use_count[i] > 0) - { - replacement_joint_names.push_back(mSkinInfo.mJointNames[i]); - replacement_joint_nums.push_back(mSkinInfo.mJointNums[i]); - replacement_inv_bind.push_back(mSkinInfo.mInvBindMatrix[i]); - replacement_alt_bind.push_back(mSkinInfo.mAlternateBindMatrix[i]); - index_map[i] = replacement_index++; - } - } - - // Apply new data - mSkinInfo.mJointNames.clear(); - mSkinInfo.mJointNames = replacement_joint_names; - mSkinInfo.mJointNums.clear(); - mSkinInfo.mJointNums = replacement_joint_nums; - mSkinInfo.mInvBindMatrix.clear(); - mSkinInfo.mInvBindMatrix = replacement_inv_bind; - mSkinInfo.mAlternateBindMatrix.clear(); - mSkinInfo.mAlternateBindMatrix = replacement_alt_bind; - - // remap weights - for (auto& weights : replacement_weights) - { - for (auto& weight : weights.second) - { - weight.mJointIdx = index_map[weight.mJointIdx]; - } - } - - mSkinWeights.clear(); - mSkinWeights = replacement_weights; -} - void LLModel::optimizeVolumeFaces() { for (S32 i = 0; i < getNumVolumeFaces(); ++i) -- cgit v1.2.3