summaryrefslogtreecommitdiff
path: root/indra/newview/lldrawpoolavatar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/lldrawpoolavatar.cpp')
-rwxr-xr-xindra/newview/lldrawpoolavatar.cpp295
1 files changed, 10 insertions, 285 deletions
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index dff6cada9a..89233b8e32 100755
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "lldrawpoolavatar.h"
+#include "llskinningutil.h"
#include "llrender.h"
#include "llvoavatar.h"
@@ -1537,282 +1538,6 @@ void LLDrawPoolAvatar::getRiggedGeometry(
buffer->flush();
}
-// static
-U32 LLDrawPoolAvatar::getMaxJointCount()
-{
- return llmin(LL_MAX_JOINTS_PER_MESH_OBJECT, gSavedSettings.getU32("MaxJointsPerMeshObject"));
-}
-
-// static
-U32 LLDrawPoolAvatar::getMeshJointCount(const LLMeshSkinInfo *skin)
-{
- return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size());
-}
-
-bool getNameIndex(const std::string& name, std::vector<std::string>& names, U32& result)
-{
- std::vector<std::string>::const_iterator find_it =
- std::find(names.begin(), names.end(), name);
- if (find_it != names.end())
- {
- result = find_it - names.begin();
- return true;
- }
- else
- {
- return false;
- }
-}
-
-// Find a name table index that is also a valid joint on the
-// avatar. Order of preference is: requested name, mPelvis, first
-// valid match in names table.
-U32 getValidJointIndex(const std::string& name, LLVOAvatar *avatar, std::vector<std::string>& joint_names)
-{
- U32 result;
- if (avatar->getJoint(name) && getNameIndex(name,joint_names,result))
- {
- return result;
- }
- if (getNameIndex("mPelvis",joint_names,result))
- {
- return result;
- }
- for (U32 j=0; j<joint_names.size(); j++)
- {
- if (avatar->getJoint(joint_names[j]))
- {
- return j;
- }
- }
- // BENTO how to handle?
- LL_ERRS() << "no valid joints in joint_names" << LL_ENDL;
- return 0;
-}
-
-// Which joint will stand in for this joint?
-U32 getProxyJointIndex(U32 joint_index, LLVOAvatar *avatar, std::vector<std::string>& joint_names)
-{
- 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]);
- llassert(joint);
- // 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.
- while (1)
- {
- if (include_enhanced ||
- joint->getSupport()==LLJoint::SUPPORT_BASE)
- break;
- LLJoint *parent = joint->getParent();
- if (!parent)
- break;
- if (!getNameIndex(parent->getName(), joint_names, j_proxy))
- {
- break;
- }
- joint = parent;
- }
- return j_proxy;
-}
-
-// static
-
-// Destructively remap the joints in skin info based on what joints
-// are known in the avatar, and which are currently supported. This
-// will also populate mJointRemap[] in the skin, which can be used to
-// make the corresponding changes to the integer part of vertex
-// weights.
-//
-// 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.
- if (!skin->mJointRemap.empty())
- {
- return;
- }
-
- // Compute the remap
- std::vector<U32> j_proxy(skin->mJointNames.size());
- for (U32 j = 0; j < skin->mJointNames.size(); ++j)
- {
- U32 j_rep = getProxyJointIndex(j, avatar, skin->mJointNames);
- j_proxy[j] = j_rep;
- }
- S32 top = 0;
- std::vector<U32> j_remap(skin->mJointNames.size());
- // Fill in j_remap for all joints that will make the cut.
- for (U32 j = 0; j < skin->mJointNames.size(); ++j)
- {
- if (j_proxy[j] == j)
- {
- // Joint will be included
- j_remap[j] = top++;
- }
- }
- // Then use j_proxy to fill in j_remap for the joints that will be discarded
- for (U32 j = 0; j < skin->mJointNames.size(); ++j)
- {
- if (j_proxy[j] != j)
- {
- j_remap[j] = j_remap[j_proxy[j]];
- }
- }
-
-
- // Apply the remap to mJointNames, mInvBindMatrix, and mAlternateBindMatrix
- std::vector<std::string> new_joint_names;
- std::vector<LLMatrix4> new_inv_bind_matrix;
- std::vector<LLMatrix4> new_alternate_bind_matrix;
-
- for (U32 j = 0; j < skin->mJointNames.size(); ++j)
- {
- if (j_proxy[j] == j)
- {
- new_joint_names.push_back(skin->mJointNames[j]);
- new_inv_bind_matrix.push_back(skin->mInvBindMatrix[j]);
- if (!skin->mAlternateBindMatrix.empty())
- {
- new_alternate_bind_matrix.push_back(skin->mAlternateBindMatrix[j]);
- }
- }
- }
-
- for (U32 j = 0; j < skin->mJointNames.size(); ++j)
- {
- 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->mJointRemap = j_remap;
-}
-
-// static
-void LLDrawPoolAvatar::initSkinningMatrixPalette(
- LLMatrix4* mat,
- S32 count,
- const LLMeshSkinInfo* skin,
- LLVOAvatar *avatar)
-{
- // 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]);
- 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)
- {
- S32 i = llfloor(w[k]);
- F32 f = w[k]-i;
- i = llclamp(i,0,max_joints-1);
- w[k] = remap[i] + f;
- }
- }
-}
-
-// 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++)
- {
- F32 *w = weights[j].getF32ptr();
-
- for (U32 k=0; k<4; ++k)
- {
- S32 i = llfloor(w[k]);
- llassert(i>=0);
- llassert(i<max_joints);
- }
- }
- }
-}
-
-// static
-void LLDrawPoolAvatar::getPerVertexSkinMatrix(
- F32* weights,
- LLMatrix4a* mat,
- bool handle_bad_scale,
- LLMatrix4a& final_mat,
- U32 max_joints)
-{
-
- final_mat.clear();
-
- S32 idx[4];
-
- LLVector4 wght;
-
- F32 scale = 0.f;
- for (U32 k = 0; k < 4; k++)
- {
- F32 w = weights[k];
-
- // BENTO potential optimizations
- // - Do clamping in unpackVolumeFaces() (once instead of every time)
- // - int vs floor: if we know w is
- // >= 0.0, we can use int instead of floorf; the latter
- // allegedly has a lot of overhead due to ieeefp error
- // checking which we should not need.
- idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)max_joints-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);
- }
-}
-
void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
LLVOAvatar* avatar,
LLFace* face,
@@ -1826,7 +1551,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
return;
}
// BENTO ugly const cast
- remapSkinInfoJoints(avatar, const_cast<LLMeshSkinInfo*>(skin));
+ LLSkinningUtil::remapSkinInfoJoints(avatar, const_cast<LLMeshSkinInfo*>(skin));
LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
LLDrawable* drawable = face->getDrawable();
@@ -1835,7 +1560,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
if (!vol_face.mWeightsRemapped)
{
- remapSkinWeights(weight, vol_face.mNumVertices, skin);
+ LLSkinningUtil::remapSkinWeights(weight, vol_face.mNumVertices, skin);
vol_face.mWeightsRemapped = TRUE;
}
@@ -1890,18 +1615,18 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
//build matrix palette
LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
- U32 count = getMeshJointCount(skin);
- initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar);
- checkSkinWeights(weight, buffer->getNumVerts(), skin);
+ U32 count = LLSkinningUtil::getMeshJointCount(skin);
+ LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar);
+ LLSkinningUtil::checkSkinWeights(weight, buffer->getNumVerts(), skin);
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
- const U32 max_joints = getMaxJointCount();
+ const U32 max_joints = LLSkinningUtil::getMaxJointCount();
for (U32 j = 0; j < buffer->getNumVerts(); ++j)
{
LLMatrix4a final_mat;
- getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints);
+ LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints);
LLVector4a& v = vol_face.mPositions[j];
LLVector4a t;
@@ -1984,8 +1709,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
{
// upload matrix palette to shader
LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
- U32 count = getMeshJointCount(skin);
- initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar);
+ U32 count = LLSkinningUtil::getMeshJointCount(skin);
+ LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar);
stop_glerror();