Merge bento-box

master
Ansariel 2015-12-17 11:47:42 +01:00
commit be6ce75a96
52 changed files with 14719 additions and 1211 deletions

View File

@ -44,6 +44,7 @@
#include "lltexglobalcolor.h"
#include "llwearabledata.h"
#include "boost/bind.hpp"
#include "boost/tokenizer.hpp"
#if LL_MSVC
@ -87,8 +88,11 @@ public:
private:
std::string mName;
std::string mSupport;
std::string mAliases;
BOOL mIsJoint;
LLVector3 mPos;
LLVector3 mEnd;
LLVector3 mRot;
LLVector3 mScale;
LLVector3 mPivot;
@ -118,6 +122,7 @@ public:
private:
S32 mNumBones;
S32 mNumCollisionVolumes;
LLAvatarAppearance::joint_alias_map_t mJointAliasMap;
typedef std::vector<LLAvatarBoneInfo*> bone_info_list_t;
bone_info_list_t mBoneInfoList;
};
@ -333,36 +338,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;
@ -375,16 +393,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);
@ -557,7 +578,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;
@ -573,6 +594,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);
@ -604,6 +631,8 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY],
info->mRot.mV[VZ], LLQuaternion::XYZ));
joint->setScale(info->mScale);
joint->setSupport(info->mSupport);
joint->setEnd(info->mEnd);
if (info->mIsJoint)
{
@ -636,10 +665,7 @@ BOOL LLAvatarAppearance::allocateCharacterJoints( S32 num )
{
clearSkeleton();
for(S32 joint_num = 0; joint_num < num; joint_num++)
{
mSkeleton.push_back(createAvatarJoint(joint_num));
}
mSkeleton = avatar_joint_list_t(num,NULL);
return TRUE;
}
@ -650,6 +676,7 @@ BOOL LLAvatarAppearance::allocateCharacterJoints( S32 num )
//-----------------------------------------------------------------------------
BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info)
{
LL_DEBUGS("BVH") << "numBones " << info->mNumBones << " numCollisionVolumes " << info->mNumCollisionVolumes << LL_ENDL;
//-------------------------------------------------------------------------
// allocate joints
//-------------------------------------------------------------------------
@ -676,8 +703,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;
@ -1261,6 +1288,10 @@ LLJoint *LLAvatarAppearance::getCharacterJoint( U32 num )
{
return NULL;
}
if (!mSkeleton[num])
{
mSkeleton[num] = createAvatarJoint(num);
}
return mSkeleton[num];
}
@ -1532,6 +1563,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"))
{
@ -1569,6 +1603,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");
@ -1624,6 +1672,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

View File

@ -66,7 +66,8 @@ public:
LLAvatarAppearance(LLWearableData* wearable_data);
virtual ~LLAvatarAppearance();
static void initClass(); // initializes static members
static void initClass(const std::string& avatar_file_name, const std::string& skeleton_file_name); // initializes static members
static void initClass();
static void cleanupClass(); // Cleanup data that's only init'd once per class.
virtual void initInstance(); // Called after construction to initialize the instance.
virtual BOOL loadSkeletonNode();
@ -128,6 +129,9 @@ 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; }
@ -144,6 +148,12 @@ public:
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);
@ -158,12 +168,12 @@ protected:
BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
BOOL allocateCharacterJoints(S32 num);
BOOL buildSkeleton(const LLAvatarSkeletonInfo *info);
protected:
void clearSkeleton();
BOOL mIsBuilt; // state of deferred character building
typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;
avatar_joint_list_t mSkeleton;
LLPosOverrideMap mPelvisFixups;
joint_alias_map_t mJointAliasMap;
//--------------------------------------------------------------------
// Pelvis height adjustment members.

View File

@ -29,6 +29,7 @@
#include "llbvhloader.h"
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include "lldatapacker.h"
#include "lldir.h"
@ -36,6 +37,7 @@
#include "llquantize.h"
#include "llstl.h"
#include "llapr.h"
#include "llsdserialize.h"
using namespace std;
@ -121,52 +123,16 @@ LLQuaternion::Order bvhStringToOrder( char *str )
// LLBVHLoader()
//-----------------------------------------------------------------------------
/*
LLBVHLoader::LLBVHLoader(const char* buffer)
{
reset();
mStatus = loadTranslationTable("anim.ini");
if (mStatus == LLBVHLoader::ST_NO_XLT_FILE)
{
LL_WARNS() << "NOTE: No translation table found." << LL_ENDL;
return;
}
else
{
if (mStatus != LLBVHLoader::ST_OK)
{
LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL;
return;
}
}
char error_text[128]; // Flawfinder: ignore
S32 error_line;
mStatus = loadBVHFile(buffer, error_text, error_line);
if (mStatus != LLBVHLoader::ST_OK)
{
LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL;
return;
}
applyTranslations();
optimize();
mInitialized = TRUE;
}
*/
LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine)
LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string>& joint_alias_map )
{
reset();
errorLine = 0;
mStatus = loadTranslationTable("anim.ini");
loadStatus = mStatus;
LL_INFOS()<<"Load Status 00 : "<< loadStatus << LL_ENDL;
LL_INFOS("BVH") << "Load Status 00 : " << loadStatus << LL_ENDL;
if (mStatus == E_ST_NO_XLT_FILE)
{
//LL_WARNS() << "NOTE: No translation table found." << LL_ENDL;
LL_WARNS("BVH") << "NOTE: No translation table found." << LL_ENDL;
loadStatus = mStatus;
return;
}
@ -174,28 +140,43 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error
{
if (mStatus != E_ST_OK)
{
//LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL;
LL_WARNS("BVH") << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL;
errorLine = getLineNumber();
loadStatus = mStatus;
return;
}
}
// Recognize all names we've been told are legal.
std::map<std::string, std::string>::iterator iter;
for (iter = joint_alias_map.begin(); iter != joint_alias_map.end(); iter++)
{
makeTranslation( iter->first , iter->second );
}
char error_text[128]; /* Flawfinder: ignore */
S32 error_line;
mStatus = loadBVHFile(buffer, error_text, error_line);
mStatus = loadBVHFile(buffer, error_text, error_line); //Reads all joints in BVH file.
LL_DEBUGS("BVH") << "============================================================" << LL_ENDL;
LL_DEBUGS("BVH") << "Raw data from file" << LL_ENDL;
dumpBVHInfo();
if (mStatus != E_ST_OK)
{
//LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL;
LL_WARNS("BVH") << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL;
loadStatus = mStatus;
errorLine = getLineNumber();
return;
}
applyTranslations();
applyTranslations(); //Maps between joints found in file and the aliased names.
optimize();
LL_DEBUGS("BVH") << "============================================================" << LL_ENDL;
LL_DEBUGS("BVH") << "After translations and optimize" << LL_ENDL;
dumpBVHInfo();
mInitialized = TRUE;
}
@ -211,10 +192,6 @@ LLBVHLoader::~LLBVHLoader()
//------------------------------------------------------------------------
ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
{
mLineNumber = 0;
mTranslations.clear();
mConstraints.clear();
//--------------------------------------------------------------------
// open file
//--------------------------------------------------------------------
@ -231,7 +208,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
if (!fp)
return E_ST_NO_XLT_FILE;
LL_INFOS() << "NOTE: Loading translation table: " << fileName << LL_ENDL;
LL_INFOS("BVH") << "NOTE: Loading translation table: " << fileName << LL_ENDL;
//--------------------------------------------------------------------
// register file to be closed on function exit
@ -249,7 +226,6 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
// load data one line at a time
//--------------------------------------------------------------------
BOOL loadingGlobals = FALSE;
Translation *trans = NULL;
while ( getLine(fp) )
{
//----------------------------------------------------------------
@ -276,13 +252,6 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
loadingGlobals = TRUE;
continue;
}
else
{
loadingGlobals = FALSE;
Translation &newTrans = mTranslations[ name ];
trans = &newTrans;
continue;
}
}
//----------------------------------------------------------------
@ -504,173 +473,98 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
mConstraints.push_back(constraint);
continue;
}
//----------------------------------------------------------------
// at this point there must be a valid trans pointer
//----------------------------------------------------------------
if ( ! trans )
return E_ST_NO_XLT_NAME;
//----------------------------------------------------------------
// check for ignore flag
//----------------------------------------------------------------
if ( LLStringUtil::compareInsensitive(token, "ignore")==0 )
{
char trueFalse[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 ) /* Flawfinder: ignore */
return E_ST_NO_XLT_IGNORE;
trans->mIgnore = (LLStringUtil::compareInsensitive(trueFalse, "true")==0);
continue;
}
//----------------------------------------------------------------
// check for relativepos flag
//----------------------------------------------------------------
if ( LLStringUtil::compareInsensitive(token, "relativepos")==0 )
{
F32 x, y, z;
char relpos[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %f %f %f", &x, &y, &z) == 3 )
{
trans->mRelativePosition.setVec( x, y, z );
}
else if ( sscanf(mLine, " %*s = %127s", relpos) == 1 ) /* Flawfinder: ignore */
{
if ( LLStringUtil::compareInsensitive(relpos, "firstkey")==0 )
{
trans->mRelativePositionKey = TRUE;
}
else
{
return E_ST_NO_XLT_RELATIVE;
}
}
else
{
return E_ST_NO_XLT_RELATIVE;
}
continue;
}
//----------------------------------------------------------------
// check for relativerot flag
//----------------------------------------------------------------
if ( LLStringUtil::compareInsensitive(token, "relativerot")==0 )
{
//F32 x, y, z;
char relpos[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %127s", relpos) == 1 ) /* Flawfinder: ignore */
{
if ( LLStringUtil::compareInsensitive(relpos, "firstkey")==0 )
{
trans->mRelativeRotationKey = TRUE;
}
else
{
return E_ST_NO_XLT_RELATIVE;
}
}
else
{
return E_ST_NO_XLT_RELATIVE;
}
continue;
}
//----------------------------------------------------------------
// check for outname value
//----------------------------------------------------------------
if ( LLStringUtil::compareInsensitive(token, "outname")==0 )
{
char outName[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %127s", outName) != 1 ) /* Flawfinder: ignore */
return E_ST_NO_XLT_OUTNAME;
trans->mOutName = outName;
continue;
}
//----------------------------------------------------------------
// check for frame matrix value
//----------------------------------------------------------------
if ( LLStringUtil::compareInsensitive(token, "frame")==0 )
{
LLMatrix3 fm;
if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f",
&fm.mMatrix[0][0], &fm.mMatrix[0][1], &fm.mMatrix[0][2],
&fm.mMatrix[1][0], &fm.mMatrix[1][1], &fm.mMatrix[1][2],
&fm.mMatrix[2][0], &fm.mMatrix[2][1], &fm.mMatrix[2][2] ) != 9 )
return E_ST_NO_XLT_MATRIX;
trans->mFrameMatrix = fm;
continue;
}
//----------------------------------------------------------------
// check for offset matrix value
//----------------------------------------------------------------
if ( LLStringUtil::compareInsensitive(token, "offset")==0 )
{
LLMatrix3 om;
if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f",
&om.mMatrix[0][0], &om.mMatrix[0][1], &om.mMatrix[0][2],
&om.mMatrix[1][0], &om.mMatrix[1][1], &om.mMatrix[1][2],
&om.mMatrix[2][0], &om.mMatrix[2][1], &om.mMatrix[2][2] ) != 9 )
return E_ST_NO_XLT_MATRIX;
trans->mOffsetMatrix = om;
continue;
}
//----------------------------------------------------------------
// check for mergeparent value
//----------------------------------------------------------------
if ( LLStringUtil::compareInsensitive(token, "mergeparent")==0 )
{
char mergeParentName[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 ) /* Flawfinder: ignore */
return E_ST_NO_XLT_MERGEPARENT;
trans->mMergeParentName = mergeParentName;
continue;
}
//----------------------------------------------------------------
// check for mergechild value
//----------------------------------------------------------------
if ( LLStringUtil::compareInsensitive(token, "mergechild")==0 )
{
char mergeChildName[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 ) /* Flawfinder: ignore */
return E_ST_NO_XLT_MERGECHILD;
trans->mMergeChildName = mergeChildName;
continue;
}
//----------------------------------------------------------------
// check for per-joint priority
//----------------------------------------------------------------
if ( LLStringUtil::compareInsensitive(token, "priority")==0 )
{
S32 priority;
if ( sscanf(mLine, " %*s = %d", &priority) != 1 )
return E_ST_NO_XLT_PRIORITY;
trans->mPriorityModifier = priority;
continue;
}
}
infile.close() ;
return E_ST_OK;
}
void LLBVHLoader::makeTranslation(std::string alias_name, std::string joint_name)
{
//Translation &newTrans = (foomap.insert(value_type(alias_name, Translation()))).first();
Translation &newTrans = mTranslations[ alias_name ]; //Uses []'s implicit call to ctor.
newTrans.mOutName = joint_name;
LLMatrix3 fm;
LLVector3 vect1(0, 1, 0);
LLVector3 vect2(0, 0, 1);
LLVector3 vect3(1, 0, 0);
fm.setRows(vect1, vect2, vect3);
newTrans.mFrameMatrix = fm;
if (joint_name == "mPelvis")
{
newTrans.mRelativePositionKey = TRUE;
newTrans.mRelativeRotationKey = TRUE;
}
}
ELoadStatus LLBVHLoader::loadAliases(const char * filename)
{
LLSD aliases_sd;
std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,filename);
llifstream input_stream;
input_stream.open(fullpath.c_str(), std::ios::in | std::ios::binary);
if(input_stream.is_open())
{
if ( LLSDSerialize::fromXML(aliases_sd, input_stream) )
{
for(LLSD::map_iterator alias_iter = aliases_sd.beginMap();
alias_iter != aliases_sd.endMap();
++alias_iter)
{
LLSD::String alias_name = alias_iter->first;
LLSD::String joint_name = alias_iter->second;
makeTranslation(alias_name, joint_name);
}
}
else
{
return E_ST_NO_XLT_HEADER;
}
input_stream.close();
}
else
{
LL_WARNS("BVH") << "Can't open joint alias file " << fullpath << LL_ENDL;
return E_ST_NO_XLT_FILE;
}
return E_ST_OK;
}
void LLBVHLoader::dumpBVHInfo()
{
for (U32 j=0; j<mJoints.size(); j++)
{
Joint *joint = mJoints[j];
LL_DEBUGS("BVH") << joint->mName << LL_ENDL;
for (S32 i=0; i<mNumFrames; i++)
{
Key &prevkey = joint->mKeys[llmax(i-1,0)];
Key &key = joint->mKeys[i];
if ((i==0) ||
(key.mPos[0] != prevkey.mPos[0]) ||
(key.mPos[1] != prevkey.mPos[1]) ||
(key.mPos[2] != prevkey.mPos[2]) ||
(key.mRot[0] != prevkey.mRot[0]) ||
(key.mRot[1] != prevkey.mRot[1]) ||
(key.mRot[2] != prevkey.mRot[2])
)
{
LL_DEBUGS("BVH") << "FRAME " << i
<< " POS " << key.mPos[0] << "," << key.mPos[1] << "," << key.mPos[2]
<< " ROT " << key.mRot[0] << "," << key.mRot[1] << "," << key.mRot[2] << LL_ENDL;
}
}
}
}
//------------------------------------------------------------------------
// LLBVHLoader::loadBVHFile()
@ -751,6 +645,7 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &
{
iter++; // {
iter++; // OFFSET
iter++; // }
S32 depth = 0;
for (S32 j = (S32)parent_joints.size() - 1; j >= 0; j--)
{
@ -782,12 +677,19 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &
//---------------------------------------------------------------
// we require the root joint be "hip" - DEV-26188
//---------------------------------------------------------------
const char* FORCED_ROOT_NAME = "hip";
if ( (mJoints.size() == 0 ) && ( !strstr(jointName, FORCED_ROOT_NAME) ) )
{
strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */
return E_ST_BAD_ROOT;
}
if (mJoints.size() == 0 )
{
//The root joint of the BVH file must be hip (mPelvis) or an alias of mPelvis.
const char* FORCED_ROOT_NAME = "hip";
TranslationMap::iterator hip_joint = mTranslations.find( FORCED_ROOT_NAME );
TranslationMap::iterator root_joint = mTranslations.find( jointName );
if ( hip_joint == mTranslations.end() || root_joint == mTranslations.end() || root_joint->second.mOutName != hip_joint->second.mOutName )
{
strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */
return E_ST_BAD_ROOT;
}
}
//----------------------------------------------------------------
@ -795,11 +697,14 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &
//----------------------------------------------------------------
mJoints.push_back( new Joint( jointName ) );
Joint *joint = mJoints.back();
LL_DEBUGS("BVH") << "Created joint " << jointName << LL_ENDL;
LL_DEBUGS("BVH") << "- index " << mJoints.size()-1 << LL_ENDL;
S32 depth = 1;
for (S32 j = (S32)parent_joints.size() - 1; j >= 0; j--)
{
Joint *pjoint = mJoints[parent_joints[j]];
LL_DEBUGS("BVH") << "- ancestor " << pjoint->mName << LL_ENDL;
if (depth > pjoint->mChildTreeMaxDepth)
{
pjoint->mChildTreeMaxDepth = depth;
@ -868,6 +773,21 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &
return E_ST_NO_CHANNELS;
}
// Animating position (via mNumChannels = 6) is only supported for mPelvis.
int res = sscanf(line.c_str(), " CHANNELS %d", &joint->mNumChannels);
if ( res != 1 )
{
// Assume default if not otherwise specified.
if (mJoints.size()==1)
{
joint->mNumChannels = 6;
}
else
{
joint->mNumChannels = 3;
}
}
//----------------------------------------------------------------
// get rotation order
//----------------------------------------------------------------
@ -966,57 +886,41 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &
line = (*(iter++));
err_line++;
// read and store values
const char *p = line.c_str();
// Split line into a collection of floats.
std::deque<F32> floats;
boost::char_separator<char> whitespace_sep("\t ");
tokenizer float_tokens(line, whitespace_sep);
tokenizer::iterator float_token_iter = float_tokens.begin();
while (float_token_iter != float_tokens.end())
{
F32 val = boost::lexical_cast<float>(*float_token_iter);
floats.push_back(val);
float_token_iter++;
}
LL_DEBUGS("BVH") << "Got " << floats.size() << " floats " << LL_ENDL;
for (U32 j=0; j<mJoints.size(); j++)
{
Joint *joint = mJoints[j];
joint->mKeys.push_back( Key() );
Key &key = joint->mKeys.back();
// get 3 pos values for root joint only
if (j==0)
if (floats.size() < joint->mNumChannels)
{
if ( sscanf(p, "%f %f %f", key.mPos, key.mPos+1, key.mPos+2) != 3 )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
return E_ST_NO_POS;
}
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
return E_ST_NO_POS;
}
// skip to next 3 values in the line
p = find_next_whitespace(p);
if (!p)
// assume either numChannels == 6, in which case we have pos + rot,
// or numChannels == 3, in which case we have only rot.
if (joint->mNumChannels == 6)
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
return E_ST_NO_ROT;
key.mPos[0] = floats.front(); floats.pop_front();
key.mPos[1] = floats.front(); floats.pop_front();
key.mPos[2] = floats.front(); floats.pop_front();
}
p = find_next_whitespace(++p);
if (!p)
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
return E_ST_NO_ROT;
}
p = find_next_whitespace(++p);
if (!p)
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
return E_ST_NO_ROT;
}
// get 3 rot values for joint
F32 rot[3];
if ( sscanf(p, " %f %f %f", rot, rot+1, rot+2) != 3 )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
return E_ST_NO_ROT;
}
p++;
key.mRot[ joint->mOrder[0]-'X' ] = rot[0];
key.mRot[ joint->mOrder[1]-'X' ] = rot[1];
key.mRot[ joint->mOrder[2]-'X' ] = rot[2];
key.mRot[ joint->mOrder[0]-'X' ] = floats.front(); floats.pop_front();
key.mRot[ joint->mOrder[1]-'X' ] = floats.front(); floats.pop_front();
key.mRot[ joint->mOrder[2]-'X' ] = floats.front(); floats.pop_front();
}
}
@ -1339,6 +1243,9 @@ void LLBVHLoader::reset()
mInitialized = FALSE;
mEmoteName = "";
mLineNumber = 0;
mTranslations.clear();
mConstraints.clear();
}
//------------------------------------------------------------------------
@ -1595,5 +1502,6 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp)
dp.packF32(constraint_it->mEaseOutStop, "ease_out_stop");
}
return TRUE;
}

