#4214 Revert and remake "weights remap"
This reverts commits fe10a83f69
and 08f6f5c697fce4ccbfba357ab9ce5af915dd0574..
master
parent
5bc92322e9
commit
f5320302d4
|
|
@ -112,93 +112,6 @@ void LLModel::remapVolumeFaces()
|
|||
}
|
||||
}
|
||||
|
||||
void LLModel::remapSkinWeightsAndJoints()
|
||||
{
|
||||
if (mSkinWeights.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mPosition.clear();
|
||||
|
||||
// Make a list of positions
|
||||
std::set<LLVector3> 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<S32> 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<std::string> replacement_joint_names;
|
||||
std::vector<S32> replacement_joint_nums;
|
||||
LLMeshSkinInfo::matrix_list_t replacement_inv_bind;
|
||||
LLMeshSkinInfo::matrix_list_t replacement_alt_bind;
|
||||
std::vector<S32> 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)
|
||||
|
|
|
|||
|
|
@ -205,7 +205,6 @@ public:
|
|||
void normalizeVolumeFacesAndWeights();
|
||||
void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
|
||||
void remapVolumeFaces();
|
||||
void remapSkinWeightsAndJoints();
|
||||
void optimizeVolumeFaces();
|
||||
void offsetMesh( const LLVector3& pivotPoint );
|
||||
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) const;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -207,6 +207,9 @@ protected:
|
|||
bind_matrices_t mInverseBindMatrices;
|
||||
bind_matrices_t mAlternateBindMatrices;
|
||||
|
||||
// per skin joint count, needs to be tracked for the sake of limits check.
|
||||
std::vector<S32> mValidJointsCount;
|
||||
|
||||
private:
|
||||
bool parseMeshes();
|
||||
void uploadMeshes();
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@
|
|||
<string name="UnsupportedExtension">Unable to load model, unsupported extension: [EXT]</string>
|
||||
<string name="TooManyMeshParts">Model contains [PART_COUNT] mesh parts. Maximum allowed: [LIMIT]</string>
|
||||
<string name="FailedToCreateTempFile">Failed to create temporary file for embedded texture [TEXTURE_INDEX]: [TEMP_FILE]</string>
|
||||
<string name="SkinJointsOverLimit">Skin [SKIN_INDEX] defines [JOINT_COUNT] compatible joints, maximum is: [MAX]. Unused joints will be stripped on per model basis.</string>
|
||||
<string name="ModelTooManyJoint">Model [MODEL_NAME] uses [JOINT_COUNT], maximum: [MAX], upload might fail</string>
|
||||
|
||||
<panel
|
||||
follows="top|left"
|
||||
|
|
|
|||
Loading…
Reference in New Issue