diff options
Diffstat (limited to 'indra/newview/llskinningutil.cpp')
-rw-r--r-- | indra/newview/llskinningutil.cpp | 224 |
1 files changed, 11 insertions, 213 deletions
diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index 3ad30dac69..c0589e33bb 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -32,97 +32,15 @@ #include "llviewercontrol.h" #include "llmeshrepository.h" -bool LLSkinningUtil::sIncludeEnhancedSkeleton = true; - -namespace { - -bool get_name_index(const std::string& name, std::vector<std::string>& names, U32& result) -{ - std::vector<std::string>::const_iterator find_it = - std::find(names.begin(), names.end(), name); - if (find_it != names.end()) - { - result = find_it - names.begin(); - return true; - } - else - { - return false; - } -} - -// Find a name table index that is also a valid joint on the -// avatar. Order of preference is: requested name, mPelvis, first -// valid match in names table. -U32 get_valid_joint_index(const std::string& name, LLVOAvatar *avatar, std::vector<std::string>& joint_names) -{ - U32 result; - if (avatar->getJoint(name) && get_name_index(name,joint_names,result)) - { - return result; - } - if (get_name_index("mPelvis",joint_names,result)) - { - return result; - } - for (U32 j=0; j<joint_names.size(); j++) - { - if (avatar->getJoint(joint_names[j])) - { - return j; - } - } - // Shouldn't ever get here, because of the name cleanup pass in remapSkinInfoJoints() - LL_ERRS() << "no valid joints in joint_names" << LL_ENDL; - return 0; -} - -// Which joint will stand in for this joint? -U32 get_proxy_joint_index(U32 joint_index, LLVOAvatar *avatar, std::vector<std::string>& joint_names) -{ - bool include_enhanced = LLSkinningUtil::sIncludeEnhancedSkeleton; - U32 j_proxy = get_valid_joint_index(joint_names[joint_index], avatar, joint_names); - LLJoint *joint = avatar->getJoint(joint_names[j_proxy]); - llassert(joint); - // Find the first ancestor that's not flagged as extended, or the - // last ancestor that's rigged in this mesh, whichever - // comes first. - while (1) - { - if (include_enhanced || - joint->getSupport()==LLJoint::SUPPORT_BASE) - break; - LLJoint *parent = joint->getParent(); - if (!parent) - break; - if (!get_name_index(parent->getName(), joint_names, j_proxy)) - { - break; - } - joint = parent; - } - return j_proxy; -} - -} - // static void LLSkinningUtil::initClass() { - sIncludeEnhancedSkeleton = gSavedSettings.getBOOL("IncludeEnhancedSkeleton"); } // static U32 LLSkinningUtil::getMaxJointCount() { U32 result = LL_MAX_JOINTS_PER_MESH_OBJECT; - if (!sIncludeEnhancedSkeleton) - { - // Currently the remap logic does not guarantee joint count <= 52; - // if one of the base ancestors is not rigged in a given mesh, an extended - // joint can still be included. - result = llmin(result,(U32)52); - } return result; } @@ -133,33 +51,8 @@ U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin) } // static - -// Destructively remap the joints in skin info based on what joints -// are known in the avatar, and which are currently supported. This -// will also populate mJointRemap[] in the skin, which can be used to -// make the corresponding changes to the integer part of vertex -// weights. -// -// This will throw away joint info for any joints that are not known -// in the avatar, or not currently flagged to support based on the -// debug setting for IncludeEnhancedSkeleton. -// - -// BENTO maybe this really only makes sense for new leaf joints? New spine -// joints may need different logic. - -// static -void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin) +void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin) { - // skip if already done. - if (!skin->mJointRemap.empty()) - { - return; - } - - U32 max_joints = getMeshJointCount(skin); - - // Compute the remap for (U32 j = 0; j < skin->mJointNames.size(); ++j) { // Fix invalid names to "mPelvis". Currently meshes with @@ -170,70 +63,6 @@ void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* ski skin->mJointNames[j] = "mPelvis"; } } - std::vector<U32> j_proxy(skin->mJointNames.size()); - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - U32 j_rep = get_proxy_joint_index(j, avatar, skin->mJointNames); - j_proxy[j] = j_rep; - } - S32 top = 0; - std::vector<U32> j_remap(skin->mJointNames.size()); - // Fill in j_remap for all joints that will be kept. - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - if (j_proxy[j] == j) - { - // Joint will be included - j_remap[j] = top; - if (top < max_joints-1) - { - top++; - } - } - } - // Then use j_proxy to fill in j_remap for the joints that will be discarded - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - if (j_proxy[j] != j) - { - j_remap[j] = j_remap[j_proxy[j]]; - } - } - - - // Apply the remap to mJointNames, mInvBindMatrix, and mAlternateBindMatrix - std::vector<std::string> new_joint_names; - std::vector<S32> new_joint_nums; - std::vector<LLMatrix4> new_inv_bind_matrix; - std::vector<LLMatrix4> new_alternate_bind_matrix; - - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - if (j_proxy[j] == j && new_joint_names.size() < max_joints) - { - new_joint_names.push_back(skin->mJointNames[j]); - new_joint_nums.push_back(-1); - new_inv_bind_matrix.push_back(skin->mInvBindMatrix[j]); - if (!skin->mAlternateBindMatrix.empty()) - { - new_alternate_bind_matrix.push_back(skin->mAlternateBindMatrix[j]); - } - } - } - llassert(new_joint_names.size() <= max_joints); - - for (U32 j = 0; j < skin->mJointNames.size(); ++j) - { - if (skin->mJointNames[j] != new_joint_names[j_remap[j]]) - { - LL_DEBUGS("Avatar") << "Starting joint[" << j << "] = " << skin->mJointNames[j] << " j_remap " << j_remap[j] << " ==> " << new_joint_names[j_remap[j]] << LL_ENDL; - } - } - - skin->mJointNames = new_joint_names; - skin->mInvBindMatrix = new_inv_bind_matrix; - skin->mAlternateBindMatrix = new_alternate_bind_matrix; - skin->mJointRemap = j_remap; } // static @@ -278,61 +107,30 @@ void LLSkinningUtil::initSkinningMatrixPalette( // This shouldn't happen - in mesh upload, skinned // rendering should be disabled unless all joints are // valid. In other cases of skinned rendering, invalid - // joints should already have been removed during remap. + // joints should already have been removed during scrubInvalidJoints(). LL_WARNS_ONCE("Avatar") << "Rigged to invalid joint name " << skin->mJointNames[j] << LL_ENDL; } } } -// Transform the weights based on the remap info stored in skin. Note -// that this is destructive and non-idempotent, so we need to keep -// track of whether we've done it already. If the desired remapping -// changes, the viewer must be restarted. -// // static -void LLSkinningUtil::remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) +void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) { - checkSkinWeights(weights, num_vertices, skin); - llassert(skin->mJointRemap.size()>0); // Must call remapSkinInfoJoints() first, which this checks for. - const U32* remap = &skin->mJointRemap[0]; - const S32 max_joints = skin->mJointRemap.size(); +#ifndef LL_RELEASE_FOR_DOWNLOAD + const S32 max_joints = skin->mJointNames.size(); for (U32 j=0; j<num_vertices; j++) { F32 *w = weights[j].getF32ptr(); - + + F32 wsum = 0.0; for (U32 k=0; k<4; ++k) { S32 i = llfloor(w[k]); - F32 f = w[k]-i; - i = llclamp(i,0,max_joints-1); - w[k] = remap[i] + f; - } - } - checkSkinWeights(weights, num_vertices, skin); -} - -// static -void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) -{ -#ifndef LL_RELEASE_FOR_DOWNLOAD - const S32 max_joints = skin->mJointRemap.size(); - if (skin->mJointRemap.size()>0) - { - // Check the weights are consistent with the current remap. - for (U32 j=0; j<num_vertices; j++) - { - F32 *w = weights[j].getF32ptr(); - - F32 wsum = 0.0; - for (U32 k=0; k<4; ++k) - { - S32 i = llfloor(w[k]); - llassert(i>=0); - llassert(i<max_joints); - wsum += w[k]-i; - } - llassert(wsum > 0.0f); + llassert(i>=0); + llassert(i<max_joints); + wsum += w[k]-i; } + llassert(wsum > 0.0f); } #endif } |