diff options
| author | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2016-11-30 14:03:54 -0500 | 
|---|---|---|
| committer | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2016-11-30 14:03:54 -0500 | 
| commit | 93db7eacbd1e46c78f8f5d0071578b9bed3202ac (patch) | |
| tree | e0394c9a47876759aafc92461d3226b0184340e1 | |
| parent | 4c2144e1153fb71544140bb51630b13e17ead6d3 (diff) | |
SL-540 - fix for regression in handling of out-of-range joint indices in skin weights
| -rw-r--r-- | indra/llmath/llvolume.cpp | 3 | ||||
| -rw-r--r-- | indra/llmath/llvolume.h | 2 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolavatar.cpp | 14 | ||||
| -rw-r--r-- | indra/newview/llskinningutil.cpp | 19 | ||||
| -rw-r--r-- | indra/newview/llskinningutil.h | 1 | 
5 files changed, 35 insertions, 4 deletions
| diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index bd24a46e8d..6f0b4b2410 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4575,6 +4575,7 @@ LLVolumeFace::LLVolumeFace() :  	mTexCoords(NULL),  	mIndices(NULL),  	mWeights(NULL), +    mWeightsScrubbed(FALSE),  	mOctree(NULL),  	mOptimized(FALSE)  { @@ -4600,6 +4601,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)  	mTexCoords(NULL),  	mIndices(NULL),  	mWeights(NULL), +    mWeightsScrubbed(FALSE),  	mOctree(NULL)  {   	mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); @@ -4671,6 +4673,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  			ll_aligned_free_16(mWeights);  			mWeights = NULL;  		} +        mWeightsScrubbed = src.mWeightsScrubbed;  	}  	if (mNumIndices) diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 1da2d0c6b1..d66004cdad 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -953,6 +953,8 @@ public:  	// mWeights.size() should be empty or match mVertices.size()    	LLVector4a* mWeights; +    mutable BOOL mWeightsScrubbed; +      	LLOctreeNode<LLVolumeTriangle>* mOctree;  	//whether or not face has been cache optimized diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 10311044d2..499cf76bff 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1544,8 +1544,8 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(      LLVolume* volume,      const LLVolumeFace& vol_face)  { -	LLVector4a* weight = vol_face.mWeights; -	if (!weight) +	LLVector4a* weights = vol_face.mWeights; +	if (!weights)  	{  		return;  	} @@ -1556,6 +1556,12 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(  	LLDrawable* drawable = face->getDrawable();  	U32 data_mask = face->getRiggedVertexBufferDataMask(); + +    if (!vol_face.mWeightsScrubbed) +    { +        LLSkinningUtil::scrubSkinWeights(weights, vol_face.mNumVertices, skin); +        vol_face.mWeightsScrubbed = TRUE; +    }  	if (buffer.isNull() ||   		buffer->getTypeMask() != data_mask || @@ -1610,7 +1616,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(  		LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];          U32 count = LLSkinningUtil::getMeshJointCount(skin);          LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); -        LLSkinningUtil::checkSkinWeights(weight, buffer->getNumVerts(), skin); +        LLSkinningUtil::checkSkinWeights(weights, buffer->getNumVerts(), skin);  		LLMatrix4a bind_shape_matrix;  		bind_shape_matrix.loadu(skin->mBindShapeMatrix); @@ -1619,7 +1625,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(  		for (U32 j = 0; j < buffer->getNumVerts(); ++j)  		{  			LLMatrix4a final_mat; -            LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); +            LLSkinningUtil::getPerVertexSkinMatrix(weights[j].getF32ptr(), mat, false, final_mat, max_joints);  			LLVector4a& v = vol_face.mPositions[j]; diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index b2fd1744bc..cf09f6f978 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -64,6 +64,7 @@ void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin          // needed for handling of any legacy bad data.          if (!avatar->getJoint(skin->mJointNames[j]))          { +            LL_DEBUGS("Avatar") << "Mesh rigged to invalid joint" << skin->mJointNames[j] << LL_ENDL;              skin->mJointNames[j] = "mPelvis";          }      } @@ -140,6 +141,24 @@ void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, con  #endif  } +void LLSkinningUtil::scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) +{ +    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) +        { +            S32 i = llfloor(w[k]); +            F32 f = w[k]-i; +            i = llclamp(i,0,max_joints-1); +            w[k] = i + f; +        } +    } +	checkSkinWeights(weights, num_vertices, skin); +} +  // static  void LLSkinningUtil::getPerVertexSkinMatrix(      F32* weights, diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h index 6a6091114c..135b25d4d2 100644 --- a/indra/newview/llskinningutil.h +++ b/indra/newview/llskinningutil.h @@ -40,6 +40,7 @@ public:      static void scrubInvalidJoints(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 scrubSkinWeights(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);  }; | 