View File

@ -102,6 +102,7 @@ struct Joint
mNumRotKeys = 0;
mChildTreeMaxDepth = 0;
mPriority = 0;
mNumChannels = 3;
}
// Include aligned members first
@ -123,6 +124,7 @@ struct Joint
S32 mNumRotKeys;
S32 mChildTreeMaxDepth;
S32 mPriority;
S32 mNumChannels;
};
@ -225,8 +227,7 @@ class LLBVHLoader
friend class LLKeyframeMotion;
public:
// Constructor
// LLBVHLoader(const char* buffer);
LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine);
LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string>& joint_alias_map );
~LLBVHLoader();
/*
@ -265,13 +266,22 @@ public:
static const char *ST_NO_XLT_EMOTE;
static const char *ST_BAD_ROOT;
*/
// Loads the specified translation table.
ELoadStatus loadTranslationTable(const char *fileName);
//Create a new joint alias
void makeTranslation(std::string key, std::string value);
// Loads joint aliases from XML file.
ELoadStatus loadAliases(const char * filename);
// Load the specified BVH file.
// Returns status code.
ELoadStatus loadBVHFile(const char *buffer, char *error_text, S32 &error_line);
void dumpBVHInfo();
// Applies translations to BVH data loaded.
void applyTranslations();

View File

@ -108,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() :
@ -169,6 +171,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.

View File

@ -40,9 +40,14 @@
#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;
// BENTO JOINT COUNT LIMIT - need to set this to final skeleton size + 2
const U32 LL_CHARACTER_MAX_JOINTS = 144; // 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_JOINTS-1);
const U32 LL_FACE_JOINT_NUM = (LL_CHARACTER_MAX_JOINTS-2);
const S32 LL_CHARACTER_MAX_PRIORITY = 7;
const F32 LL_MAX_PELVIS_OFFSET = 5.f;
@ -86,9 +91,17 @@ 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;
@ -104,6 +117,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
@ -139,6 +156,15 @@ public:
const std::string& getName() const { return mName; }
void setName( const std::string &name ) { mName = name; }
// 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; }

View File

@ -1926,6 +1926,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");
@ -1939,6 +1941,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);
@ -1946,6 +1961,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)
{
@ -1963,6 +1979,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");
@ -1981,37 +1999,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;
@ -2029,6 +2064,51 @@ U32 LLKeyframeMotion::getFileSize()
return dp.getCurrentSize();
}
//-----------------------------------------------------------------------------
// dumpToFile()
//-----------------------------------------------------------------------------
void LLKeyframeMotion::dumpToFile(const std::string& name)
{
if (isLoaded())
{
std::string outfile_base;
if (!name.empty())
{
outfile_base = name;
}
else if (!getName().empty())
{
outfile_base = getName();
}
else
{
const LLUUID& id = getID();
outfile_base = id.asString();
}
std::string outfilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfile_base + ".anim");
if (LLFile::isfile(outfilename))
{
return;
}
S32 file_size = getFileSize();
U8* buffer = new U8[file_size];
LL_DEBUGS("BVH") << "Dumping " << outfilename << LL_ENDL;
LLDataPackerBinaryBuffer dp(buffer, file_size);
if (serialize(dp))
{
LLAPRFile outfile;
outfile.open(outfilename, LL_APR_WPB);
if (outfile.getFileHandle())
{
outfile.write(buffer, file_size);
}
}
delete [] buffer;
}
}
//-----------------------------------------------------------------------------
// getPelvisBBox()
//-----------------------------------------------------------------------------

View File

@ -153,6 +153,7 @@ public:
BOOL serialize(LLDataPacker& dp) const;
BOOL deserialize(LLDataPacker& dp);
BOOL isLoaded() { return mJointMotionList != NULL; }
void dumpToFile(const std::string& name);
// setters for modifying a keyframe animation

View File

@ -111,9 +111,14 @@ 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_JOINTS) || (joint_num < 0))
{
LL_WARNS() << "joint_num " << joint_num << " is outside of legal range [0-" << LL_CHARACTER_MAX_JOINTS << ")" << LL_ENDL;
}
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 )

View File

@ -576,7 +576,6 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
}
else
{
// NUM_JOINT_SIGNATURE_STRIDES should be multiple of 4
for (S32 i = 0; i < NUM_JOINT_SIGNATURE_STRIDES; i++)
{
U32 *current_signature = (U32*)&(mJointSignature[0][i * 4]);

View File

@ -4641,6 +4641,7 @@ LLVolumeFace::LLVolumeFace() :
mTexCoords(NULL),
mIndices(NULL),
mWeights(NULL),
mWeightsRemapped(FALSE),
mOctree(NULL),
mOptimized(FALSE)
{

View File

@ -956,6 +956,10 @@ public:
// mWeights.size() should be empty or match mVertices.size()
LLVector4a* mWeights;
// Whether or not the weights have been cleaned up and remapped
// based on currently supported joints.
mutable BOOL mWeightsRemapped;
LLOctreeNode<LLVolumeTriangle>* mOctree;
//whether or not face has been cache optimized

View File

@ -833,15 +833,17 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
// LLDAELoader
//-----------------------------------------------------------------------------
LLDAELoader::LLDAELoader(
std::string filename,
S32 lod,
std::string filename,
S32 lod,
load_callback_t load_cb,
joint_lookup_func_t joint_lookup_func,
texture_load_func_t texture_load_func,
state_callback_t state_cb,
void* opaque_userdata,
JointTransformMap& jointMap,
JointSet& jointsFromNodes,
state_callback_t state_cb,
void* opaque_userdata,
JointTransformMap& jointTransformMap,
JointNameSet& jointsFromNodes,
std::map<std::string, std::string>& jointAliasMap,
U32 maxJointsPerMesh,
U32 modelLimit)
: LLModelLoader(
filename,
@ -851,8 +853,10 @@ LLDAELoader::LLDAELoader(
texture_load_func,
state_cb,
opaque_userdata,
jointMap,
jointsFromNodes),
jointTransformMap,
jointsFromNodes,
jointAliasMap,
maxJointsPerMesh),
mGeneratedModelLimit(modelLimit),
mForceIdNaming(false)
{
@ -1257,6 +1261,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
extractTranslation( pTranslateA, workingTransform );
}
else
{
if ( pTranslateB )
{
extractTranslation( pTranslateB, workingTransform );
@ -1281,9 +1286,10 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
}
}
}
//Store the joint transform w/respect to it's name.
mJointList[(*jointIt).second.c_str()] = workingTransform;
//Store the joint transform w/respect to its name.
mJointList[(*jointIt).second.c_str()] = workingTransform;
}
}
@ -1329,7 +1335,6 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
name = mJointMap[name];
}
model->mSkinInfo.mJointNames.push_back(name);
model->mSkinInfo.mJointMap[name] = j;
}
}
else
@ -1347,7 +1352,6 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
name = mJointMap[name];
}
model->mSkinInfo.mJointNames.push_back(name);
model->mSkinInfo.mJointMap[name] = j;
}
}
}
@ -1375,8 +1379,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);
}
}
}
@ -1392,35 +1395,40 @@ 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
//The joints are reset in the dtor
if ( getRigWithSceneParity() )
{
JointMap :: const_iterator masterJointIt = mJointMap.begin();
JointMap :: const_iterator masterJointItEnd = mJointMap.end();
for (;masterJointIt!=masterJointItEnd;++masterJointIt )
{
std::string lookingForJoint = (*masterJointIt).first.c_str();
//Set the joint translations on the avatar
JointMap :: const_iterator masterJointIt = mJointMap.begin();
JointMap :: const_iterator masterJointItEnd = mJointMap.end();
for (;masterJointIt!=masterJointItEnd;++masterJointIt )
{
std::string lookingForJoint = (*masterJointIt).first.c_str();
if ( mJointList.find( lookingForJoint ) != mJointList.end() )
{
//LL_INFOS()<<"joint "<<lookingForJoint.c_str()<<LL_ENDL;
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, "");
}
else
{
//Most likely an error in the asset.
LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL;
}
}
}
}
if ( mJointList.find( lookingForJoint ) != mJointList.end() )
{
//LL_INFOS()<<"joint "<<lookingForJoint.c_str()<<LL_ENDL;
LLMatrix4 jointTransform = mJointList[lookingForJoint];
LLJoint* pJoint = mJointLookupFunc(lookingForJoint,mOpaqueData);
if ( pJoint )
{
// 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();
pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, "");
}
else
{
//Most likely an error in the asset.
LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL;
}
}
}
} //missingSkeletonOrScene
//We need to construct the alternate bind matrix (which contains the new joint positions)
@ -1434,16 +1442,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;
}
}
@ -1890,7 +1897,7 @@ daeElement* LLDAELoader::getChildFromElement( daeElement* pElement, std::string
{
return pChildOfElement;
}
LL_WARNS()<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL;
LL_DEBUGS("Mesh")<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL;
return NULL;
}

View File

@ -47,15 +47,17 @@ public:
dae_model_map mModelsMap;
LLDAELoader(
std::string filename,
S32 lod,
std::string filename,
S32 lod,
LLModelLoader::load_callback_t load_cb,
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);
virtual ~LLDAELoader() ;
@ -105,6 +107,5 @@ protected:
private:
U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels
bool mForceIdNaming;
};
#endif // LL_LLDAELLOADER_H

View File

@ -867,6 +867,7 @@ LLSD LLModel::writeModel(
S32 count = 0;
for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter)
{
// Note joint index cannot exceed 255.
if (iter->mJointIdx < 255 && iter->mJointIdx >= 0)
{
U8 idx = (U8) iter->mJointIdx;

View File

@ -46,7 +46,7 @@ public:
std::vector<std::string> mJointNames;
std::vector<LLMatrix4> mInvBindMatrix;
std::vector<LLMatrix4> mAlternateBindMatrix;
std::map<std::string, U32> mJointMap;
std::vector<U32> mJointRemap;
LLMeshSkinInfo() { }
LLMeshSkinInfo(LLSD& data);

View File

@ -104,16 +104,18 @@ void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3&
// LLModelLoader
//-----------------------------------------------------------------------------
LLModelLoader::LLModelLoader(
std::string filename,
S32 lod,
std::string filename,
S32 lod,
load_callback_t load_cb,
joint_lookup_func_t joint_lookup_func,
texture_load_func_t texture_load_func,
state_callback_t state_cb,
void* opaque_userdata,
JointTransformMap& jointMap,
JointSet& jointsFromNodes )
: mJointList( jointMap )
state_callback_t state_cb,
void* opaque_userdata,
JointTransformMap& jointTransformMap,
JointNameSet& jointsFromNodes,
JointMap& legalJointNamesMap,
U32 maxJointsPerMesh)
: mJointList( jointTransformMap )
, mJointsFromNode( jointsFromNodes )
, LLThread("Model Loader")
, mFilename(filename)
@ -126,88 +128,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)
{
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";
, mMaxJointsPerMesh(maxJointsPerMesh)
, mJointMap(legalJointNamesMap)
{
// <FS:Ansariel> FIRE-17144: Option to rig to attachment spots
if (LLControlGroup::getInstance("Global")->getBOOL("FSEnableRiggingToAttachmentSpots"))
@ -237,7 +165,6 @@ LLModelLoader::LLModelLoader(
mJointMap["Left_Foot"] = "Left Foot";
}
// </FS:Ansariel>
//move into joint mapper class
//1. joints for joint offset verification
mMasterJointList.push_front("mPelvis");
@ -507,8 +434,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
@ -516,59 +441,27 @@ void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::st
bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset );
bool isRigLegacyOK = isRigLegacy( jointListFromAsset );
//It's OK that both could end up being true, both default to false
if ( isJointPositionUploadOK )
// It's OK that both could end up being true.
// 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()
//-----------------------------------------------------------------------------
@ -580,68 +473,80 @@ 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();
// 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;
}
// Note that this is basically the same code as
// isRigSuitableForJointPositionUpload(), but the set of joints is
// different.
JointNameSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin();
JointNameSet :: const_iterator masterJointEndIt = mMasterLegacyJointList.end();
std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
S32 missing_joint_count = 0;
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;
}
if (std::find(modelJointIt,modelJointItEnd,*masterJointIt)==modelJointItEnd)
{
LL_INFOS() <<" Asset did not contain a joint required for skinned mesh upload: " << *masterJointIt<< LL_ENDL;
missing_joint_count++;
}
}
return result;
if (missing_joint_count>0)
{
LL_WARNS() << "Skinning disabled due to missing joints" << LL_ENDL;
}
return missing_joint_count==0;
}
//-----------------------------------------------------------------------------
// 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();
JointNameSet :: const_iterator masterJointIt = mMasterJointList.begin();
JointNameSet :: const_iterator masterJointEndIt = mMasterJointList.end();
std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
S32 missing_joint_count = 0;
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;
}
if (std::find(modelJointIt,modelJointItEnd,*masterJointIt)==modelJointItEnd)
{
LL_INFOS() <<" Asset did not contain a joint required for joint position upload: " << *masterJointIt<< LL_ENDL;
missing_joint_count++;
}
}
return result;
if (missing_joint_count>0)
{
LL_WARNS() << "Joint upload disabled due to missing joints" << LL_ENDL;
}
return missing_joint_count==0;
}

