Fixed an annoying showstopper regarding rigged attachment vertex corruption. Rigged meshes have can have poor weighting, causing potential div-by-zero issues.
This commit is contained in:
@@ -2065,14 +2065,14 @@ bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 co
|
||||
return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range);
|
||||
}
|
||||
|
||||
bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
|
||||
bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
|
||||
{
|
||||
return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range);
|
||||
return VertexBufferStrider<LLVector4a,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range);
|
||||
}
|
||||
|
||||
bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
|
||||
bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
|
||||
{
|
||||
return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range);
|
||||
return VertexBufferStrider<LLVector4a,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -255,8 +255,8 @@ public:
|
||||
bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getWeight4Strider(LLStrider<LLVector4a>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getClothWeightStrider(LLStrider<LLVector4a>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
|
||||
|
||||
bool useVBOs() const;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<LLVector3> position;
|
||||
LLStrider<LLVector3> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ class LLMeshSkinInfo;
|
||||
class LLVolume;
|
||||
class LLVolumeFace;
|
||||
|
||||
const U32 JOINT_COUNT = 52;
|
||||
|
||||
class LLDrawPoolAvatar : public LLFacePool
|
||||
{
|
||||
|
||||
@@ -452,7 +452,7 @@ U16 LLFace::getGeometryAvatar(
|
||||
LLStrider<LLVector3> &normals,
|
||||
LLStrider<LLVector2> &tex_coords,
|
||||
LLStrider<F32> &vertex_weights,
|
||||
LLStrider<LLVector4> &clothing_weights)
|
||||
LLStrider<LLVector4a> &clothing_weights)
|
||||
{
|
||||
if (mVertexBuffer.notNull())
|
||||
{
|
||||
@@ -1143,11 +1143,11 @@ void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf)
|
||||
|
||||
if (vf.mWeights)
|
||||
{
|
||||
LLStrider<LLVector4> f_wght;
|
||||
LLStrider<LLVector4a> 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<LLColor4U> colors;
|
||||
LLStrider<LLVector3> tangent;
|
||||
LLStrider<U16> indicesp;
|
||||
LLStrider<LLVector4> wght;
|
||||
LLStrider<LLVector4a> 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;i<num_vertices;++i)
|
||||
{
|
||||
*(wght++) = vf.mWeights[i];
|
||||
}
|
||||
if (map_range)
|
||||
{
|
||||
mVertexBuffer->flush();
|
||||
|
||||
@@ -183,7 +183,7 @@ public:
|
||||
LLStrider<LLVector3> &normals,
|
||||
LLStrider<LLVector2> &texCoords,
|
||||
LLStrider<F32> &vertex_weights,
|
||||
LLStrider<LLVector4> &clothing_weights);
|
||||
LLStrider<LLVector4a> &clothing_weights);
|
||||
|
||||
// For volumes, etc.
|
||||
U16 getGeometry(LLStrider<LLVector3> &vertices,
|
||||
|
||||
@@ -4692,7 +4692,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
|
||||
LLStrider<LLVector3> normal_strider;
|
||||
LLStrider<LLVector2> tc_strider;
|
||||
LLStrider<U16> index_strider;
|
||||
LLStrider<LLVector4> weights_strider;
|
||||
LLStrider<LLVector4a> 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<LLVector3> position;
|
||||
buffer->getVertexStrider(position);
|
||||
|
||||
LLStrider<LLVector4> weight;
|
||||
LLStrider<LLVector4a> 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];
|
||||
|
||||
@@ -413,7 +413,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w
|
||||
LLStrider<LLVector3> normalsp;
|
||||
LLStrider<LLVector2> tex_coordsp;
|
||||
LLStrider<F32> vertex_weightsp;
|
||||
LLStrider<LLVector4> clothing_weightsp;
|
||||
LLStrider<LLVector4a> clothing_weightsp;
|
||||
LLStrider<U16> indicesp;
|
||||
|
||||
// Copy data into the faces from the polymesh data.
|
||||
|
||||
@@ -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<LLVector3> position;
|
||||
LLStrider<LLVector3> 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
|
||||
|
||||
@@ -74,6 +74,7 @@ class LLHUDEffectSpiral;
|
||||
class LLTexGlobalColor;
|
||||
class LLViewerJoint;
|
||||
struct LLAppearanceMessageContents;
|
||||
class LLMeshSkinInfo;
|
||||
|
||||
class SHClientTagMgr : public LLSingleton<SHClientTagMgr>, 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<LLUUID>& ids);
|
||||
bool allTexturesCompletelyDownloaded(std::set<LLUUID>& ids) const;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user