diff options
author | Graham Linden <graham@lindenlab.com> | 2019-08-06 14:41:55 -0700 |
---|---|---|
committer | Graham Linden <graham@lindenlab.com> | 2019-08-06 14:41:55 -0700 |
commit | 71af0a2a9e9f90d1e336f8a30f642bb5e19ef658 (patch) | |
tree | b730f130358e4d1c7bffefdddc183b242d75fe5a /indra | |
parent | 76128c4357bc36acd54575153516c6d337fe4263 (diff) |
Fix shutdown crash in teardown of joint heirarchy.
Ifdef'd code for potential skinning speed up to avoid lots of int<->float conversions (expensive and static for min space investment)
as updating rigged VBs shows up as a profiling bottleneck for Low rendering (where we actually use CPU skinning).
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llcharacter/lljoint.cpp | 17 | ||||
-rw-r--r-- | indra/llmath/llvolume.cpp | 39 | ||||
-rw-r--r-- | indra/llmath/llvolume.h | 4 | ||||
-rw-r--r-- | indra/newview/lldrawpoolavatar.cpp | 133 | ||||
-rw-r--r-- | indra/newview/lldrawpoolavatar.h | 2 | ||||
-rw-r--r-- | indra/newview/llskinningutil.cpp | 71 | ||||
-rw-r--r-- | indra/newview/llskinningutil.h | 29 | ||||
-rw-r--r-- | indra/newview/llvovolume.cpp | 48 |
8 files changed, 270 insertions, 73 deletions
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 36ecf8cb4b..a685df5925 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -303,16 +303,17 @@ void LLJoint::removeChild(LLJoint* joint) //-------------------------------------------------------------------- void LLJoint::removeAllChildren() { - for (joints_t::iterator iter = mChildren.begin(); - iter != mChildren.end();) + for (LLJoint* joint : mChildren) { - joints_t::iterator curiter = iter++; - LLJoint* joint = *curiter; - mChildren.erase(curiter); - joint->mXform.setParent(NULL); - joint->mParent = NULL; - joint->touch(); + if (joint) + { + joint->mXform.setParent(NULL); + joint->mParent = NULL; + joint->touch(); + //delete joint; + } } + mChildren.clear(); } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 9d0cf1e119..df867b332d 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2526,7 +2526,6 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) if (mdl[i].has("Weights")) { face.allocateWeights(num_verts); - face.allocateJointIndices(num_verts); LLSD::Binary weights = mdl[i]["Weights"]; @@ -2567,13 +2566,6 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) { wght = LLVector4(0.999f,0.f,0.f,0.f); } - if (face.mJointIndices) - { - for (U32 k=0; k<4; k++) - { - face.mJointIndices[cur_vertex * 4 + k] = llclamp((U8)joints[k], (U8)0, (U8)110); - } - } for (U32 k=0; k<4; k++) { F32 f_combined = (F32) joints[k] + wght[k]; @@ -4664,7 +4656,10 @@ LLVolumeFace::LLVolumeFace() : mTexCoords(NULL), mIndices(NULL), mWeights(NULL), +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + mJustWeights(NULL), mJointIndices(NULL), +#endif mWeightsScrubbed(FALSE), mOctree(NULL), mOptimized(FALSE) @@ -4691,7 +4686,10 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) mTexCoords(NULL), mIndices(NULL), mWeights(NULL), +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + mJustWeights(NULL), mJointIndices(NULL), +#endif mWeightsScrubbed(FALSE), mOctree(NULL) { @@ -4768,19 +4766,22 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) mWeightsScrubbed = FALSE; } + #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS if (src.mJointIndices) { llassert(!mJointIndices); // don't orphan an old alloc here accidentally allocateJointIndices(src.mNumVertices); LLVector4a::memcpyNonAliased16((F32*) mJointIndices, (F32*) src.mJointIndices, src.mNumVertices * sizeof(U8) * 4); } - else + else*/ { ll_aligned_free_16(mJointIndices); mJointIndices = NULL; } - } + #endif + } + if (mNumIndices) { S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; @@ -4823,8 +4824,13 @@ void LLVolumeFace::freeData() mTangents = NULL; ll_aligned_free_16(mWeights); mWeights = NULL; + +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS ll_aligned_free_16(mJointIndices); mJointIndices = NULL; + ll_aligned_free_16(mJustWeights); + mJustWeights = NULL; +#endif delete mOctree; mOctree = NULL; @@ -5479,13 +5485,17 @@ bool LLVolumeFace::cacheOptimize() // DO NOT free mNormals and mTexCoords as they are part of mPositions buffer ll_aligned_free_16(mWeights); ll_aligned_free_16(mTangents); +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS ll_aligned_free_16(mJointIndices); + ll_aligned_free_16(mJustWeights); + mJustWeights = NULL; + mJointIndices = NULL; // filled in later as necessary by skinning code for acceleration +#endif mPositions = pos; mNormals = norm; mTexCoords = tc; - mWeights = wght; - mJointIndices = NULL; // filled in later as necessary by skinning code for acceleration + mWeights = wght; mTangents = binorm; //std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks); @@ -6401,8 +6411,13 @@ void LLVolumeFace::allocateWeights(S32 num_verts) void LLVolumeFace::allocateJointIndices(S32 num_verts) { +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS ll_aligned_free_16(mJointIndices); + ll_aligned_free_16(mJustWeights); + mJointIndices = (U8*)ll_aligned_malloc_16(sizeof(U8) * 4 * num_verts); + mJustWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * num_verts); +#endif } void LLVolumeFace::resizeIndices(S32 num_indices) diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index ed2cd9cde0..a77e8c08c6 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -956,7 +956,11 @@ public: // format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight> // mWeights.size() should be empty or match mVertices.size() LLVector4a* mWeights; + +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + LLVector4a* mJustWeights; U8* mJointIndices; +#endif mutable BOOL mWeightsScrubbed; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 15a0595179..789a254389 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -38,6 +38,7 @@ #include "lldrawable.h" #include "lldrawpoolbump.h" #include "llface.h" +#include "llvolume.h" #include "llmeshrepository.h" #include "llsky.h" #include "llviewercamera.h" @@ -1833,15 +1834,13 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, - const LLVolumeFace& vol_face) + LLVolumeFace& vol_face) { LLVector4a* weights = vol_face.mWeights; if (!weights) { return; } - // FIXME ugly const cast - LLSkinningUtil::scrubInvalidJoints(avatar, const_cast<LLMeshSkinInfo*>(skin)); LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer(); LLDrawable* drawable = face->getDrawable(); @@ -1851,6 +1850,48 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( return; } + const U32 max_joints = LLSkinningUtil::getMaxJointCount(); + +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + #define CONDITION_WEIGHT(f) ((U8)llclamp((S32)f, (S32)0, (S32)max_joints-1)) + LLVector4a* just_weights = vol_face.mJustWeights; + // we need to calculate the separated indices and store just the matrix weights for this vol... + if (!vol_face.mJointIndices) + { + // not very consty after all... + vol_face.allocateJointIndices(vol_face.mNumVertices); + just_weights = vol_face.mJustWeights; + + U8* joint_indices_cursor = vol_face.mJointIndices; + for (int i = 0; i < vol_face.mNumVertices; i++) + { + F32* w = weights[i].getF32ptr(); + F32* w_ = just_weights[i].getF32ptr(); + + F32 w0 = floorf(w[0]); + F32 w1 = floorf(w[1]); + F32 w2 = floorf(w[2]); + F32 w3 = floorf(w[3]); + + joint_indices_cursor[0] = CONDITION_WEIGHT(w0); + joint_indices_cursor[1] = CONDITION_WEIGHT(w1); + joint_indices_cursor[2] = CONDITION_WEIGHT(w2); + joint_indices_cursor[3] = CONDITION_WEIGHT(w3); + + // remove joint portion of combined weight + w_[0] = w[0] - w0; + w_[1] = w[1] - w1; + w_[2] = w[2] - w2; + w_[3] = w[3] - w3; + + joint_indices_cursor += 4; + } + } +#endif + + // FIXME ugly const cast + LLSkinningUtil::scrubInvalidJoints(avatar, const_cast<LLMeshSkinInfo*>(skin)); + U32 data_mask = face->getRiggedVertexBufferDataMask(); if (!vol_face.mWeightsScrubbed) @@ -1927,29 +1968,67 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); - const U32 max_joints = LLSkinningUtil::getMaxJointCount(); - for (U32 j = 0; j < buffer->getNumVerts(); ++j) - { - LLMatrix4a final_mat; - LLSkinningUtil::getPerVertexSkinMatrix(weights[j].getF32ptr(), mat, false, final_mat, max_joints); - - LLVector4a& v = vol_face.mPositions[j]; - - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - - if (norm) - { - LLVector4a& n = vol_face.mNormals[j]; - bind_shape_matrix.rotate(n, t); - final_mat.rotate(t, dst); - dst.normalize3fast(); - norm[j] = dst; - } - } +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + U8* joint_indices_cursor = vol_face.mJointIndices; + // fast path with joint indices separate from weights + if (joint_indices_cursor) + { + LLMatrix4a src[4]; + for (U32 j = 0; j < buffer->getNumVerts(); ++j) + { + LLMatrix4a final_mat; + //LLMatrix4a final_mat_correct; + + F32* jw = just_weights[j].getF32ptr(); + + LLSkinningUtil::getPerVertexSkinMatrixWithIndices(jw, joint_indices_cursor, mat, final_mat, src); + + joint_indices_cursor += 4; + + LLVector4a& v = vol_face.mPositions[j]; + + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + + if (norm) + { + LLVector4a& n = vol_face.mNormals[j]; + bind_shape_matrix.rotate(n, t); + final_mat.rotate(t, dst); + dst.normalize3fast(); + norm[j] = dst; + } + } + } + // slow path with joint indices calculated from weights + else +#endif + { + for (U32 j = 0; j < buffer->getNumVerts(); ++j) + { + LLMatrix4a final_mat; + LLSkinningUtil::getPerVertexSkinMatrix(weights[j].getF32ptr(), mat, false, final_mat, max_joints); + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + + if (norm) + { + LLVector4a& n = vol_face.mNormals[j]; + bind_shape_matrix.rotate(n, t); + final_mat.rotate(t, dst); + //dst.normalize3fast(); + norm[j] = dst; + } + } + } } } @@ -2301,7 +2380,7 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) stop_glerror(); - const LLVolumeFace& vol_face = volume->getVolumeFace(te); + LLVolumeFace& vol_face = volume->getVolumeFace(te); updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); } } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index e8add0e1d8..cb09eb18e2 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -257,7 +257,7 @@ typedef enum LLFace* facep, const LLMeshSkinInfo* skin, LLVolume* volume, - const LLVolumeFace& vol_face); + LLVolumeFace& vol_face); void updateRiggedVertexBuffers(LLVOAvatar* avatar); void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false); diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index 0fa4c2b114..83b9c8971a 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -34,8 +34,12 @@ #include "llvolume.h" #include "llrigginginfo.h" +#define DEBUG_SKINNING LL_DEBUG +#define MAT_USE_SSE 1 + void dump_avatar_and_skin_state(const std::string& reason, LLVOAvatar *avatar, const LLMeshSkinInfo *skin) { +#if DEBUG_SKINNING static S32 dump_count = 0; const S32 max_dump = 10; @@ -81,16 +85,16 @@ void dump_avatar_and_skin_state(const std::string& reason, LLVOAvatar *avatar, c dump_count++; } +#endif } void LLSkinningUtil::initClass() { } -U32 LLSkinningUtil::getMaxJointCount() +S32 LLSkinningUtil::getMaxJointCount() { - U32 result = LL_MAX_JOINTS_PER_MESH_OBJECT; - return result; + return (S32)LL_MAX_JOINTS_PER_MESH_OBJECT; } U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin) @@ -120,6 +124,8 @@ void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin skin->mInvalidJointsScrubbed = true; } +#define MAT_USE_SSE 1 + void LLSkinningUtil::initSkinningMatrixPalette( LLMatrix4* mat, S32 count, @@ -130,9 +136,9 @@ void LLSkinningUtil::initSkinningMatrixPalette( for (U32 j = 0; j < count; ++j) { LLJoint *joint = avatar->getJoint(skin->mJointNums[j]); + llassert(joint); if (joint) { -#define MAT_USE_SSE #ifdef MAT_USE_SSE LLMatrix4a bind, world, res; bind.loadu(skin->mInvBindMatrix[j]); @@ -147,6 +153,7 @@ void LLSkinningUtil::initSkinningMatrixPalette( else { mat[j] = skin->mInvBindMatrix[j]; +#if DEBUG_SKINNING // This shouldn't happen - in mesh upload, skinned // rendering should be disabled unless all joints are // valid. In other cases of skinned rendering, invalid @@ -157,16 +164,15 @@ void LLSkinningUtil::initSkinningMatrixPalette( LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " avatar build state: isBuilt() " << avatar->isBuilt() << " mInitFlags " << avatar->mInitFlags << LL_ENDL; -#if 0 - dump_avatar_and_skin_state("initSkinningMatrixPalette joint not found", avatar, skin); #endif + dump_avatar_and_skin_state("initSkinningMatrixPalette joint not found", avatar, skin); } } } void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) { -#ifdef SHOW_ASSERT // same condition that controls llassert() +#if DEBUG_SKINNING const S32 max_joints = skin->mJointNames.size(); for (U32 j=0; j<num_vertices; j++) { @@ -265,6 +271,7 @@ void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar) { for (U32 j = 0; j < skin->mJointNames.size(); ++j) { + #if DEBUG_SKINNING LLJoint *joint = NULL; if (skin->mJointNums[j] == -1) { @@ -282,11 +289,16 @@ void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar) { LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " unable to find joint " << skin->mJointNames[j] << LL_ENDL; LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " avatar build state: isBuilt() " << avatar->isBuilt() << " mInitFlags " << avatar->mInitFlags << LL_ENDL; -#if 0 dump_avatar_and_skin_state("initJointNums joint not found", avatar, skin); -#endif + skin->mJointNums[j] = 0; } } + #else + LLJoint *joint = (skin->mJointNums[j] == -1) ? avatar->getJoint(skin->mJointNames[j]) : avatar->getJoint(skin->mJointNums[j]); + skin->mJointNums[j] = joint ? joint->getJointNum() : 0; + #endif + // insure we have *a* valid joint to reference + llassert(skin->mJointNums[j] >= 0); } skin->mJointNumsInitialized = true; } @@ -344,14 +356,17 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a // FIXME could precompute these matMuls. LLMatrix4a bind_shape; - bind_shape.loadu(skin->mBindShapeMatrix); LLMatrix4a inv_bind; - inv_bind.loadu(skin->mInvBindMatrix[joint_index]); LLMatrix4a mat; - matMul(bind_shape, inv_bind, mat); LLVector4a pos_joint_space; + + bind_shape.loadu(skin->mBindShapeMatrix); + inv_bind.loadu(skin->mInvBindMatrix[joint_index]); + matMul(bind_shape, inv_bind, mat); + mat.affineTransform(pos, pos_joint_space); pos_joint_space.mul(wght[k]); + LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents(); update_min_max(extents[0], extents[1], pos_joint_space); } @@ -366,6 +381,8 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a vol_face.mJointRiggingInfoTab.setNeedsUpdate(false); } } + +#if DEBUG_SKINNING if (vol_face.mJointRiggingInfoTab.size()!=0) { LL_DEBUGS("RigSpammish") << "we have rigging info for vf " << &vol_face @@ -376,10 +393,40 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a LL_DEBUGS("RigSpammish") << "no rigging info for vf " << &vol_face << " num_verts " << vol_face.mNumVertices << LL_ENDL; } +#endif } } +void LLSkinningUtil::updateRiggingInfo_(LLMeshSkinInfo* skin, LLVOAvatar *avatar, S32 num_verts, LLVector4a* weights, LLVector4a* positions, U8* joint_indices, LLJointRiggingInfoTab &rig_info_tab) +{ + LL_RECORD_BLOCK_TIME(FTM_FACE_RIGGING_INFO); + for (S32 i=0; i < num_verts; i++) + { + LLVector4a& pos = positions[i]; + LLVector4a& wght = weights[i]; + for (U32 k=0; k<4; ++k) + { + S32 joint_num = skin->mJointNums[joint_indices[k]]; + llassert(joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS); + { + rig_info_tab[joint_num].setIsRiggedTo(true); + LLMatrix4a bind_shape; + bind_shape.loadu(skin->mBindShapeMatrix); + LLMatrix4a inv_bind; + inv_bind.loadu(skin->mInvBindMatrix[joint_indices[k]]); + LLMatrix4a mat; + matMul(bind_shape, inv_bind, mat); + LLVector4a pos_joint_space; + mat.affineTransform(pos, pos_joint_space); + pos_joint_space.mul(wght[k]); + LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents(); + update_min_max(extents[0], extents[1], pos_joint_space); + } + } + } +} + // This is used for extracting rotation from a bind shape matrix that // already has scales baked in LLQuaternion LLSkinningUtil::getUnscaledQuaternion(const LLMatrix4& mat4) diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h index ccc501adc0..d39356451d 100644 --- a/indra/newview/llskinningutil.h +++ b/indra/newview/llskinningutil.h @@ -27,23 +27,48 @@ #ifndef LLSKINNINGUTIL_H #define LLSKINNINGUTIL_H +#include "v2math.h" +#include "v4math.h" +#include "llvector4a.h" +#include "llmatrix4a.h" + class LLVOAvatar; class LLMeshSkinInfo; -class LLMatrix4a; class LLVolumeFace; +class LLJointRiggingInfoTab; namespace LLSkinningUtil { void initClass(); - U32 getMaxJointCount(); + S32 getMaxJointCount(); U32 getMeshJointCount(const LLMeshSkinInfo *skin); void scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); + + LL_FORCE_INLINE void getPerVertexSkinMatrixWithIndices( + F32* weights, + U8* idx, + LLMatrix4a* mat, + LLMatrix4a& final_mat, + LLMatrix4a* src) + { + final_mat.clear(); + src[0].setMul(mat[idx[0]], weights[0]); + src[1].setMul(mat[idx[1]], weights[1]); + final_mat.add(src[0]); + final_mat.add(src[1]); + src[2].setMul(mat[idx[2]], weights[2]); + src[3].setMul(mat[idx[3]], weights[3]); + final_mat.add(src[2]); + final_mat.add(src[3]); + } + void initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar); void updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, LLVolumeFace& vol_face); + void updateRiggingInfo_(LLMeshSkinInfo* skin, LLVOAvatar *avatar, S32 num_verts, LLVector4a* weights, LLVector4a* positions, U8* joint_indices, LLJointRiggingInfoTab &rig_info_tab); LLQuaternion getUnscaledQuaternion(const LLMatrix4& mat4); }; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 02ef7612a7..706e2c6895 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4787,18 +4787,44 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons U32 max_joints = LLSkinningUtil::getMaxJointCount(); rigged_vert_count += dst_face.mNumVertices; rigged_face_count++; - for (U32 j = 0; j < dst_face.mNumVertices; ++j) - { - LLMatrix4a final_mat; - LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); + + #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + if (vol_face.mJointIndices) // fast path with preconditioned joint indices + { + LLMatrix4a src[4]; + U8* joint_indices_cursor = vol_face.mJointIndices; + LLVector4a* just_weights = vol_face.mJustWeights; + for (U32 j = 0; j < dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; + F32* w = just_weights[j].getF32ptr(); + LLSkinningUtil::getPerVertexSkinMatrixWithIndices(w, joint_indices_cursor, mat, final_mat, src); + joint_indices_cursor += 4; + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } + } + else + #endif + { + for (U32 j = 0; j < dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; + 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); - final_mat.affineTransform(t, dst); - pos[j] = dst; - } + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } + } //update bounding box // VFExtents change |