View File

@ -34,10 +34,10 @@
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::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> JointNameSet;
const S32 SLM_SUPPORTED_VERSION = 3;
const S32 NUM_LOD = 4;
@ -116,18 +116,21 @@ 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,
S32 lod,
std::string filename,
S32 lod,
LLModelLoader::load_callback_t load_cb,
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; }
@ -158,7 +161,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 +168,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; }
@ -189,17 +188,16 @@ 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;
JointNameSet mMasterJointList;
JointNameSet mMasterLegacyJointList;
JointTransformMap mJointTransformMap;
static std::list<LLModelLoader*> sActiveLoaderList;

View File

@ -658,6 +658,7 @@ set(viewer_SOURCE_FILES
llsidepaneliteminfo.cpp
llsidepaneltaskinfo.cpp
llsidetraypanelcontainer.cpp
llskinningutil.cpp
llsky.cpp
#llslurl.cpp #<FS:AW optional opensim support>
llsnapshotlivepreview.cpp
@ -1392,6 +1393,7 @@ set(viewer_HEADER_FILES
llsidepaneliteminfo.h
llsidepaneltaskinfo.h
llsidetraypanelcontainer.h
llskinningutil.h
llsky.h
llslurl.h
llsnapshotlivepreview.h

View File

@ -1,87 +1,2 @@
Translations 1.0
[hip]
relativepos = firstkey
relativerot = firstkey
outname = mPelvis
frame = 0 1 0, 0 0 1, 1 0 0
[abdomen]
outname = mTorso
frame = 0 1 0, 0 0 1, 1 0 0
[chest]
outname = mChest
frame = 0 1 0, 0 0 1, 1 0 0
[neckDummy]
ignore = true
frame = 0 1 0, 0 0 1, 1 0 0
[neck]
outname = mNeck
frame = 0 1 0, 0 0 1, 1 0 0
[head]
outname = mHead
frame = 0 1 0, 0 0 1, 1 0 0
[figureHair]
ignore = true
frame = 0 1 0, 0 0 1, 1 0 0
[lCollar]
outname = mCollarLeft
frame = 0 1 0, 0 0 1, 1 0 0
[lShldr]
outname = mShoulderLeft
frame = 0 1 0, 0 0 1, 1 0 0
[lForeArm]
outname = mElbowLeft
frame = 0 1 0, 0 0 1, 1 0 0
[lHand]
outname = mWristLeft
frame = 0 1 0, 0 0 1, 1 0 0
[rCollar]
outname = mCollarRight
frame = 0 1 0, 0 0 1, 1 0 0
[rShldr]
outname = mShoulderRight
frame = 0 1 0, 0 0 1, 1 0 0
[rForeArm]
outname = mElbowRight
frame = 0 1 0, 0 0 1, 1 0 0
[rHand]
outname = mWristRight
frame = 0 1 0, 0 0 1, 1 0 0
[lThigh]
outname = mHipLeft
frame = 0 1 0, 0 0 1, 1 0 0
[lShin]
outname = mKneeLeft
frame = 0 1 0, 0 0 1, 1 0 0
[lFoot]
outname = mAnkleLeft
frame = 0 1 0, 0 0 1, 1 0 0
[rThigh]
outname = mHipRight
frame = 0 1 0, 0 0 1, 1 0 0
[rShin]
outname = mKneeRight
frame = 0 1 0, 0 0 1, 1 0 0
[rFoot]
outname = mAnkleRight
frame = 0 1 0, 0 0 1, 1 0 0

View File

@ -5437,6 +5437,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>IncludeEnhancedSkeleton</key>
<map>
<key>Comment</key>
<string>Include extended skeleton joints when rendering skinned meshes.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>MinObjectsForUnlinkConfirm</key>
<map>
<key>Comment</key>

View File

@ -24,8 +24,11 @@
ATTRIBUTE vec4 weight4;
uniform mat3 matrixPalette[52];
uniform vec3 translationPalette[52];
/* BENTO JOINT COUNT LIMITS
* Note that the value in these two lines also needs to be updated to value-1 several places below.
*/
uniform mat3 matrixPalette[MAX_JOINTS_PER_MESH_OBJECT];
uniform vec3 translationPalette[MAX_JOINTS_PER_MESH_OBJECT];
mat4 getObjectSkinnedTransform()
{
@ -34,7 +37,7 @@ mat4 getObjectSkinnedTransform()
vec4 w = fract(weight4);
vec4 index = floor(weight4);
index = min(index, vec4(51.0));
index = min(index, vec4(MAX_JOINTS_PER_MESH_OBJECT-1));
index = max(index, vec4( 0.0));
w *= 1.0/(w.x+w.y+w.z+w.w);
@ -67,8 +70,8 @@ mat4 getObjectSkinnedTransform()
// If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts.
mat3 dummy1 = matrixPalette[0];
vec3 dummy2 = translationPalette[0];
mat3 dummy3 = matrixPalette[51];
vec3 dummy4 = translationPalette[51];
mat3 dummy3 = matrixPalette[MAX_JOINTS_PER_MESH_OBJECT-1];
vec3 dummy4 = translationPalette[MAX_JOINTS_PER_MESH_OBJECT-1];
#endif
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<linden_avatar
version="1.0" wearable_definition_version="22">
version="2.0" wearable_definition_version="22">
<!-- The wearable_definition_version is checked during asset upload. -->
<!-- If you increment it, check indra/lib/python/indra/assetutil.py. -->
<skeleton
@ -73,7 +73,7 @@
joint="mFootLeft"
position="0 0.0 0.0"
rotation="0 0 0"
visible_in_first_person="true"/>
visible_in_first_person="true"/>
<attachment_point
id="8"
@ -83,7 +83,7 @@
joint="mFootRight"
position="0 0.0 0.0"
rotation="0 0 0"
visible_in_first_person="true"/>
visible_in_first_person="true"/>
<attachment_point
id="9"
@ -93,7 +93,7 @@
joint="mChest"
position="-0.15 0 -0.1"
rotation="0 -90 90"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="10"
@ -103,7 +103,7 @@
joint="mPelvis"
position="0 0 -0.15"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="11"
@ -113,8 +113,8 @@
joint="mHead"
position="0.12 0 0.001"
rotation="0 0 0"
visible_in_first_person="false"/>
visible_in_first_person="false"/>
<attachment_point
id="12"
group="2"
@ -123,7 +123,7 @@
joint="mHead"
position="0.12 0 -0.04"
rotation="0 0 0"
visible_in_first_person="false" />
visible_in_first_person="false" />
<attachment_point
id="13"
@ -133,7 +133,7 @@
joint="mHead"
position="0.015 0.08 0.017"
rotation="0 0 0"
visible_in_first_person="false" />
visible_in_first_person="false" />
<attachment_point
id="14"
@ -143,7 +143,7 @@
joint="mHead"
position="0.015 -0.08 0.017"
rotation="0 0 0"
visible_in_first_person="false" />
visible_in_first_person="false" />
<attachment_point
id="15"
@ -153,7 +153,7 @@
joint="mEyeLeft"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="false"/>
visible_in_first_person="false"/>
<attachment_point
id="16"
@ -163,7 +163,7 @@
joint="mEyeRight"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="false" />
visible_in_first_person="false" />
<attachment_point
id="17"
@ -173,7 +173,7 @@
joint="mHead"
position="0.1 0 0.05"
rotation="0 0 0"
visible_in_first_person="false"/>
visible_in_first_person="false"/>
<attachment_point
id="18"
@ -183,7 +183,7 @@
joint="mShoulderRight"
position="0.01 -0.13 0.01"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="19"
@ -193,7 +193,7 @@
joint="mElbowRight"
position="0 -0.12 0"
rotation="0 0 0"
visible_in_first_person="true"/>
visible_in_first_person="true"/>
<attachment_point
id="20"
@ -203,7 +203,7 @@
joint="mShoulderLeft"
position="0.01 0.15 -0.01"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="21"
@ -213,7 +213,7 @@
joint="mElbowLeft"
position="0 0.113 0"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="22"
@ -223,7 +223,7 @@
joint="mHipRight"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="23"
@ -233,7 +233,7 @@
joint="mHipRight"
position="-0.017 0.041 -0.310"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="24"
@ -243,7 +243,7 @@
joint="mKneeRight"
position="-0.044 -0.007 -0.262"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="25"
@ -253,8 +253,8 @@
joint="mHipLeft"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="26"
group="5"
@ -263,7 +263,7 @@
joint="mHipLeft"
position="-0.019 -0.034 -0.310"
rotation="0 0 0"
visible_in_first_person="true"/>
visible_in_first_person="true"/>
<attachment_point
id="27"
@ -273,7 +273,7 @@
joint="mKneeLeft"
position="-0.044 -0.007 -0.261"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="28"
@ -283,7 +283,7 @@
joint="mPelvis"
position="0.092 0.0 0.088"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="29"
@ -293,7 +293,7 @@
joint="mTorso"
position="0.104 0.082 0.247"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="30"
@ -303,11 +303,11 @@
joint="mTorso"
position="0.104 -0.082 0.247"
rotation="0 0 0"
visible_in_first_person="true" />
visible_in_first_person="true" />
<attachment_point
id="31"
group="8"
group="9"
name="Center 2"
joint="mScreen"
position="0 0 0"
@ -318,7 +318,7 @@
<attachment_point
id="32"
group="8"
group="9"
name="Top Right"
joint="mScreen"
position="0 -0.5 0.5"
@ -329,7 +329,7 @@
<attachment_point
id="33"
group="8"
group="9"
name="Top"
joint="mScreen"
position="0 0 0.5"
@ -340,7 +340,7 @@
<attachment_point
id="34"
group="8"
group="9"
name="Top Left"
joint="mScreen"
position="0 0.5 0.5"
@ -351,7 +351,7 @@
<attachment_point
id="35"
group="8"
group="9"
name="Center"
joint="mScreen"
position="0 0 0"
@ -362,7 +362,7 @@
<attachment_point
id="36"
group="8"
group="9"
name="Bottom Left"
joint="mScreen"
position="0 0.5 -0.5"
@ -373,7 +373,7 @@
<attachment_point
id="37"
group="8"
group="9"
name="Bottom"
joint="mScreen"
position="0 0 -0.5"
@ -384,7 +384,7 @@
<attachment_point
id="38"
group="8"
group="9"
name="Bottom Right"
joint="mScreen"
position="0 -0.5 -0.5"
@ -413,6 +413,140 @@
rotation="0 0 0"
visible_in_first_person="true" />
<!-- BENTO ADDITIONS -->
<attachment_point
id="41"
group="8"
pie_slice="0"
name="Left Ring Finger"
joint="mHandRing1Left"
position="-0.006 0.019 -0.002"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="42"
group="8"
pie_slice="1"
name="Right Ring Finger"
joint="mHandRing1Right"
position="-0.006 -0.019 -0.002"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="43"
group="8"
pie_slice="2"
name="Tail Base"
joint="mTail1"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="44"
group="8"
pie_slice="3"
name="Tail Tip"
joint="mTail6"
position="-0.025 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="45"
group="8"
pie_slice="4"
name="Left Wing"
joint="mWing4Left"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="46"
group="8"
pie_slice="5"
name="Right Wing"
joint="mWing4Right"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="47"
group="8"
pie_slice="6"
name="Jaw"
joint="mFaceJaw"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="48"
group="8"
pie_slice="7"
name="Alt Left Ear"
joint="mFaceEarLeft"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="49"
group="8"
pie_slice="8"
name="Alt Right Ear"
joint="mFaceEarRight"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="50"
group="8"
pie_slice="9"
name="Alt Left Eye"
joint="mFaceEyeAltLeft"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="51"
group="8"
pie_slice="10"
name="Alt Right Eye"
joint="mFaceEyeAltRight"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="52"
group="8"
pie_slice="11"
name="Tongue"
joint="mFaceTongueTip"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<attachment_point
id="53"
group="8"
pie_slice="12"
name="Groin"
joint="mGroin"
position="0.000 0.000 0.000"
rotation="0 0 0"
visible_in_first_person="true"/>
<!-- END BENTO -->
<param
id="32"
group="1"
@ -478,6 +612,13 @@
<bone
name="mKneeRight"
scale=".05 .05 .1" />
<bone name="mWingsRoot1" scale="1 0 0" offset="0 0 0" />
<bone name="mWingsRoot2" scale="1 0 0" offset="0 0 0" />
<bone name="mWingsRoot3" scale="1 0 0" offset="0 0 0" />
<bone name="mWing1Right" scale="0 0 0" offset="0.02 0 0" />
<bone name="mWing1Left" scale="0 0 0" offset="0.02 0 0" />
</param_skeleton>
</param>
@ -624,6 +765,17 @@
<bone
name="mKneeRight"
scale="0.12 0.12 0" />
<bone name="mTail1" scale="0.05 0.1 0.1" />
<bone name="mTail2" scale="0.05 0.1 0.1" />
<bone name="mTail3" scale="0.05 0.1 0.1" />
<bone name="mTail4" scale="0.05 0.1 0.1" />
<bone name="mTail5" scale="0.05 0.1 0.1" />
<bone name="mTail6" scale="0.05 0 0" />
<bone name="mWing1Right" offset="-0.01 -0.01 0" />
<bone name="mWing1Left" offset="-0.01 0.01 0" />
</param_skeleton>
</param>
@ -662,6 +814,10 @@
<bone
name="mChest"
scale="0.02 0.08 0" />
<bone name="mWing1Right" offset="0 -0.02 0" />
<bone name="mWing1Left" offset="0 0.02 0" />
</param_skeleton>
</param>
@ -693,6 +849,11 @@
name="mHipRight"
scale="0 0 0"
offset="0 -.004 0" />
<bone name="mTail1" scale="0.0 0.05 0" />
<bone name="mTail2" scale="0.0 0.02 0" />
<bone name="mTail3" scale="0.0 0.01 0" />
</param_skeleton>
</param>
@ -774,6 +935,17 @@
name="mEyeRight"
scale="0 0 0"
offset="0 -.009 0" />
<bone
name="mFaceEyeAltLeft"
scale="0 0 0 "
offset="0 .009 0" />
<bone
name="mFaceEyeAltRight"
scale="0 0 0 "
offset="0 -.009 0" />
</param_skeleton>
</param>
@ -797,6 +969,17 @@
name="mEyeRight"
scale="0 0 0"
offset="0 0 -.004" />
<bone
name="mFaceEyeAltLeft"
scale="0 0 0"
offset="0 0 .004" />
<bone
name="mFaceEyeAltRight"
scale="0 0 0"
offset="0 0 -.004" />
</param_skeleton>
</param>
@ -820,6 +1003,17 @@
name="mEyeRight"
scale="0 0 0"
offset=".016 0 0" />
<bone
name="mFaceEyeAltLeft"
scale="0 0 0"
offset=".016 0 0" />
<bone
name="mFaceEyeAltRight"
scale="0 0 0"
offset=".016 0 0" />
</param_skeleton>
</param>
@ -843,6 +1037,15 @@
name="mEyeRight"
scale="0 0 0"
offset=".005 0 0" />
<bone
name="mFaceEyeAltLeft"
scale="0 0 0"
offset=".005 0 0" />
<bone
name="mFaceEyeAltRight"
scale="0 0 0"
offset=".005 0 0" />
</param_skeleton>
</param>
@ -878,6 +1081,147 @@
name="mEyeRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyeAltLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyeAltRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceForeheadLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceForeheadRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyebrowOuterLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyebrowCenterLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyebrowInnerLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyebrowOuterRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyebrowCenterRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyebrowInnerRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyeLidUpperLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyeLidLowerLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyeLidUpperRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceEyeLidLowerRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceNoseLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceNoseCenter"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceoseRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceCheekUpperInnerLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceCheekUpperOuterLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceCheekUpperInnerRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceCheekUpperOuterRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceJaw"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceLipUpperLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceLipUpperRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceLipCornerLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceLipCornerRight"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceLipLowerLeft"
scale="1 1 1"
offset="0 0 0" />
<bone
name="mFaceLipLowerRight"
scale="1 1 1"
offset="0 0 0" />
</param_skeleton>
</param>
@ -951,6 +1295,47 @@
name="mWristLeft"
scale="1 1 1"
offset="0 0 0" />
<bone name = "mHandThumb1Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandThumb2Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandThumb3Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandIndex1Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandIndex2Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandIndex3Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandMiddle1Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandMiddle2Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandMiddle3Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandRing1Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandRing2Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandRing3Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandPinky1Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandPinky2Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandPinky3Right" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandThumb1Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandThumb2Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandThumb3Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandIndex1Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandIndex2Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandIndex3Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandMiddle1Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandMiddle2Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandMiddle3Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandRing1Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandRing2Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandRing3Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandPinky1Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandPinky2Left" scale = "1 1 1" offset = "0 0 0" />
<bone name = "mHandPinky3Left" scale = "1 1 1" offset = "0 0 0" />
</param_skeleton>
</param>
@ -997,6 +1382,17 @@
name="mEyeRight"
scale="0 0 0"
offset="-.005 0 0" />
<bone
name="mFaceEyeAltLeft"
scale="0 0 0"
offset="-.005 0 0" />
<bone
name="mFaceEyeAltRight"
scale="0 0 0"
offset="-.005 0 0" />
</param_skeleton>
</param>

File diff suppressed because it is too large Load Diff

View File

@ -1,81 +1,192 @@
<?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 num_bones="106" num_collision_volumes="26" version="2.0">
<bone aliases="hip avatar_mPelvis" end="0.000 0.000 0.084" group="SL Base" 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" connected="false">
<collision_volume end="0.020 0.000 0.100" 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 aliases="abdomen avatar_mTorso" connected="true" end="-0.015 0.000 0.205" group="SL Base" 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.020 0.000 0.100" 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 aliases="chest avatar_mChest" connected="true" end="-0.010 0.000 0.250" group="SL Base" 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.080 0.000 0.180" 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.000" 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.000" 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="SL Base" 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="SL Base" 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="true" end="0.000 0.000 0.033" group="SL Base" 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" end="0.100 0.000 0.000" group="SL Base" 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" connected="false"/>
<bone aliases="avatar_mEyeLeft" end="0.100 0.000 0.000" group="SL Base" 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" connected="false"/>
<bone end="0.024 0.004 0.018" group="Face" name="mFaceForeheadLeft" pivot="0.086323 0.035081 0.128273" pos="0.086 0.035 0.128" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.024 -0.004 0.018" group="Face" name="mFaceForeheadRight" pivot="0.086323 -0.035081 0.128273" pos="0.086 -0.035 0.128" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.027 0.000 0.000" group="Face" name="mFaceEyebrowOuterLeft" pivot="0.084314 0.064144 0.093192" pos="0.084 0.064 0.093" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.027 0.000 0.000" group="Face" name="mFaceEyebrowCenterLeft" pivot="0.095341 0.043099 0.101210" pos="0.095 0.043 0.101" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.027 -0.001 -0.001" group="Face" name="mFaceEyebrowInnerLeft" pivot="0.099350 0.023054 0.097201" pos="0.099 0.023 0.097" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.027 0.000 0.000" group="Face" name="mFaceEyebrowOuterRight" pivot="0.084314 -0.064144 0.093192" pos="0.084 -0.064 0.093" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.027 0.000 0.000" group="Face" name="mFaceEyebrowCenterRight" pivot="0.095341 -0.043099 0.101210" pos="0.095 -0.043 0.101" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.027 0.001 -0.001" group="Face" name="mFaceEyebrowInnerRight" pivot="0.099350 -0.023054 0.097201" pos="0.099 -0.023 0.097" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.038 0.000 0.000" group="Face" name="mFaceEyeLidUpperLeft" pivot="0.087323 0.036081 0.084174" pos="0.087 0.036 0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.100 0.000 0.000" group="Face" name="mFaceEyeAltLeft" pivot="0.098486 0.036009 0.079020" pos="0.098 0.036 0.079" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.036 0.000 0.000" group="Face" name="mFaceEyeLidLowerLeft" pivot="0.086323 0.036081 0.072147" pos="0.086 0.036 0.072" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.038 0.000 0.000" group="Face" name="mFaceEyeLidUpperRight" pivot="0.087323 -0.036081 0.084174" pos="0.087 -0.036 0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.100 0.000 0.000" group="Face" name="mFaceEyeAltRight" pivot="0.098486 -0.036009 0.079020" pos="0.098 -0.036 0.079" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.036 0.000 0.000" group="Face" name="mFaceEyeLidLowerRight" pivot="0.086323 -0.036081 0.072147" pos="0.086 -0.036 0.072" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="-0.019 0.018 0.025" group="Face" name="mFaceEarLeft" pivot="0.025179 0.080180 0.047093" pos="0.025 0.080 0.047" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="-0.019 -0.018 0.025" group="Face" name="mFaceEarRight" pivot="0.025179 -0.080180 0.047093" pos="0.025 -0.080 0.047" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.007 0.005 0.002" group="Face" name="mFaceNoseLeft" pivot="0.121395 0.014036 0.045084" pos="0.121 0.014 0.045" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.031 0.000 0.000" group="Face" name="mFaceNoseCenter" pivot="0.121395 0.000000 0.045084" pos="0.121 0.000 0.045" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.007 -0.005 0.002" group="Face" name="mFaceNoseRight" pivot="0.121395 -0.014036 0.045084" pos="0.121 -0.014 0.045" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.018 0.004 -0.006" group="Face" name="mFaceCheekUpperInnerLeft" pivot="0.101350 0.044099 0.043084" pos="0.101 0.044 0.043" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.005 0.015 0.005" group="Face" name="mFaceCheekUpperOuterLeft" pivot="0.082314 0.057126 0.053102" pos="0.082 0.057 0.053" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.018 -0.004 -0.006" group="Face" name="mFaceCheekUpperInnerRight" pivot="0.101350 -0.044099 0.043084" pos="0.101 -0.044 0.043" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.005 -0.015 0.005" group="Face" name="mFaceCheekUpperOuterRight" pivot="0.082314 -0.057126 0.053102" pos="0.082 -0.057 0.053" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.053 0.004 -0.007" group="Face" name="mFaceLipUpperLeft" pivot="0.081305 0.011027 0.021030" pos="0.081 0.011 0.021" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.053 -0.004 -0.007" group="Face" name="mFaceLipUpperRight" pivot="0.081305 -0.011027 0.021030" pos="0.081 -0.011 0.021" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.037 -0.001 0.000" group="Face" name="mFaceLipCornerLeft" pivot="0.082314 0.033072 0.007002" pos="0.082 0.033 0.007" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.037 0.001 0.000" group="Face" name="mFaceLipCornerRight" pivot="0.082314 -0.033072 0.007002" pos="0.082 -0.033 0.007" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.045 0.000 -0.021" group="Face" name="mFaceJaw" pivot="0.044224 0.000000 0.008003" pos="0.044 0.000 0.008" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="0.020 0.000 0.008" group="Face" name="mFaceTongueBase" pivot="0.045000 0.000000 -0.021000" pos="0.045 0.000 -0.021" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="0.007 0.000 0.003" group="Face" name="mFaceTongueTip" pivot="0.020000 0.000000 0.008000" pos="0.020 0.000 0.008" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
<bone end="0.045 0.000 0.005" group="Face" name="mFaceLipLowerLeft" pivot="0.042000 0.017000 -0.021000" pos="0.042 0.017 -0.021" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
<bone end="0.045 0.000 0.005" group="Face" name="mFaceLipLowerRight" pivot="0.042000 -0.017000 -0.021000" pos="0.042 -0.017 -0.021" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
</bone>
</bone>
</bone>
<bone aliases="lCollar avatar_mCollarLeft" end="0.000 0.079 0.000" group="SL Base" 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" connected="false">
<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="SL Base" 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.000" 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="SL Base" 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.000" 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="SL Base" 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.000 0.050 0.000" 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 end="-0.001 0.041 -0.004" group="Hand" name="mHandMiddle1Left" pivot="0.013427 0.099641 0.008427" pos="0.013 0.100 0.008" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.001 0.049 -0.006" group="Hand" name="mHandMiddle2Left" pivot="-0.000959 0.040656 -0.004287" pos="-0.001 0.041 -0.004" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.002 0.033 -0.004" group="Hand" name="mHandMiddle3Left" pivot="-0.001476 0.048719 -0.005798" pos="-0.001 0.049 -0.006" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
<bone end="0.019 0.042 -0.004" group="Hand" name="mHandIndex1Left" pivot="0.036416 0.091419 0.010424" pos="0.036 0.091 0.010" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="0.014 0.032 -0.004" group="Hand" name="mHandIndex2Left" pivot="0.019056 0.041560 -0.004473" pos="0.019 0.042 -0.004" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="0.011 0.025 -0.003" group="Hand" name="mHandIndex3Left" pivot="0.014330 0.032011 -0.004359" pos="0.014 0.032 -0.004" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
<bone end="-0.013 0.039 -0.005" group="Hand" name="mHandRing1Left" pivot="-0.010432 0.098025 0.003099" pos="-0.010 0.098 0.003" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.013 0.040 -0.007" group="Hand" name="mHandRing2Left" pivot="-0.013326 0.038577 -0.005495" pos="-0.013 0.039 -0.005" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.010 0.028 -0.004" group="Hand" name="mHandRing3Left" pivot="-0.013398 0.039825 -0.006514" pos="-0.013 0.040 -0.007" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
<bone end="-0.020 0.024 -0.004" group="Hand" name="mHandPinky1Left" pivot="-0.035119 0.095515 -0.001334" pos="-0.035 0.096 -0.001" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.015 0.018 -0.003" group="Hand" name="mHandPinky2Left" pivot="-0.020450 0.023623 -0.003633" pos="-0.020 0.024 -0.004" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.013 0.016 -0.003" group="Hand" name="mHandPinky3Left" pivot="-0.015199 0.018236 -0.003472" pos="-0.015 0.018 -0.003" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
<bone end="0.028 0.030 0.001" group="Hand" name="mHandThumb1Left" pivot="0.035471 0.035681 -0.000635" pos="0.035 0.036 -0.001" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="0.018 0.026 0.001" group="Hand" name="mHandThumb2Left" pivot="0.028355 0.029579 0.001081" pos="0.028 0.030 0.001" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="0.016 0.024 0.001" group="Hand" name="mHandThumb3Left" pivot="0.017873 0.026014 0.000851" pos="0.018 0.026 0.001" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
</bone>
</bone>
</bone>
</bone>
<bone aliases="rCollar avatar_mCollarRight" end="0.000 -0.079 0.000" group="SL Base" 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" connected="false">
<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="SL Base" 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.000" 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="SL Base" 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.000" 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="SL Base" 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.000 -0.050 0.000" 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 end="-0.001 -0.041 -0.004" group="Hand" name="mHandMiddle1Right" pivot="0.013427 -0.099641 0.008427" pos="0.013 -0.100 0.008" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.001 -0.049 -0.006" group="Hand" name="mHandMiddle2Right" pivot="-0.000959 -0.040656 -0.004287" pos="-0.001 -0.041 -0.004" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.002 -0.033 -0.004" group="Hand" name="mHandMiddle3Right" pivot="-0.001476 -0.048719 -0.005798" pos="-0.001 -0.049 -0.006" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
<bone end="0.019 -0.042 -0.004" group="Hand" name="mHandIndex1Right" pivot="0.036416 -0.091419 0.010424" pos="0.036 -0.091 0.010" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="0.014 -0.032 -0.004" group="Hand" name="mHandIndex2Right" pivot="0.019056 -0.041560 -0.004473" pos="0.019 -0.042 -0.004" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="0.011 -0.025 -0.003" group="Hand" name="mHandIndex3Right" pivot="0.014330 -0.032011 -0.004359" pos="0.014 -0.032 -0.004" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
<bone end="-0.013 -0.039 -0.005" group="Hand" name="mHandRing1Right" pivot="-0.010432 -0.098025 0.003099" pos="-0.010 -0.098 0.003" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.013 -0.040 -0.007" group="Hand" name="mHandRing2Right" pivot="-0.013326 -0.038577 -0.005495" pos="-0.013 -0.039 -0.005" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.010 -0.028 -0.004" group="Hand" name="mHandRing3Right" pivot="-0.013398 -0.039825 -0.006514" pos="-0.013 -0.040 -0.007" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
<bone end="-0.020 -0.024 -0.004" group="Hand" name="mHandPinky1Right" pivot="-0.035119 -0.095515 -0.001334" pos="-0.035 -0.096 -0.001" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.015 -0.018 -0.003" group="Hand" name="mHandPinky2Right" pivot="-0.020450 -0.023623 -0.003633" pos="-0.020 -0.024 -0.004" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.013 -0.016 -0.003" group="Hand" name="mHandPinky3Right" pivot="-0.015199 -0.018236 -0.003472" pos="-0.015 -0.018 -0.003" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
<bone end="0.028 -0.030 0.001" group="Hand" name="mHandThumb1Right" pivot="0.035471 -0.035681 -0.000635" pos="0.035 -0.036 -0.001" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="0.018 -0.026 0.001" group="Hand" name="mHandThumb2Right" pivot="0.028355 -0.029579 0.001081" pos="0.028 -0.030 0.001" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="0.016 -0.024 0.001" group="Hand" name="mHandThumb3Right" pivot="0.017873 -0.026014 0.000851" pos="0.018 -0.026 0.001" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
</bone>
</bone>
</bone>
</bone>
<bone end="-0.015 0.000 0.000" group="Wing" name="mWingsRoot1" pivot="-0.014427 0.000057 -0.000108" pos="-0.014 0.000 -0.000" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.020 0.000 0.000" group="Wing" name="mWingsRoot2" pivot="-0.015000 0.000000 0.000000" pos="-0.015 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.026 0.000 0.000" group="Wing" name="mWingsRoot3" pivot="-0.020095 0.000000 0.000000" pos="-0.020 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone end="-0.168 0.169 0.067" group="Wing" name="mWing1Left" pivot="-0.063834 0.105140 0.181096" pos="-0.064 0.105 0.181" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.181 0.183 -0.000" group="Wing" name="mWing2Left" pivot="-0.167657 0.169194 0.066907" pos="-0.168 0.169 0.067" rot="0.000000 0.000000 0.000000" 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.181322 0.182984 -0.000120" pos="-0.181 0.183 -0.000" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.028 0.029 0.000" group="Wing" name="mWing4Left" pivot="-0.170953 0.172520 -0.000113" pos="-0.171 0.173 -0.000" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
</bone>
<bone end="-0.168 -0.169 0.067" group="Wing" name="mWing1Right" pivot="-0.063834 -0.105254 0.181096" pos="-0.064 -0.105 0.181" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.181 -0.183 -0.000" group="Wing" name="mWing2Right" pivot="-0.167657 -0.169194 0.066907" pos="-0.168 -0.169 0.067" rot="0.000000 0.000000 0.000000" 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.181322 -0.182984 -0.000120" pos="-0.181 -0.183 -0.000" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.028 -0.029 0.000" group="Wing" name="mWing4Right" pivot="-0.170953 -0.172520 -0.000113" pos="-0.171 -0.173 -0.000" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
</bone>
</bone>
</bone>
</bone>
</bone>
</bone>
<bone aliases="rThigh avatar_mHipRight" end="-0.001 0.046 -0.491" group="SL Base" 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" connected="false">
<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.001 -0.469" group="SL Base" 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="SL Base" 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.100 0.000 -0.020" 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.008 -0.000" group="SL Base" 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="true" end="0.020 0.000 0.000" group="SL Base" 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" end="-0.001 -0.046 -0.491" group="SL Base" 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" connected="false">
<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="SL Base" 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="SL Base" 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.100 0.000 -0.020" 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="SL Base" 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="true" end="0.020 0.000 0.000" group="SL Base" 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 end="-0.197 0.000 0.000" group="Tail" name="mTail1" pivot="-0.116417 0.000000 0.047423" pos="-0.116 0.000 0.047" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false">
<bone connected="true" end="-0.168 0.000 0.000" group="Tail" name="mTail2" pivot="-0.197078 0.000000 0.000000" pos="-0.197 0.000 0.000" rot="0.000000 0.000000 0.000000" 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.168068 0.000000 0.000000" pos="-0.168 0.000 0.000" rot="0.000000 0.000000 0.000000" 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.142056 0.000000 0.000000" pos="-0.142 0.000 0.000" rot="0.000000 0.000000 0.000000" 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.112044 0.000000 0.000000" pos="-0.112 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
<bone connected="true" end="-0.025 0.000 0.000" group="Tail" name="mTail6" pivot="-0.094038 0.000000 0.000000" pos="-0.094 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
</bone>
</bone>
</bone>
</bone>
</bone>
<bone end="0.004 0.000 -0.007" group="SL Extended" name="mGroin" pivot="0.064234 0.000000 -0.096868" pos="0.064 0.000 -0.097" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" connected="false"/>
</bone>
</linden_skeleton>

View File

@ -0,0 +1,81 @@
<?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>

View File

@ -116,6 +116,7 @@
#include "llscenemonitor.h"
#include "llavatarrenderinfoaccountant.h"
#include "lllocalbitmaps.h"
#include "llskinningutil.h"
// Linden library includes
#include "llavatarnamecache.h"
@ -970,6 +971,9 @@ bool LLAppViewer::init()
LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ;
// initialize skinning util
LLSkinningUtil::initClass();
//set the max heap size.
initMaxHeapSize() ;
LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
@ -3311,7 +3315,7 @@ bool LLAppViewer::initConfiguration()
//
gWindowTitle = LLVersionInfo::getChannelAndVersion(); // <FS:CR>
#if LL_DEBUG
gWindowTitle += std::string(" [DEBUG]")
gWindowTitle += std::string(" [DEBUG]");
#endif
if (!gArgs.empty())
{

View File

@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "lldrawpoolavatar.h"
#include "llskinningutil.h"
#include "llrender.h"
#include "llvoavatar.h"
@ -63,8 +64,6 @@ static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK;
static U32 sBufferUsage = GL_STREAM_DRAW_ARB;
static U32 sShaderLevel = 0;
#define JOINT_COUNT 52
LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL;
BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE;
BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE;
@ -1588,7 +1587,13 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
}
void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
void LLDrawPoolAvatar::getRiggedGeometry(
LLFace* face,
LLPointer<LLVertexBuffer>& buffer,
U32 data_mask,
const LLMeshSkinInfo* skin,
LLVolume* volume,
const LLVolumeFace& vol_face)
{
// <FS:ND> FIRE-14261 try to skip broken or out of bounds faces
if( vol_face.mNumVertices > 0x10000 || vol_face.mNumVertices < 0 || vol_face.mNumIndices < 0 )
@ -1608,7 +1613,8 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
face->setTextureIndex(255);
if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable())
{ //make a new buffer
{
// make a new buffer
if (sShaderLevel > 0)
{
buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
@ -1620,7 +1626,8 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true);
}
else
{ //resize existing buffer
{
//resize existing buffer
buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices);
}
@ -1634,9 +1641,9 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
m = m.inverse().transpose();
F32 mat3[] =
{ m.m[0], m.m[1], m.m[2],
m.m[4], m.m[5], m.m[6],
m.m[8], m.m[9], m.m[10] };
{ m.m[0], m.m[1], m.m[2],
m.m[4], m.m[5], m.m[6],
m.m[8], m.m[9], m.m[10] };
LLMatrix3 mat_normal(mat3);
@ -1674,26 +1681,37 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
{
face->clearState(LLFace::TEXTURE_ANIM);
}
face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true);
buffer->flush();
}
void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
LLVOAvatar* avatar,
LLFace* face,
const LLMeshSkinInfo* skin,
LLVolume* volume,
const LLVolumeFace& vol_face)
{
LLVector4a* weight = vol_face.mWeights;
if (!weight)
{
return;
}
// FIXME ugly const cast
LLSkinningUtil::remapSkinInfoJoints(avatar, const_cast<LLMeshSkinInfo*>(skin));
LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
LLDrawable* drawable = face->getDrawable();
U32 data_mask = face->getRiggedVertexBufferDataMask();
if (!vol_face.mWeightsRemapped)
{
LLSkinningUtil::remapSkinWeights(weight, vol_face.mNumVertices, skin);
vol_face.mWeightsRemapped = TRUE;
}
if (buffer.isNull() ||
buffer->getTypeMask() != data_mask ||
buffer->getNumVerts() != vol_face.mNumVertices ||
@ -1744,85 +1762,19 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL;
//build matrix palette
LLMatrix4a mp[JOINT_COUNT];
LLMatrix4* mat = (LLMatrix4*) mp;
U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT);
for (U32 j = 0; j < count; ++j)
{
LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
if (!joint)
{
joint = avatar->getJoint("mPelvis");
}
if (!joint)
{
LL_DEBUGS("Avatar") << "Failed to find " << skin->mJointNames[j] << LL_ENDL;
}
if (joint)
{
mat[j] = skin->mInvBindMatrix[j];
mat[j] *= joint->getWorldMatrix();
}
}
LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
U32 count = LLSkinningUtil::getMeshJointCount(skin);
LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar);
LLSkinningUtil::checkSkinWeights(weight, buffer->getNumVerts(), skin);
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
__m128i _mMaxIdx = _mm_set_epi16( count-1, count-1, count-1, count-1, count-1, count-1, count-1, count-1 );
const U32 max_joints = LLSkinningUtil::getMaxJointCount();
for (U32 j = 0; j < buffer->getNumVerts(); ++j)
{
LLMatrix4a final_mat;
final_mat.clear();
// <FS:ND> Avoid the 8 floorf by using SSE2.
// S32 idx[4];
//
// LLVector4 wght;
//
// F32 scale = 0.f;
// for (U32 k = 0; k < 4; k++)
// {
// F32 w = weight[j][k];
//
// idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)JOINT_COUNT-1);
//
//
// wght[k] = w - floorf(w);
// scale += wght[k];
// }
//// This is enforced in unpackVolumeFaces()
//llassert(scale>0.f);
// wght *= 1.f/scale;
LL_ALIGN_16( S32 idx[4] );
LL_ALIGN_16( F32 wght[4] );
__m128i _mIdx = _mm_cvttps_epi32( weight[j] );
__m128 _mWeight = _mm_sub_ps( weight[j], _mm_cvtepi32_ps( _mIdx ) );
_mIdx = _mm_min_epi16( _mIdx, _mMaxIdx );
_mm_store_si128( (__m128i*)idx, _mIdx );
__m128 _mScale = _mm_add_ps( _mWeight, _mm_movehl_ps( _mWeight, _mWeight ));
_mScale = _mm_add_ss( _mScale, _mm_shuffle_ps( _mScale, _mScale, 1) );
_mScale = _mm_shuffle_ps( _mScale, _mScale, 0 );
_mWeight = _mm_div_ps( _mWeight, _mScale );
_mm_store_ps( wght, _mWeight );
// </FS:ND>
for (U32 k = 0; k < 4; k++)
{
F32 w = wght[k];
LLMatrix4a src;
src.setMul(mp[idx[k]], w);
final_mat.add(src);
}
LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints);
LLVector4a& v = vol_face.mPositions[j];
LLVector4a t;
@ -1902,34 +1854,21 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
if (buff)
{
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((LLMatrix4*)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("mPelvis");
}
if (joint)
{
mat[i] = skin->mInvBindMatrix[i];
mat[i] *= joint->getWorldMatrix();
}
}
stop_glerror();
F32 mp[JOINT_COUNT*9];
F32 mp[LL_MAX_JOINTS_PER_MESH_OBJECT*9];
F32 transp[JOINT_COUNT*3];
F32 transp[LL_MAX_JOINTS_PER_MESH_OBJECT*3];
for (U32 i = 0; i < count; ++i)
{
F32* m = (F32*) mat[i].mMatrix;
F32* m = (F32*) mat[i].mMatrix[0].getF32ptr();
U32 idx = i*9;
@ -2110,30 +2049,21 @@ void LLDrawPoolAvatar::renderRiggedShadows(LLVOAvatar* avatar)
if (buff)
{
if (sShaderLevel > 0)
{ //upload matrix palette to shader
LLMatrix4 mat[JOINT_COUNT];
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)
{
mat[i] = skin->mInvBindMatrix[i];
mat[i] *= joint->getWorldMatrix();
}
}
{
// upload matrix palette to shader
LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
U32 count = LLSkinningUtil::getMeshJointCount(skin);
LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar);
stop_glerror();
F32 mp[JOINT_COUNT * 9];
F32 mp[LL_MAX_JOINTS_PER_MESH_OBJECT*9];
F32 transp[JOINT_COUNT * 3];
F32 transp[LL_MAX_JOINTS_PER_MESH_OBJECT*3];
for (U32 i = 0; i < count; ++i)
{
F32* m = (F32*)mat[i].mMatrix;
F32* m = (F32*)mat[i].mMatrix[0].getF32ptr();
U32 idx = i * 9;

View File

@ -196,6 +196,12 @@ void LLFloaterBvhPreview::setAnimCallbacks()
getChild<LLUICtrl>("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseOut, this, _1));
}
std::map <std::string, std::string> LLFloaterBvhPreview::getJointAliases()
{
LLPointer<LLVOAvatar> av = (LLVOAvatar*)mAnimPreview->getDummyAvatar();
return av->getJointAliases();
}
//-----------------------------------------------------------------------------
// postBuild()
//-----------------------------------------------------------------------------
@ -279,6 +285,8 @@ BOOL LLFloaterBvhPreview::loadBVH()
getChildView("bad_animation_text")->setVisible(FALSE);
mAnimPreview = new LLPreviewAnimation(256, 256);
std::string exten = gDirUtilp->getExtension(mFilename);
if (exten == "bvh")
{
@ -305,8 +313,11 @@ BOOL LLFloaterBvhPreview::loadBVH()
file_buffer[file_size] = '\0';
LL_INFOS() << "Loading BVH file " << mFilename << LL_ENDL;
ELoadStatus load_status = E_ST_OK;
S32 line_number = 0;
loaderp = new LLBVHLoader(file_buffer, load_status, line_number);
S32 line_number = 0;
std::map<std::string, std::string> joint_alias_map = getJointAliases();
loaderp = new LLBVHLoader(file_buffer, load_status, line_number, joint_alias_map);
std::string status = getString(STATUS[load_status]);
if(load_status == E_ST_NO_XLT_FILE)
@ -330,8 +341,6 @@ BOOL LLFloaterBvhPreview::loadBVH()
mTransactionID.generate();
mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
mAnimPreview = new LLPreviewAnimation(256, 256);
// motion will be returned, but it will be in a load-pending state, as this is a new motion
// this motion will not request an asset transfer until next update, so we have a chance to
// load the keyframe data locally
@ -361,9 +370,12 @@ BOOL LLFloaterBvhPreview::loadBVH()
LLDataPackerBinaryBuffer dp(buffer, buffer_size);
// pass animation data through memory buffer
LL_INFOS("BVH") << "Serializing loaderp" << LL_ENDL;
loaderp->serialize(dp);
dp.reset();
LL_INFOS("BVH") << "Deserializing motionp" << LL_ENDL;
BOOL success = motionp && motionp->deserialize(dp);
LL_INFOS("BVH") << "Done" << LL_ENDL;
delete []buffer;

View File

@ -124,11 +124,13 @@ public:
// </FS:Sei>
private:
void setAnimCallbacks() ;
std::map <std::string, std::string> getJointAliases();
// <FS> Reload animation from disk
BOOL loadBVH();
void unloadMotion();
// </FS>
protected:
void draw();
void resetMotion();

View File

@ -42,7 +42,6 @@
#include "llcombobox.h"
#include "lldatapacker.h"
#include "lldrawable.h"
#include "lldrawpoolavatar.h"
#include "llrender.h"
#include "llface.h"
#include "lleconomy.h"
@ -54,6 +53,7 @@
#include "llmeshrepository.h"
#include "llnotificationsutil.h"
#include "llsdutil_math.h"
#include "llskinningutil.h"
#include "lltextbox.h"
#include "lltoolmgr.h"
#include "llui.h"
@ -90,9 +90,6 @@
// </AW: opensim-limits>
#include "nd/ndboolswitch.h" // <FS:ND/> To toggle LLRender::sGLCoreProfile
// <FS:Ansariel> Proper matrix array length for fitted mesh
#define JOINT_COUNT 52
#include "glod/glod.h"
#include <boost/algorithm/string.hpp>
@ -273,6 +270,7 @@ mCalculateBtn(NULL)
mLastMouseY = 0;
mStatusLock = new LLMutex(NULL);
mModelPreview = NULL;
mLODMode[LLModel::LOD_HIGH] = 0;
for (U32 i = 0; i < LLModel::LOD_HIGH; i++)
{
@ -1241,7 +1239,6 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
, mPhysicsSearchLOD( LLModel::LOD_PHYSICS )
, mResetJoints( false )
, mModelNoErrors( true )
, mRigParityWithScene( false )
, mLastJointUpdate( false )
{
mNeedsUpdate = TRUE;
@ -1779,6 +1776,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->mNumCollisionVolumes; 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();
@ -1821,6 +1832,9 @@ 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,
lod,
@ -1831,6 +1845,8 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
this,
mJointTransformMap,
mJointsFromNode,
joint_alias_map,
LLSkinningUtil::getMaxJointCount(),
gSavedSettings.getU32("ImporterModelLimit"));
if (force_disable_slm)
@ -3419,19 +3435,6 @@ void LLModelPreview::update()
}
}
//-----------------------------------------------------------------------------
// getTranslationForJointOffset()
//-----------------------------------------------------------------------------
LLVector3 LLModelPreview::getTranslationForJointOffset( std::string joint )
{
LLMatrix4 jointTransform;
if ( mJointTransformMap.find( joint ) != mJointTransformMap.end() )
{
jointTransform = mJointTransformMap[joint];
return jointTransform.getTranslation();
}
return LLVector3(0.0f,0.0f,0.0f);
}
//-----------------------------------------------------------------------------
// createPreviewAvatar
//-----------------------------------------------------------------------------
@ -3569,6 +3572,7 @@ void LLModelPreview::addEmptyFace( LLModel* pTarget )
pTarget->setVolumeFaceData( faceCnt+1, pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices() );
}
//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
@ -4062,20 +4066,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)
@ -4100,70 +4090,32 @@ BOOL LLModelPreview::render()
//quick 'n dirty software vertex skinning
//build matrix palette
// <FS:Ansariel> Proper matrix array length for fitted mesh
//LLMatrix4 mat[64];
//for (U32 j = 0; j < model->mSkinInfo.mJointNames.size(); ++j)
LLMatrix4 mat[JOINT_COUNT];
U32 count = llmin((U32) model->mSkinInfo.mJointNames.size(), (U32) JOINT_COUNT);
for (U32 j = 0; j < count; ++j)
// </FS:Ansariel>
{
LLJoint* joint = getPreviewAvatar()->getJoint(model->mSkinInfo.mJointNames[j]);
if (joint)
{
mat[j] = model->mSkinInfo.mInvBindMatrix[j];
mat[j] *= joint->getWorldMatrix();
}
}
LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
const LLMeshSkinInfo *skin = &model->mSkinInfo;
U32 count = LLSkinningUtil::getMeshJointCount(skin);
LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count,
skin, getPreviewAvatar());
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
U32 max_joints = LLSkinningUtil::getMaxJointCount();
for (U32 j = 0; j < buffer->getNumVerts(); ++j)
{
LLMatrix4 final_mat;
final_mat.mMatrix[0][0] = final_mat.mMatrix[1][1] = final_mat.mMatrix[2][2] = final_mat.mMatrix[3][3] = 0.f;
LLVector4 wght;
S32 idx[4];
F32 scale = 0.f;
for (U32 k = 0; k < 4; k++)
{
F32 w = weight[j].mV[k];
idx[k] = (S32) floorf(w);
wght.mV[k] = w - floorf(w);
scale += wght.mV[k];
}
wght *= 1.f/scale;
for (U32 k = 0; k < 4; k++)
{
// <FS:Ansariel> Proper matrix array length for fitted mesh
//F32* src = (F32*) mat[idx[k]].mMatrix;
S32 l = idx[k];
if( l >= JOINT_COUNT )
l = 0;
F32* src = (F32*) mat[l].mMatrix;
// </FS:Ansariel>
F32* dst = (F32*) final_mat.mMatrix;
F32 w = wght.mV[k];
for (U32 l = 0; l < 16; l++)
{
dst[l] += src[l]*w;
}
}
LLMatrix4a final_mat;
F32 *wptr = weight[j].mV;
LLSkinningUtil::getPerVertexSkinMatrix(wptr, mat, true, final_mat, max_joints);
//VECTORIZE THIS
LLVector3 v(face.mPositions[j].getF32ptr());
LLVector4a& v = face.mPositions[j];
v = v * model->mSkinInfo.mBindShapeMatrix;
v = v * final_mat;
LLVector4a t;
LLVector4a dst;
bind_shape_matrix.affineTransform(v, t);
final_mat.affineTransform(t, dst);
position[j] = v;
position[j][0] = dst[0];
position[j][1] = dst[1];
position[j][2] = dst[2];
}
// <FS:ND> FIRE-13465 Make sure there's a material set before dereferencing it
@ -4186,7 +4138,6 @@ BOOL LLModelPreview::render()
if (tex)
{
mTextureSet.insert(tex);
}
} else // <FS:ND> FIRE-13465 Make sure there's a material set before dereferencing it, if none, set buffer type and unbind texture.
@ -4210,6 +4161,22 @@ BOOL LLModelPreview::render()
}
}
}
if (joint_positions)
{
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
if (shader)
{
gDebugProgram.bind();
}
getPreviewAvatar()->renderCollisionVolumes();
getPreviewAvatar()->renderBones();
if (shader)
{
shader->bind();
}
}
}
}
@ -4346,7 +4313,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();

