diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1b163ee4c..5171dcf87 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -2065,14 +2065,14 @@ bool LLVertexBuffer::getWeightStrider(LLStrider& strider, S32 index, S32 co return VertexBufferStrider::get(*this, strider, index, count, map_range); } -bool LLVertexBuffer::getWeight4Strider(LLStrider& strider, S32 index, S32 count, bool map_range) +bool LLVertexBuffer::getWeight4Strider(LLStrider& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider::get(*this, strider, index, count, map_range); + return VertexBufferStrider::get(*this, strider, index, count, map_range); } -bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, S32 index, S32 count, bool map_range) +bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider::get(*this, strider, index, count, map_range); + return VertexBufferStrider::get(*this, strider, index, count, map_range); } //---------------------------------------------------------------------------- diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index d33bc9ff4..77c753fc9 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -255,8 +255,8 @@ public: bool getColorStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getEmissiveStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getWeightStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); - bool getWeight4Strider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); - bool getClothWeightStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getWeight4Strider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getClothWeightStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); bool useVBOs() const; diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index 44bd9f5ed..aa445fd14 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -22,30 +22,34 @@ * $/LicenseInfo$ */ +#define FLT_MAX 3.402823466e+38 + ATTRIBUTE vec4 weight4; uniform mat3 matrixPalette[52]; uniform vec3 translationPalette[52]; uniform float maxWeight; + + mat4 getObjectSkinnedTransform() { int i; vec4 w = fract(weight4); vec4 index = floor(weight4); - + index = min(index, vec4(maxWeight)); index = max(index, vec4( 0.0)); - float scale = 1.0/(w.x+w.y+w.z+w.w); - w *= scale; - + float sum = (w.x+w.y+w.z+w.w); + int i1 = int(index.x); int i2 = int(index.y); int i3 = int(index.z); int i4 = int(index.w); - + + mat3 mat = matrixPalette[i1]*w.x; mat += matrixPalette[i2]*w.y; mat += matrixPalette[i3]*w.z; @@ -58,10 +62,10 @@ mat4 getObjectSkinnedTransform() mat4 ret; - ret[0] = vec4(mat[0], 0); - ret[1] = vec4(mat[1], 0); - ret[2] = vec4(mat[2], 0); - ret[3] = vec4(trans, 1.0); + ret[0] = vec4(mat[0].xyz, 0); + ret[1] = vec4(mat[1].xyz, 0); + ret[2] = vec4(mat[2].xyz, 0); + ret[3] = vec4(trans, scale); return ret; } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 42dcd4547..4597f6e9d 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -61,8 +61,6 @@ static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; static U32 sBufferUsage = GL_STREAM_DRAW_ARB; static U32 sShaderLevel = 0; -#define JOINT_COUNT 52 - LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; @@ -1550,93 +1548,8 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* } if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime()) - { //perform software vertex skinning for this face - LLStrider position; - LLStrider normal; - - bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - buffer->getVertexStrider(position); - - if (has_normal) - { - buffer->getNormalStrider(normal); - } - - LLVector4a* pos = (LLVector4a*) position.get(); - - LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; - - //build matrix palette - LLMatrix4a mp[JOINT_COUNT]; - LLMatrix4* mat = (LLMatrix4*) mp; - - U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); - - for (U32 j = 0; j < count; ++j) - { - LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); - if(!joint) - { - joint = avatar->getJoint("mRoot"); - } - if (joint) - { - mat[j] = skin->mInvBindMatrix[j]; - mat[j] *= joint->getWorldMatrix(); - } - } - - LLMatrix4a bind_shape_matrix; - bind_shape_matrix.loadu(skin->mBindShapeMatrix); - - for (U32 j = 0; j < (U32)buffer->getNumVerts(); ++j) - { - LLMatrix4a final_mat; - final_mat.clear(); - - S32 idx[4]; - - LLVector4 wght; - - F32 scale = 0.f; - for (U32 k = 0; k < 4; k++) - { - F32 w = weight[j][k]; - - idx[k] = llclamp((S32) floorf(w), 0, S32(count-1)); - wght[k] = w - floorf(w); - scale += wght[k]; - } - - wght *= 1.f/scale; - - for (U32 k = 0; k < 4; k++) - { - F32 w = wght[k]; - - LLMatrix4a src; - src.setMul(mp[idx[k]], w); - - final_mat.add(src); - } - - - 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; - } - } + { + avatar->updateSoftwareSkinnedVertices(skin, weight, vol_face, buffer); } } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 9569a9b1f..af06c4836 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -42,6 +42,7 @@ class LLMeshSkinInfo; class LLVolume; class LLVolumeFace; +const U32 JOINT_COUNT = 52; class LLDrawPoolAvatar : public LLFacePool { diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 15430989e..692724a38 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -452,7 +452,7 @@ U16 LLFace::getGeometryAvatar( LLStrider &normals, LLStrider &tex_coords, LLStrider &vertex_weights, - LLStrider &clothing_weights) + LLStrider &clothing_weights) { if (mVertexBuffer.notNull()) { @@ -1143,11 +1143,11 @@ void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf) if (vf.mWeights) { - LLStrider f_wght; + LLStrider f_wght; buff->getWeight4Strider(f_wght); for (U32 i = 0; i < (U32)vf.mNumVertices; ++i) { - (*f_wght++).set(vf.mWeights[i].getF32ptr()); + (*f_wght++) = vf.mWeights[i]; } } @@ -1253,7 +1253,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLStrider colors; LLStrider tangent; LLStrider indicesp; - LLStrider wght; + LLStrider wght; BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); @@ -2126,8 +2126,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); - F32* weights = (F32*) wght.get(); - LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); + for(S32 i=0;iflush(); diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 7cdb6272e..470375b04 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -183,7 +183,7 @@ public: LLStrider &normals, LLStrider &texCoords, LLStrider &vertex_weights, - LLStrider &clothing_weights); + LLStrider &clothing_weights); // For volumes, etc. U16 getGeometry(LLStrider &vertices, diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 16c33c6b5..4c2e68a6c 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -4692,7 +4692,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) LLStrider normal_strider; LLStrider tc_strider; LLStrider index_strider; - LLStrider weights_strider; + LLStrider weights_strider; vb->getVertexStrider(vertex_strider); vb->getIndexStrider(index_strider); @@ -4735,7 +4735,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) w.mV[i] = joint + wght; } - *(weights_strider++) = w; + (*(weights_strider++)).loadua(w.mV); } } @@ -5372,71 +5372,11 @@ BOOL LLModelPreview::render() for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) { LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; - const LLVolumeFace& face = model->getVolumeFace(i); - - LLStrider position; - buffer->getVertexStrider(position); - - LLStrider weight; + LLStrider weight; buffer->getWeight4Strider(weight); - //quick 'n dirty software vertex skinning - - //build matrix palette - - LLMatrix4 mat[64]; - for (U32 j = 0; j < model->mSkinInfo.mJointNames.size(); ++j) - { - LLJoint* joint = getPreviewAvatar()->getJoint(model->mSkinInfo.mJointNames[j]); - if (joint) - { - mat[j] = model->mSkinInfo.mInvBindMatrix[j]; - mat[j] *= joint->getWorldMatrix(); - } - } - - for (S32 j = 0; j < buffer->getNumVerts(); ++j) - { - LLMatrix4 final_mat; - final_mat.mMatrix[0][0] = final_mat.mMatrix[1][1] = final_mat.mMatrix[2][2] = final_mat.mMatrix[3][3] = 0.f; - - LLVector4 wght; - S32 idx[4]; - - F32 scale = 0.f; - for (U32 k = 0; k < 4; k++) - { - F32 w = weight[j].mV[k]; - - idx[k] = (S32) floorf(w); - wght.mV[k] = w - floorf(w); - scale += wght.mV[k]; - } - - wght *= 1.f/scale; - - for (U32 k = 0; k < 4; k++) - { - F32* src = (F32*) mat[idx[k]].mMatrix; - F32* dst = (F32*) final_mat.mMatrix; - - F32 w = wght.mV[k]; - - for (U32 l = 0; l < 16; l++) - { - dst[l] += src[l]*w; - } - } - - //VECTORIZE THIS - LLVector3 v(face.mPositions[j].getF32ptr()); - - v = v * model->mSkinInfo.mBindShapeMatrix; - v = v * final_mat; - - position[j] = v; - } + getPreviewAvatar()->updateSoftwareSkinnedVertices(&model->mSkinInfo, weight.get(), face, buffer); const std::string& binding = instance.mModel->mMaterialList[i]; const LLImportMaterial& material = instance.mMaterial[binding]; diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 1184cf73c..c3bdfe5f8 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -413,7 +413,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w LLStrider normalsp; LLStrider tex_coordsp; LLStrider vertex_weightsp; - LLStrider clothing_weightsp; + LLStrider clothing_weightsp; LLStrider indicesp; // Copy data into the faces from the polymesh data. diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3b15311e7..62b4a9a60 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -8743,6 +8743,100 @@ void LLVOAvatar::updateLODRiggedAttachments( void ) updateLOD(); rebuildRiggedAttachments(); } + +void LLVOAvatar::updateSoftwareSkinnedVertices(const LLMeshSkinInfo* skin, const LLVector4a* weight, const LLVolumeFace& vol_face, LLVertexBuffer *buffer) +{ + //perform software vertex skinning for this face + LLStrider position; + LLStrider normal; + + bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + buffer->getVertexStrider(position); + + if (has_normal) + { + buffer->getNormalStrider(normal); + } + + LLVector4a* pos = (LLVector4a*) position.get(); + + LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; + + //build matrix palette + LLMatrix4a mp[JOINT_COUNT]; + LLMatrix4* mat = (LLMatrix4*) mp; + + U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); + + llassert_always(count); + + for (U32 j = 0; j < count; ++j) + { + LLJoint* joint = getJoint(skin->mJointNames[j]); + if(!joint) + { + joint = getJoint("mRoot"); + } + if (joint) + { + mat[j] = skin->mInvBindMatrix[j]; + mat[j] *= joint->getWorldMatrix(); + } + } + + LLMatrix4a bind_shape_matrix; + bind_shape_matrix.loadu(skin->mBindShapeMatrix); + + for (U32 j = 0; j < (U32)buffer->getNumVerts(); ++j) + { + LLMatrix4a final_mat; + final_mat.clear(); + + S32 idx[4]; + + LLVector4 wght; + + F32 scale = 0.f; + for (U32 k = 0; k < 4; k++) + { + F32 w = weight[j][k]; + + idx[k] = (S32) floorf(w); + wght[k] = w - floorf(w); + scale += wght[k]; + } + + if(scale > 0.f) + wght *= 1.f/scale; + else + wght = LLVector4(F32_MAX,F32_MAX,F32_MAX,F32_MAX); + + for (U32 k = 0; k < 4; k++) + { + F32 w = wght[k]; + LLMatrix4a src; + src.setMul(mp[idx[k]], w); + + final_mat.add(src); + } + + 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; + } + } +} U32 LLVOAvatar::getPartitionType() const { // Avatars merely exist as drawables in the bridge partition diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 891fae7d9..7044c1e1c 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -74,6 +74,7 @@ class LLHUDEffectSpiral; class LLTexGlobalColor; class LLViewerJoint; struct LLAppearanceMessageContents; +class LLMeshSkinInfo; class SHClientTagMgr : public LLSingleton, public boost::signals2::trackable { @@ -176,6 +177,7 @@ public: /*virtual*/ BOOL updateLOD(); BOOL updateJointLODs(); void updateLODRiggedAttachments( void ); + void updateSoftwareSkinnedVertices(const LLMeshSkinInfo* skin, const LLVector4a* weight, const LLVolumeFace& vol_face, LLVertexBuffer *buffer); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. S32 totalTextureMemForUUIDS(std::set& ids); bool allTexturesCompletelyDownloaded(std::set& ids) const; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a94d9e856..2c7aa39aa 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3916,15 +3916,20 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons } //build matrix palette - static const size_t kMaxJoints = 64; - - LLMatrix4a mp[kMaxJoints]; + LLMatrix4a mp[JOINT_COUNT]; LLMatrix4* mat = (LLMatrix4*) mp; - - U32 maxJoints = llmin(skin->mJointNames.size(), kMaxJoints); - for (U32 j = 0; j < maxJoints; ++j) + + U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); + + llassert_always(count); + + for (U32 j = 0; j < count; ++j) { LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); + if(!joint) + { + joint = avatar->getJoint("mRoot"); + } if (joint) { mat[j] = skin->mInvBindMatrix[j]; @@ -3973,17 +3978,17 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons scale += wght[k]; } - wght *= 1.f/scale; + if(scale > 0.f) + wght *= 1.f/scale; + else + wght = LLVector4(F32_MAX,F32_MAX,F32_MAX,F32_MAX); for (U32 k = 0; k < 4; k++) { F32 w = wght[k]; - LLMatrix4a src; - // Ensure ref'd bone is in our clamped array of mats - llassert(idx[k] < kMaxJoints); - // clamp k to kMaxJoints to avoid reading garbage off stack in release - src.setMul(mp[idx[(k < kMaxJoints) ? k : 0]], w); + src.setMul(mp[idx[k]], w); + final_mat.add(src); }