Bento hell and back, and back to hell, and back.
This commit is contained in:
@@ -44,6 +44,8 @@
|
||||
#include "llstl.h"
|
||||
#include "lltexglobalcolor.h"
|
||||
#include "llwearabledata.h"
|
||||
#include "boost/bind.hpp"
|
||||
#include "boost/tokenizer.hpp"
|
||||
|
||||
|
||||
#if LL_MSVC
|
||||
@@ -87,8 +89,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 +123,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;
|
||||
};
|
||||
@@ -180,7 +186,9 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
|
||||
mPelvisToFoot(0.f),
|
||||
mHeadOffset(),
|
||||
mRoot(NULL),
|
||||
mWearableData(wearable_data)
|
||||
mWearableData(wearable_data),
|
||||
mNumBones(0),
|
||||
mIsBuilt(FALSE)
|
||||
{
|
||||
llassert_always(mWearableData);
|
||||
mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES);
|
||||
@@ -193,8 +201,6 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
|
||||
mBakedTextureDatas[i].mMaskTexName = 0;
|
||||
mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i);
|
||||
}
|
||||
|
||||
mIsBuilt = FALSE;
|
||||
}
|
||||
|
||||
// virtual
|
||||
@@ -327,36 +333,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;
|
||||
@@ -369,16 +388,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);
|
||||
@@ -441,11 +463,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
|
||||
@@ -505,7 +572,8 @@ void LLAvatarAppearance::computeBodySize()
|
||||
if (new_body_size != mBodySize || old_offset != mAvatarOffset)
|
||||
{
|
||||
mBodySize = new_body_size;
|
||||
bodySizeChanged();
|
||||
|
||||
compareJointStateMaps(mLastBodySizeState, mCurrBodySizeState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,7 +609,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;
|
||||
@@ -557,6 +625,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);
|
||||
@@ -571,7 +645,7 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
|
||||
{
|
||||
if (volume_num >= (S32)mCollisionVolumes.size())
|
||||
{
|
||||
LL_WARNS() << "Too many bones" << LL_ENDL;
|
||||
LL_WARNS() << "Too many collision volumes" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
joint = (mCollisionVolumes[volume_num]);
|
||||
@@ -579,26 +653,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)
|
||||
@@ -618,18 +700,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.empty() || !mSkeleton[0])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (mSkeleton.size() != num)
|
||||
{
|
||||
clearSkeleton();
|
||||
mSkeleton = avatar_joint_list_t(num,NULL);
|
||||
mNumBones = num;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -642,6 +718,8 @@ BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info)
|
||||
{
|
||||
if (!info)
|
||||
return FALSE;
|
||||
LL_DEBUGS("BVH") << "numBones " << info->mNumBones << " numCollisionVolumes " << info->mNumCollisionVolumes << LL_ENDL;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// allocate joints
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -668,8 +746,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;
|
||||
@@ -1128,6 +1206,7 @@ BOOL LLAvatarAppearance::loadMeshNodes()
|
||||
{
|
||||
// This should never happen
|
||||
LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1264,6 +1343,10 @@ LLJoint *LLAvatarAppearance::getCharacterJoint( U32 num )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (!mSkeleton[num])
|
||||
{
|
||||
mSkeleton[num] = createAvatarJoint();
|
||||
}
|
||||
return mSkeleton[num];
|
||||
}
|
||||
|
||||
@@ -1563,21 +1646,24 @@ LLTexLayerSet* LLAvatarAppearance::getAvatarLayerSet(EBakedTextureIndex baked_in
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num )
|
||||
{
|
||||
delete_and_clear(mCollisionVolumes);
|
||||
mCollisionVolumes.reserve(num);
|
||||
|
||||
LLAvatarJointCollisionVolume* cv;
|
||||
for (U32 i = 0; i < num; ++i)
|
||||
if(num != mCollisionVolumes.size() )
|
||||
{
|
||||
cv = new LLAvatarJointCollisionVolume();
|
||||
if (cv)
|
||||
delete_and_clear(mCollisionVolumes);
|
||||
mCollisionVolumes.reserve(num);
|
||||
|
||||
LLAvatarJointCollisionVolume* cv;
|
||||
for (U32 i = 0; i < num; ++i)
|
||||
{
|
||||
mCollisionVolumes.push_back(cv);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete_and_clear(mCollisionVolumes);
|
||||
return false;
|
||||
cv = new LLAvatarJointCollisionVolume();
|
||||
if (cv)
|
||||
{
|
||||
mCollisionVolumes.push_back(cv);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete_and_clear(mCollisionVolumes);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
@@ -1597,6 +1683,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"))
|
||||
{
|
||||
@@ -1634,6 +1723,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");
|
||||
@@ -1689,6 +1792,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
|
||||
@@ -1719,7 +1870,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro
|
||||
{
|
||||
LL_WARNS() << "Unknown param type." << LL_ENDL;
|
||||
}
|
||||
continue;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo;
|
||||
@@ -1744,7 +1895,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");
|
||||
@@ -1752,7 +1903,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");
|
||||
@@ -1778,7 +1929,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");
|
||||
@@ -1864,7 +2015,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
|
||||
{
|
||||
LL_WARNS() << "Unknown param type." << LL_ENDL;
|
||||
}
|
||||
continue;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo();
|
||||
@@ -2025,7 +2176,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");
|
||||
@@ -2033,7 +2184,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");
|
||||
@@ -2041,7 +2192,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.
|
||||
|
||||
@@ -66,6 +66,7 @@ public:
|
||||
LLAvatarAppearance(LLWearableData* wearable_data);
|
||||
virtual ~LLAvatarAppearance();
|
||||
|
||||
static void initClass(const std::string& avatar_file_name, const std::string& skeleton_file_name); // initializes static members
|
||||
static void initClass(); // initializes static members
|
||||
static void cleanupClass(); // Cleanup data that's only init'd once per class.
|
||||
virtual void initInstance(); // Called after construction to initialize the instance.
|
||||
@@ -132,6 +133,7 @@ protected:
|
||||
virtual LLAvatarJoint* createAvatarJoint() = 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; }
|
||||
@@ -139,17 +141,27 @@ public:
|
||||
LLVector3 mHeadOffset; // current head position
|
||||
LLAvatarJoint *mRoot;
|
||||
|
||||
typedef std::map<std::string, LLJoint*> joint_map_t;
|
||||
typedef std::vector<std::pair<char[64], 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);
|
||||
virtual void buildCharacter();
|
||||
virtual BOOL loadAvatar();
|
||||
virtual void bodySizeChanged() = 0;
|
||||
|
||||
BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num);
|
||||
BOOL allocateCharacterJoints(U32 num);
|
||||
@@ -157,9 +169,10 @@ protected:
|
||||
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.
|
||||
@@ -343,6 +356,7 @@ protected:
|
||||
// Collision volumes
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
S32 mNumBones;
|
||||
std::vector<LLAvatarJointCollisionVolume*> mCollisionVolumes;
|
||||
protected:
|
||||
BOOL allocateCollisionVolumes(U32 num);
|
||||
|
||||
@@ -53,19 +53,18 @@ LLAvatarJoint::LLAvatarJoint() :
|
||||
init();
|
||||
}
|
||||
|
||||
LLAvatarJoint::LLAvatarJoint(S32 joint_num) :
|
||||
LLJoint(joint_num)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) :
|
||||
LLJoint(name, parent)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
LLAvatarJoint::LLAvatarJoint(S32 joint_num) :
|
||||
LLJoint(joint_num)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
void LLAvatarJoint::init()
|
||||
{
|
||||
mValid = FALSE;
|
||||
|
||||
@@ -57,6 +57,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()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLJoint *getBaseSkeletonAncestor(LLJoint* 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 ancestor;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// totalSkinOffset()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLVector3 totalSkinOffset(LLJoint *joint)
|
||||
{
|
||||
LLVector3 totalOffset;
|
||||
while (joint)
|
||||
{
|
||||
if (joint->getSupport() == LLJoint::SUPPORT_BASE)
|
||||
{
|
||||
totalOffset += joint->getSkinOffset();
|
||||
}
|
||||
joint = joint->getParent();
|
||||
}
|
||||
return totalOffset;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLAvatarJointMesh::LLSkinJoint
|
||||
@@ -83,29 +118,24 @@ LLSkinJoint::~LLSkinJoint()
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLSkinJoint::setupSkinJoint()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLSkinJoint::setupSkinJoint( LLJoint *joint)
|
||||
BOOL LLSkinJoint::setupSkinJoint( LLJoint *joint)
|
||||
{
|
||||
|
||||
// find the named joint
|
||||
if (!(mJoint = joint))
|
||||
if (!(mJoint = dynamic_cast<LLAvatarJoint*>(joint)))
|
||||
{
|
||||
LL_INFOS() << "Can't find joint" << LL_ENDL;
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// compute the inverse root skin matrix
|
||||
mRootToJointSkinOffset.clearVec();
|
||||
mRootToParentJointSkinOffset.clearVec();
|
||||
mRootToJointSkinOffset = totalSkinOffset((LLAvatarJoint*)joint);
|
||||
mRootToJointSkinOffset = -mRootToJointSkinOffset;
|
||||
|
||||
do
|
||||
{
|
||||
mRootToJointSkinOffset -= joint->getSkinOffset();
|
||||
} while (joint = joint->getParent());
|
||||
//mRootToParentJointSkinOffset = totalSkinOffset((LLAvatarJoint*)joint->getParent());
|
||||
mRootToParentJointSkinOffset = totalSkinOffset(getBaseSkeletonAncestor((LLAvatarJoint*)joint));
|
||||
mRootToParentJointSkinOffset = -mRootToParentJointSkinOffset;
|
||||
|
||||
mRootToParentJointSkinOffset = mRootToJointSkinOffset;
|
||||
mRootToParentJointSkinOffset += mJoint->getSkinOffset();
|
||||
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -314,9 +344,9 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh )
|
||||
if (!mMesh->isLOD())
|
||||
{
|
||||
setupJoint(getRoot());
|
||||
LL_DEBUGS("Avatar") << getName() << " joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL;
|
||||
}
|
||||
|
||||
LL_DEBUGS() << "joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -324,10 +354,8 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh )
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLAvatarJointMesh::setupJoint(LLJoint* current_joint)
|
||||
{
|
||||
// LL_INFOS() << "Mesh: " << getName() << LL_ENDL;
|
||||
|
||||
// S32 joint_count = 0;
|
||||
U32 sj;
|
||||
|
||||
for (sj=0; sj<mNumSkinJoints; sj++)
|
||||
{
|
||||
LLSkinJoint &js = mSkinJoints[sj];
|
||||
@@ -338,25 +366,30 @@ void LLAvatarJointMesh::setupJoint(LLJoint* 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 == ¤t_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
|
||||
LLJoint* jointp = js.mJoint;
|
||||
mMesh->mJointRenderData.push_back(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
|
||||
// LL_INFOS() << "joint " << joint_count << js.mJoint->getName() << LL_ENDL;
|
||||
// joint_count++;
|
||||
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(¤t_joint->getParent()->getWorldMatrix(), NULL));
|
||||
// LL_INFOS() << "joint " << joint_count << current_joint->getParent()->getName() << LL_ENDL;
|
||||
// joint_count++;
|
||||
mMesh->mJointRenderData.push_back(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js));
|
||||
// LL_INFOS() << "joint " << joint_count << current_joint->getName() << LL_ENDL;
|
||||
// joint_count++;
|
||||
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(¤t_joint->getWorldMatrix(), &js));
|
||||
LL_DEBUGS("Avatar") << "add2 joint[" << (jrd.size()-1) << "] = " << current_joint->getName() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class LLSkinJoint
|
||||
public:
|
||||
LLSkinJoint();
|
||||
~LLSkinJoint();
|
||||
void setupSkinJoint( LLJoint *joint);
|
||||
BOOL setupSkinJoint( LLJoint *joint);
|
||||
|
||||
LLJoint* mJoint;
|
||||
LLVector3 mRootToJointSkinOffset;
|
||||
@@ -124,6 +124,9 @@ public:
|
||||
// Sets up joint matrix data for rendering
|
||||
void setupJoint(LLJoint* current_joint);
|
||||
|
||||
// Render time method to upload batches of joint matrices
|
||||
void uploadJointMatrices();
|
||||
|
||||
// Sets ID for picking
|
||||
void setMeshID( S32 id ) {mMeshID = id;}
|
||||
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -130,6 +130,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);
|
||||
@@ -137,7 +141,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.
|
||||
|
||||
@@ -680,8 +680,8 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
|
||||
if (!mMorphData)
|
||||
{
|
||||
const std::string driven_tag = "_Driven";
|
||||
size_t pos = morph_param_name.find(driven_tag);
|
||||
if (pos != std::string::npos)
|
||||
U32 pos = morph_param_name.find(driven_tag);
|
||||
if (pos > 0)
|
||||
{
|
||||
morph_param_name = morph_param_name.substr(0,pos);
|
||||
mMorphData = mMesh->getMorphData(morph_param_name);
|
||||
@@ -1027,6 +1027,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()
|
||||
|
||||
@@ -186,6 +186,7 @@ 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)
|
||||
{
|
||||
|
||||
@@ -155,7 +155,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
|
||||
if (!joint)
|
||||
{
|
||||
LL_WARNS() << "Joint " << bone_info->mBoneName << " not found." << LL_ENDL;
|
||||
continue;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (mJointScales.find(joint) != mJointScales.end())
|
||||
@@ -205,10 +205,10 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
|
||||
{
|
||||
LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY);
|
||||
|
||||
F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
|
||||
F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
|
||||
|
||||
LLJoint* joint;
|
||||
joint_vec_map_t::iterator iter;
|
||||
LLJoint* joint;
|
||||
joint_vec_map_t::iterator iter;
|
||||
|
||||
for (iter = mJointScales.begin();
|
||||
iter != mJointScales.end();
|
||||
@@ -216,9 +216,18 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
|
||||
{
|
||||
joint = iter->first;
|
||||
LLVector3 newScale = joint->getScale();
|
||||
LLVector3 scaleDelta = iter->second;
|
||||
newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
|
||||
joint->setScale(newScale);
|
||||
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;
|
||||
|
||||
joint->setScale(newScale, true);
|
||||
}
|
||||
|
||||
for (iter = mJointOffsets.begin();
|
||||
@@ -229,14 +238,16 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
|
||||
LLVector3 newPosition = joint->getPosition();
|
||||
LLVector3 positionDelta = iter->second;
|
||||
newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
|
||||
joint->setPosition(newPosition);
|
||||
}
|
||||
// SL-315
|
||||
bool allow_attachment_pos_overrides = true;
|
||||
joint->setPosition(newPosition, allow_attachment_pos_overrides);
|
||||
}
|
||||
|
||||
if (mLastWeight != mCurWeight && !mIsAnimating)
|
||||
if (mLastWeight != effective_weight && !mIsAnimating)
|
||||
{
|
||||
mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1);
|
||||
}
|
||||
mLastWeight = mCurWeight;
|
||||
mLastWeight = effective_weight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -279,7 +279,9 @@ LLEyeMotion::LLEyeMotion(LLUUID const& id, LLMotionController* controller) : AIM
|
||||
mName = "eye_rot";
|
||||
|
||||
mLeftEyeState = new LLJointState;
|
||||
mAltLeftEyeState = new LLJointState;
|
||||
mRightEyeState = new LLJointState;
|
||||
mAltRightEyeState = new LLJointState;
|
||||
}
|
||||
|
||||
|
||||
@@ -312,32 +314,135 @@ LLMotion::LLMotionInitStatus LLEyeMotion::onInitialize(LLCharacter *character)
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
mAltLeftEyeState->setJoint( character->getJoint("mFaceEyeAltLeft") );
|
||||
if ( ! mAltLeftEyeState->getJoint() )
|
||||
{
|
||||
LL_INFOS() << getName() << ": Can't get alt left eyeball joint." << LL_ENDL;
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
mRightEyeState->setJoint( character->getJoint("mEyeRight") );
|
||||
if ( ! mRightEyeState->getJoint() )
|
||||
{
|
||||
LL_INFOS() << getName() << ": Can't get Right eyeball joint." << LL_ENDL;
|
||||
LL_INFOS() << getName() << ": Can't get right eyeball joint." << LL_ENDL;
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
mAltRightEyeState->setJoint( character->getJoint("mFaceEyeAltRight") );
|
||||
if ( ! mAltRightEyeState->getJoint() )
|
||||
{
|
||||
LL_INFOS() << getName() << ": Can't get alt right eyeball joint." << LL_ENDL;
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
mLeftEyeState->setUsage(LLJointState::ROT);
|
||||
mAltLeftEyeState->setUsage(LLJointState::ROT);
|
||||
|
||||
mRightEyeState->setUsage(LLJointState::ROT);
|
||||
mAltRightEyeState->setUsage(LLJointState::ROT);
|
||||
|
||||
addJointState( mLeftEyeState );
|
||||
addJointState( mAltLeftEyeState );
|
||||
|
||||
addJointState( mRightEyeState );
|
||||
addJointState( mAltRightEyeState );
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLEyeMotion::adjustEyeTarget()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLEyeMotion::adjustEyeTarget(LLVector3* targetPos, LLJointState& left_eye_state, LLJointState& right_eye_state)
|
||||
{
|
||||
// Compute eye rotation.
|
||||
BOOL has_eye_target = FALSE;
|
||||
LLQuaternion target_eye_rot;
|
||||
LLVector3 eye_look_at;
|
||||
F32 vergence;
|
||||
|
||||
if (targetPos)
|
||||
{
|
||||
LLVector3 skyward(0.f, 0.f, 1.f);
|
||||
LLVector3 left;
|
||||
LLVector3 up;
|
||||
|
||||
eye_look_at = *targetPos;
|
||||
has_eye_target = TRUE;
|
||||
F32 lookAtDistance = eye_look_at.normVec();
|
||||
|
||||
left.setVec(skyward % eye_look_at);
|
||||
up.setVec(eye_look_at % left);
|
||||
|
||||
target_eye_rot = LLQuaternion(eye_look_at, left, up);
|
||||
// convert target rotation to head-local coordinates
|
||||
target_eye_rot *= ~mHeadJoint->getWorldRotation();
|
||||
// eliminate any Euler roll - we're lucky that roll is applied last.
|
||||
F32 roll, pitch, yaw;
|
||||
target_eye_rot.getEulerAngles(&roll, &pitch, &yaw);
|
||||
target_eye_rot.setQuat(0.0f, pitch, yaw);
|
||||
// constrain target orientation to be in front of avatar's face
|
||||
target_eye_rot.constrain(EYE_ROT_LIMIT_ANGLE);
|
||||
|
||||
// calculate vergence
|
||||
F32 interocular_dist = (left_eye_state.getJoint()->getWorldPosition() - right_eye_state.getJoint()->getWorldPosition()).magVec();
|
||||
vergence = -atan2((interocular_dist / 2.f), lookAtDistance);
|
||||
llclamp(vergence, -F_PI_BY_TWO, 0.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
target_eye_rot = LLQuaternion::DEFAULT;
|
||||
vergence = 0.f;
|
||||
}
|
||||
|
||||
//RN: subtract 4 degrees to account for foveal angular offset relative to pupil
|
||||
vergence += 4.f * DEG_TO_RAD;
|
||||
|
||||
// calculate eye jitter
|
||||
LLQuaternion eye_jitter_rot;
|
||||
|
||||
// vergence not too high...
|
||||
if (vergence > -0.05f)
|
||||
{
|
||||
//...go ahead and jitter
|
||||
eye_jitter_rot.setQuat(0.f, mEyeJitterPitch + mEyeLookAwayPitch, mEyeJitterYaw + mEyeLookAwayYaw);
|
||||
}
|
||||
else
|
||||
{
|
||||
//...or don't
|
||||
eye_jitter_rot.loadIdentity();
|
||||
}
|
||||
|
||||
// calculate vergence of eyes as an object gets closer to the avatar's head
|
||||
LLQuaternion vergence_quat;
|
||||
|
||||
if (has_eye_target)
|
||||
{
|
||||
vergence_quat.setQuat(vergence, LLVector3(0.f, 0.f, 1.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
vergence_quat.loadIdentity();
|
||||
}
|
||||
|
||||
// calculate eye rotations
|
||||
LLQuaternion left_eye_rot = target_eye_rot;
|
||||
left_eye_rot = vergence_quat * eye_jitter_rot * left_eye_rot;
|
||||
|
||||
LLQuaternion right_eye_rot = target_eye_rot;
|
||||
vergence_quat.transQuat();
|
||||
right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot;
|
||||
|
||||
left_eye_state.setRotation( left_eye_rot );
|
||||
right_eye_state.setRotation( right_eye_rot );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLEyeMotion::onUpdate()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
{
|
||||
// Compute eye rotation.
|
||||
LLQuaternion target_eye_rot;
|
||||
LLVector3 eye_look_at;
|
||||
F32 vergence;
|
||||
|
||||
//calculate jitter
|
||||
if (mEyeJitterTimer.getElapsedTimeF32() > mEyeJitterTime)
|
||||
{
|
||||
@@ -410,83 +515,10 @@ BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
}
|
||||
}
|
||||
|
||||
BOOL has_eye_target = FALSE;
|
||||
LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint");
|
||||
|
||||
if (targetPos)
|
||||
{
|
||||
LLVector3 skyward(0.f, 0.f, 1.f);
|
||||
LLVector3 left;
|
||||
LLVector3 up;
|
||||
|
||||
eye_look_at = *targetPos;
|
||||
has_eye_target = TRUE;
|
||||
F32 lookAtDistance = eye_look_at.normVec();
|
||||
|
||||
left.setVec(skyward % eye_look_at);
|
||||
up.setVec(eye_look_at % left);
|
||||
|
||||
target_eye_rot = LLQuaternion(eye_look_at, left, up);
|
||||
// convert target rotation to head-local coordinates
|
||||
target_eye_rot *= ~mHeadJoint->getWorldRotation();
|
||||
// eliminate any Euler roll - we're lucky that roll is applied last.
|
||||
F32 roll, pitch, yaw;
|
||||
target_eye_rot.getEulerAngles(&roll, &pitch, &yaw);
|
||||
target_eye_rot.setQuat(0.0f, pitch, yaw);
|
||||
// constrain target orientation to be in front of avatar's face
|
||||
target_eye_rot.constrain(EYE_ROT_LIMIT_ANGLE);
|
||||
|
||||
// calculate vergence
|
||||
F32 interocular_dist = (mLeftEyeState->getJoint()->getWorldPosition() - mRightEyeState->getJoint()->getWorldPosition()).magVec();
|
||||
vergence = -atan2((interocular_dist / 2.f), lookAtDistance);
|
||||
llclamp(vergence, -F_PI_BY_TWO, 0.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
target_eye_rot = LLQuaternion::DEFAULT;
|
||||
vergence = 0.f;
|
||||
}
|
||||
|
||||
//RN: subtract 4 degrees to account for foveal angular offset relative to pupil
|
||||
vergence += 4.f * DEG_TO_RAD;
|
||||
|
||||
// calculate eye jitter
|
||||
LLQuaternion eye_jitter_rot;
|
||||
|
||||
// vergence not too high...
|
||||
if (vergence > -0.05f)
|
||||
{
|
||||
//...go ahead and jitter
|
||||
eye_jitter_rot.setQuat(0.f, mEyeJitterPitch + mEyeLookAwayPitch, mEyeJitterYaw + mEyeLookAwayYaw);
|
||||
}
|
||||
else
|
||||
{
|
||||
//...or don't
|
||||
eye_jitter_rot.loadIdentity();
|
||||
}
|
||||
|
||||
// calculate vergence of eyes as an object gets closer to the avatar's head
|
||||
LLQuaternion vergence_quat;
|
||||
|
||||
if (has_eye_target)
|
||||
{
|
||||
vergence_quat.setQuat(vergence, LLVector3(0.f, 0.f, 1.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
vergence_quat.loadIdentity();
|
||||
}
|
||||
|
||||
// calculate eye rotations
|
||||
LLQuaternion left_eye_rot = target_eye_rot;
|
||||
left_eye_rot = vergence_quat * eye_jitter_rot * left_eye_rot;
|
||||
|
||||
LLQuaternion right_eye_rot = target_eye_rot;
|
||||
vergence_quat.transQuat();
|
||||
right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot;
|
||||
|
||||
mLeftEyeState->setRotation( left_eye_rot );
|
||||
mRightEyeState->setRotation( right_eye_rot );
|
||||
adjustEyeTarget(targetPos, *mLeftEyeState, *mRightEyeState);
|
||||
adjustEyeTarget(targetPos, *mAltLeftEyeState, *mAltRightEyeState);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -503,12 +535,24 @@ void LLEyeMotion::onDeactivate()
|
||||
joint->setRotation(LLQuaternion::DEFAULT);
|
||||
}
|
||||
|
||||
joint = mAltLeftEyeState->getJoint();
|
||||
if (joint)
|
||||
{
|
||||
joint->setRotation(LLQuaternion::DEFAULT);
|
||||
}
|
||||
|
||||
joint = mRightEyeState->getJoint();
|
||||
if (joint)
|
||||
{
|
||||
joint->setRotation(LLQuaternion::DEFAULT);
|
||||
}
|
||||
|
||||
joint = mAltRightEyeState->getJoint();
|
||||
if (joint)
|
||||
{
|
||||
joint->setRotation(LLQuaternion::DEFAULT);
|
||||
}
|
||||
|
||||
AIMaskedMotion::onDeactivate();
|
||||
}
|
||||
|
||||
|
||||
@@ -169,6 +169,9 @@ public:
|
||||
// must return true to indicate success and be available for activation
|
||||
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
|
||||
|
||||
|
||||
void adjustEyeTarget(LLVector3* targetPos, LLJointState& left_eye_state, LLJointState& right_eye_state);
|
||||
|
||||
// called per time step
|
||||
// must return TRUE while it is active, and
|
||||
// must return FALSE when the motion is completed.
|
||||
@@ -186,6 +189,8 @@ public:
|
||||
LLJoint *mHeadJoint;
|
||||
LLPointer<LLJointState> mLeftEyeState;
|
||||
LLPointer<LLJointState> mRightEyeState;
|
||||
LLPointer<LLJointState> mAltLeftEyeState;
|
||||
LLPointer<LLJointState> mAltRightEyeState;
|
||||
|
||||
LLFrameTimer mEyeJitterTimer;
|
||||
F32 mEyeJitterTime;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "lljoint.h"
|
||||
|
||||
#include "llmath.h"
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
S32 LLJoint::sNumUpdates = 0;
|
||||
S32 LLJoint::sNumTouches = 0;
|
||||
@@ -42,7 +43,7 @@ bool attachment_map_iter_compare_key(const T& a, const T& b)
|
||||
return a.first < b.first;
|
||||
}
|
||||
|
||||
bool LLPosOverrideMap::findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const
|
||||
bool LLVector3OverrideMap::findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const
|
||||
{
|
||||
pos = LLVector3(0,0,0);
|
||||
mesh_id = LLUUID();
|
||||
@@ -60,7 +61,7 @@ bool LLPosOverrideMap::findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const
|
||||
return found;
|
||||
}
|
||||
|
||||
void LLPosOverrideMap::showJointPosOverrides( std::ostringstream& os ) const
|
||||
void LLVector3OverrideMap::showJointVector3Overrides( std::ostringstream& os ) const
|
||||
{
|
||||
map_type::const_iterator max_it = std::max_element(m_map.begin(),
|
||||
m_map.end(),
|
||||
@@ -73,23 +74,23 @@ void LLPosOverrideMap::showJointPosOverrides( std::ostringstream& os ) const
|
||||
}
|
||||
}
|
||||
|
||||
U32 LLPosOverrideMap::count() const
|
||||
U32 LLVector3OverrideMap::count() const
|
||||
{
|
||||
return m_map.size();
|
||||
}
|
||||
|
||||
void LLPosOverrideMap::add(const LLUUID& mesh_id, const LLVector3& pos)
|
||||
void LLVector3OverrideMap::add(const LLUUID& mesh_id, const LLVector3& pos)
|
||||
{
|
||||
m_map[mesh_id] = pos;
|
||||
}
|
||||
|
||||
bool LLPosOverrideMap::remove(const LLUUID& mesh_id)
|
||||
bool LLVector3OverrideMap::remove(const LLUUID& mesh_id)
|
||||
{
|
||||
U32 remove_count = m_map.erase(mesh_id);
|
||||
return (remove_count > 0);
|
||||
}
|
||||
|
||||
void LLPosOverrideMap::clear()
|
||||
void LLVector3OverrideMap::clear()
|
||||
{
|
||||
m_map.clear();
|
||||
}
|
||||
@@ -107,6 +108,8 @@ void LLJoint::init()
|
||||
mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
|
||||
mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
|
||||
mUpdateXform = TRUE;
|
||||
mSupport = SUPPORT_BASE;
|
||||
mEnd = LLVector3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
LLJoint::LLJoint() :
|
||||
@@ -129,7 +132,7 @@ LLJoint::LLJoint(S32 joint_num) :
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLJoint::LLJoint(const std::string &name, LLJoint *parent) :
|
||||
mJointNum(0)
|
||||
mJointNum(-2)
|
||||
{
|
||||
init();
|
||||
mUpdateXform = FALSE;
|
||||
@@ -169,6 +172,27 @@ void LLJoint::setup(const std::string &name, LLJoint *parent)
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// setSupport()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLJoint::setSupport(const std::string& support_name)
|
||||
{
|
||||
if (support_name == "extended")
|
||||
{
|
||||
setSupport(SUPPORT_EXTENDED);
|
||||
}
|
||||
else if (support_name == "base")
|
||||
{
|
||||
setSupport(SUPPORT_BASE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "unknown support string " << support_name << LL_ENDL;
|
||||
setSupport(SUPPORT_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// touch()
|
||||
// Sets all dirty flags for all children, recursively.
|
||||
@@ -194,6 +218,18 @@ void LLJoint::touch(U32 flags)
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// setJointNum()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLJoint::setJointNum(S32 joint_num)
|
||||
{
|
||||
mJointNum = joint_num;
|
||||
if (mJointNum + 2 >= LL_CHARACTER_MAX_ANIMATED_JOINTS)
|
||||
{
|
||||
LL_INFOS() << "LL_CHARACTER_MAX_ANIMATED_JOINTS needs to be increased" << LL_ENDL;
|
||||
LL_ERRS() << "joint_num " << joint_num << " + 2 is too large for " << LL_CHARACTER_MAX_ANIMATED_JOINTS << LL_ENDL;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// getRoot()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -239,6 +275,7 @@ void LLJoint::addChild(LLJoint* joint)
|
||||
joint->mParent->removeChild(joint);
|
||||
|
||||
mChildren.push_back(joint);
|
||||
//LL_INFOS() << getName() << " +child " << joint->getName() << LL_ENDL;
|
||||
joint->mXform.setParent(&mXform);
|
||||
joint->mParent = this;
|
||||
joint->touch();
|
||||
@@ -254,7 +291,7 @@ void LLJoint::removeChild(LLJoint* joint)
|
||||
if (iter != mChildren.end())
|
||||
{
|
||||
mChildren.erase(iter);
|
||||
|
||||
//LL_INFOS() << getName() << " -child " << joint->getName() << LL_ENDL;
|
||||
joint->mXform.setParent(NULL);
|
||||
joint->mParent = NULL;
|
||||
joint->touch();
|
||||
@@ -273,6 +310,7 @@ void LLJoint::removeAllChildren()
|
||||
child_list_t::iterator curiter = iter++;
|
||||
LLJoint* joint = *curiter;
|
||||
mChildren.erase(curiter);
|
||||
//LL_INFOS() << getName() << " -child " << joint->getName() << LL_ENDL;
|
||||
joint->mXform.setParent(NULL);
|
||||
joint->mParent = NULL;
|
||||
joint->touch();
|
||||
@@ -290,43 +328,113 @@ const LLVector3& LLJoint::getPosition()
|
||||
|
||||
bool do_debug_joint(const std::string& name)
|
||||
{
|
||||
return false;
|
||||
if (std::find(LLJoint::s_debugJointNames.begin(), LLJoint::s_debugJointNames.end(),name) != LLJoint::s_debugJointNames.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// setPosition()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::setPosition( const LLVector3& pos )
|
||||
void LLJoint::setPosition( const LLVector3& requested_pos, bool apply_attachment_overrides )
|
||||
{
|
||||
if (pos != getPosition())
|
||||
LLVector3 pos(requested_pos);
|
||||
|
||||
LLVector3 active_override;
|
||||
LLUUID mesh_id;
|
||||
if (apply_attachment_overrides && m_attachmentPosOverrides.findActiveOverride(mesh_id,active_override))
|
||||
{
|
||||
if (pos != active_override && do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << " joint " << getName() << " requested_pos " << requested_pos
|
||||
<< " overriden by attachment " << active_override << LL_ENDL;
|
||||
}
|
||||
pos = active_override;
|
||||
}
|
||||
if ((pos != getPosition()) && do_debug_joint(getName()))
|
||||
{
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL;
|
||||
}
|
||||
LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL;
|
||||
}
|
||||
mXform.setPosition(pos);
|
||||
touch(MATRIX_DIRTY | POSITION_DIRTY);
|
||||
if (pos != getPosition())
|
||||
{
|
||||
mXform.setPosition(pos);
|
||||
touch(MATRIX_DIRTY | POSITION_DIRTY);
|
||||
}
|
||||
}
|
||||
|
||||
void LLJoint::setDefaultPosition( const LLVector3& pos )
|
||||
{
|
||||
mDefaultPosition = pos;
|
||||
}
|
||||
|
||||
const LLVector3& LLJoint::getDefaultPosition() const
|
||||
{
|
||||
return mDefaultPosition;
|
||||
}
|
||||
|
||||
void LLJoint::setDefaultScale( const LLVector3& scale )
|
||||
{
|
||||
mDefaultScale = scale;
|
||||
}
|
||||
|
||||
const LLVector3& LLJoint::getDefaultScale() const
|
||||
{
|
||||
return mDefaultScale;
|
||||
}
|
||||
|
||||
void showJointPosOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info )
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << joint.m_posBeforeOverrides;
|
||||
joint.m_attachmentOverrides.showJointPosOverrides(os);
|
||||
joint.m_attachmentPosOverrides.showJointVector3Overrides(os);
|
||||
LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL;
|
||||
}
|
||||
|
||||
void showJointScaleOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info )
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << joint.m_scaleBeforeOverrides;
|
||||
joint.m_attachmentScaleOverrides.showJointVector3Overrides(os);
|
||||
LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL;
|
||||
}
|
||||
|
||||
bool LLJoint::aboveJointPosThreshold(const LLVector3& pos) const
|
||||
{
|
||||
LLVector3 diff = pos - getDefaultPosition();
|
||||
const F32 max_joint_pos_offset = 0.0001f; // 0.1 mm
|
||||
return diff.lengthSquared() > max_joint_pos_offset * max_joint_pos_offset;
|
||||
}
|
||||
|
||||
bool LLJoint::aboveJointScaleThreshold(const LLVector3& scale) const
|
||||
{
|
||||
LLVector3 diff = scale - getDefaultScale();
|
||||
const F32 max_joint_scale_offset = 0.0001f; // 0.1 mm
|
||||
return diff.lengthSquared() > max_joint_scale_offset * max_joint_scale_offset;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// addAttachmentPosOverride()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info )
|
||||
void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed )
|
||||
{
|
||||
active_override_changed = false;
|
||||
if (mesh_id.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!m_attachmentOverrides.count())
|
||||
// BENTO
|
||||
// Not clear pelvis overrides are meaningful/useful.
|
||||
//if (mName == "mPelvis")
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
LLVector3 before_pos;
|
||||
LLUUID before_mesh_id;
|
||||
bool has_active_override_before = hasAttachmentPosOverride( before_pos, before_mesh_id );
|
||||
if (!m_attachmentPosOverrides.count())
|
||||
{
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
@@ -334,32 +442,50 @@ void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh
|
||||
}
|
||||
m_posBeforeOverrides = getPosition();
|
||||
}
|
||||
m_attachmentOverrides.add(mesh_id,pos);
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentPosOverride for mesh " << mesh_id << " pos " << pos << LL_ENDL;
|
||||
}
|
||||
updatePos(av_info);
|
||||
m_attachmentPosOverrides.add(mesh_id,pos);
|
||||
LLVector3 after_pos;
|
||||
LLUUID after_mesh_id;
|
||||
hasAttachmentPosOverride(after_pos, after_mesh_id);
|
||||
if (!has_active_override_before || (after_pos != before_pos))
|
||||
{
|
||||
active_override_changed = true;
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentPosOverride for mesh " << mesh_id << " pos " << pos << LL_ENDL;
|
||||
}
|
||||
updatePos(av_info);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// removeAttachmentPosOverride()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info )
|
||||
void LLJoint::removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed )
|
||||
{
|
||||
active_override_changed = false;
|
||||
if (mesh_id.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_attachmentOverrides.remove(mesh_id))
|
||||
LLVector3 before_pos;
|
||||
LLUUID before_mesh_id;
|
||||
hasAttachmentPosOverride( before_pos, before_mesh_id );
|
||||
if (m_attachmentPosOverrides.remove(mesh_id))
|
||||
{
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
|
||||
<< " removeAttachmentPosOverride for " << mesh_id << LL_ENDL;
|
||||
showJointPosOverrides(*this, "remove", av_info);
|
||||
}
|
||||
updatePos(av_info);
|
||||
LLVector3 after_pos;
|
||||
LLUUID after_mesh_id;
|
||||
bool has_active_override_after = hasAttachmentPosOverride(after_pos, after_mesh_id);
|
||||
if (!has_active_override_after || (after_pos != before_pos))
|
||||
{
|
||||
active_override_changed = true;
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
|
||||
<< " removeAttachmentPosOverride for " << mesh_id << LL_ENDL;
|
||||
showJointPosOverrides(*this, "remove", av_info);
|
||||
}
|
||||
updatePos(av_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,7 +494,7 @@ void LLJoint::removeAttachmentPosOverride( const LLUUID& mesh_id, const std::str
|
||||
//--------------------------------------------------------------------
|
||||
bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const
|
||||
{
|
||||
return m_attachmentOverrides.findActiveOverride(mesh_id,pos);
|
||||
return m_attachmentPosOverrides.findActiveOverride(mesh_id,pos);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@@ -376,11 +502,81 @@ bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::clearAttachmentPosOverrides()
|
||||
{
|
||||
if (m_attachmentOverrides.count())
|
||||
if (m_attachmentPosOverrides.count())
|
||||
{
|
||||
m_attachmentOverrides.clear();
|
||||
m_attachmentPosOverrides.clear();
|
||||
setPosition(m_posBeforeOverrides);
|
||||
setId( LLUUID::null );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// getAllAttachmentPosOverrides()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::getAllAttachmentPosOverrides(S32& num_pos_overrides,
|
||||
std::set<LLVector3>& distinct_pos_overrides)
|
||||
{
|
||||
num_pos_overrides = m_attachmentPosOverrides.count();
|
||||
LLVector3OverrideMap::map_type::const_iterator it = m_attachmentPosOverrides.getMap().begin();
|
||||
for (; it != m_attachmentPosOverrides.getMap().end(); ++it)
|
||||
{
|
||||
distinct_pos_overrides.insert(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// getAllAttachmentScaleOverrides()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::getAllAttachmentScaleOverrides(S32& num_scale_overrides,
|
||||
std::set<LLVector3>& distinct_scale_overrides)
|
||||
{
|
||||
num_scale_overrides = m_attachmentScaleOverrides.count();
|
||||
LLVector3OverrideMap::map_type::const_iterator it = m_attachmentScaleOverrides.getMap().begin();
|
||||
for (; it != m_attachmentScaleOverrides.getMap().end(); ++it)
|
||||
{
|
||||
distinct_scale_overrides.insert(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// showAttachmentPosOverrides()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::showAttachmentPosOverrides(const std::string& av_info) const
|
||||
{
|
||||
LLVector3 active_override;
|
||||
bool has_active_override;
|
||||
LLUUID mesh_id;
|
||||
has_active_override = m_attachmentPosOverrides.findActiveOverride(mesh_id,active_override);
|
||||
U32 count = m_attachmentPosOverrides.count();
|
||||
if (count==1)
|
||||
{
|
||||
LLVector3OverrideMap::map_type::const_iterator it = m_attachmentPosOverrides.getMap().begin();
|
||||
std::string highlight = (has_active_override && (it->second == active_override)) ? "*" : "";
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
|
||||
<< " has single attachment pos override " << highlight << "" << it->second << " default " << mDefaultPosition << LL_ENDL;
|
||||
}
|
||||
else if (count>1)
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " has " << count << " attachment pos overrides" << LL_ENDL;
|
||||
std::set<LLVector3> distinct_offsets;
|
||||
LLVector3OverrideMap::map_type::const_iterator it = m_attachmentPosOverrides.getMap().begin();
|
||||
for (; it != m_attachmentPosOverrides.getMap().end(); ++it)
|
||||
{
|
||||
distinct_offsets.insert(it->second);
|
||||
}
|
||||
if (distinct_offsets.size()>1)
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "CONFLICTS, " << distinct_offsets.size() << " different values" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "no conflicts" << LL_ENDL;
|
||||
}
|
||||
std::set<LLVector3>::iterator dit = distinct_offsets.begin();
|
||||
for ( ; dit != distinct_offsets.end(); ++dit)
|
||||
{
|
||||
std::string highlight = (has_active_override && *dit == active_override) ? "*" : "";
|
||||
LL_DEBUGS("Avatar") << " POS " << highlight << "" << (*dit) << " default " << mDefaultPosition << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,19 +587,177 @@ void LLJoint::updatePos(const std::string& av_info)
|
||||
{
|
||||
LLVector3 pos, found_pos;
|
||||
LLUUID mesh_id;
|
||||
if (m_attachmentOverrides.findActiveOverride(mesh_id,found_pos))
|
||||
if (m_attachmentPosOverrides.findActiveOverride(mesh_id,found_pos))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL;
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentPosOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL;
|
||||
}
|
||||
pos = found_pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL;
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL;
|
||||
}
|
||||
pos = m_posBeforeOverrides;
|
||||
}
|
||||
setPosition(pos);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// updateScale()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::updateScale(const std::string& av_info)
|
||||
{
|
||||
LLVector3 scale, found_scale;
|
||||
LLUUID mesh_id;
|
||||
if (m_attachmentScaleOverrides.findActiveOverride(mesh_id,found_scale))
|
||||
{
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updateScale, winner of " << m_attachmentScaleOverrides.count() << " is mesh " << mesh_id << " scale " << found_scale << LL_ENDL;
|
||||
}
|
||||
scale = found_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updateScale, winner is scaleBeforeOverrides " << m_scaleBeforeOverrides << LL_ENDL;
|
||||
}
|
||||
scale = m_scaleBeforeOverrides;
|
||||
}
|
||||
setScale(scale);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// addAttachmentScaleOverride()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::addAttachmentScaleOverride( const LLVector3& scale, const LLUUID& mesh_id, const std::string& av_info )
|
||||
{
|
||||
if (mesh_id.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!m_attachmentScaleOverrides.count())
|
||||
{
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_scaleBeforeOverrides " << getScale() << LL_ENDL;
|
||||
}
|
||||
m_scaleBeforeOverrides = getScale();
|
||||
}
|
||||
m_attachmentScaleOverrides.add(mesh_id,scale);
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentScaleOverride for mesh " << mesh_id << " scale " << scale << LL_ENDL;
|
||||
}
|
||||
updateScale(av_info);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// removeAttachmentScaleOverride()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::removeAttachmentScaleOverride( const LLUUID& mesh_id, const std::string& av_info )
|
||||
{
|
||||
if (mesh_id.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_attachmentScaleOverrides.remove(mesh_id))
|
||||
{
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
|
||||
<< " removeAttachmentScaleOverride for " << mesh_id << LL_ENDL;
|
||||
showJointScaleOverrides(*this, "remove", av_info);
|
||||
}
|
||||
updateScale(av_info);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// hasAttachmentScaleOverride()
|
||||
//--------------------------------------------------------------------
|
||||
bool LLJoint::hasAttachmentScaleOverride( LLVector3& scale, LLUUID& mesh_id ) const
|
||||
{
|
||||
return m_attachmentScaleOverrides.findActiveOverride(mesh_id,scale);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// clearAttachmentScaleOverrides()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::clearAttachmentScaleOverrides()
|
||||
{
|
||||
if (m_attachmentScaleOverrides.count())
|
||||
{
|
||||
m_attachmentScaleOverrides.clear();
|
||||
setScale(m_scaleBeforeOverrides);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// showAttachmentScaleOverrides()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::showAttachmentScaleOverrides(const std::string& av_info) const
|
||||
{
|
||||
LLVector3 active_override;
|
||||
bool has_active_override;
|
||||
LLUUID mesh_id;
|
||||
has_active_override = m_attachmentScaleOverrides.findActiveOverride(mesh_id,active_override);
|
||||
U32 count = m_attachmentScaleOverrides.count();
|
||||
if (count==1)
|
||||
{
|
||||
LLVector3OverrideMap::map_type::const_iterator it = m_attachmentScaleOverrides.getMap().begin();
|
||||
std::string highlight = (has_active_override && (it->second == active_override)) ? "*" : "";
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
|
||||
<< " has single attachment scale override " << highlight << "" << it->second << " default " << mDefaultScale << LL_ENDL;
|
||||
}
|
||||
else if (count>1)
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " has " << count << " attachment scale overrides" << LL_ENDL;
|
||||
std::set<LLVector3> distinct_offsets;
|
||||
LLVector3OverrideMap::map_type::const_iterator it = m_attachmentScaleOverrides.getMap().begin();
|
||||
for (; it != m_attachmentScaleOverrides.getMap().end(); ++it)
|
||||
{
|
||||
distinct_offsets.insert(it->second);
|
||||
}
|
||||
if (distinct_offsets.size()>1)
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "CONFLICTS, " << distinct_offsets.size() << " different values" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "no conflicts" << LL_ENDL;
|
||||
}
|
||||
std::set<LLVector3>::iterator dit = distinct_offsets.begin();
|
||||
for ( ; dit != distinct_offsets.end(); ++dit)
|
||||
{
|
||||
std::string highlight = (has_active_override && *dit == active_override) ? "*" : "";
|
||||
LL_DEBUGS("Avatar") << " POS " << highlight << "" << (*dit) << " default " << mDefaultScale << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// init static
|
||||
LLJoint::debug_joint_name_t LLJoint::s_debugJointNames = debug_joint_name_t();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// setDebugJointNames
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::setDebugJointNames(const debug_joint_name_t& names)
|
||||
{
|
||||
s_debugJointNames = names;
|
||||
}
|
||||
void LLJoint::setDebugJointNames(const std::string& names_string)
|
||||
{
|
||||
debug_joint_name_t names;
|
||||
boost::split(names, names_string, boost::is_any_of(" :,"));
|
||||
setDebugJointNames(names);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// getWorldPosition()
|
||||
//--------------------------------------------------------------------
|
||||
@@ -527,13 +881,22 @@ const LLVector3& LLJoint::getScale()
|
||||
//--------------------------------------------------------------------
|
||||
// setScale()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::setScale( const LLVector3& scale )
|
||||
void LLJoint::setScale( const LLVector3& requested_scale, bool apply_attachment_overrides )
|
||||
{
|
||||
// if (mXform.getScale() != scale)
|
||||
{
|
||||
mXform.setScale(scale);
|
||||
touch();
|
||||
}
|
||||
LLVector3 scale(requested_scale);
|
||||
LLUUID mesh_id;
|
||||
LLVector3 active_override;
|
||||
if (apply_attachment_overrides && m_attachmentScaleOverrides.findActiveOverride(mesh_id,active_override))
|
||||
{
|
||||
if (scale != active_override && do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << " joint " << getName() << " requested_scale " << requested_scale
|
||||
<< " overriden by attachment " << active_override << LL_ENDL;
|
||||
}
|
||||
scale = active_override;
|
||||
}
|
||||
mXform.setScale(scale);
|
||||
touch();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -40,24 +40,33 @@
|
||||
#include "xform.h"
|
||||
|
||||
const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15;
|
||||
const U32 LL_CHARACTER_MAX_JOINTS = 32; // must be divisible by 4!
|
||||
const U32 LL_HAND_JOINT_NUM = 31;
|
||||
const U32 LL_FACE_JOINT_NUM = 30;
|
||||
// Need to set this to count of animate-able joints,
|
||||
// currently = #bones + #collision_volumes + #attachments + 2,
|
||||
// rounded to next multiple of 4.
|
||||
const U32 LL_CHARACTER_MAX_ANIMATED_JOINTS = 216; // must be divisible by 4!
|
||||
const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 110;
|
||||
|
||||
// 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_ANIMATED_JOINTS-1);
|
||||
const U32 LL_FACE_JOINT_NUM = (LL_CHARACTER_MAX_ANIMATED_JOINTS-2);
|
||||
const S32 LL_CHARACTER_MAX_PRIORITY = 7;
|
||||
const F32 LL_MAX_PELVIS_OFFSET = 5.f;
|
||||
|
||||
class LLPosOverrideMap
|
||||
class LLVector3OverrideMap
|
||||
{
|
||||
public:
|
||||
LLPosOverrideMap() {}
|
||||
LLVector3OverrideMap() {}
|
||||
bool findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const;
|
||||
void showJointPosOverrides(std::ostringstream& os) const;
|
||||
void showJointVector3Overrides(std::ostringstream& os) const;
|
||||
U32 count() const;
|
||||
void add(const LLUUID& mesh_id, const LLVector3& pos);
|
||||
bool remove(const LLUUID& mesh_id);
|
||||
void clear();
|
||||
private:
|
||||
|
||||
typedef std::map<LLUUID,LLVector3> map_type;
|
||||
const map_type& getMap() const { return m_map; }
|
||||
private:
|
||||
map_type m_map;
|
||||
};
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -85,17 +94,26 @@ public:
|
||||
POSITION_DIRTY = 0x1 << 2,
|
||||
ALL_DIRTY = 0x7
|
||||
};
|
||||
public:
|
||||
enum SupportCategory
|
||||
{
|
||||
SUPPORT_BASE,
|
||||
SUPPORT_EXTENDED
|
||||
};
|
||||
protected:
|
||||
std::string mName;
|
||||
|
||||
SupportCategory mSupport;
|
||||
|
||||
// parent joint
|
||||
LLJoint *mParent;
|
||||
|
||||
// explicit transformation members
|
||||
LLXformMatrix mXform;
|
||||
|
||||
LLUUID mId;
|
||||
|
||||
LLVector3 mDefaultPosition;
|
||||
LLVector3 mDefaultScale;
|
||||
|
||||
public:
|
||||
U32 mDirtyFlags;
|
||||
BOOL mUpdateXform;
|
||||
@@ -103,6 +121,10 @@ public:
|
||||
// describes the skin binding pose
|
||||
LLVector3 mSkinOffset;
|
||||
|
||||
// Endpoint of the bone, if applicable. This is only relevant for
|
||||
// external programs like Blender, and for diagnostic display.
|
||||
LLVector3 mEnd;
|
||||
|
||||
S32 mJointNum;
|
||||
|
||||
// child joints
|
||||
@@ -112,11 +134,21 @@ public:
|
||||
// debug statics
|
||||
static S32 sNumTouches;
|
||||
static S32 sNumUpdates;
|
||||
typedef std::set<std::string> debug_joint_name_t;
|
||||
static debug_joint_name_t s_debugJointNames;
|
||||
static void setDebugJointNames(const debug_joint_name_t& names);
|
||||
static void setDebugJointNames(const std::string& names_string);
|
||||
|
||||
LLPosOverrideMap m_attachmentOverrides;
|
||||
// Position overrides
|
||||
LLVector3OverrideMap m_attachmentPosOverrides;
|
||||
LLVector3 m_posBeforeOverrides;
|
||||
|
||||
// Scale overrides
|
||||
LLVector3OverrideMap m_attachmentScaleOverrides;
|
||||
LLVector3 m_scaleBeforeOverrides;
|
||||
|
||||
void updatePos(const std::string& av_info);
|
||||
void updateScale(const std::string& av_info);
|
||||
|
||||
public:
|
||||
LLJoint();
|
||||
@@ -138,6 +170,19 @@ public:
|
||||
const std::string& getName() const { return mName; }
|
||||
void setName( const std::string &name ) { mName = name; }
|
||||
|
||||
// joint num
|
||||
S32 getJointNum() const { return mJointNum; }
|
||||
void setJointNum(S32 joint_num);
|
||||
|
||||
// get/set support
|
||||
SupportCategory getSupport() const { return mSupport; }
|
||||
void setSupport( const SupportCategory& support) { mSupport = support; }
|
||||
void setSupport( const std::string& support_string);
|
||||
|
||||
// get/set end point
|
||||
void setEnd( const LLVector3& end) { mEnd = end; }
|
||||
const LLVector3& getEnd() const { return mEnd; }
|
||||
|
||||
// getParent
|
||||
LLJoint *getParent() { return mParent; }
|
||||
|
||||
@@ -154,10 +199,16 @@ public:
|
||||
|
||||
// get/set local position
|
||||
const LLVector3& getPosition();
|
||||
void setPosition( const LLVector3& pos );
|
||||
|
||||
void setPosition( const LLVector3& pos, bool apply_attachment_overrides = false );
|
||||
|
||||
// Tracks the default position defined by the skeleton
|
||||
void setDefaultPosition( const LLVector3& pos );
|
||||
|
||||
const LLVector3& getDefaultPosition() const;
|
||||
|
||||
// Tracks the default scale defined by the skeleton
|
||||
void setDefaultScale( const LLVector3& scale );
|
||||
const LLVector3& getDefaultScale() const;
|
||||
|
||||
// get/set world position
|
||||
LLVector3 getWorldPosition();
|
||||
LLVector3 getLastWorldPosition();
|
||||
@@ -174,7 +225,7 @@ public:
|
||||
|
||||
// get/set local scale
|
||||
const LLVector3& getScale();
|
||||
void setScale( const LLVector3& scale );
|
||||
void setScale( const LLVector3& scale, bool apply_attachment_overrides = false );
|
||||
|
||||
// get/set world matrix
|
||||
const LLMatrix4a &getWorldMatrix();
|
||||
@@ -197,21 +248,28 @@ public:
|
||||
|
||||
virtual BOOL isAnimatable() const { return TRUE; }
|
||||
|
||||
S32 getJointNum() const { return mJointNum; }
|
||||
|
||||
void addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info );
|
||||
void removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info );
|
||||
void addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed );
|
||||
void removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed );
|
||||
bool hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const;
|
||||
void clearAttachmentPosOverrides();
|
||||
void showAttachmentPosOverrides(const std::string& av_info) const;
|
||||
|
||||
//Accessor for the joint id
|
||||
LLUUID getId( void ) { return mId; }
|
||||
//Setter for the joints id
|
||||
void setId( const LLUUID& id ) { mId = id;}
|
||||
void addAttachmentScaleOverride( const LLVector3& scale, const LLUUID& mesh_id, const std::string& av_info );
|
||||
void removeAttachmentScaleOverride( const LLUUID& mesh_id, const std::string& av_info );
|
||||
bool hasAttachmentScaleOverride( LLVector3& scale, LLUUID& mesh_id ) const;
|
||||
void clearAttachmentScaleOverrides();
|
||||
void showAttachmentScaleOverrides(const std::string& av_info) const;
|
||||
|
||||
// <edit>
|
||||
std::string exportString(U32 tabs = 0);
|
||||
// </edit>
|
||||
void getAllAttachmentPosOverrides(S32& num_pos_overrides,
|
||||
std::set<LLVector3>& distinct_pos_overrides);
|
||||
void getAllAttachmentScaleOverrides(S32& num_scale_overrides,
|
||||
std::set<LLVector3>& distinct_scale_overrides);
|
||||
|
||||
// These are used in checks of whether a pos/scale override is considered significant.
|
||||
bool aboveJointPosThreshold(const LLVector3& pos) const;
|
||||
bool aboveJointScaleThreshold(const LLVector3& scale) const;
|
||||
|
||||
std::string exportString(U32 tabs);
|
||||
};
|
||||
#endif // LL_LLJOINT_H
|
||||
|
||||
|
||||
@@ -1049,7 +1049,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
|
||||
{
|
||||
case CONSTRAINT_TARGET_TYPE_GROUND:
|
||||
target_pos = mCharacter->getPosAgentFromGlobal(constraint->mGroundPos);
|
||||
target_pos += mCharacter->getHoverOffset();
|
||||
//target_pos += mCharacter->getHoverOffset();
|
||||
// LL_INFOS() << "Target Pos " << constraint->mGroundPos << " on " << mCharacter->findCollisionVolume(shared_data->mSourceConstraintVolume)->getName() << LL_ENDL;
|
||||
break;
|
||||
case CONSTRAINT_TARGET_TYPE_BODY:
|
||||
@@ -1468,7 +1468,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
LL_WARNS() << "no joints in animation" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
else if (num_motions > LL_CHARACTER_MAX_JOINTS)
|
||||
else if (num_motions > LL_CHARACTER_MAX_ANIMATED_JOINTS)
|
||||
{
|
||||
LL_WARNS() << "too many joints in animation" << LL_ENDL;
|
||||
return FALSE;
|
||||
@@ -1514,7 +1514,14 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
LLJoint *joint = mCharacter->getJoint( joint_name );
|
||||
if (joint)
|
||||
{
|
||||
S32 joint_num = joint->getJointNum();
|
||||
// LL_INFOS() << " joint: " << joint_name << LL_ENDL;
|
||||
if ((joint_num >= (S32)LL_CHARACTER_MAX_ANIMATED_JOINTS) || (joint_num < 0))
|
||||
{
|
||||
LL_WARNS() << "Joint will be omitted from animation: joint_num " << joint_num << " is outside of legal range [0-"
|
||||
<< LL_CHARACTER_MAX_ANIMATED_JOINTS << ") for joint " << joint->getName() << LL_ENDL;
|
||||
joint = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1710,6 +1717,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
if (old_version)
|
||||
{
|
||||
success = dp.unpackVector3(pos_key.mPosition, "pos");
|
||||
|
||||
//MAINT-6162
|
||||
pos_key.mPosition.mV[VX] = llclamp( pos_key.mPosition.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
|
||||
pos_key.mPosition.mV[VY] = llclamp( pos_key.mPosition.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
|
||||
pos_key.mPosition.mV[VZ] = llclamp( pos_key.mPosition.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1974,6 +1987,8 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
|
||||
LL_DEBUGS("BVH") << "serializing" << LL_ENDL;
|
||||
|
||||
success &= dp.packU16(KEYFRAME_MOTION_VERSION, "version");
|
||||
success &= dp.packU16(KEYFRAME_MOTION_SUBVERSION, "sub_version");
|
||||
success &= dp.packS32(mJointMotionList->mBasePriority, "base_priority");
|
||||
@@ -1987,6 +2002,19 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const
|
||||
success &= dp.packU32(mJointMotionList->mHandPose, "hand_pose");
|
||||
success &= dp.packU32(mJointMotionList->getNumJointMotions(), "num_joints");
|
||||
|
||||
LL_DEBUGS("BVH") << "version " << KEYFRAME_MOTION_VERSION << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "sub_version " << KEYFRAME_MOTION_SUBVERSION << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "base_priority " << mJointMotionList->mBasePriority << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "duration " << mJointMotionList->mDuration << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "emote_name " << mJointMotionList->mEmoteName << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "loop_in_point " << mJointMotionList->mLoopInPoint << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "loop_out_point " << mJointMotionList->mLoopOutPoint << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "loop " << mJointMotionList->mLoop << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "ease_in_duration " << mJointMotionList->mEaseInDuration << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "ease_out_duration " << mJointMotionList->mEaseOutDuration << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "hand_pose " << mJointMotionList->mHandPose << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << "num_joints " << mJointMotionList->getNumJointMotions() << LL_ENDL;
|
||||
|
||||
for (U32 i = 0; i < mJointMotionList->getNumJointMotions(); i++)
|
||||
{
|
||||
JointMotion* joint_motionp = mJointMotionList->getJointMotion(i);
|
||||
@@ -1994,6 +2022,7 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const
|
||||
success &= dp.packS32(joint_motionp->mPriority, "joint_priority");
|
||||
success &= dp.packS32(joint_motionp->mRotationCurve.mNumKeys, "num_rot_keys");
|
||||
|
||||
LL_DEBUGS("BVH") << "Joint " << joint_motionp->mJointName << LL_ENDL;
|
||||
for (RotationCurve::key_map_t::iterator iter = joint_motionp->mRotationCurve.mKeys.begin();
|
||||
iter != joint_motionp->mRotationCurve.mKeys.end(); ++iter)
|
||||
{
|
||||
@@ -2011,6 +2040,8 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const
|
||||
success &= dp.packU16(x, "rot_angle_x");
|
||||
success &= dp.packU16(y, "rot_angle_y");
|
||||
success &= dp.packU16(z, "rot_angle_z");
|
||||
|
||||
LL_DEBUGS("BVH") << " rot: t " << rot_key.mTime << " angles " << rot_angles.mV[VX] <<","<< rot_angles.mV[VY] <<","<< rot_angles.mV[VZ] << LL_ENDL;
|
||||
}
|
||||
|
||||
success &= dp.packS32(joint_motionp->mPositionCurve.mNumKeys, "num_pos_keys");
|
||||
@@ -2029,37 +2060,54 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const
|
||||
success &= dp.packU16(x, "pos_x");
|
||||
success &= dp.packU16(y, "pos_y");
|
||||
success &= dp.packU16(z, "pos_z");
|
||||
|
||||
LL_DEBUGS("BVH") << " pos: t " << pos_key.mTime << " pos " << pos_key.mPosition.mV[VX] <<","<< pos_key.mPosition.mV[VY] <<","<< pos_key.mPosition.mV[VZ] << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
success &= dp.packS32(mJointMotionList->mConstraints.size(), "num_constraints");
|
||||
LL_DEBUGS("BVH") << "num_constraints " << mJointMotionList->mConstraints.size() << LL_ENDL;
|
||||
for (JointMotionList::constraint_list_t::const_iterator iter = mJointMotionList->mConstraints.begin();
|
||||
iter != mJointMotionList->mConstraints.end(); ++iter)
|
||||
{
|
||||
JointConstraintSharedData* shared_constraintp = *iter;
|
||||
success &= dp.packU8(shared_constraintp->mChainLength, "chain_length");
|
||||
success &= dp.packU8(shared_constraintp->mConstraintType, "constraint_type");
|
||||
char volume_name[16]; /* Flawfinder: ignore */
|
||||
snprintf(volume_name, sizeof(volume_name), "%s", /* Flawfinder: ignore */
|
||||
char source_volume[16]; /* Flawfinder: ignore */
|
||||
snprintf(source_volume, sizeof(source_volume), "%s", /* Flawfinder: ignore */
|
||||
mCharacter->findCollisionVolume(shared_constraintp->mSourceConstraintVolume)->getName().c_str());
|
||||
success &= dp.packBinaryDataFixed((U8*)volume_name, 16, "source_volume");
|
||||
|
||||
success &= dp.packBinaryDataFixed((U8*)source_volume, 16, "source_volume");
|
||||
success &= dp.packVector3(shared_constraintp->mSourceConstraintOffset, "source_offset");
|
||||
char target_volume[16]; /* Flawfinder: ignore */
|
||||
if (shared_constraintp->mConstraintTargetType == CONSTRAINT_TARGET_TYPE_GROUND)
|
||||
{
|
||||
snprintf(volume_name,sizeof(volume_name), "%s", "GROUND"); /* Flawfinder: ignore */
|
||||
snprintf(target_volume,sizeof(target_volume), "%s", "GROUND"); /* Flawfinder: ignore */
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(volume_name, sizeof(volume_name),"%s", /* Flawfinder: ignore */
|
||||
snprintf(target_volume, sizeof(target_volume),"%s", /* Flawfinder: ignore */
|
||||
mCharacter->findCollisionVolume(shared_constraintp->mTargetConstraintVolume)->getName().c_str());
|
||||
}
|
||||
success &= dp.packBinaryDataFixed((U8*)volume_name, 16, "target_volume");
|
||||
success &= dp.packBinaryDataFixed((U8*)target_volume, 16, "target_volume");
|
||||
success &= dp.packVector3(shared_constraintp->mTargetConstraintOffset, "target_offset");
|
||||
success &= dp.packVector3(shared_constraintp->mTargetConstraintDir, "target_dir");
|
||||
success &= dp.packF32(shared_constraintp->mEaseInStartTime, "ease_in_start");
|
||||
success &= dp.packF32(shared_constraintp->mEaseInStopTime, "ease_in_stop");
|
||||
success &= dp.packF32(shared_constraintp->mEaseOutStartTime, "ease_out_start");
|
||||
success &= dp.packF32(shared_constraintp->mEaseOutStopTime, "ease_out_stop");
|
||||
|
||||
LL_DEBUGS("BVH") << " chain_length " << shared_constraintp->mChainLength << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " constraint_type " << (S32)shared_constraintp->mConstraintType << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " source_volume " << source_volume << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " source_offset " << shared_constraintp->mSourceConstraintOffset << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " target_volume " << target_volume << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " target_offset " << shared_constraintp->mTargetConstraintOffset << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " target_dir " << shared_constraintp->mTargetConstraintDir << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " ease_in_start " << shared_constraintp->mEaseInStartTime << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " ease_in_stop " << shared_constraintp->mEaseInStopTime << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " ease_out_start " << shared_constraintp->mEaseOutStartTime << LL_ENDL;
|
||||
LL_DEBUGS("BVH") << " ease_out_stop " << shared_constraintp->mEaseOutStopTime << LL_ENDL;
|
||||
}
|
||||
|
||||
return success;
|
||||
@@ -2255,7 +2303,7 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
|
||||
LLCharacter* character = *char_iter;
|
||||
|
||||
// look for an existing instance of this motion
|
||||
LLKeyframeMotion* motionp = (LLKeyframeMotion*) character->findMotion(asset_uuid);
|
||||
LLKeyframeMotion* motionp = dynamic_cast<LLKeyframeMotion*> (character->findMotion(asset_uuid));
|
||||
if (motionp)
|
||||
{
|
||||
if (0 == status)
|
||||
@@ -2270,8 +2318,8 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
|
||||
|
||||
U8* buffer = new U8[size];
|
||||
file.read((U8*)buffer, size); /*Flawfinder: ignore*/
|
||||
|
||||
LL_DEBUGS() << "Loading keyframe data for: " << motionp->getName() << ":" << motionp->getID() << " (" << size << " bytes)" << LL_ENDL;
|
||||
|
||||
LL_DEBUGS("Animation") << "Loading keyframe data for: " << motionp->getName() << ":" << motionp->getID() << " (" << size << " bytes)" << LL_ENDL;
|
||||
|
||||
LLDataPackerBinaryBuffer dp(buffer, size);
|
||||
if (motionp->deserialize(dp))
|
||||
@@ -2315,9 +2363,9 @@ void LLKeyframeDataCache::dumpDiagInfo(int quiet)
|
||||
|
||||
if (quiet < 2)
|
||||
{
|
||||
LL_INFOS() << "-----------------------------------------------------" << LL_ENDL;
|
||||
LL_INFOS() << " Global Motion Table" << LL_ENDL;
|
||||
LL_INFOS() << "-----------------------------------------------------" << LL_ENDL;
|
||||
LL_INFOS() << "-----------------------------------------------------" << LL_ENDL;
|
||||
LL_INFOS() << " Global Motion Table (DEBUG only)" << LL_ENDL;
|
||||
LL_INFOS() << "-----------------------------------------------------" << LL_ENDL;
|
||||
}
|
||||
|
||||
// print each loaded mesh, and it's memory usage
|
||||
@@ -2335,8 +2383,8 @@ void LLKeyframeDataCache::dumpDiagInfo(int quiet)
|
||||
|
||||
if (motion_list_p)
|
||||
{
|
||||
joint_motion_kb = motion_list_p->dumpDiagInfo(quiet);
|
||||
total_size += joint_motion_kb;
|
||||
joint_motion_kb = motion_list_p->dumpDiagInfo(quiet);
|
||||
total_size += joint_motion_kb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,8 +180,8 @@ LLMotion::LLMotion(LLUUID const& id, LLMotionController* controller) :
|
||||
mDeactivateCallback(NULL),
|
||||
mDeactivateCallbackUserData(NULL)
|
||||
{
|
||||
for (int i=0; i<3; ++i)
|
||||
memset(&mJointSignature[i][0], 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS);
|
||||
for (S32 i=0; i<3; ++i)
|
||||
memset(&mJointSignature[i][0], 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -237,9 +237,15 @@ void LLMotion::addJointState(const LLPointer<LLJointState>& jointState)
|
||||
U32 usage = jointState->getUsage();
|
||||
|
||||
// for now, usage is everything
|
||||
mJointSignature[0][jointState->getJoint()->getJointNum()] = (usage & LLJointState::POS) ? (0xff >> (7 - priority)) : 0;
|
||||
mJointSignature[1][jointState->getJoint()->getJointNum()] = (usage & LLJointState::ROT) ? (0xff >> (7 - priority)) : 0;
|
||||
mJointSignature[2][jointState->getJoint()->getJointNum()] = (usage & LLJointState::SCALE) ? (0xff >> (7 - priority)) : 0;
|
||||
S32 joint_num = jointState->getJoint()->getJointNum();
|
||||
if ((joint_num >= (S32)LL_CHARACTER_MAX_ANIMATED_JOINTS) || (joint_num < 0))
|
||||
{
|
||||
LL_WARNS() << "joint_num " << joint_num << " is outside of legal range [0-" << LL_CHARACTER_MAX_ANIMATED_JOINTS << ") for joint " << jointState->getJoint()->getName() << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
mJointSignature[0][joint_num] = (usage & LLJointState::POS) ? (0xff >> (7 - priority)) : 0;
|
||||
mJointSignature[1][joint_num] = (usage & LLJointState::ROT) ? (0xff >> (7 - priority)) : 0;
|
||||
mJointSignature[2][joint_num] = (usage & LLJointState::SCALE) ? (0xff >> (7 - priority)) : 0;
|
||||
}
|
||||
|
||||
void LLMotion::setDeactivateCallback( void (*cb)(void *), void* userdata )
|
||||
|
||||
@@ -274,7 +274,7 @@ protected:
|
||||
F32 mSendStopTimestamp; // time when simulator should be told to stop this motion
|
||||
F32 mResidualWeight; // blend weight at beginning of stop motion phase
|
||||
F32 mFadeWeight; // for fading in and out based on LOD
|
||||
U8 mJointSignature[3][LL_CHARACTER_MAX_JOINTS]; // signature of which joints are animated at what priority
|
||||
U8 mJointSignature[3][LL_CHARACTER_MAX_ANIMATED_JOINTS]; // signature of which joints are animated at what priority
|
||||
void (*mDeactivateCallback)(void* data);
|
||||
void* mDeactivateCallbackUserData;
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include "llanimationstates.h"
|
||||
#include "llstl.h"
|
||||
|
||||
const S32 NUM_JOINT_SIGNATURE_STRIDES = LL_CHARACTER_MAX_JOINTS / 4;
|
||||
const S32 NUM_JOINT_SIGNATURE_STRIDES = LL_CHARACTER_MAX_ANIMATED_JOINTS / 4;
|
||||
const U32 MAX_MOTION_INSTANCES = 32;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -517,8 +517,8 @@ void LLMotionController::updateAdditiveMotions()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLMotionController::resetJointSignatures()
|
||||
{
|
||||
memset(&mJointSignature[0][0], 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS);
|
||||
memset(&mJointSignature[1][0], 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS);
|
||||
memset(&mJointSignature[0][0], 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS);
|
||||
memset(&mJointSignature[1][0], 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -582,9 +582,9 @@ static LLFastTimer::DeclareTimer FTM_MOTION_ON_UPDATE("Motion onUpdate");
|
||||
void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_type)
|
||||
{
|
||||
BOOL update_result = TRUE;
|
||||
U8 last_joint_signature[LL_CHARACTER_MAX_JOINTS];
|
||||
U8 last_joint_signature[LL_CHARACTER_MAX_ANIMATED_JOINTS];
|
||||
|
||||
memset(&last_joint_signature, 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS);
|
||||
memset(&last_joint_signature, 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS);
|
||||
|
||||
// iterate through active motions in chronological order
|
||||
for (motion_list_t::iterator iter = mActiveMotions.begin();
|
||||
|
||||
@@ -253,7 +253,7 @@ protected:
|
||||
S32 mTimeStepCount;
|
||||
F32 mLastInterp;
|
||||
|
||||
U8 mJointSignature[2][LL_CHARACTER_MAX_JOINTS];
|
||||
U8 mJointSignature[2][LL_CHARACTER_MAX_ANIMATED_JOINTS];
|
||||
|
||||
//<singu>
|
||||
public:
|
||||
|
||||
@@ -2540,7 +2540,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
|
||||
U16 influence = weights[idx++];
|
||||
influence |= ((U16) weights[idx++] << 8);
|
||||
|
||||
F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f);
|
||||
F32 w = llclamp((F32) influence / 65535.f, 0.001f, 0.999f);
|
||||
wght.mV[cur_influence] = w;
|
||||
joints[cur_influence] = joint;
|
||||
cur_influence++;
|
||||
@@ -2554,15 +2554,19 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
|
||||
joint = weights[idx++];
|
||||
}
|
||||
}
|
||||
F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW];
|
||||
if (wsum <= 0.f)
|
||||
{
|
||||
wght = LLVector4(0.99999f,0.f,0.f,0.f);
|
||||
}
|
||||
for (U32 k=0; k<4; k++)
|
||||
{
|
||||
joints_with_weights[k] = (F32) joints[k] + wght[k];
|
||||
}
|
||||
F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW];
|
||||
if (wsum <= 0.f)
|
||||
{
|
||||
wght = LLVector4(0.999f,0.f,0.f,0.f);
|
||||
}
|
||||
for (U32 k=0; k<4; k++)
|
||||
{
|
||||
F32 f_combined = (F32) joints[k] + wght[k];
|
||||
joints_with_weights[k] = f_combined;
|
||||
// Any weights we added above should wind up non-zero and applied to a specific bone.
|
||||
// A failure here would indicate a floating point precision error in the math.
|
||||
llassert((k >= cur_influence) || (f_combined - S32(f_combined) > 0.0f));
|
||||
}
|
||||
face.mWeights[cur_vertex].loadua(joints_with_weights.mV);
|
||||
|
||||
cur_vertex++;
|
||||
@@ -4600,6 +4604,7 @@ LLVolumeFace::LLVolumeFace() :
|
||||
mTexCoords(NULL),
|
||||
mIndices(NULL),
|
||||
mWeights(NULL),
|
||||
mWeightsScrubbed(FALSE),
|
||||
mOctree(NULL),
|
||||
mOptimized(FALSE)
|
||||
{
|
||||
@@ -4625,6 +4630,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
|
||||
mTexCoords(NULL),
|
||||
mIndices(NULL),
|
||||
mWeights(NULL),
|
||||
mWeightsScrubbed(FALSE),
|
||||
mOctree(NULL),
|
||||
mOptimized(FALSE)
|
||||
{
|
||||
@@ -4687,6 +4693,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
|
||||
{
|
||||
LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size);
|
||||
}
|
||||
mWeightsScrubbed = src.mWeightsScrubbed;
|
||||
}
|
||||
|
||||
if (mNumIndices)
|
||||
@@ -5992,7 +5999,10 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
|
||||
}
|
||||
else
|
||||
{ //degenerate, make up a value
|
||||
normal.set(0,0,1);
|
||||
if(normal.getF32ptr()[2] >= 0)
|
||||
normal.set(0.f,0.f,1.f);
|
||||
else
|
||||
normal.set(0.f,0.f,-1.f);
|
||||
}
|
||||
|
||||
llassert(std::isfinite(normal.getF32ptr()[0]));
|
||||
|
||||
@@ -959,6 +959,8 @@ public:
|
||||
// mWeights.size() should be empty or match mVertices.size()
|
||||
LLVector4a* mWeights;
|
||||
|
||||
mutable BOOL mWeightsScrubbed;
|
||||
|
||||
LLOctreeNode<LLVolumeTriangle>* mOctree;
|
||||
|
||||
//whether or not face has been cache optimized
|
||||
|
||||
@@ -929,8 +929,10 @@ LLDAELoader::LLDAELoader(
|
||||
texture_load_func_t texture_load_func,
|
||||
state_callback_t state_cb,
|
||||
void* opaque_userdata,
|
||||
JointTransformMap& jointMap,
|
||||
JointSet& jointsFromNodes,
|
||||
JointTransformMap& jointTransformMap,
|
||||
JointNameSet& jointsFromNodes,
|
||||
std::map<std::string, std::string>& jointAliasMap,
|
||||
U32 maxJointsPerMesh,
|
||||
U32 modelLimit,
|
||||
bool preprocess)
|
||||
: LLModelLoader(
|
||||
@@ -941,10 +943,12 @@ LLDAELoader::LLDAELoader(
|
||||
texture_load_func,
|
||||
state_cb,
|
||||
opaque_userdata,
|
||||
jointMap,
|
||||
jointsFromNodes),
|
||||
mGeneratedModelLimit(modelLimit),
|
||||
mPreprocessDAE(preprocess)
|
||||
jointTransformMap,
|
||||
jointsFromNodes,
|
||||
jointAliasMap,
|
||||
maxJointsPerMesh),
|
||||
mGeneratedModelLimit(modelLimit),
|
||||
mPreprocessDAE(preprocess)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1264,28 +1268,29 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
||||
|
||||
|
||||
//Some collada setup for accessing the skeleton
|
||||
daeElement* pElement = 0;
|
||||
dae->getDatabase()->getElement( &pElement, 0, 0, "skeleton" );
|
||||
U32 skeleton_count = dae->getDatabase()->getElementCount( NULL, "skeleton" );
|
||||
std::vector<domInstance_controller::domSkeleton*> skeletons;
|
||||
for (U32 i=0; i<skeleton_count; i++)
|
||||
{
|
||||
daeElement* pElement = 0;
|
||||
dae->getDatabase()->getElement( &pElement, i, 0, "skeleton" );
|
||||
|
||||
//Try to get at the skeletal instance controller
|
||||
domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement );
|
||||
//Try to get at the skeletal instance controller
|
||||
domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement );
|
||||
daeElement* pSkeletonRootNode = NULL;
|
||||
if ( pSkeleton )
|
||||
{
|
||||
pSkeletonRootNode = pSkeleton->getValue().getElement();
|
||||
}
|
||||
if (pSkeleton && pSkeletonRootNode)
|
||||
{
|
||||
skeletons.push_back(pSkeleton);
|
||||
}
|
||||
}
|
||||
bool missingSkeletonOrScene = false;
|
||||
|
||||
//If no skeleton, do a breadth-first search to get at specific joints
|
||||
bool rootNode = false;
|
||||
|
||||
//Need to test for a skeleton that does not have a root node
|
||||
//This occurs when your instance controller does not have an associated scene
|
||||
if ( pSkeleton )
|
||||
{
|
||||
daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
|
||||
if ( pSkeletonRootNode )
|
||||
{
|
||||
rootNode = true;
|
||||
}
|
||||
|
||||
}
|
||||
if ( !pSkeleton || !rootNode )
|
||||
if ( skeletons.size() == 0 )
|
||||
{
|
||||
daeElement* pScene = root->getDescendant("visual_scene");
|
||||
if ( !pScene )
|
||||
@@ -1312,74 +1317,81 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
||||
}
|
||||
}
|
||||
else
|
||||
//Has Skeleton
|
||||
{
|
||||
//Get the root node of the skeleton
|
||||
daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
|
||||
if ( pSkeletonRootNode )
|
||||
//Has one or more skeletons
|
||||
for (std::vector<domInstance_controller::domSkeleton*>::iterator skel_it = skeletons.begin();
|
||||
skel_it != skeletons.end(); ++skel_it)
|
||||
{
|
||||
//Once we have the root node - start acccessing it's joint components
|
||||
const int jointCnt = mJointMap.size();
|
||||
JointMap :: const_iterator jointIt = mJointMap.begin();
|
||||
|
||||
//Loop over all the possible joints within the .dae - using the allowed joint list in the ctor.
|
||||
for ( int i=0; i<jointCnt; ++i, ++jointIt )
|
||||
domInstance_controller::domSkeleton* pSkeleton = *skel_it;
|
||||
//Get the root node of the skeleton
|
||||
daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
|
||||
if ( pSkeletonRootNode )
|
||||
{
|
||||
//Build a joint for the resolver to work with
|
||||
char str[64]={0};
|
||||
sprintf(str,"./%s",(*jointIt).first.c_str() );
|
||||
//LL_WARNS()<<"Joint "<< str <<LL_ENDL;
|
||||
//Once we have the root node - start acccessing it's joint components
|
||||
const int jointCnt = mJointMap.size();
|
||||
JointMap :: const_iterator jointIt = mJointMap.begin();
|
||||
|
||||
//Setup the resolver
|
||||
daeSIDResolver resolver( pSkeletonRootNode, str );
|
||||
|
||||
//Look for the joint
|
||||
domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() );
|
||||
if ( pJoint )
|
||||
//Loop over all the possible joints within the .dae - using the allowed joint list in the ctor.
|
||||
for ( int i=0; i<jointCnt; ++i, ++jointIt )
|
||||
{
|
||||
//Pull out the translate id and store it in the jointTranslations map
|
||||
daeSIDResolver jointResolverA( pJoint, "./translate" );
|
||||
domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
|
||||
daeSIDResolver jointResolverB( pJoint, "./location" );
|
||||
domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
|
||||
//Build a joint for the resolver to work with
|
||||
char str[64]={0};
|
||||
sprintf(str,"./%s",(*jointIt).first.c_str() );
|
||||
//LL_WARNS()<<"Joint "<< str <<LL_ENDL;
|
||||
|
||||
LLMatrix4 workingTransform;
|
||||
//Setup the resolver
|
||||
daeSIDResolver resolver( pSkeletonRootNode, str );
|
||||
|
||||
//Translation via SID
|
||||
if ( pTranslateA )
|
||||
//Look for the joint
|
||||
domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() );
|
||||
if ( pJoint )
|
||||
{
|
||||
extractTranslation( pTranslateA, workingTransform );
|
||||
}
|
||||
else
|
||||
if ( pTranslateB )
|
||||
// FIXME this has a lot of overlap with processJointNode(), would be nice to refactor.
|
||||
|
||||
//Pull out the translate id and store it in the jointTranslations map
|
||||
daeSIDResolver jointResolverA( pJoint, "./translate" );
|
||||
domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
|
||||
daeSIDResolver jointResolverB( pJoint, "./location" );
|
||||
domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
|
||||
|
||||
LLMatrix4 workingTransform;
|
||||
|
||||
//Translation via SID
|
||||
if ( pTranslateA )
|
||||
{
|
||||
extractTranslation( pTranslateB, workingTransform );
|
||||
extractTranslation( pTranslateA, workingTransform );
|
||||
}
|
||||
else
|
||||
{
|
||||
//Translation via child from element
|
||||
daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" );
|
||||
if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() )
|
||||
if ( pTranslateB )
|
||||
{
|
||||
LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
|
||||
missingSkeletonOrScene = true;
|
||||
extractTranslation( pTranslateB, workingTransform );
|
||||
}
|
||||
else
|
||||
if ( pTranslateElement )
|
||||
{
|
||||
//Translation via child from element
|
||||
daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" );
|
||||
if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() )
|
||||
{
|
||||
extractTranslationViaElement( pTranslateElement, workingTransform );
|
||||
LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
|
||||
missingSkeletonOrScene = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
extractTranslationViaSID( pJoint, workingTransform );
|
||||
}
|
||||
if ( pTranslateElement )
|
||||
{
|
||||
extractTranslationViaElement( pTranslateElement, workingTransform );
|
||||
}
|
||||
else
|
||||
{
|
||||
extractTranslationViaSID( pJoint, workingTransform );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Store the joint transform w/respect to it's name.
|
||||
mJointList[(*jointIt).second.c_str()] = workingTransform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If anything failed in regards to extracting the skeleton, joints or translation id,
|
||||
//mention it
|
||||
@@ -1423,7 +1435,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
||||
name = mJointMap[name];
|
||||
}
|
||||
model->mSkinInfo.mJointNames.push_back(name);
|
||||
model->mSkinInfo.mJointMap[name] = j;
|
||||
model->mSkinInfo.mJointNums.push_back(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1441,7 +1453,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
||||
name = mJointMap[name];
|
||||
}
|
||||
model->mSkinInfo.mJointNames.push_back(name);
|
||||
model->mSkinInfo.mJointMap[name] = j;
|
||||
model->mSkinInfo.mJointNums.push_back(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1469,8 +1481,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
||||
mat.mMatrix[i][j] = transform[k*16 + i + j*4];
|
||||
}
|
||||
}
|
||||
|
||||
model->mSkinInfo.mInvBindMatrix.push_back(mat);
|
||||
model->mSkinInfo.mInvBindMatrix.push_back(mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1486,9 +1497,18 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
||||
|
||||
if ( !missingSkeletonOrScene )
|
||||
{
|
||||
//Set the joint translations on the avatar - if it's a full mapping
|
||||
// FIXME: mesh_id is used to determine which mesh gets to
|
||||
// set the joint offset, in the event of a conflict. Since
|
||||
// we don't know the mesh id yet, we can't guarantee that
|
||||
// joint offsets will be applied with the same priority as
|
||||
// in the uploaded model. If the file contains multiple
|
||||
// meshes with conflicting joint offsets, preview may be
|
||||
// incorrect.
|
||||
LLUUID fake_mesh_id;
|
||||
fake_mesh_id.generate();
|
||||
|
||||
//The joints are reset in the dtor
|
||||
if ( getRigWithSceneParity() )
|
||||
//if ( getRigWithSceneParity() )
|
||||
{
|
||||
JointMap :: const_iterator masterJointIt = mJointMap.begin();
|
||||
JointMap :: const_iterator masterJointItEnd = mJointMap.end();
|
||||
@@ -1502,10 +1522,17 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
||||
LLMatrix4 jointTransform = mJointList[lookingForJoint];
|
||||
LLJoint* pJoint = mJointLookupFunc(lookingForJoint,mOpaqueData);
|
||||
if ( pJoint )
|
||||
{
|
||||
LLUUID fake_mesh_id;
|
||||
fake_mesh_id.generate();
|
||||
pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, "");
|
||||
{
|
||||
const LLVector3& joint_pos = jointTransform.getTranslation();
|
||||
if (pJoint->aboveJointPosThreshold(joint_pos))
|
||||
{
|
||||
bool override_changed; // not used
|
||||
pJoint->addAttachmentPosOverride(joint_pos, fake_mesh_id, "", override_changed);
|
||||
if (model->mSkinInfo.mLockScaleIfJointPosition)
|
||||
{
|
||||
pJoint->addAttachmentScaleOverride(pJoint->getDefaultScale(), fake_mesh_id, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1528,16 +1555,15 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
||||
std::string lookingForJoint = (*jointIt).c_str();
|
||||
//Look for the joint xform that we extracted from the skeleton, using the jointIt as the key
|
||||
//and store it in the alternate bind matrix
|
||||
if ( mJointList.find( lookingForJoint ) != mJointList.end() )
|
||||
if ( mJointMap.find( lookingForJoint ) != mJointMap.end() )
|
||||
{
|
||||
LLMatrix4 jointTransform = mJointList[lookingForJoint];
|
||||
LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];
|
||||
newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() );
|
||||
model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse );
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS()<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<LL_ENDL;
|
||||
LL_DEBUGS("Mesh")<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<"] "<<LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1980,13 +2006,13 @@ void LLDAELoader::processJointNode( domNode* pNode, JointTransformMap& jointTran
|
||||
//-----------------------------------------------------------------------------
|
||||
daeElement* LLDAELoader::getChildFromElement( daeElement* pElement, std::string const & name )
|
||||
{
|
||||
daeElement* pChildOfElement = pElement->getChild(name.c_str());
|
||||
daeElement* pChildOfElement = pElement->getChild(name.c_str());
|
||||
if (pChildOfElement)
|
||||
{
|
||||
return pChildOfElement;
|
||||
}
|
||||
LL_WARNS() << "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL;
|
||||
return NULL;
|
||||
LL_DEBUGS("Mesh")<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* dae )
|
||||
@@ -2351,7 +2377,11 @@ std::string LLDAELoader::getElementLabel(daeElement *element)
|
||||
// retrieve index to distinguish items inside same parent
|
||||
size_t ind = 0;
|
||||
parent->getChildren().find(element, ind);
|
||||
index_string = "_" + boost::lexical_cast<std::string>(ind);
|
||||
|
||||
if (ind > 0)
|
||||
{
|
||||
index_string = "_" + boost::lexical_cast<std::string>(ind);
|
||||
}
|
||||
|
||||
// if parent has a name or ID, use it
|
||||
std::string name = parent->getAttribute("name");
|
||||
|
||||
@@ -53,11 +53,13 @@ public:
|
||||
LLModelLoader::joint_lookup_func_t joint_lookup_func,
|
||||
LLModelLoader::texture_load_func_t texture_load_func,
|
||||
LLModelLoader::state_callback_t state_cb,
|
||||
void* opaque_userdata,
|
||||
JointTransformMap& jointMap,
|
||||
JointSet& jointsFromNodes,
|
||||
void* opaque_userdata,
|
||||
JointTransformMap& jointTransformMap,
|
||||
JointNameSet& jointsFromNodes,
|
||||
std::map<std::string, std::string>& jointAliasMap,
|
||||
U32 maxJointsPerMesh,
|
||||
U32 modelLimit,
|
||||
bool preprocess);
|
||||
bool preprocess);
|
||||
virtual ~LLDAELoader() ;
|
||||
|
||||
virtual bool OpenFile(const std::string& filename);
|
||||
|
||||
@@ -51,8 +51,12 @@ std::string model_names[] =
|
||||
const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
|
||||
|
||||
LLModel::LLModel(LLVolumeParams& params, F32 detail)
|
||||
: LLVolume(params, detail), mNormalizedScale(1,1,1), mNormalizedTranslation(0,0,0)
|
||||
, mPelvisOffset( 0.0f ), mStatus(NO_ERRORS), mSubmodelID(0)
|
||||
: LLVolume(params, detail),
|
||||
mNormalizedScale(1,1,1),
|
||||
mNormalizedTranslation(0,0,0),
|
||||
mPelvisOffset( 0.0f ),
|
||||
mStatus(NO_ERRORS),
|
||||
mSubmodelID(0)
|
||||
{
|
||||
mDecompID = -1;
|
||||
mLocalID = -1;
|
||||
@@ -677,6 +681,7 @@ LLSD LLModel::writeModel(
|
||||
const LLModel::Decomposition& decomp,
|
||||
BOOL upload_skin,
|
||||
BOOL upload_joints,
|
||||
BOOL lock_scale_if_joint_position,
|
||||
BOOL nowrite,
|
||||
BOOL as_slm,
|
||||
int submodel_id)
|
||||
@@ -696,7 +701,7 @@ LLSD LLModel::writeModel(
|
||||
|
||||
if (skinning)
|
||||
{ //write skinning block
|
||||
mdl["skin"] = high->mSkinInfo.asLLSD(upload_joints);
|
||||
mdl["skin"] = high->mSkinInfo.asLLSD(upload_joints, lock_scale_if_joint_position);
|
||||
}
|
||||
|
||||
if (!decomp.mBaseHull.empty() ||
|
||||
@@ -1042,6 +1047,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
|
||||
|
||||
weight_map::iterator best = iter_up;
|
||||
|
||||
// iter == mSkinWeights.end()...
|
||||
F32 min_dist = (iter_up->first - pos).magVec();
|
||||
|
||||
bool done = false;
|
||||
@@ -1390,8 +1396,17 @@ bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
|
||||
return true;
|
||||
}
|
||||
|
||||
LLMeshSkinInfo::LLMeshSkinInfo():
|
||||
mPelvisOffset(0.0),
|
||||
mLockScaleIfJointPosition(false),
|
||||
mInvalidJointsScrubbed(false)
|
||||
{
|
||||
}
|
||||
|
||||
LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin)
|
||||
LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin):
|
||||
mPelvisOffset(0.0),
|
||||
mLockScaleIfJointPosition(false),
|
||||
mInvalidJointsScrubbed(false)
|
||||
{
|
||||
fromLLSD(skin);
|
||||
}
|
||||
@@ -1400,10 +1415,11 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
|
||||
{
|
||||
if (skin.has("joint_names"))
|
||||
{
|
||||
const U32 joint_count = llmin((U32)skin["joint_names"].size(),(U32)64);
|
||||
const U32 joint_count = skin["joint_names"].size();
|
||||
for (U32 i = 0; i < joint_count; ++i)
|
||||
{
|
||||
mJointNames.push_back(skin["joint_names"][i]);
|
||||
mJointNums.push_back(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1456,9 +1472,18 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
|
||||
{
|
||||
mPelvisOffset = skin["pelvis_offset"].asReal();
|
||||
}
|
||||
|
||||
if (skin.has("lock_scale_if_joint_position"))
|
||||
{
|
||||
mLockScaleIfJointPosition = skin["lock_scale_if_joint_position"].asBoolean();
|
||||
}
|
||||
else
|
||||
{
|
||||
mLockScaleIfJointPosition = false;
|
||||
}
|
||||
}
|
||||
|
||||
LLSD LLMeshSkinInfo::asLLSD(bool include_joints) const
|
||||
LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_position) const
|
||||
{
|
||||
LLSD ret;
|
||||
|
||||
@@ -1496,6 +1521,11 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints) const
|
||||
}
|
||||
}
|
||||
|
||||
if (lock_scale_if_joint_position)
|
||||
{
|
||||
ret["lock_scale_if_joint_position"] = lock_scale_if_joint_position;
|
||||
}
|
||||
|
||||
ret["pelvis_offset"] = mPelvisOffset;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,18 +42,21 @@ class domMesh;
|
||||
class LLMeshSkinInfo
|
||||
{
|
||||
public:
|
||||
LLUUID mMeshID;
|
||||
std::vector<std::string> mJointNames;
|
||||
std::vector<LLMatrix4> mInvBindMatrix;
|
||||
std::vector<LLMatrix4> mAlternateBindMatrix;
|
||||
std::map<std::string, U32> mJointMap;
|
||||
|
||||
LLMeshSkinInfo() { }
|
||||
LLMeshSkinInfo();
|
||||
LLMeshSkinInfo(LLSD& data);
|
||||
void fromLLSD(LLSD& data);
|
||||
LLSD asLLSD(bool include_joints) const;
|
||||
LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const;
|
||||
|
||||
LLUUID mMeshID;
|
||||
std::vector<std::string> mJointNames;
|
||||
mutable std::vector<S32> mJointNums;
|
||||
std::vector<LLMatrix4> mInvBindMatrix;
|
||||
std::vector<LLMatrix4> mAlternateBindMatrix;
|
||||
|
||||
LLMatrix4 mBindShapeMatrix;
|
||||
float mPelvisOffset;
|
||||
bool mLockScaleIfJointPosition;
|
||||
bool mInvalidJointsScrubbed;
|
||||
};
|
||||
|
||||
class LLModel : public LLVolume
|
||||
@@ -138,6 +141,7 @@ public:
|
||||
const LLModel::Decomposition& decomp,
|
||||
BOOL upload_skin,
|
||||
BOOL upload_joints,
|
||||
BOOL lock_scale_if_joint_position,
|
||||
BOOL nowrite = FALSE,
|
||||
BOOL as_slm = FALSE,
|
||||
int submodel_id = 0);
|
||||
|
||||
@@ -109,9 +109,11 @@ LLModelLoader::LLModelLoader(
|
||||
texture_load_func_t texture_load_func,
|
||||
state_callback_t state_cb,
|
||||
void* opaque_userdata,
|
||||
JointTransformMap& jointMap,
|
||||
JointSet& jointsFromNodes )
|
||||
: mJointList( jointMap )
|
||||
JointTransformMap& jointTransformMap,
|
||||
JointNameSet& jointsFromNodes,
|
||||
JointMap& legalJointNamesMap,
|
||||
U32 maxJointsPerMesh)
|
||||
: mJointList( jointTransformMap )
|
||||
, mJointsFromNode( jointsFromNodes )
|
||||
, LLThread("Model Loader")
|
||||
, mFilename(filename)
|
||||
@@ -124,124 +126,14 @@ LLModelLoader::LLModelLoader(
|
||||
, mTextureLoadFunc(texture_load_func)
|
||||
, mStateCallback(state_cb)
|
||||
, mOpaqueData(opaque_userdata)
|
||||
, mRigParityWithScene(false)
|
||||
, mRigValidJointUpload(false)
|
||||
, mLegacyRigValid(false)
|
||||
, mRigValidJointUpload(true)
|
||||
, mLegacyRigValid(true)
|
||||
, mNoNormalize(false)
|
||||
, mNoOptimize(false)
|
||||
, mCacheOnlyHitIfRigged(false)
|
||||
, mMaxJointsPerMesh(maxJointsPerMesh)
|
||||
, mJointMap(legalJointNamesMap)
|
||||
{
|
||||
mJointMap["mPelvis"] = "mPelvis";
|
||||
mJointMap["mTorso"] = "mTorso";
|
||||
mJointMap["mChest"] = "mChest";
|
||||
mJointMap["mNeck"] = "mNeck";
|
||||
mJointMap["mHead"] = "mHead";
|
||||
mJointMap["mSkull"] = "mSkull";
|
||||
mJointMap["mEyeRight"] = "mEyeRight";
|
||||
mJointMap["mEyeLeft"] = "mEyeLeft";
|
||||
mJointMap["mCollarLeft"] = "mCollarLeft";
|
||||
mJointMap["mShoulderLeft"] = "mShoulderLeft";
|
||||
mJointMap["mElbowLeft"] = "mElbowLeft";
|
||||
mJointMap["mWristLeft"] = "mWristLeft";
|
||||
mJointMap["mCollarRight"] = "mCollarRight";
|
||||
mJointMap["mShoulderRight"] = "mShoulderRight";
|
||||
mJointMap["mElbowRight"] = "mElbowRight";
|
||||
mJointMap["mWristRight"] = "mWristRight";
|
||||
mJointMap["mHipRight"] = "mHipRight";
|
||||
mJointMap["mKneeRight"] = "mKneeRight";
|
||||
mJointMap["mAnkleRight"] = "mAnkleRight";
|
||||
mJointMap["mFootRight"] = "mFootRight";
|
||||
mJointMap["mToeRight"] = "mToeRight";
|
||||
mJointMap["mHipLeft"] = "mHipLeft";
|
||||
mJointMap["mKneeLeft"] = "mKneeLeft";
|
||||
mJointMap["mAnkleLeft"] = "mAnkleLeft";
|
||||
mJointMap["mFootLeft"] = "mFootLeft";
|
||||
mJointMap["mToeLeft"] = "mToeLeft";
|
||||
|
||||
mJointMap["avatar_mPelvis"] = "mPelvis";
|
||||
mJointMap["avatar_mTorso"] = "mTorso";
|
||||
mJointMap["avatar_mChest"] = "mChest";
|
||||
mJointMap["avatar_mNeck"] = "mNeck";
|
||||
mJointMap["avatar_mHead"] = "mHead";
|
||||
mJointMap["avatar_mSkull"] = "mSkull";
|
||||
mJointMap["avatar_mEyeRight"] = "mEyeRight";
|
||||
mJointMap["avatar_mEyeLeft"] = "mEyeLeft";
|
||||
mJointMap["avatar_mCollarLeft"] = "mCollarLeft";
|
||||
mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft";
|
||||
mJointMap["avatar_mElbowLeft"] = "mElbowLeft";
|
||||
mJointMap["avatar_mWristLeft"] = "mWristLeft";
|
||||
mJointMap["avatar_mCollarRight"] = "mCollarRight";
|
||||
mJointMap["avatar_mShoulderRight"] = "mShoulderRight";
|
||||
mJointMap["avatar_mElbowRight"] = "mElbowRight";
|
||||
mJointMap["avatar_mWristRight"] = "mWristRight";
|
||||
mJointMap["avatar_mHipRight"] = "mHipRight";
|
||||
mJointMap["avatar_mKneeRight"] = "mKneeRight";
|
||||
mJointMap["avatar_mAnkleRight"] = "mAnkleRight";
|
||||
mJointMap["avatar_mFootRight"] = "mFootRight";
|
||||
mJointMap["avatar_mToeRight"] = "mToeRight";
|
||||
mJointMap["avatar_mHipLeft"] = "mHipLeft";
|
||||
mJointMap["avatar_mKneeLeft"] = "mKneeLeft";
|
||||
mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft";
|
||||
mJointMap["avatar_mFootLeft"] = "mFootLeft";
|
||||
mJointMap["avatar_mToeLeft"] = "mToeLeft";
|
||||
|
||||
|
||||
mJointMap["hip"] = "mPelvis";
|
||||
mJointMap["abdomen"] = "mTorso";
|
||||
mJointMap["chest"] = "mChest";
|
||||
mJointMap["neck"] = "mNeck";
|
||||
mJointMap["head"] = "mHead";
|
||||
mJointMap["figureHair"] = "mSkull";
|
||||
mJointMap["lCollar"] = "mCollarLeft";
|
||||
mJointMap["lShldr"] = "mShoulderLeft";
|
||||
mJointMap["lForeArm"] = "mElbowLeft";
|
||||
mJointMap["lHand"] = "mWristLeft";
|
||||
mJointMap["rCollar"] = "mCollarRight";
|
||||
mJointMap["rShldr"] = "mShoulderRight";
|
||||
mJointMap["rForeArm"] = "mElbowRight";
|
||||
mJointMap["rHand"] = "mWristRight";
|
||||
mJointMap["rThigh"] = "mHipRight";
|
||||
mJointMap["rShin"] = "mKneeRight";
|
||||
mJointMap["rFoot"] = "mFootRight";
|
||||
mJointMap["lThigh"] = "mHipLeft";
|
||||
mJointMap["lShin"] = "mKneeLeft";
|
||||
mJointMap["lFoot"] = "mFootLeft";
|
||||
|
||||
//move into joint mapper class
|
||||
//1. joints for joint offset verification
|
||||
mMasterJointList.push_front("mPelvis");
|
||||
mMasterJointList.push_front("mTorso");
|
||||
mMasterJointList.push_front("mChest");
|
||||
mMasterJointList.push_front("mNeck");
|
||||
mMasterJointList.push_front("mHead");
|
||||
mMasterJointList.push_front("mCollarLeft");
|
||||
mMasterJointList.push_front("mShoulderLeft");
|
||||
mMasterJointList.push_front("mElbowLeft");
|
||||
mMasterJointList.push_front("mWristLeft");
|
||||
mMasterJointList.push_front("mCollarRight");
|
||||
mMasterJointList.push_front("mShoulderRight");
|
||||
mMasterJointList.push_front("mElbowRight");
|
||||
mMasterJointList.push_front("mWristRight");
|
||||
mMasterJointList.push_front("mHipRight");
|
||||
mMasterJointList.push_front("mKneeRight");
|
||||
mMasterJointList.push_front("mFootRight");
|
||||
mMasterJointList.push_front("mHipLeft");
|
||||
mMasterJointList.push_front("mKneeLeft");
|
||||
mMasterJointList.push_front("mFootLeft");
|
||||
|
||||
//2. legacy joint list - used to verify rigs that will not be using joint offsets
|
||||
mMasterLegacyJointList.push_front("mPelvis");
|
||||
mMasterLegacyJointList.push_front("mTorso");
|
||||
mMasterLegacyJointList.push_front("mChest");
|
||||
mMasterLegacyJointList.push_front("mNeck");
|
||||
mMasterLegacyJointList.push_front("mHead");
|
||||
mMasterLegacyJointList.push_front("mHipRight");
|
||||
mMasterLegacyJointList.push_front("mKneeRight");
|
||||
mMasterLegacyJointList.push_front("mFootRight");
|
||||
mMasterLegacyJointList.push_front("mHipLeft");
|
||||
mMasterLegacyJointList.push_front("mKneeLeft");
|
||||
mMasterLegacyJointList.push_front("mFootLeft");
|
||||
|
||||
assert_main_thread();
|
||||
sActiveLoaderList.push_back(this) ;
|
||||
}
|
||||
@@ -258,6 +150,23 @@ void LLModelLoader::run()
|
||||
doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::string& slm_filename)
|
||||
{
|
||||
slm_filename = model_filename;
|
||||
|
||||
std::string::size_type i = model_filename.rfind(".");
|
||||
if (i != std::string::npos)
|
||||
{
|
||||
slm_filename.replace(i, model_filename.size()-1, ".slm");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLModelLoader::doLoadModel()
|
||||
{
|
||||
//first, look for a .slm file of the same name that was modified later
|
||||
@@ -265,20 +174,17 @@ bool LLModelLoader::doLoadModel()
|
||||
|
||||
if (mTrySLM)
|
||||
{
|
||||
std::string filename = mFilename;
|
||||
|
||||
std::string::size_type i = filename.rfind(".");
|
||||
if (i != std::string::npos)
|
||||
{
|
||||
filename.replace(i, filename.size()-1, ".slm");
|
||||
std::string slm_filename;
|
||||
if (getSLMFilename(mFilename, slm_filename))
|
||||
{
|
||||
llstat slm_status;
|
||||
if (LLFile::stat(filename, &slm_status) == 0)
|
||||
if (LLFile::stat(slm_filename, &slm_status) == 0)
|
||||
{ //slm file exists
|
||||
llstat dae_status;
|
||||
if (LLFile::stat(mFilename, &dae_status) != 0 ||
|
||||
dae_status.st_mtime < slm_status.st_mtime)
|
||||
{
|
||||
if (loadFromSLM(filename))
|
||||
if (loadFromSLM(slm_filename))
|
||||
{ //slm successfully loaded, if this fails, fall through and
|
||||
//try loading from dae
|
||||
|
||||
@@ -476,8 +382,6 @@ void LLModelLoader::loadModelCallback()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset )
|
||||
{
|
||||
critiqueJointToNodeMappingFromScene();
|
||||
|
||||
//Determines the following use cases for a rig:
|
||||
//1. It is suitable for upload with skin weights & joint positions, or
|
||||
//2. It is suitable for upload as standard av with just skin weights
|
||||
@@ -486,58 +390,26 @@ void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::st
|
||||
bool isRigLegacyOK = isRigLegacy( jointListFromAsset );
|
||||
|
||||
//It's OK that both could end up being true, both default to false
|
||||
if ( isJointPositionUploadOK )
|
||||
|
||||
// Both start out as true and are forced to false if any mesh in
|
||||
// the model file is not vald by that criterion. Note that a file
|
||||
// can contain multiple meshes.
|
||||
if ( !isJointPositionUploadOK )
|
||||
{
|
||||
setRigValidForJointPositionUpload( true );
|
||||
// This starts out true, becomes false if false for any loaded
|
||||
// mesh.
|
||||
setRigValidForJointPositionUpload( false );
|
||||
}
|
||||
|
||||
if ( isRigLegacyOK)
|
||||
if ( !isRigLegacyOK)
|
||||
{
|
||||
setLegacyRigValid( true );
|
||||
// This starts out true, becomes false if false for any loaded
|
||||
// mesh.
|
||||
setLegacyRigValid( false );
|
||||
}
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// critiqueJointToNodeMappingFromScene()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLModelLoader::critiqueJointToNodeMappingFromScene( void )
|
||||
{
|
||||
//Do the actual nodes back the joint listing from the dae?
|
||||
//if yes then this is a fully rigged asset, otherwise it's just a partial rig
|
||||
|
||||
JointSet::iterator jointsFromNodeIt = mJointsFromNode.begin();
|
||||
JointSet::iterator jointsFromNodeEndIt = mJointsFromNode.end();
|
||||
bool result = true;
|
||||
|
||||
if ( !mJointsFromNode.empty() )
|
||||
{
|
||||
for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt )
|
||||
{
|
||||
std::string name = *jointsFromNodeIt;
|
||||
if ( mJointTransformMap.find( name ) != mJointTransformMap.end() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() <<"critiqueJointToNodeMappingFromScene is missing a: " << name << LL_ENDL;
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
//Determines the following use cases for a rig:
|
||||
//1. Full av rig w/1-1 mapping from the scene and joint array
|
||||
//2. Partial rig but w/o parity between the scene and joint array
|
||||
if ( result )
|
||||
{
|
||||
setRigWithSceneParity( true );
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// isRigLegacy()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -549,68 +421,39 @@ bool LLModelLoader::isRigLegacy( const std::vector<std::string> &jointListFromAs
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
// Too many joints in asset
|
||||
if (jointListFromAsset.size()>mMaxJointsPerMesh)
|
||||
{
|
||||
LL_WARNS() << "Rigged to " << jointListFromAsset.size() << " joints, max is " << mMaxJointsPerMesh << LL_ENDL;
|
||||
LL_WARNS() << "Skinning disabled due to too many joints" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
JointSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin();
|
||||
JointSet :: const_iterator masterJointEndIt = mMasterLegacyJointList.end();
|
||||
|
||||
std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
|
||||
std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
|
||||
|
||||
for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
|
||||
{
|
||||
result = false;
|
||||
modelJointIt = jointListFromAsset.begin();
|
||||
// Unknown joints in asset
|
||||
S32 unknown_joint_count = 0;
|
||||
for (std::vector<std::string>::const_iterator it = jointListFromAsset.begin();
|
||||
it != jointListFromAsset.end(); ++it)
|
||||
{
|
||||
if (mJointMap.find(*it)==mJointMap.end())
|
||||
{
|
||||
LL_WARNS() << "Rigged to unrecognized joint name " << *it << LL_ENDL;
|
||||
unknown_joint_count++;
|
||||
}
|
||||
}
|
||||
if (unknown_joint_count>0)
|
||||
{
|
||||
LL_WARNS() << "Skinning disabled due to unknown joints" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
|
||||
{
|
||||
if ( *masterJointIt == *modelJointIt )
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !result )
|
||||
{
|
||||
LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// isRigSuitableForJointPositionUpload()
|
||||
//-----------------------------------------------------------------------------
|
||||
bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset )
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
JointSet :: const_iterator masterJointIt = mMasterJointList.begin();
|
||||
JointSet :: const_iterator masterJointEndIt = mMasterJointList.end();
|
||||
|
||||
std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
|
||||
std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
|
||||
|
||||
for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
|
||||
{
|
||||
result = false;
|
||||
modelJointIt = jointListFromAsset.begin();
|
||||
|
||||
for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
|
||||
{
|
||||
if ( *masterJointIt == *modelJointIt )
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !result )
|
||||
{
|
||||
LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class LLJoint;
|
||||
typedef std::map<std::string, LLMatrix4> JointTransformMap;
|
||||
typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
|
||||
typedef std::map<std::string, std::string> JointMap;
|
||||
typedef std::deque<std::string> JointSet;
|
||||
typedef std::deque<std::string> JointNameSet;
|
||||
|
||||
const S32 SLM_SUPPORTED_VERSION = 3;
|
||||
const S32 NUM_LOD = 4;
|
||||
@@ -116,7 +116,8 @@ public:
|
||||
//map of avatar joints as named in COLLADA assets to internal joint names
|
||||
JointMap mJointMap;
|
||||
JointTransformMap& mJointList;
|
||||
JointSet& mJointsFromNode;
|
||||
JointNameSet& mJointsFromNode;
|
||||
U32 mMaxJointsPerMesh;
|
||||
|
||||
LLModelLoader(
|
||||
std::string filename,
|
||||
@@ -125,16 +126,20 @@ public:
|
||||
LLModelLoader::joint_lookup_func_t joint_lookup_func,
|
||||
LLModelLoader::texture_load_func_t texture_load_func,
|
||||
LLModelLoader::state_callback_t state_cb,
|
||||
void* opaque_userdata,
|
||||
JointTransformMap& jointMap,
|
||||
JointSet& jointsFromNodes);
|
||||
void* opaque_userdata,
|
||||
JointTransformMap& jointTransformMap,
|
||||
JointNameSet& jointsFromNodes,
|
||||
JointMap& legalJointNamesMap,
|
||||
U32 maxJointsPerMesh);
|
||||
virtual ~LLModelLoader() ;
|
||||
|
||||
virtual void setNoNormalize() { mNoNormalize = true; }
|
||||
virtual void setNoOptimize() { mNoOptimize = true; }
|
||||
|
||||
virtual void run();
|
||||
|
||||
|
||||
static bool getSLMFilename(const std::string& model_filename, std::string& slm_filename);
|
||||
|
||||
// Will try SLM or derived class OpenFile as appropriate
|
||||
//
|
||||
virtual bool doLoadModel();
|
||||
@@ -158,7 +163,6 @@ public:
|
||||
|
||||
//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
|
||||
void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
|
||||
void critiqueJointToNodeMappingFromScene( void );
|
||||
|
||||
//Determines if a rig is a legacy from the joint list
|
||||
bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );
|
||||
@@ -166,9 +170,6 @@ public:
|
||||
//Determines if a rig is suitable for upload
|
||||
bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
|
||||
|
||||
void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
|
||||
const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }
|
||||
|
||||
const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
|
||||
void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
|
||||
|
||||
@@ -180,7 +181,7 @@ public:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool isNodeAJoint(const char* name)
|
||||
{
|
||||
return mJointMap.find(name) != mJointMap.end();
|
||||
return name != NULL && mJointMap.find(name) != mJointMap.end();
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -189,17 +190,14 @@ protected:
|
||||
LLModelLoader::joint_lookup_func_t mJointLookupFunc;
|
||||
LLModelLoader::texture_load_func_t mTextureLoadFunc;
|
||||
LLModelLoader::state_callback_t mStateCallback;
|
||||
void* mOpaqueData;
|
||||
void* mOpaqueData;
|
||||
|
||||
bool mRigParityWithScene;
|
||||
bool mRigValidJointUpload;
|
||||
bool mLegacyRigValid;
|
||||
|
||||
bool mNoNormalize;
|
||||
bool mNoOptimize;
|
||||
|
||||
JointSet mMasterJointList;
|
||||
JointSet mMasterLegacyJointList;
|
||||
JointTransformMap mJointTransformMap;
|
||||
|
||||
static std::list<LLModelLoader*> sActiveLoaderList;
|
||||
|
||||
@@ -440,6 +440,7 @@ set(viewer_SOURCE_FILES
|
||||
llscrollingpanelparambase.cpp
|
||||
llselectmgr.cpp
|
||||
llshareavatarhandler.cpp
|
||||
llskinningutil.cpp
|
||||
llsky.cpp
|
||||
llslurl.cpp
|
||||
llspatialpartition.cpp
|
||||
@@ -973,6 +974,7 @@ set(viewer_HEADER_FILES
|
||||
llscrollingpanelparambase.h
|
||||
llselectmgr.h
|
||||
llsimplestat.h
|
||||
llskinningutil.h
|
||||
llsky.h
|
||||
llslurl.h
|
||||
llspatialpartition.h
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
ATTRIBUTE vec4 weight4;
|
||||
|
||||
uniform mat3x4 matrixPalette[52];
|
||||
uniform mat3x4 matrixPalette[MAX_JOINTS_PER_MESH_OBJECT];
|
||||
uniform float maxWeight;
|
||||
|
||||
mat4 getObjectSkinnedTransform()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,81 +1,232 @@
|
||||
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
|
||||
<linden_skeleton version="1.0" num_bones="53" num_collision_volumes="26">
|
||||
<bone name="mPelvis" pos="0.000 0.000 1.067" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.000000 0.000000 1.067015">
|
||||
<collision_volume name="PELVIS" pos = "-0.01 0 -0.02" rot="0.000000 8.00000 0.000000" scale="0.12 0.16 0.17"/>
|
||||
<collision_volume name="BUTT" pos = "-0.06 0 -0.1" rot="0.000000 0.00000 0.000000" scale="0.1 0.1 0.1"/>
|
||||
<bone name="mTorso" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.000000 0.000000 0.084073">
|
||||
<collision_volume name="BELLY" pos = "0.028 0 0.04" rot="0.000000 8.00000 0.000000" scale="0.09 0.13 0.15"/>
|
||||
<collision_volume name="LOWER_BACK" pos = "0.0 0.0 0.023" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15"/>
|
||||
<collision_volume name="LEFT_HANDLE" pos = "0.0 0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05"/>
|
||||
<collision_volume name="RIGHT_HANDLE" pos = "0.0 -0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05"/>
|
||||
<bone name="mChest" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.015368 0.000000 0.204877">
|
||||
<collision_volume name="CHEST" pos = "0.028 0 0.07" rot="0.000000 -10.00000 0.000000" scale="0.11 0.15 0.2"/>
|
||||
<collision_volume name="UPPER_BACK" pos = "0.0 0.0 0.017" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15"/>
|
||||
<collision_volume name="LEFT_PEC" pos = "0.119 0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05"/>
|
||||
<collision_volume name="RIGHT_PEC" pos = "0.119 -0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05"/>
|
||||
<bone name="mNeck" pos="-0.010 0.000 0.251" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.009507 0.000000 0.251108">
|
||||
<collision_volume name="NECK" pos = "0.0 0 0.02" rot="0.000000 0.000000 0.000000" scale="0.05 0.06 0.08"/>
|
||||
<bone name="mHead" pos="0.000 -0.000 0.076" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.000000 -0.000000 0.075630">
|
||||
<collision_volume name="HEAD" pos = "0.02 0 0.07" rot="0.000000 0.000000 0.000000" scale="0.11 0.09 0.12"/>
|
||||
<bone name="mSkull" pos="0.000 0.000 0.079" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.000000 0.000000 0.079000">
|
||||
</bone>
|
||||
<bone name="mEyeRight" pos="0.098 -0.036 0.079" rot="0.000000 0.000000 -0.000000" scale="1.000 1.000 1.000" pivot="0.098466 -0.036000 0.079000">
|
||||
</bone>
|
||||
<bone name="mEyeLeft" pos="0.098 0.036 0.079" rot="0.000000 -0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.098461 0.036000 0.079000">
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone name="mCollarLeft" pos="-0.021 0.085 0.165" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.020927 0.084665 0.165396">
|
||||
<collision_volume name="L_CLAVICLE" pos = "0.02 0 0.02" rot="0.000000 0.00000 0.000000" scale="0.07 0.14 0.05"/>
|
||||
<bone name="mShoulderLeft" pos="0.000 0.079 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.000000 0.079000 -0.000000">
|
||||
<collision_volume name="L_UPPER_ARM" pos = "0.0 0.12 0.01" rot="-5.000000 0.00000 0.000000" scale="0.05 0.17 0.05"/>
|
||||
<bone name="mElbowLeft" pos="0.000 0.248 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.000000 0.248000 0.000000">
|
||||
<collision_volume name="L_LOWER_ARM" pos = "0.0 0.1 0.0" rot="-3.000000 0.00000 0.000000" scale="0.04 0.14 0.04"/>
|
||||
<bone name="mWristLeft" pos="-0.000 0.205 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.000000 0.204846 0.000000">
|
||||
<collision_volume name="L_HAND" pos = "0.01 0.05 0.0" rot="-3.000000 0.00000 -10.000000" scale="0.05 0.08 0.03"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone name="mCollarRight" pos="-0.021 -0.085 0.165" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.020927 -0.085000 0.165396">
|
||||
<collision_volume name="R_CLAVICLE" pos = "0.02 0 0.02" rot="0.000000 0.00000 0.000000" scale="0.07 0.14 0.05"/>
|
||||
<bone name="mShoulderRight" pos="0.000 -0.079 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.000000 -0.079418 -0.000000">
|
||||
<collision_volume name="R_UPPER_ARM" pos = "0.0 -0.12 0.01" rot="5.000000 0.00000 0.000000" scale="0.05 0.17 0.05"/>
|
||||
<bone name="mElbowRight" pos="0.000 -0.248 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.000000 -0.248000 -0.000000">
|
||||
<collision_volume name="R_LOWER_ARM" pos = "0.0 -0.1 0.0" rot="3.000000 0.00000 0.000000" scale="0.04 0.14 0.04"/>
|
||||
<bone name="mWristRight" pos="0.000 -0.205 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.000000 -0.205000 -0.000000">
|
||||
<collision_volume name="R_HAND" pos = "0.01 -0.05 0.0" rot="3.000000 0.00000 10.000000" scale="0.05 0.08 0.03"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone name="mHipRight" pos="0.034 -0.129 -0.041" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.033620 -0.128806 -0.041086">
|
||||
<collision_volume name="R_UPPER_LEG" pos = "-0.02 0.05 -0.22" rot="0.000000 0.00000 0.000000" scale="0.09 0.09 0.32"/>
|
||||
<bone name="mKneeRight" pos="-0.001 0.049 -0.491" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.000780 0.048635 -0.490922">
|
||||
<collision_volume name="R_LOWER_LEG" pos = "-0.02 0.0 -0.2" rot="0.000000 0.00000 0.000000" scale="0.06 0.06 0.25"/>
|
||||
<bone name="mAnkleRight" pos="-0.029 0.000 -0.468" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.028869 0.000000 -0.468494">
|
||||
<collision_volume name="R_FOOT" pos = "0.077 0.0 -0.041" rot="0.000000 10.00000 0.000000" scale="0.13 0.05 0.05"/>
|
||||
<bone name="mFootRight" pos="0.112 -0.000 -0.061" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.111956 -0.000000 -0.060637">
|
||||
<bone name="mToeRight" pos="0.109 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.105399 -0.010408 -0.000104">
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone name="mHipLeft" pos="0.034 0.127 -0.041" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.033757 0.126765 -0.040998">
|
||||
<collision_volume name="L_UPPER_LEG" pos = "-0.02 -0.05 -0.22" rot="0.000000 0.00000 0.000000" scale="0.09 0.09 0.32"/>
|
||||
<bone name="mKneeLeft" pos="-0.001 -0.046 -0.491" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.000887 -0.045568 -0.491053">
|
||||
<collision_volume name="L_LOWER_LEG" pos = "-0.02 0.0 -0.2" rot="0.000000 0.00000 0.000000" scale="0.06 0.06 0.25"/>
|
||||
<bone name="mAnkleLeft" pos="-0.029 0.001 -0.468" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="-0.028887 0.001378 -0.468449">
|
||||
<collision_volume name="L_FOOT" pos = "0.077 0.0 -0.041" rot="0.000000 10.00000 0.000000" scale="0.13 0.05 0.05"/>
|
||||
<bone name="mFootLeft" pos="0.112 -0.000 -0.061" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.111956 -0.000000 -0.060620">
|
||||
<bone name="mToeLeft" pos="0.109 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" pivot="0.105387 0.008270 0.000871">
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</linden_skeleton>
|
||||
<linden_skeleton num_bones="133" num_collision_volumes="26" version="2.0">
|
||||
<bone aliases="hip avatar_mPelvis" connected="false" end="0.000 0.000 0.084" group="Torso" name="mPelvis" pivot="0.000000 0.000000 1.067015" pos="0.000 0.000 1.067" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.030 0.000 0.095" group="Collision" name="PELVIS" pos="-0.01 0 -0.02" rot="0.000000 8.00000 0.000000" scale="0.12 0.16 0.17" support="base"/>
|
||||
<collision_volume end="-0.100 0.000 0.000" group="Collision" name="BUTT" pos="-0.06 0 -0.1" rot="0.000000 0.00000 0.000000" scale="0.1 0.1 0.1" support="base"/>
|
||||
<bone connected="true" end="0.000 0.000 -0.084" group="Spine" name="mSpine1" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.000 0.000 0.084" group="Spine" name="mSpine2" pivot="0.000000 0.000000 -0.084073" pos="0.000 0.000 -0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone aliases="abdomen avatar_mTorso" connected="true" end="-0.015 0.000 0.205" group="Torso" name="mTorso" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.028 0.000 0.094" group="Collision" name="BELLY" pos="0.028 0 0.04" rot="0.000000 8.00000 0.000000" scale="0.09 0.13 0.15" support="base"/>
|
||||
<collision_volume end="0.000 0.100 0.000" group="Collision" name="LEFT_HANDLE" pos="0.0 0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base"/>
|
||||
<collision_volume end="0.000 -0.100 0.000" group="Collision" name="RIGHT_HANDLE" pos="0.0 -0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base"/>
|
||||
<collision_volume end="-0.100 0.000 0.000" group="Collision" name="LOWER_BACK" pos="0.0 0.0 0.023" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15" support="base"/>
|
||||
<bone connected="true" end="0.015 0.000 -0.205" group="Spine" name="mSpine3" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.015 0.000 0.205" group="Spine" name="mSpine4" pivot="0.015368 0.000000 -0.204877" pos="0.015 0.000 -0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone aliases="chest avatar_mChest" connected="true" end="-0.010 0.000 0.250" group="Torso" name="mChest" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="-0.096 0.000 0.152" group="Collision" name="CHEST" pos="0.028 0 0.07" rot="0.000000 -10.00000 0.000000" scale="0.11 0.15 0.2" support="base"/>
|
||||
<collision_volume end="0.080 0.000 -0.006" group="Collision" name="LEFT_PEC" pos="0.119 0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05" support="base"/>
|
||||
<collision_volume end="0.080 0.000 -0.006" group="Collision" name="RIGHT_PEC" pos="0.119 -0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05" support="base"/>
|
||||
<collision_volume end="-0.100 0.000 0.000" group="Collision" name="UPPER_BACK" pos="0.0 0.0 0.017" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15" support="base"/>
|
||||
<bone aliases="neck avatar_mNeck" connected="true" end="0.000 0.000 0.077" group="Torso" name="mNeck" pivot="-0.009507 0.000000 0.251108" pos="-0.010 0.000 0.251" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 0.000 0.080" group="Collision" name="NECK" pos="0.0 0 0.02" rot="0.000000 0.000000 0.000000" scale="0.05 0.06 0.08" support="base"/>
|
||||
<bone aliases="head avatar_mHead" connected="true" end="0.000 0.000 0.079" group="Torso" name="mHead" pivot="0.000000 -0.000000 0.075630" pos="0.000 -0.000 0.076" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 0.000 0.100" group="Collision" name="HEAD" pos="0.02 0 0.07" rot="0.000000 0.000000 0.000000" scale="0.11 0.09 0.12" support="base"/>
|
||||
<bone aliases="figureHair avatar_mSkull" connected="false" end="0.000 0.000 0.033" group="Extra" name="mSkull" pivot="0.000000 0.000000 0.079000" pos="0.000 0.000 0.079" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/>
|
||||
<bone aliases="avatar_mEyeRight" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeRight" pivot="0.098466 -0.036000 0.079000" pos="0.098 -0.036 0.079" rot="0.000000 0.000000 -0.000000" scale="1.000 1.000 1.000" support="base"/>
|
||||
<bone aliases="avatar_mEyeLeft" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeLeft" pivot="0.098461 0.036000 0.079000" pos="0.098 0.036 0.079" rot="0.000000 -0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/>
|
||||
<bone connected="false" end="0.020 0.000 0.000" group="Face" name="mFaceRoot" pivot="0.025000 0.000000 0.045000" pos="0.025 0.000 0.045" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltRight" pivot="0.073466 -0.036000 0.0339300" pos="0.073 -0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltLeft" pivot="0.073461 0.036000 0.0339300" pos="0.073 0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.024 0.004 0.018" group="Face" name="mFaceForeheadLeft" pivot="0.061 0.035 0.083" pos="0.061 0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.024 -0.004 0.018" group="Face" name="mFaceForeheadRight" pivot="0.061 -0.035 0.083" pos="0.061 -0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.023 0.013 0.000" group="Eyes" name="mFaceEyebrowOuterLeft" pivot="0.064 0.051 0.048" pos="0.064 0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterLeft" pivot="0.070 0.043 0.056" pos="0.070 0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerLeft" pivot="0.075 0.022 0.051" pos="0.075 0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.023 -0.013 0.000" group="Eyes" name="mFaceEyebrowOuterRight" pivot="0.064 -0.051 0.048" pos="0.064 -0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterRight" pivot="0.070 -0.043 0.056" pos="0.070 -0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerRight" pivot="0.075 -0.022 0.051" pos="0.075 -0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="-0.019 0.018 0.025" group="Ears" name="mFaceEar1Left" pivot="0.000 0.080 0.002" pos="0.000 0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Left" pivot="-0.019 0.018 0.025" pos="-0.019 0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
<bone connected="false" end="-0.019 -0.018 0.025" group="Ears" name="mFaceEar1Right" pivot="0.000 -0.080 0.002" pos="0.000 -0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Right" pivot="-0.019 -0.018 0.025" pos="-0.019 -0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
<bone connected="false" end="0.015 0.004 0.000" group="Face" name="mFaceNoseLeft" pivot="0.086 0.015 -0.004" pos="0.086 0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceNoseCenter" pivot="0.102 0.000 0.000" pos="0.102 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.015 -0.004 0.000" group="Face" name="mFaceNoseRight" pivot="0.086 -0.015 -0.004" pos="0.086 -0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.013 0.030 0.000" group="Face" name="mFaceCheekLowerLeft" pivot="0.050 0.034 -0.031" pos="0.050 0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.022 0.015 0.000" group="Face" name="mFaceCheekUpperLeft" pivot="0.070 0.034 -0.005" pos="0.070 0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.013 -0.030 0.000" group="Face" name="mFaceCheekLowerRight" pivot="0.050 -0.034 -0.031" pos="0.050 -0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.022 -0.015 0.000" group="Face" name="mFaceCheekUpperRight" pivot="0.070 -0.034 -0.005" pos="0.070 -0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.059 0.000 -0.039" group="Mouth" name="mFaceJaw" pivot="-0.001 0.000 -0.015" pos="-0.001 0.000 -0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="false" end="0.021 0.000 -0.018" group="Mouth" name="mFaceChin" pivot="0.074 0.000 -0.054" pos="0.074 0.000 -0.054" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethLower" pivot="0.021 0.000 -0.039" pos="0.021 0.000 -0.039" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="false" end="0.034 0.017 0.005" group="Lips" name="mFaceLipLowerLeft" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.034 -0.017 0.005" group="Lips" name="mFaceLipLowerRight" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.040 0.000 0.002" group="Lips" name="mFaceLipLowerCenter" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.022 0.000 0.007" group="Mouth" name="mFaceTongueBase" pivot="0.039 0.000 0.005" pos="0.039 0.000 0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.010 0.000 0.000" group="Mouth" name="mFaceTongueTip" pivot="0.022 0.000 0.007" pos="0.022 0.000 0.007" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="-0.017 0.000 0.000" group="Face" name="mFaceJawShaper" pivot="0.000 0.000 0.000" pos="0.000 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.036 0.000 0.000" group="Face" name="mFaceForeheadCenter" pivot="0.069 0.000 0.065" pos="0.069 0.000 0.065" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.014 0.000 0.000" group="Nose" name="mFaceNoseBase" pivot="0.094 0.000 -0.016" pos="0.094 0.000 -0.016" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethUpper" pivot="0.020 0.000 -0.030" pos="0.020 0.000 -0.030" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="false" end="0.041 0.015 0.000" group="Lips" name="mFaceLipUpperLeft" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.041 -0.015 0.000" group="Lips" name="mFaceLipUpperRight" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.045 0.051 0.000" group="Lips" name="mFaceLipCornerLeft" pivot="0.028 -0.019 -0.010" pos="0.028 -0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.045 -0.051 0.000" group="Lips" name="mFaceLipCornerRight" pivot="0.028 0.019 -0.010" pos="0.028 0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.043 0.000 0.002" group="Lips" name="mFaceLipUpperCenter" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
<bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerLeft" pivot="0.075 0.017 0.032" pos="0.075 0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerRight" pivot="0.075 -0.017 0.032" pos="0.075 -0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="0.015 0.000 0.008" group="Nose" name="mFaceNoseBridge" pivot="0.091 0.000 0.020" pos="0.091 0.000 0.020" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone aliases="lCollar avatar_mCollarLeft" connected="false" end="0.000 0.079 0.000" group="Arms" name="mCollarLeft" pivot="-0.020927 0.084665 0.165396" pos="-0.021 0.085 0.165" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 0.100 0.000" group="Collision" name="L_CLAVICLE" pos="0.02 0 0.02" rot="0.000000 0.00000 0.000000" scale="0.07 0.14 0.05" support="base"/>
|
||||
<bone aliases="lShldr avatar_mShoulderLeft" connected="true" end="0.000 0.247 0.000" group="Arms" name="mShoulderLeft" pivot="0.000000 0.079000 -0.000000" pos="0.000 0.079 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 0.130 -0.003" group="Collision" name="L_UPPER_ARM" pos="0.0 0.12 0.01" rot="-5.000000 0.00000 0.000000" scale="0.05 0.17 0.05" support="base"/>
|
||||
<bone aliases="lForeArm avatar_mElbowLeft" connected="true" end="0.000 0.205 0.000" group="Arms" name="mElbowLeft" pivot="0.000000 0.248000 0.000000" pos="0.000 0.248 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 0.100 -0.001" group="Collision" name="L_LOWER_ARM" pos="0.0 0.1 0.0" rot="-3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base"/>
|
||||
<bone aliases="lHand avatar_mWristLeft" connected="true" end="0.000 0.060 0.000" group="Arms" name="mWristLeft" pivot="-0.000000 0.204846 0.000000" pos="-0.000 0.205 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.005 0.049 -0.001" group="Collision" name="L_HAND" pos="0.01 0.05 0.0" rot="-3.000000 0.00000 -10.000000" scale="0.05 0.08 0.03" support="base"/>
|
||||
<bone connected="false" end="-0.001 0.040 -0.006" group="Hand" name="mHandMiddle1Left" pivot="0.013 0.101 0.015" pos="0.013 0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.001 0.049 -0.008" group="Hand" name="mHandMiddle2Left" pivot="-0.001 0.040 -0.006" pos="-0.001 0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.002 0.033 -0.006" group="Hand" name="mHandMiddle3Left" pivot="-0.001 0.049 -0.008" pos="-0.001 0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="0.017 0.036 -0.006" group="Hand" name="mHandIndex1Left" pivot="0.038 0.097 0.015" pos="0.038 0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.014 0.032 -0.006" group="Hand" name="mHandIndex2Left" pivot="0.017 0.036 -0.006" pos="0.017 0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.011 0.025 -0.004" group="Hand" name="mHandIndex3Left" pivot="0.014 0.032 -0.006" pos="0.014 0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="-0.013 0.038 -0.008" group="Hand" name="mHandRing1Left" pivot="-0.010 0.099 0.009" pos="-0.010 0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.013 0.040 -0.009" group="Hand" name="mHandRing2Left" pivot="-0.013 0.038 -0.008" pos="-0.013 0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.010 0.028 -0.006" group="Hand" name="mHandRing3Left" pivot="-0.013 0.040 -0.009" pos="-0.013 0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="-0.024 0.025 -0.006" group="Hand" name="mHandPinky1Left" pivot="-0.031 0.095 0.003" pos="-0.031 0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.015 0.018 -0.004" group="Hand" name="mHandPinky2Left" pivot="-0.024 0.025 -0.006" pos="-0.024 0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.013 0.016 -0.004" group="Hand" name="mHandPinky3Left" pivot="-0.015 0.018 -0.004" pos="-0.015 0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="0.028 0.032 0.000" group="Hand" name="mHandThumb1Left" pivot="0.031 0.026 0.004" pos="0.031 0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.023 0.031 0.000" group="Hand" name="mHandThumb2Left" pivot="0.028 0.032 -0.001" pos="0.028 0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.015 0.025 0.000" group="Hand" name="mHandThumb3Left" pivot="0.023 0.031 -0.001" pos="0.023 0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone aliases="rCollar avatar_mCollarRight" connected="false" end="0.000 -0.079 0.000" group="Arms" name="mCollarRight" pivot="-0.020927 -0.085000 0.165396" pos="-0.021 -0.085 0.165" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 -0.100 0.000" group="Collision" name="R_CLAVICLE" pos="0.02 0 0.02" rot="0.000000 0.00000 0.000000" scale="0.07 0.14 0.05" support="base"/>
|
||||
<bone aliases="rShldr avatar_mShoulderRight" connected="true" end="0.000 -0.247 0.000" group="Arms" name="mShoulderRight" pivot="0.000000 -0.079418 -0.000000" pos="0.000 -0.079 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 -0.130 -0.003" group="Collision" name="R_UPPER_ARM" pos="0.0 -0.12 0.01" rot="5.000000 0.00000 0.000000" scale="0.05 0.17 0.05" support="base"/>
|
||||
<bone aliases="rForeArm avatar_mElbowRight" connected="true" end="0.000 -0.205 0.000" group="Arms" name="mElbowRight" pivot="0.000000 -0.248000 -0.000000" pos="0.000 -0.248 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 -0.100 -0.001" group="Collision" name="R_LOWER_ARM" pos="0.0 -0.1 0.0" rot="3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base"/>
|
||||
<bone aliases="rHand avatar_mWristRight" connected="true" end="0.000 -0.060 0.000" group="Arms" name="mWristRight" pivot="-0.000000 -0.205000 -0.000000" pos="0.000 -0.205 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.005 -0.049 -0.001" group="Collision" name="R_HAND" pos="0.01 -0.05 0.0" rot="3.000000 0.00000 10.000000" scale="0.05 0.08 0.03" support="base"/>
|
||||
<bone connected="false" end="-0.001 -0.040 -0.006" group="Hand" name="mHandMiddle1Right" pivot="0.013 -0.101 0.015" pos="0.013 -0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.001 -0.049 -0.008" group="Hand" name="mHandMiddle2Right" pivot="-0.001 -0.040 -0.006" pos="-0.001 -0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.002 -0.033 -0.006" group="Hand" name="mHandMiddle3Right" pivot="-0.001 -0.049 -0.008" pos="-0.001 -0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="0.017 -0.036 -0.006" group="Hand" name="mHandIndex1Right" pivot="0.038 -0.097 0.015" pos="0.038 -0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.014 -0.032 -0.006" group="Hand" name="mHandIndex2Right" pivot="0.017 -0.036 -0.006" pos="0.017 -0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.011 -0.025 -0.004" group="Hand" name="mHandIndex3Right" pivot="0.014 -0.032 -0.006" pos="0.014 -0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="-0.013 -0.038 -0.008" group="Hand" name="mHandRing1Right" pivot="-0.010 -0.099 0.009" pos="-0.010 -0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.013 -0.040 -0.009" group="Hand" name="mHandRing2Right" pivot="-0.013 -0.038 -0.008" pos="-0.013 -0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.010 -0.028 -0.006" group="Hand" name="mHandRing3Right" pivot="-0.013 -0.040 -0.009" pos="-0.013 -0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="-0.024 -0.025 -0.006" group="Hand" name="mHandPinky1Right" pivot="-0.031 -0.095 0.003" pos="-0.031 -0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.015 -0.018 -0.004" group="Hand" name="mHandPinky2Right" pivot="-0.024 -0.025 -0.006" pos="-0.024 -0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.013 -0.016 -0.004" group="Hand" name="mHandPinky3Right" pivot="-0.015 -0.018 -0.004" pos="-0.015 -0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="0.028 -0.032 0.000" group="Hand" name="mHandThumb1Right" pivot="0.031 -0.026 0.004" pos="0.031 -0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.023 -0.031 0.000" group="Hand" name="mHandThumb2Right" pivot="0.028 -0.032 -0.001" pos="0.028 -0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.015 -0.025 0.000" group="Hand" name="mHandThumb3Right" pivot="0.023 -0.031 -0.001" pos="0.023 -0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="-0.061 0.000 0.000" group="Wing" name="mWingsRoot" pivot="-0.014 0.000 0.000" pos="-0.014 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="false" end="-0.168 0.169 0.067" group="Wing" name="mWing1Left" pivot="-0.099 0.105 0.181" pos="-0.099 0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.181 0.183 0.000" group="Wing" name="mWing2Left" pivot="-0.168 0.169 0.067" pos="-0.168 0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.171 0.173 0.000" group="Wing" name="mWing3Left" pivot="-0.181 0.183 0.000" pos="-0.181 0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.146 0.132 0.000" group="Wing" name="mWing4Left" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="true" end="-0.068 0.062 -0.159" group="Wing" name="mWing4FanLeft" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="-0.168 -0.169 0.067" group="Wing" name="mWing1Right" pivot="-0.099 -0.105 0.181" pos="-0.099 -0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.181 -0.183 0.000" group="Wing" name="mWing2Right" pivot="-0.168 -0.169 0.067" pos="-0.168 -0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.171 -0.173 0.000" group="Wing" name="mWing3Right" pivot="-0.181 -0.183 0.000" pos="-0.181 -0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.146 -0.132 0.000" group="Wing" name="mWing4Right" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="true" end="-0.068 -0.062 -0.159" group="Wing" name="mWing4FanRight" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone aliases="rThigh avatar_mHipRight" connected="false" end="-0.001 0.049 -0.491" group="Legs" name="mHipRight" pivot="0.033620 -0.128806 -0.041086" pos="0.034 -0.129 -0.041" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 0.000 -0.200" group="Collision" name="R_UPPER_LEG" pos="-0.02 0.05 -0.22" rot="0.000000 0.00000 0.000000" scale="0.09 0.09 0.32" support="base"/>
|
||||
<bone aliases="rShin avatar_mKneeRight" connected="true" end="-0.029 0.000 -0.469" group="Legs" name="mKneeRight" pivot="-0.000780 0.048635 -0.490922" pos="-0.001 0.049 -0.491" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="-0.010 0.000 -0.150" group="Collision" name="R_LOWER_LEG" pos="-0.02 0.0 -0.2" rot="0.000000 0.00000 0.000000" scale="0.06 0.06 0.25" support="base"/>
|
||||
<bone aliases="rFoot avatar_mAnkleRight" connected="true" end="0.112 0.000 -0.061" group="Legs" name="mAnkleRight" pivot="-0.028869 0.000000 -0.468494" pos="-0.029 0.000 -0.468" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.089 0.000 -0.026" group="Collision" name="R_FOOT" pos="0.077 0.0 -0.041" rot="0.000000 10.00000 0.000000" scale="0.13 0.05 0.05" support="base"/>
|
||||
<bone aliases="avatar_mFootRight" connected="true" end="0.105 -0.010 0.000" group="Extra" name="mFootRight" pivot="0.111956 -0.000000 -0.060637" pos="0.112 -0.000 -0.061" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<bone aliases="avatar_mToeRight" connected="false" end="0.020 0.000 0.000" group="Extra" name="mToeRight" pivot="0.105399 -0.010408 -0.000104" pos="0.109 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone aliases="lThigh avatar_mHipLeft" connected="false" end="-0.001 -0.046 -0.491" group="Legs" name="mHipLeft" pivot="0.033757 0.126765 -0.040998" pos="0.034 0.127 -0.041" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.000 0.000 -0.200" group="Collision" name="L_UPPER_LEG" pos="-0.02 -0.05 -0.22" rot="0.000000 0.00000 0.000000" scale="0.09 0.09 0.32" support="base"/>
|
||||
<bone aliases="lShin avatar_mKneeLeft" connected="true" end="-0.029 0.001 -0.469" group="Legs" name="mKneeLeft" pivot="-0.000887 -0.045568 -0.491053" pos="-0.001 -0.046 -0.491" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="-0.010 0.000 -0.150" group="Collision" name="L_LOWER_LEG" pos="-0.02 0.0 -0.2" rot="0.000000 0.00000 0.000000" scale="0.06 0.06 0.25" support="base"/>
|
||||
<bone aliases="lFoot avatar_mAnkleLeft" connected="true" end="0.112 0.000 -0.061" group="Legs" name="mAnkleLeft" pivot="-0.028887 0.001378 -0.468449" pos="-0.029 0.001 -0.468" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<collision_volume end="0.089 0.000 -0.026" group="Collision" name="L_FOOT" pos="0.077 0.0 -0.041" rot="0.000000 10.00000 0.000000" scale="0.13 0.05 0.05" support="base"/>
|
||||
<bone aliases="avatar_mFootLeft" connected="true" end="0.105 0.008 0.001" group="Extra" name="mFootLeft" pivot="0.111956 -0.000000 -0.060620" pos="0.112 -0.000 -0.061" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
|
||||
<bone aliases="avatar_mToeLeft" connected="false" end="0.020 0.000 0.000" group="Extra" name="mToeLeft" pivot="0.105387 0.008270 0.000871" pos="0.109 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="-0.197 0.000 0.000" group="Tail" name="mTail1" pivot="-0.116 0.000 0.047" pos="-0.116 0.000 0.047" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.168 0.000 0.000" group="Tail" name="mTail2" pivot="-0.197 0.000 0.000" pos="-0.197 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.142 0.000 0.000" group="Tail" name="mTail3" pivot="-0.168 0.000 0.000" pos="-0.168 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.112 0.000 0.000" group="Tail" name="mTail4" pivot="-0.142 0.000 0.000" pos="-0.142 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.094 0.000 0.000" group="Tail" name="mTail5" pivot="-0.112 0.000 0.000" pos="-0.112 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.089 0.000 0.000" group="Tail" name="mTail6" pivot="-0.094 0.000 0.000" pos="-0.094 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="0.004 0.000 -0.066" group="Groin" name="mGroin" pivot="0.064 0.000 -0.097" pos="0.064 0.000 -0.097" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
<bone connected="false" end="-0.204 0.000 0.000" group="Limb" name="mHindLimbsRoot" pivot="-0.200 0.000 0.084" pos="-0.200 0.000 0.084" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="false" end="0.002 -0.046 -0.491" group="Limb" name="mHindLimb1Left" pivot="-0.204 0.129 -0.125" pos="-0.204 0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.030 -0.003 -0.468" group="Limb" name="mHindLimb2Left" pivot="0.002 -0.046 -0.491" pos="0.002 -0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Left" pivot="-0.030 -0.003 -0.468" pos="-0.030 -0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.105 0.008 0.000" group="Limb" name="mHindLimb4Left" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
<bone connected="false" end="0.002 0.046 -0.491" group="Limb" name="mHindLimb1Right" pivot="-0.204 -0.129 -0.125" pos="-0.204 -0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="-0.030 0.003 -0.468" group="Limb" name="mHindLimb2Right" pivot="0.002 0.046 -0.491" pos="0.002 0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Right" pivot="-0.030 0.003 -0.468" pos="-0.030 0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
|
||||
<bone connected="true" end="0.105 -0.008 0.000" group="Limb" name="mHindLimb4Right" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</bone>
|
||||
</linden_skeleton>
|
||||
|
||||
@@ -4580,7 +4580,7 @@ void LLAgent::requestLeaveGodMode()
|
||||
sendReliableMessage();
|
||||
}
|
||||
|
||||
extern void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value);
|
||||
extern void dump_visual_param(apr_file_t* file, LLVisualParam const* viewer_param, F32 value);
|
||||
extern std::string get_sequential_numbered_file_name(const std::string& prefix,
|
||||
const std::string& suffix);
|
||||
|
||||
@@ -4606,7 +4606,7 @@ void LLAgent::dumpSentAppearance(const std::string& dump_prefix)
|
||||
if (appearance_version_param)
|
||||
{
|
||||
F32 value = appearance_version_param->getWeight();
|
||||
dump_visual_param(outfile, appearance_version_param, value);
|
||||
dump_visual_param(file, appearance_version_param, value);
|
||||
}
|
||||
for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
|
||||
iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();
|
||||
|
||||
@@ -2624,7 +2624,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
|
||||
// attachments, even those that are not being removed. This is
|
||||
// needed to get joint positions all slammed down to their
|
||||
// pre-attachment states.
|
||||
gAgentAvatarp->clearAttachmentPosOverrides();
|
||||
gAgentAvatarp->clearAttachmentOverrides();
|
||||
|
||||
// Take off the attachments that will no longer be in the outfit.
|
||||
// (but don't remove attachments until avatar is fully loaded - should reduce random attaching/detaching/reattaching at log-on)
|
||||
@@ -2638,7 +2638,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
|
||||
for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin(); it != objects_to_retain.end(); ++it)
|
||||
{
|
||||
LLViewerObject *objectp = *it;
|
||||
gAgentAvatarp->addAttachmentPosOverridesForObject(objectp);
|
||||
gAgentAvatarp->addAttachmentOverridesForObject(objectp);
|
||||
}
|
||||
|
||||
// Add new attachments to match those requested.
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
#include "llweb.h"
|
||||
#include "llsecondlifeurls.h"
|
||||
#include "llavatarrenderinfoaccountant.h"
|
||||
#include "llskinningutil.h"
|
||||
|
||||
// Linden library includes
|
||||
#include "llavatarnamecache.h"
|
||||
@@ -674,6 +675,10 @@ bool LLAppViewer::init()
|
||||
|
||||
LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ;
|
||||
|
||||
|
||||
// initialize skinning util
|
||||
LLSkinningUtil::initClass();
|
||||
|
||||
//set the max heap size.
|
||||
initMaxHeapSize() ;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "lldrawpoolavatar.h"
|
||||
#include "llskinningutil.h"
|
||||
#include "llrender.h"
|
||||
|
||||
#include "llvoavatar.h"
|
||||
@@ -366,7 +367,7 @@ void LLDrawPoolAvatar::endPostDeferredAlpha()
|
||||
|
||||
void LLDrawPoolAvatar::renderPostDeferred(S32 pass)
|
||||
{
|
||||
const S32 actual_pass[] =
|
||||
static const S32 actual_pass[] =
|
||||
{ //map post deferred pass numbers to what render() expects
|
||||
2, //skinned
|
||||
4, // rigged fullbright
|
||||
@@ -1516,33 +1517,18 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
|
||||
{
|
||||
if (sShaderLevel > 0)
|
||||
{ //upload matrix palette to shader
|
||||
LLMatrix4 mat[JOINT_COUNT];
|
||||
// upload matrix palette to shader
|
||||
LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
|
||||
U32 count = LLSkinningUtil::getMeshJointCount(skin);
|
||||
LLSkinningUtil::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("mRoot");
|
||||
}
|
||||
if (joint)
|
||||
{
|
||||
LLMatrix4a tmp;
|
||||
tmp.loadu((F32*)skin->mInvBindMatrix[i].mMatrix);
|
||||
tmp.setMul(joint->getWorldMatrix(),tmp);
|
||||
mat[i] = LLMatrix4(tmp.getF32ptr());
|
||||
}
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
|
||||
F32 mp[JOINT_COUNT*12];
|
||||
F32 mp[LL_MAX_JOINTS_PER_MESH_OBJECT*12];
|
||||
|
||||
for (U32 i = 0; i < count; ++i)
|
||||
{
|
||||
F32* m = (F32*) mat[i].mMatrix;
|
||||
F32* m = (F32*) mat[i].getF32ptr();
|
||||
|
||||
U32 idx = i*12;
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "llmatrix4a.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llsdutil_math.h"
|
||||
#include "llskinningutil.h"
|
||||
#include "lltextbox.h"
|
||||
#include "lltoolmgr.h"
|
||||
#include "llui.h"
|
||||
@@ -648,6 +649,10 @@ void LLFloaterModelPreview::draw()
|
||||
{
|
||||
LLFloater::draw();
|
||||
|
||||
if (!mModelPreview)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mModelPreview->update();
|
||||
|
||||
if (!mModelPreview->mLoading)
|
||||
@@ -1190,7 +1195,6 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
|
||||
, mPhysicsSearchLOD( LLModel::LOD_PHYSICS )
|
||||
, mResetJoints( false )
|
||||
, mModelNoErrors( true )
|
||||
, mRigParityWithScene( false )
|
||||
, mLastJointUpdate( false )
|
||||
{
|
||||
mNeedsUpdate = TRUE;
|
||||
@@ -1309,15 +1313,16 @@ U32 LLModelPreview::calcResourceCost()
|
||||
|
||||
std::stringstream ostr;
|
||||
LLSD ret = LLModel::writeModel(ostr,
|
||||
instance.mLOD[4],
|
||||
instance.mLOD[3],
|
||||
instance.mLOD[2],
|
||||
instance.mLOD[1],
|
||||
instance.mLOD[0],
|
||||
decomp,
|
||||
mFMP->childGetValue("upload_skin").asBoolean(),
|
||||
mFMP->childGetValue("upload_joints").asBoolean(),
|
||||
TRUE,
|
||||
instance.mLOD[4],
|
||||
instance.mLOD[3],
|
||||
instance.mLOD[2],
|
||||
instance.mLOD[1],
|
||||
instance.mLOD[0],
|
||||
decomp,
|
||||
mFMP->childGetValue("upload_skin").asBoolean(),
|
||||
mFMP->childGetValue("upload_joints").asBoolean(),
|
||||
false,
|
||||
TRUE,
|
||||
FALSE,
|
||||
instance.mModel->mSubmodelID);
|
||||
|
||||
@@ -1696,7 +1701,8 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
|
||||
instance.mLOD[LLModel::LOD_LOW],
|
||||
instance.mLOD[LLModel::LOD_IMPOSTOR],
|
||||
decomp,
|
||||
save_skinweights, save_joint_positions,
|
||||
save_skinweights,
|
||||
save_joint_positions,
|
||||
FALSE, TRUE, instance.mModel->mSubmodelID);
|
||||
|
||||
data["mesh"][instance.mModel->mLocalID] = str.str();
|
||||
@@ -1723,6 +1729,20 @@ void LLModelPreview::clearModel(S32 lod)
|
||||
mScene[lod].clear();
|
||||
}
|
||||
|
||||
void LLModelPreview::getJointAliases( JointMap& joint_map)
|
||||
{
|
||||
// Get all standard skeleton joints from the preview avatar.
|
||||
LLVOAvatar *av = getPreviewAvatar();
|
||||
|
||||
//Joint names and aliases come from avatar_skeleton.xml
|
||||
|
||||
joint_map = av->getJointAliases();
|
||||
for (S32 i = 0; i < av->mCollisionVolumes.size(); i++)
|
||||
{
|
||||
joint_map[av->mCollisionVolumes[i]->getName()] = av->mCollisionVolumes[i]->getName();
|
||||
}
|
||||
}
|
||||
|
||||
void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable_slm)
|
||||
{
|
||||
assert_main_thread();
|
||||
@@ -1765,8 +1785,11 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
|
||||
clearGLODGroup();
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> joint_alias_map;
|
||||
getJointAliases(joint_alias_map);
|
||||
|
||||
mModelLoader = new LLDAELoader(
|
||||
filename,
|
||||
filename,
|
||||
lod,
|
||||
&LLModelPreview::loadedCallback,
|
||||
&LLModelPreview::lookupJointByName,
|
||||
@@ -1775,6 +1798,8 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
|
||||
this,
|
||||
mJointTransformMap,
|
||||
mJointsFromNode,
|
||||
joint_alias_map,
|
||||
LLSkinningUtil::getMaxJointCount(),
|
||||
gSavedSettings.getU32("ImporterModelLimit"),
|
||||
gSavedSettings.getBOOL("ImporterPreprocessDAE"));
|
||||
|
||||
@@ -3401,9 +3426,11 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
|
||||
|
||||
for (U32 i = 0; i < weight_list.size(); ++i)
|
||||
{
|
||||
F32 wght = llmin(weight_list[i].mWeight, 0.999999f);
|
||||
F32 wght = llclamp(weight_list[i].mWeight, 0.001f, 0.999f);
|
||||
F32 joint = (F32) weight_list[i].mJointIdx;
|
||||
w.mV[i] = joint + wght;
|
||||
llassert(w.mV[i]-(S32)w.mV[i]>0.0f); // because weights are non-zero, and range of wt values
|
||||
//should not cause floating point precision issues.
|
||||
}
|
||||
|
||||
(*(weights_strider++)).loadua(w.mV);
|
||||
@@ -4098,20 +4125,6 @@ BOOL LLModelPreview::render()
|
||||
LLVector3::z_axis, // up
|
||||
target_pos); // point of interest
|
||||
|
||||
if (joint_positions)
|
||||
{
|
||||
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
|
||||
if (shader)
|
||||
{
|
||||
gDebugProgram.bind();
|
||||
}
|
||||
getPreviewAvatar()->renderCollisionVolumes();
|
||||
if (shader)
|
||||
{
|
||||
shader->bind();
|
||||
}
|
||||
}
|
||||
|
||||
for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
|
||||
{
|
||||
for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
|
||||
@@ -4160,6 +4173,22 @@ BOOL LLModelPreview::render()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (joint_positions)
|
||||
{
|
||||
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
|
||||
if (shader)
|
||||
{
|
||||
gDebugProgram.bind();
|
||||
}
|
||||
getPreviewAvatar()->renderCollisionVolumes();
|
||||
getPreviewAvatar()->renderBones();
|
||||
if (shader)
|
||||
{
|
||||
shader->bind();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4295,7 +4324,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();
|
||||
|
||||
@@ -253,6 +253,7 @@ public:
|
||||
virtual BOOL needsRender() { return mNeedsUpdate; }
|
||||
void setPreviewLOD(S32 lod);
|
||||
void clearModel(S32 lod);
|
||||
void getJointAliases(JointMap& joint_map);
|
||||
void loadModel(std::string filename, S32 lod, bool force_disable_slm = false);
|
||||
void loadModelCallback(S32 lod);
|
||||
bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); }
|
||||
@@ -404,7 +405,7 @@ private:
|
||||
|
||||
bool mLastJointUpdate;
|
||||
|
||||
JointSet mJointsFromNode;
|
||||
JointNameSet mJointsFromNode;
|
||||
JointTransformMap mJointTransformMap;
|
||||
|
||||
LLPointer<LLVOAvatar> mPreviewAvatar;
|
||||
|
||||
225
indra/newview/llskinningutil.cpp
Normal file
225
indra/newview/llskinningutil.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* @file llskinningutil.cpp
|
||||
* @brief Functions for mesh object skinning
|
||||
* @author vir@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2015, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llskinningutil.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llmeshrepository.h"
|
||||
|
||||
// static
|
||||
void LLSkinningUtil::initClass()
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
U32 LLSkinningUtil::getMaxJointCount()
|
||||
{
|
||||
U32 result = LL_MAX_JOINTS_PER_MESH_OBJECT;
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin)
|
||||
{
|
||||
return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size());
|
||||
}
|
||||
|
||||
// static
|
||||
void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin)
|
||||
{
|
||||
if (skin->mInvalidJointsScrubbed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (U32 j = 0; j < skin->mJointNames.size(); ++j)
|
||||
{
|
||||
// Fix invalid names to "mPelvis". Currently meshes with
|
||||
// invalid names will be blocked on upload, so this is just
|
||||
// needed for handling of any legacy bad data.
|
||||
if (!avatar->getJoint(skin->mJointNames[j]))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "Mesh rigged to invalid joint" << skin->mJointNames[j] << LL_ENDL;
|
||||
skin->mJointNames[j] = "mPelvis";
|
||||
}
|
||||
}
|
||||
skin->mInvalidJointsScrubbed = true;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLSkinningUtil::initSkinningMatrixPalette(
|
||||
LLMatrix4a* mat,
|
||||
S32 count,
|
||||
const LLMeshSkinInfo* skin,
|
||||
LLVOAvatar *avatar)
|
||||
{
|
||||
for (U32 j = 0; j < (U32)count; ++j)
|
||||
{
|
||||
LLJoint *joint = NULL;
|
||||
if( skin->mJointNums[j] <= -50 )
|
||||
{
|
||||
// Give up silently.
|
||||
mat[j].loadu((F32*)skin->mInvBindMatrix[j].mMatrix);
|
||||
continue;
|
||||
}
|
||||
else if (skin->mJointNums[j] < 0 )
|
||||
{
|
||||
joint = avatar->getJoint(skin->mJointNames[j]);
|
||||
if (!joint)
|
||||
{
|
||||
LL_WARNS_ONCE("Avatar") << "Rigged to invalid joint name " << skin->mJointNames[j] << " Using 'root' fallback." << LL_ENDL;
|
||||
joint = avatar->getJoint("mRoot");
|
||||
}
|
||||
if (joint)
|
||||
{
|
||||
//LL_INFOS() << "Found joint " << skin->mJointNames[j] << " Id = " << joint->getJointNum() << LL_ENDL;
|
||||
skin->mJointNums[j] = joint->getJointNum();
|
||||
}
|
||||
else
|
||||
{
|
||||
--skin->mJointNums[j];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
joint = avatar->getJoint(skin->mJointNums[j]);
|
||||
if (!joint)
|
||||
{
|
||||
LL_WARNS_ONCE() << "Joint not found: " << skin->mJointNames[j] << " Id = " << skin->mJointNums[j] << LL_ENDL;
|
||||
}
|
||||
}
|
||||
if (joint)
|
||||
{
|
||||
LLMatrix4a bind;
|
||||
bind.loadu((F32*)skin->mInvBindMatrix[j].mMatrix);
|
||||
mat[j].setMul(joint->getWorldMatrix(), bind);
|
||||
}
|
||||
else
|
||||
{
|
||||
mat[j].loadu((F32*)skin->mInvBindMatrix[j].mMatrix);
|
||||
// This shouldn't happen - in mesh upload, skinned
|
||||
// rendering should be disabled unless all joints are
|
||||
// valid. In other cases of skinned rendering, invalid
|
||||
// joints should already have been removed during scrubInvalidJoints().
|
||||
LL_WARNS_ONCE("Avatar") << "Rigged to invalid joint name " << skin->mJointNames[j] << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLSkinningUtil::checkSkinWeights(const LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)
|
||||
{
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
const S32 max_joints = skin->mJointNames.size();
|
||||
for (U32 j=0; j<num_vertices; j++)
|
||||
{
|
||||
F32 *w = weights[j].getF32ptr();
|
||||
|
||||
F32 wsum = 0.0;
|
||||
for (U32 k=0; k<4; ++k)
|
||||
{
|
||||
S32 i = llfloor(w[k]);
|
||||
llassert(i>=0);
|
||||
llassert(i<max_joints);
|
||||
wsum += w[k]-i;
|
||||
}
|
||||
llassert(wsum > 0.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLSkinningUtil::scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)
|
||||
{
|
||||
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] = i + f;
|
||||
}
|
||||
}
|
||||
checkSkinWeights(weights, num_vertices, skin);
|
||||
}
|
||||
|
||||
// static
|
||||
void LLSkinningUtil::getPerVertexSkinMatrix(
|
||||
const F32* weights,
|
||||
LLMatrix4a* mat,
|
||||
bool handle_bad_scale,
|
||||
LLMatrix4a& final_mat,
|
||||
U32 max_joints)
|
||||
{
|
||||
bool valid_weights = true;
|
||||
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] = (S32) floorf(w);
|
||||
|
||||
wght[k] = w - floorf(w);
|
||||
scale += wght[k];
|
||||
}
|
||||
if (handle_bad_scale && scale <= 0.f)
|
||||
{
|
||||
wght = LLVector4(F32_MAX,F32_MAX,F32_MAX,F32_MAX);
|
||||
valid_weights = false;
|
||||
}
|
||||
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);
|
||||
}
|
||||
// SL-366 - with weight validation/cleanup code, it should no longer be
|
||||
// possible to hit the bad scale case.
|
||||
llassert(valid_weights);
|
||||
}
|
||||
|
||||
47
indra/newview/llskinningutil.h
Normal file
47
indra/newview/llskinningutil.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file llskinningutil.h
|
||||
* @brief Functions for mesh object skinning
|
||||
* @author vir@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2015, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LLSKINNINGUTIL_H
|
||||
#define LLSKINNINGUTIL_H
|
||||
|
||||
class LLVOAvatar;
|
||||
class LLMeshSkinInfo;
|
||||
class LLMatrix4a;
|
||||
|
||||
class LLSkinningUtil
|
||||
{
|
||||
public:
|
||||
static void initClass();
|
||||
static U32 getMaxJointCount();
|
||||
static U32 getMeshJointCount(const LLMeshSkinInfo *skin);
|
||||
static void scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin);
|
||||
static void initSkinningMatrixPalette(LLMatrix4a* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar);
|
||||
static void checkSkinWeights(const LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
|
||||
static void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
|
||||
static void getPerVertexSkinMatrix(const F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2912,6 +2912,10 @@ void renderAvatarCollisionVolumes(LLVOAvatar* avatar)
|
||||
avatar->renderCollisionVolumes();
|
||||
}
|
||||
|
||||
void renderAvatarBones(LLVOAvatar* avatar)
|
||||
{
|
||||
avatar->renderBones();
|
||||
}
|
||||
void renderAgentTarget(LLVOAvatar* avatar)
|
||||
{
|
||||
// render these for self only (why, i don't know)
|
||||
@@ -3072,7 +3076,7 @@ public:
|
||||
|
||||
if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_JOINTS))
|
||||
{
|
||||
avatar->renderJoints();
|
||||
renderAvatarBones(avatar);
|
||||
}
|
||||
|
||||
if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET))
|
||||
|
||||
@@ -48,14 +48,13 @@ LLViewerJoint::LLViewerJoint() :
|
||||
LLAvatarJoint()
|
||||
{ }
|
||||
|
||||
LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) :
|
||||
LLAvatarJoint(name, parent)
|
||||
{ }
|
||||
|
||||
LLViewerJoint::LLViewerJoint(S32 joint_num) :
|
||||
LLAvatarJoint(joint_num)
|
||||
{ }
|
||||
|
||||
LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) :
|
||||
LLAvatarJoint(name, parent)
|
||||
{ }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ~LLViewerJoint()
|
||||
|
||||
@@ -223,10 +223,10 @@ LLMenuGL* gMeshesAndMorphsMenu = NULL;
|
||||
LLContextMenu* gPieRate = NULL;
|
||||
LLContextMenu* gAttachScreenPieMenu = NULL;
|
||||
LLContextMenu* gAttachPieMenu = NULL;
|
||||
LLContextMenu* gAttachBodyPartPieMenus[8];
|
||||
LLContextMenu* gAttachPieMenu2 = NULL;
|
||||
LLContextMenu* gDetachPieMenu = NULL;
|
||||
LLContextMenu* gDetachPieMenu2 = NULL;
|
||||
LLContextMenu* gDetachScreenPieMenu = NULL;
|
||||
LLContextMenu* gDetachBodyPartPieMenus[8];
|
||||
|
||||
LLMenuItemCallGL* gAFKMenu = NULL;
|
||||
LLMenuItemCallGL* gBusyMenu = NULL;
|
||||
@@ -555,6 +555,7 @@ void build_pie_menus()
|
||||
// TomY TODO: what shall we do about these?
|
||||
gDetachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach HUD", true);
|
||||
gDetachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach", true);
|
||||
gDetachPieMenu2 = gMenuHolder->getChild<LLContextMenu>("Object Detach More", true);
|
||||
|
||||
if (gPieAvatar) delete gPieAvatar;
|
||||
gPieAvatar = LLUICtrlFactory::getInstance()->buildContextMenu("menu_pie_avatar.xml", gMenuHolder);
|
||||
@@ -564,6 +565,7 @@ void build_pie_menus()
|
||||
|
||||
gAttachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach HUD");
|
||||
gAttachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach");
|
||||
gAttachPieMenu2 = gMenuHolder->getChild<LLContextMenu>("Object Attach More");
|
||||
gPieRate = gMenuHolder->getChild<LLContextMenu>("Rate Menu");
|
||||
|
||||
if (gPieAttachment) delete gPieAttachment;
|
||||
@@ -6039,6 +6041,33 @@ class LLAvatarAddFriend : public view_listener_t
|
||||
}
|
||||
};
|
||||
|
||||
class LLAvatarResetSkeleton: public view_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
|
||||
if(avatar)
|
||||
{
|
||||
avatar->resetSkeleton(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class LLAvatarResetSkeletonAndAnimations : public view_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
|
||||
if (avatar)
|
||||
{
|
||||
avatar->resetSkeleton(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection)
|
||||
{
|
||||
S32 option = LLNotification::getSelectedOption(notification, response);
|
||||
@@ -9411,6 +9440,8 @@ void initialize_menus()
|
||||
addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
|
||||
addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");
|
||||
addMenu(new LLObjectEnableMute(), "Avatar.EnableMute");
|
||||
addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton");
|
||||
addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeletonAndAnimations");
|
||||
addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend");
|
||||
addMenu(new LLAvatarEnableFreezeEject(), "Avatar.EnableFreezeEject");
|
||||
addMenu(new LLAvatarCopyUUID(), "Avatar.CopyUUID");
|
||||
|
||||
@@ -183,8 +183,8 @@ extern LLContextMenu* gAttachScreenPieMenu;
|
||||
extern LLContextMenu* gDetachScreenPieMenu;
|
||||
extern LLContextMenu* gAttachPieMenu;
|
||||
extern LLContextMenu* gDetachPieMenu;
|
||||
extern LLContextMenu* gAttachBodyPartPieMenus[8];
|
||||
extern LLContextMenu* gDetachBodyPartPieMenus[8];
|
||||
extern LLContextMenu* gAttachPieMenu2;
|
||||
extern LLContextMenu* gDetachPieMenu2;
|
||||
|
||||
extern LLMenuItemCallGL* gAFKMenu;
|
||||
extern LLMenuItemCallGL* gBusyMenu;
|
||||
|
||||
@@ -381,7 +381,7 @@ void LLViewerObject::markDead()
|
||||
if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id))
|
||||
{
|
||||
// This case is needed for indirectly attached mesh objects.
|
||||
av->resetJointPositionsOnDetach(mesh_id);
|
||||
av->resetJointsOnDetach(mesh_id);
|
||||
}
|
||||
|
||||
// Mark itself as dead
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "llfeaturemanager.h"
|
||||
#include "llviewershadermgr.h"
|
||||
|
||||
@@ -46,6 +48,8 @@
|
||||
#include "llsky.h"
|
||||
#include "llvosky.h"
|
||||
#include "llrender.h"
|
||||
#include "lljoint.h"
|
||||
#include "llskinningutil.h"
|
||||
|
||||
#if LL_DARWIN
|
||||
#include "OpenGL/OpenGL.h"
|
||||
@@ -583,11 +587,15 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
|
||||
}
|
||||
shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) );
|
||||
|
||||
std::map<std::string, std::string> attribs;
|
||||
attribs["MAX_JOINTS_PER_MESH_OBJECT"] =
|
||||
boost::lexical_cast<std::string>(LLSkinningUtil::getMaxJointCount());
|
||||
|
||||
// We no longer have to bind the shaders to global glhandles, they are automatically added to a map now.
|
||||
for (U32 i = 0; i < shaders.size(); i++)
|
||||
{
|
||||
// Note usage of GL_VERTEX_SHADER_ARB
|
||||
if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB) == 0)
|
||||
if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB, &attribs) == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -634,7 +642,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
|
||||
for (U32 i = 0; i < shaders.size(); i++)
|
||||
{
|
||||
// Note usage of GL_FRAGMENT_SHADER_ARB
|
||||
if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, NULL, index_channels[i]) == 0)
|
||||
if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, &attribs, index_channels[i]) == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -248,11 +248,18 @@ public:
|
||||
void dumpAnimationState();
|
||||
|
||||
virtual LLJoint* getJoint(const std::string &name);
|
||||
LLJoint* getJoint(S32 num);
|
||||
|
||||
void addAttachmentPosOverridesForObject(LLViewerObject *vo);
|
||||
void resetJointPositionsOnDetach(const LLUUID& mesh_id);
|
||||
void resetJointPositionsOnDetach(LLViewerObject *vo);
|
||||
void clearAttachmentPosOverrides();
|
||||
void addAttachmentOverridesForObject(LLViewerObject *vo);
|
||||
void resetJointsOnDetach(const LLUUID& mesh_id);
|
||||
void resetJointsOnDetach(LLViewerObject *vo);
|
||||
bool jointIsRiggedTo(const std::string& joint_name);
|
||||
bool jointIsRiggedTo(const std::string& joint_name, const LLViewerObject *vo);
|
||||
void clearAttachmentOverrides();
|
||||
void rebuildAttachmentOverrides();
|
||||
void showAttachmentOverrides(bool verbose = false) const;
|
||||
void getAttachmentOverrideNames( std::set<std::string>& pos_names,
|
||||
std::set<std::string>& scale_names) const;
|
||||
|
||||
/*virtual*/ const LLUUID& getID() const;
|
||||
/*virtual*/ void addDebugText(const std::string& text);
|
||||
@@ -416,7 +423,10 @@ public:
|
||||
void postPelvisSetRecalc( void );
|
||||
|
||||
/*virtual*/ BOOL loadSkeletonNode();
|
||||
void initAttachmentPoints(bool ignore_hud_joints = false);
|
||||
/*virtual*/ void buildCharacter();
|
||||
void resetVisualParams();
|
||||
void resetSkeleton(bool reset_animations);
|
||||
|
||||
LLVector3 mCurRootToHeadOffset;
|
||||
LLVector3 mTargetRootToHeadOffset;
|
||||
@@ -444,6 +454,7 @@ public:
|
||||
U32 renderSkinnedAttachments();
|
||||
U32 renderTransparent(BOOL first_pass);
|
||||
void renderCollisionVolumes();
|
||||
void renderBones();
|
||||
void renderJoints();
|
||||
static void deleteCachedImages(bool clearAll=true);
|
||||
static void destroyGL();
|
||||
@@ -698,9 +709,12 @@ protected:
|
||||
** APPEARANCE
|
||||
**/
|
||||
|
||||
LLPointer<LLAppearanceMessageContents> mLastProcessedAppearance;
|
||||
|
||||
public:
|
||||
void parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& msg);
|
||||
void processAvatarAppearance(LLMessageSystem* mesgsys);
|
||||
void applyParsedAppearanceMessage(LLAppearanceMessageContents& contents, bool slam_params);
|
||||
void hideSkirt();
|
||||
void startAppearanceAnimation();
|
||||
/*virtual*/ void bodySizeChanged();
|
||||
@@ -1018,13 +1032,13 @@ private:
|
||||
// General
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
void getSortedJointNames(S32 joint_type, std::vector<std::string>& result) const;
|
||||
static void dumpArchetypeXML_header(LLAPRFile& file, std::string const& archetype_name = "???");
|
||||
static void dumpArchetypeXML_footer(LLAPRFile& file);
|
||||
void dumpArchetypeXML(const std::string& prefix, bool group_by_wearables = false);
|
||||
void dumpArchetypeXML_cont(std::string const& fullpath, bool group_by_wearables);
|
||||
void dumpAppearanceMsgParams( const std::string& dump_prefix,
|
||||
const std::vector<F32>& paramsForDump,
|
||||
const LLTEContents& tec);
|
||||
const LLAppearanceMessageContents& contents);
|
||||
static void dumpBakedStatus();
|
||||
const std::string getBakedStatusForPrintout() const;
|
||||
void dumpAvatarTEs(const std::string& context) const;
|
||||
@@ -1111,6 +1125,8 @@ extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL;
|
||||
extern const F32 MAX_HOVER_Z;
|
||||
extern const F32 MIN_HOVER_Z;
|
||||
|
||||
constexpr U32 NUM_ATTACHMENT_GROUPS = 24;
|
||||
|
||||
void dump_sequential_xml(const std::string outprefix, const LLSD& content);
|
||||
|
||||
#endif // LL_VOAVATAR_H
|
||||
|
||||
@@ -394,128 +394,115 @@ static LLContextMenu* make_part_menu(const std::string& label, bool context)
|
||||
|
||||
void LLVOAvatarSelf::buildContextMenus()
|
||||
{
|
||||
gAttachBodyPartPieMenus[0] = gDetachBodyPartPieMenus[0] = NULL;
|
||||
|
||||
bool context(gSavedSettings.getBOOL("LiruUseContextMenus"));
|
||||
std::string label = LLTrans::getString("BodyPartsRightArm");
|
||||
gAttachBodyPartPieMenus[1] = make_part_menu(label, context);
|
||||
gDetachBodyPartPieMenus[1] = make_part_menu(label, context);
|
||||
|
||||
label = LLTrans::getString("BodyPartsHead");
|
||||
gAttachBodyPartPieMenus[2] = make_part_menu(label, context);
|
||||
gDetachBodyPartPieMenus[2] = make_part_menu(label, context);
|
||||
|
||||
label = LLTrans::getString("BodyPartsLeftArm");
|
||||
gAttachBodyPartPieMenus[3] = make_part_menu(label, context);
|
||||
gDetachBodyPartPieMenus[3] = make_part_menu(label, context);
|
||||
|
||||
gAttachBodyPartPieMenus[4] = gDetachBodyPartPieMenus[4] = NULL;
|
||||
|
||||
label = LLTrans::getString("BodyPartsLeftLeg");
|
||||
gAttachBodyPartPieMenus[5] = make_part_menu(label, context);
|
||||
gDetachBodyPartPieMenus[5] = make_part_menu(label, context);
|
||||
|
||||
label = LLTrans::getString("BodyPartsTorso");
|
||||
gAttachBodyPartPieMenus[6] = make_part_menu(label, context);
|
||||
gDetachBodyPartPieMenus[6] = make_part_menu(label, context);
|
||||
|
||||
label = LLTrans::getString("BodyPartsRightLeg");
|
||||
gAttachBodyPartPieMenus[7] = make_part_menu(label, context);
|
||||
gDetachBodyPartPieMenus[7] = make_part_menu(label, context);
|
||||
|
||||
for (S32 i = 0; i < 8; i++)
|
||||
struct EntryData
|
||||
{
|
||||
if (gAttachBodyPartPieMenus[i])
|
||||
const char * subMenu;
|
||||
LLContextMenu* attachMenu;
|
||||
LLContextMenu* detachMenu;
|
||||
} entries[NUM_ATTACHMENT_GROUPS] = {
|
||||
{ nullptr, gAttachPieMenu, gDetachPieMenu }, //Group 0 = Right Hand
|
||||
{ "BodyPartsRightArm", gAttachPieMenu, gDetachPieMenu },
|
||||
{ "BodyPartsHead", gAttachPieMenu, gDetachPieMenu },
|
||||
{ "BodyPartsLeftArm", gAttachPieMenu, gDetachPieMenu },
|
||||
{ nullptr, gAttachPieMenu, gDetachPieMenu }, //Group 4 = Left Hand
|
||||
{ "BodyPartsLeftLeg", gAttachPieMenu, gDetachPieMenu },
|
||||
{ "BodyPartsTorso", gAttachPieMenu, gDetachPieMenu },
|
||||
{ "BodyPartsRightLeg", gAttachPieMenu, gDetachPieMenu },
|
||||
|
||||
// BENTO
|
||||
{ nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 8 = Right Ring Finger
|
||||
{ nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 9 = Right Wing
|
||||
{ "BodyPartsHead", gAttachPieMenu2, gDetachPieMenu2 },
|
||||
{ nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 11 = Left Wing
|
||||
{ nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 12 = Left Ring Finger
|
||||
{ nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 13 = Left Hind Foot
|
||||
{ "BodyPartsWaist", gAttachPieMenu2, gDetachPieMenu2 },
|
||||
{ nullptr, gAttachPieMenu2, gDetachPieMenu2 }, // Group 15 = Right Hind Foot
|
||||
|
||||
// HUD
|
||||
{ nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 16 = Center 2
|
||||
{ nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 17 = Top Right
|
||||
{ nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 18 = Top
|
||||
{ nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 19 = Top Left
|
||||
{ nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 20 = Center
|
||||
{ nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 21 = Bottom Left
|
||||
{ nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu }, // Group 22 = Bottom
|
||||
{ nullptr, gAttachScreenPieMenu, gDetachScreenPieMenu } // Group 23 = Bottom Right
|
||||
};
|
||||
|
||||
for (S32 group = 0; group < NUM_ATTACHMENT_GROUPS; group++)
|
||||
{
|
||||
LLContextMenu* attach_menu = entries[group].attachMenu;
|
||||
LLContextMenu* detach_menu = entries[group].detachMenu;
|
||||
|
||||
if (attach_menu && detach_menu)
|
||||
{
|
||||
gAttachPieMenu->appendContextSubMenu( gAttachBodyPartPieMenus[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL attachment_found = FALSE;
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
if (entries[group].subMenu != nullptr)
|
||||
{
|
||||
std::string label = LLTrans::getString(entries[group].subMenu);
|
||||
LLContextMenu* new_menu = make_part_menu(label, context); // Attach
|
||||
attach_menu->appendContextSubMenu(new_menu);
|
||||
attach_menu = new_menu;
|
||||
new_menu = make_part_menu(label, context); // Detach
|
||||
detach_menu->appendContextSubMenu(new_menu);
|
||||
detach_menu = new_menu;
|
||||
}
|
||||
|
||||
if (!attach_menu || !detach_menu)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::multimap<S32, S32> attachment_pie_menu_map;
|
||||
|
||||
// gather up all attachment points assigned to this group, and throw into map sorted by pie slice number
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
if (attachment->getGroup() == i)
|
||||
if (attachment && attachment->getGroup() == group)
|
||||
{
|
||||
LLMenuItemCallGL* item;
|
||||
// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
|
||||
// We need the userdata param to disable options in this pie menu later on (Left Hand / Right Hand option)
|
||||
item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
NULL,
|
||||
object_selected_and_point_valid, attachment);
|
||||
// [/RLVa:KB]
|
||||
// item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
// NULL,
|
||||
// object_selected_and_point_valid);
|
||||
item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", iter->first);
|
||||
|
||||
gAttachPieMenu->addChild(item);
|
||||
|
||||
attachment_found = TRUE;
|
||||
break;
|
||||
|
||||
// use multimap to provide a partial order off of the pie slice key
|
||||
S32 pie_index = attachment->getPieSlice();
|
||||
attachment_pie_menu_map.insert(std::make_pair(pie_index, iter->first));
|
||||
}
|
||||
}
|
||||
|
||||
if (!context && !attachment_found)
|
||||
// add in requested order to pie menu, inserting separators as necessary
|
||||
for (std::multimap<S32, S32>::iterator attach_it = attachment_pie_menu_map.begin();
|
||||
attach_it != attachment_pie_menu_map.end(); ++attach_it)
|
||||
{
|
||||
gAttachPieMenu->addSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
if (gDetachBodyPartPieMenus[i])
|
||||
{
|
||||
gDetachPieMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL attachment_found = FALSE;
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
if (attachment->getGroup() == i)
|
||||
if (!context) // Singu Note: Separators are only needed to keep slices of pies from moving
|
||||
{
|
||||
gDetachPieMenu->addChild(new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
&handle_detach_from_avatar, object_attached, attachment));
|
||||
S32 requested_pie_slice = attach_it->first;
|
||||
while ((S32)attach_menu->getItemCount() < requested_pie_slice)
|
||||
{
|
||||
attach_menu->addSeparator();
|
||||
detach_menu->addSeparator();
|
||||
}
|
||||
}
|
||||
S32 attach_index = attach_it->second;
|
||||
|
||||
attachment_found = TRUE;
|
||||
break;
|
||||
LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL);
|
||||
if (attachment)
|
||||
{
|
||||
// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
|
||||
// We need the userdata param to disable options in this pie menu later on
|
||||
LLMenuItemCallGL* item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
NULL, object_selected_and_point_valid, attachment);
|
||||
// [/RLVa:KB]
|
||||
// LLMenuItemCallGL* item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
// NULL, object_selected_and_point_valid);
|
||||
attach_menu->addChild(item);
|
||||
item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index);
|
||||
detach_menu->addChild(new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
&handle_detach_from_avatar,
|
||||
object_attached, attachment));
|
||||
}
|
||||
}
|
||||
|
||||
if (!context && !attachment_found)
|
||||
{
|
||||
gDetachPieMenu->addSeparator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add screen attachments
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
if (attachment->getGroup() == 8)
|
||||
{
|
||||
LLMenuItemCallGL* item;
|
||||
// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
|
||||
// We need the userdata param to disable options in this pie menu later on
|
||||
item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
NULL,
|
||||
object_selected_and_point_valid, attachment);
|
||||
// [/RLVa:KB]
|
||||
// item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
// NULL,
|
||||
// object_selected_and_point_valid);
|
||||
item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", iter->first);
|
||||
gAttachScreenPieMenu->addChild(item);
|
||||
gDetachScreenPieMenu->addChild(new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
&handle_detach_from_avatar, object_attached, attachment));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,67 +540,6 @@ void LLVOAvatarSelf::buildContextMenus()
|
||||
gDetachSubMenu->addSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
for (S32 group = 0; group < 8; group++)
|
||||
{
|
||||
// skip over groups that don't have sub menus
|
||||
if (!gAttachBodyPartPieMenus[group] || !gDetachBodyPartPieMenus[group])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::multimap<S32, S32> attachment_pie_menu_map;
|
||||
|
||||
// gather up all attachment points assigned to this group, and throw into map sorted by pie slice number
|
||||
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
if(attachment->getGroup() == group)
|
||||
{
|
||||
// use multimap to provide a partial order off of the pie slice key
|
||||
S32 pie_index = attachment->getPieSlice();
|
||||
attachment_pie_menu_map.insert(std::make_pair(pie_index, iter->first));
|
||||
}
|
||||
}
|
||||
|
||||
// add in requested order to pie menu, inserting separators as necessary
|
||||
S32 cur_pie_slice = 0;
|
||||
for (std::multimap<S32, S32>::iterator attach_it = attachment_pie_menu_map.begin();
|
||||
attach_it != attachment_pie_menu_map.end(); ++attach_it)
|
||||
{
|
||||
if (!context) // Singu Note: Separators are only needed to keep slices of pies from moving
|
||||
{
|
||||
S32 requested_pie_slice = attach_it->first;
|
||||
while (cur_pie_slice < requested_pie_slice)
|
||||
{
|
||||
gAttachBodyPartPieMenus[group]->addSeparator();
|
||||
gDetachBodyPartPieMenus[group]->addSeparator();
|
||||
cur_pie_slice++;
|
||||
}
|
||||
}
|
||||
S32 attach_index = attach_it->second;
|
||||
|
||||
LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL);
|
||||
if (attachment)
|
||||
{
|
||||
// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c)
|
||||
// We need the userdata param to disable options in this pie menu later on
|
||||
LLMenuItemCallGL* item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
NULL, object_selected_and_point_valid, attachment);
|
||||
// [/RLVa:KB]
|
||||
// LLMenuItemCallGL* item = new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
// NULL, object_selected_and_point_valid);
|
||||
gAttachBodyPartPieMenus[group]->addChild(item);
|
||||
item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index);
|
||||
gDetachBodyPartPieMenus[group]->addChild(new LLMenuItemCallGL(LLTrans::getString(attachment->getName()),
|
||||
&handle_detach_from_avatar,
|
||||
object_attached, attachment));
|
||||
if (!context) cur_pie_slice++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLVOAvatarSelf::cleanup()
|
||||
@@ -3180,7 +3106,7 @@ BOOL LLVOAvatarSelf::needsRenderBeam()
|
||||
return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection());
|
||||
}
|
||||
|
||||
void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value);
|
||||
void dump_visual_param(apr_file_t* file, LLVisualParam const* viewer_param, F32 value);
|
||||
|
||||
void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile)
|
||||
{
|
||||
@@ -3208,7 +3134,7 @@ void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile)
|
||||
it != v_params.end(); ++it)
|
||||
{
|
||||
LLVisualParam *param = *it;
|
||||
dump_visual_param(outfile, param, param->getWeight());
|
||||
dump_visual_param(file, param, param->getWeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "llspatialpartition.h"
|
||||
#include "llhudmanager.h"
|
||||
#include "llflexibleobject.h"
|
||||
#include "llskinningutil.h"
|
||||
#include "llsky.h"
|
||||
#include "lltexturefetch.h"
|
||||
#include "llvector4a.h"
|
||||
@@ -93,7 +94,7 @@
|
||||
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
|
||||
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
|
||||
const F32 FORCE_CULL_AREA = 8.f;
|
||||
U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 20;
|
||||
U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 1;
|
||||
|
||||
BOOL gAnimateTextures = TRUE;
|
||||
//extern BOOL gHideSelectedObjects;
|
||||
@@ -3833,8 +3834,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
|
||||
static const LLCachedControl<bool> allow_mesh_picking("SGAllowRiggedMeshSelection");
|
||||
if (allow_mesh_picking && (gFloaterTools->getVisible() || LLFloaterInspect::findInstance()))
|
||||
{
|
||||
updateRiggedVolume();
|
||||
//genBBoxes(FALSE);
|
||||
updateRiggedVolume(true);
|
||||
volume = mRiggedVolume;
|
||||
transform = false;
|
||||
}
|
||||
@@ -4033,12 +4033,12 @@ void LLVOVolume::clearRiggedVolume()
|
||||
}
|
||||
}
|
||||
|
||||
void LLVOVolume::updateRiggedVolume()
|
||||
void LLVOVolume::updateRiggedVolume(bool force_update)
|
||||
{
|
||||
//Update mRiggedVolume to match current animation frame of avatar.
|
||||
//Also update position/size in octree.
|
||||
|
||||
if (!treatAsRigged())
|
||||
if ((!force_update) && (!treatAsRigged()))
|
||||
{
|
||||
clearRiggedVolume();
|
||||
|
||||
@@ -4103,26 +4103,11 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
|
||||
}
|
||||
|
||||
//build matrix palette
|
||||
LLMatrix4a mp[JOINT_COUNT];
|
||||
static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT;
|
||||
|
||||
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)
|
||||
{
|
||||
LLMatrix4a mat;
|
||||
mat.loadu((F32*)skin->mInvBindMatrix[j].mMatrix);
|
||||
mp[j].setMul(joint->getWorldMatrix(), mat);
|
||||
}
|
||||
}
|
||||
LLMatrix4a mat[kMaxJoints];
|
||||
U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin);
|
||||
LLSkinningUtil::initSkinningMatrixPalette(mat, maxJoints, skin, avatar);
|
||||
|
||||
for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
|
||||
{
|
||||
@@ -4136,7 +4121,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin);
|
||||
LLMatrix4a bind_shape_matrix;
|
||||
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
|
||||
|
||||
@@ -4146,42 +4131,11 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
|
||||
{
|
||||
LLFastTimer t(FTM_SKIN_RIGGED);
|
||||
|
||||
U32 max_joints = LLSkinningUtil::getMaxJointCount();
|
||||
for (U32 j = 0; j < (U32)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];
|
||||
|
||||
const F32 w_floor = floorf(w);
|
||||
idx[k] = (S32) w_floor;
|
||||
wght[k] = w - w_floor;
|
||||
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;
|
||||
// clamp k to kMaxJoints to avoid reading garbage off stack in release
|
||||
src.setMul(mp[(idx[k] < (S32)count) ? idx[k] : 0], w);
|
||||
|
||||
final_mat.add(src);
|
||||
}
|
||||
|
||||
LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints);
|
||||
|
||||
LLVector4a& v = vol_face.mPositions[j];
|
||||
LLVector4a t;
|
||||
@@ -4802,6 +4756,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
|
||||
bool is_rigged = false;
|
||||
|
||||
if (rigged && pAvatarVO)
|
||||
{
|
||||
pAvatarVO->addAttachmentOverridesForObject(vobj);
|
||||
/*if (!LLApp::isExiting() && pAvatarVO->isSelf() && debugLoggingEnabled("AvatarAttachments"))
|
||||
{
|
||||
bool verbose = true;
|
||||
pAvatarVO->showAttachmentOverrides(verbose);
|
||||
}*/
|
||||
}
|
||||
|
||||
static const LLCachedControl<bool> alt_batching("SHAltBatching",true);
|
||||
|
||||
//for each face
|
||||
@@ -4837,10 +4801,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
|
||||
// FIXME should this be inside the face loop?
|
||||
// doesn't seem to depend on any per-face state.
|
||||
if ( pAvatarVO )
|
||||
/*if ( pAvatarVO )
|
||||
{
|
||||
pAvatarVO->addAttachmentPosOverridesForObject(vobj);
|
||||
}
|
||||
pAvatarVO->addAttachmentOverridesForObject(vobj);
|
||||
}*/
|
||||
|
||||
if (pool)
|
||||
{
|
||||
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
|
||||
|
||||
//rigged volume update (for raycasting)
|
||||
void updateRiggedVolume();
|
||||
void updateRiggedVolume(bool force_update = false);
|
||||
LLRiggedVolume* getRiggedVolume();
|
||||
|
||||
//returns true if volume should be treated as a rigged volume
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<on_click function="Avatar.AddFriend" />
|
||||
<on_enable function="Avatar.EnableAddFriend" />
|
||||
</menu_item_call>
|
||||
<menu_item_call enabled="false" label="Pay..." mouse_opaque="true" name="Pay...">
|
||||
<menu_item_call enabled="false" label="Pay..." mouse_opaque="true" name="Pay...">
|
||||
<on_click function="PayObject" />
|
||||
<on_enable function="EnablePayObject" />
|
||||
</menu_item_call>
|
||||
@@ -33,6 +33,15 @@
|
||||
<on_click function="Avatar.InviteToGroup" />
|
||||
</menu_item_call>
|
||||
<pie_menu label="Tools" name="Tools">
|
||||
<menu_item_call enabled="true" label="Reload" mouse_opaque="true" name="Reload Textures">
|
||||
<on_click function="Avatar.ReloadTextures" />
|
||||
</menu_item_call>
|
||||
<menu_item_call enabled="true" label="Reset Skeleton" mouse_opaque="true" name="Reset Skeleton">
|
||||
<on_click function="Avatar.ResetSkeleton" />
|
||||
</menu_item_call>
|
||||
<menu_item_call enabled="true" label="Reset Skeleton And Animations" mouse_opaque="true" name="Reset Skeleton And Animations">
|
||||
<on_click function="Avatar.ResetSkeletonAndAnimations" />
|
||||
</menu_item_call>
|
||||
<menu_item_call enabled="false" hidden="false" label="S. Count" mouse_opaque="true" name="ScriptCount">
|
||||
<on_click function="Object.ScriptCount" />
|
||||
<on_visible function="Object.VisibleScriptCount" />
|
||||
@@ -46,9 +55,6 @@
|
||||
<menu_item_call enabled="true" label="Derender" mouse_opaque="true" name="Derender">
|
||||
<on_click function="Object.DERENDER" />
|
||||
</menu_item_call>
|
||||
<menu_item_call enabled="true" label="Reload" mouse_opaque="true" name="Reload Textures">
|
||||
<on_click function="Avatar.ReloadTextures" />
|
||||
</menu_item_call>
|
||||
</pie_menu>
|
||||
<menu_item_call enabled="false" label="Eject..." mouse_opaque="true" name="Eject...">
|
||||
<on_click function="Avatar.Eject" />
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
</menu_item_call>
|
||||
<pie_menu label="Attach HUD" name="Object Attach HUD" />
|
||||
<pie_menu label="Attach" name="Object Attach" />
|
||||
<pie_menu label="Attach More" name="Object Attach More" />
|
||||
<menu_item_call enabled="false" label="Return..." mouse_opaque="true" name="Return...">
|
||||
<on_click function="Object.Return" />
|
||||
<on_enable function="Object.EnableReturn" />
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
<pie_menu enabled="true" label="HUD" name="Object Detach HUD" />
|
||||
<menu_item_separator />
|
||||
<pie_menu enabled="true" label="Detach" name="Object Detach" />
|
||||
<menu_item_separator />
|
||||
<pie_menu enabled="true" label="Detach More" name="Object Detach More" />
|
||||
<menu_item_call enabled="true" label="Detach All" name="Detach All">
|
||||
<on_click function="Self.RemoveAllAttachments" userdata="" />
|
||||
<on_enable function="Self.EnableRemoveAllAttachments" />
|
||||
@@ -89,6 +89,12 @@
|
||||
<menu_item_call enabled="true" label="Reload" mouse_opaque="true" name="Reload Textures">
|
||||
<on_click function="Avatar.ReloadTextures" />
|
||||
</menu_item_call>
|
||||
<menu_item_call enabled="true" label="Reset Skel" mouse_opaque="true" name="Reset Skeleton">
|
||||
<on_click function="Avatar.ResetSkeleton" />
|
||||
</menu_item_call>
|
||||
<menu_item_call enabled="true" label="Reset Anims" mouse_opaque="true" name="Reset Skeleton And Animations">
|
||||
<on_click function="Avatar.ResetSkeletonAndAnimations" />
|
||||
</menu_item_call>
|
||||
<menu_item_call enabled="true" hidden="false" label="Anims..." mouse_opaque="true"
|
||||
name="Anims...">
|
||||
<on_click function="ShowFloater" userdata="anims_explorer" />
|
||||
@@ -101,9 +107,9 @@
|
||||
<on_click function="ShowFloater" userdata="script info" />
|
||||
<on_visible function="Self.VisibleScriptInfo" />
|
||||
</menu_item_call>
|
||||
<menu_item_call enabled="true" label="Debug..." mouse_opaque="true" name="Debug Layers">
|
||||
<!--<menu_item_call enabled="true" label="Debug..." mouse_opaque="true" name="Debug Layers">
|
||||
<on_click function="Avatar.Debug" />
|
||||
</menu_item_call>
|
||||
</menu_item_call>-->
|
||||
<menu_item_call enabled="true" label="Copy UUID" mouse_opaque="true" name="CopyUUID">
|
||||
<on_click function="Avatar.CopyUUID" />
|
||||
</menu_item_call>
|
||||
|
||||
@@ -3151,7 +3151,8 @@ Where tag = tag string to match. Removes bot's matching the tag.
|
||||
<string name="BodyPartsLeftLeg">Left Leg</string>
|
||||
<string name="BodyPartsTorso">Torso</string>
|
||||
<string name="BodyPartsRightLeg">Right Leg</string>
|
||||
|
||||
<string name="BodyPartsEnhancedSkeleton">Enhanced Skeleton</string>
|
||||
<string name="BodyPartsWaist">Waist</string>
|
||||
<!-- mouselook -->
|
||||
<string name="LeaveMouselook">Press ESC to return to World View</string>
|
||||
|
||||
@@ -3289,6 +3290,21 @@ The
|
||||
<string name="Right Pec">Right Pec</string>
|
||||
<string name="Neck">Neck</string>
|
||||
<string name="Avatar Center">Root</string>
|
||||
<string name="Left Ring Finger">Left Ring Finger</string>
|
||||
<string name="Right Ring Finger">Right Ring Finger</string>
|
||||
<string name="Tail Base">Tail Base</string>
|
||||
<string name="Tail Tip">Tail Tip</string>
|
||||
<string name="Left Wing">Left Wing</string>
|
||||
<string name="Right Wing">Right Wing</string>
|
||||
<string name="Jaw">Jaw</string>
|
||||
<string name="Alt Left Ear">Alt Left Ear</string>
|
||||
<string name="Alt Right Ear">Alt Right Ear</string>
|
||||
<string name="Alt Left Eye">Alt Left Eye</string>
|
||||
<string name="Alt Right Eye">Alt Right Eye</string>
|
||||
<string name="Tongue">Tongue</string>
|
||||
<string name="Groin">Groin</string>
|
||||
<string name="Left Hind Foot">Left Hind Foot</string>
|
||||
<string name="Right Hind Foot">Right Hind Foot</string>
|
||||
<string name="Invalid Attachment">Invalid Attachment Point</string>
|
||||
<string name="ATTACHMENT_MISSING_ITEM">Error: missing item</string>
|
||||
<string name="ATTACHMENT_MISSING_BASE_ITEM">Error: missing base item</string>
|
||||
@@ -3421,8 +3437,8 @@ The
|
||||
<string name="ATTACH_LULEG">Left Upper Leg</string>
|
||||
<string name="ATTACH_LLLEG">Left Lower Leg</string>
|
||||
<string name="ATTACH_BELLY">Belly</string>
|
||||
<string name="ATTACH_RPEC">Right Pec</string>
|
||||
<string name="ATTACH_LPEC">Left Pec</string>
|
||||
<string name="ATTACH_LEFT_PEC">Left Pec</string>
|
||||
<string name="ATTACH_RIGHT_PEC">Right Pec</string>
|
||||
<string name="ATTACH_HUD_CENTER_2">HUD Center 2</string>
|
||||
<string name="ATTACH_HUD_TOP_RIGHT">HUD Top Right</string>
|
||||
<string name="ATTACH_HUD_TOP_CENTER">HUD Top Center</string>
|
||||
@@ -3433,6 +3449,21 @@ The
|
||||
<string name="ATTACH_HUD_BOTTOM_RIGHT">HUD Bottom Right</string>
|
||||
<string name="ATTACH_NECK">Neck</string>
|
||||
<string name="ATTACH_AVATAR_CENTER">Root</string>
|
||||
<string name="ATTACH_LHAND_RING1">Left Ring Finger</string>
|
||||
<string name="ATTACH_RHAND_RING1">Right Ring Finger</string>
|
||||
<string name="ATTACH_TAIL_BASE">Tail Base</string>
|
||||
<string name="ATTACH_TAIL_TIP">Tail Tip</string>
|
||||
<string name="ATTACH_LWING">Left Wing</string>
|
||||
<string name="ATTACH_RWING">Right Wing</string>
|
||||
<string name="ATTACH_FACE_JAW">Jaw</string>
|
||||
<string name="ATTACH_FACE_LEAR">Alt Left Ear</string>
|
||||
<string name="ATTACH_FACE_REAR">Alt Right Ear</string>
|
||||
<string name="ATTACH_FACE_LEYE">Alt Left Eye</string>
|
||||
<string name="ATTACH_FACE_REYE">Alt Right Eye</string>
|
||||
<string name="ATTACH_FACE_TONGUE">Tongue</string>
|
||||
<string name="ATTACH_GROIN">Groin</string>
|
||||
<string name="ATTACH_HIND_LFOOT">Left Hind Foot</string>
|
||||
<string name="ATTACH_HIND_RFOOT">Right Hind Foot</string>
|
||||
|
||||
<!-- panel contents -->
|
||||
<string name="PanelContentsNewScript">New Script</string>
|
||||
|
||||
Reference in New Issue
Block a user