View File

@ -262,6 +262,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);
void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
@ -299,11 +300,7 @@ public:
void setLoadState( U32 state ) { mLoadState = state; }
U32 getLoadState() { return mLoadState; }
void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }
LLVector3 getTranslationForJointOffset( std::string joint );
static bool sIgnoreLoadedCallback;
protected:
@ -350,7 +347,6 @@ private:
bool mLoading;
U32 mLoadState;
bool mResetJoints;
bool mRigParityWithScene;
bool mModelNoErrors;
std::map<std::string, bool> mViewOption;
@ -408,7 +404,7 @@ private:
bool mLastJointUpdate;
JointSet mJointsFromNode;
JointNameSet mJointsFromNode;
JointTransformMap mJointTransformMap;
LLPointer<LLVOAvatar> mPreviewAvatar;

View File

@ -490,6 +490,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.HardwareSettings", boost::bind(&LLFloaterPreference::onOpenHardwareSettings, this));
mCommitCallbackRegistrar.add("Pref.HardwareDefaults", boost::bind(&LLFloaterPreference::setHardwareDefaults, this));
mCommitCallbackRegistrar.add("Pref.VertexShaderEnable", boost::bind(&LLFloaterPreference::onVertexShaderEnable, this));
mCommitCallbackRegistrar.add("Pref.EnhancedSkeletonEnable", boost::bind(&LLFloaterPreference::onEnhancedSkeletonEnable, this, _1));
mCommitCallbackRegistrar.add("Pref.LocalLightsEnable", boost::bind(&LLFloaterPreference::onLocalLightsEnable, this));
mCommitCallbackRegistrar.add("Pref.WindowedMod", boost::bind(&LLFloaterPreference::onCommitWindowedMode, this));
mCommitCallbackRegistrar.add("Pref.UpdateSliderText", boost::bind(&LLFloaterPreference::refreshUI,this));
@ -1153,6 +1154,16 @@ void LLFloaterPreference::onVertexShaderEnable()
refreshEnabledGraphics();
}
void LLFloaterPreference::onEnhancedSkeletonEnable(LLUICtrl *ctrl)
{
bool enabled = ctrl->getValue().asBoolean();
bool curr_enabled = gSavedSettings.getBOOL("IncludeEnhancedSkeleton");
if (enabled != curr_enabled)
{
gSavedSettings.setBOOL("IncludeEnhancedSkeleton",enabled);
}
}
// <FS:AO> toggle lighting detail availability in response to local light rendering, to avoid confusion
void LLFloaterPreference::onLocalLightsEnable()
{
@ -1871,7 +1882,11 @@ void LLFloaterPreference::refreshEnabledState()
// <FS:Ansariel> Radio group "ReflectionDetailRadio" doesn't exist as of 20/11/2012
//radio_reflection_detail->setEnabled(reflections);
LLCheckBoxCtrl* ctrl_enhanced_skel = getChild<LLCheckBoxCtrl>("AvatarEnhancedSkeleton");
bool enhanced_skel_enabled = gSavedSettings.getBOOL("IncludeEnhancedSkeleton");
ctrl_enhanced_skel->setValue(enhanced_skel_enabled);
// Avatar Mode
// Enable Avatar Shaders
LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
@ -2574,7 +2589,7 @@ void LLFloaterPreference::onClickAutoReplace()
void LLFloaterPreference::onClickSpellChecker()
{
LLFloaterReg::showInstance("prefs_spellchecker");
LLFloaterReg::showInstance("prefs_spellchecker");
}
void LLFloaterPreference::onClickActionChange()

View File

@ -138,6 +138,8 @@ protected:
void setHardwareDefaults();
// callback for when client turns on shaders
void onVertexShaderEnable();
// callback for when enhanced skeleton support checkbox toggled.
void onEnhancedSkeletonEnable(LLUICtrl *ctrl);
// <FS:AO> callback for local lights toggle
void onLocalLightsEnable();

View File

@ -37,6 +37,7 @@
#include "lllineeditor.h"
#include "lluictrlfactory.h"
#include "lluictrlfactory.h"
#include "lldatapacker.h"
extern LLAgent gAgent;

View File

@ -0,0 +1,354 @@
/**
* @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"
bool LLSkinningUtil::sIncludeEnhancedSkeleton = true;
namespace {
bool get_name_index(const std::string& name, std::vector<std::string>& names, U32& result)
{
std::vector<std::string>::const_iterator find_it =
std::find(names.begin(), names.end(), name);
if (find_it != names.end())
{
result = find_it - names.begin();
return true;
}
else
{
return false;
}
}
// Find a name table index that is also a valid joint on the
// avatar. Order of preference is: requested name, mPelvis, first
// valid match in names table.
U32 get_valid_joint_index(const std::string& name, LLVOAvatar *avatar, std::vector<std::string>& joint_names)
{
U32 result;
if (avatar->getJoint(name) && get_name_index(name,joint_names,result))
{
return result;
}
if (get_name_index("mPelvis",joint_names,result))
{
return result;
}
for (U32 j=0; j<joint_names.size(); j++)
{
if (avatar->getJoint(joint_names[j]))
{
return j;
}
}
// BENTO how to handle?
LL_ERRS() << "no valid joints in joint_names" << LL_ENDL;
return 0;
}
// Which joint will stand in for this joint?
U32 get_proxy_joint_index(U32 joint_index, LLVOAvatar *avatar, std::vector<std::string>& joint_names)
{
bool include_enhanced = LLSkinningUtil::sIncludeEnhancedSkeleton;
U32 j_proxy = get_valid_joint_index(joint_names[joint_index], avatar, joint_names);
LLJoint *joint = avatar->getJoint(joint_names[j_proxy]);
llassert(joint);
// Find the first ancestor that's not flagged as extended, or the
// last ancestor that's rigged in this mesh, whichever
// comes first.
while (1)
{
if (include_enhanced ||
joint->getSupport()==LLJoint::SUPPORT_BASE)
break;
LLJoint *parent = joint->getParent();
if (!parent)
break;
if (!get_name_index(parent->getName(), joint_names, j_proxy))
{
break;
}
joint = parent;
}
return j_proxy;
}
}
// static
void LLSkinningUtil::initClass()
{
sIncludeEnhancedSkeleton = gSavedSettings.getBOOL("IncludeEnhancedSkeleton");
}
// static
U32 LLSkinningUtil::getMaxJointCount()
{
U32 result = LL_MAX_JOINTS_PER_MESH_OBJECT;
if (!sIncludeEnhancedSkeleton)
{
// BENTO - currently the remap logic does not guarantee joint count <= 52;
// if one of the base ancestors is not rigged in a given mesh, an extended
// joint can still be included.
result = llmin(result,(U32)52);
}
return result;
}
// static
U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin)
{
return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size());
}
// static
// Destructively remap the joints in skin info based on what joints
// are known in the avatar, and which are currently supported. This
// will also populate mJointRemap[] in the skin, which can be used to
// make the corresponding changes to the integer part of vertex
// weights.
//
// This will throw away joint info for any joints that are not known
// in the avatar, or not currently flagged to support based on the
// debug setting for IncludeEnhancedSkeleton.
//
// BENTO maybe this really only makes sense for new leaf joints? New spine
// joints may need different logic.
// static
void LLSkinningUtil::remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin)
{
// skip if already done.
if (!skin->mJointRemap.empty())
{
return;
}
U32 max_joints = getMeshJointCount(skin);
// Compute the remap
std::vector<U32> j_proxy(skin->mJointNames.size());
for (U32 j = 0; j < skin->mJointNames.size(); ++j)
{
U32 j_rep = get_proxy_joint_index(j, avatar, skin->mJointNames);
j_proxy[j] = j_rep;
}
S32 top = 0;
std::vector<U32> j_remap(skin->mJointNames.size());
// Fill in j_remap for all joints that will be kept.
for (U32 j = 0; j < skin->mJointNames.size(); ++j)
{
if (j_proxy[j] == j)
{
// Joint will be included
j_remap[j] = top;
if (top < max_joints-1)
{
top++;
}
}
}
// Then use j_proxy to fill in j_remap for the joints that will be discarded
for (U32 j = 0; j < skin->mJointNames.size(); ++j)
{
if (j_proxy[j] != j)
{
j_remap[j] = j_remap[j_proxy[j]];
}
}
// Apply the remap to mJointNames, mInvBindMatrix, and mAlternateBindMatrix
std::vector<std::string> new_joint_names;
std::vector<LLMatrix4> new_inv_bind_matrix;
std::vector<LLMatrix4> new_alternate_bind_matrix;
for (U32 j = 0; j < skin->mJointNames.size(); ++j)
{
if (j_proxy[j] == j && new_joint_names.size() < max_joints)
{
new_joint_names.push_back(skin->mJointNames[j]);
new_inv_bind_matrix.push_back(skin->mInvBindMatrix[j]);
if (!skin->mAlternateBindMatrix.empty())
{
new_alternate_bind_matrix.push_back(skin->mAlternateBindMatrix[j]);
}
}
}
llassert(new_joint_names.size() <= max_joints);
for (U32 j = 0; j < skin->mJointNames.size(); ++j)
{
LL_DEBUGS("Avatar") << "Starting joint[" << j << "] = " << skin->mJointNames[j] << " j_remap " << j_remap[j] << " ==> " << new_joint_names[j_remap[j]] << LL_ENDL;
}
skin->mJointNames = new_joint_names;
skin->mInvBindMatrix = new_inv_bind_matrix;
skin->mAlternateBindMatrix = new_alternate_bind_matrix;
skin->mJointRemap = j_remap;
}
// static
void LLSkinningUtil::initSkinningMatrixPalette(
LLMatrix4* mat,
S32 count,
const LLMeshSkinInfo* skin,
LLVOAvatar *avatar)
{
// BENTO - switching to use Matrix4a and SSE might speed this up.
// Note that we are mostly passing Matrix4a's to this routine anyway, just dubiously casted.
for (U32 j = 0; j < count; ++j)
{
LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
mat[j] = skin->mInvBindMatrix[j];
if (joint)
{
mat[j] *= joint->getWorldMatrix();
}
else
{
// 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 remap.
LL_WARNS_ONCE("Avatar") << "Rigged to invalid joint name " << skin->mJointNames[j] << LL_ENDL;
}
}
}
// Transform the weights based on the remap info stored in skin. Note
// that this is destructive and non-idempotent, so we need to keep
// track of whether we've done it already. If the desired remapping
// changes, the viewer must be restarted.
//
// static
void LLSkinningUtil::remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)
{
llassert(skin->mJointRemap.size()>0); // Must call remapSkinInfoJoints() first, which this checks for.
const U32* remap = &skin->mJointRemap[0];
const S32 max_joints = skin->mJointNames.size();
for (U32 j=0; j<num_vertices; j++)
{
F32 *w = weights[j].getF32ptr();
for (U32 k=0; k<4; ++k)
{
S32 i = llfloor(w[k]);
F32 f = w[k]-i;
i = llclamp(i,0,max_joints-1);
w[k] = remap[i] + f;
}
}
}
// static
void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)
{
#ifndef LL_RELEASE_FOR_DOWNLOAD
const S32 max_joints = skin->mJointNames.size();
if (skin->mJointRemap.size()>0)
{
// Check the weights are consistent with the current remap.
for (U32 j=0; j<num_vertices; j++)
{
F32 *w = weights[j].getF32ptr();
for (U32 k=0; k<4; ++k)
{
S32 i = llfloor(w[k]);
llassert(i>=0);
llassert(i<max_joints);
}
}
}
#endif
}
// static
void LLSkinningUtil::getPerVertexSkinMatrix(
F32* weights,
LLMatrix4a* mat,
bool handle_bad_scale,
LLMatrix4a& final_mat,
U32 max_joints)
{
final_mat.clear();
S32 idx[4];
LLVector4 wght;
F32 scale = 0.f;
for (U32 k = 0; k < 4; k++)
{
F32 w = weights[k];
// BENTO potential optimizations
// - Do clamping in unpackVolumeFaces() (once instead of every time)
// - int vs floor: if we know w is
// >= 0.0, we can use int instead of floorf; the latter
// allegedly has a lot of overhead due to ieeefp error
// checking which we should not need.
idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)max_joints-1);
wght[k] = w - floorf(w);
scale += wght[k];
}
if (handle_bad_scale && scale <= 0.f)
{
wght = LLVector4(1.0f, 0.0f, 0.0f, 0.0f);
}
else
{
// This is enforced in unpackVolumeFaces()
llassert(scale>0.f);
wght *= 1.f/scale;
}
for (U32 k = 0; k < 4; k++)
{
F32 w = wght[k];
LLMatrix4a src;
src.setMul(mat[idx[k]], w);
final_mat.add(src);
}
}

View File

@ -0,0 +1,50 @@
/**
* @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 remapSkinInfoJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin);
static void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar);
static void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
static void remapSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints);
// This is initialized from gSavedSettings at startup and then left alone.
static bool sIncludeEnhancedSkeleton;
};
#endif

View File

@ -3219,6 +3219,11 @@ 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)
@ -3377,6 +3382,11 @@ public:
renderAvatarCollisionVolumes(avatar);
}
if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_JOINTS))
{
renderAvatarBones(avatar);
}
if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET))
{
renderAgentTarget(avatar);
@ -3667,6 +3677,7 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_TEXTURE_ANIM |
LLPipeline::RENDER_DEBUG_RAYCAST |
LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |
LLPipeline::RENDER_DEBUG_AVATAR_JOINTS |
LLPipeline::RENDER_DEBUG_AGENT_TARGET |
//LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA |

View File

@ -1757,7 +1757,7 @@ bool idle_startup()
LLPostProcess::initClass();
display_startup();
LLAvatarAppearance::initClass();
LLAvatarAppearance::initClass("avatar_lad.xml","avatar_skeleton.xml");
display_startup();
LLViewerObject::initVOClasses();

View File

@ -67,6 +67,7 @@
#include "llvowlsky.h"
#include "llrender.h"
#include "llnavigationbar.h"
#include "llnotificationsutil.h"
#include "llfloatertools.h"
#include "llpaneloutfitsinventory.h"
// <FS:Ansariel> [FS Login Panel]
@ -164,6 +165,12 @@ static bool handleTerrainDetailChanged(const LLSD& newvalue)
}
static bool handleDeferredDebugSettingChanged(const LLSD& newvalue)
{
LLNotificationsUtil::add("ChangeDeferredDebugSetting");
return true;
}
// <FS:Ansariel> Expose handleSetShaderChanged()
//static bool handleSetShaderChanged(const LLSD& newvalue)
bool handleSetShaderChanged(const LLSD& newvalue)
@ -1031,6 +1038,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&handleSpellCheckChanged));
gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged));
gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged));
gSavedSettings.getControl("IncludeEnhancedSkeleton")->getCommitSignal()->connect(boost::bind(&handleDeferredDebugSettingChanged, _2));
gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")->getSignal()->connect(boost::bind(&handleAvatarZOffsetChanged, _2)); // <FS:Zi> Moved Avatar Z offset from RLVa to here
// <FS:Zi> Is done inside XUI now, using visibility_control
// gSavedSettings.getControl("ShowNavbarFavoritesPanel")->getSignal()->connect(boost::bind(&toggle_show_favorites_panel, _2));

View File

@ -224,18 +224,18 @@ LLMenuGL* gDetachSubMenu = NULL;
LLMenuGL* gTakeOffClothes = NULL;
LLContextMenu* gAttachScreenPieMenu = NULL;
LLContextMenu* gAttachPieMenu = NULL;
LLContextMenu* gAttachBodyPartPieMenus[8];
LLContextMenu* gAttachBodyPartPieMenus[9];
LLContextMenu* gDetachPieMenu = NULL;
LLContextMenu* gDetachScreenPieMenu = NULL;
LLContextMenu* gDetachBodyPartPieMenus[8];
LLContextMenu* gDetachBodyPartPieMenus[9];
// ## Zi: Pie menu
PieMenu* gPieAttachScreenMenu = NULL;
PieMenu* gPieAttachMenu = NULL;
PieMenu* gPieAttachBodyPartMenus[8];
PieMenu* gPieAttachBodyPartMenus[9];
PieMenu* gPieDetachMenu = NULL;
PieMenu* gPieDetachScreenMenu = NULL;
PieMenu* gPieDetachBodyPartMenus[8];
PieMenu* gPieDetachBodyPartMenus[9];
// ## Zi: Pie menu
LLMenuItemCallGL* gAutorespondMenu = NULL;

View File

@ -213,8 +213,8 @@ extern LLContextMenu* gAttachScreenPieMenu;
extern LLContextMenu* gDetachScreenPieMenu;
extern LLContextMenu* gAttachPieMenu;
extern LLContextMenu* gDetachPieMenu;
extern LLContextMenu* gAttachBodyPartPieMenus[8];
extern LLContextMenu* gDetachBodyPartPieMenus[8];
extern LLContextMenu* gAttachBodyPartPieMenus[9];
extern LLContextMenu* gDetachBodyPartPieMenus[9];
// ## Zi: Pie Menu
// Pie menus in 3D scene
@ -231,8 +231,8 @@ extern PieMenu* gPieAttachScreenMenu;
extern PieMenu* gPieDetachScreenMenu;
extern PieMenu* gPieAttachMenu;
extern PieMenu* gPieDetachMenu;
extern PieMenu* gPieAttachBodyPartMenus[8];
extern PieMenu* gPieDetachBodyPartMenus[8];
extern PieMenu* gPieAttachBodyPartMenus[9];
extern PieMenu* gPieDetachBodyPartMenus[9];
// ## Zi: Pie Menu
extern LLMenuItemCallGL* gAutorespondMenu;

View File

@ -27,6 +27,8 @@
#include "llviewerprecompiledheaders.h"
#include <boost/lexical_cast.hpp>
#include "llfeaturemanager.h"
#include "llviewershadermgr.h"
@ -41,6 +43,8 @@
#include "llsky.h"
#include "llvosky.h"
#include "llrender.h"
#include "lljoint.h"
#include "llskinningutil.h"
#ifdef LL_RELEASE_FOR_DOWNLOAD
#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
@ -873,7 +877,9 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) );
boost::unordered_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++)
{

View File

@ -224,24 +224,6 @@ struct LLTextureMaskData
**
**/
//------------------------------------------------------------------------
// LLVOAvatarBoneInfo
// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton.
//------------------------------------------------------------------------
struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block<LLVOAvatarCollisionVolumeInfo>
{
LLVOAvatarCollisionVolumeInfo()
: name("name"),
pos("pos"),
rot("rot"),
scale("scale")
{}
Mandatory<std::string> name;
Mandatory<LLVector3> pos,
rot,
scale;
};
struct LLAppearanceMessageContents
{
@ -263,49 +245,6 @@ struct LLAppearanceMessageContents
bool mHoverOffsetWasSet;
};
struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint>
{
Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_A_BLOCK> > bone;
Alternative<LLVOAvatarCollisionVolumeInfo> collision_volume;
LLVOAvatarChildJoint()
: bone("bone"),
collision_volume("collision_volume")
{}
};
struct LLVOAvatarBoneInfo : public LLInitParam::Block<LLVOAvatarBoneInfo, LLVOAvatarCollisionVolumeInfo>
{
LLVOAvatarBoneInfo()
: pivot("pivot")
{}
Mandatory<LLVector3> pivot;
Multiple<LLVOAvatarChildJoint> children;
};
//------------------------------------------------------------------------
// LLVOAvatarSkeletonInfo
// Overall avatar skeleton
//------------------------------------------------------------------------
struct LLVOAvatarSkeletonInfo : public LLInitParam::Block<LLVOAvatarSkeletonInfo>
{
LLVOAvatarSkeletonInfo()
: skeleton_root(""),
num_bones("num_bones"),
num_collision_volumes("num_collision_volumes"),
version("version")
{}
Mandatory<std::string> version;
Mandatory<S32> num_bones,
num_collision_volumes;
Mandatory<LLVOAvatarChildJoint> skeleton_root;
};
//-----------------------------------------------------------------------------
// class LLBodyNoiseMotion
@ -1499,6 +1438,84 @@ void LLVOAvatar::renderCollisionVolumes()
addDebugText(ostr.str());
}
void LLVOAvatar::renderBones()
{
LLGLEnable blend(GL_BLEND);
std::ostringstream ostr;
std::ostringstream nullstr;
avatar_joint_list_t::iterator iter = mSkeleton.begin();
avatar_joint_list_t::iterator end = mSkeleton.end();
for (; iter != end; ++iter)
{
LLJoint* jointp = *iter;
if (!jointp)
{
continue;
}
ostr << jointp->getName() << ", ";
jointp->updateWorldMatrix();
LLJoint::SupportCategory sc = jointp->getSupport();
gGL.pushMatrix();
gGL.multMatrix( &jointp->getXform()->getWorldMatrix().mMatrix[0][0] );
gGL.begin(LLRender::LINES);
LLVector3 v[] =
{
LLVector3(0,0,0),
LLVector3(0,0,0),
};
v[1] = jointp->getEnd();
LLGLDepthTest normal_depth(GL_TRUE);
// Unoccluded bone portions
if (sc == LLJoint::SUPPORT_BASE)
{
gGL.diffuseColor3f( 1.0f, 0.5f, 0.5f );
}
else
{
gGL.diffuseColor3f( 0.5f, 1.0f, 0.5f );
}
gGL.vertex3fv(v[0].mV);
gGL.vertex3fv(v[1].mV);
LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
// Unoccluded bone portions
if (sc == LLJoint::SUPPORT_BASE)
{
gGL.diffuseColor3f( 1.0f, 0.0f, 0.0f );
}
else
{
gGL.diffuseColor3f( 0.0f, 1.0f, 0.0f );
}
gGL.vertex3fv(v[0].mV);
gGL.vertex3fv(v[1].mV);
gGL.end();
gGL.popMatrix();
}
mDebugText.clear();
addDebugText(ostr.str());
addDebugText(nullstr.str());
}
void LLVOAvatar::renderJoints()
{
std::ostringstream ostr;
@ -1608,7 +1625,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
for (S32 i = 0; i < mNumCollisionVolumes; ++i)
{
mCollisionVolumes[i].updateWorldMatrix();
glh::matrix4f mat((F32*) mCollisionVolumes[i].getXform()->getWorldMatrix().mMatrix);
glh::matrix4f inverse = mat.inverse();
glh::matrix4f norm_mat = inverse.transpose();
@ -5746,7 +5763,10 @@ void LLVOAvatar::clearAttachmentPosOverrides()
for (; iter != end; ++iter)
{
LLJoint* pJoint = (*iter);
pJoint->clearAttachmentPosOverrides();
if (pJoint)
{
pJoint->clearAttachmentPosOverrides();
}
}
}
@ -6028,8 +6048,14 @@ BOOL LLVOAvatar::loadSkeletonNode ()
LLViewerJointAttachment* attachment = new LLViewerJointAttachment();
attachment->setName(info->mName);
LLJoint *parentJoint = getJoint(info->mJointName);
if (!parentJoint)
LLJoint *parent_joint = getJoint(info->mJointName);
if (!parent_joint)
{
// If the intended location for attachment point is unavailable, stick it in a default location.
LL_INFOS() << "attachment pt " << info->mName << " using mPelvis as default parent" << LL_ENDL;
parent_joint = getJoint("mPelvis");
}
if (!parent_joint)
{
LL_WARNS() << "No parent joint by name " << info->mJointName << " found for attachment point " << info->mName << LL_ENDL;
delete attachment;
@ -6084,7 +6110,7 @@ BOOL LLVOAvatar::loadSkeletonNode ()
mAttachmentPoints[attachmentID] = attachment;
// now add attachment joint
parentJoint->addChild(attachment);
parent_joint->addChild(attachment);
}
}

