summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Payne (Vir Linden) <vir@lindenlab.com>2015-09-24 11:35:19 -0400
committerBrad Payne (Vir Linden) <vir@lindenlab.com>2015-09-24 11:35:19 -0400
commit2da22ad9fc92b255f9ec63dee11cf56342c2ac33 (patch)
treec338fe314e1aead6a07d269493e360ec8a34a657
parent7f19cb367e6182fff78d66738087601470faa9fa (diff)
SL-227 WIP - initial pass at consolidating skinning code. Less duplication of functionality, still needs more cleanup.
-rwxr-xr-xindra/llcharacter/lljoint.h2
-rwxr-xr-xindra/newview/lldrawpoolavatar.cpp191
-rwxr-xr-xindra/newview/lldrawpoolavatar.h2
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp59
-rwxr-xr-xindra/newview/llvovolume.cpp54
5 files changed, 139 insertions, 169 deletions
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index d9101c04ca..b3bf588d79 100755
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -42,6 +42,8 @@
const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15;
// BENTO JOINT COUNT LIMIT
const U32 LL_CHARACTER_MAX_JOINTS = 152; // must be divisible by 4!
+const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 152;
+
// FIXME BENTO - these should be higher than the joint_num of any
// other joint, to avoid conflicts in updateMotionsByType()
const U32 LL_HAND_JOINT_NUM = (LL_CHARACTER_MAX_JOINTS-1);
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index f1bfe4ecb2..7ccc779ba4 100755
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -55,9 +55,6 @@ static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK;
static U32 sBufferUsage = GL_STREAM_DRAW_ARB;
static U32 sShaderLevel = 0;
-// BENTO JOINT COUNT LIMIT
-#define JOINT_COUNT 152
-
LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL;
BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE;
BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE;
@@ -1463,7 +1460,13 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
}
-void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
+void LLDrawPoolAvatar::getRiggedGeometry(
+ LLFace* face,
+ LLPointer<LLVertexBuffer>& buffer,
+ U32 data_mask,
+ const LLMeshSkinInfo* skin,
+ LLVolume* volume,
+ const LLVolumeFace& vol_face)
{
face->setGeomIndex(0);
face->setIndicesIndex(0);
@@ -1472,7 +1475,8 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
face->setTextureIndex(255);
if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable())
- { //make a new buffer
+ {
+ // make a new buffer
if (sShaderLevel > 0)
{
buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
@@ -1484,7 +1488,8 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true);
}
else
- { //resize existing buffer
+ {
+ //resize existing buffer
buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices);
}
@@ -1498,9 +1503,9 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
m = m.inverse().transpose();
F32 mat3[] =
- { m.m[0], m.m[1], m.m[2],
- m.m[4], m.m[5], m.m[6],
- m.m[8], m.m[9], m.m[10] };
+ { m.m[0], m.m[1], m.m[2],
+ m.m[4], m.m[5], m.m[6],
+ m.m[8], m.m[9], m.m[10] };
LLMatrix3 mat_normal(mat3);
@@ -1527,14 +1532,98 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
{
face->clearState(LLFace::TEXTURE_ANIM);
}
-
-
face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true);
buffer->flush();
}
-void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
+// static
+void LLDrawPoolAvatar::initSkinningMatrixPalette(
+ LLMatrix4* mat,
+ S32 count,
+ const LLMeshSkinInfo* skin,
+ LLVOAvatar *avatar)
+{
+ for (U32 j = 0; j < count; ++j)
+ {
+ LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
+ if (!joint)
+ {
+ joint = avatar->getJoint("mPelvis");
+ }
+ if (joint)
+ {
+ mat[j] = skin->mInvBindMatrix[j];
+ mat[j] *= joint->getWorldMatrix();
+ }
+ }
+}
+
+// static
+void LLDrawPoolAvatar::getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat)
+{
+ final_mat.clear();
+
+ S32 idx[4];
+
+ LLVector4 wght;
+
+ F32 scale = 0.f;
+ for (U32 k = 0; k < 4; k++)
+ {
+ F32 w = weights[k];
+
+ idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)LL_MAX_JOINTS_PER_MESH_OBJECT-1);
+
+ wght[k] = w - floorf(w);
+ scale += wght[k];
+ }
+ if (handle_bad_scale && scale <= 0.f)
+ {
+ wght = LLVector4(1.0f, 0.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ // This is enforced in unpackVolumeFaces()
+ llassert(scale>0.f);
+ wght *= 1.f/scale;
+ }
+
+ for (U32 k = 0; k < 4; k++)
+ {
+ F32 w = wght[k];
+
+ LLMatrix4a src;
+ src.setMul(mat[idx[k]], w);
+
+ final_mat.add(src);
+ }
+}
+
+bool operator==(const LLMatrix4a& a, const LLMatrix4a& b)
+{
+ for (S32 i=0; i<4; i++)
+ for (S32 j=0; j<4; j++)
+ {
+ if (a.mMatrix[i][j] != b.mMatrix[i][j])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool operator!=(const LLMatrix4a& a, const LLMatrix4a& b)
+{
+ return !(a==b);
+}
+
+void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
+ LLVOAvatar* avatar,
+ LLFace* face,
+ const LLMeshSkinInfo* skin,
+ LLVolume* volume,
+ const LLVolumeFace& vol_face)
{
LLVector4a* weight = vol_face.mWeights;
if (!weight)
@@ -1597,23 +1686,10 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL;
//build matrix palette
- LLMatrix4a mp[JOINT_COUNT];
- LLMatrix4* mat = (LLMatrix4*) mp;
+ LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
+ U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT);
- 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("mPelvis");
- }
- if (joint)
- {
- mat[j] = skin->mInvBindMatrix[j];
- mat[j] *= joint->getWorldMatrix();
- }
- }
+ initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar);
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
@@ -1621,36 +1697,8 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
for (U32 j = 0; j < 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), (S32)0, (S32)JOINT_COUNT-1);
-
- wght[k] = w - floorf(w);
- scale += wght[k];
- }
- // This is enforced in unpackVolumeFaces()
- llassert(scale>0.f);
- 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);
- }
-
+ LLMatrix4a final_mat2;
+ getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat);
LLVector4a& v = vol_face.mPositions[j];
LLVector4a t;
@@ -1730,30 +1778,17 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
if (buff)
{
if (sShaderLevel > 0)
- { //upload matrix palette to shader
- LLMatrix4 mat[JOINT_COUNT];
-
- U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT);
+ {
+ // upload matrix palette to shader
+ LLMatrix4 mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
+ U32 count = llmin((U32) skin->mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT);
+ initSkinningMatrixPalette(mat, count, skin, avatar);
- for (U32 i = 0; i < count; ++i)
- {
- LLJoint* joint = avatar->getJoint(skin->mJointNames[i]);
- if (!joint)
- {
- joint = avatar->getJoint("mPelvis");
- }
- if (joint)
- {
- mat[i] = skin->mInvBindMatrix[i];
- mat[i] *= joint->getWorldMatrix();
- }
- }
-
stop_glerror();
- F32 mp[JOINT_COUNT*9];
+ F32 mp[LL_MAX_JOINTS_PER_MESH_OBJECT*9];
- F32 transp[JOINT_COUNT*3];
+ F32 transp[LL_MAX_JOINTS_PER_MESH_OBJECT*3];
for (U32 i = 0; i < count; ++i)
{
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index b9d2204052..af063ee74e 100755
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -134,6 +134,8 @@ public:
void endDeferredRiggedBump();
void getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face);
+ static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar);
+ static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat);
void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar,
LLFace* facep,
const LLMeshSkinInfo* skin,
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 851e2d2eb7..7e5d3a9f29 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -5026,6 +5026,7 @@ void LLModelPreview::addEmptyFace( LLModel* pTarget )
pTarget->setVolumeFaceData( faceCnt+1, pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices() );
}
+
//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
@@ -5571,50 +5572,19 @@ BOOL LLModelPreview::render()
//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();
- }
- }
+
+ LLMatrix4 mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
+ U32 count = llmin((U32) model->mSkinInfo.mJointNames.size(), (U32) LL_MAX_JOINTS_PER_MESH_OBJECT);
+ LLDrawPoolAvatar::initSkinningMatrixPalette(mat, count, &model->mSkinInfo, getPreviewAvatar());
for (U32 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];
+ LLMatrix4a final_mata;
+ LLDrawPoolAvatar::getPerVertexSkinMatrix(weight[j].mV, (LLMatrix4a*)mat, true, final_mata);
- 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;
- }
- }
+ // BENTO GROSS KLUDGERY
+ LLMatrix4 final_mat;
+ memcpy(&final_mat,&final_mata,sizeof(LLMatrix4a));
//VECTORIZE THIS
LLVector3 v(face.mPositions[j].getF32ptr());
@@ -5792,7 +5762,14 @@ void LLFloaterModelPreview::refresh()
}
//static
-void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata )
+void LLModelPreview::textureLoadedCallback(
+ BOOL success,
+ LLViewerFetchedTexture *src_vi,
+ LLImageRaw* src,
+ LLImageRaw* src_aux,
+ S32 discard_level,
+ BOOL final,
+ void* userdata )
{
LLModelPreview* preview = (LLModelPreview*) userdata;
preview->refresh();
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index eefe452c14..5e010a4712 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4164,27 +4164,11 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
//build matrix palette
// BENTO JOINT COUNT LIMIT
- static const size_t kMaxJoints = 152;
+ static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT;
- LLMatrix4a mp[kMaxJoints];
- LLMatrix4* mat = (LLMatrix4*) mp;
-
+ LLMatrix4a mat[kMaxJoints];
U32 maxJoints = llmin(skin->mJointNames.size(), kMaxJoints);
- for (U32 j = 0; j < maxJoints; ++j)
- {
- LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
- if (!joint)
- {
- // Fall back to a point inside the avatar if mesh is
- // rigged to an unknown joint.
- joint = avatar->getJoint("mPelvis");
- }
- if (joint)
- {
- mat[j] = skin->mInvBindMatrix[j];
- mat[j] *= joint->getWorldMatrix();
- }
- }
+ LLDrawPoolAvatar::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar);
for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
{
@@ -4208,37 +4192,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
for (U32 j = 0; j < dst_face.mNumVertices; ++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];
- }
- // This is enforced in unpackVolumeFaces()
- llassert(scale>0.f);
- wght *= 1.f / scale;
-
- for (U32 k = 0; k < 4; k++)
- {
- F32 w = wght[k];
-
- LLMatrix4a src;
- // Insure ref'd bone is in our clamped array of mats
- // clamp idx to maxJoints to avoid reading garbage off stack in release
- S32 index = llclamp((S32)idx[k],(S32)0,(S32)kMaxJoints-1);
- src.setMul(mp[index], w);
- final_mat.add(src);
- }
-
+ LLDrawPoolAvatar::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat);
LLVector4a& v = vol_face.mPositions[j];
LLVector4a t;