diff options
-rwxr-xr-x | indra/llmath/llvolume.cpp | 1 | ||||
-rwxr-xr-x | indra/llmath/llvolume.h | 4 | ||||
-rwxr-xr-x | indra/newview/lldrawpoolavatar.cpp | 113 | ||||
-rwxr-xr-x | indra/newview/lldrawpoolavatar.h | 2 | ||||
-rwxr-xr-x | indra/newview/llvovolume.cpp | 1 |
5 files changed, 64 insertions, 57 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 8608e45a91..206330fd53 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4568,6 +4568,7 @@ LLVolumeFace::LLVolumeFace() : mTexCoords(NULL), mIndices(NULL), mWeights(NULL), + mWeightsRemapped(FALSE), mOctree(NULL), mOptimized(FALSE) { diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 1da2d0c6b1..33e1403a14 100755 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -953,6 +953,10 @@ public: // mWeights.size() should be empty or match mVertices.size() LLVector4a* mWeights; + // Whether or not the weights have been cleaned up and remapped + // based on currently supported joints. + mutable BOOL mWeightsRemapped; + LLOctreeNode<LLVolumeTriangle>* mOctree; //whether or not face has been cache optimized diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 987a15c72d..dff6cada9a 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1593,7 +1593,6 @@ U32 getValidJointIndex(const std::string& name, LLVOAvatar *avatar, std::vector< // Which joint will stand in for this joint? U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector<std::string>& joint_names) { -#if 1 bool include_enhanced = gSavedSettings.getBOOL("IncludeEnhancedSkeleton"); U32 j_proxy = getValidJointIndex(joint_names[joint_index], avatar, joint_names); LLJoint *joint = avatar->getJoint(joint_names[j_proxy]); @@ -1618,9 +1617,6 @@ U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector<std::str joint = parent; } return j_proxy; -#else - return 0; -#endif } // static @@ -1634,6 +1630,8 @@ U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector<std::str // 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. +// +// static void LLDrawPoolAvatar::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin) { // skip if already done. @@ -1693,9 +1691,9 @@ void LLDrawPoolAvatar::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* s LL_INFOS() << "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->mJointNames = new_joint_names; + skin->mInvBindMatrix = new_inv_bind_matrix; + skin->mAlternateBindMatrix = new_alternate_bind_matrix; skin->mJointRemap = j_remap; } @@ -1706,67 +1704,59 @@ void LLDrawPoolAvatar::initSkinningMatrixPalette( const LLMeshSkinInfo* skin, LLVOAvatar *avatar) { - // BENTO ugly const cast - remapSkinInfoJoints(avatar, const_cast<LLMeshSkinInfo*>(skin)); - // BENTO - switching to use Matrix4a and SSE might speed this up. // Note that we are mostly passing Matrix4a's to this routine anyway, just dubiously casted. for (U32 j = 0; j < count; ++j) { LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); -#if 1 // Don't need this stuff if we've already remapped/cleaned up above - if (!joint) + mat[j] = skin->mInvBindMatrix[j]; + mat[j] *= joint->getWorldMatrix(); + } +} + +// 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 LLDrawPoolAvatar::remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* 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->mJointNames.size(); + for (U32 j=0; j<num_vertices; j++) + { + F32 *w = weights[j].getF32ptr(); + + for (U32 k=0; k<4; ++k) { - joint = avatar->getJoint("mPelvis"); + S32 i = llfloor(w[k]); + F32 f = w[k]-i; + i = llclamp(i,0,max_joints-1); + w[k] = remap[i] + f; } - if (joint) + } +} + +// static +void LLDrawPoolAvatar::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) +{ + if (skin->mJointRemap.size()>0) + { + // Check the weights are consistent with the current remap. + const S32 max_joints = skin->mJointNames.size(); + for (U32 j=0; j<num_vertices; j++) { - if (!gSavedSettings.getBOOL("IncludeEnhancedSkeleton")) - { - // BENTO - test of simple push-to-base-ancestor - // complexity reduction scheme. Find the first - // ancestor that's not flagged as extended, or the - // last ancestor that's rigged in this mesh, whichever - // comes first. - U32 j_remap = 0; - while (1) - { - if (joint->getSupport()==LLJoint::SUPPORT_BASE) - break; - LLJoint *parent = joint->getParent(); - if (!parent) - break; - std::vector<std::string>::const_iterator find_it = - std::find(skin->mJointNames.begin(), skin->mJointNames.end(), parent->getName()); - if (find_it != skin->mJointNames.end()) - { - j_remap = find_it - skin->mJointNames.begin(); - } - else - { - break; - } - joint = parent; - } - mat[j] = skin->mInvBindMatrix[j_remap]; - } - else + F32 *w = weights[j].getF32ptr(); + + for (U32 k=0; k<4; ++k) { - mat[j] = skin->mInvBindMatrix[j]; + S32 i = llfloor(w[k]); + llassert(i>=0); + llassert(i<max_joints); } -#else - mat[j] = skin->mInvBindMatrix[j]; -#endif - mat[j] *= joint->getWorldMatrix(); - } } - // This handles a bogus weights case that has turned up in - // practice, without the overhead of zeroing every matrix. We are - // doing this here instead of in getPerVertexSkinMatrix so the fix - // will also work in the HW skinning case. - if (count < LL_MAX_JOINTS_PER_MESH_OBJECT) - { - mat[count].setIdentity(); } } @@ -1835,12 +1825,20 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( { return; } + // BENTO ugly const cast + remapSkinInfoJoints(avatar, const_cast<LLMeshSkinInfo*>(skin)); LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer(); LLDrawable* drawable = face->getDrawable(); U32 data_mask = face->getRiggedVertexBufferDataMask(); + if (!vol_face.mWeightsRemapped) + { + remapSkinWeights(weight, vol_face.mNumVertices, skin); + vol_face.mWeightsRemapped = TRUE; + } + if (buffer.isNull() || buffer->getTypeMask() != data_mask || buffer->getNumVerts() != vol_face.mNumVertices || @@ -1894,6 +1892,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; U32 count = getMeshJointCount(skin); initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); + checkSkinWeights(weight, buffer->getNumVerts(), skin); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 27d4c949fd..8d6e95ba1a 100755 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -138,6 +138,8 @@ public: static U32 getMeshJointCount(const LLMeshSkinInfo *skin); static void remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); + static void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); + static void remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* facep, diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index c09786b7c7..5d8558cb46 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4192,6 +4192,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons if ( weight ) { + LLDrawPoolAvatar::checkSkinWeights(weight, dst_face.mNumVertices, skin); LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); |