View File

@ -68,13 +68,11 @@ class LLVoiceVisualizer;
class LLHUDNameTag;
class LLHUDEffectSpiral;
class LLTexGlobalColor;
struct LLVOAvatarBoneInfo;
struct LLVOAvatarChildJoint;
//class LLViewerJoint;
struct LLAppearanceMessageContents;
struct LLVOAvatarSkeletonInfo;
class LLViewerJointMesh;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLVOAvatar
//
@ -419,6 +417,7 @@ public:
F32 getLastSkinTime() { return mLastSkinTime; }
U32 renderTransparent(BOOL first_pass);
void renderCollisionVolumes();
void renderBones();
void renderJoints();
static void deleteCachedImages(bool clearAll=true);
static void destroyGL();

View File

@ -277,7 +277,6 @@ void LLVOAvatarSelf::initInstance()
{
mDebugBakedTextureTimes[i][0] = -1.0f;
mDebugBakedTextureTimes[i][1] = -1.0f;
mInitialBakeIDs[i] = LLUUID::null;
}
// [RLVa:KB] - Checked: 2010-12-12 (RLVa-1.2.2c) | Added: RLVa-1.2.2c
@ -445,6 +444,10 @@ BOOL LLVOAvatarSelf::buildMenus()
params.name(params.label);
gAttachBodyPartPieMenus[7] = LLUICtrlFactory::create<LLContextMenu> (params);
params.label(LLTrans::getString("BodyPartsEnhancedSkeleton"));
params.name(params.label);
gAttachBodyPartPieMenus[8] = LLUICtrlFactory::create<LLContextMenu>(params);
gDetachBodyPartPieMenus[0] = NULL;
params.label(LLTrans::getString("BodyPartsRightArm"));
@ -473,7 +476,11 @@ BOOL LLVOAvatarSelf::buildMenus()
params.name(params.label);
gDetachBodyPartPieMenus[7] = LLUICtrlFactory::create<LLContextMenu> (params);
// ## Zi: Pie menu
params.label(LLTrans::getString("BodyPartsEnhancedSkeleton"));
params.name(params.label);
gDetachBodyPartPieMenus[8] = LLUICtrlFactory::create<LLContextMenu>(params);
// <FS:Zi> Pie menu
//-------------------------------------------------------------------------
// build the attach and detach pie menus
//-------------------------------------------------------------------------
@ -507,6 +514,10 @@ BOOL LLVOAvatarSelf::buildMenus()
pieParams.name(pieParams.label);
gPieAttachBodyPartMenus[7] = LLUICtrlFactory::create<PieMenu> (pieParams);
pieParams.label(LLTrans::getString("BodyPartsEnhancedSkeleton"));
pieParams.name(pieParams.label);
gPieAttachBodyPartMenus[8] = LLUICtrlFactory::create<PieMenu>(pieParams);
gPieDetachBodyPartMenus[0] = NULL;
pieParams.label(LLTrans::getString("BodyPartsRightArm"));
@ -534,14 +545,24 @@ BOOL LLVOAvatarSelf::buildMenus()
pieParams.label(LLTrans::getString("BodyPartsRightLeg"));
pieParams.name(pieParams.label);
gPieDetachBodyPartMenus[7] = LLUICtrlFactory::create<PieMenu> (pieParams);
// ## Zi: Pie menu
for (S32 i = 0; i < 8; i++)
pieParams.label(LLTrans::getString("BodyPartsEnhancedSkeleton"));
pieParams.name(pieParams.label);
gPieDetachBodyPartMenus[8] = LLUICtrlFactory::create<PieMenu>(pieParams);
// </FS:Zi> Pie menu
for (S32 i = 0; i < 9; i++)
{
if (gAttachBodyPartPieMenus[i])
{
gAttachPieMenu->appendContextSubMenu( gAttachBodyPartPieMenus[i] );
gPieAttachMenu->appendContextSubMenu( gPieAttachBodyPartMenus[i] ); // ## Zi: Pie menu
// <FS:Zi> Pie menu
// Ansa: Exclude Bento additions for now until we figured out a way where to put them...
if (i < 8)
{
gPieAttachMenu->appendContextSubMenu(gPieAttachBodyPartMenus[i]);
}
// </FS:Zi>
}
else
{
@ -576,16 +597,20 @@ BOOL LLVOAvatarSelf::buildMenus()
gAttachPieMenu->addChild(item);
// ## Zi: Pie menu
slice_params.name =(slice_params.label );
slice_params.on_click.function_name = "Object.AttachToAvatar";
slice_params.on_click.parameter = iter->first;
slice_params.on_enable.function_name = "Object.EnableWear";
slice_params.on_enable.parameter = iter->first;
PieSlice* slice = LLUICtrlFactory::create<PieSlice>(slice_params);
// <FS:Zi> Pie menu
// Ansa: Exclude Bento additions for now until we figured out a way where to put them...
if (i < 8)
{
slice_params.name = (slice_params.label);
slice_params.on_click.function_name = "Object.AttachToAvatar";
slice_params.on_click.parameter = iter->first;
slice_params.on_enable.function_name = "Object.EnableWear";
slice_params.on_enable.parameter = iter->first;
PieSlice* slice = LLUICtrlFactory::create<PieSlice>(slice_params);
gPieAttachMenu->addChild(slice);
// ## Zi: Pie menu
gPieAttachMenu->addChild(slice);
}
// </FS:Zi> Pie menu
break;
@ -596,7 +621,13 @@ BOOL LLVOAvatarSelf::buildMenus()
if (gDetachBodyPartPieMenus[i])
{
gDetachPieMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] );
gPieDetachMenu->appendContextSubMenu( gPieDetachBodyPartMenus[i] ); // ## Zi: Pie menu
// <FS:Zi> Pie menu
// Ansa: Exclude Bento additions for now until we figured out a way where to put them...
if (i < 8)
{
gPieDetachMenu->appendContextSubMenu(gPieDetachBodyPartMenus[i]);
}
// </FS:Zi> Pie menu
}
else
{
@ -608,17 +639,17 @@ BOOL LLVOAvatarSelf::buildMenus()
if (attachment->getGroup() == i)
{
LLMenuItemCallGL::Params item_params;
PieSlice::Params slice_params; // ## Zi: Pie menu
PieSlice::Params slice_params; // <FS:Zi> Pie menu
std::string sub_piemenu_name = attachment->getName();
if (LLTrans::getString(sub_piemenu_name) != "")
{
item_params.label = LLTrans::getString(sub_piemenu_name);
slice_params.label = LLTrans::getString(sub_piemenu_name); // ## Zi: Pie menu
slice_params.label = LLTrans::getString(sub_piemenu_name); // <FS:Zi> Pie menu
}
else
{
item_params.label = sub_piemenu_name;
slice_params.label = sub_piemenu_name; // ## Zi: Pie menu
slice_params.label = sub_piemenu_name; // <FS:Zi> Pie menu
}
item_params.name =(item_params.label );
item_params.on_click.function_name = "Attachment.DetachFromPoint";
@ -629,16 +660,20 @@ BOOL LLVOAvatarSelf::buildMenus()
gDetachPieMenu->addChild(item);
// ## Zi: Pie menu
slice_params.name =(slice_params.label );
slice_params.on_click.function_name = "Attachment.DetachFromPoint";
slice_params.on_click.parameter = iter->first;
slice_params.on_enable.function_name = "Attachment.PointFilled";
slice_params.on_enable.parameter = iter->first;
PieSlice* slice = LLUICtrlFactory::create<PieSlice>(slice_params);
// <FS:Zi> Pie menu
// Ansa: Exclude Bento additions for now until we figured out a way where to put them...
if (i < 8)
{
slice_params.name = (slice_params.label);
slice_params.on_click.function_name = "Attachment.DetachFromPoint";
slice_params.on_click.parameter = iter->first;
slice_params.on_enable.function_name = "Attachment.PointFilled";
slice_params.on_enable.parameter = iter->first;
PieSlice* slice = LLUICtrlFactory::create<PieSlice>(slice_params);
gPieDetachMenu->addChild(slice);
// ## Zi: Pie menu
gPieDetachMenu->addChild(slice);
}
// </FS:Zi> Pie menu
break;
}
@ -652,7 +687,7 @@ BOOL LLVOAvatarSelf::buildMenus()
++iter)
{
LLViewerJointAttachment* attachment = iter->second;
if (attachment->getGroup() == 8)
if (attachment->getGroup() == 9)
{
LLMenuItemCallGL::Params item_params;
PieSlice::Params slice_params; // ## Zi: Pie menu
@ -660,12 +695,12 @@ BOOL LLVOAvatarSelf::buildMenus()
if (LLTrans::getString(sub_piemenu_name) != "")
{
item_params.label = LLTrans::getString(sub_piemenu_name);
slice_params.label = LLTrans::getString(sub_piemenu_name); // ## Zi: Pie menu
slice_params.label = LLTrans::getString(sub_piemenu_name); // <FS:Zi> Pie menu
}
else
{
item_params.label = sub_piemenu_name;
slice_params.label = sub_piemenu_name; // ## Zi: Pie menu
slice_params.label = sub_piemenu_name; // <FS:Zi> Pie menu
}
item_params.name =(item_params.label );
item_params.on_click.function_name = "Object.AttachToAvatar";
@ -683,7 +718,7 @@ BOOL LLVOAvatarSelf::buildMenus()
item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
gDetachScreenPieMenu->addChild(item);
// ## Zi: Pie menu
// <FS:Zi> Pie menu
slice_params.name =(slice_params.label );
slice_params.on_click.function_name = "Object.AttachToAvatar";
slice_params.on_click.parameter = iter->first;
@ -698,7 +733,7 @@ BOOL LLVOAvatarSelf::buildMenus()
slice_params.on_enable.parameter = iter->first;
slice = LLUICtrlFactory::create<PieSlice>(slice_params);
gPieDetachScreenMenu->addChild(slice);
// ## Zi: Pie menu
// </FS:Zi> Pie menu
}
}
@ -760,7 +795,7 @@ BOOL LLVOAvatarSelf::buildMenus()
}
}
for (S32 group = 0; group < 8; group++)
for (S32 group = 0; group < 9; group++)
{
// skip over groups that don't have sub menus
if (!gAttachBodyPartPieMenus[group] || !gDetachBodyPartPieMenus[group])
@ -768,7 +803,8 @@ BOOL LLVOAvatarSelf::buildMenus()
continue;
}
std::multimap<S32, S32> attachment_pie_menu_map; // ## Zi: Pie menu
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();
@ -818,25 +854,29 @@ BOOL LLVOAvatarSelf::buildMenus()
item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
gDetachBodyPartPieMenus[group]->addChild(item);
// ## Zi: Pie menu
PieSlice::Params slice_params;
slice_params.name = attachment->getName();
slice_params.label = LLTrans::getString(attachment->getName());
slice_params.on_click.function_name = "Object.AttachToAvatar";
slice_params.on_click.parameter = attach_index;
slice_params.on_enable.function_name = "Object.EnableWear";
slice_params.on_enable.parameter = attach_index;
// <FS:Zi> Pie menu
// Ansa: Exclude Bento additions for now until we figured out a way where to put them...
if (group < 8)
{
PieSlice::Params slice_params;
slice_params.name = attachment->getName();
slice_params.label = LLTrans::getString(attachment->getName());
slice_params.on_click.function_name = "Object.AttachToAvatar";
slice_params.on_click.parameter = attach_index;
slice_params.on_enable.function_name = "Object.EnableWear";
slice_params.on_enable.parameter = attach_index;
PieSlice* slice = LLUICtrlFactory::create<PieSlice>(slice_params);
gPieAttachBodyPartMenus[group]->addChild(slice);
PieSlice* slice = LLUICtrlFactory::create<PieSlice>(slice_params);
gPieAttachBodyPartMenus[group]->addChild(slice);
slice_params.on_click.function_name = "Attachment.DetachFromPoint";
slice_params.on_click.parameter = attach_index;
slice_params.on_enable.function_name = "Attachment.PointFilled";
slice_params.on_enable.parameter = attach_index;
slice = LLUICtrlFactory::create<PieSlice>(slice_params);
gPieDetachBodyPartMenus[group]->addChild(slice);
// ## Zi: Pie menu
slice_params.on_click.function_name = "Attachment.DetachFromPoint";
slice_params.on_click.parameter = attach_index;
slice_params.on_enable.function_name = "Attachment.PointFilled";
slice_params.on_enable.parameter = attach_index;
slice = LLUICtrlFactory::create<PieSlice>(slice_params);
gPieDetachBodyPartMenus[group]->addChild(slice);
}
// </FS:Zi> Pie menu
}
}
}
@ -3551,18 +3591,18 @@ void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid
LLViewerTexLayerSet *layerset = getTexLayerSet(i);
if ( mBakedTextureDatas[i].mTextureIndex == te && layerset)
{
if (mInitialBakeIDs[i] != LLUUID::null)
{
if (mInitialBakeIDs[i] == uuid)
{
LL_INFOS() << "baked texture correctly loaded at login! " << i << LL_ENDL;
}
else
{
LL_WARNS() << "baked texture does not match id loaded at login!" << i << LL_ENDL;
}
mInitialBakeIDs[i] = LLUUID::null;
}
//if (mInitialBakeIDs[i] != LLUUID::null)
//{
// if (mInitialBakeIDs[i] == uuid)
// {
// LL_INFOS() << "baked texture correctly loaded at login! " << i << LL_ENDL;
// }
// else
// {
// LL_WARNS() << "baked texture does not match id loaded at login!" << i << LL_ENDL;
// }
// mInitialBakeIDs[i] = LLUUID::null;
//}
layerset->cancelUpload();
}
}

