SL-227 WIP - initial pass at consolidating skinning code. Less duplication of functionality, still needs more cleanup.

master
Brad Payne (Vir Linden) 2015-09-24 11:35:19 -04:00
parent 7f19cb367e
commit 2da22ad9fc
5 changed files with 139 additions and 169 deletions

View File

@ -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);

View File

@ -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];
{
// 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);
U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT);
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)
{

View File

@ -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,

View File

@ -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)
{
LLMatrix4a final_mata;
LLDrawPoolAvatar::getPerVertexSkinMatrix(weight[j].mV, (LLMatrix4a*)mat, true, final_mata);
// BENTO GROSS KLUDGERY
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;
}
}
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();

View File

@ -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;