summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Payne (Vir Linden) <vir@lindenlab.com>2015-10-19 16:32:49 -0400
committerBrad Payne (Vir Linden) <vir@lindenlab.com>2015-10-19 16:32:49 -0400
commit6c6a95478ecd657c271354d93a6f98c90093bac5 (patch)
tree3272eb91816b849d65c9d72293ee0a4769827306
parent58992e2cb4ae2787b85cff63c3ed680cd99fa8ce (diff)
SL-234 WIP - remap skin weights to match included-joint logic
-rwxr-xr-xindra/llmath/llvolume.cpp1
-rwxr-xr-xindra/llmath/llvolume.h4
-rwxr-xr-xindra/newview/lldrawpoolavatar.cpp113
-rwxr-xr-xindra/newview/lldrawpoolavatar.h2
-rwxr-xr-xindra/newview/llvovolume.cpp1
5 files changed, 64 insertions, 57 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 8608e45a91..206330fd53 100755
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -4568,6 +4568,7 @@ LLVolumeFace::LLVolumeFace() :
mTexCoords(NULL),
mIndices(NULL),
mWeights(NULL),
+ mWeightsRemapped(FALSE),
mOctree(NULL),
mOptimized(FALSE)
{
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 1da2d0c6b1..33e1403a14 100755
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -953,6 +953,10 @@ public:
// mWeights.size() should be empty or match mVertices.size()
LLVector4a* mWeights;
+ // Whether or not the weights have been cleaned up and remapped
+ // based on currently supported joints.
+ mutable BOOL mWeightsRemapped;
+
LLOctreeNode<LLVolumeTriangle>* mOctree;
//whether or not face has been cache optimized
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 987a15c72d..dff6cada9a 100755
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1593,7 +1593,6 @@ U32 getValidJointIndex(const std::string& name, LLVOAvatar *avatar, std::vector<
// Which joint will stand in for this joint?
U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector<std::string>& joint_names)
{
-#if 1
bool include_enhanced = gSavedSettings.getBOOL("IncludeEnhancedSkeleton");
U32 j_proxy = getValidJointIndex(joint_names[joint_index], avatar, joint_names);
LLJoint *joint = avatar->getJoint(joint_names[j_proxy]);
@@ -1618,9 +1617,6 @@ U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector<std::str
joint = parent;
}
return j_proxy;
-#else
- return 0;
-#endif
}
// static
@@ -1634,6 +1630,8 @@ U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector<std::str
// This will throw away joint info for any joints that are not known
// in the avatar, or not currently flagged to support based on the
// debug setting for IncludeEnhancedSkeleton.
+//
+// static
void LLDrawPoolAvatar::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin)
{
// skip if already done.
@@ -1693,9 +1691,9 @@ void LLDrawPoolAvatar::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* s
LL_INFOS() << "Starting joint[" << j << "] = " << skin->mJointNames[j] << " j_remap " << j_remap[j] << " ==> " << new_joint_names[j_remap[j]] << LL_ENDL;
}
- //skin->mJointNames = new_joint_names;
- //skin->mInvBindMatrix = new_inv_bind_matrix;
- //skin->mAlternateBindMatrix = new_alternate_bind_matrix;
+ skin->mJointNames = new_joint_names;
+ skin->mInvBindMatrix = new_inv_bind_matrix;
+ skin->mAlternateBindMatrix = new_alternate_bind_matrix;
skin->mJointRemap = j_remap;
}
@@ -1706,67 +1704,59 @@ void LLDrawPoolAvatar::initSkinningMatrixPalette(
const LLMeshSkinInfo* skin,
LLVOAvatar *avatar)
{
- // BENTO ugly const cast
- remapSkinInfoJoints(avatar, const_cast<LLMeshSkinInfo*>(skin));
-
// BENTO - switching to use Matrix4a and SSE might speed this up.
// Note that we are mostly passing Matrix4a's to this routine anyway, just dubiously casted.
for (U32 j = 0; j < count; ++j)
{
LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
-#if 1 // Don't need this stuff if we've already remapped/cleaned up above
- if (!joint)
+ mat[j] = skin->mInvBindMatrix[j];
+ mat[j] *= joint->getWorldMatrix();
+ }
+}
+
+// Transform the weights based on the remap info stored in skin. Note
+// that this is destructive and non-idempotent, so we need to keep
+// track of whether we've done it already. If the desired remapping
+// changes, the viewer must be restarted.
+//
+// static
+void LLDrawPoolAvatar::remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)
+{
+ llassert(skin->mJointRemap.size()>0); // Must call remapSkinInfoJoints() first, which this checks for.
+ const U32* remap = &skin->mJointRemap[0];
+ const S32 max_joints = skin->mJointNames.size();
+ for (U32 j=0; j<num_vertices; j++)
+ {
+ F32 *w = weights[j].getF32ptr();
+
+ for (U32 k=0; k<4; ++k)
{
- joint = avatar->getJoint("mPelvis");
+ S32 i = llfloor(w[k]);
+ F32 f = w[k]-i;
+ i = llclamp(i,0,max_joints-1);
+ w[k] = remap[i] + f;
}
- if (joint)
+ }
+}
+
+// static
+void LLDrawPoolAvatar::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)
+{
+ if (skin->mJointRemap.size()>0)
+ {
+ // Check the weights are consistent with the current remap.
+ const S32 max_joints = skin->mJointNames.size();
+ for (U32 j=0; j<num_vertices; j++)
{
- if (!gSavedSettings.getBOOL("IncludeEnhancedSkeleton"))
- {
- // BENTO - test of simple push-to-base-ancestor
- // complexity reduction scheme. Find the first
- // ancestor that's not flagged as extended, or the
- // last ancestor that's rigged in this mesh, whichever
- // comes first.
- U32 j_remap = 0;
- while (1)
- {
- if (joint->getSupport()==LLJoint::SUPPORT_BASE)
- break;
- LLJoint *parent = joint->getParent();
- if (!parent)
- break;
- std::vector<std::string>::const_iterator find_it =
- std::find(skin->mJointNames.begin(), skin->mJointNames.end(), parent->getName());
- if (find_it != skin->mJointNames.end())
- {
- j_remap = find_it - skin->mJointNames.begin();
- }
- else
- {
- break;
- }
- joint = parent;
- }
- mat[j] = skin->mInvBindMatrix[j_remap];
- }
- else
+ F32 *w = weights[j].getF32ptr();
+
+ for (U32 k=0; k<4; ++k)
{
- mat[j] = skin->mInvBindMatrix[j];
+ S32 i = llfloor(w[k]);
+ llassert(i>=0);
+ llassert(i<max_joints);
}
-#else
- mat[j] = skin->mInvBindMatrix[j];
-#endif
- mat[j] *= joint->getWorldMatrix();
- }
}
- // This handles a bogus weights case that has turned up in
- // practice, without the overhead of zeroing every matrix. We are
- // doing this here instead of in getPerVertexSkinMatrix so the fix
- // will also work in the HW skinning case.
- if (count < LL_MAX_JOINTS_PER_MESH_OBJECT)
- {
- mat[count].setIdentity();
}
}
@@ -1835,12 +1825,20 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
{
return;
}
+ // BENTO ugly const cast
+ remapSkinInfoJoints(avatar, const_cast<LLMeshSkinInfo*>(skin));
LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
LLDrawable* drawable = face->getDrawable();
U32 data_mask = face->getRiggedVertexBufferDataMask();
+ if (!vol_face.mWeightsRemapped)
+ {
+ remapSkinWeights(weight, vol_face.mNumVertices, skin);
+ vol_face.mWeightsRemapped = TRUE;
+ }
+
if (buffer.isNull() ||
buffer->getTypeMask() != data_mask ||
buffer->getNumVerts() != vol_face.mNumVertices ||
@@ -1894,6 +1892,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
U32 count = getMeshJointCount(skin);
initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar);
+ checkSkinWeights(weight, buffer->getNumVerts(), skin);
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 27d4c949fd..8d6e95ba1a 100755
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -138,6 +138,8 @@ public:
static U32 getMeshJointCount(const LLMeshSkinInfo *skin);
static void remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin);
static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar);
+ static void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
+ static void remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints);
void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar,
LLFace* facep,
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index c09786b7c7..5d8558cb46 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4192,6 +4192,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
if ( weight )
{
+ LLDrawPoolAvatar::checkSkinWeights(weight, dst_face.mNumVertices, skin);
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);