View File

@ -116,17 +116,6 @@ private:
//BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight);
BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE);
/** Initialization
** **
*******************************************************************************/
private:
LLUUID mInitialBakeIDs[6];
//bool mInitialBakesLoaded;
/********************************************************************************
** **
** STATE

View File

@ -54,6 +54,7 @@
#include "llspatialpartition.h"
#include "llhudmanager.h"
#include "llflexibleobject.h"
#include "llskinningutil.h"
#include "llsky.h"
#include "lltexturefetch.h"
#include "llvector4a.h"
@ -4277,27 +4278,11 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
}
//build matrix palette
static const size_t kMaxJoints = 52;
static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT;
LLMatrix4a mp[kMaxJoints];
LLMatrix4* mat = (LLMatrix4*) mp;
U32 maxJoints = llmin(skin->mJointNames.size(), kMaxJoints);
for (U32 j = 0; j < maxJoints; ++j)
{
LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
if (!joint)
{
// Fall back to a point inside the avatar if mesh is
// rigged to an unknown joint.
joint = avatar->getJoint("mPelvis");
}
if (joint)
{
mat[j] = skin->mInvBindMatrix[j];
mat[j] *= joint->getWorldMatrix();
}
}
LLMatrix4a mat[kMaxJoints];
U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin);
LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar);
for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
{
@ -4309,6 +4294,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
if ( weight )
{
LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin);
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
@ -4318,59 +4304,11 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
{
LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED);
U32 max_joints = LLSkinningUtil::getMaxJointCount();
for (U32 j = 0; j < dst_face.mNumVertices; ++j)
{
LLMatrix4a final_mat;
final_mat.clear();
// <FS:ND> Avoid the 8 floorf by using SSE2.
// Using _mm_cvttps_epi32 (truncate) under the assumption that the index can never be negative.
// S32 idx[4];
//
// LLVector4 wght;
//
// F32 scale = 0.f;
// for (U32 k = 0; k < 4; k++)
// {
// F32 w = weight[j][k];
//
// idx[k] = (S32) floorf(w);
// wght[k] = w - floorf(w);
// scale += wght[k];
// }
//// This is enforced in unpackVolumeFaces()
//llassert(scale>0.f);
//wght *= 1.f / scale;
LL_ALIGN_16( S32 idx[4] );
LL_ALIGN_16( F32 wght[4] );
__m128i _mIdx = _mm_cvttps_epi32( weight[j] );
__m128 _mWeight = _mm_sub_ps( weight[j], _mm_cvtepi32_ps( _mIdx ) );
_mm_store_si128( (__m128i*)idx, _mIdx );
__m128 _mScale = _mm_add_ps( _mWeight, _mm_movehl_ps( _mWeight, _mWeight ));
_mScale = _mm_add_ss( _mScale, _mm_shuffle_ps( _mScale, _mScale, 1) );
_mScale = _mm_shuffle_ps( _mScale, _mScale, 0 );
_mWeight = _mm_div_ps( _mWeight, _mScale );
_mm_store_ps( wght, _mWeight );
// </FS:ND>
for (U32 k = 0; k < 4; k++)
{
F32 w = wght[k];
LLMatrix4a src;
// Insure ref'd bone is in our clamped array of mats
// clamp idx to maxJoints to avoid reading garbage off stack in release
S32 index = llclamp((S32)idx[k],(S32)0,(S32)kMaxJoints-1);
src.setMul(mp[index], w);
final_mat.add(src);
}
LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints);
LLVector4a& v = vol_face.mPositions[j];
LLVector4a t;

View File

@ -4610,6 +4610,16 @@
function="Advanced.ToggleInfoDisplay"
parameter="collision skeleton" />
</menu_item_check>
<menu_item_check
label="Show Bones"
name="Show Bones">
<menu_item_check.on_check
function="Advanced.CheckInfoDisplay"
parameter="joints" />
<menu_item_check.on_click
function="Advanced.ToggleInfoDisplay"
parameter="joints" />
</menu_item_check>
<menu_item_check
label="Display Agent Target"
name="Display Agent Target">

View File

@ -1454,6 +1454,13 @@ Sound cache will be moved after restarting [APP_NAME].
Port settings take effect after restarting [APP_NAME].
</notification>
<notification
icon="alertmodal.tga"
name="ChangeDeferredDebugSetting"
type="alertmodal">
This debug setting change will take effect after you restart [APP_NAME].
</notification>
<notification
icon="alertmodal.tga"
name="ChangeSkin"
@ -11462,6 +11469,14 @@ Not enough script resources available to attach object!
Cannot attach object because it is already being removed.
</notification>
<notification
icon="alertmodal.tga"
name="IllegalAttachment"
type="notify">
<tag>fail</tag>
The attachment has requested a nonexistent point on the avatar. It has been attached to the chest instead.
</notification>
<notification
icon="alertmodal.tga"
name="CantDropItemTrialUser"

View File

@ -768,6 +768,19 @@
<check_box.commit_callback
function="Pref.VertexShaderEnable" />
</check_box>
<check_box
control_name="RenderAvatarEnhancedSkeleton"
height="16"
initial_value="true"
label="Enhanced skeleton"
layout="topleft"
left_delta="0"
name="AvatarEnhancedSkeleton"
top_pad="1"
width="256">
<check_box.commit_callback
function="Pref.EnhancedSkeletonEnable" />
</check_box>
<check_box
control_name="RenderAvatarCloth"
height="16"
@ -787,7 +800,7 @@
left="407"
left_delta="200"
name="TerrainDetailText"
top_pad="-67"
top_pad="-84"
width="155">
Terrain detail:
</text>

View File

@ -700,6 +700,7 @@ Please try logging in again in a minute.</string>
<string name="BodyPartsLeftLeg">Left Leg</string>
<string name="BodyPartsTorso">Torso</string>
<string name="BodyPartsRightLeg">Right Leg</string>
<string name="BodyPartsEnhancedSkeleton">Enhanced Skeleton</string>
<!-- slider -->
<string name="GraphicsQualityLow">Low</string>
@ -925,8 +926,21 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f
<string name="Stomach">Stomach</string>
<string name="Left Pec">Left Pec</string>
<string name="Right Pec">Right Pec</string>
<string name="Neck">Neck</string>
<string name="Avatar Center">Avatar Center</string>
<string name="Neck">Neck</string>
<string name="Avatar Center">Avatar Center</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="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>