From 6c6a95478ecd657c271354d93a6f98c90093bac5 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 19 Oct 2015 16:32:49 -0400 Subject: SL-234 WIP - remap skin weights to match included-joint logic --- indra/llmath/llvolume.cpp | 1 + indra/llmath/llvolume.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'indra/llmath') 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* mOctree; //whether or not face has been cache optimized -- cgit v1.3 From ba1e3e4f86f969932f9bdc077b716a7a647d6fb7 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 31 Mar 2016 10:53:26 -0400 Subject: SL-352 - another case where legacy content revealed a bug in weight remapping. --- indra/llmath/llvolume.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 206330fd53..725e50ee2b 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4594,6 +4594,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) mTexCoords(NULL), mIndices(NULL), mWeights(NULL), + mWeightsRemapped(FALSE), mOctree(NULL) { mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); @@ -4665,6 +4666,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) ll_aligned_free_16(mWeights); mWeights = NULL; } + mWeightsRemapped = src.mWeightsRemapped; } if (mNumIndices) -- cgit v1.3 From b138ca8aeec421f6e5b1412e7c7fbcefd87570d0 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 6 Apr 2016 16:12:39 -0400 Subject: SL-366 - more cases where skinned weights can go awry, and a bunch more asserts to verify. --- indra/llmath/llvolume.cpp | 10 ++++++---- indra/llprimitive/llmodel.cpp | 3 +-- indra/newview/llfloatermodelpreview.cpp | 5 ++++- indra/newview/llskinningutil.cpp | 9 ++++++++- 4 files changed, 19 insertions(+), 8 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 725e50ee2b..e5b1cf536d 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2544,7 +2544,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) U16 influence = weights[idx++]; influence |= ((U16) weights[idx++] << 8); - F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f); + F32 w = llclamp((F32) influence / 65535.f, 0.001f, 0.999f); wght.mV[cur_influence] = w; joints[cur_influence] = joint; cur_influence++; @@ -2561,11 +2561,13 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW]; if (wsum <= 0.f) { - wght = LLVector4(0.99999f,0.f,0.f,0.f); + wght = LLVector4(0.999f,0.f,0.f,0.f); } - for (U32 k=0; k<4; k++) + for (U32 k=0; k0); // If this fails, we have a floating point precision error. + joints_with_weights[k] = f_combined; } face.mWeights[cur_vertex].loadua(joints_with_weights.mV); diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index adf392fa21..398f0997f3 100755 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1001,7 +1001,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BO LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos) { - //1. If a vertex has been weighted then we'll find it via pos and return it's weight list + //1. If a vertex has been weighted then we'll find it via pos and return its weight list weight_map::iterator iterPos = mSkinWeights.begin(); weight_map::iterator iterEnd = mSkinWeights.end(); @@ -1224,7 +1224,6 @@ bool LLModel::loadModel(std::istream& is) } return false; - } bool LLModel::isMaterialListSubset( LLModel* ref ) diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index ceb3566d95..cda704f47b 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -3317,14 +3317,17 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) LLVector3 pos(vf.mPositions[i].getF32ptr()); const LLModel::weight_list& weight_list = base_mdl->getJointInfluences(pos); + llassert(weight_list.size()>0 && weight_list.size() <= 4); // LLModel::loadModel() should guarantee this LLVector4 w(0,0,0,0); for (U32 i = 0; i < weight_list.size(); ++i) { - F32 wght = llmin(weight_list[i].mWeight, 0.999999f); + F32 wght = llclamp(weight_list[i].mWeight, 0.001f, 0.999f); F32 joint = (F32) weight_list[i].mJointIdx; w.mV[i] = joint + wght; + llassert(w.mV[i]-(S32)w.mV[i]>0.0f); // because weights are non-zero, and range of wt values + //should not cause floating point precision issues. } *(weights_strider++) = w; diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index fbe45c8ea6..732afdfa9a 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -291,12 +291,15 @@ void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, con { 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 0.0f); } } #endif @@ -310,7 +313,7 @@ void LLSkinningUtil::getPerVertexSkinMatrix( LLMatrix4a& final_mat, U32 max_joints) { - + bool valid_weights = true; final_mat.clear(); S32 idx[4]; @@ -336,6 +339,7 @@ void LLSkinningUtil::getPerVertexSkinMatrix( if (handle_bad_scale && scale <= 0.f) { wght = LLVector4(1.0f, 0.0f, 0.0f, 0.0f); + valid_weights = false; } else { @@ -353,5 +357,8 @@ void LLSkinningUtil::getPerVertexSkinMatrix( final_mat.add(src); } + // SL-366 - with weight validation/cleanup code, it should no longer be + // possible to hit the bad scale case. + llassert(valid_weights); } -- cgit v1.3 From bd09297b8ec465a52f294092998812745ec6c566 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 3 Jun 2016 08:08:41 -0400 Subject: SL-220 - handle case that a weighted vertex includes no skin weights --- indra/llmath/llvolume.cpp | 6 ++++-- indra/newview/llskinningutil.cpp | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 2918e2e272..ac6f77b5ab 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2563,11 +2563,13 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) { wght = LLVector4(0.999f,0.f,0.f,0.f); } - for (U32 k=0; k0); // If this fails, we have a floating point precision error. joints_with_weights[k] = f_combined; + // Any weights we added above should wind up non-zero and applied to a specific bone. + // A failure here would indicate a floating point precision error in the math. + llassert((k >= cur_influence) || (f_combined - S32(f_combined) > 0.0f)); } face.mWeights[cur_vertex].loadua(joints_with_weights.mV); diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index 732afdfa9a..b36bfc870f 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -262,6 +262,7 @@ void LLSkinningUtil::initSkinningMatrixPalette( // static void LLSkinningUtil::remapSkinWeights(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(); @@ -277,6 +278,7 @@ void LLSkinningUtil::remapSkinWeights(LLVector4a* weights, U32 num_vertices, con w[k] = remap[i] + f; } } + checkSkinWeights(weights, num_vertices, skin); } // static -- cgit v1.3 From c86ab13b6b44aafc4f5fae8388c7d3f55cc5b0bc Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 27 Jul 2016 20:33:04 +0300 Subject: MAINT-612 FIXED LOD switch distance calculation ignores z-axis scale --- indra/llmath/llvolume.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index d932eb53a0..567ad9a414 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2143,19 +2143,22 @@ BOOL LLVolume::generate() F32 profile_detail = mDetail; F32 path_detail = mDetail; - - U8 path_type = mParams.getPathParams().getCurveType(); - U8 profile_type = mParams.getProfileParams().getCurveType(); - - if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) - { //cylinders don't care about Z-Axis - mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); - } - else if (path_type == LL_PCODE_PATH_CIRCLE) - { - mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); + + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) + { + U8 path_type = mParams.getPathParams().getCurveType(); + U8 profile_type = mParams.getProfileParams().getCurveType(); + if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) + { + //cylinders don't care about Z-Axis + mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); + } + else if (path_type == LL_PCODE_PATH_CIRCLE) + { + mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); + } } - + BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); -- cgit v1.3 From 278825191bdbcc61d398d85c9377c4e921423dde Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 23 Aug 2016 15:08:14 -0400 Subject: TEST - non-SSE code path for matrix ops used in mesh skinning. --- indra/llmath/llmatrix4a.h | 16 +++++++++++++++- indra/newview/lldrawpoolavatar.cpp | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index d141298f69..72b61e2a74 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -121,7 +121,7 @@ public: res.add(z); } - inline void affineTransform(const LLVector4a& v, LLVector4a& res) + inline void affineTransformSSE(const LLVector4a& v, LLVector4a& res) { LLVector4a x,y,z; @@ -137,6 +137,20 @@ public: z.add(mMatrix[3]); res.setAdd(x,z); } + + inline void affineTransformNonSSE(const LLVector4a& v, LLVector4a& res) + { + F32 x = v[0] * mMatrix[0][0] + v[1] * mMatrix[1][0] + v[2] * mMatrix[2][0] + mMatrix[3][0]; + F32 y = v[0] * mMatrix[0][1] + v[1] * mMatrix[1][1] + v[2] * mMatrix[2][1] + mMatrix[3][1]; + F32 z = v[0] * mMatrix[0][2] + v[1] * mMatrix[1][2] + v[2] * mMatrix[2][2] + mMatrix[3][2]; + F32 w = 1.0f; + res.set(x,y,z,w); + } + + inline void affineTransform(const LLVector4a& v, LLVector4a& res) + { + affineTransformNonSSE(v,res); + } }; #endif diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 843cd9b249..e9524189ed 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1628,6 +1628,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; LLVector4a dst; bind_shape_matrix.affineTransform(v, t); -- cgit v1.3 From f9be47d6695a7aab4bdf273043bcc5129c934c27 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 23 Aug 2016 17:08:57 -0400 Subject: SL-274 - disabled test w/non-SSE matrix ops. MAINT-6672 - fixed Reset Skeleton, no longer crashes. --- indra/llappearance/llavatarappearance.cpp | 6 ++---- indra/llmath/llmatrix4a.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index f9745efb78..e09bf51b93 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -663,18 +663,16 @@ BOOL LLAvatarAppearance::allocateCharacterJoints( U32 num ) BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) { LL_DEBUGS("BVH") << "numBones " << info->mNumBones << " numCollisionVolumes " << info->mNumCollisionVolumes << LL_ENDL; - //------------------------------------------------------------------------- + mNextJointNum = 0; + // allocate joints - //------------------------------------------------------------------------- if (!allocateCharacterJoints(info->mNumBones)) { LL_ERRS() << "Can't allocate " << info->mNumBones << " joints" << LL_ENDL; return FALSE; } - //------------------------------------------------------------------------- // allocate volumes - //------------------------------------------------------------------------- if (info->mNumCollisionVolumes) { if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index 72b61e2a74..e11fa1bf72 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -149,7 +149,7 @@ public: inline void affineTransform(const LLVector4a& v, LLVector4a& res) { - affineTransformNonSSE(v,res); + affineTransformSSE(v,res); } }; -- cgit v1.3 From 8d6bb9ee4e9def306454e9ecda1980793dcf7ad5 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 28 Sep 2016 15:43:07 -0400 Subject: SL-451 - SSE-optimized matrix multiply, used in initSkinningMatrixPalette() --- indra/llcommon/llerror.cpp | 17 +++++++++++++++++ indra/llcommon/llerror.h | 3 +++ indra/llmath/llmatrix4a.h | 23 +++++++++++++++++++++++ indra/newview/llskinningutil.cpp | 14 +++++++++++--- indra/newview/llvovolume.cpp | 6 ++---- 5 files changed, 56 insertions(+), 7 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 5ed348e13c..16ae1f0604 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -1493,3 +1493,20 @@ namespace LLError } } +bool debugLoggingEnabled(const std::string& tag) +{ + const char* tags[] = {tag.c_str()}; + ::size_t tag_count = 1; + LLError::CallSite _site(LLError::LEVEL_DEBUG, __FILE__, __LINE__, + typeid(_LL_CLASS_TO_LOG), __FUNCTION__, false, tags, tag_count); + if (LL_UNLIKELY(_site.shouldLog())) + { + return true; + } + else + { + return false; + } +} + + diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 3beef65723..555a189b00 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -363,4 +363,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; #define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__) #define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__) +// Check at run-time whether logging is enabled, without generating output +bool debugLoggingEnabled(const std::string& tag); + #endif // LL_LLERROR_H diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index e11fa1bf72..216334752a 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -153,4 +153,27 @@ public: } }; +inline LLVector4a rowMul(const LLVector4a &row, const LLMatrix4a &mat) +{ + LLVector4a result; + result = _mm_mul_ps(_mm_shuffle_ps(row, row, _MM_SHUFFLE(0, 0, 0, 0)), mat.mMatrix[0]); + result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(row, row, _MM_SHUFFLE(1, 1, 1, 1)), mat.mMatrix[1])); + result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(row, row, _MM_SHUFFLE(2, 2, 2, 2)), mat.mMatrix[2])); + result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(row, row, _MM_SHUFFLE(3, 3, 3, 3)), mat.mMatrix[3])); + return result; +} + +inline void matMul(const LLMatrix4a &a, const LLMatrix4a &b, LLMatrix4a &res) +{ + LLVector4a row0 = rowMul(a.mMatrix[0], b); + LLVector4a row1 = rowMul(a.mMatrix[1], b); + LLVector4a row2 = rowMul(a.mMatrix[2], b); + LLVector4a row3 = rowMul(a.mMatrix[3], b); + + res.mMatrix[0] = row0; + res.mMatrix[1] = row1; + res.mMatrix[2] = row2; + res.mMatrix[3] = row3; +} + #endif diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index e1333b8352..3ad30dac69 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -243,8 +243,6 @@ void LLSkinningUtil::initSkinningMatrixPalette( const LLMeshSkinInfo* skin, LLVOAvatar *avatar) { - // 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 = NULL; @@ -260,13 +258,23 @@ void LLSkinningUtil::initSkinningMatrixPalette( { joint = avatar->getJoint(skin->mJointNums[j]); } - mat[j] = skin->mInvBindMatrix[j]; if (joint) { +#define MAT_USE_SSE +#ifdef MAT_USE_SSE + LLMatrix4a bind, world, res; + bind.loadu(skin->mInvBindMatrix[j]); + world.loadu(joint->getWorldMatrix()); + matMul(bind,world,res); + memcpy(mat[j].mMatrix,res.mMatrix,16*sizeof(float)); +#else + mat[j] = skin->mInvBindMatrix[j]; mat[j] *= joint->getWorldMatrix(); +#endif } else { + mat[j] = skin->mInvBindMatrix[j]; // This shouldn't happen - in mesh upload, skinned // rendering should be disabled unless all joints are // valid. In other cases of skinned rendering, invalid diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index fd77bc2985..f476a3641e 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4779,13 +4779,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (rigged && pAvatarVO) { pAvatarVO->addAttachmentOverridesForObject(vobj); -#if 0 - if (pAvatarVO->isSelf()) - { + if (debugLoggingEnabled("Avatar") && pAvatarVO->isSelf()) + { bool verbose = true; pAvatarVO->showAttachmentOverrides(verbose); } -#endif } //for each face -- cgit v1.3 From 8230a9937f3bded847dae6c33e01b44158a7f8ee Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 18 Oct 2016 16:05:35 -0400 Subject: MAINT-6841 - removed the joint remapping code, since it was designed to support a feature we no longer have. This also incidentally fixes any bugs caused by the joint remapping code. --- indra/llmath/llvolume.cpp | 3 - indra/llmath/llvolume.h | 4 - indra/llprimitive/llmodel.h | 1 - indra/newview/lldrawpoolavatar.cpp | 8 +- indra/newview/llskinningutil.cpp | 224 ++----------------------------------- indra/newview/llskinningutil.h | 6 +- indra/newview/llvoavatar.cpp | 1 - 7 files changed, 13 insertions(+), 234 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index ac6f77b5ab..d57fe81de4 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4572,7 +4572,6 @@ LLVolumeFace::LLVolumeFace() : mTexCoords(NULL), mIndices(NULL), mWeights(NULL), - mWeightsRemapped(FALSE), mOctree(NULL), mOptimized(FALSE) { @@ -4598,7 +4597,6 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) mTexCoords(NULL), mIndices(NULL), mWeights(NULL), - mWeightsRemapped(FALSE), mOctree(NULL) { mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); @@ -4670,7 +4668,6 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) ll_aligned_free_16(mWeights); mWeights = NULL; } - mWeightsRemapped = src.mWeightsRemapped; } if (mNumIndices) diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 33e1403a14..1da2d0c6b1 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -953,10 +953,6 @@ 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* mOctree; //whether or not face has been cache optimized diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 2034686529..365ba8a51c 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -52,7 +52,6 @@ public: mutable std::vector mJointNums; std::vector mInvBindMatrix; std::vector mAlternateBindMatrix; - std::vector mJointRemap; LLMatrix4 mBindShapeMatrix; float mPelvisOffset; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index e9524189ed..517c69305a 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1550,19 +1550,13 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( return; } // FIXME ugly const cast - LLSkinningUtil::remapSkinInfoJoints(avatar, const_cast(skin)); + LLSkinningUtil::scrubInvalidJoints(avatar, const_cast(skin)); LLPointer buffer = face->getVertexBuffer(); LLDrawable* drawable = face->getDrawable(); U32 data_mask = face->getRiggedVertexBufferDataMask(); - if (!vol_face.mWeightsRemapped) - { - LLSkinningUtil::remapSkinWeights(weight, vol_face.mNumVertices, skin); - vol_face.mWeightsRemapped = TRUE; - } - if (buffer.isNull() || buffer->getTypeMask() != data_mask || buffer->getNumVerts() != vol_face.mNumVertices || 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& names, U32& result) -{ - std::vector::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& 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; jgetJoint(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& 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 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 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 new_joint_names; - std::vector new_joint_nums; - std::vector new_inv_bind_matrix; - std::vector 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; jmJointRemap.size(); - if (skin->mJointRemap.size()>0) - { - // Check the weights are consistent with the current remap. - for (U32 j=0; j=0); - llassert(i 0.0f); + llassert(i>=0); + llassert(i 0.0f); } #endif } diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h index 9a28100dc3..6a6091114c 100644 --- a/indra/newview/llskinningutil.h +++ b/indra/newview/llskinningutil.h @@ -37,14 +37,10 @@ public: static void initClass(); static U32 getMaxJointCount(); static U32 getMeshJointCount(const LLMeshSkinInfo *skin); - static void remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); + 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 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); - - // This is initialized from gSavedSettings at startup and then left alone. - static bool sIncludeEnhancedSkeleton; }; #endif diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 1ff4c1f681..46c367b4e6 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -6001,7 +6001,6 @@ void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) attachment->setIsHUDAttachment(info->mIsHUDAttachment); // attachment can potentially be animated, needs a number. attachment->setJointNum(mNumBones + mNumCollisionVolumes + attachmentID - 1); - LL_WARNS() << "Initialized attachment" << attachment->getName() << " joint_num " << attachment->getJointNum() << LL_ENDL; if (newly_created) { -- cgit v1.3 From 93db7eacbd1e46c78f8f5d0071578b9bed3202ac Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 30 Nov 2016 14:03:54 -0500 Subject: SL-540 - fix for regression in handling of out-of-range joint indices in skin weights --- indra/llmath/llvolume.cpp | 3 +++ indra/llmath/llvolume.h | 2 ++ indra/newview/lldrawpoolavatar.cpp | 14 ++++++++++---- indra/newview/llskinningutil.cpp | 19 +++++++++++++++++++ indra/newview/llskinningutil.h | 1 + 5 files changed, 35 insertions(+), 4 deletions(-) (limited to 'indra/llmath') 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* 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