summaryrefslogtreecommitdiff
path: root/indra/llappearance
diff options
context:
space:
mode:
authorAndreyL ProductEngine <alihatskiy@productengine.com>2016-12-05 21:51:29 +0200
committerAndreyL ProductEngine <alihatskiy@productengine.com>2016-12-05 21:51:29 +0200
commit2abd0eef41a94d5626ca9f5f1b18aa959157c50f (patch)
tree625e2c9cf747fb1507302257a93a557de135b395 /indra/llappearance
parent84c546182c67b2d9f6542f95d979ed33903cb95f (diff)
parent68413474c4479eee9bdbeb34ea131475ba1d646e (diff)
Merged in lindenlab/viewer-release
DRTVWR-412 Bento (avatar skeleton extensions)
Diffstat (limited to 'indra/llappearance')
-rw-r--r--indra/llappearance/llavatarappearance.cpp287
-rw-r--r--indra/llappearance/llavatarappearance.h28
-rw-r--r--indra/llappearance/llavatarjoint.cpp13
-rw-r--r--indra/llappearance/llavatarjointmesh.cpp96
-rw-r--r--indra/llappearance/lldriverparam.cpp8
-rw-r--r--indra/llappearance/lldriverparam.h5
-rw-r--r--indra/llappearance/llpolymorph.cpp18
-rw-r--r--indra/llappearance/llpolymorph.h2
-rw-r--r--indra/llappearance/llpolyskeletaldistortion.cpp165
-rw-r--r--indra/llappearance/llwearable.cpp2
10 files changed, 423 insertions, 201 deletions
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index d1eb389013..94c431feb4 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -44,6 +44,7 @@
#include "lltexglobalcolor.h"
#include "llwearabledata.h"
#include "boost/bind.hpp"
+#include "boost/tokenizer.hpp"
#if LL_MSVC
@@ -87,8 +88,11 @@ public:
private:
std::string mName;
+ std::string mSupport;
+ std::string mAliases;
BOOL mIsJoint;
LLVector3 mPos;
+ LLVector3 mEnd;
LLVector3 mRot;
LLVector3 mScale;
LLVector3 mPivot;
@@ -118,6 +122,7 @@ public:
private:
S32 mNumBones;
S32 mNumCollisionVolumes;
+ LLAvatarAppearance::joint_alias_map_t mJointAliasMap;
typedef std::vector<LLAvatarBoneInfo*> bone_info_list_t;
bone_info_list_t mBoneInfoList;
};
@@ -181,7 +186,11 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
mPelvisToFoot(0.f),
mHeadOffset(),
mRoot(NULL),
- mWearableData(wearable_data)
+ mWearableData(wearable_data),
+ mNumBones(0),
+ mNumCollisionVolumes(0),
+ mCollisionVolumes(NULL),
+ mIsBuilt(FALSE)
{
llassert_always(mWearableData);
mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES);
@@ -194,11 +203,6 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
mBakedTextureDatas[i].mMaskTexName = 0;
mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i);
}
-
- mIsBuilt = FALSE;
-
- mNumCollisionVolumes = 0;
- mCollisionVolumes = NULL;
}
// virtual
@@ -323,36 +327,49 @@ LLAvatarAppearance::~LLAvatarAppearance()
//static
void LLAvatarAppearance::initClass()
{
- std::string xmlFile;
+ initClass("","");
+}
- xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml";
- BOOL success = sXMLTree.parseFile( xmlFile, FALSE );
+//static
+void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, const std::string& skeleton_file_name_arg)
+{
+ std::string avatar_file_name;
+
+ if (!avatar_file_name_arg.empty())
+ {
+ avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,avatar_file_name_arg);
+ }
+ else
+ {
+ avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR + "_lad.xml");
+ }
+ BOOL success = sXMLTree.parseFile( avatar_file_name, FALSE );
if (!success)
{
- LL_ERRS() << "Problem reading avatar configuration file:" << xmlFile << LL_ENDL;
+ LL_ERRS() << "Problem reading avatar configuration file:" << avatar_file_name << LL_ENDL;
}
// now sanity check xml file
LLXmlTreeNode* root = sXMLTree.getRoot();
if (!root)
{
- LL_ERRS() << "No root node found in avatar configuration file: " << xmlFile << LL_ENDL;
+ LL_ERRS() << "No root node found in avatar configuration file: " << avatar_file_name << LL_ENDL;
return;
}
//-------------------------------------------------------------------------
- // <linden_avatar version="1.0"> (root)
+ // <linden_avatar version="2.0"> (root)
//-------------------------------------------------------------------------
if( !root->hasName( "linden_avatar" ) )
{
- LL_ERRS() << "Invalid avatar file header: " << xmlFile << LL_ENDL;
+ LL_ERRS() << "Invalid avatar file header: " << avatar_file_name << LL_ENDL;
}
std::string version;
static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version");
- if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") )
+ if( !root->getFastAttributeString( version_string, version ) || ((version != "1.0") && (version != "2.0")))
{
- LL_ERRS() << "Invalid avatar file version: " << version << " in file: " << xmlFile << LL_ENDL;
+ LL_ERRS() << "Invalid avatar file version: " << version << " in file: " << avatar_file_name << LL_ENDL;
}
S32 wearable_def_version = 1;
@@ -365,16 +382,19 @@ void LLAvatarAppearance::initClass()
LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" );
if (!skeleton_node)
{
- LL_ERRS() << "No skeleton in avatar configuration file: " << xmlFile << LL_ENDL;
+ LL_ERRS() << "No skeleton in avatar configuration file: " << avatar_file_name << LL_ENDL;
return;
}
-
- std::string skeleton_file_name;
- static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name");
- if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name))
- {
- LL_ERRS() << "No file name in skeleton node in avatar config file: " << xmlFile << LL_ENDL;
- }
+
+ std::string skeleton_file_name = skeleton_file_name_arg;
+ if (skeleton_file_name.empty())
+ {
+ static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name");
+ if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name))
+ {
+ LL_ERRS() << "No file name in skeleton node in avatar config file: " << avatar_file_name << LL_ENDL;
+ }
+ }
std::string skeleton_path;
skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name);
@@ -437,11 +457,56 @@ void LLAvatarAppearance::cleanupClass()
using namespace LLAvatarAppearanceDefines;
+void LLAvatarAppearance::compareJointStateMaps(joint_state_map_t& last_state,
+ joint_state_map_t& curr_state)
+{
+ if (!last_state.empty() && (last_state != curr_state))
+ {
+ S32 diff_count = 0;
+ joint_state_map_t::iterator it;
+ for (it=last_state.begin(); it != last_state.end(); ++it)
+ {
+ const std::string& key = it->first;
+ if (last_state[key] != curr_state[key])
+ {
+ LL_DEBUGS("AvatarBodySize") << "BodySize change " << key << " " << last_state[key] << "->" << curr_state[key] << LL_ENDL;
+ diff_count++;
+ }
+ }
+ if (diff_count > 0)
+ {
+ LL_DEBUGS("AvatarBodySize") << "Total of BodySize changes " << diff_count << LL_ENDL;
+ }
+
+ }
+}
+
//------------------------------------------------------------------------
// The viewer can only suggest a good size for the agent,
// the simulator will keep it inside a reasonable range.
void LLAvatarAppearance::computeBodySize()
{
+ mLastBodySizeState = mCurrBodySizeState;
+
+ mCurrBodySizeState["mPelvis scale"] = mPelvisp->getScale();
+ mCurrBodySizeState["mSkull pos"] = mSkullp->getPosition();
+ mCurrBodySizeState["mSkull scale"] = mSkullp->getScale();
+ mCurrBodySizeState["mNeck pos"] = mNeckp->getPosition();
+ mCurrBodySizeState["mNeck scale"] = mNeckp->getScale();
+ mCurrBodySizeState["mChest pos"] = mChestp->getPosition();
+ mCurrBodySizeState["mChest scale"] = mChestp->getScale();
+ mCurrBodySizeState["mHead pos"] = mHeadp->getPosition();
+ mCurrBodySizeState["mHead scale"] = mHeadp->getScale();
+ mCurrBodySizeState["mTorso pos"] = mTorsop->getPosition();
+ mCurrBodySizeState["mTorso scale"] = mTorsop->getScale();
+ mCurrBodySizeState["mHipLeft pos"] = mHipLeftp->getPosition();
+ mCurrBodySizeState["mHipLeft scale"] = mHipLeftp->getScale();
+ mCurrBodySizeState["mKneeLeft pos"] = mKneeLeftp->getPosition();
+ mCurrBodySizeState["mKneeLeft scale"] = mKneeLeftp->getScale();
+ mCurrBodySizeState["mAnkleLeft pos"] = mAnkleLeftp->getPosition();
+ mCurrBodySizeState["mAnkleLeft scale"] = mAnkleLeftp->getScale();
+ mCurrBodySizeState["mFootLeft pos"] = mFootLeftp->getPosition();
+
LLVector3 pelvis_scale = mPelvisp->getScale();
// some of the joints have not been cached
@@ -501,6 +566,8 @@ void LLAvatarAppearance::computeBodySize()
if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ])
{
mBodySize = new_body_size;
+
+ compareJointStateMaps(mLastBodySizeState, mCurrBodySizeState);
}
}
@@ -536,7 +603,7 @@ BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename)
std::string version;
static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version");
- if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") )
+ if( !root->getFastAttributeString( version_string, version ) || ((version != "1.0") && (version != "2.0")))
{
LL_ERRS() << "Invalid avatar skeleton file version: " << version << " in file: " << filename << LL_ENDL;
return FALSE;
@@ -552,6 +619,12 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
{
LLJoint* joint = NULL;
+ LL_DEBUGS("BVH") << "bone info: name " << info->mName
+ << " isJoint " << info->mIsJoint
+ << " volume_num " << volume_num
+ << " joint_num " << joint_num
+ << LL_ENDL;
+
if (info->mIsJoint)
{
joint = getCharacterJoint(joint_num);
@@ -566,7 +639,7 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
{
if (volume_num >= (S32)mNumCollisionVolumes)
{
- LL_WARNS() << "Too many bones" << LL_ENDL;
+ LL_WARNS() << "Too many collision volumes" << LL_ENDL;
return FALSE;
}
joint = (&mCollisionVolumes[volume_num]);
@@ -574,26 +647,34 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
}
// add to parent
- if (parent)
+ if (parent && (joint->getParent()!=parent))
{
parent->addChild( joint );
}
+ // SL-315
joint->setPosition(info->mPos);
+ joint->setDefaultPosition(info->mPos);
joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY],
info->mRot.mV[VZ], LLQuaternion::XYZ));
joint->setScale(info->mScale);
+ joint->setDefaultScale(info->mScale);
+ joint->setSupport(info->mSupport);
+ joint->setEnd(info->mEnd);
if (info->mIsJoint)
{
joint->setSkinOffset( info->mPivot );
+ joint->setJointNum(joint_num);
joint_num++;
}
else // collision volume
{
+ joint->setJointNum(mNumBones+volume_num);
volume_num++;
}
+
// setup children
LLAvatarBoneInfo::child_list_t::const_iterator iter;
for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter)
@@ -613,12 +694,12 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
//-----------------------------------------------------------------------------
BOOL LLAvatarAppearance::allocateCharacterJoints( U32 num )
{
- clearSkeleton();
-
- for(S32 joint_num = 0; joint_num < (S32)num; joint_num++)
- {
- mSkeleton.push_back(createAvatarJoint(joint_num));
- }
+ if (mSkeleton.size() != num)
+ {
+ clearSkeleton();
+ mSkeleton = avatar_joint_list_t(num,NULL);
+ mNumBones = num;
+ }
return TRUE;
}
@@ -629,18 +710,16 @@ BOOL LLAvatarAppearance::allocateCharacterJoints( U32 num )
//-----------------------------------------------------------------------------
BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info)
{
- //-------------------------------------------------------------------------
+ LL_DEBUGS("BVH") << "numBones " << info->mNumBones << " numCollisionVolumes " << info->mNumCollisionVolumes << LL_ENDL;
+
// allocate joints
- //-------------------------------------------------------------------------
if (!allocateCharacterJoints(info->mNumBones))
{
LL_ERRS() << "Can't allocate " << info->mNumBones << " joints" << LL_ENDL;
return FALSE;
}
- //-------------------------------------------------------------------------
// allocate volumes
- //-------------------------------------------------------------------------
if (info->mNumCollisionVolumes)
{
if (!allocateCollisionVolumes(info->mNumCollisionVolumes))
@@ -655,8 +734,8 @@ BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info)
LLAvatarSkeletonInfo::bone_info_list_t::const_iterator iter;
for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter)
{
- LLAvatarBoneInfo *info = *iter;
- if (!setupBone(info, NULL, current_volume_num, current_joint_num))
+ LLAvatarBoneInfo *bone_info = *iter;
+ if (!setupBone(bone_info, NULL, current_volume_num, current_joint_num))
{
LL_ERRS() << "Error parsing bone in skeleton file" << LL_ENDL;
return FALSE;
@@ -820,6 +899,7 @@ void LLAvatarAppearance::buildCharacter()
//-------------------------------------------------------------------------
// initialize the pelvis
//-------------------------------------------------------------------------
+ // SL-315
mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) );
mIsBuilt = TRUE;
@@ -834,21 +914,21 @@ BOOL LLAvatarAppearance::loadAvatar()
// avatar_skeleton.xml
if( !buildSkeleton(sAvatarSkeletonInfo) )
{
- LL_WARNS() << "avatar file: buildSkeleton() failed" << LL_ENDL;
+ LL_ERRS() << "avatar file: buildSkeleton() failed" << LL_ENDL;
return FALSE;
}
// avatar_lad.xml : <skeleton>
if( !loadSkeletonNode() )
{
- LL_WARNS() << "avatar file: loadNodeSkeleton() failed" << LL_ENDL;
+ LL_ERRS() << "avatar file: loadNodeSkeleton() failed" << LL_ENDL;
return FALSE;
}
// avatar_lad.xml : <mesh>
if( !loadMeshNodes() )
{
- LL_WARNS() << "avatar file: loadNodeMesh() failed" << LL_ENDL;
+ LL_ERRS() << "avatar file: loadNodeMesh() failed" << LL_ENDL;
return FALSE;
}
@@ -858,13 +938,13 @@ BOOL LLAvatarAppearance::loadAvatar()
mTexSkinColor = new LLTexGlobalColor( this );
if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) )
{
- LL_WARNS() << "avatar file: mTexSkinColor->setInfo() failed" << LL_ENDL;
+ LL_ERRS() << "avatar file: mTexSkinColor->setInfo() failed" << LL_ENDL;
return FALSE;
}
}
else
{
- LL_WARNS() << "<global_color> name=\"skin_color\" not found" << LL_ENDL;
+ LL_ERRS() << "<global_color> name=\"skin_color\" not found" << LL_ENDL;
return FALSE;
}
if( sAvatarXmlInfo->mTexHairColorInfo )
@@ -872,13 +952,13 @@ BOOL LLAvatarAppearance::loadAvatar()
mTexHairColor = new LLTexGlobalColor( this );
if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) )
{
- LL_WARNS() << "avatar file: mTexHairColor->setInfo() failed" << LL_ENDL;
+ LL_ERRS() << "avatar file: mTexHairColor->setInfo() failed" << LL_ENDL;
return FALSE;
}
}
else
{
- LL_WARNS() << "<global_color> name=\"hair_color\" not found" << LL_ENDL;
+ LL_ERRS() << "<global_color> name=\"hair_color\" not found" << LL_ENDL;
return FALSE;
}
if( sAvatarXmlInfo->mTexEyeColorInfo )
@@ -886,26 +966,26 @@ BOOL LLAvatarAppearance::loadAvatar()
mTexEyeColor = new LLTexGlobalColor( this );
if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) )
{
- LL_WARNS() << "avatar file: mTexEyeColor->setInfo() failed" << LL_ENDL;
+ LL_ERRS() << "avatar file: mTexEyeColor->setInfo() failed" << LL_ENDL;
return FALSE;
}
}
else
{
- LL_WARNS() << "<global_color> name=\"eye_color\" not found" << LL_ENDL;
+ LL_ERRS() << "<global_color> name=\"eye_color\" not found" << LL_ENDL;
return FALSE;
}
// avatar_lad.xml : <layer_set>
if (sAvatarXmlInfo->mLayerInfoList.empty())
{
- LL_WARNS() << "avatar file: missing <layer_set> node" << LL_ENDL;
+ LL_ERRS() << "avatar file: missing <layer_set> node" << LL_ENDL;
return FALSE;
}
if (sAvatarXmlInfo->mMorphMaskInfoList.empty())
{
- LL_WARNS() << "avatar file: missing <morph_masks> node" << LL_ENDL;
+ LL_ERRS() << "avatar file: missing <morph_masks> node" << LL_ENDL;
return FALSE;
}
@@ -1104,6 +1184,7 @@ BOOL LLAvatarAppearance::loadMeshNodes()
{
// This should never happen
LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL;
+ return FALSE;
}
}
else
@@ -1240,6 +1321,10 @@ LLJoint *LLAvatarAppearance::getCharacterJoint( U32 num )
{
return NULL;
}
+ if (!mSkeleton[num])
+ {
+ mSkeleton[num] = createAvatarJoint();
+ }
return mSkeleton[num];
}
@@ -1476,16 +1561,19 @@ LLTexLayerSet* LLAvatarAppearance::getAvatarLayerSet(EBakedTextureIndex baked_in
//-----------------------------------------------------------------------------
BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num )
{
- delete_and_clear_array(mCollisionVolumes);
- mNumCollisionVolumes = 0;
-
- mCollisionVolumes = new LLAvatarJointCollisionVolume[num];
- if (!mCollisionVolumes)
- {
- return FALSE;
- }
-
- mNumCollisionVolumes = num;
+ if (mNumCollisionVolumes !=num)
+ {
+ delete_and_clear_array(mCollisionVolumes);
+ mNumCollisionVolumes = 0;
+
+ mCollisionVolumes = new LLAvatarJointCollisionVolume[num];
+ if (!mCollisionVolumes)
+ {
+ return FALSE;
+ }
+
+ mNumCollisionVolumes = num;
+ }
return TRUE;
}
@@ -1503,6 +1591,9 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
LL_WARNS() << "Bone without name" << LL_ENDL;
return FALSE;
}
+
+ static LLStdStringHandle aliases_string = LLXmlTree::addAttributeString("aliases");
+ node->getFastAttributeString(aliases_string, mAliases ); //Aliases are not required.
}
else if (node->hasName("collision_volume"))
{
@@ -1540,6 +1631,20 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
return FALSE;
}
+ static LLStdStringHandle end_string = LLXmlTree::addAttributeString("end");
+ if (!node->getFastAttributeVector3(end_string, mEnd))
+ {
+ LL_WARNS() << "Bone without end " << mName << LL_ENDL;
+ mEnd = LLVector3(0.0f, 0.0f, 0.0f);
+ }
+
+ static LLStdStringHandle support_string = LLXmlTree::addAttributeString("support");
+ if (!node->getFastAttributeString(support_string,mSupport))
+ {
+ LL_WARNS() << "Bone without support " << mName << LL_ENDL;
+ mSupport = "base";
+ }
+
if (mIsJoint)
{
static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot");
@@ -1595,6 +1700,54 @@ BOOL LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
return TRUE;
}
+//Make aliases for joint and push to map.
+void LLAvatarAppearance::makeJointAliases(LLAvatarBoneInfo *bone_info)
+{
+ if (! bone_info->mIsJoint )
+ {
+ return;
+ }
+
+ std::string bone_name = bone_info->mName;
+ mJointAliasMap[bone_name] = bone_name; //Actual name is a valid alias.
+
+ std::string aliases = bone_info->mAliases;
+
+ boost::char_separator<char> sep(" ");
+ boost::tokenizer<boost::char_separator<char> > tok(aliases, sep);
+ for(boost::tokenizer<boost::char_separator<char> >::iterator i = tok.begin(); i != tok.end(); ++i)
+ {
+ if ( mJointAliasMap.find(*i) != mJointAliasMap.end() )
+ {
+ LL_WARNS() << "avatar skeleton: Joint alias \"" << *i << "\" remapped from " << mJointAliasMap[*i] << " to " << bone_name << LL_ENDL;
+ }
+ mJointAliasMap[*i] = bone_name;
+ }
+
+ LLAvatarBoneInfo::child_list_t::const_iterator iter;
+ for (iter = bone_info->mChildList.begin(); iter != bone_info->mChildList.end(); ++iter)
+ {
+ makeJointAliases( *iter );
+ }
+}
+
+const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases ()
+{
+ LLAvatarAppearance::joint_alias_map_t alias_map;
+ if (mJointAliasMap.empty())
+ {
+
+ LLAvatarSkeletonInfo::bone_info_list_t::const_iterator iter;
+ for (iter = sAvatarSkeletonInfo->mBoneInfoList.begin(); iter != sAvatarSkeletonInfo->mBoneInfoList.end(); ++iter)
+ {
+ //LLAvatarBoneInfo *bone_info = *iter;
+ makeJointAliases( *iter );
+ }
+ }
+
+ return mJointAliasMap;
+}
+
//-----------------------------------------------------------------------------
// parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree
@@ -1625,7 +1778,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro
{
LL_WARNS() << "Unknown param type." << LL_ENDL;
}
- continue;
+ return FALSE;
}
LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo;
@@ -1650,7 +1803,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro
{
LL_WARNS() << "No name supplied for attachment point." << LL_ENDL;
delete info;
- continue;
+ return FALSE;
}
static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint");
@@ -1658,7 +1811,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro
{
LL_WARNS() << "No bone declared in attachment point " << info->mName << LL_ENDL;
delete info;
- continue;
+ return FALSE;
}
static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position");
@@ -1684,7 +1837,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro
{
LL_WARNS() << "No id supplied for attachment point " << info->mName << LL_ENDL;
delete info;
- continue;
+ return FALSE;
}
static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice");
@@ -1770,7 +1923,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
{
LL_WARNS() << "Unknown param type." << LL_ENDL;
}
- continue;
+ return FALSE;
}
LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo();
@@ -1931,7 +2084,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root
{
LL_WARNS() << "No name supplied for morph mask." << LL_ENDL;
delete info;
- continue;
+ return FALSE;
}
static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region");
@@ -1939,7 +2092,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root
{
LL_WARNS() << "No region supplied for morph mask." << LL_ENDL;
delete info;
- continue;
+ return FALSE;
}
static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer");
@@ -1947,7 +2100,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root
{
LL_WARNS() << "No layer supplied for morph mask." << LL_ENDL;
delete info;
- continue;
+ return FALSE;
}
// optional parameter. don't throw a warning if not present.
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index a0ef49b7cb..ccd6323ed8 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -66,7 +66,8 @@ public:
LLAvatarAppearance(LLWearableData* wearable_data);
virtual ~LLAvatarAppearance();
- static void initClass(); // initializes static members
+ static void initClass(const std::string& avatar_file_name, const std::string& skeleton_file_name); // initializes static members
+ static void initClass();
static void cleanupClass(); // Cleanup data that's only init'd once per class.
virtual void initInstance(); // Called after construction to initialize the instance.
virtual BOOL loadSkeletonNode();
@@ -124,8 +125,11 @@ public:
protected:
virtual LLAvatarJoint* createAvatarJoint() = 0;
- virtual LLAvatarJoint* createAvatarJoint(S32 joint_num) = 0;
+ virtual LLAvatarJoint* createAvatarJoint(S32 joint_num) = 0;
virtual LLAvatarJointMesh* createAvatarJointMesh() = 0;
+ void makeJointAliases(LLAvatarBoneInfo *bone_info);
+
+
public:
F32 getPelvisToFoot() const { return mPelvisToFoot; }
/*virtual*/ LLJoint* getRootJoint() { return mRoot; }
@@ -135,9 +139,20 @@ public:
typedef std::map<std::string, LLJoint*> joint_map_t;
joint_map_t mJointMap;
-
+
+ typedef std::map<std::string, LLVector3> joint_state_map_t;
+ joint_state_map_t mLastBodySizeState;
+ joint_state_map_t mCurrBodySizeState;
+ void compareJointStateMaps(joint_state_map_t& last_state,
+ joint_state_map_t& curr_state);
void computeBodySize();
+public:
+ typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;
+ const avatar_joint_list_t& getSkeleton() { return mSkeleton; }
+ typedef std::map<std::string, std::string> joint_alias_map_t;
+ const joint_alias_map_t& getJointAliases();
+
protected:
static BOOL parseSkeletonFile(const std::string& filename);
@@ -147,12 +162,12 @@ protected:
BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
BOOL allocateCharacterJoints(U32 num);
BOOL buildSkeleton(const LLAvatarSkeletonInfo *info);
-protected:
+
void clearSkeleton();
BOOL mIsBuilt; // state of deferred character building
- typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;
avatar_joint_list_t mSkeleton;
- LLPosOverrideMap mPelvisFixups;
+ LLVector3OverrideMap mPelvisFixups;
+ joint_alias_map_t mJointAliasMap;
//--------------------------------------------------------------------
// Pelvis height adjustment members.
@@ -335,6 +350,7 @@ protected:
// Collision volumes
//--------------------------------------------------------------------
public:
+ S32 mNumBones;
S32 mNumCollisionVolumes;
LLAvatarJointCollisionVolume* mCollisionVolumes;
protected:
diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp
index 2ee3c65a01..29642be099 100644
--- a/indra/llappearance/llavatarjoint.cpp
+++ b/indra/llappearance/llavatarjoint.cpp
@@ -52,19 +52,18 @@ LLAvatarJoint::LLAvatarJoint() :
init();
}
-LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) :
- LLJoint(name, parent)
+LLAvatarJoint::LLAvatarJoint(S32 joint_num) :
+ LLJoint(joint_num)
{
- init();
+ init();
}
-
-LLAvatarJoint::LLAvatarJoint(S32 joint_num) :
- LLJoint(joint_num)
+
+LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) :
+ LLJoint(name, parent)
{
init();
}
-
void LLAvatarJoint::init()
{
mValid = FALSE;
diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp
index 520ad775db..7ca0928171 100644
--- a/indra/llappearance/llavatarjointmesh.cpp
+++ b/indra/llappearance/llavatarjointmesh.cpp
@@ -33,22 +33,7 @@
#include "llavatarjointmesh.h"
#include "llavatarappearance.h"
-//#include "llapr.h"
-//#include "llbox.h"
-//#include "lldrawable.h"
-//#include "lldrawpoolavatar.h"
-//#include "lldrawpoolbump.h"
-//#include "lldynamictexture.h"
-//#include "llface.h"
-//#include "llgldbg.h"
-//#include "llglheaders.h"
#include "lltexlayer.h"
-//#include "llviewercamera.h"
-//#include "llviewercontrol.h"
-//#include "llviewertexturelist.h"
-//#include "llsky.h"
-//#include "pipeline.h"
-//#include "llviewershadermgr.h"
#include "llmath.h"
#include "v4math.h"
#include "m3math.h"
@@ -56,6 +41,41 @@
#include "llmatrix4a.h"
+// Utility functions added with Bento to simplify handling of extra
+// spine joints, or other new joints internal to the original
+// skeleton, and unknown to the system avatar.
+
+//-----------------------------------------------------------------------------
+// getBaseSkeletonAncestor()
+//-----------------------------------------------------------------------------
+LLAvatarJoint *getBaseSkeletonAncestor(LLAvatarJoint* joint)
+{
+ LLJoint *ancestor = joint->getParent();
+ while (ancestor->getParent() && (ancestor->getSupport() != LLJoint::SUPPORT_BASE))
+ {
+ LL_DEBUGS("Avatar") << "skipping non-base ancestor " << ancestor->getName() << LL_ENDL;
+ ancestor = ancestor->getParent();
+ }
+ return (LLAvatarJoint*) ancestor;
+}
+
+//-----------------------------------------------------------------------------
+// totalSkinOffset()
+//-----------------------------------------------------------------------------
+LLVector3 totalSkinOffset(LLAvatarJoint *joint)
+{
+ LLVector3 totalOffset;
+ while (joint)
+ {
+ if (joint->getSupport() == LLJoint::SUPPORT_BASE)
+ {
+ totalOffset += joint->getSkinOffset();
+ }
+ joint = (LLAvatarJoint*)joint->getParent();
+ }
+ return totalOffset;
+}
+
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLAvatarJointMesh::LLSkinJoint
@@ -92,18 +112,12 @@ BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint)
}
// compute the inverse root skin matrix
- mRootToJointSkinOffset.clearVec();
-
- LLVector3 rootSkinOffset;
- while (joint)
- {
- rootSkinOffset += joint->getSkinOffset();
- joint = (LLAvatarJoint*)joint->getParent();
- }
+ mRootToJointSkinOffset = totalSkinOffset(joint);
+ mRootToJointSkinOffset = -mRootToJointSkinOffset;
- mRootToJointSkinOffset = -rootSkinOffset;
- mRootToParentJointSkinOffset = mRootToJointSkinOffset;
- mRootToParentJointSkinOffset += mJoint->getSkinOffset();
+ //mRootToParentJointSkinOffset = totalSkinOffset((LLAvatarJoint*)joint->getParent());
+ mRootToParentJointSkinOffset = totalSkinOffset(getBaseSkeletonAncestor(joint));
+ mRootToParentJointSkinOffset = -mRootToParentJointSkinOffset;
return TRUE;
}
@@ -289,6 +303,7 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh )
}
// acquire the transform from the mesh object
+ // SL-315
setPosition( mMesh->getPosition() );
setRotation( mMesh->getRotation() );
setScale( mMesh->getScale() );
@@ -314,9 +329,9 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh )
if (!mMesh->isLOD())
{
setupJoint((LLAvatarJoint*)getRoot());
+ LL_DEBUGS("Avatar") << getName() << " joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL;
}
- LL_DEBUGS() << "joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL;
}
//-----------------------------------------------------------------------------
@@ -324,9 +339,6 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh )
//-----------------------------------------------------------------------------
void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint)
{
- LL_DEBUGS() << "Mesh: " << getName() << LL_ENDL;
-
- S32 joint_count = 0;
U32 sj;
for (sj=0; sj<mNumSkinJoints; sj++)
@@ -339,22 +351,30 @@ void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint)
}
// we've found a skinjoint for this joint..
+ LL_DEBUGS("Avatar") << "Mesh: " << getName() << " joint " << current_joint->getName() << " matches skinjoint " << sj << LL_ENDL;
// is the last joint in the array our parent?
- if(mMesh->mJointRenderData.size() && mMesh->mJointRenderData[mMesh->mJointRenderData.size() - 1]->mWorldMatrix == &current_joint->getParent()->getWorldMatrix())
+
+ std::vector<LLJointRenderData*> &jrd = mMesh->mJointRenderData;
+
+ // SL-287 - need to update this so the results are the same if
+ // additional extended-skeleton joints lie between this joint
+ // and the original parent.
+ LLJoint *ancestor = getBaseSkeletonAncestor(current_joint);
+ if(jrd.size() && jrd.back()->mWorldMatrix == &ancestor->getWorldMatrix())
{
// ...then just add ourselves
LLAvatarJoint* jointp = js.mJoint;
- mMesh->mJointRenderData.push_back(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
- LL_DEBUGS() << "joint " << joint_count++ << js.mJoint->getName() << LL_ENDL;
+ jrd.push_back(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
+ LL_DEBUGS("Avatar") << "add joint[" << (jrd.size()-1) << "] = " << js.mJoint->getName() << LL_ENDL;
}
- // otherwise add our parent and ourselves
+ // otherwise add our ancestor and ourselves
else
{
- mMesh->mJointRenderData.push_back(new LLJointRenderData(&current_joint->getParent()->getWorldMatrix(), NULL));
- LL_DEBUGS() << "joint " << joint_count++ << current_joint->getParent()->getName() << LL_ENDL;
- mMesh->mJointRenderData.push_back(new LLJointRenderData(&current_joint->getWorldMatrix(), &js));
- LL_DEBUGS() << "joint " << joint_count++ << current_joint->getName() << LL_ENDL;
+ jrd.push_back(new LLJointRenderData(&ancestor->getWorldMatrix(), NULL));
+ LL_DEBUGS("Avatar") << "add2 ancestor joint[" << (jrd.size()-1) << "] = " << ancestor->getName() << LL_ENDL;
+ jrd.push_back(new LLJointRenderData(&current_joint->getWorldMatrix(), &js));
+ LL_DEBUGS("Avatar") << "add2 joint[" << (jrd.size()-1) << "] = " << current_joint->getName() << LL_ENDL;
}
}
diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp
index e630c1118b..e5e502b158 100644
--- a/indra/llappearance/lldriverparam.cpp
+++ b/indra/llappearance/lldriverparam.cpp
@@ -110,6 +110,14 @@ void LLDriverParamInfo::toStream(std::ostream &out)
out << std::endl;
+ // FIXME - this mDriverParam backlink makes no sense, because the
+ // LLDriverParamInfos are static objects - there's only one copy
+ // for each param type, so the backlink will just reference the
+ // corresponding param in the most recently created
+ // avatar. Apparently these toStream() methods are not currently
+ // used anywhere, so it's not an urgent problem.
+ LL_WARNS_ONCE() << "Invalid usage of mDriverParam." << LL_ENDL;
+
if(mDriverParam && mDriverParam->getAvatarAppearance()->isSelf() &&
mDriverParam->getAvatarAppearance()->isValid())
{
diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h
index f71c930e5e..f278dcc2e2 100644
--- a/indra/llappearance/lldriverparam.h
+++ b/indra/llappearance/lldriverparam.h
@@ -128,6 +128,10 @@ public:
S32 getDrivenParamsCount() const;
const LLViewerVisualParam* getDrivenParam(S32 index) const;
+ typedef std::vector<LLDrivenEntry> entry_list_t;
+ entry_list_t& getDrivenList() { return mDriven; }
+ void setDrivenList(entry_list_t& driven_list) { mDriven = driven_list; }
+
protected:
LLDriverParam(const LLDriverParam& pOther);
F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight);
@@ -135,7 +139,6 @@ protected:
LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder
- typedef std::vector<LLDrivenEntry> entry_list_t;
entry_list_t mDriven;
LLViewerVisualParam* mCurrentDistortionParam;
// Backlink only; don't make this an LLPointer.
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
index e3992a080e..2cb4c65d7c 100644
--- a/indra/llappearance/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -369,7 +369,8 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
{
if (avatarp->mCollisionVolumes[i].getName() == volume_info->mName)
{
- mVolumeMorphs.push_back(LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i],
+ mVolumeMorphs.push_back(
+ LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i],
volume_info->mScale,
volume_info->mPos));
break;
@@ -647,6 +648,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex )
LLVector3 pos_delta = volume_morph->mPos * delta_weight;
volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta);
+ // SL-315
volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta);
}
}
@@ -730,6 +732,20 @@ void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3
apply(mLastSex);
}
+void LLPolyMorphTarget::applyVolumeChanges(F32 delta_weight)
+{
+ // now apply volume changes
+ for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); iter++ )
+ {
+ LLPolyVolumeMorph* volume_morph = &(*iter);
+ LLVector3 scale_delta = volume_morph->mScale * delta_weight;
+ LLVector3 pos_delta = volume_morph->mPos * delta_weight;
+
+ volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta);
+ // SL-315
+ volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta);
+ }
+}
//-----------------------------------------------------------------------------
// LLPolyVertexMask()
diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h
index 3c2c68079c..c6133cd831 100644
--- a/indra/llappearance/llpolymorph.h
+++ b/indra/llappearance/llpolymorph.h
@@ -182,6 +182,8 @@ public:
void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert);
void addPendingMorphMask() { mNumMorphMasksPending++; }
+ void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton()
+
void* operator new(size_t size)
{
return ll_aligned_malloc_16(size);
diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp
index fbc312c426..5b77a7433a 100644
--- a/indra/llappearance/llpolyskeletaldistortion.cpp
+++ b/indra/llappearance/llpolyskeletaldistortion.cpp
@@ -34,6 +34,7 @@
#include "llpolymorph.h"
#include "llwearable.h"
#include "llfasttimer.h"
+#include "llcallstack.h"
#include "llpolyskeletaldistortion.h"
@@ -134,55 +135,49 @@ LLPolySkeletalDistortion::~LLPolySkeletalDistortion()
BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
{
- llassert(mInfo == NULL);
- if (info->mID < 0)
- return FALSE;
- mInfo = info;
- mID = info->mID;
- setWeight(getDefaultWeight());
-
- LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
- for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
+ if (info->mID < 0)
+ {
+ return FALSE;
+ }
+ mInfo = info;
+ mID = info->mID;
+ setWeight(getDefaultWeight());
+
+ LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
+ for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
+ {
+ LLPolySkeletalBoneInfo *bone_info = &(*iter);
+ LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName);
+ if (!joint)
{
- LLPolySkeletalBoneInfo *bone_info = &(*iter);
- LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName);
- if (!joint)
- {
- LL_WARNS() << "Joint " << bone_info->mBoneName << " not found." << LL_ENDL;
- continue;
- }
-
- if (mJointScales.find(joint) != mJointScales.end())
- {
- LL_WARNS() << "Scale deformation already supplied for joint " << joint->getName() << "." << LL_ENDL;
- }
+ // There's no point continuing after this error - means
+ // that either the skeleton or lad file is broken.
+ LL_WARNS() << "Joint " << bone_info->mBoneName << " not found." << LL_ENDL;
+ return FALSE;
+ }
- // store it
- mJointScales[joint] = bone_info->mScaleDeformation;
+ // store it
+ mJointScales[joint] = bone_info->mScaleDeformation;
- // apply to children that need to inherit it
- for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
- iter != joint->mChildren.end(); ++iter)
- {
- LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
- if (child_joint->inheritScale())
- {
- LLVector3 childDeformation = LLVector3(child_joint->getScale());
- childDeformation.scaleVec(bone_info->mScaleDeformation);
- mJointScales[child_joint] = childDeformation;
- }
- }
+ // apply to children that need to inherit it
+ for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
+ iter != joint->mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
+ if (child_joint->inheritScale())
+ {
+ LLVector3 childDeformation = LLVector3(child_joint->getScale());
+ childDeformation.scaleVec(bone_info->mScaleDeformation);
+ mJointScales[child_joint] = childDeformation;
+ }
+ }
- if (bone_info->mHasPositionDeformation)
- {
- if (mJointOffsets.find(joint) != mJointOffsets.end())
- {
- LL_WARNS() << "Offset deformation already supplied for joint " << joint->getName() << "." << LL_ENDL;
- }
- mJointOffsets[joint] = bone_info->mPositionDeformation;
- }
+ if (bone_info->mHasPositionDeformation)
+ {
+ mJointOffsets[joint] = bone_info->mPositionDeformation;
}
- return TRUE;
+ }
+ return TRUE;
}
/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
@@ -197,42 +192,52 @@ static LLTrace::BlockTimerStatHandle FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal
void LLPolySkeletalDistortion::apply( ESex avatar_sex )
{
- LL_RECORD_BLOCK_TIME(FTM_POLYSKELETAL_DISTORTION_APPLY);
-
- F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
-
- LLJoint* joint;
- joint_vec_map_t::iterator iter;
-
- for (iter = mJointScales.begin();
- iter != mJointScales.end();
- iter++)
- {
- joint = iter->first;
- LLVector3 newScale = joint->getScale();
- LLVector3 scaleDelta = iter->second;
- newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
- //An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached
- // needed? // joint->storeScaleForReset( newScale );
- joint->setScale(newScale);
- }
-
- for (iter = mJointOffsets.begin();
- iter != mJointOffsets.end();
- iter++)
- {
- joint = iter->first;
- LLVector3 newPosition = joint->getPosition();
- LLVector3 positionDelta = iter->second;
- newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
- joint->setPosition(newPosition);
- }
-
- if (mLastWeight != mCurWeight && !mIsAnimating)
- {
- mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1);
- }
- mLastWeight = mCurWeight;
+ LL_RECORD_BLOCK_TIME(FTM_POLYSKELETAL_DISTORTION_APPLY);
+
+ F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
+
+ LLJoint* joint;
+ joint_vec_map_t::iterator iter;
+
+ for (iter = mJointScales.begin();
+ iter != mJointScales.end();
+ iter++)
+ {
+ joint = iter->first;
+ LLVector3 newScale = joint->getScale();
+ LLVector3 scaleDelta = iter->second;
+ LLVector3 offset = (effective_weight - mLastWeight) * scaleDelta;
+ newScale = newScale + offset;
+ //An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached
+ // needed?
+ // joint->storeScaleForReset( newScale );
+
+ // BENTO for detailed stack tracing of params.
+ std::stringstream ostr;
+ ostr << "LLPolySkeletalDistortion::apply, id " << getID() << " " << getName() << " effective wt " << effective_weight << " last wt " << mLastWeight << " scaleDelta " << scaleDelta << " offset " << offset;
+ LLScopedContextString str(ostr.str());
+
+ joint->setScale(newScale, true);
+ }
+
+ for (iter = mJointOffsets.begin();
+ iter != mJointOffsets.end();
+ iter++)
+ {
+ joint = iter->first;
+ LLVector3 newPosition = joint->getPosition();
+ LLVector3 positionDelta = iter->second;
+ newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
+ // SL-315
+ bool allow_attachment_pos_overrides = true;
+ joint->setPosition(newPosition, allow_attachment_pos_overrides);
+ }
+
+ if (mLastWeight != effective_weight && !mIsAnimating)
+ {
+ mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1);
+ }
+ mLastWeight = effective_weight;
}
diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
index 5ca9f55ac8..63069adcc8 100644
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -173,7 +173,7 @@ void LLWearable::createVisualParams(LLAvatarAppearance *avatarp)
{
if( !param->linkDrivenParams(boost::bind(param_function,avatarp,_1 ), true))
{
- LL_WARNS() << "could not link driven params for wearable " << getName() << " id: " << param->getID() << LL_ENDL;
+ LL_DEBUGS("Avatar") << "could not link driven params for wearable " << getName() << " id: " << param->getID() << LL_ENDL;
continue;
}
}