summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llappearance/CMakeLists.txt10
-rw-r--r--indra/llappearance/llavatarappearance.cpp1393
-rw-r--r--indra/llappearance/llavatarappearance.h207
-rw-r--r--indra/llappearance/llavatarjoint.cpp261
-rw-r--r--indra/llappearance/llavatarjoint.h127
-rwxr-xr-xindra/llappearance/llavatarjointmesh.cpp359
-rwxr-xr-xindra/llappearance/llavatarjointmesh.h140
-rw-r--r--indra/llappearance/llpolymesh.cpp (renamed from indra/newview/llpolymesh.cpp)257
-rw-r--r--indra/llappearance/llpolymesh.h (renamed from indra/newview/llpolymesh.h)83
-rw-r--r--indra/llappearance/llpolymorph.cpp748
-rw-r--r--indra/llappearance/llpolymorph.h182
-rw-r--r--indra/llappearance/llpolyskeletaldistortion.cpp293
-rw-r--r--indra/llappearance/llpolyskeletaldistortion.h119
-rwxr-xr-xindra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/llagentcamera.cpp10
-rw-r--r--indra/newview/llfloaterbvhpreview.cpp4
-rw-r--r--indra/newview/llfloaterimagepreview.cpp8
-rw-r--r--indra/newview/llhudeffectlookat.cpp2
-rw-r--r--indra/newview/llpolymorph.h6
-rw-r--r--indra/newview/llspatialpartition.cpp2
-rwxr-xr-xindra/newview/llstartup.cpp3
-rw-r--r--indra/newview/llviewerjoint.cpp121
-rw-r--r--indra/newview/llviewerjoint.h20
-rwxr-xr-xindra/newview/llviewerjointmesh.cpp283
-rwxr-xr-xindra/newview/llviewerjointmesh.h86
-rwxr-xr-xindra/newview/llviewerwindow.cpp2
-rwxr-xr-xindra/newview/llvoavatar.cpp1548
-rwxr-xr-xindra/newview/llvoavatar.h172
-rwxr-xr-xindra/newview/llvoavatarself.cpp6
-rwxr-xr-xindra/newview/llvoavatarself.h2
30 files changed, 4045 insertions, 2413 deletions
diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt
index 41da898457..c5a855a505 100644
--- a/indra/llappearance/CMakeLists.txt
+++ b/indra/llappearance/CMakeLists.txt
@@ -42,9 +42,14 @@ include_directories(
set(llappearance_SOURCE_FILES
llavatarappearance.cpp
+ llavatarjoint.cpp
+ llavatarjointmesh.cpp
lldriverparam.cpp
llinventoryicon.cpp
lllocaltextureobject.cpp
+ llpolyskeletaldistortion.cpp
+ llpolymesh.cpp
+ llpolymorph.cpp
lltexglobalcolor.cpp
lltexlayer.cpp
lltexlayerparams.cpp
@@ -60,10 +65,15 @@ set(llappearance_HEADER_FILES
CMakeLists.txt
llavatarappearance.h
+ llavatarjoint.h
+ llavatarjointmesh.h
lldriverparam.h
llinventoryicon.h
lljointpickname.h
lllocaltextureobject.h
+ llpolyskeletaldistortion.h
+ llpolymesh.h
+ llpolymorph.h
lltexglobalcolor.h
lltexlayer.h
lltexlayerparams.h
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 2c03f8ba02..406e6153e0 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -29,19 +29,128 @@
#include "llavatarappearance.h"
#include "llavatarappearancedefines.h"
+#include "llavatarjointmesh.h"
#include "imageids.h"
+#include "lldir.h"
#include "lldeleteutils.h"
+#include "llpolymorph.h"
+#include "llpolymesh.h"
+#include "llpolyskeletaldistortion.h"
#include "lltexglobalcolor.h"
#include "llwearabledata.h"
+//-----------------------------------------------------------------------------
+// Constants
+//-----------------------------------------------------------------------------
+
+const std::string AVATAR_DEFAULT_CHAR = "avatar";
const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0);
+/*********************************************************************************
+ ** **
+ ** Begin private LLAvatarAppearance Support classes
+ **
+ **/
+
+//------------------------------------------------------------------------
+// LLAvatarBoneInfo
+// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton.
+//------------------------------------------------------------------------
+class LLAvatarBoneInfo
+{
+ friend class LLAvatarAppearance;
+ friend class LLAvatarSkeletonInfo;
+public:
+ LLAvatarBoneInfo() : mIsJoint(FALSE) {}
+ ~LLAvatarBoneInfo()
+ {
+ std::for_each(mChildList.begin(), mChildList.end(), DeletePointer());
+ }
+ BOOL parseXml(LLXmlTreeNode* node);
+
+private:
+ std::string mName;
+ BOOL mIsJoint;
+ LLVector3 mPos;
+ LLVector3 mRot;
+ LLVector3 mScale;
+ LLVector3 mPivot;
+ typedef std::vector<LLAvatarBoneInfo*> child_list_t;
+ child_list_t mChildList;
+};
+
+//------------------------------------------------------------------------
+// LLAvatarSkeletonInfo
+// Overall avatar skeleton
+//------------------------------------------------------------------------
+class LLAvatarSkeletonInfo
+{
+ friend class LLAvatarAppearance;
+public:
+ LLAvatarSkeletonInfo() :
+ mNumBones(0), mNumCollisionVolumes(0) {}
+ ~LLAvatarSkeletonInfo()
+ {
+ std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer());
+ }
+ BOOL parseXml(LLXmlTreeNode* node);
+ S32 getNumBones() const { return mNumBones; }
+ S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; }
+
+private:
+ S32 mNumBones;
+ S32 mNumCollisionVolumes;
+ typedef std::vector<LLAvatarBoneInfo*> bone_info_list_t;
+ bone_info_list_t mBoneInfoList;
+};
+
+//-----------------------------------------------------------------------------
+// LLAvatarXmlInfo
+//-----------------------------------------------------------------------------
+
+LLAvatarAppearance::LLAvatarXmlInfo::LLAvatarXmlInfo()
+ : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0)
+{
+}
+
+LLAvatarAppearance::LLAvatarXmlInfo::~LLAvatarXmlInfo()
+{
+ std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer());
+ std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer());
+ std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer());
+ deleteAndClear(mTexSkinColorInfo);
+ deleteAndClear(mTexHairColorInfo);
+ deleteAndClear(mTexEyeColorInfo);
+ std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer());
+ std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer());
+ std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer());
+}
+
+
+/**
+ **
+ ** End LLAvatarAppearance Support classes
+ ** **
+ *********************************************************************************/
+
+//-----------------------------------------------------------------------------
+// Static Data
+//-----------------------------------------------------------------------------
+LLXmlTree LLAvatarAppearance::sXMLTree;
+LLXmlTree LLAvatarAppearance::sSkeletonXMLTree;
+LLAvatarSkeletonInfo* LLAvatarAppearance::sAvatarSkeletonInfo = NULL;
+LLAvatarAppearance::LLAvatarXmlInfo* LLAvatarAppearance::sAvatarXmlInfo = NULL;
+
+
LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
LLCharacter(),
mIsDummy(FALSE),
mTexSkinColor( NULL ),
mTexHairColor( NULL ),
mTexEyeColor( NULL ),
+ mPelvisToFoot(0.f),
+ mHeadOffset(),
+
mWearableData(wearable_data)
{
llassert(mWearableData);
@@ -55,6 +164,17 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
mBakedTextureDatas[i].mMaskTexName = 0;
mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i);
}
+
+ mIsBuilt = FALSE;
+
+ mNumJoints = 0;
+ mSkeleton = NULL;
+
+ mNumCollisionVolumes = 0;
+ mCollisionVolumes = NULL;
+
+ mRoot = new LLAvatarJoint();
+
}
// virtual
@@ -76,10 +196,793 @@ LLAvatarAppearance::~LLAvatarAppearance()
delete masked_morph;
}
}
+
+ mRoot->removeAllChildren();
+ mJointMap.clear();
+
+ deleteAndClearArray(mSkeleton);
+ deleteAndClearArray(mCollisionVolumes);
+
+ mNumJoints = 0;
+
+ deleteAndClear(mTexSkinColor);
+ deleteAndClear(mTexHairColor);
+ deleteAndClear(mTexEyeColor);
+
+ std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer());
+ mMeshes.clear();
+
+ for (std::vector<LLAvatarJoint*>::iterator jointIter = mMeshLOD.begin();
+ jointIter != mMeshLOD.end();
+ ++jointIter)
+ {
+ LLAvatarJoint* joint = (LLAvatarJoint *) *jointIter;
+ std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer());
+ joint->mMeshParts.clear();
+ }
+ std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer());
+ mMeshLOD.clear();
+}
+
+//static
+void LLAvatarAppearance::initClass()
+{
+ std::string xmlFile;
+
+ xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml";
+ BOOL success = sXMLTree.parseFile( xmlFile, FALSE );
+ if (!success)
+ {
+ llerrs << "Problem reading avatar configuration file:" << xmlFile << llendl;
+ }
+
+ // now sanity check xml file
+ LLXmlTreeNode* root = sXMLTree.getRoot();
+ if (!root)
+ {
+ llerrs << "No root node found in avatar configuration file: " << xmlFile << llendl;
+ return;
+ }
+
+ //-------------------------------------------------------------------------
+ // <linden_avatar version="1.0"> (root)
+ //-------------------------------------------------------------------------
+ if( !root->hasName( "linden_avatar" ) )
+ {
+ llerrs << "Invalid avatar file header: " << xmlFile << llendl;
+ }
+
+ std::string version;
+ static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version");
+ if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") )
+ {
+ llerrs << "Invalid avatar file version: " << version << " in file: " << xmlFile << llendl;
+ }
+
+ S32 wearable_def_version = 1;
+ static LLStdStringHandle wearable_definition_version_string = LLXmlTree::addAttributeString("wearable_definition_version");
+ root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version );
+ LLWearable::setCurrentDefinitionVersion( wearable_def_version );
+
+ std::string mesh_file_name;
+
+ LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" );
+ if (!skeleton_node)
+ {
+ llerrs << "No skeleton in avatar configuration file: " << xmlFile << llendl;
+ 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))
+ {
+ llerrs << "No file name in skeleton node in avatar config file: " << xmlFile << llendl;
+ }
+
+ std::string skeleton_path;
+ skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name);
+ if (!parseSkeletonFile(skeleton_path))
+ {
+ llerrs << "Error parsing skeleton file: " << skeleton_path << llendl;
+ }
+
+ // Process XML data
+
+ // avatar_skeleton.xml
+ if (sAvatarSkeletonInfo)
+ { //this can happen if a login attempt failed
+ delete sAvatarSkeletonInfo;
+ }
+ sAvatarSkeletonInfo = new LLAvatarSkeletonInfo;
+ if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot()))
+ {
+ llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl;
+ }
+ // parse avatar_lad.xml
+ if (sAvatarXmlInfo)
+ { //this can happen if a login attempt failed
+ deleteAndClear(sAvatarXmlInfo);
+ }
+ sAvatarXmlInfo = new LLAvatarXmlInfo;
+ if (!sAvatarXmlInfo->parseXmlSkeletonNode(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlMeshNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlColorNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlLayerNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlDriverNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
+ if (!sAvatarXmlInfo->parseXmlMorphNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
}
using namespace LLAvatarAppearanceDefines;
+//------------------------------------------------------------------------
+// The viewer can only suggest a good size for the agent,
+// the simulator will keep it inside a reasonable range.
+void LLAvatarAppearance::computeBodySize()
+{
+ LLVector3 pelvis_scale = mPelvisp->getScale();
+
+ // some of the joints have not been cached
+ LLVector3 skull = mSkullp->getPosition();
+ LLVector3 skull_scale = mSkullp->getScale();
+
+ LLVector3 neck = mNeckp->getPosition();
+ LLVector3 neck_scale = mNeckp->getScale();
+
+ LLVector3 chest = mChestp->getPosition();
+ LLVector3 chest_scale = mChestp->getScale();
+
+ // the rest of the joints have been cached
+ LLVector3 head = mHeadp->getPosition();
+ LLVector3 head_scale = mHeadp->getScale();
+
+ LLVector3 torso = mTorsop->getPosition();
+ LLVector3 torso_scale = mTorsop->getScale();
+
+ LLVector3 hip = mHipLeftp->getPosition();
+ LLVector3 hip_scale = mHipLeftp->getScale();
+
+ LLVector3 knee = mKneeLeftp->getPosition();
+ LLVector3 knee_scale = mKneeLeftp->getScale();
+
+ LLVector3 ankle = mAnkleLeftp->getPosition();
+ LLVector3 ankle_scale = mAnkleLeftp->getScale();
+
+ LLVector3 foot = mFootLeftp->getPosition();
+
+ mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] -
+ knee.mV[VZ] * hip_scale.mV[VZ] -
+ ankle.mV[VZ] * knee_scale.mV[VZ] -
+ foot.mV[VZ] * ankle_scale.mV[VZ];
+
+ LLVector3 new_body_size;
+ new_body_size.mV[VZ] = mPelvisToFoot +
+ // the sqrt(2) correction below is an approximate
+ // correction to get to the top of the head
+ F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) +
+ head.mV[VZ] * neck_scale.mV[VZ] +
+ neck.mV[VZ] * chest_scale.mV[VZ] +
+ chest.mV[VZ] * torso_scale.mV[VZ] +
+ torso.mV[VZ] * pelvis_scale.mV[VZ];
+
+ // TODO -- measure the real depth and width
+ new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH;
+ new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH;
+
+ if (new_body_size != mBodySize)
+ {
+ mBodySize = new_body_size;
+ bodySizeChanged();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// parseSkeletonFile()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename)
+{
+ LLMemType mt(LLMemType::MTYPE_AVATAR);
+
+ //-------------------------------------------------------------------------
+ // parse the file
+ //-------------------------------------------------------------------------
+ BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE );
+
+ if (!parsesuccess)
+ {
+ llerrs << "Can't parse skeleton file: " << filename << llendl;
+ return FALSE;
+ }
+
+ // now sanity check xml file
+ LLXmlTreeNode* root = sSkeletonXMLTree.getRoot();
+ if (!root)
+ {
+ llerrs << "No root node found in avatar skeleton file: " << filename << llendl;
+ return FALSE;
+ }
+
+ if( !root->hasName( "linden_skeleton" ) )
+ {
+ llerrs << "Invalid avatar skeleton file header: " << filename << llendl;
+ return FALSE;
+ }
+
+ std::string version;
+ static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version");
+ if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") )
+ {
+ llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// setupBone()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &volume_num, S32 &joint_num)
+{
+ LLMemType mt(LLMemType::MTYPE_AVATAR);
+
+ LLJoint* joint = NULL;
+
+ if (info->mIsJoint)
+ {
+ joint = getCharacterJoint(joint_num);
+ if (!joint)
+ {
+ llwarns << "Too many bones" << llendl;
+ return FALSE;
+ }
+ joint->setName( info->mName );
+ }
+ else // collision volume
+ {
+ if (volume_num >= (S32)mNumCollisionVolumes)
+ {
+ llwarns << "Too many bones" << llendl;
+ return FALSE;
+ }
+ joint = (&mCollisionVolumes[volume_num]);
+ joint->setName( info->mName );
+ }
+
+ // add to parent
+ if (parent)
+ {
+ parent->addChild( joint );
+ }
+
+ joint->setPosition(info->mPos);
+ joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY],
+ info->mRot.mV[VZ], LLQuaternion::XYZ));
+ joint->setScale(info->mScale);
+
+ joint->setDefaultFromCurrentXform();
+
+ if (info->mIsJoint)
+ {
+ joint->setSkinOffset( info->mPivot );
+ joint_num++;
+ }
+ else // collision volume
+ {
+ volume_num++;
+ }
+
+ // setup children
+ LLAvatarBoneInfo::child_list_t::const_iterator iter;
+ for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter)
+ {
+ LLAvatarBoneInfo *child_info = *iter;
+ if (!setupBone(child_info, joint, volume_num, joint_num))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// buildSkeleton()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info)
+{
+ LLMemType mt(LLMemType::MTYPE_AVATAR);
+
+ //-------------------------------------------------------------------------
+ // allocate joints
+ //-------------------------------------------------------------------------
+ if (!allocateCharacterJoints(info->mNumBones))
+ {
+ llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl;
+ return FALSE;
+ }
+
+ //-------------------------------------------------------------------------
+ // allocate volumes
+ //-------------------------------------------------------------------------
+ if (info->mNumCollisionVolumes)
+ {
+ if (!allocateCollisionVolumes(info->mNumCollisionVolumes))
+ {
+ llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl;
+ return FALSE;
+ }
+ }
+
+ S32 current_joint_num = 0;
+ S32 current_volume_num = 0;
+ 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))
+ {
+ llerrs << "Error parsing bone in skeleton file" << llendl;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarAppearance::buildCharacter()
+// Deferred initialization and rebuild of the avatar.
+//-----------------------------------------------------------------------------
+void LLAvatarAppearance::buildCharacter()
+{
+ LLMemType mt(LLMemType::MTYPE_AVATAR);
+
+ //-------------------------------------------------------------------------
+ // remove all references to our existing skeleton
+ // so we can rebuild it
+ //-------------------------------------------------------------------------
+ flushAllMotions();
+
+ //-------------------------------------------------------------------------
+ // remove all of mRoot's children
+ //-------------------------------------------------------------------------
+ mRoot->removeAllChildren();
+ mJointMap.clear();
+ mIsBuilt = FALSE;
+
+ //-------------------------------------------------------------------------
+ // (re)load our skeleton and meshes
+ //-------------------------------------------------------------------------
+ LLTimer timer;
+
+ BOOL status = loadAvatar();
+ stop_glerror();
+
+// gPrintMessagesThisFrame = TRUE;
+ lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl;
+
+ if (!status)
+ {
+ if (isSelf())
+ {
+ llerrs << "Unable to load user's avatar" << llendl;
+ }
+ else
+ {
+ llwarns << "Unable to load other's avatar" << llendl;
+ }
+ return;
+ }
+
+ //-------------------------------------------------------------------------
+ // initialize "well known" joint pointers
+ //-------------------------------------------------------------------------
+ mPelvisp = mRoot->findJoint("mPelvis");
+ mTorsop = mRoot->findJoint("mTorso");
+ mChestp = mRoot->findJoint("mChest");
+ mNeckp = mRoot->findJoint("mNeck");
+ mHeadp = mRoot->findJoint("mHead");
+ mSkullp = mRoot->findJoint("mSkull");
+ mHipLeftp = mRoot->findJoint("mHipLeft");
+ mHipRightp = mRoot->findJoint("mHipRight");
+ mKneeLeftp = mRoot->findJoint("mKneeLeft");
+ mKneeRightp = mRoot->findJoint("mKneeRight");
+ mAnkleLeftp = mRoot->findJoint("mAnkleLeft");
+ mAnkleRightp = mRoot->findJoint("mAnkleRight");
+ mFootLeftp = mRoot->findJoint("mFootLeft");
+ mFootRightp = mRoot->findJoint("mFootRight");
+ mWristLeftp = mRoot->findJoint("mWristLeft");
+ mWristRightp = mRoot->findJoint("mWristRight");
+ mEyeLeftp = mRoot->findJoint("mEyeLeft");
+ mEyeRightp = mRoot->findJoint("mEyeRight");
+
+ //-------------------------------------------------------------------------
+ // Make sure "well known" pointers exist
+ //-------------------------------------------------------------------------
+ if (!(mPelvisp &&
+ mTorsop &&
+ mChestp &&
+ mNeckp &&
+ mHeadp &&
+ mSkullp &&
+ mHipLeftp &&
+ mHipRightp &&
+ mKneeLeftp &&
+ mKneeRightp &&
+ mAnkleLeftp &&
+ mAnkleRightp &&
+ mFootLeftp &&
+ mFootRightp &&
+ mWristLeftp &&
+ mWristRightp &&
+ mEyeLeftp &&
+ mEyeRightp))
+ {
+ llerrs << "Failed to create avatar." << llendl;
+ return;
+ }
+
+ //-------------------------------------------------------------------------
+ // initialize the pelvis
+ //-------------------------------------------------------------------------
+ mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) );
+
+ mIsBuilt = TRUE;
+ stop_glerror();
+
+}
+
+BOOL LLAvatarAppearance::loadAvatar()
+{
+// LLFastTimer t(FTM_LOAD_AVATAR);
+
+ // avatar_skeleton.xml
+ if( !buildSkeleton(sAvatarSkeletonInfo) )
+ {
+ llwarns << "avatar file: buildSkeleton() failed" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml : <skeleton>
+ if( !loadSkeletonNode() )
+ {
+ llwarns << "avatar file: loadNodeSkeleton() failed" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml : <mesh>
+ if( !loadMeshNodes() )
+ {
+ llwarns << "avatar file: loadNodeMesh() failed" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml : <global_color>
+ if( sAvatarXmlInfo->mTexSkinColorInfo )
+ {
+ mTexSkinColor = new LLTexGlobalColor( this );
+ if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) )
+ {
+ llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else
+ {
+ llwarns << "<global_color> name=\"skin_color\" not found" << llendl;
+ return FALSE;
+ }
+ if( sAvatarXmlInfo->mTexHairColorInfo )
+ {
+ mTexHairColor = new LLTexGlobalColor( this );
+ if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) )
+ {
+ llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else
+ {
+ llwarns << "<global_color> name=\"hair_color\" not found" << llendl;
+ return FALSE;
+ }
+ if( sAvatarXmlInfo->mTexEyeColorInfo )
+ {
+ mTexEyeColor = new LLTexGlobalColor( this );
+ if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) )
+ {
+ llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else
+ {
+ llwarns << "<global_color> name=\"eye_color\" not found" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml : <layer_set>
+ if (sAvatarXmlInfo->mLayerInfoList.empty())
+ {
+ llwarns << "avatar file: missing <layer_set> node" << llendl;
+ return FALSE;
+ }
+
+ if (sAvatarXmlInfo->mMorphMaskInfoList.empty())
+ {
+ llwarns << "avatar file: missing <morph_masks> node" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml : <morph_masks>
+ for (LLAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin();
+ iter != sAvatarXmlInfo->mMorphMaskInfoList.end();
+ ++iter)
+ {
+ LLAvatarXmlInfo::LLAvatarMorphInfo *info = *iter;
+
+ EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion);
+ if (baked != BAKED_NUM_INDICES)
+ {
+ LLVisualParam* morph_param;
+ const std::string *name = &info->mName;
+ morph_param = getVisualParam(name->c_str());
+ if (morph_param)
+ {
+ BOOL invert = info->mInvert;
+ addMaskedMorph(baked, morph_param, invert, info->mLayer);
+ }
+ }
+
+ }
+
+ loadLayersets();
+
+ // avatar_lad.xml : <driver_parameters>
+ for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin();
+ iter != sAvatarXmlInfo->mDriverInfoList.end();
+ ++iter)
+ {
+ LLDriverParamInfo *info = *iter;
+ LLDriverParam* driver_param = new LLDriverParam( this );
+ if (driver_param->setInfo(info))
+ {
+ addVisualParam( driver_param );
+ LLVisualParam*(LLAvatarAppearance::*avatar_function)(S32)const = &LLAvatarAppearance::getVisualParam;
+ if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLAvatarAppearance*)this,_1 ), false))
+ {
+ llwarns << "could not link driven params for avatar " << getID().asString() << " param id: " << driver_param->getID() << llendl;
+ continue;
+ }
+ }
+ else
+ {
+ delete driver_param;
+ llwarns << "avatar file: driver_param->parseData() failed" << llendl;
+ return FALSE;
+ }
+ }
+
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// loadSkeletonNode(): loads <skeleton> node from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::loadSkeletonNode ()
+{
+ mRoot->addChild( &mSkeleton[0] );
+
+ mRoot->addChild(mMeshLOD[MESH_ID_HEAD]);
+ mRoot->addChild(mMeshLOD[MESH_ID_EYELASH]);
+ mRoot->addChild(mMeshLOD[MESH_ID_UPPER_BODY]);
+ mRoot->addChild(mMeshLOD[MESH_ID_LOWER_BODY]);
+ mRoot->addChild(mMeshLOD[MESH_ID_SKIRT]);
+ mRoot->addChild(mMeshLOD[MESH_ID_HEAD]);
+
+ LLAvatarJoint *skull = (LLAvatarJoint*)mRoot->findJoint("mSkull");
+ if (skull)
+ {
+ skull->addChild(mMeshLOD[MESH_ID_HAIR] );
+ }
+
+ LLAvatarJoint *eyeL = (LLAvatarJoint*)mRoot->findJoint("mEyeLeft");
+ if (eyeL)
+ {
+ eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] );
+ }
+
+ LLAvatarJoint *eyeR = (LLAvatarJoint*)mRoot->findJoint("mEyeRight");
+ if (eyeR)
+ {
+ eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] );
+ }
+
+ // SKELETAL DISTORTIONS
+ {
+ LLAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter;
+ for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin();
+ iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end();
+ ++iter)
+ {
+ LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)*iter;
+ LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this);
+ if (!param->setInfo(info))
+ {
+ delete param;
+ return FALSE;
+ }
+ else
+ {
+ addVisualParam(param);
+ }
+ }
+ }
+
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// loadMeshNodes(): loads <mesh> nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::loadMeshNodes()
+{
+ for (LLAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin();
+ meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end();
+ ++meshinfo_iter)
+ {
+ const LLAvatarXmlInfo::LLAvatarMeshInfo *info = *meshinfo_iter;
+ const std::string &type = info->mType;
+ S32 lod = info->mLOD;
+
+ LLAvatarJointMesh* mesh = NULL;
+ U8 mesh_id = 0;
+ BOOL found_mesh_id = FALSE;
+
+ /* if (type == "hairMesh")
+ switch(lod)
+ case 0:
+ mesh = &mHairMesh0; */
+ for (LLAvatarAppearanceDictionary::Meshes::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin();
+ mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end();
+ ++mesh_iter)
+ {
+ const EMeshIndex mesh_index = mesh_iter->first;
+ const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_iter->second;
+ if (type.compare(mesh_dict->mName) == 0)
+ {
+ mesh_id = mesh_index;
+ found_mesh_id = TRUE;
+ break;
+ }
+ }
+
+ if (found_mesh_id)
+ {
+ if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size())
+ {
+ mesh = mMeshLOD[mesh_id]->mMeshParts[lod];
+ }
+ else
+ {
+ llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
+ return FALSE;
+ }
+ }
+ else
+ {
+ llwarns << "Ignoring unrecognized mesh type: " << type << llendl;
+ return FALSE;
+ }
+
+ // llinfos << "Parsing mesh data for " << type << "..." << llendl;
+
+ // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings.
+ // Do not touch!!!
+ mesh->setColor( 1.0f, 1.0f, 1.0f, 1.0f );
+
+ LLPolyMesh *poly_mesh = NULL;
+
+ if (!info->mReferenceMeshName.empty())
+ {
+ polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName);
+ if (polymesh_iter != mMeshes.end())
+ {
+ poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second);
+ poly_mesh->setAvatar(this);
+ }
+ else
+ {
+ // This should never happen
+ LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL;
+ }
+ }
+ else
+ {
+ poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName);
+ poly_mesh->setAvatar(this);
+ }
+
+ if( !poly_mesh )
+ {
+ llwarns << "Failed to load mesh of type " << type << llendl;
+ return FALSE;
+ }
+
+ // Multimap insert
+ mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh));
+
+ mesh->setMesh( poly_mesh );
+ mesh->setLOD( info->mMinPixelArea );
+
+ for (LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin();
+ xmlinfo_iter != info->mPolyMorphTargetInfoList.end();
+ ++xmlinfo_iter)
+ {
+ const LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter);
+ LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh());
+ if (!param->setInfo((LLPolyMorphTargetInfo*)info_pair->first))
+ {
+ delete param;
+ return FALSE;
+ }
+ else
+ {
+ if (info_pair->second)
+ {
+ addSharedVisualParam(param);
+ }
+ else
+ {
+ addVisualParam(param);
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// loadLayerSets()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::loadLayersets()
+{
+ BOOL success = TRUE;
+ for (LLAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin();
+ layerset_iter != sAvatarXmlInfo->mLayerInfoList.end();
+ ++layerset_iter)
+ {
+ // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
+ LLTexLayerSetInfo *layerset_info = *layerset_iter;
+ layerset_info->createVisualParams(this);
+ }
+ return success;
+}
+
+
+
// virtual
BOOL LLAvatarAppearance::isValid() const
{
@@ -273,4 +1176,494 @@ BOOL LLAvatarAppearance::isWearingWearableType(LLWearableType::EType type) const
return FALSE;
}
+//-----------------------------------------------------------------------------
+// allocateCollisionVolumes()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num )
+{
+ deleteAndClearArray(mCollisionVolumes);
+ mNumCollisionVolumes = 0;
+
+ mCollisionVolumes = new LLAvatarJointCollisionVolume[num];
+ if (!mCollisionVolumes)
+ {
+ return FALSE;
+ }
+
+ mNumCollisionVolumes = num;
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarBoneInfo::parseXml()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
+{
+ if (node->hasName("bone"))
+ {
+ mIsJoint = TRUE;
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (!node->getFastAttributeString(name_string, mName))
+ {
+ llwarns << "Bone without name" << llendl;
+ return FALSE;
+ }
+ }
+ else if (node->hasName("collision_volume"))
+ {
+ mIsJoint = FALSE;
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (!node->getFastAttributeString(name_string, mName))
+ {
+ mName = "Collision Volume";
+ }
+ }
+ else
+ {
+ llwarns << "Invalid node " << node->getName() << llendl;
+ return FALSE;
+ }
+
+ static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos");
+ if (!node->getFastAttributeVector3(pos_string, mPos))
+ {
+ llwarns << "Bone without position" << llendl;
+ return FALSE;
+ }
+
+ static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot");
+ if (!node->getFastAttributeVector3(rot_string, mRot))
+ {
+ llwarns << "Bone without rotation" << llendl;
+ return FALSE;
+ }
+
+ static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
+ if (!node->getFastAttributeVector3(scale_string, mScale))
+ {
+ llwarns << "Bone without scale" << llendl;
+ return FALSE;
+ }
+
+ if (mIsJoint)
+ {
+ static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot");
+ if (!node->getFastAttributeVector3(pivot_string, mPivot))
+ {
+ llwarns << "Bone without pivot" << llendl;
+ return FALSE;
+ }
+ }
+
+ // parse children
+ LLXmlTreeNode* child;
+ for( child = node->getFirstChild(); child; child = node->getNextChild() )
+ {
+ LLAvatarBoneInfo *child_info = new LLAvatarBoneInfo;
+ if (!child_info->parseXml(child))
+ {
+ delete child_info;
+ return FALSE;
+ }
+ mChildList.push_back(child_info);
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarSkeletonInfo::parseXml()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
+{
+ static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones");
+ if (!node->getFastAttributeS32(num_bones_string, mNumBones))
+ {
+ llwarns << "Couldn't find number of bones." << llendl;
+ return FALSE;
+ }
+
+ static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes");
+ node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes);
+
+ LLXmlTreeNode* child;
+ for( child = node->getFirstChild(); child; child = node->getNextChild() )
+ {
+ LLAvatarBoneInfo *info = new LLAvatarBoneInfo;
+ if (!info->parseXml(child))
+ {
+ delete info;
+ llwarns << "Error parsing bone in skeleton file" << llendl;
+ return FALSE;
+ }
+ mBoneInfoList.push_back(info);
+ }
+ return TRUE;
+}
+
+
+//-----------------------------------------------------------------------------
+// parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
+{
+ LLXmlTreeNode* node = root->getChildByName( "skeleton" );
+ if( !node )
+ {
+ llwarns << "avatar file: missing <skeleton>" << llendl;
+ return FALSE;
+ }
+
+ LLXmlTreeNode* child;
+
+ // SKELETON DISTORTIONS
+ for (child = node->getChildByName( "param" );
+ child;
+ child = node->getNextNamedChild())
+ {
+ if (!child->getChildByName("param_skeleton"))
+ {
+ if (child->getChildByName("param_morph"))
+ {
+ llwarns << "Can't specify morph param in skeleton definition." << llendl;
+ }
+ else
+ {
+ llwarns << "Unknown param type." << llendl;
+ }
+ continue;
+ }
+
+ LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo;
+ if (!info->parseXml(child))
+ {
+ delete info;
+ return FALSE;
+ }
+
+ mSkeletalDistortionInfoList.push_back(info);
+ }
+
+ // ATTACHMENT POINTS
+ for (child = node->getChildByName( "attachment_point" );
+ child;
+ child = node->getNextNamedChild())
+ {
+ LLAvatarAttachmentInfo* info = new LLAvatarAttachmentInfo();
+
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (!child->getFastAttributeString(name_string, info->mName))
+ {
+ llwarns << "No name supplied for attachment point." << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint");
+ if (!child->getFastAttributeString(joint_string, info->mJointName))
+ {
+ llwarns << "No bone declared in attachment point " << info->mName << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position");
+ if (child->getFastAttributeVector3(position_string, info->mPosition))
+ {
+ info->mHasPosition = TRUE;
+ }
+
+ static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation");
+ if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler))
+ {
+ info->mHasRotation = TRUE;
+ }
+ static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group");
+ if (child->getFastAttributeS32(group_string, info->mGroup))
+ {
+ if (info->mGroup == -1)
+ info->mGroup = -1111; // -1 = none parsed, < -1 = bad value
+ }
+
+ static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id");
+ if (!child->getFastAttributeS32(id_string, info->mAttachmentID))
+ {
+ llwarns << "No id supplied for attachment point " << info->mName << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice");
+ child->getFastAttributeS32(slot_string, info->mPieMenuSlice);
+
+ static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person");
+ child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson);
+
+ static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud");
+ child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment);
+
+ mAttachmentInfoList.push_back(info);
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlMeshNodes(): parses <mesh> nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
+{
+ for (LLXmlTreeNode* node = root->getChildByName( "mesh" );
+ node;
+ node = root->getNextNamedChild())
+ {
+ LLAvatarMeshInfo *info = new LLAvatarMeshInfo;
+
+ // attribute: type
+ static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type");
+ if( !node->getFastAttributeString( type_string, info->mType ) )
+ {
+ llwarns << "Avatar file: <mesh> is missing type attribute. Ignoring element. " << llendl;
+ delete info;
+ return FALSE; // Ignore this element
+ }
+
+ static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod");
+ if (!node->getFastAttributeS32( lod_string, info->mLOD ))
+ {
+ llwarns << "Avatar file: <mesh> is missing lod attribute. Ignoring element. " << llendl;
+ delete info;
+ return FALSE; // Ignore this element
+ }
+
+ static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name");
+ if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) )
+ {
+ llwarns << "Avatar file: <mesh> is missing file_name attribute. Ignoring: " << info->mType << llendl;
+ delete info;
+ return FALSE; // Ignore this element
+ }
+
+ static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference");
+ node->getFastAttributeString( reference_string, info->mReferenceMeshName );
+
+ // attribute: min_pixel_area
+ static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area");
+ static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width");
+ if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea ))
+ {
+ F32 min_pixel_area = 0.1f;
+ if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area ))
+ {
+ // this is square root of pixel area (sensible to use linear space in defining lods)
+ min_pixel_area = min_pixel_area * min_pixel_area;
+ }
+ info->mMinPixelArea = min_pixel_area;
+ }
+
+ // Parse visual params for this node only if we haven't already
+ for (LLXmlTreeNode* child = node->getChildByName( "param" );
+ child;
+ child = node->getNextNamedChild())
+ {
+ if (!child->getChildByName("param_morph"))
+ {
+ if (child->getChildByName("param_skeleton"))
+ {
+ llwarns << "Can't specify skeleton param in a mesh definition." << llendl;
+ }
+ else
+ {
+ llwarns << "Unknown param type." << llendl;
+ }
+ continue;
+ }
+
+ LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo();
+ if (!morphinfo->parseXml(child))
+ {
+ delete morphinfo;
+ delete info;
+ return -1;
+ }
+ BOOL shared = FALSE;
+ static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared");
+ child->getFastAttributeBOOL(shared_string, shared);
+
+ info->mPolyMorphTargetInfoList.push_back(LLAvatarMeshInfo::morph_info_pair_t(morphinfo, shared));
+ }
+
+ mMeshInfoList.push_back(info);
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlColorNodes(): parses <global_color> nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
+{
+ for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" );
+ color_node;
+ color_node = root->getNextNamedChild())
+ {
+ std::string global_color_name;
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (color_node->getFastAttributeString( name_string, global_color_name ) )
+ {
+ if( global_color_name == "skin_color" )
+ {
+ if (mTexSkinColorInfo)
+ {
+ llwarns << "avatar file: multiple instances of skin_color" << llendl;
+ return FALSE;
+ }
+ mTexSkinColorInfo = new LLTexGlobalColorInfo;
+ if( !mTexSkinColorInfo->parseXml( color_node ) )
+ {
+ deleteAndClear(mTexSkinColorInfo);
+ llwarns << "avatar file: mTexSkinColor->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else if( global_color_name == "hair_color" )
+ {
+ if (mTexHairColorInfo)
+ {
+ llwarns << "avatar file: multiple instances of hair_color" << llendl;
+ return FALSE;
+ }
+ mTexHairColorInfo = new LLTexGlobalColorInfo;
+ if( !mTexHairColorInfo->parseXml( color_node ) )
+ {
+ deleteAndClear(mTexHairColorInfo);
+ llwarns << "avatar file: mTexHairColor->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ else if( global_color_name == "eye_color" )
+ {
+ if (mTexEyeColorInfo)
+ {
+ llwarns << "avatar file: multiple instances of eye_color" << llendl;
+ return FALSE;
+ }
+ mTexEyeColorInfo = new LLTexGlobalColorInfo;
+ if( !mTexEyeColorInfo->parseXml( color_node ) )
+ {
+ llwarns << "avatar file: mTexEyeColor->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlLayerNodes(): parses <layer_set> nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
+{
+ for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" );
+ layer_node;
+ layer_node = root->getNextNamedChild())
+ {
+ LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo();
+ if( layer_info->parseXml( layer_node ) )
+ {
+ mLayerInfoList.push_back(layer_info);
+ }
+ else
+ {
+ delete layer_info;
+ llwarns << "avatar file: layer_set->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
+{
+ LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" );
+ if( driver )
+ {
+ for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" );
+ grand_child;
+ grand_child = driver->getNextNamedChild())
+ {
+ if( grand_child->getChildByName( "param_driver" ) )
+ {
+ LLDriverParamInfo* driver_info = new LLDriverParamInfo();
+ if( driver_info->parseXml( grand_child ) )
+ {
+ mDriverInfoList.push_back(driver_info);
+ }
+ else
+ {
+ delete driver_info;
+ llwarns << "avatar file: driver_param->parseXml() failed" << llendl;
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root)
+{
+ LLXmlTreeNode* masks = root->getChildByName( "morph_masks" );
+ if( !masks )
+ {
+ return FALSE;
+ }
+
+ for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" );
+ grand_child;
+ grand_child = masks->getNextNamedChild())
+ {
+ LLAvatarMorphInfo* info = new LLAvatarMorphInfo();
+
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name");
+ if (!grand_child->getFastAttributeString(name_string, info->mName))
+ {
+ llwarns << "No name supplied for morph mask." << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region");
+ if (!grand_child->getFastAttributeString(region_string, info->mRegion))
+ {
+ llwarns << "No region supplied for morph mask." << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer");
+ if (!grand_child->getFastAttributeString(layer_string, info->mLayer))
+ {
+ llwarns << "No layer supplied for morph mask." << llendl;
+ delete info;
+ continue;
+ }
+
+ // optional parameter. don't throw a warning if not present.
+ static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert");
+ grand_child->getFastAttributeBOOL(invert_string, info->mInvert);
+
+ mMorphMaskInfoList.push_back(info);
+ }
+
+ return TRUE;
+}
+
+
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index b2ab6b069f..38a54d904d 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -30,11 +30,17 @@
#include "llcharacter.h"
//#include "llframetimer.h"
#include "llavatarappearancedefines.h"
-#include "lljoint.h"
+#include "llavatarjoint.h"
+#include "lldriverparam.h"
+#include "lltexlayer.h"
+#include "llviewervisualparam.h"
+#include "llxmltree.h"
class LLTexLayerSet;
class LLTexGlobalColor;
class LLWearableData;
+class LLAvatarBoneInfo;
+class LLAvatarSkeletonInfo;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLAvatarAppearance
@@ -45,6 +51,9 @@ class LLAvatarAppearance : public LLCharacter
{
LOG_CLASS(LLAvatarAppearance);
+protected:
+ struct LLAvatarXmlInfo;
+
/********************************************************************************
** **
** INITIALIZATION
@@ -57,6 +66,12 @@ public:
LLAvatarAppearance(LLWearableData* wearable_data);
virtual ~LLAvatarAppearance();
+ static void initClass(); // initializes static members
+ virtual BOOL loadSkeletonNode();
+ virtual BOOL loadMeshNodes();
+ virtual BOOL loadLayersets();
+
+
/** Initialization
** **
*******************************************************************************/
@@ -69,16 +84,94 @@ public:
virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent
virtual BOOL isValid() const;
virtual BOOL isUsingBakedTextures() const = 0;
+
+ bool isBuilt() const { return mIsBuilt; }
+
/** State
** **
*******************************************************************************/
+/********************************************************************************
+ ** **
+ ** SKELETON
+ **/
+
+public:
+ F32 getPelvisToFoot() const { return mPelvisToFoot; }
+
+ LLVector3 mHeadOffset; // current head position
+ LLAvatarJoint *mRoot;
+
+ typedef std::map<std::string, LLJoint*> joint_map_t;
+ joint_map_t mJointMap;
+
+protected:
+ static BOOL parseSkeletonFile(const std::string& filename);
+ virtual void buildCharacter();
+ virtual BOOL loadAvatar();
+ virtual void bodySizeChanged() = 0;
+ void computeBodySize();
+
+ BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
+ BOOL buildSkeleton(const LLAvatarSkeletonInfo *info);
+protected:
+ BOOL mIsBuilt; // state of deferred character building
+ S32 mNumJoints;
+ LLJoint* mSkeleton;
+
+ //--------------------------------------------------------------------
+ // Pelvis height adjustment members.
+ //--------------------------------------------------------------------
+public:
+ LLVector3 mBodySize;
+protected:
+ F32 mPelvisToFoot;
+
+ //--------------------------------------------------------------------
+ // Cached pointers to well known joints
+ //--------------------------------------------------------------------
+public:
+ LLJoint* mPelvisp;
+ LLJoint* mTorsop;
+ LLJoint* mChestp;
+ LLJoint* mNeckp;
+ LLJoint* mHeadp;
+ LLJoint* mSkullp;
+ LLJoint* mEyeLeftp;
+ LLJoint* mEyeRightp;
+ LLJoint* mHipLeftp;
+ LLJoint* mHipRightp;
+ LLJoint* mKneeLeftp;
+ LLJoint* mKneeRightp;
+ LLJoint* mAnkleLeftp;
+ LLJoint* mAnkleRightp;
+ LLJoint* mFootLeftp;
+ LLJoint* mFootRightp;
+ LLJoint* mWristLeftp;
+ LLJoint* mWristRightp;
+
+ //--------------------------------------------------------------------
+ // XML parse tree
+ //--------------------------------------------------------------------
+protected:
+ static LLXmlTree sXMLTree; // avatar config file
+ static LLXmlTree sSkeletonXMLTree; // avatar skeleton file
+
+ static LLAvatarSkeletonInfo* sAvatarSkeletonInfo;
+ static LLAvatarXmlInfo* sAvatarXmlInfo;
+
+
+/** Skeleton
+ ** **
+ *******************************************************************************/
+
/********************************************************************************
** **
** RENDERING
**/
+public:
BOOL mIsDummy; // for special views
//--------------------------------------------------------------------
@@ -109,6 +202,11 @@ public:
protected:
virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority
+protected:
+ typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t;
+ polymesh_map_t mMeshes;
+ std::vector<LLAvatarJoint *> mMeshLOD;
+
/** Meshes
** **
*******************************************************************************/
@@ -182,12 +280,115 @@ protected:
typedef std::vector<BakedTextureData> bakedtexturedata_vec_t;
bakedtexturedata_vec_t mBakedTextureDatas;
+/********************************************************************************
+ ** **
+ ** PHYSICS
+ **/
+
+ //--------------------------------------------------------------------
+ // Collision volumes
+ //--------------------------------------------------------------------
+public:
+ S32 mNumCollisionVolumes;
+ LLAvatarJointCollisionVolume* mCollisionVolumes;
+protected:
+ BOOL allocateCollisionVolumes(U32 num);
+
+/** Physics
+ ** **
+ *******************************************************************************/
/********************************************************************************
** **
** SUPPORT CLASSES
**/
+ struct LLAvatarXmlInfo
+ {
+ LLAvatarXmlInfo();
+ ~LLAvatarXmlInfo();
+
+ BOOL parseXmlSkeletonNode(LLXmlTreeNode* root);
+ BOOL parseXmlMeshNodes(LLXmlTreeNode* root);
+ BOOL parseXmlColorNodes(LLXmlTreeNode* root);
+ BOOL parseXmlLayerNodes(LLXmlTreeNode* root);
+ BOOL parseXmlDriverNodes(LLXmlTreeNode* root);
+ BOOL parseXmlMorphNodes(LLXmlTreeNode* root);
+
+ struct LLAvatarMeshInfo
+ {
+ typedef std::pair<LLViewerVisualParamInfo*,BOOL> morph_info_pair_t; // LLPolyMorphTargetInfo stored here
+ typedef std::vector<morph_info_pair_t> morph_info_list_t;
+
+ LLAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {}
+ ~LLAvatarMeshInfo()
+ {
+ morph_info_list_t::iterator iter;
+ for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++)
+ {
+ delete iter->first;
+ }
+ mPolyMorphTargetInfoList.clear();
+ }
+
+ std::string mType;
+ S32 mLOD;
+ std::string mMeshFileName;
+ std::string mReferenceMeshName;
+ F32 mMinPixelArea;
+ morph_info_list_t mPolyMorphTargetInfoList;
+ };
+ typedef std::vector<LLAvatarMeshInfo*> mesh_info_list_t;
+ mesh_info_list_t mMeshInfoList;
+
+ typedef std::vector<LLViewerVisualParamInfo*> skeletal_distortion_info_list_t; // LLPolySkeletalDistortionInfo stored here
+ skeletal_distortion_info_list_t mSkeletalDistortionInfoList;
+
+ struct LLAvatarAttachmentInfo
+ {
+ LLAvatarAttachmentInfo()
+ : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE),
+ mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {}
+ std::string mName;
+ std::string mJointName;
+ LLVector3 mPosition;
+ LLVector3 mRotationEuler;
+ S32 mGroup;
+ S32 mAttachmentID;
+ S32 mPieMenuSlice;
+ BOOL mVisibleFirstPerson;
+ BOOL mIsHUDAttachment;
+ BOOL mHasPosition;
+ BOOL mHasRotation;
+ };
+ typedef std::vector<LLAvatarAttachmentInfo*> attachment_info_list_t;
+ attachment_info_list_t mAttachmentInfoList;
+
+ LLTexGlobalColorInfo *mTexSkinColorInfo;
+ LLTexGlobalColorInfo *mTexHairColorInfo;
+ LLTexGlobalColorInfo *mTexEyeColorInfo;
+
+ typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t;
+ layer_info_list_t mLayerInfoList;
+
+ typedef std::vector<LLDriverParamInfo*> driver_info_list_t;
+ driver_info_list_t mDriverInfoList;
+
+ struct LLAvatarMorphInfo
+ {
+ LLAvatarMorphInfo()
+ : mInvert(FALSE) {}
+ std::string mName;
+ std::string mRegion;
+ std::string mLayer;
+ BOOL mInvert;
+ };
+
+ typedef std::vector<LLAvatarMorphInfo*> morph_info_list_t;
+ morph_info_list_t mMorphMaskInfoList;
+ };
+
+
class LLMaskedMorph
{
public:
@@ -197,7 +398,9 @@ protected:
BOOL mInvert;
std::string mLayer;
};
-
+/** Support Classes
+ ** **
+ *******************************************************************************/
};
#endif // LL_AVATAR_APPEARANCE_H
diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp
new file mode 100644
index 0000000000..809a261633
--- /dev/null
+++ b/indra/llappearance/llavatarjoint.cpp
@@ -0,0 +1,261 @@
+/**
+ * @file llavatarjoint.cpp
+ * @brief Implementation of LLAvatarJoint class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "llavatarjoint.h"
+
+#include "llgl.h"
+#include "llrender.h"
+#include "llmath.h"
+#include "llglheaders.h"
+#include "llrendersphere.h"
+#include "llavatarappearance.h"
+//#include "pipeline.h"
+
+#define DEFAULT_LOD 0.0f
+
+const S32 MIN_PIXEL_AREA_3PASS_HAIR = 64*64;
+
+//-----------------------------------------------------------------------------
+// Static Data
+//-----------------------------------------------------------------------------
+BOOL LLAvatarJoint::sDisableLOD = FALSE;
+
+//-----------------------------------------------------------------------------
+// LLAvatarJoint()
+// Class Constructor
+//-----------------------------------------------------------------------------
+LLAvatarJoint::LLAvatarJoint()
+ : LLJoint()
+{
+ init();
+}
+
+
+//-----------------------------------------------------------------------------
+// LLAvatarJoint()
+// Class Constructor
+//-----------------------------------------------------------------------------
+LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent)
+ : LLJoint(name, parent)
+{
+ init();
+}
+
+
+void LLAvatarJoint::init()
+{
+ mValid = FALSE;
+ mComponents = SC_JOINT | SC_BONE | SC_AXES;
+ mMinPixelArea = DEFAULT_LOD;
+ mPickName = PN_DEFAULT;
+ mVisible = TRUE;
+ mMeshID = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// ~LLAvatarJoint()
+// Class Destructor
+//-----------------------------------------------------------------------------
+LLAvatarJoint::~LLAvatarJoint()
+{
+}
+
+
+//--------------------------------------------------------------------
+// setValid()
+//--------------------------------------------------------------------
+void LLAvatarJoint::setValid( BOOL valid, BOOL recursive )
+{
+ //----------------------------------------------------------------
+ // set visibility for this joint
+ //----------------------------------------------------------------
+ mValid = valid;
+
+ //----------------------------------------------------------------
+ // set visibility for children
+ //----------------------------------------------------------------
+ if (recursive)
+ {
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
+ joint->setValid(valid, TRUE);
+ }
+ }
+
+}
+
+//--------------------------------------------------------------------
+// isTransparent()
+//--------------------------------------------------------------------
+BOOL LLAvatarJoint::isTransparent()
+{
+ return FALSE;
+}
+
+//--------------------------------------------------------------------
+// setSkeletonComponents()
+//--------------------------------------------------------------------
+void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive )
+{
+ mComponents = comp;
+ if (recursive)
+ {
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
+ joint->setSkeletonComponents(comp, recursive);
+ }
+ }
+}
+
+void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive)
+{
+ mVisible = visible;
+
+ if (recursive)
+ {
+ for (child_list_t::iterator iter = mChildren.begin();
+ iter != mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
+ joint->setVisible(visible, recursive);
+ }
+ }
+}
+
+
+void LLAvatarJoint::setMeshesToChildren()
+{
+ removeAllChildren();
+ for (std::vector<LLAvatarJointMesh*>::iterator iter = mMeshParts.begin();
+ iter != mMeshParts.end(); iter++)
+ {
+ addChild((LLAvatarJoint*) *iter);
+ }
+}
+//-----------------------------------------------------------------------------
+// LLAvatarJointCollisionVolume()
+//-----------------------------------------------------------------------------
+
+LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume()
+{
+ mUpdateXform = FALSE;
+}
+
+LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume(const std::string &name, LLJoint *parent) : LLAvatarJoint(name, parent)
+{
+
+}
+
+LLVector3 LLAvatarJointCollisionVolume::getVolumePos(LLVector3 &offset)
+{
+ mUpdateXform = TRUE;
+
+ LLVector3 result = offset;
+ result.scaleVec(getScale());
+ result.rotVec(getWorldRotation());
+ result += getWorldPosition();
+
+ return result;
+}
+
+void LLAvatarJointCollisionVolume::renderCollision()
+{
+ updateWorldMatrix();
+
+ gGL.pushMatrix();
+ gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] );
+
+ gGL.diffuseColor3f( 0.f, 0.f, 1.f );
+
+ gGL.begin(LLRender::LINES);
+
+ LLVector3 v[] =
+ {
+ LLVector3(1,0,0),
+ LLVector3(-1,0,0),
+ LLVector3(0,1,0),
+ LLVector3(0,-1,0),
+
+ LLVector3(0,0,-1),
+ LLVector3(0,0,1),
+ };
+
+ //sides
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[2].mV);
+
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[3].mV);
+
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[2].mV);
+
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[3].mV);
+
+
+ //top
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[4].mV);
+
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[4].mV);
+
+ gGL.vertex3fv(v[2].mV);
+ gGL.vertex3fv(v[4].mV);
+
+ gGL.vertex3fv(v[3].mV);
+ gGL.vertex3fv(v[4].mV);
+
+
+ //bottom
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[5].mV);
+
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[5].mV);
+
+ gGL.vertex3fv(v[2].mV);
+ gGL.vertex3fv(v[5].mV);
+
+ gGL.vertex3fv(v[3].mV);
+ gGL.vertex3fv(v[5].mV);
+
+ gGL.end();
+
+ gGL.popMatrix();
+}
+
+
+// End
diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h
new file mode 100644
index 0000000000..cbfc1b73ea
--- /dev/null
+++ b/indra/llappearance/llavatarjoint.h
@@ -0,0 +1,127 @@
+/**
+ * @file llavatarjoint.h
+ * @brief Implementation of LLAvatarJoint class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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 LL_LLAVATARJOINT_H
+#define LL_LLAVATARJOINT_H
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "lljoint.h"
+#include "lljointpickname.h"
+
+class LLFace;
+class LLAvatarJointMesh;
+
+//-----------------------------------------------------------------------------
+// class LLViewerJoint
+//-----------------------------------------------------------------------------
+class LLAvatarJoint :
+ public LLJoint
+{
+public:
+ LLAvatarJoint();
+ LLAvatarJoint(const std::string &name, LLJoint *parent = NULL);
+ virtual ~LLAvatarJoint();
+
+ // Gets the validity of this joint
+ BOOL getValid() { return mValid; }
+
+ // Sets the validity of this joint
+ virtual void setValid( BOOL valid, BOOL recursive=FALSE );
+
+ // Returns true if this object is transparent.
+ // This is used to determine in which order to draw objects.
+ virtual BOOL isTransparent();
+
+ // Returns true if this object should inherit scale modifiers from its immediate parent
+ virtual BOOL inheritScale() { return FALSE; }
+
+
+ enum Components
+ {
+ SC_BONE = 1,
+ SC_JOINT = 2,
+ SC_AXES = 4
+ };
+
+ // Selects which skeleton components to draw
+ void setSkeletonComponents( U32 comp, BOOL recursive = TRUE );
+
+ // Returns which skeleton components are enables for drawing
+ U32 getSkeletonComponents() { return mComponents; }
+
+ // Sets the level of detail for this node as a minimum
+ // pixel area threshold. If the current pixel area for this
+ // object is less than the specified threshold, the node is
+ // not traversed. In addition, if a value is specified (not
+ // default of 0.0), and the pixel area is larger than the
+ // specified minimum, the node is rendered, but no other siblings
+ // of this node under the same parent will be.
+ F32 getLOD() { return mMinPixelArea; }
+ void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; }
+
+ void setPickName(LLJointPickName name) { mPickName = name; }
+ LLJointPickName getPickName() { return mPickName; }
+
+ void setVisible( BOOL visible, BOOL recursive );
+
+ // Takes meshes in mMeshParts and sets each one as a child joint
+ void setMeshesToChildren();
+
+public:
+ static BOOL sDisableLOD;
+ std::vector<LLAvatarJointMesh*> mMeshParts; //LLViewerJointMesh*
+ void setMeshID( S32 id ) {mMeshID = id;}
+
+protected:
+ void init();
+
+ BOOL mValid;
+ U32 mComponents;
+ F32 mMinPixelArea;
+ LLJointPickName mPickName;
+ BOOL mVisible;
+ S32 mMeshID;
+};
+
+class LLAvatarJointCollisionVolume : public LLAvatarJoint
+{
+public:
+ LLAvatarJointCollisionVolume();
+ LLAvatarJointCollisionVolume(const std::string &name, LLJoint *parent = NULL);
+ virtual ~LLAvatarJointCollisionVolume() {};
+
+ virtual BOOL inheritScale() { return TRUE; }
+
+ void renderCollision();
+
+ LLVector3 getVolumePos(LLVector3 &offset);
+};
+
+#endif // LL_LLAVATARJOINT_H
+
+
diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp
new file mode 100755
index 0000000000..92c213126a
--- /dev/null
+++ b/indra/llappearance/llavatarjointmesh.cpp
@@ -0,0 +1,359 @@
+/**
+ * @file LLAvatarJointMesh.cpp
+ * @brief Implementation of LLAvatarJointMesh class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "linden_common.h"
+#include "imageids.h"
+#include "llfasttimer.h"
+#include "llrender.h"
+
+#include "llavatarjointmesh.h"
+#include "llavatarappearance.h"
+//#include "llapr.h"
+//#include "llbox.h"
+//#include "lldrawable.h"
+//#include "lldrawpoolavatar.h"
+//#include "lldrawpoolbump.h"
+//#include "lldynamictexture.h"
+//#include "llface.h"
+//#include "llgldbg.h"
+//#include "llglheaders.h"
+#include "lltexlayer.h"
+//#include "llviewercamera.h"
+//#include "llviewercontrol.h"
+//#include "llviewertexturelist.h"
+//#include "llsky.h"
+//#include "pipeline.h"
+//#include "llviewershadermgr.h"
+#include "llmath.h"
+#include "v4math.h"
+#include "m3math.h"
+#include "m4math.h"
+#include "llmatrix4a.h"
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh::LLSkinJoint
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// LLSkinJoint
+//-----------------------------------------------------------------------------
+LLSkinJoint::LLSkinJoint()
+{
+ mJoint = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// ~LLSkinJoint
+//-----------------------------------------------------------------------------
+LLSkinJoint::~LLSkinJoint()
+{
+ mJoint = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// LLSkinJoint::setupSkinJoint()
+//-----------------------------------------------------------------------------
+BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint)
+{
+ // find the named joint
+ mJoint = joint;
+ if ( !mJoint )
+ {
+ llinfos << "Can't find joint" << llendl;
+ }
+
+ // compute the inverse root skin matrix
+ mRootToJointSkinOffset.clearVec();
+
+ LLVector3 rootSkinOffset;
+ while (joint)
+ {
+ rootSkinOffset += joint->getSkinOffset();
+ joint = (LLAvatarJoint*)joint->getParent();
+ }
+
+ mRootToJointSkinOffset = -rootSkinOffset;
+ mRootToParentJointSkinOffset = mRootToJointSkinOffset;
+ mRootToParentJointSkinOffset += mJoint->getSkinOffset();
+
+ return TRUE;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+BOOL LLAvatarJointMesh::sPipelineRender = FALSE;
+EAvatarRenderPass LLAvatarJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE;
+U32 LLAvatarJointMesh::sClothingMaskImageName = 0;
+LLColor4 LLAvatarJointMesh::sClothingInnerColor;
+
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh()
+//-----------------------------------------------------------------------------
+LLAvatarJointMesh::LLAvatarJointMesh()
+ :
+ mTexture( NULL ),
+ mLayerSet( NULL ),
+ mTestImageName( 0 ),
+ mFaceIndexCount(0),
+ mIsTransparent(FALSE)
+{
+
+ mColor[0] = 1.0f;
+ mColor[1] = 1.0f;
+ mColor[2] = 1.0f;
+ mColor[3] = 1.0f;
+ mShiny = 0.0f;
+ mCullBackFaces = TRUE;
+
+ mMesh = NULL;
+
+ mNumSkinJoints = 0;
+ mSkinJoints = NULL;
+
+ mFace = NULL;
+
+ mMeshID = 0;
+ mUpdateXform = FALSE;
+
+ mValid = FALSE;
+}
+
+
+//-----------------------------------------------------------------------------
+// ~LLAvatarJointMesh()
+// Class Destructor
+//-----------------------------------------------------------------------------
+LLAvatarJointMesh::~LLAvatarJointMesh()
+{
+ mMesh = NULL;
+ mTexture = NULL;
+ freeSkinData();
+}
+
+
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh::allocateSkinData()
+//-----------------------------------------------------------------------------
+BOOL LLAvatarJointMesh::allocateSkinData( U32 numSkinJoints )
+{
+ mSkinJoints = new LLSkinJoint[ numSkinJoints ];
+ mNumSkinJoints = numSkinJoints;
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh::freeSkinData()
+//-----------------------------------------------------------------------------
+void LLAvatarJointMesh::freeSkinData()
+{
+ mNumSkinJoints = 0;
+ delete [] mSkinJoints;
+ mSkinJoints = NULL;
+}
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::getColor()
+//--------------------------------------------------------------------
+void LLAvatarJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha )
+{
+ *red = mColor[0];
+ *green = mColor[1];
+ *blue = mColor[2];
+ *alpha = mColor[3];
+}
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::setColor()
+//--------------------------------------------------------------------
+void LLAvatarJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha )
+{
+ mColor[0] = red;
+ mColor[1] = green;
+ mColor[2] = blue;
+ mColor[3] = alpha;
+}
+
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::getTexture()
+//--------------------------------------------------------------------
+//LLViewerTexture *LLAvatarJointMesh::getTexture()
+//{
+// return mTexture;
+//}
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::setTexture()
+//--------------------------------------------------------------------
+void LLAvatarJointMesh::setTexture( LLGLTexture *texture )
+{
+ mTexture = texture;
+
+ // texture and dynamic_texture are mutually exclusive
+ if( texture )
+ {
+ mLayerSet = NULL;
+ //texture->bindTexture(0);
+ //texture->setClamp(TRUE, TRUE);
+ }
+}
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::setLayerSet()
+// Sets the shape texture (takes precedence over normal texture)
+//--------------------------------------------------------------------
+void LLAvatarJointMesh::setLayerSet( LLTexLayerSet* layer_set )
+{
+ mLayerSet = layer_set;
+
+ // texture and dynamic_texture are mutually exclusive
+ if( layer_set )
+ {
+ mTexture = NULL;
+ }
+}
+
+
+
+//--------------------------------------------------------------------
+// LLAvatarJointMesh::getMesh()
+//--------------------------------------------------------------------
+LLPolyMesh *LLAvatarJointMesh::getMesh()
+{
+ return mMesh;
+}
+
+//-----------------------------------------------------------------------------
+// LLAvatarJointMesh::setMesh()
+//-----------------------------------------------------------------------------
+void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh )
+{
+ // set the mesh pointer
+ mMesh = mesh;
+
+ // release any existing skin joints
+ freeSkinData();
+
+ if ( mMesh == NULL )
+ {
+ return;
+ }
+
+ // acquire the transform from the mesh object
+ setPosition( mMesh->getPosition() );
+ setRotation( mMesh->getRotation() );
+ setScale( mMesh->getScale() );
+
+ // create skin joints if necessary
+ if ( mMesh->hasWeights() && !mMesh->isLOD())
+ {
+ U32 numJointNames = mMesh->getNumJointNames();
+
+ allocateSkinData( numJointNames );
+ std::string *jointNames = mMesh->getJointNames();
+
+ U32 jn;
+ for (jn = 0; jn < numJointNames; jn++)
+ {
+ //llinfos << "Setting up joint " << jointNames[jn] << llendl;
+ LLAvatarJoint* joint = (LLAvatarJoint*)(getRoot()->findJoint(jointNames[jn]) );
+ mSkinJoints[jn].setupSkinJoint( joint );
+ }
+ }
+
+ // setup joint array
+ if (!mMesh->isLOD())
+ {
+ setupJoint((LLAvatarJoint*)getRoot());
+ }
+
+// llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl;
+}
+
+//-----------------------------------------------------------------------------
+// setupJoint()
+//-----------------------------------------------------------------------------
+void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint)
+{
+// llinfos << "Mesh: " << getName() << llendl;
+
+// S32 joint_count = 0;
+ U32 sj;
+ for (sj=0; sj<mNumSkinJoints; sj++)
+ {
+ LLSkinJoint &js = mSkinJoints[sj];
+
+ if (js.mJoint != current_joint)
+ {
+ continue;
+ }
+
+ // we've found a skinjoint for this joint..
+
+ // is the last joint in the array our parent?
+ if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == &current_joint->getParent()->getWorldMatrix())
+ {
+ // ...then just add ourselves
+ LLAvatarJoint* jointp = js.mJoint;
+ mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
+// llinfos << "joint " << joint_count << js.mJoint->getName() << llendl;
+// joint_count++;
+ }
+ // otherwise add our parent and ourselves
+ else
+ {
+ mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getParent()->getWorldMatrix(), NULL));
+// llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl;
+// joint_count++;
+ mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getWorldMatrix(), &js));
+// llinfos << "joint " << joint_count << current_joint->getName() << llendl;
+// joint_count++;
+ }
+ }
+
+ // depth-first traversal
+ for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
+ iter != current_joint->mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
+ setupJoint(child_joint);
+ }
+}
+
+
+// End
diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h
new file mode 100755
index 0000000000..dcd202bdaf
--- /dev/null
+++ b/indra/llappearance/llavatarjointmesh.h
@@ -0,0 +1,140 @@
+/**
+ * @file llavatarjointmesh.h
+ * @brief Implementation of LLAvatarJointMesh class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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 LL_LLAVATARJOINTMESH_H
+#define LL_LLAVATARJOINTMESH_H
+
+#include "llavatarjoint.h"
+#include "llgltexture.h"
+#include "llpolymesh.h"
+#include "v4color.h"
+
+class LLDrawable;
+class LLFace;
+class LLCharacter;
+class LLTexLayerSet;
+
+typedef enum e_avatar_render_pass
+{
+ AVATAR_RENDER_PASS_SINGLE,
+ AVATAR_RENDER_PASS_CLOTHING_INNER,
+ AVATAR_RENDER_PASS_CLOTHING_OUTER
+} EAvatarRenderPass;
+
+class LLSkinJoint
+{
+public:
+ LLSkinJoint();
+ ~LLSkinJoint();
+ BOOL setupSkinJoint( LLAvatarJoint *joint);
+
+ LLAvatarJoint *mJoint;
+ LLVector3 mRootToJointSkinOffset;
+ LLVector3 mRootToParentJointSkinOffset;
+};
+
+//-----------------------------------------------------------------------------
+// class LLViewerJointMesh
+//-----------------------------------------------------------------------------
+class LLAvatarJointMesh : public LLAvatarJoint
+{
+ friend class LLAvatarAppearance;
+protected:
+ LLColor4 mColor; // color value
+// LLColor4 mSpecular; // specular color (always white for now)
+ F32 mShiny; // shiny value
+ LLPointer<LLGLTexture> mTexture; // ptr to a global texture
+ LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar
+ U32 mTestImageName; // handle to a temporary texture for previewing uploads
+ LLPolyMesh* mMesh; // ptr to a global polymesh
+ BOOL mCullBackFaces; // true by default
+ LLFace* mFace; // ptr to a face w/ AGP copy of mesh
+
+ U32 mFaceIndexCount;
+ BOOL mIsTransparent;
+
+ U32 mNumSkinJoints;
+ LLSkinJoint* mSkinJoints;
+ S32 mMeshID;
+
+public:
+ static BOOL sPipelineRender;
+ //RN: this is here for testing purposes
+ static U32 sClothingMaskImageName;
+ static EAvatarRenderPass sRenderPass;
+ static LLColor4 sClothingInnerColor;
+
+public:
+ // Constructor
+ LLAvatarJointMesh();
+
+ // Destructor
+ virtual ~LLAvatarJointMesh();
+
+ // Gets the shape color
+ void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha );
+
+ // Sets the shape color
+ void setColor( F32 red, F32 green, F32 blue, F32 alpha );
+
+ // Sets the shininess
+ void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; };
+
+ // Sets the shape texture
+ void setTexture( LLGLTexture *texture );
+
+ void setTestTexture( U32 name ) { mTestImageName = name; }
+
+ // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture)
+ void setLayerSet( LLTexLayerSet* layer_set );
+
+ // Gets the poly mesh
+ LLPolyMesh *getMesh();
+
+ // Sets the poly mesh
+ void setMesh( LLPolyMesh *mesh );
+
+ // Sets up joint matrix data for rendering
+ void setupJoint(LLAvatarJoint* current_joint);
+
+ // Render time method to upload batches of joint matrices
+ void uploadJointMatrices();
+
+ // Sets ID for picking
+ void setMeshID( S32 id ) {mMeshID = id;}
+
+ // Gets ID for picking
+ S32 getMeshID() { return mMeshID; }
+
+private:
+ // Allocate skin data
+ BOOL allocateSkinData( U32 numSkinJoints );
+
+ // Free skin data
+ void freeSkinData();
+};
+
+#endif // LL_LLAVATARJOINTMESH_H
diff --git a/indra/newview/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp
index 70f3b5335e..b1370ab1e3 100644
--- a/indra/newview/llpolymesh.cpp
+++ b/indra/llappearance/llpolymesh.cpp
@@ -27,25 +27,24 @@
//-----------------------------------------------------------------------------
// Header Files
//-----------------------------------------------------------------------------
-#include "llviewerprecompiledheaders.h"
-
+#include "linden_common.h"
+#include "llpolymesh.h"
#include "llfasttimer.h"
#include "llmemory.h"
-#include "llviewercontrol.h"
+//#include "llviewercontrol.h"
#include "llxmltree.h"
-#include "llvoavatar.h"
+#include "llavatarappearance.h"
#include "llwearable.h"
#include "lldir.h"
#include "llvolume.h"
#include "llendianswizzle.h"
-#include "llpolymesh.h"
#define HEADER_ASCII "Linden Mesh 1.0"
#define HEADER_BINARY "Linden Binary Mesh 1.0"
-extern LLControlGroup gSavedSettings; // read only
+//extern LLControlGroup gSavedSettings; // read only
LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data,
const std::string &name);
@@ -1048,250 +1047,4 @@ F32* LLPolyMesh::getWritableWeights() const
return mSharedData->mWeights;
}
-//-----------------------------------------------------------------------------
-// LLPolySkeletalDistortionInfo()
-//-----------------------------------------------------------------------------
-LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo()
-{
-}
-
-BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node)
-{
- llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) );
-
- if (!LLViewerVisualParamInfo::parseXml(node))
- return FALSE;
-
- LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton");
-
- if (NULL == skeletalParam)
- {
- llwarns << "Failed to getChildByName(\"param_skeleton\")"
- << llendl;
- return FALSE;
- }
-
- for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() )
- {
- if (bone->hasName("bone"))
- {
- std::string name;
- LLVector3 scale;
- LLVector3 pos;
- BOOL haspos = FALSE;
-
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (!bone->getFastAttributeString(name_string, name))
- {
- llwarns << "No bone name specified for skeletal param." << llendl;
- continue;
- }
-
- static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
- if (!bone->getFastAttributeVector3(scale_string, scale))
- {
- llwarns << "No scale specified for bone " << name << "." << llendl;
- continue;
- }
-
- // optional offset deformation (translation)
- static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset");
- if (bone->getFastAttributeVector3(offset_string, pos))
- {
- haspos = TRUE;
- }
- mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos));
- }
- else
- {
- llwarns << "Unrecognized element " << bone->getName() << " in skeletal distortion" << llendl;
- continue;
- }
- }
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// LLPolySkeletalDistortion()
-//-----------------------------------------------------------------------------
-LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLVOAvatar *avatarp)
-{
- mAvatar = avatarp;
- mDefaultVec.splat(0.001f);
-}
-
-//-----------------------------------------------------------------------------
-// ~LLPolySkeletalDistortion()
-//-----------------------------------------------------------------------------
-LLPolySkeletalDistortion::~LLPolySkeletalDistortion()
-{
-}
-
-BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
-{
- llassert(mInfo == NULL);
- if (info->mID < 0)
- return FALSE;
- mInfo = info;
- mID = info->mID;
- setWeight(getDefaultWeight(), FALSE );
-
- LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
- for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
- {
- LLPolySkeletalBoneInfo *bone_info = &(*iter);
- LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName);
- if (!joint)
- {
- llwarns << "Joint " << bone_info->mBoneName << " not found." << llendl;
- continue;
- }
-
- if (mJointScales.find(joint) != mJointScales.end())
- {
- llwarns << "Scale deformation already supplied for joint " << joint->getName() << "." << llendl;
- }
-
- // store it
- mJointScales[joint] = bone_info->mScaleDeformation;
-
- // apply to children that need to inherit it
- for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
- iter != joint->mChildren.end(); ++iter)
- {
- LLViewerJoint* child_joint = (LLViewerJoint*)(*iter);
- if (child_joint->inheritScale())
- {
- LLVector3 childDeformation = LLVector3(child_joint->getScale());
- childDeformation.scaleVec(bone_info->mScaleDeformation);
- mJointScales[child_joint] = childDeformation;
- }
- }
-
- if (bone_info->mHasPositionDeformation)
- {
- if (mJointOffsets.find(joint) != mJointOffsets.end())
- {
- llwarns << "Offset deformation already supplied for joint " << joint->getName() << "." << llendl;
- }
- mJointOffsets[joint] = bone_info->mPositionDeformation;
- }
- }
- return TRUE;
-}
-
-/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
-{
- LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar);
- *new_param = *this;
- return new_param;
-}
-
-//-----------------------------------------------------------------------------
-// apply()
-//-----------------------------------------------------------------------------
-static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion");
-
-void LLPolySkeletalDistortion::apply( ESex avatar_sex )
-{
- LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY);
-
- F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
-
- LLJoint* joint;
- joint_vec_map_t::iterator iter;
-
- for (iter = mJointScales.begin();
- iter != mJointScales.end();
- iter++)
- {
- joint = iter->first;
- LLVector3 newScale = joint->getScale();
- LLVector3 scaleDelta = iter->second;
- newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
- joint->setScale(newScale);
- }
-
- for (iter = mJointOffsets.begin();
- iter != mJointOffsets.end();
- iter++)
- {
- joint = iter->first;
- LLVector3 newPosition = joint->getPosition();
- LLVector3 positionDelta = iter->second;
- newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
- joint->setPosition(newPosition);
- }
-
- if (mLastWeight != mCurWeight && !mIsAnimating)
- {
- mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1);
- }
- mLastWeight = mCurWeight;
-}
-
-
-LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data,
- const std::string &name)
-{
- LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
- cloned_morph_data->mName = name;
- for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
- {
- cloned_morph_data->mCoords[v] = src_data->mCoords[v];
- cloned_morph_data->mNormals[v] = src_data->mNormals[v];
- cloned_morph_data->mBinormals[v] = src_data->mBinormals[v];
- }
- return cloned_morph_data;
-}
-
-LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data,
- const LLVector3 &direction,
- const std::string &name)
-{
- LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
- cloned_morph_data->mName = name;
- LLVector4a dir;
- dir.load3(direction.mV);
-
- for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
- {
- cloned_morph_data->mCoords[v] = dir;
- cloned_morph_data->mNormals[v].clear();
- cloned_morph_data->mBinormals[v].clear();
- }
- return cloned_morph_data;
-}
-
-LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data,
- F32 scale,
- const std::string &name)
-{
- LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
- cloned_morph_data->mName = name;
-
- LLVector4a sc;
- sc.splat(scale);
-
- LLVector4a nsc;
- nsc.set(scale, -scale, scale, scale);
-
- for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
- {
- if (cloned_morph_data->mCoords[v][1] < 0)
- {
- cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc);
- cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc);
- cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc);
- }
- else
- {
- cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc);
- cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc);
- cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc);
- }
- }
- return cloned_morph_data;
-}
-
// End
diff --git a/indra/newview/llpolymesh.h b/indra/llappearance/llpolymesh.h
index ffb11a3f7e..ef1dfb1adb 100644
--- a/indra/newview/llpolymesh.h
+++ b/indra/llappearance/llpolymesh.h
@@ -24,8 +24,8 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLPOLYMESH_H
-#define LL_LLPOLYMESH_H
+#ifndef LL_LLPOLYMESHINTERFACE_H
+#define LL_LLPOLYMESHINTERFACE_H
#include <string>
#include <map>
@@ -39,7 +39,7 @@
//#include "lldarray.h"
class LLSkinJoint;
-class LLVOAvatar;
+class LLAvatarAppearance;
class LLWearable;
//#define USE_STRIPS // Use tri-strips for rendering.
@@ -319,8 +319,8 @@ public:
BOOL isLOD() { return mSharedData && mSharedData->isLOD(); }
- void setAvatar(LLVOAvatar* avatarp) { mAvatarp = avatarp; }
- LLVOAvatar* getAvatar() { return mAvatarp; }
+ void setAvatar(LLAvatarAppearance* avatarp) { mAvatarp = avatarp; }
+ LLAvatarAppearance* getAvatar() { return mAvatarp; }
LLDynamicArray<LLJointRenderData*> mJointRenderData;
@@ -362,77 +362,8 @@ protected:
static LLPolyMeshSharedDataTable sGlobalSharedMeshList;
// Backlink only; don't make this an LLPointer.
- LLVOAvatar* mAvatarp;
+ LLAvatarAppearance* mAvatarp;
};
-//-----------------------------------------------------------------------------
-// LLPolySkeletalDeformationInfo
-// Shared information for LLPolySkeletalDeformations
-//-----------------------------------------------------------------------------
-struct LLPolySkeletalBoneInfo
-{
- LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, BOOL haspos)
- : mBoneName(name),
- mScaleDeformation(scale),
- mPositionDeformation(pos),
- mHasPositionDeformation(haspos) {}
- std::string mBoneName;
- LLVector3 mScaleDeformation;
- LLVector3 mPositionDeformation;
- BOOL mHasPositionDeformation;
-};
-
-class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo
-{
- friend class LLPolySkeletalDistortion;
-public:
- LLPolySkeletalDistortionInfo();
- /*virtual*/ ~LLPolySkeletalDistortionInfo() {};
-
- /*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
-
-protected:
- typedef std::vector<LLPolySkeletalBoneInfo> bone_info_list_t;
- bone_info_list_t mBoneInfoList;
-};
-
-//-----------------------------------------------------------------------------
-// LLPolySkeletalDeformation
-// A set of joint scale data for deforming the avatar mesh
-//-----------------------------------------------------------------------------
-class LLPolySkeletalDistortion : public LLViewerVisualParam
-{
-public:
- LLPolySkeletalDistortion(LLVOAvatar *avatarp);
- ~LLPolySkeletalDistortion();
-
- // Special: These functions are overridden by child classes
- LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; }
- // This sets mInfo and calls initialization functions
- BOOL setInfo(LLPolySkeletalDistortionInfo *info);
-
- /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
-
- // LLVisualParam Virtual functions
- ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
- /*virtual*/ void apply( ESex sex );
-
- // LLViewerVisualParam Virtual functions
- /*virtual*/ F32 getTotalDistortion() { return 0.1f; }
- /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; }
- /*virtual*/ F32 getMaxDistortion() { return 0.1f; }
- /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);}
- /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;};
- /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;};
-
-protected:
- typedef std::map<LLJoint*, LLVector3> joint_vec_map_t;
- joint_vec_map_t mJointScales;
- joint_vec_map_t mJointOffsets;
- LLVector4a mDefaultVec;
- // Backlink only; don't make this an LLPointer.
- LLVOAvatar *mAvatar;
-};
-
-#endif // LL_LLPOLYMESH_H
+#endif // LL_LLPOLYMESHINTERFACE_H
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
new file mode 100644
index 0000000000..aa680894ff
--- /dev/null
+++ b/indra/llappearance/llpolymorph.cpp
@@ -0,0 +1,748 @@
+/**
+ * @file llpolymorph.cpp
+ * @brief Implementation of LLPolyMesh class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+
+#include "llpolymorph.h"
+#include "llavatarappearance.h"
+#include "llavatarjoint.h"
+#include "llwearable.h"
+#include "llxmltree.h"
+#include "llendianswizzle.h"
+#include "llpolymesh.h"
+
+//#include "../tools/imdebug/imdebug.h"
+
+const F32 NORMAL_SOFTEN_FACTOR = 0.65f;
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphData()
+//-----------------------------------------------------------------------------
+LLPolyMorphData::LLPolyMorphData(const std::string& morph_name)
+ : mName(morph_name)
+{
+ mNumIndices = 0;
+ mCurrentIndex = 0;
+ mTotalDistortion = 0.f;
+ mAvgDistortion.clear();
+ mMaxDistortion = 0.f;
+ mVertexIndices = NULL;
+ mCoords = NULL;
+ mNormals = NULL;
+ mBinormals = NULL;
+ mTexCoords = NULL;
+
+ mMesh = NULL;
+}
+
+LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) :
+ mName(rhs.mName),
+ mNumIndices(rhs.mNumIndices),
+ mTotalDistortion(rhs.mTotalDistortion),
+ mAvgDistortion(rhs.mAvgDistortion),
+ mMaxDistortion(rhs.mMaxDistortion),
+ mVertexIndices(NULL),
+ mCoords(NULL),
+ mNormals(NULL),
+ mBinormals(NULL),
+ mTexCoords(NULL)
+{
+ const S32 numVertices = mNumIndices;
+
+ mCoords = new LLVector4a[numVertices];
+ mNormals = new LLVector4a[numVertices];
+ mBinormals = new LLVector4a[numVertices];
+ mTexCoords = new LLVector2[numVertices];
+ mVertexIndices = new U32[numVertices];
+
+ for (S32 v=0; v < numVertices; v++)
+ {
+ mCoords[v] = rhs.mCoords[v];
+ mNormals[v] = rhs.mNormals[v];
+ mBinormals[v] = rhs.mBinormals[v];
+ mTexCoords[v] = rhs.mTexCoords[v];
+ mVertexIndices[v] = rhs.mVertexIndices[v];
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// ~LLPolyMorphData()
+//-----------------------------------------------------------------------------
+LLPolyMorphData::~LLPolyMorphData()
+{
+ delete [] mVertexIndices;
+ delete [] mCoords;
+ delete [] mNormals;
+ delete [] mBinormals;
+ delete [] mTexCoords;
+}
+
+//-----------------------------------------------------------------------------
+// loadBinary()
+//-----------------------------------------------------------------------------
+BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh)
+{
+ S32 numVertices;
+ S32 numRead;
+
+ numRead = fread(&numVertices, sizeof(S32), 1, fp);
+ llendianswizzle(&numVertices, sizeof(S32), 1);
+ if (numRead != 1)
+ {
+ llwarns << "Can't read number of morph target vertices" << llendl;
+ return FALSE;
+ }
+
+ //-------------------------------------------------------------------------
+ // allocate vertices
+ //-------------------------------------------------------------------------
+ mCoords = new LLVector4a[numVertices];
+ mNormals = new LLVector4a[numVertices];
+ mBinormals = new LLVector4a[numVertices];
+ mTexCoords = new LLVector2[numVertices];
+ // Actually, we are allocating more space than we need for the skiplist
+ mVertexIndices = new U32[numVertices];
+ mNumIndices = 0;
+ mTotalDistortion = 0.f;
+ mMaxDistortion = 0.f;
+ mAvgDistortion.clear();
+ mMesh = mesh;
+
+ //-------------------------------------------------------------------------
+ // read vertices
+ //-------------------------------------------------------------------------
+ for(S32 v = 0; v < numVertices; v++)
+ {
+ numRead = fread(&mVertexIndices[v], sizeof(U32), 1, fp);
+ llendianswizzle(&mVertexIndices[v], sizeof(U32), 1);
+ if (numRead != 1)
+ {
+ llwarns << "Can't read morph target vertex number" << llendl;
+ return FALSE;
+ }
+
+ if (mVertexIndices[v] > 10000)
+ {
+ llerrs << "Bad morph index: " << mVertexIndices[v] << llendl;
+ }
+
+
+ numRead = fread(&mCoords[v], sizeof(F32), 3, fp);
+ llendianswizzle(&mCoords[v], sizeof(F32), 3);
+ if (numRead != 3)
+ {
+ llwarns << "Can't read morph target vertex coordinates" << llendl;
+ return FALSE;
+ }
+
+ F32 magnitude = mCoords[v].getLength3().getF32();
+
+ mTotalDistortion += magnitude;
+ LLVector4a t;
+ t.setAbs(mCoords[v]);
+ mAvgDistortion.add(t);
+
+ if (magnitude > mMaxDistortion)
+ {
+ mMaxDistortion = magnitude;
+ }
+
+ numRead = fread(&mNormals[v], sizeof(F32), 3, fp);
+ llendianswizzle(&mNormals[v], sizeof(F32), 3);
+ if (numRead != 3)
+ {
+ llwarns << "Can't read morph target normal" << llendl;
+ return FALSE;
+ }
+
+ numRead = fread(&mBinormals[v], sizeof(F32), 3, fp);
+ llendianswizzle(&mBinormals[v], sizeof(F32), 3);
+ if (numRead != 3)
+ {
+ llwarns << "Can't read morph target binormal" << llendl;
+ return FALSE;
+ }
+
+
+ numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp);
+ llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2);
+ if (numRead != 2)
+ {
+ llwarns << "Can't read morph target uv" << llendl;
+ return FALSE;
+ }
+
+ mNumIndices++;
+ }
+
+ mAvgDistortion.mul(1.f/(F32)mNumIndices);
+ mAvgDistortion.normalize3fast();
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphTargetInfo()
+//-----------------------------------------------------------------------------
+LLPolyMorphTargetInfo::LLPolyMorphTargetInfo()
+ : mIsClothingMorph(FALSE)
+{
+}
+
+BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node)
+{
+ llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) );
+
+ if (!LLViewerVisualParamInfo::parseXml(node))
+ return FALSE;
+
+ // Get mixed-case name
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if( !node->getFastAttributeString( name_string, mMorphName ) )
+ {
+ llwarns << "Avatar file: <param> is missing name attribute" << llendl;
+ return FALSE; // Continue, ignoring this tag
+ }
+
+ static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph");
+ node->getFastAttributeBOOL(clothing_morph_string, mIsClothingMorph);
+
+ LLXmlTreeNode *paramNode = node->getChildByName("param_morph");
+
+ if (NULL == paramNode)
+ {
+ llwarns << "Failed to getChildByName(\"param_morph\")"
+ << llendl;
+ return FALSE;
+ }
+
+ for (LLXmlTreeNode* child_node = paramNode->getFirstChild();
+ child_node;
+ child_node = paramNode->getNextChild())
+ {
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (child_node->hasName("volume_morph"))
+ {
+ std::string volume_name;
+ if (child_node->getFastAttributeString(name_string, volume_name))
+ {
+ LLVector3 scale;
+ static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
+ child_node->getFastAttributeVector3(scale_string, scale);
+
+ LLVector3 pos;
+ static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos");
+ child_node->getFastAttributeVector3(pos_string, pos);
+
+ mVolumeInfoList.push_back(LLPolyVolumeMorphInfo(volume_name,scale,pos));
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphTarget()
+//-----------------------------------------------------------------------------
+LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh)
+ : mMorphData(NULL), mMesh(poly_mesh),
+ mVertMask(NULL),
+ mLastSex(SEX_FEMALE),
+ mNumMorphMasksPending(0)
+{
+}
+
+//-----------------------------------------------------------------------------
+// ~LLPolyMorphTarget()
+//-----------------------------------------------------------------------------
+LLPolyMorphTarget::~LLPolyMorphTarget()
+{
+ if (mVertMask)
+ {
+ delete mVertMask;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// setInfo()
+//-----------------------------------------------------------------------------
+BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
+{
+ llassert(mInfo == NULL);
+ if (info->mID < 0)
+ return FALSE;
+ mInfo = info;
+ mID = info->mID;
+ setWeight(getDefaultWeight(), FALSE );
+
+ LLAvatarAppearance* avatarp = mMesh->getAvatar();
+ LLPolyMorphTargetInfo::volume_info_list_t::iterator iter;
+ for (iter = getInfo()->mVolumeInfoList.begin(); iter != getInfo()->mVolumeInfoList.end(); iter++)
+ {
+ LLPolyVolumeMorphInfo *volume_info = &(*iter);
+ for (S32 i = 0; i < avatarp->mNumCollisionVolumes; i++)
+ {
+ if (avatarp->mCollisionVolumes[i].getName() == volume_info->mName)
+ {
+ mVolumeMorphs.push_back(LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i],
+ volume_info->mScale,
+ volume_info->mPos));
+ break;
+ }
+ }
+ }
+
+ std::string morph_param_name = getInfo()->mMorphName;
+
+ mMorphData = mMesh->getMorphData(morph_param_name);
+ if (!mMorphData)
+ {
+ const std::string driven_tag = "_Driven";
+ U32 pos = morph_param_name.find(driven_tag);
+ if (pos > 0)
+ {
+ morph_param_name = morph_param_name.substr(0,pos);
+ mMorphData = mMesh->getMorphData(morph_param_name);
+ }
+ }
+ if (!mMorphData)
+ {
+ llwarns << "No morph target named " << morph_param_name << " found in mesh." << llendl;
+ return FALSE; // Continue, ignoring this tag
+ }
+ return TRUE;
+}
+
+/*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const
+{
+ LLPolyMorphTarget *new_param = new LLPolyMorphTarget(mMesh);
+ *new_param = *this;
+ return new_param;
+}
+
+#if 0 // obsolete
+//-----------------------------------------------------------------------------
+// parseData()
+//-----------------------------------------------------------------------------
+BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node)
+{
+ LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo;
+
+ info->parseXml(node);
+ if (!setInfo(info))
+ {
+ delete info;
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// getVertexDistortion()
+//-----------------------------------------------------------------------------
+LLVector4a LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh)
+{
+ if (!mMorphData || mMesh != mesh) return LLVector4a::getZero();
+
+ for(U32 index = 0; index < mMorphData->mNumIndices; index++)
+ {
+ if (mMorphData->mVertexIndices[index] == (U32)requested_index)
+ {
+ return mMorphData->mCoords[index];
+ }
+ }
+
+ return LLVector4a::getZero();
+}
+
+//-----------------------------------------------------------------------------
+// getFirstDistortion()
+//-----------------------------------------------------------------------------
+const LLVector4a *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh)
+{
+ if (!mMorphData) return &LLVector4a::getZero();
+
+ LLVector4a* resultVec;
+ mMorphData->mCurrentIndex = 0;
+ if (mMorphData->mNumIndices)
+ {
+ resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex];
+ if (index != NULL)
+ {
+ *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex];
+ }
+ if (poly_mesh != NULL)
+ {
+ *poly_mesh = mMesh;
+ }
+
+ return resultVec;
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// getNextDistortion()
+//-----------------------------------------------------------------------------
+const LLVector4a *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh)
+{
+ if (!mMorphData) return &LLVector4a::getZero();
+
+ LLVector4a* resultVec;
+ mMorphData->mCurrentIndex++;
+ if (mMorphData->mCurrentIndex < mMorphData->mNumIndices)
+ {
+ resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex];
+ if (index != NULL)
+ {
+ *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex];
+ }
+ if (poly_mesh != NULL)
+ {
+ *poly_mesh = mMesh;
+ }
+ return resultVec;
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// getTotalDistortion()
+//-----------------------------------------------------------------------------
+F32 LLPolyMorphTarget::getTotalDistortion()
+{
+ if (mMorphData)
+ {
+ return mMorphData->mTotalDistortion;
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// getAvgDistortion()
+//-----------------------------------------------------------------------------
+const LLVector4a& LLPolyMorphTarget::getAvgDistortion()
+{
+ if (mMorphData)
+ {
+ return mMorphData->mAvgDistortion;
+ }
+ else
+ {
+ return LLVector4a::getZero();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// getMaxDistortion()
+//-----------------------------------------------------------------------------
+F32 LLPolyMorphTarget::getMaxDistortion()
+{
+ if (mMorphData)
+ {
+ return mMorphData->mMaxDistortion;
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// apply()
+//-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_APPLY_MORPH_TARGET("Apply Morph");
+
+void LLPolyMorphTarget::apply( ESex avatar_sex )
+{
+ if (!mMorphData || mNumMorphMasksPending > 0)
+ {
+ return;
+ }
+
+ LLFastTimer t(FTM_APPLY_MORPH_TARGET);
+
+ mLastSex = avatar_sex;
+
+ // Check for NaN condition (NaN is detected if a variable doesn't equal itself.
+ if (mCurWeight != mCurWeight)
+ {
+ mCurWeight = 0.0;
+ }
+ if (mLastWeight != mLastWeight)
+ {
+ mLastWeight = mCurWeight+.001;
+ }
+
+ // perform differential update of morph
+ F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight);
+ // store last weight
+ mLastWeight += delta_weight;
+
+ if (delta_weight != 0.f)
+ {
+ llassert(!mMesh->isLOD());
+ LLVector4a *coords = mMesh->getWritableCoords();
+
+ LLVector4a *scaled_normals = mMesh->getScaledNormals();
+ LLVector4a *normals = mMesh->getWritableNormals();
+
+ LLVector4a *scaled_binormals = mMesh->getScaledBinormals();
+ LLVector4a *binormals = mMesh->getWritableBinormals();
+
+ LLVector4a *clothing_weights = mMesh->getWritableClothingWeights();
+ LLVector2 *tex_coords = mMesh->getWritableTexCoords();
+
+ F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL;
+
+ for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++)
+ {
+ S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph];
+
+ F32 maskWeight = 1.f;
+ if (maskWeightArray)
+ {
+ maskWeight = maskWeightArray[vert_index_morph];
+ }
+
+
+ LLVector4a pos = mMorphData->mCoords[vert_index_morph];
+ pos.mul(delta_weight*maskWeight);
+ coords[vert_index_mesh].add(pos);
+
+ if (getInfo()->mIsClothingMorph && clothing_weights)
+ {
+ LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph];
+ clothing_offset.mul(delta_weight * maskWeight);
+ LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh];
+ clothing_weight->add(clothing_offset);
+ clothing_weight->getF32ptr()[VW] = maskWeight;
+ }
+
+ // calculate new normals based on half angles
+ LLVector4a norm = mMorphData->mNormals[vert_index_morph];
+ norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR);
+ scaled_normals[vert_index_mesh].add(norm);
+ norm = scaled_normals[vert_index_mesh];
+ norm.normalize3fast();
+ normals[vert_index_mesh] = norm;
+
+ // calculate new binormals
+ LLVector4a binorm = mMorphData->mBinormals[vert_index_morph];
+ binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR);
+ scaled_binormals[vert_index_mesh].add(binorm);
+ LLVector4a tangent;
+ tangent.setCross3(scaled_binormals[vert_index_mesh], norm);
+ LLVector4a& normalized_binormal = binormals[vert_index_mesh];
+ normalized_binormal.setCross3(norm, tangent);
+ normalized_binormal.normalize3fast();
+
+ tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight;
+ }
+
+ // now apply volume changes
+ for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); iter++ )
+ {
+ LLPolyVolumeMorph* volume_morph = &(*iter);
+ LLVector3 scale_delta = volume_morph->mScale * delta_weight;
+ LLVector3 pos_delta = volume_morph->mPos * delta_weight;
+
+ volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta);
+ volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta);
+ }
+ }
+
+ if (mNext)
+ {
+ mNext->apply(avatar_sex);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// applyMask()
+//-----------------------------------------------------------------------------
+void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert)
+{
+ LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL;
+
+ if (!mVertMask)
+ {
+ mVertMask = new LLPolyVertexMask(mMorphData);
+ mNumMorphMasksPending--;
+ }
+ else
+ {
+ // remove effect of previous mask
+ F32 *maskWeights = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL;
+
+ if (maskWeights)
+ {
+ LLVector4a *coords = mMesh->getWritableCoords();
+ LLVector4a *scaled_normals = mMesh->getScaledNormals();
+ LLVector4a *scaled_binormals = mMesh->getScaledBinormals();
+ LLVector2 *tex_coords = mMesh->getWritableTexCoords();
+
+ LLVector4Logical clothing_mask;
+ clothing_mask.clear();
+ clothing_mask.setElement<0>();
+ clothing_mask.setElement<1>();
+ clothing_mask.setElement<2>();
+
+
+ for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++)
+ {
+ F32 lastMaskWeight = mLastWeight * maskWeights[vert];
+ S32 out_vert = mMorphData->mVertexIndices[vert];
+
+ // remove effect of existing masked morph
+ LLVector4a t;
+ t = mMorphData->mCoords[vert];
+ t.mul(lastMaskWeight);
+ coords[out_vert].sub(t);
+
+ t = mMorphData->mNormals[vert];
+ t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR);
+ scaled_normals[out_vert].sub(t);
+
+ t = mMorphData->mBinormals[vert];
+ t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR);
+ scaled_binormals[out_vert].sub(t);
+
+ tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight;
+
+ if (clothing_weights)
+ {
+ LLVector4a clothing_offset = mMorphData->mCoords[vert];
+ clothing_offset.mul(lastMaskWeight);
+ LLVector4a* clothing_weight = &clothing_weights[out_vert];
+ LLVector4a t;
+ t.setSub(*clothing_weight, clothing_offset);
+ clothing_weight->setSelectWithMask(clothing_mask, t, *clothing_weight);
+ }
+ }
+ }
+ }
+
+ // set last weight to 0, since we've removed the effect of this morph
+ mLastWeight = 0.f;
+
+ mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights);
+
+ apply(mLastSex);
+}
+
+
+//-----------------------------------------------------------------------------
+// LLPolyVertexMask()
+//-----------------------------------------------------------------------------
+LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data)
+{
+ mWeights = new F32[morph_data->mNumIndices];
+ mMorphData = morph_data;
+ mWeightsGenerated = FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// ~LLPolyVertexMask()
+//-----------------------------------------------------------------------------
+LLPolyVertexMask::~LLPolyVertexMask()
+{
+ delete[] mWeights;
+}
+
+//-----------------------------------------------------------------------------
+// generateMask()
+//-----------------------------------------------------------------------------
+void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights)
+{
+// RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/)
+// BOOL debugImg = FALSE;
+// if (debugImg)
+// {
+// if (invert)
+// {
+// imdebug("lum rbga=rgba b=8 w=%d h=%d *-1 %p", width, height, maskTextureData);
+// }
+// else
+// {
+// imdebug("lum rbga=rgba b=8 w=%d h=%d %p", width, height, maskTextureData);
+// }
+// }
+ for (U32 index = 0; index < mMorphData->mNumIndices; index++)
+ {
+ S32 vertIndex = mMorphData->mVertexIndices[index];
+ const S32 *sharedVertIndex = mMorphData->mMesh->getSharedVert(vertIndex);
+ LLVector2 uvCoords;
+
+ if (sharedVertIndex)
+ {
+ uvCoords = mMorphData->mMesh->getUVs(*sharedVertIndex);
+ }
+ else
+ {
+ uvCoords = mMorphData->mMesh->getUVs(vertIndex);
+ }
+ U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1);
+ U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1);
+
+ mWeights[index] = ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f;
+
+ if (invert)
+ {
+ mWeights[index] = 1.f - mWeights[index];
+ }
+
+ // now apply step function
+ // mWeights[index] = mWeights[index] > 0.95f ? 1.f : 0.f;
+
+ if (clothing_weights)
+ {
+ clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index];
+ }
+ }
+ mWeightsGenerated = TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// getMaskForMorphIndex()
+//-----------------------------------------------------------------------------
+F32* LLPolyVertexMask::getMorphMaskWeights()
+{
+ if (!mWeightsGenerated)
+ {
+ return NULL;
+ }
+
+ return mWeights;
+}
diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h
new file mode 100644
index 0000000000..d6cf9e52ca
--- /dev/null
+++ b/indra/llappearance/llpolymorph.h
@@ -0,0 +1,182 @@
+/**
+ * @file llpolymorph.h
+ * @brief Implementation of LLPolyMesh class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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 LL_LLPOLYMORPH_H
+#define LL_LLPOLYMORPH_H
+
+#include <string>
+#include <vector>
+
+#include "llviewervisualparam.h"
+
+class LLAvatarJointCollisionVolume;
+class LLPolyMeshSharedData;
+class LLVector2;
+class LLAvatarJointCollisionVolume;
+class LLWearable;
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphData()
+//-----------------------------------------------------------------------------
+class LLPolyMorphData
+{
+public:
+ LLPolyMorphData(const std::string& morph_name);
+ ~LLPolyMorphData();
+ LLPolyMorphData(const LLPolyMorphData &rhs);
+
+ BOOL loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh);
+ const std::string& getName() { return mName; }
+
+public:
+ std::string mName;
+
+ // morphology
+ U32 mNumIndices;
+ U32* mVertexIndices;
+ U32 mCurrentIndex;
+ LLVector4a* mCoords;
+ LLVector4a* mNormals;
+ LLVector4a* mBinormals;
+ LLVector2* mTexCoords;
+
+ F32 mTotalDistortion; // vertex distortion summed over entire morph
+ F32 mMaxDistortion; // maximum single vertex distortion in a given morph
+ LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph
+ LLPolyMeshSharedData* mMesh;
+};
+
+//-----------------------------------------------------------------------------
+// LLPolyVertexMask()
+//-----------------------------------------------------------------------------
+class LLPolyVertexMask
+{
+public:
+ LLPolyVertexMask(LLPolyMorphData* morph_data);
+ ~LLPolyVertexMask();
+
+ void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights);
+ F32* getMorphMaskWeights();
+
+
+protected:
+ F32* mWeights;
+ LLPolyMorphData *mMorphData;
+ BOOL mWeightsGenerated;
+
+};
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphTarget Data structs
+//-----------------------------------------------------------------------------
+struct LLPolyVolumeMorphInfo
+{
+ LLPolyVolumeMorphInfo(std::string &name, LLVector3 &scale, LLVector3 &pos)
+ : mName(name), mScale(scale), mPos(pos) {};
+
+ std::string mName;
+ LLVector3 mScale;
+ LLVector3 mPos;
+};
+
+struct LLPolyVolumeMorph
+{
+ LLPolyVolumeMorph(LLAvatarJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos)
+ : mVolume(volume), mScale(scale), mPos(pos) {};
+
+ LLAvatarJointCollisionVolume* mVolume;
+ LLVector3 mScale;
+ LLVector3 mPos;
+};
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphTargetInfo
+// Shared information for LLPolyMorphTargets
+//-----------------------------------------------------------------------------
+class LLPolyMorphTargetInfo : public LLViewerVisualParamInfo
+{
+ friend class LLPolyMorphTarget;
+public:
+ LLPolyMorphTargetInfo();
+ /*virtual*/ ~LLPolyMorphTargetInfo() {};
+
+ /*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
+
+protected:
+ std::string mMorphName;
+ BOOL mIsClothingMorph;
+ typedef std::vector<LLPolyVolumeMorphInfo> volume_info_list_t;
+ volume_info_list_t mVolumeInfoList;
+};
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphTarget
+// A set of vertex data associated with morph target.
+// These morph targets must be topologically consistent with a given Polymesh
+// (share face sets)
+//-----------------------------------------------------------------------------
+class LLPolyMorphTarget : public LLViewerVisualParam
+{
+public:
+ LLPolyMorphTarget(LLPolyMesh *poly_mesh);
+ ~LLPolyMorphTarget();
+
+ // Special: These functions are overridden by child classes
+ LLPolyMorphTargetInfo* getInfo() const { return (LLPolyMorphTargetInfo*)mInfo; }
+ // This sets mInfo and calls initialization functions
+ BOOL setInfo(LLPolyMorphTargetInfo *info);
+
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
+
+ // LLVisualParam Virtual functions
+ ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
+ /*virtual*/ void apply( ESex sex );
+
+ // LLViewerVisualParam Virtual functions
+ /*virtual*/ F32 getTotalDistortion();
+ /*virtual*/ const LLVector4a& getAvgDistortion();
+ /*virtual*/ F32 getMaxDistortion();
+ /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh);
+ /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh);
+ /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh);
+
+ void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert);
+ void addPendingMorphMask() { mNumMorphMasksPending++; }
+
+protected:
+ LLPolyMorphData* mMorphData;
+ LLPolyMesh* mMesh;
+ LLPolyVertexMask * mVertMask;
+ ESex mLastSex;
+ // number of morph masks that haven't been generated, must be 0 before this morph is applied
+ BOOL mNumMorphMasksPending;
+
+ typedef std::vector<LLPolyVolumeMorph> volume_list_t;
+ volume_list_t mVolumeMorphs;
+
+};
+
+#endif // LL_LLPOLYMORPH_H
diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp
new file mode 100644
index 0000000000..4ba16691c2
--- /dev/null
+++ b/indra/llappearance/llpolyskeletaldistortion.cpp
@@ -0,0 +1,293 @@
+/**
+ * @file llpolyskeletaldistortion.cpp
+ * @brief Implementation of LLPolySkeletalDistortion classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "llpreprocessor.h"
+#include "llerrorlegacy.h"
+//#include "llcommon.h"
+//#include "llmemory.h"
+#include "llavatarappearance.h"
+#include "llavatarjoint.h"
+#include "llpolymorph.h"
+//#include "llviewercontrol.h"
+//#include "llxmltree.h"
+//#include "llvoavatar.h"
+#include "llwearable.h"
+//#include "lldir.h"
+//#include "llvolume.h"
+//#include "llendianswizzle.h"
+
+#include "llpolyskeletaldistortion.h"
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDistortionInfo()
+//-----------------------------------------------------------------------------
+LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo()
+{
+}
+
+BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node)
+{
+ llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) );
+
+ if (!LLViewerVisualParamInfo::parseXml(node))
+ return FALSE;
+
+ LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton");
+
+ if (NULL == skeletalParam)
+ {
+ llwarns << "Failed to getChildByName(\"param_skeleton\")"
+ << llendl;
+ return FALSE;
+ }
+
+ for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() )
+ {
+ if (bone->hasName("bone"))
+ {
+ std::string name;
+ LLVector3 scale;
+ LLVector3 pos;
+ BOOL haspos = FALSE;
+
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (!bone->getFastAttributeString(name_string, name))
+ {
+ llwarns << "No bone name specified for skeletal param." << llendl;
+ continue;
+ }
+
+ static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
+ if (!bone->getFastAttributeVector3(scale_string, scale))
+ {
+ llwarns << "No scale specified for bone " << name << "." << llendl;
+ continue;
+ }
+
+ // optional offset deformation (translation)
+ static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset");
+ if (bone->getFastAttributeVector3(offset_string, pos))
+ {
+ haspos = TRUE;
+ }
+ mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos));
+ }
+ else
+ {
+ llwarns << "Unrecognized element " << bone->getName() << " in skeletal distortion" << llendl;
+ continue;
+ }
+ }
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDistortion()
+//-----------------------------------------------------------------------------
+LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLAvatarAppearance *avatarp)
+{
+ mAvatar = avatarp;
+ mDefaultVec.splat(0.001f);
+}
+
+//-----------------------------------------------------------------------------
+// ~LLPolySkeletalDistortion()
+//-----------------------------------------------------------------------------
+LLPolySkeletalDistortion::~LLPolySkeletalDistortion()
+{
+}
+
+BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
+{
+ llassert(mInfo == NULL);
+ if (info->mID < 0)
+ return FALSE;
+ mInfo = info;
+ mID = info->mID;
+ setWeight(getDefaultWeight(), FALSE );
+
+ LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
+ for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
+ {
+ LLPolySkeletalBoneInfo *bone_info = &(*iter);
+ LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName);
+ if (!joint)
+ {
+ llwarns << "Joint " << bone_info->mBoneName << " not found." << llendl;
+ continue;
+ }
+
+ if (mJointScales.find(joint) != mJointScales.end())
+ {
+ llwarns << "Scale deformation already supplied for joint " << joint->getName() << "." << llendl;
+ }
+
+ // store it
+ mJointScales[joint] = bone_info->mScaleDeformation;
+
+ // apply to children that need to inherit it
+ for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
+ iter != joint->mChildren.end(); ++iter)
+ {
+ LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
+ if (child_joint->inheritScale())
+ {
+ LLVector3 childDeformation = LLVector3(child_joint->getScale());
+ childDeformation.scaleVec(bone_info->mScaleDeformation);
+ mJointScales[child_joint] = childDeformation;
+ }
+ }
+
+ if (bone_info->mHasPositionDeformation)
+ {
+ if (mJointOffsets.find(joint) != mJointOffsets.end())
+ {
+ llwarns << "Offset deformation already supplied for joint " << joint->getName() << "." << llendl;
+ }
+ mJointOffsets[joint] = bone_info->mPositionDeformation;
+ }
+ }
+ return TRUE;
+}
+
+/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
+{
+ LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar);
+ *new_param = *this;
+ return new_param;
+}
+
+//-----------------------------------------------------------------------------
+// apply()
+//-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion");
+
+void LLPolySkeletalDistortion::apply( ESex avatar_sex )
+{
+ LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY);
+
+ F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
+
+ LLJoint* joint;
+ joint_vec_map_t::iterator iter;
+
+ for (iter = mJointScales.begin();
+ iter != mJointScales.end();
+ iter++)
+ {
+ joint = iter->first;
+ LLVector3 newScale = joint->getScale();
+ LLVector3 scaleDelta = iter->second;
+ newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
+ joint->setScale(newScale);
+ }
+
+ for (iter = mJointOffsets.begin();
+ iter != mJointOffsets.end();
+ iter++)
+ {
+ joint = iter->first;
+ LLVector3 newPosition = joint->getPosition();
+ LLVector3 positionDelta = iter->second;
+ newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
+ joint->setPosition(newPosition);
+ }
+
+ if (mLastWeight != mCurWeight && !mIsAnimating)
+ {
+ mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1);
+ }
+ mLastWeight = mCurWeight;
+}
+
+
+LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data,
+ const std::string &name)
+{
+ LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
+ cloned_morph_data->mName = name;
+ for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
+ {
+ cloned_morph_data->mCoords[v] = src_data->mCoords[v];
+ cloned_morph_data->mNormals[v] = src_data->mNormals[v];
+ cloned_morph_data->mBinormals[v] = src_data->mBinormals[v];
+ }
+ return cloned_morph_data;
+}
+
+LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data,
+ const LLVector3 &direction,
+ const std::string &name)
+{
+ LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
+ cloned_morph_data->mName = name;
+ LLVector4a dir;
+ dir.load3(direction.mV);
+
+ for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
+ {
+ cloned_morph_data->mCoords[v] = dir;
+ cloned_morph_data->mNormals[v].clear();
+ cloned_morph_data->mBinormals[v].clear();
+ }
+ return cloned_morph_data;
+}
+
+LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data,
+ F32 scale,
+ const std::string &name)
+{
+ LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
+ cloned_morph_data->mName = name;
+
+ LLVector4a sc;
+ sc.splat(scale);
+
+ LLVector4a nsc;
+ nsc.set(scale, -scale, scale, scale);
+
+ for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
+ {
+ if (cloned_morph_data->mCoords[v][1] < 0)
+ {
+ cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc);
+ cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc);
+ cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc);
+ }
+ else
+ {
+ cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc);
+ cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc);
+ cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc);
+ }
+ }
+ return cloned_morph_data;
+}
+
+// End
diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h
new file mode 100644
index 0000000000..040cf841ea
--- /dev/null
+++ b/indra/llappearance/llpolyskeletaldistortion.h
@@ -0,0 +1,119 @@
+/**
+ * @file llpolyskeletaldistortion.h
+ * @brief Implementation of LLPolyMesh class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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 LL_LLPOLYSKELETALDISTORTION_H
+#define LL_LLPOLYSKELETALDISTORTION_H
+
+#include "llcommon.h"
+
+#include <string>
+#include <map>
+#include "llstl.h"
+
+#include "v3math.h"
+#include "v2math.h"
+#include "llquaternion.h"
+//#include "llpolymorph.h"
+#include "lljoint.h"
+#include "llviewervisualparam.h"
+//#include "lldarray.h"
+
+//class LLSkinJoint;
+class LLAvatarAppearance;
+
+//#define USE_STRIPS // Use tri-strips for rendering.
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDeformationInfo
+// Shared information for LLPolySkeletalDeformations
+//-----------------------------------------------------------------------------
+struct LLPolySkeletalBoneInfo
+{
+ LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, BOOL haspos)
+ : mBoneName(name),
+ mScaleDeformation(scale),
+ mPositionDeformation(pos),
+ mHasPositionDeformation(haspos) {}
+ std::string mBoneName;
+ LLVector3 mScaleDeformation;
+ LLVector3 mPositionDeformation;
+ BOOL mHasPositionDeformation;
+};
+
+class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo
+{
+ friend class LLPolySkeletalDistortion;
+public:
+ LLPolySkeletalDistortionInfo();
+ /*virtual*/ ~LLPolySkeletalDistortionInfo() {};
+
+ /*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
+
+protected:
+ typedef std::vector<LLPolySkeletalBoneInfo> bone_info_list_t;
+ bone_info_list_t mBoneInfoList;
+};
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDeformation
+// A set of joint scale data for deforming the avatar mesh
+//-----------------------------------------------------------------------------
+class LLPolySkeletalDistortion : public LLViewerVisualParam
+{
+public:
+ LLPolySkeletalDistortion(LLAvatarAppearance *avatarp);
+ ~LLPolySkeletalDistortion();
+
+ // Special: These functions are overridden by child classes
+ LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; }
+ // This sets mInfo and calls initialization functions
+ BOOL setInfo(LLPolySkeletalDistortionInfo *info);
+
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
+
+ // LLVisualParam Virtual functions
+ ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
+ /*virtual*/ void apply( ESex sex );
+
+ // LLViewerVisualParam Virtual functions
+ /*virtual*/ F32 getTotalDistortion() { return 0.1f; }
+ /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; }
+ /*virtual*/ F32 getMaxDistortion() { return 0.1f; }
+ /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);}
+ /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;};
+ /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;};
+
+protected:
+ typedef std::map<LLJoint*, LLVector3> joint_vec_map_t;
+ joint_vec_map_t mJointScales;
+ joint_vec_map_t mJointOffsets;
+ LLVector4a mDefaultVec;
+ // Backlink only; don't make this an LLPointer.
+ LLAvatarAppearance *mAvatar;
+};
+
+#endif // LL_LLPOLYSKELETALDISTORTION_H
+
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 21b1512e58..7942e815ae 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -443,8 +443,6 @@ set(viewer_SOURCE_FILES
llplacesinventorybridge.cpp
llplacesinventorypanel.cpp
llpopupview.cpp
- llpolymesh.cpp
- llpolymorph.cpp
llpostcard.cpp
llpreview.cpp
llpreviewanim.cpp
@@ -1000,8 +998,6 @@ set(viewer_HEADER_FILES
llpipelinelistener.h
llplacesinventorybridge.h
llplacesinventorypanel.h
- llpolymesh.h
- llpolymorph.h
llpopupview.h
llpostcard.h
llpreview.h
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index e1ef0d5399..7f4d33753d 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -1078,8 +1078,8 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y)
if (!isAgentAvatarValid()) return;
- LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot.getWorldRotation();
- LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot.getWorldRotation();
+ LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot->getWorldRotation();
+ LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot->getWorldRotation();
if ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) &&
(root_at * last_at_axis > 0.95f))
@@ -1432,7 +1432,7 @@ void LLAgentCamera::updateCamera()
LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() +
LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation();
LLVector3 diff = mCameraPositionAgent - head_pos;
- diff = diff * ~gAgentAvatarp->mRoot.getWorldRotation();
+ diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation();
LLJoint* torso_joint = gAgentAvatarp->mTorsop;
LLJoint* chest_joint = gAgentAvatarp->mChestp;
@@ -1456,7 +1456,7 @@ void LLAgentCamera::updateCamera()
gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff);
- gAgentAvatarp->mRoot.updateWorldMatrixChildren();
+ gAgentAvatarp->mRoot->updateWorldMatrixChildren();
for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
iter != gAgentAvatarp->mAttachmentPoints.end(); )
@@ -1684,7 +1684,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
F32 camera_land_height;
LLVector3d frame_center_global = !isAgentAvatarValid() ?
gAgent.getPositionGlobal() :
- gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition());
+ gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition());
BOOL isConstrained = FALSE;
LLVector3d head_offset;
diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp
index fa0ad20fdb..ce67c6c65d 100644
--- a/indra/newview/llfloaterbvhpreview.cpp
+++ b/indra/newview/llfloaterbvhpreview.cpp
@@ -1097,12 +1097,12 @@ BOOL LLPreviewAnimation::render()
gGL.flush();
- LLVector3 target_pos = avatarp->mRoot.getWorldPosition();
+ LLVector3 target_pos = avatarp->mRoot->getWorldPosition();
LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) *
LLQuaternion(mCameraYaw, LLVector3::z_axis);
- LLQuaternion av_rot = avatarp->mRoot.getWorldRotation() * camera_rot;
+ LLQuaternion av_rot = avatarp->mRoot->getWorldRotation() * camera_rot;
LLViewerCamera::getInstance()->setOriginAndLookAt(
target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera
LLVector3::z_axis, // up
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index 6b2492d927..887cd2f4b0 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -593,7 +593,7 @@ S8 LLImagePreviewAvatar::getType() const
void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male)
{
- mTargetJoint = mDummyAvatar->mRoot.findJoint(joint_name);
+ mTargetJoint = mDummyAvatar->mRoot->findJoint(joint_name);
// clear out existing test mesh
if (mTargetMesh)
{
@@ -612,9 +612,9 @@ void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const
mDummyAvatar->updateVisualParams();
mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
}
- mDummyAvatar->mRoot.setVisible(FALSE, TRUE);
+ mDummyAvatar->mRoot->setVisible(FALSE, TRUE);
- mTargetMesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name);
+ mTargetMesh = (LLViewerJointMesh*)mDummyAvatar->mRoot->findJoint(mesh_name);
mTargetMesh->setTestTexture(mTextureName);
mTargetMesh->setVisible(TRUE, FALSE);
mCameraDistance = distance;
@@ -631,7 +631,7 @@ void LLImagePreviewAvatar::clearPreviewTexture(const std::string& mesh_name)
{
if (mDummyAvatar)
{
- LLViewerJointMesh *mesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name);
+ LLViewerJointMesh *mesh = (LLViewerJointMesh*)mDummyAvatar->mRoot->findJoint(mesh_name);
// clear out existing test mesh
if (mesh)
{
diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp
index bc3b220dc0..9dde65ceb6 100644
--- a/indra/newview/llhudeffectlookat.cpp
+++ b/indra/newview/llhudeffectlookat.cpp
@@ -636,7 +636,7 @@ bool LLHUDEffectLookAt::calcTargetPosition()
}
else
{
- target_rot = target_av->mRoot.getWorldRotation();
+ target_rot = target_av->mRoot->getWorldRotation();
}
}
else // target obj is not an avatar
diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h
index 46e23b7792..28d7755d4d 100644
--- a/indra/newview/llpolymorph.h
+++ b/indra/newview/llpolymorph.h
@@ -35,7 +35,7 @@
class LLPolyMeshSharedData;
class LLVOAvatar;
class LLVector2;
-class LLViewerJointCollisionVolume;
+class LLAvatarJointCollisionVolume;
class LLWearable;
//-----------------------------------------------------------------------------
@@ -104,10 +104,10 @@ struct LLPolyVolumeMorphInfo
struct LLPolyVolumeMorph
{
- LLPolyVolumeMorph(LLViewerJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos)
+ LLPolyVolumeMorph(LLAvatarJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos)
: mVolume(volume), mScale(scale), mPos(pos) {};
- LLViewerJointCollisionVolume* mVolume;
+ LLAvatarJointCollisionVolume* mVolume;
LLVector3 mScale;
LLVector3 mPos;
};
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index c804898cc3..fadaaf4541 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -4028,7 +4028,7 @@ void renderAgentTarget(LLVOAvatar* avatar)
{
renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f));
renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f));
- renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f));
+ renderCrossHairs(avatar->mRoot->getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f));
renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f));
}
}
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 6782e3ef8a..ab06b1f5aa 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1247,6 +1247,9 @@ bool idle_startup()
LLPostProcess::initClass();
display_startup();
+ LLAvatarAppearance::initClass();
+ display_startup();
+
LLViewerObject::initVOClasses();
display_startup();
diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp
index a907f102f8..bb45cf89fc 100644
--- a/indra/newview/llviewerjoint.cpp
+++ b/indra/newview/llviewerjoint.cpp
@@ -53,7 +53,7 @@ BOOL LLViewerJoint::sDisableLOD = FALSE;
// Class Constructor
//-----------------------------------------------------------------------------
LLViewerJoint::LLViewerJoint()
- : LLJoint()
+ : LLAvatarJoint()
{
init();
}
@@ -64,7 +64,7 @@ LLViewerJoint::LLViewerJoint()
// Class Constructor
//-----------------------------------------------------------------------------
LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent)
- : LLJoint(name, parent)
+ : LLAvatarJoint(name, parent)
{
init();
}
@@ -91,31 +91,6 @@ LLViewerJoint::~LLViewerJoint()
//--------------------------------------------------------------------
-// setValid()
-//--------------------------------------------------------------------
-void LLViewerJoint::setValid( BOOL valid, BOOL recursive )
-{
- //----------------------------------------------------------------
- // set visibility for this joint
- //----------------------------------------------------------------
- mValid = valid;
-
- //----------------------------------------------------------------
- // set visibility for children
- //----------------------------------------------------------------
- if (recursive)
- {
- for (child_list_t::iterator iter = mChildren.begin();
- iter != mChildren.end(); ++iter)
- {
- LLViewerJoint* joint = (LLViewerJoint*)(*iter);
- joint->setValid(valid, TRUE);
- }
- }
-
-}
-
-//--------------------------------------------------------------------
// renderSkeleton()
// DEBUG (UNUSED)
//--------------------------------------------------------------------
@@ -522,98 +497,6 @@ void LLViewerJoint::setMeshesToChildren()
addChild((LLViewerJointMesh *) *iter);
}
}
-//-----------------------------------------------------------------------------
-// LLViewerJointCollisionVolume()
-//-----------------------------------------------------------------------------
-
-LLViewerJointCollisionVolume::LLViewerJointCollisionVolume()
-{
- mUpdateXform = FALSE;
-}
-LLViewerJointCollisionVolume::LLViewerJointCollisionVolume(const std::string &name, LLJoint *parent) : LLViewerJoint(name, parent)
-{
-
-}
-
-void LLViewerJointCollisionVolume::renderCollision()
-{
- updateWorldMatrix();
-
- gGL.pushMatrix();
- gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] );
-
- gGL.diffuseColor3f( 0.f, 0.f, 1.f );
-
- gGL.begin(LLRender::LINES);
-
- LLVector3 v[] =
- {
- LLVector3(1,0,0),
- LLVector3(-1,0,0),
- LLVector3(0,1,0),
- LLVector3(0,-1,0),
-
- LLVector3(0,0,-1),
- LLVector3(0,0,1),
- };
-
- //sides
- gGL.vertex3fv(v[0].mV);
- gGL.vertex3fv(v[2].mV);
-
- gGL.vertex3fv(v[0].mV);
- gGL.vertex3fv(v[3].mV);
-
- gGL.vertex3fv(v[1].mV);
- gGL.vertex3fv(v[2].mV);
-
- gGL.vertex3fv(v[1].mV);
- gGL.vertex3fv(v[3].mV);
-
-
- //top
- gGL.vertex3fv(v[0].mV);
- gGL.vertex3fv(v[4].mV);
-
- gGL.vertex3fv(v[1].mV);
- gGL.vertex3fv(v[4].mV);
-
- gGL.vertex3fv(v[2].mV);
- gGL.vertex3fv(v[4].mV);
-
- gGL.vertex3fv(v[3].mV);
- gGL.vertex3fv(v[4].mV);
-
-
- //bottom
- gGL.vertex3fv(v[0].mV);
- gGL.vertex3fv(v[5].mV);
-
- gGL.vertex3fv(v[1].mV);
- gGL.vertex3fv(v[5].mV);
-
- gGL.vertex3fv(v[2].mV);
- gGL.vertex3fv(v[5].mV);
-
- gGL.vertex3fv(v[3].mV);
- gGL.vertex3fv(v[5].mV);
-
- gGL.end();
-
- gGL.popMatrix();
-}
-
-LLVector3 LLViewerJointCollisionVolume::getVolumePos(LLVector3 &offset)
-{
- mUpdateXform = TRUE;
-
- LLVector3 result = offset;
- result.scaleVec(getScale());
- result.rotVec(getWorldRotation());
- result += getWorldPosition();
-
- return result;
-}
// End
diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h
index 531c0f765c..37c80dafeb 100644
--- a/indra/newview/llviewerjoint.h
+++ b/indra/newview/llviewerjoint.h
@@ -30,7 +30,7 @@
//-----------------------------------------------------------------------------
// Header Files
//-----------------------------------------------------------------------------
-#include "lljoint.h"
+#include "llavatarjoint.h"
#include "lljointpickname.h"
class LLFace;
@@ -40,7 +40,7 @@ class LLViewerJointMesh;
// class LLViewerJoint
//-----------------------------------------------------------------------------
class LLViewerJoint :
- public LLJoint
+ public LLAvatarJoint
{
public:
LLViewerJoint();
@@ -50,9 +50,6 @@ public:
// Gets the validity of this joint
BOOL getValid() { return mValid; }
- // Sets the validity of this joint
- virtual void setValid( BOOL valid, BOOL recursive=FALSE );
-
// Primarily for debugging and character setup
// Derived classes may add text/graphic output.
// Draw skeleton graphic for debugging and character setup
@@ -134,19 +131,6 @@ protected:
S32 mMeshID;
};
-class LLViewerJointCollisionVolume : public LLViewerJoint
-{
-public:
- LLViewerJointCollisionVolume();
- LLViewerJointCollisionVolume(const std::string &name, LLJoint *parent = NULL);
- virtual ~LLViewerJointCollisionVolume() {};
-
- virtual BOOL inheritScale() { return TRUE; }
-
- void renderCollision();
- LLVector3 getVolumePos(LLVector3 &offset);
-};
-
#endif // LL_LLVIEWERJOINT_H
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 3532fac1bc..8d479ab0bf 100755
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -67,101 +67,20 @@ static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_NORMAL |
LLVertexBuffer::MAP_TEXCOORD0;
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// LLViewerJointMesh::LLSkinJoint
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// LLSkinJoint
-//-----------------------------------------------------------------------------
-LLSkinJoint::LLSkinJoint()
-{
- mJoint = NULL;
-}
-
-//-----------------------------------------------------------------------------
-// ~LLSkinJoint
-//-----------------------------------------------------------------------------
-LLSkinJoint::~LLSkinJoint()
-{
- mJoint = NULL;
-}
-
-
-//-----------------------------------------------------------------------------
-// LLSkinJoint::setupSkinJoint()
-//-----------------------------------------------------------------------------
-BOOL LLSkinJoint::setupSkinJoint( LLViewerJoint *joint)
-{
- // find the named joint
- mJoint = joint;
- if ( !mJoint )
- {
- llinfos << "Can't find joint" << llendl;
- }
-
- // compute the inverse root skin matrix
- mRootToJointSkinOffset.clearVec();
-
- LLVector3 rootSkinOffset;
- while (joint)
- {
- rootSkinOffset += joint->getSkinOffset();
- joint = (LLViewerJoint*)joint->getParent();
- }
-
- mRootToJointSkinOffset = -rootSkinOffset;
- mRootToParentJointSkinOffset = mRootToJointSkinOffset;
- mRootToParentJointSkinOffset += mJoint->getSkinOffset();
-
- return TRUE;
-}
-
-
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLViewerJointMesh
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
-BOOL LLViewerJointMesh::sPipelineRender = FALSE;
-EAvatarRenderPass LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE;
-U32 LLViewerJointMesh::sClothingMaskImageName = 0;
-LLColor4 LLViewerJointMesh::sClothingInnerColor;
//-----------------------------------------------------------------------------
// LLViewerJointMesh()
//-----------------------------------------------------------------------------
LLViewerJointMesh::LLViewerJointMesh()
:
- mTexture( NULL ),
- mLayerSet( NULL ),
- mTestImageName( 0 ),
- mFaceIndexCount(0),
- mIsTransparent(FALSE)
+ LLAvatarJointMesh()
{
-
- mColor[0] = 1.0f;
- mColor[1] = 1.0f;
- mColor[2] = 1.0f;
- mColor[3] = 1.0f;
- mShiny = 0.0f;
- mCullBackFaces = TRUE;
-
- mMesh = NULL;
-
- mNumSkinJoints = 0;
- mSkinJoints = NULL;
-
- mFace = NULL;
-
- mMeshID = 0;
- mUpdateXform = FALSE;
-
- mValid = FALSE;
}
@@ -171,199 +90,6 @@ LLViewerJointMesh::LLViewerJointMesh()
//-----------------------------------------------------------------------------
LLViewerJointMesh::~LLViewerJointMesh()
{
- mMesh = NULL;
- mTexture = NULL;
- freeSkinData();
-}
-
-
-//-----------------------------------------------------------------------------
-// LLViewerJointMesh::allocateSkinData()
-//-----------------------------------------------------------------------------
-BOOL LLViewerJointMesh::allocateSkinData( U32 numSkinJoints )
-{
- mSkinJoints = new LLSkinJoint[ numSkinJoints ];
- mNumSkinJoints = numSkinJoints;
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// LLViewerJointMesh::freeSkinData()
-//-----------------------------------------------------------------------------
-void LLViewerJointMesh::freeSkinData()
-{
- mNumSkinJoints = 0;
- delete [] mSkinJoints;
- mSkinJoints = NULL;
-}
-
-//--------------------------------------------------------------------
-// LLViewerJointMesh::getColor()
-//--------------------------------------------------------------------
-void LLViewerJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha )
-{
- *red = mColor[0];
- *green = mColor[1];
- *blue = mColor[2];
- *alpha = mColor[3];
-}
-
-//--------------------------------------------------------------------
-// LLViewerJointMesh::setColor()
-//--------------------------------------------------------------------
-void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha )
-{
- mColor[0] = red;
- mColor[1] = green;
- mColor[2] = blue;
- mColor[3] = alpha;
-}
-
-
-//--------------------------------------------------------------------
-// LLViewerJointMesh::getTexture()
-//--------------------------------------------------------------------
-//LLViewerTexture *LLViewerJointMesh::getTexture()
-//{
-// return mTexture;
-//}
-
-//--------------------------------------------------------------------
-// LLViewerJointMesh::setTexture()
-//--------------------------------------------------------------------
-void LLViewerJointMesh::setTexture( LLViewerTexture *texture )
-{
- mTexture = texture;
-
- // texture and dynamic_texture are mutually exclusive
- if( texture )
- {
- mLayerSet = NULL;
- //texture->bindTexture(0);
- //texture->setClamp(TRUE, TRUE);
- }
-}
-
-//--------------------------------------------------------------------
-// LLViewerJointMesh::setLayerSet()
-// Sets the shape texture (takes precedence over normal texture)
-//--------------------------------------------------------------------
-void LLViewerJointMesh::setLayerSet( LLViewerTexLayerSet* layer_set )
-{
- mLayerSet = layer_set;
-
- // texture and dynamic_texture are mutually exclusive
- if( layer_set )
- {
- mTexture = NULL;
- }
-}
-
-
-
-//--------------------------------------------------------------------
-// LLViewerJointMesh::getMesh()
-//--------------------------------------------------------------------
-LLPolyMesh *LLViewerJointMesh::getMesh()
-{
- return mMesh;
-}
-
-//-----------------------------------------------------------------------------
-// LLViewerJointMesh::setMesh()
-//-----------------------------------------------------------------------------
-void LLViewerJointMesh::setMesh( LLPolyMesh *mesh )
-{
- // set the mesh pointer
- mMesh = mesh;
-
- // release any existing skin joints
- freeSkinData();
-
- if ( mMesh == NULL )
- {
- return;
- }
-
- // acquire the transform from the mesh object
- setPosition( mMesh->getPosition() );
- setRotation( mMesh->getRotation() );
- setScale( mMesh->getScale() );
-
- // create skin joints if necessary
- if ( mMesh->hasWeights() && !mMesh->isLOD())
- {
- U32 numJointNames = mMesh->getNumJointNames();
-
- allocateSkinData( numJointNames );
- std::string *jointNames = mMesh->getJointNames();
-
- U32 jn;
- for (jn = 0; jn < numJointNames; jn++)
- {
- //llinfos << "Setting up joint " << jointNames[jn] << llendl;
- LLViewerJoint* joint = (LLViewerJoint*)(getRoot()->findJoint(jointNames[jn]) );
- mSkinJoints[jn].setupSkinJoint( joint );
- }
- }
-
- // setup joint array
- if (!mMesh->isLOD())
- {
- setupJoint((LLViewerJoint*)getRoot());
- }
-
-// llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl;
-}
-
-//-----------------------------------------------------------------------------
-// setupJoint()
-//-----------------------------------------------------------------------------
-void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint)
-{
-// llinfos << "Mesh: " << getName() << llendl;
-
-// S32 joint_count = 0;
- U32 sj;
- for (sj=0; sj<mNumSkinJoints; sj++)
- {
- LLSkinJoint &js = mSkinJoints[sj];
-
- if (js.mJoint != current_joint)
- {
- continue;
- }
-
- // we've found a skinjoint for this joint..
-
- // is the last joint in the array our parent?
- if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == &current_joint->getParent()->getWorldMatrix())
- {
- // ...then just add ourselves
- LLViewerJoint* jointp = js.mJoint;
- mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
-// llinfos << "joint " << joint_count << js.mJoint->getName() << llendl;
-// joint_count++;
- }
- // otherwise add our parent and ourselves
- else
- {
- mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getParent()->getWorldMatrix(), NULL));
-// llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl;
-// joint_count++;
- mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getWorldMatrix(), &js));
-// llinfos << "joint " << joint_count << current_joint->getName() << llendl;
-// joint_count++;
- }
- }
-
- // depth-first traversal
- for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
- iter != current_joint->mChildren.end(); ++iter)
- {
- LLViewerJoint* child_joint = (LLViewerJoint*)(*iter);
- setupJoint(child_joint);
- }
}
const S32 NUM_AXES = 3;
@@ -544,6 +270,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive
LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP;
+ LLViewerTexLayerSet *layerset = dynamic_cast<LLViewerTexLayerSet*>(mLayerSet);
if (mTestImageName)
{
gGL.getTexUnit(diffuse_channel)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName);
@@ -558,11 +285,11 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
}
}
- else if( !is_dummy && mLayerSet )
+ else if( !is_dummy && layerset )
{
- if( mLayerSet->hasComposite() )
+ if( layerset->hasComposite() )
{
- gGL.getTexUnit(diffuse_channel)->bind(mLayerSet->getViewerComposite());
+ gGL.getTexUnit(diffuse_channel)->bind(layerset->getViewerComposite());
}
else
{
diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h
index ff6bed4f0f..039175830f 100755
--- a/indra/newview/llviewerjointmesh.h
+++ b/indra/newview/llviewerjointmesh.h
@@ -29,6 +29,7 @@
#include "llviewerjoint.h"
#include "llviewertexture.h"
+#include "llavatarjointmesh.h"
#include "llpolymesh.h"
#include "v4color.h"
@@ -37,56 +38,12 @@ class LLFace;
class LLCharacter;
class LLViewerTexLayerSet;
-typedef enum e_avatar_render_pass
-{
- AVATAR_RENDER_PASS_SINGLE,
- AVATAR_RENDER_PASS_CLOTHING_INNER,
- AVATAR_RENDER_PASS_CLOTHING_OUTER
-} EAvatarRenderPass;
-
-class LLSkinJoint
-{
-public:
- LLSkinJoint();
- ~LLSkinJoint();
- BOOL setupSkinJoint( LLViewerJoint *joint);
-
- LLViewerJoint *mJoint;
- LLVector3 mRootToJointSkinOffset;
- LLVector3 mRootToParentJointSkinOffset;
-};
-
//-----------------------------------------------------------------------------
// class LLViewerJointMesh
//-----------------------------------------------------------------------------
-class LLViewerJointMesh : public LLViewerJoint
+class LLViewerJointMesh : public LLAvatarJointMesh
{
friend class LLVOAvatar;
-protected:
- LLColor4 mColor; // color value
-// LLColor4 mSpecular; // specular color (always white for now)
- F32 mShiny; // shiny value
- LLPointer<LLViewerTexture> mTexture; // ptr to a global texture
- LLViewerTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar
- U32 mTestImageName; // handle to a temporary texture for previewing uploads
- LLPolyMesh* mMesh; // ptr to a global polymesh
- BOOL mCullBackFaces; // true by default
- LLFace* mFace; // ptr to a face w/ AGP copy of mesh
-
- U32 mFaceIndexCount;
- BOOL mIsTransparent;
-
- U32 mNumSkinJoints;
- LLSkinJoint* mSkinJoints;
- S32 mMeshID;
-
-public:
- static BOOL sPipelineRender;
- //RN: this is here for testing purposes
- static U32 sClothingMaskImageName;
- static EAvatarRenderPass sRenderPass;
- static LLColor4 sClothingInnerColor;
-
public:
// Constructor
LLViewerJointMesh();
@@ -94,41 +51,9 @@ public:
// Destructor
virtual ~LLViewerJointMesh();
- // Gets the shape color
- void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha );
-
- // Sets the shape color
- void setColor( F32 red, F32 green, F32 blue, F32 alpha );
-
- // Sets the shininess
- void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; };
-
- // Sets the shape texture
- void setTexture( LLViewerTexture *texture );
-
- void setTestTexture( U32 name ) { mTestImageName = name; }
-
- // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture)
- void setLayerSet( LLViewerTexLayerSet* layer_set );
-
- // Gets the poly mesh
- LLPolyMesh *getMesh();
-
- // Sets the poly mesh
- void setMesh( LLPolyMesh *mesh );
-
- // Sets up joint matrix data for rendering
- void setupJoint(LLViewerJoint* current_joint);
-
// Render time method to upload batches of joint matrices
void uploadJointMatrices();
- // Sets ID for picking
- void setMeshID( S32 id ) {mMeshID = id;}
-
- // Gets ID for picking
- S32 getMeshID() { return mMeshID; }
-
// overloaded from base class
/*virtual*/ void drawBone();
/*virtual*/ BOOL isTransparent();
@@ -148,13 +73,6 @@ private:
//copy mesh into given face's vertex buffer, applying current animation pose
static void updateGeometry(LLFace* face, LLPolyMesh* mesh);
-
-private:
- // Allocate skin data
- BOOL allocateSkinData( U32 numSkinJoints );
-
- // Free skin data
- void freeSkinData();
};
#endif // LL_LLVIEWERJOINTMESH_H
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index d5ca01931f..8fc5a3f277 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -382,7 +382,7 @@ public:
if (isAgentAvatarValid())
{
- tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition());
+ tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition());
agent_root_center_text = llformat("AgentRootCenter %f %f %f",
(F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
}
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index f6cac6d2d6..f0f469e959 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -139,7 +139,6 @@ const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df44
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
-const std::string AVATAR_DEFAULT_CHAR = "avatar";
const S32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024;
const F32 SHADOW_OFFSET_AMT = 0.03f;
@@ -220,58 +219,6 @@ struct LLTextureMaskData
**
**/
-//------------------------------------------------------------------------
-// LLVOBoneInfo
-// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton.
-//------------------------------------------------------------------------
-class LLVOAvatarBoneInfo
-{
- friend class LLVOAvatar;
- friend class LLVOAvatarSkeletonInfo;
-public:
- LLVOAvatarBoneInfo() : mIsJoint(FALSE) {}
- ~LLVOAvatarBoneInfo()
- {
- std::for_each(mChildList.begin(), mChildList.end(), DeletePointer());
- }
- BOOL parseXml(LLXmlTreeNode* node);
-
-private:
- std::string mName;
- BOOL mIsJoint;
- LLVector3 mPos;
- LLVector3 mRot;
- LLVector3 mScale;
- LLVector3 mPivot;
- typedef std::vector<LLVOAvatarBoneInfo*> child_list_t;
- child_list_t mChildList;
-};
-
-//------------------------------------------------------------------------
-// LLVOAvatarSkeletonInfo
-// Overall avatar skeleton
-//------------------------------------------------------------------------
-class LLVOAvatarSkeletonInfo
-{
- friend class LLVOAvatar;
-public:
- LLVOAvatarSkeletonInfo() :
- mNumBones(0), mNumCollisionVolumes(0) {}
- ~LLVOAvatarSkeletonInfo()
- {
- std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer());
- }
- BOOL parseXml(LLXmlTreeNode* node);
- S32 getNumBones() const { return mNumBones; }
- S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; }
-
-private:
- S32 mNumBones;
- S32 mNumCollisionVolumes;
- typedef std::vector<LLVOAvatarBoneInfo*> bone_info_list_t;
- bone_info_list_t mBoneInfoList;
-};
-
//-----------------------------------------------------------------------------
// class LLBodyNoiseMotion
//-----------------------------------------------------------------------------
@@ -593,10 +540,6 @@ private:
//-----------------------------------------------------------------------------
// Static Data
//-----------------------------------------------------------------------------
-LLXmlTree LLVOAvatar::sXMLTree;
-LLXmlTree LLVOAvatar::sSkeletonXMLTree;
-LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL;
-LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL;
LLAvatarAppearanceDictionary *LLVOAvatar::sAvatarDictionary = NULL;
S32 LLVOAvatar::sFreezeCounter = 0;
U32 LLVOAvatar::sMaxVisible = 12;
@@ -650,9 +593,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mAttachmentGeometryBytes(0),
mAttachmentSurfaceArea(0.f),
mTurning(FALSE),
- mPelvisToFoot(0.f),
mLastSkeletonSerialNum( 0 ),
- mHeadOffset(),
mIsSitting(FALSE),
mTimeVisible(),
mTyping(FALSE),
@@ -707,13 +648,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mMeshTexturesDirty = FALSE;
mHeadp = NULL;
- mIsBuilt = FALSE;
-
- mNumJoints = 0;
- mSkeleton = NULL;
-
- mNumCollisionVolumes = 0;
- mCollisionVolumes = NULL;
// set up animation variables
mSpeed = 0.f;
@@ -802,35 +736,9 @@ LLVOAvatar::~LLVOAvatar()
lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl;
- mRoot.removeAllChildren();
- mJointMap.clear();
-
- deleteAndClearArray(mSkeleton);
- deleteAndClearArray(mCollisionVolumes);
-
- mNumJoints = 0;
-
std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer());
mAttachmentPoints.clear();
- deleteAndClear(mTexSkinColor);
- deleteAndClear(mTexHairColor);
- deleteAndClear(mTexEyeColor);
-
- std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer());
- mMeshes.clear();
-
- for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin();
- jointIter != mMeshLOD.end();
- ++jointIter)
- {
- LLViewerJoint* joint = (LLViewerJoint *) *jointIter;
- std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer());
- joint->mMeshParts.clear();
- }
- std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer());
- mMeshLOD.clear();
-
mDead = TRUE;
mAnimationSources.clear();
@@ -1127,109 +1035,6 @@ void LLVOAvatar::deleteCachedImages(bool clearAll)
//------------------------------------------------------------------------
void LLVOAvatar::initClass()
{
- std::string xmlFile;
-
- xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml";
- BOOL success = sXMLTree.parseFile( xmlFile, FALSE );
- if (!success)
- {
- llerrs << "Problem reading avatar configuration file:" << xmlFile << llendl;
- }
-
- // now sanity check xml file
- LLXmlTreeNode* root = sXMLTree.getRoot();
- if (!root)
- {
- llerrs << "No root node found in avatar configuration file: " << xmlFile << llendl;
- return;
- }
-
- //-------------------------------------------------------------------------
- // <linden_avatar version="1.0"> (root)
- //-------------------------------------------------------------------------
- if( !root->hasName( "linden_avatar" ) )
- {
- llerrs << "Invalid avatar file header: " << xmlFile << llendl;
- }
-
- std::string version;
- static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version");
- if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") )
- {
- llerrs << "Invalid avatar file version: " << version << " in file: " << xmlFile << llendl;
- }
-
- S32 wearable_def_version = 1;
- static LLStdStringHandle wearable_definition_version_string = LLXmlTree::addAttributeString("wearable_definition_version");
- root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version );
- LLWearable::setCurrentDefinitionVersion( wearable_def_version );
-
- std::string mesh_file_name;
-
- LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" );
- if (!skeleton_node)
- {
- llerrs << "No skeleton in avatar configuration file: " << xmlFile << llendl;
- 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))
- {
- llerrs << "No file name in skeleton node in avatar config file: " << xmlFile << llendl;
- }
-
- std::string skeleton_path;
- skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name);
- if (!parseSkeletonFile(skeleton_path))
- {
- llerrs << "Error parsing skeleton file: " << skeleton_path << llendl;
- }
-
- // Process XML data
-
- // avatar_skeleton.xml
- if (sAvatarSkeletonInfo)
- { //this can happen if a login attempt failed
- delete sAvatarSkeletonInfo;
- }
- sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo;
- if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot()))
- {
- llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl;
- }
- // parse avatar_lad.xml
- if (sAvatarXmlInfo)
- { //this can happen if a login attempt failed
- deleteAndClear(sAvatarXmlInfo);
- }
- sAvatarXmlInfo = new LLVOAvatarXmlInfo;
- if (!sAvatarXmlInfo->parseXmlSkeletonNode(root))
- {
- llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
- }
- if (!sAvatarXmlInfo->parseXmlMeshNodes(root))
- {
- llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
- }
- if (!sAvatarXmlInfo->parseXmlColorNodes(root))
- {
- llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
- }
- if (!sAvatarXmlInfo->parseXmlLayerNodes(root))
- {
- llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
- }
- if (!sAvatarXmlInfo->parseXmlDriverNodes(root))
- {
- llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
- }
- if (!sAvatarXmlInfo->parseXmlMorphNodes(root))
- {
- llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
- }
-
gAnimLibrary.animStateSetString(ANIM_AGENT_BODY_NOISE,"body_noise");
gAnimLibrary.animStateSetString(ANIM_AGENT_BREATHE_ROT,"breathe_rot");
gAnimLibrary.animStateSetString(ANIM_AGENT_PHYSICS_MOTION,"physics_motion");
@@ -1256,7 +1061,12 @@ void LLVOAvatar::initInstance(void)
//-------------------------------------------------------------------------
// initialize joint, mesh and shape members
//-------------------------------------------------------------------------
- mRoot.setName( "mRoot" );
+ if (mRoot)
+ {
+ delete mRoot;
+ }
+ mRoot = new LLViewerJoint();
+ mRoot->setName( "mRoot" );
for (LLAvatarAppearanceDictionary::Meshes::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin();
iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end();
@@ -1314,7 +1124,7 @@ void LLVOAvatar::initInstance(void)
// Skip it if there's no associated baked texture.
if (baked_texture_index == BAKED_NUM_INDICES) continue;
- for (std::vector<LLViewerJointMesh* >::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin();
+ for (std::vector<LLAvatarJointMesh* >::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin();
iter != mMeshLOD[mesh_index]->mMeshParts.end();
++iter)
{
@@ -1707,160 +1517,6 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector
return hit;
}
-//-----------------------------------------------------------------------------
-// parseSkeletonFile()
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)
-{
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- //-------------------------------------------------------------------------
- // parse the file
- //-------------------------------------------------------------------------
- BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE );
-
- if (!parsesuccess)
- {
- llerrs << "Can't parse skeleton file: " << filename << llendl;
- return FALSE;
- }
-
- // now sanity check xml file
- LLXmlTreeNode* root = sSkeletonXMLTree.getRoot();
- if (!root)
- {
- llerrs << "No root node found in avatar skeleton file: " << filename << llendl;
- return FALSE;
- }
-
- if( !root->hasName( "linden_skeleton" ) )
- {
- llerrs << "Invalid avatar skeleton file header: " << filename << llendl;
- return FALSE;
- }
-
- std::string version;
- static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version");
- if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") )
- {
- llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl;
- return FALSE;
- }
-
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// setupBone()
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num)
-{
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- LLViewerJoint* joint = NULL;
-
- if (info->mIsJoint)
- {
- joint = (LLViewerJoint*)getCharacterJoint(joint_num);
- if (!joint)
- {
- llwarns << "Too many bones" << llendl;
- return FALSE;
- }
- joint->setName( info->mName );
- }
- else // collision volume
- {
- if (volume_num >= (S32)mNumCollisionVolumes)
- {
- llwarns << "Too many bones" << llendl;
- return FALSE;
- }
- joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]);
- joint->setName( info->mName );
- }
-
- // add to parent
- if (parent)
- {
- parent->addChild( joint );
- }
-
- joint->setPosition(info->mPos);
- joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY],
- info->mRot.mV[VZ], LLQuaternion::XYZ));
- joint->setScale(info->mScale);
-
- joint->setDefaultFromCurrentXform();
-
- if (info->mIsJoint)
- {
- joint->setSkinOffset( info->mPivot );
- joint_num++;
- }
- else // collision volume
- {
- volume_num++;
- }
-
- // setup children
- LLVOAvatarBoneInfo::child_list_t::const_iterator iter;
- for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter)
- {
- LLVOAvatarBoneInfo *child_info = *iter;
- if (!setupBone(child_info, joint, volume_num, joint_num))
- {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// buildSkeleton()
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)
-{
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- //-------------------------------------------------------------------------
- // allocate joints
- //-------------------------------------------------------------------------
- if (!allocateCharacterJoints(info->mNumBones))
- {
- llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl;
- return FALSE;
- }
-
- //-------------------------------------------------------------------------
- // allocate volumes
- //-------------------------------------------------------------------------
- if (info->mNumCollisionVolumes)
- {
- if (!allocateCollisionVolumes(info->mNumCollisionVolumes))
- {
- llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl;
- return FALSE;
- }
- }
-
- S32 current_joint_num = 0;
- S32 current_volume_num = 0;
- LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter;
- for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter)
- {
- LLVOAvatarBoneInfo *info = *iter;
- if (!setupBone(info, NULL, current_volume_num, current_joint_num))
- {
- llerrs << "Error parsing bone in skeleton file" << llendl;
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
LLVOAvatar* LLVOAvatar::asAvatar()
{
return this;
@@ -1892,27 +1548,13 @@ void LLVOAvatar::startDefaultMotions()
// LLVOAvatar::buildCharacter()
// Deferred initialization and rebuild of the avatar.
//-----------------------------------------------------------------------------
+// virtual
void LLVOAvatar::buildCharacter()
{
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- //-------------------------------------------------------------------------
- // remove all references to our existing skeleton
- // so we can rebuild it
- //-------------------------------------------------------------------------
- flushAllMotions();
-
- //-------------------------------------------------------------------------
- // remove all of mRoot's children
- //-------------------------------------------------------------------------
- mRoot.removeAllChildren();
- mJointMap.clear();
- mIsBuilt = FALSE;
-
//-------------------------------------------------------------------------
// clear mesh data
//-------------------------------------------------------------------------
- for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin();
+ for (std::vector<LLAvatarJoint*>::iterator jointIter = mMeshLOD.begin();
jointIter != mMeshLOD.end(); ++jointIter)
{
LLViewerJoint* joint = (LLViewerJoint*) *jointIter;
@@ -1924,84 +1566,9 @@ void LLVOAvatar::buildCharacter()
}
}
- //-------------------------------------------------------------------------
- // (re)load our skeleton and meshes
- //-------------------------------------------------------------------------
- LLTimer timer;
-
- BOOL status = loadAvatar();
- stop_glerror();
-
-// gPrintMessagesThisFrame = TRUE;
- lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl;
-
- if (!status)
- {
- if (isSelf())
- {
- llerrs << "Unable to load user's avatar" << llendl;
- }
- else
- {
- llwarns << "Unable to load other's avatar" << llendl;
- }
- return;
- }
-
- //-------------------------------------------------------------------------
- // initialize "well known" joint pointers
- //-------------------------------------------------------------------------
- mPelvisp = (LLViewerJoint*)mRoot.findJoint("mPelvis");
- mTorsop = (LLViewerJoint*)mRoot.findJoint("mTorso");
- mChestp = (LLViewerJoint*)mRoot.findJoint("mChest");
- mNeckp = (LLViewerJoint*)mRoot.findJoint("mNeck");
- mHeadp = (LLViewerJoint*)mRoot.findJoint("mHead");
- mSkullp = (LLViewerJoint*)mRoot.findJoint("mSkull");
- mHipLeftp = (LLViewerJoint*)mRoot.findJoint("mHipLeft");
- mHipRightp = (LLViewerJoint*)mRoot.findJoint("mHipRight");
- mKneeLeftp = (LLViewerJoint*)mRoot.findJoint("mKneeLeft");
- mKneeRightp = (LLViewerJoint*)mRoot.findJoint("mKneeRight");
- mAnkleLeftp = (LLViewerJoint*)mRoot.findJoint("mAnkleLeft");
- mAnkleRightp = (LLViewerJoint*)mRoot.findJoint("mAnkleRight");
- mFootLeftp = (LLViewerJoint*)mRoot.findJoint("mFootLeft");
- mFootRightp = (LLViewerJoint*)mRoot.findJoint("mFootRight");
- mWristLeftp = (LLViewerJoint*)mRoot.findJoint("mWristLeft");
- mWristRightp = (LLViewerJoint*)mRoot.findJoint("mWristRight");
- mEyeLeftp = (LLViewerJoint*)mRoot.findJoint("mEyeLeft");
- mEyeRightp = (LLViewerJoint*)mRoot.findJoint("mEyeRight");
+ LLAvatarAppearance::buildCharacter();
//-------------------------------------------------------------------------
- // Make sure "well known" pointers exist
- //-------------------------------------------------------------------------
- if (!(mPelvisp &&
- mTorsop &&
- mChestp &&
- mNeckp &&
- mHeadp &&
- mSkullp &&
- mHipLeftp &&
- mHipRightp &&
- mKneeLeftp &&
- mKneeRightp &&
- mAnkleLeftp &&
- mAnkleRightp &&
- mFootLeftp &&
- mFootRightp &&
- mWristLeftp &&
- mWristRightp &&
- mEyeLeftp &&
- mEyeRightp))
- {
- llerrs << "Failed to create avatar." << llendl;
- return;
- }
-
- //-------------------------------------------------------------------------
- // initialize the pelvis
- //-------------------------------------------------------------------------
- mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) );
-
- //-------------------------------------------------------------------------
// set head offset from pelvis
//-------------------------------------------------------------------------
updateHeadOffset();
@@ -2033,9 +1600,6 @@ void LLVOAvatar::buildCharacter()
//-------------------------------------------------------------------------
processAnimationStateChanges();
- mIsBuilt = TRUE;
- stop_glerror();
-
mMeshValid = TRUE;
}
@@ -2055,7 +1619,7 @@ void LLVOAvatar::releaseMeshData()
//llinfos << "Releasing" << llendl;
// cleanup mesh data
- for (std::vector<LLViewerJoint*>::iterator iter = mMeshLOD.begin();
+ for (std::vector<LLAvatarJoint*>::iterator iter = mMeshLOD.begin();
iter != mMeshLOD.end();
++iter)
{
@@ -2149,7 +1713,11 @@ void LLVOAvatar::updateMeshData()
last_v_num = num_vertices ;
last_i_num = num_indices ;
- mMeshLOD[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+ LLViewerJoint* part_mesh = getViewerJoint(part_index++);
+ if (part_mesh)
+ {
+ part_mesh->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+ }
}
if(num_vertices < 1)//skip empty meshes
{
@@ -2223,7 +1791,11 @@ void LLVOAvatar::updateMeshData()
rigid = true;
}
- mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update && !rigid);
+ LLViewerJoint* mesh = getViewerJoint(k);
+ if (mesh)
+ {
+ mesh->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update && !rigid);
+ }
}
stop_glerror();
@@ -2244,72 +1816,6 @@ void LLVOAvatar::updateMeshData()
//------------------------------------------------------------------------
//------------------------------------------------------------------------
-// The viewer can only suggest a good size for the agent,
-// the simulator will keep it inside a reasonable range.
-void LLVOAvatar::computeBodySize()
-{
- LLVector3 pelvis_scale = mPelvisp->getScale();
-
- // some of the joints have not been cached
- LLVector3 skull = mSkullp->getPosition();
- LLVector3 skull_scale = mSkullp->getScale();
-
- LLVector3 neck = mNeckp->getPosition();
- LLVector3 neck_scale = mNeckp->getScale();
-
- LLVector3 chest = mChestp->getPosition();
- LLVector3 chest_scale = mChestp->getScale();
-
- // the rest of the joints have been cached
- LLVector3 head = mHeadp->getPosition();
- LLVector3 head_scale = mHeadp->getScale();
-
- LLVector3 torso = mTorsop->getPosition();
- LLVector3 torso_scale = mTorsop->getScale();
-
- LLVector3 hip = mHipLeftp->getPosition();
- LLVector3 hip_scale = mHipLeftp->getScale();
-
- LLVector3 knee = mKneeLeftp->getPosition();
- LLVector3 knee_scale = mKneeLeftp->getScale();
-
- LLVector3 ankle = mAnkleLeftp->getPosition();
- LLVector3 ankle_scale = mAnkleLeftp->getScale();
-
- LLVector3 foot = mFootLeftp->getPosition();
-
- mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] -
- knee.mV[VZ] * hip_scale.mV[VZ] -
- ankle.mV[VZ] * knee_scale.mV[VZ] -
- foot.mV[VZ] * ankle_scale.mV[VZ];
-
- LLVector3 new_body_size;
- new_body_size.mV[VZ] = mPelvisToFoot +
- // the sqrt(2) correction below is an approximate
- // correction to get to the top of the head
- F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) +
- head.mV[VZ] * neck_scale.mV[VZ] +
- neck.mV[VZ] * chest_scale.mV[VZ] +
- chest.mV[VZ] * torso_scale.mV[VZ] +
- torso.mV[VZ] * pelvis_scale.mV[VZ];
-
- // TODO -- measure the real depth and width
- new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH;
- new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH;
-
- if (new_body_size != mBodySize)
- {
- mBodySize = new_body_size;
-
- if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF())
- { // notify simulator of change in size
- // but not if we are in the middle of updating appearance
- gAgent.sendAgentSetAppearance();
- }
- }
-}
-
-//------------------------------------------------------------------------
// LLVOAvatar::processUpdateMessage()
//------------------------------------------------------------------------
U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys,
@@ -2478,7 +1984,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// animate the character
// store off last frame's root position to be consistent with camera position
- LLVector3 root_pos_last = mRoot.getWorldPosition();
+ LLVector3 root_pos_last = mRoot->getWorldPosition();
BOOL detailed_update = updateCharacter(agent);
static LLUICachedControl<bool> visualizers_in_calls("ShowVoiceVisualizersInCalls", false);
@@ -2597,11 +2103,11 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
if ( mIsSitting )
{
LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] );
- mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset );
+ mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot->getWorldPosition() + headOffset );
}
else
{
- LLVector3 tagPos = mRoot.getWorldPosition();
+ LLVector3 tagPos = mRoot->getWorldPosition();
tagPos[VZ] -= mPelvisToFoot;
tagPos[VZ] += ( mBodySize[VZ] + 0.125f );
mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos );
@@ -3338,7 +2844,7 @@ void LLVOAvatar::invalidateNameTags()
// Compute name tag position during idle update
LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)
{
- LLQuaternion root_rot = mRoot.getWorldRotation();
+ LLQuaternion root_rot = mRoot->getWorldRotation();
LLVector3 pixel_right_vec;
LLVector3 pixel_up_vec;
LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec);
@@ -3352,7 +2858,7 @@ LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)
local_camera_up.scaleVec(mBodySize * 0.5f);
local_camera_at.scaleVec(mBodySize * 0.5f);
- LLVector3 name_position = mRoot.getWorldPosition();
+ LLVector3 name_position = mRoot->getWorldPosition();
name_position[VZ] -= mPelvisToFoot;
name_position[VZ] += (mBodySize[VZ]* 0.55f);
name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av));
@@ -3417,13 +2923,13 @@ void LLVOAvatar::idleUpdateBelowWater()
void LLVOAvatar::slamPosition()
{
gAgent.setPositionAgent(getPositionAgent());
- mRoot.setWorldPosition(getPositionAgent()); // teleport
+ mRoot->setWorldPosition(getPositionAgent()); // teleport
setChanged(TRANSLATED);
if (mDrawable.notNull())
{
gPipeline.updateMoveNormalAsync(mDrawable);
}
- mRoot.updateWorldMatrixChildren();
+ mRoot->updateWorldMatrixChildren();
}
bool LLVOAvatar::isVisuallyMuted() const
@@ -3600,8 +3106,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
throttle = FALSE;
// put the pelvis at slaved position/mRotation
- mRoot.setWorldPosition( getPositionAgent() ); // first frame
- mRoot.setWorldRotation( getRotation() );
+ mRoot->setWorldPosition( getPositionAgent() ); // first frame
+ mRoot->setWorldRotation( getRotation() );
}
//--------------------------------------------------------------------
@@ -3644,10 +3150,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
- if (newPosition != mRoot.getXform()->getWorldPosition())
+ if (newPosition != mRoot->getXform()->getWorldPosition())
{
- mRoot.touch();
- mRoot.setWorldPosition( newPosition ); // regular update
+ mRoot->touch();
+ mRoot->setWorldPosition( newPosition ); // regular update
}
@@ -3708,7 +3214,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
}
- LLQuaternion root_rotation = mRoot.getWorldMatrix().quaternion();
+ LLQuaternion root_rotation = mRoot->getWorldMatrix().quaternion();
F32 root_roll, root_pitch, root_yaw;
root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw);
@@ -3717,7 +3223,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// and head turn. Once in motion, it must conform however.
BOOL self_in_mouselook = isSelf() && gAgentCamera.cameraMouselook();
- LLVector3 pelvisDir( mRoot.getWorldMatrix().getFwdRow4().mV );
+ LLVector3 pelvisDir( mRoot->getWorldMatrix().getFwdRow4().mV );
static LLCachedControl<F32> s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow");
static LLCachedControl<F32> s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast");
@@ -3803,14 +3309,14 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f);
- mRoot.setWorldRotation( slerp(u, mRoot.getWorldRotation(), wQv) );
+ mRoot->setWorldRotation( slerp(u, mRoot->getWorldRotation(), wQv) );
}
}
else if (mDrawable.notNull())
{
- mRoot.setPosition(mDrawable->getPosition());
- mRoot.setRotation(mDrawable->getRotation());
+ mRoot->setPosition(mDrawable->getPosition());
+ mRoot->setRotation(mDrawable->getRotation());
}
//-------------------------------------------------------------------------
@@ -3910,7 +3416,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
}
}
- mRoot.updateWorldMatrixChildren();
+ mRoot->updateWorldMatrixChildren();
if (!mDebugText.size() && mText.notNull())
{
@@ -3934,7 +3440,7 @@ void LLVOAvatar::updateHeadOffset()
{
// since we only care about Z, just grab one of the eyes
LLVector3 midEyePt = mEyeLeftp->getWorldPosition();
- midEyePt -= mDrawable.notNull() ? mDrawable->getWorldPosition() : mRoot.getWorldPosition();
+ midEyePt -= mDrawable.notNull() ? mDrawable->getWorldPosition() : mRoot->getWorldPosition();
midEyePt.mV[VZ] = llmax(-mPelvisToFoot + LLViewerCamera::getInstance()->getNear(), midEyePt.mV[VZ]);
if (mDrawable.notNull())
@@ -3972,8 +3478,8 @@ void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount,
void LLVOAvatar::postPelvisSetRecalc( void )
{
computeBodySize();
- mRoot.touch();
- mRoot.updateWorldMatrixChildren();
+ mRoot->touch();
+ mRoot->updateWorldMatrixChildren();
dirtyMesh();
updateHeadOffset();
}
@@ -4207,19 +3713,44 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
if (mNeedsSkin)
{
//generate animated mesh
- mMeshLOD[MESH_ID_LOWER_BODY]->updateJointGeometry();
- mMeshLOD[MESH_ID_UPPER_BODY]->updateJointGeometry();
+ LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY);
+ LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY);
+ LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT);
+ LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH);
+ LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD);
+ LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR);
+
+ if(upper_mesh)
+ {
+ upper_mesh->updateJointGeometry();
+ }
+ if (lower_mesh)
+ {
+ lower_mesh->updateJointGeometry();
+ }
if( isWearingWearableType( LLWearableType::WT_SKIRT ) )
{
- mMeshLOD[MESH_ID_SKIRT]->updateJointGeometry();
+ if(skirt_mesh)
+ {
+ skirt_mesh->updateJointGeometry();
+ }
}
if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
{
- mMeshLOD[MESH_ID_EYELASH]->updateJointGeometry();
- mMeshLOD[MESH_ID_HEAD]->updateJointGeometry();
- mMeshLOD[MESH_ID_HAIR]->updateJointGeometry();
+ if(eyelash_mesh)
+ {
+ eyelash_mesh->updateJointGeometry();
+ }
+ if(head_mesh)
+ {
+ head_mesh->updateJointGeometry();
+ }
+ if(hair_mesh)
+ {
+ hair_mesh->updateJointGeometry();
+ }
}
mNeedsSkin = FALSE;
mLastSkinTime = gFrameTimeSeconds;
@@ -4336,19 +3867,31 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
{
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy)
{
- num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea, TRUE, mIsDummy);
+ LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD);
+ if (head_mesh)
+ {
+ num_indices += head_mesh->render(mAdjustedPixelArea, TRUE, mIsDummy);
+ }
first_pass = FALSE;
}
}
if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy)
{
- num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
+ LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY);
+ if (upper_mesh)
+ {
+ num_indices += upper_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy);
+ }
first_pass = FALSE;
}
if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy)
{
- num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
+ LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY);
+ if (lower_mesh)
+ {
+ num_indices += lower_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy);
+ }
first_pass = FALSE;
}
}
@@ -4381,7 +3924,11 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (mIsDummy || isTextureVisible(TEX_SKIRT_BAKED)) )
{
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f);
- num_indices += mMeshLOD[MESH_ID_SKIRT]->render(mAdjustedPixelArea, FALSE);
+ LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT);
+ if (skirt_mesh)
+ {
+ num_indices += skirt_mesh->render(mAdjustedPixelArea, FALSE);
+ }
first_pass = FALSE;
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
@@ -4395,14 +3942,22 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
if (isTextureVisible(TEX_HEAD_BAKED))
{
- num_indices += mMeshLOD[MESH_ID_EYELASH]->render(mAdjustedPixelArea, first_pass, mIsDummy);
+ LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH);
+ if (eyelash_mesh)
+ {
+ num_indices += eyelash_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy);
+ }
first_pass = FALSE;
}
// Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair)
// TODO: 1.25 will be able to switch this logic back to calling isTextureVisible();
if (getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)
{
- num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass, mIsDummy);
+ LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR);
+ if (hair_mesh)
+ {
+ num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy);
+ }
first_pass = FALSE;
}
if (LLPipeline::sImpostorRender)
@@ -4446,8 +4001,16 @@ U32 LLVOAvatar::renderRigid()
if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy)
{
- num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
- num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
+ LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT);
+ LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT);
+ if (eyeball_left)
+ {
+ num_indices += eyeball_left->render(mAdjustedPixelArea, TRUE, mIsDummy);
+ }
+ if(eyeball_right)
+ {
+ num_indices += eyeball_right->render(mAdjustedPixelArea, TRUE, mIsDummy);
+ }
}
if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction)
@@ -5139,7 +4702,7 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
if (iter == mJointMap.end() || iter->second == NULL)
{ //search for joint and cache found joint in lookup table
- jointp = mRoot.findJoint(name);
+ jointp = mRoot->findJoint(name);
mJointMap[name] = jointp;
}
else
@@ -5168,7 +4731,7 @@ void LLVOAvatar::resetJointPositions( void )
//-----------------------------------------------------------------------------
void LLVOAvatar::resetSpecificJointPosition( const std::string& name )
{
- LLJoint* pJoint = mRoot.findJoint( name );
+ LLJoint* pJoint = mRoot->findJoint( name );
if ( pJoint && pJoint->doesJointNeedToBeReset() )
{
@@ -5356,23 +4919,6 @@ BOOL LLVOAvatar::allocateCharacterJoints( U32 num )
return TRUE;
}
-//-----------------------------------------------------------------------------
-// allocateCollisionVolumes()
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::allocateCollisionVolumes( U32 num )
-{
- deleteAndClearArray(mCollisionVolumes);
- mNumCollisionVolumes = 0;
-
- mCollisionVolumes = new LLViewerJointCollisionVolume[num];
- if (!mCollisionVolumes)
- {
- return FALSE;
- }
-
- mNumCollisionVolumes = num;
- return TRUE;
-}
//-----------------------------------------------------------------------------
@@ -5398,153 +4944,13 @@ void LLVOAvatar::requestStopMotion( LLMotion* motion )
}
//-----------------------------------------------------------------------------
-// loadAvatar()
-//-----------------------------------------------------------------------------
-static LLFastTimer::DeclareTimer FTM_LOAD_AVATAR("Load Avatar");
-
-BOOL LLVOAvatar::loadAvatar()
-{
-// LLFastTimer t(FTM_LOAD_AVATAR);
-
- // avatar_skeleton.xml
- if( !buildSkeleton(sAvatarSkeletonInfo) )
- {
- llwarns << "avatar file: buildSkeleton() failed" << llendl;
- return FALSE;
- }
-
- // avatar_lad.xml : <skeleton>
- if( !loadSkeletonNode() )
- {
- llwarns << "avatar file: loadNodeSkeleton() failed" << llendl;
- return FALSE;
- }
-
- // avatar_lad.xml : <mesh>
- if( !loadMeshNodes() )
- {
- llwarns << "avatar file: loadNodeMesh() failed" << llendl;
- return FALSE;
- }
-
- // avatar_lad.xml : <global_color>
- if( sAvatarXmlInfo->mTexSkinColorInfo )
- {
- mTexSkinColor = new LLTexGlobalColor( this );
- if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) )
- {
- llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl;
- return FALSE;
- }
- }
- else
- {
- llwarns << "<global_color> name=\"skin_color\" not found" << llendl;
- return FALSE;
- }
- if( sAvatarXmlInfo->mTexHairColorInfo )
- {
- mTexHairColor = new LLTexGlobalColor( this );
- if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) )
- {
- llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl;
- return FALSE;
- }
- }
- else
- {
- llwarns << "<global_color> name=\"hair_color\" not found" << llendl;
- return FALSE;
- }
- if( sAvatarXmlInfo->mTexEyeColorInfo )
- {
- mTexEyeColor = new LLTexGlobalColor( this );
- if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) )
- {
- llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl;
- return FALSE;
- }
- }
- else
- {
- llwarns << "<global_color> name=\"eye_color\" not found" << llendl;
- return FALSE;
- }
-
- // avatar_lad.xml : <layer_set>
- if (sAvatarXmlInfo->mLayerInfoList.empty())
- {
- llwarns << "avatar file: missing <layer_set> node" << llendl;
- return FALSE;
- }
-
- if (sAvatarXmlInfo->mMorphMaskInfoList.empty())
- {
- llwarns << "avatar file: missing <morph_masks> node" << llendl;
- return FALSE;
- }
-
- // avatar_lad.xml : <morph_masks>
- for (LLVOAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin();
- iter != sAvatarXmlInfo->mMorphMaskInfoList.end();
- ++iter)
- {
- LLVOAvatarXmlInfo::LLVOAvatarMorphInfo *info = *iter;
-
- EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion);
- if (baked != BAKED_NUM_INDICES)
- {
- LLVisualParam* morph_param;
- const std::string *name = &info->mName;
- morph_param = getVisualParam(name->c_str());
- if (morph_param)
- {
- BOOL invert = info->mInvert;
- addMaskedMorph(baked, morph_param, invert, info->mLayer);
- }
- }
-
- }
-
- loadLayersets();
-
- // avatar_lad.xml : <driver_parameters>
- for (LLVOAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin();
- iter != sAvatarXmlInfo->mDriverInfoList.end();
- ++iter)
- {
- LLDriverParamInfo *info = *iter;
- LLDriverParam* driver_param = new LLDriverParam( this );
- if (driver_param->setInfo(info))
- {
- addVisualParam( driver_param );
- LLVisualParam*(LLVOAvatar::*avatar_function)(S32)const = &LLVOAvatar::getVisualParam;
- if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLVOAvatar*)this,_1 ), false))
- {
- llwarns << "could not link driven params for avatar " << this->getFullname() << " id: " << driver_param->getID() << llendl;
- continue;
- }
- }
- else
- {
- delete driver_param;
- llwarns << "avatar file: driver_param->parseData() failed" << llendl;
- return FALSE;
- }
- }
-
-
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
// loadSkeletonNode(): loads <skeleton> node from XML tree
//-----------------------------------------------------------------------------
+//virtual
BOOL LLVOAvatar::loadSkeletonNode ()
{
- mRoot.addChild( &mSkeleton[0] );
-
- for (std::vector<LLViewerJoint *>::iterator iter = mMeshLOD.begin();
+ // make meshes children before calling parent version of the function
+ for (std::vector<LLAvatarJoint *>::iterator iter = mMeshLOD.begin();
iter != mMeshLOD.end();
++iter)
{
@@ -5553,60 +4959,19 @@ BOOL LLVOAvatar::loadSkeletonNode ()
joint->setMeshesToChildren();
}
- mRoot.addChild(mMeshLOD[MESH_ID_HEAD]);
- mRoot.addChild(mMeshLOD[MESH_ID_EYELASH]);
- mRoot.addChild(mMeshLOD[MESH_ID_UPPER_BODY]);
- mRoot.addChild(mMeshLOD[MESH_ID_LOWER_BODY]);
- mRoot.addChild(mMeshLOD[MESH_ID_SKIRT]);
- mRoot.addChild(mMeshLOD[MESH_ID_HEAD]);
-
- LLViewerJoint *skull = (LLViewerJoint*)mRoot.findJoint("mSkull");
- if (skull)
- {
- skull->addChild(mMeshLOD[MESH_ID_HAIR] );
- }
-
- LLViewerJoint *eyeL = (LLViewerJoint*)mRoot.findJoint("mEyeLeft");
- if (eyeL)
+ if (!LLAvatarAppearance::loadSkeletonNode())
{
- eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] );
- }
-
- LLViewerJoint *eyeR = (LLViewerJoint*)mRoot.findJoint("mEyeRight");
- if (eyeR)
- {
- eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] );
+ return FALSE;
}
- // SKELETAL DISTORTIONS
- {
- LLVOAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter;
- for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin();
- iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end();
- ++iter)
- {
- LLPolySkeletalDistortionInfo *info = *iter;
- LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this);
- if (!param->setInfo(info))
- {
- delete param;
- return FALSE;
- }
- else
- {
- addVisualParam(param);
- }
- }
- }
-
// ATTACHMENTS
{
- LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter;
+ LLAvatarXmlInfo::attachment_info_list_t::iterator iter;
for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin();
iter != sAvatarXmlInfo->mAttachmentInfoList.end();
++iter)
{
- LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter;
+ LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *iter;
if (!isSelf() && info->mJointName == "mScreen")
{ //don't process screen joint for other avatars
continue;
@@ -5679,144 +5044,6 @@ BOOL LLVOAvatar::loadSkeletonNode ()
}
//-----------------------------------------------------------------------------
-// loadMeshNodes(): loads <mesh> nodes from XML tree
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::loadMeshNodes()
-{
- for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin();
- meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end();
- ++meshinfo_iter)
- {
- const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter;
- const std::string &type = info->mType;
- S32 lod = info->mLOD;
-
- LLViewerJointMesh* mesh = NULL;
- U8 mesh_id = 0;
- BOOL found_mesh_id = FALSE;
-
- /* if (type == "hairMesh")
- switch(lod)
- case 0:
- mesh = &mHairMesh0; */
- for (LLAvatarAppearanceDictionary::Meshes::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin();
- mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end();
- ++mesh_iter)
- {
- const EMeshIndex mesh_index = mesh_iter->first;
- const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_iter->second;
- if (type.compare(mesh_dict->mName) == 0)
- {
- mesh_id = mesh_index;
- found_mesh_id = TRUE;
- break;
- }
- }
-
- if (found_mesh_id)
- {
- if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size())
- {
- mesh = mMeshLOD[mesh_id]->mMeshParts[lod];
- }
- else
- {
- llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
- return FALSE;
- }
- }
- else
- {
- llwarns << "Ignoring unrecognized mesh type: " << type << llendl;
- return FALSE;
- }
-
- // llinfos << "Parsing mesh data for " << type << "..." << llendl;
-
- // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings.
- // Do not touch!!!
- mesh->setColor( 1.0f, 1.0f, 1.0f, 1.0f );
-
- LLPolyMesh *poly_mesh = NULL;
-
- if (!info->mReferenceMeshName.empty())
- {
- polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName);
- if (polymesh_iter != mMeshes.end())
- {
- poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second);
- poly_mesh->setAvatar(this);
- }
- else
- {
- // This should never happen
- LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL;
- }
- }
- else
- {
- poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName);
- poly_mesh->setAvatar(this);
- }
-
- if( !poly_mesh )
- {
- llwarns << "Failed to load mesh of type " << type << llendl;
- return FALSE;
- }
-
- // Multimap insert
- mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh));
-
- mesh->setMesh( poly_mesh );
- mesh->setLOD( info->mMinPixelArea );
-
- for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin();
- xmlinfo_iter != info->mPolyMorphTargetInfoList.end();
- ++xmlinfo_iter)
- {
- const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter);
- LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh());
- if (!param->setInfo(info_pair->first))
- {
- delete param;
- return FALSE;
- }
- else
- {
- if (info_pair->second)
- {
- addSharedVisualParam(param);
- }
- else
- {
- addVisualParam(param);
- }
- }
- }
- }
-
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// loadLayerSets()
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::loadLayersets()
-{
- BOOL success = TRUE;
- for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin();
- layerset_iter != sAvatarXmlInfo->mLayerInfoList.end();
- ++layerset_iter)
- {
- // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
- LLTexLayerSetInfo *layerset_info = *layerset_iter;
- layerset_info->createVisualParams(this);
- }
- return success;
-}
-
-//-----------------------------------------------------------------------------
// updateVisualParams()
//-----------------------------------------------------------------------------
void LLVOAvatar::updateVisualParams()
@@ -5829,7 +5056,7 @@ void LLVOAvatar::updateVisualParams()
{
computeBodySize();
mLastSkeletonSerialNum = mSkeletonSerialNum;
- mRoot.updateWorldMatrixChildren();
+ mRoot->updateWorldMatrixChildren();
}
dirtyMesh();
@@ -5919,7 +5146,12 @@ BOOL LLVOAvatar::updateJointLODs()
}
// now select meshes to render based on adjusted pixel area
- BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE);
+ LLViewerJoint* root = dynamic_cast<LLViewerJoint*>(mRoot);
+ BOOL res = FALSE;
+ if (root)
+ {
+ res = root->updateLOD(mAdjustedPixelArea, TRUE);
+ }
if (res)
{
sNumLODChangesThisFrame++;
@@ -6009,6 +5241,15 @@ void LLVOAvatar::dirtyMesh(S32 priority)
{
mDirtyMesh = llmax(mDirtyMesh, priority);
}
+
+//-----------------------------------------------------------------------------
+// getViewerJoint()
+//-----------------------------------------------------------------------------
+LLViewerJoint* LLVOAvatar::getViewerJoint(S32 idx)
+{
+ return dynamic_cast<LLViewerJoint*>(mMeshLOD[idx]);
+}
+
//-----------------------------------------------------------------------------
// hideSkirt()
//-----------------------------------------------------------------------------
@@ -6322,9 +5563,9 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
// Notice that removing sitDown() from here causes avatars sitting on
// objects to be not rendered for new arrivals. See EXT-6835 and EXT-1655.
sitDown(TRUE);
- mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject
- mRoot.setPosition(getPosition());
- mRoot.updateWorldMatrixChildren();
+ mRoot->getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject
+ mRoot->setPosition(getPosition());
+ mRoot->updateWorldMatrixChildren();
stopMotion(ANIM_AGENT_BODY_NOISE);
@@ -6370,10 +5611,10 @@ void LLVOAvatar::getOffObject()
sitDown(FALSE);
- mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject
- mRoot.setPosition(cur_position_world);
- mRoot.setRotation(cur_rotation_world);
- mRoot.getXform()->update();
+ mRoot->getXform()->setParent(NULL); // LLVOAvatar::getOffObject
+ mRoot->setPosition(cur_position_world);
+ mRoot->setRotation(cur_rotation_world);
+ mRoot->getXform()->update();
startMotion(ANIM_AGENT_BODY_NOISE);
@@ -7752,501 +6993,20 @@ void LLVOAvatar::startAppearanceAnimation()
}
}
-// virtual
-void LLVOAvatar::removeMissingBakedTextures()
-{
-}
-
-//-----------------------------------------------------------------------------
-// LLVOAvatarXmlInfo
-//-----------------------------------------------------------------------------
-
-LLVOAvatar::LLVOAvatarXmlInfo::LLVOAvatarXmlInfo()
- : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0)
-{
-}
-
-LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo()
-{
- std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer());
- std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer());
- std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer());
- deleteAndClear(mTexSkinColorInfo);
- deleteAndClear(mTexHairColorInfo);
- deleteAndClear(mTexEyeColorInfo);
- std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer());
- std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer());
- std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer());
-}
-
-//-----------------------------------------------------------------------------
-// LLVOAvatarBoneInfo::parseXml()
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
-{
- if (node->hasName("bone"))
- {
- mIsJoint = TRUE;
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (!node->getFastAttributeString(name_string, mName))
- {
- llwarns << "Bone without name" << llendl;
- return FALSE;
- }
- }
- else if (node->hasName("collision_volume"))
- {
- mIsJoint = FALSE;
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (!node->getFastAttributeString(name_string, mName))
- {
- mName = "Collision Volume";
- }
- }
- else
- {
- llwarns << "Invalid node " << node->getName() << llendl;
- return FALSE;
- }
-
- static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos");
- if (!node->getFastAttributeVector3(pos_string, mPos))
- {
- llwarns << "Bone without position" << llendl;
- return FALSE;
- }
-
- static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot");
- if (!node->getFastAttributeVector3(rot_string, mRot))
- {
- llwarns << "Bone without rotation" << llendl;
- return FALSE;
- }
-
- static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
- if (!node->getFastAttributeVector3(scale_string, mScale))
- {
- llwarns << "Bone without scale" << llendl;
- return FALSE;
- }
-
- if (mIsJoint)
- {
- static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot");
- if (!node->getFastAttributeVector3(pivot_string, mPivot))
- {
- llwarns << "Bone without pivot" << llendl;
- return FALSE;
- }
- }
-
- // parse children
- LLXmlTreeNode* child;
- for( child = node->getFirstChild(); child; child = node->getNextChild() )
- {
- LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo;
- if (!child_info->parseXml(child))
- {
- delete child_info;
- return FALSE;
- }
- mChildList.push_back(child_info);
- }
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// LLVOAvatarSkeletonInfo::parseXml()
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
-{
- static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones");
- if (!node->getFastAttributeS32(num_bones_string, mNumBones))
- {
- llwarns << "Couldn't find number of bones." << llendl;
- return FALSE;
- }
-
- static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes");
- node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes);
-
- LLXmlTreeNode* child;
- for( child = node->getFirstChild(); child; child = node->getNextChild() )
- {
- LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo;
- if (!info->parseXml(child))
- {
- delete info;
- llwarns << "Error parsing bone in skeleton file" << llendl;
- return FALSE;
- }
- mBoneInfoList.push_back(info);
- }
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
-{
- LLXmlTreeNode* node = root->getChildByName( "skeleton" );
- if( !node )
- {
- llwarns << "avatar file: missing <skeleton>" << llendl;
- return FALSE;
- }
-
- LLXmlTreeNode* child;
-
- // SKELETON DISTORTIONS
- for (child = node->getChildByName( "param" );
- child;
- child = node->getNextNamedChild())
- {
- if (!child->getChildByName("param_skeleton"))
- {
- if (child->getChildByName("param_morph"))
- {
- llwarns << "Can't specify morph param in skeleton definition." << llendl;
- }
- else
- {
- llwarns << "Unknown param type." << llendl;
- }
- continue;
- }
-
- LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo;
- if (!info->parseXml(child))
- {
- delete info;
- return FALSE;
- }
-
- mSkeletalDistortionInfoList.push_back(info);
- }
-
- // ATTACHMENT POINTS
- for (child = node->getChildByName( "attachment_point" );
- child;
- child = node->getNextNamedChild())
- {
- LLVOAvatarAttachmentInfo* info = new LLVOAvatarAttachmentInfo();
-
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (!child->getFastAttributeString(name_string, info->mName))
- {
- llwarns << "No name supplied for attachment point." << llendl;
- delete info;
- continue;
- }
-
- static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint");
- if (!child->getFastAttributeString(joint_string, info->mJointName))
- {
- llwarns << "No bone declared in attachment point " << info->mName << llendl;
- delete info;
- continue;
- }
-
- static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position");
- if (child->getFastAttributeVector3(position_string, info->mPosition))
- {
- info->mHasPosition = TRUE;
- }
-
- static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation");
- if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler))
- {
- info->mHasRotation = TRUE;
- }
- static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group");
- if (child->getFastAttributeS32(group_string, info->mGroup))
- {
- if (info->mGroup == -1)
- info->mGroup = -1111; // -1 = none parsed, < -1 = bad value
- }
-
- static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id");
- if (!child->getFastAttributeS32(id_string, info->mAttachmentID))
- {
- llwarns << "No id supplied for attachment point " << info->mName << llendl;
- delete info;
- continue;
- }
-
- static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice");
- child->getFastAttributeS32(slot_string, info->mPieMenuSlice);
-
- static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person");
- child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson);
-
- static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud");
- child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment);
-
- mAttachmentInfoList.push_back(info);
- }
-
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// parseXmlMeshNodes(): parses <mesh> nodes from XML tree
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
-{
- for (LLXmlTreeNode* node = root->getChildByName( "mesh" );
- node;
- node = root->getNextNamedChild())
- {
- LLVOAvatarMeshInfo *info = new LLVOAvatarMeshInfo;
-
- // attribute: type
- static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type");
- if( !node->getFastAttributeString( type_string, info->mType ) )
- {
- llwarns << "Avatar file: <mesh> is missing type attribute. Ignoring element. " << llendl;
- delete info;
- return FALSE; // Ignore this element
- }
-
- static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod");
- if (!node->getFastAttributeS32( lod_string, info->mLOD ))
- {
- llwarns << "Avatar file: <mesh> is missing lod attribute. Ignoring element. " << llendl;
- delete info;
- return FALSE; // Ignore this element
- }
-
- static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name");
- if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) )
- {
- llwarns << "Avatar file: <mesh> is missing file_name attribute. Ignoring: " << info->mType << llendl;
- delete info;
- return FALSE; // Ignore this element
- }
-
- static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference");
- node->getFastAttributeString( reference_string, info->mReferenceMeshName );
-
- // attribute: min_pixel_area
- static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area");
- static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width");
- if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea ))
- {
- F32 min_pixel_area = 0.1f;
- if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area ))
- {
- // this is square root of pixel area (sensible to use linear space in defining lods)
- min_pixel_area = min_pixel_area * min_pixel_area;
- }
- info->mMinPixelArea = min_pixel_area;
- }
-
- // Parse visual params for this node only if we haven't already
- for (LLXmlTreeNode* child = node->getChildByName( "param" );
- child;
- child = node->getNextNamedChild())
- {
- if (!child->getChildByName("param_morph"))
- {
- if (child->getChildByName("param_skeleton"))
- {
- llwarns << "Can't specify skeleton param in a mesh definition." << llendl;
- }
- else
- {
- llwarns << "Unknown param type." << llendl;
- }
- continue;
- }
-
- LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo();
- if (!morphinfo->parseXml(child))
- {
- delete morphinfo;
- delete info;
- return -1;
- }
- BOOL shared = FALSE;
- static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared");
- child->getFastAttributeBOOL(shared_string, shared);
-
- info->mPolyMorphTargetInfoList.push_back(LLVOAvatarMeshInfo::morph_info_pair_t(morphinfo, shared));
- }
-
- mMeshInfoList.push_back(info);
- }
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// parseXmlColorNodes(): parses <global_color> nodes from XML tree
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
-{
- for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" );
- color_node;
- color_node = root->getNextNamedChild())
- {
- std::string global_color_name;
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (color_node->getFastAttributeString( name_string, global_color_name ) )
- {
- if( global_color_name == "skin_color" )
- {
- if (mTexSkinColorInfo)
- {
- llwarns << "avatar file: multiple instances of skin_color" << llendl;
- return FALSE;
- }
- mTexSkinColorInfo = new LLTexGlobalColorInfo;
- if( !mTexSkinColorInfo->parseXml( color_node ) )
- {
- deleteAndClear(mTexSkinColorInfo);
- llwarns << "avatar file: mTexSkinColor->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- else if( global_color_name == "hair_color" )
- {
- if (mTexHairColorInfo)
- {
- llwarns << "avatar file: multiple instances of hair_color" << llendl;
- return FALSE;
- }
- mTexHairColorInfo = new LLTexGlobalColorInfo;
- if( !mTexHairColorInfo->parseXml( color_node ) )
- {
- deleteAndClear(mTexHairColorInfo);
- llwarns << "avatar file: mTexHairColor->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- else if( global_color_name == "eye_color" )
- {
- if (mTexEyeColorInfo)
- {
- llwarns << "avatar file: multiple instances of eye_color" << llendl;
- return FALSE;
- }
- mTexEyeColorInfo = new LLTexGlobalColorInfo;
- if( !mTexEyeColorInfo->parseXml( color_node ) )
- {
- llwarns << "avatar file: mTexEyeColor->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- }
- }
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// parseXmlLayerNodes(): parses <layer_set> nodes from XML tree
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
-{
- for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" );
- layer_node;
- layer_node = root->getNextNamedChild())
- {
- LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo();
- if( layer_info->parseXml( layer_node ) )
- {
- mLayerInfoList.push_back(layer_info);
- }
- else
- {
- delete layer_info;
- llwarns << "avatar file: layer_set->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
+//virtual
+void LLVOAvatar::bodySizeChanged()
{
- LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" );
- if( driver )
- {
- for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" );
- grand_child;
- grand_child = driver->getNextNamedChild())
- {
- if( grand_child->getChildByName( "param_driver" ) )
- {
- LLDriverParamInfo* driver_info = new LLDriverParamInfo();
- if( driver_info->parseXml( grand_child ) )
- {
- mDriverInfoList.push_back(driver_info);
- }
- else
- {
- delete driver_info;
- llwarns << "avatar file: driver_param->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- }
+ if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF())
+ { // notify simulator of change in size
+ // but not if we are in the middle of updating appearance
+ gAgent.sendAgentSetAppearance();
}
- return TRUE;
}
-//-----------------------------------------------------------------------------
-// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root)
-{
- LLXmlTreeNode* masks = root->getChildByName( "morph_masks" );
- if( !masks )
- {
- return FALSE;
- }
- for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" );
- grand_child;
- grand_child = masks->getNextNamedChild())
- {
- LLVOAvatarMorphInfo* info = new LLVOAvatarMorphInfo();
-
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name");
- if (!grand_child->getFastAttributeString(name_string, info->mName))
- {
- llwarns << "No name supplied for morph mask." << llendl;
- delete info;
- continue;
- }
-
- static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region");
- if (!grand_child->getFastAttributeString(region_string, info->mRegion))
- {
- llwarns << "No region supplied for morph mask." << llendl;
- delete info;
- continue;
- }
-
- static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer");
- if (!grand_child->getFastAttributeString(layer_string, info->mLayer))
- {
- llwarns << "No layer supplied for morph mask." << llendl;
- delete info;
- continue;
- }
-
- // optional parameter. don't throw a warning if not present.
- static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert");
- grand_child->getFastAttributeBOOL(invert_string, info->mInvert);
-
- mMorphMaskInfoList.push_back(info);
- }
-
- return TRUE;
+// virtual
+void LLVOAvatar::removeMissingBakedTextures()
+{
}
//virtual
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index dd8663f4dc..bda09b044d 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -69,8 +69,7 @@ class LLVoiceVisualizer;
class LLHUDNameTag;
class LLHUDEffectSpiral;
class LLTexGlobalColor;
-class LLVOAvatarBoneInfo;
-class LLVOAvatarSkeletonInfo;
+class LLViewerJoint;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLVOAvatar
@@ -85,8 +84,6 @@ class LLVOAvatar :
public:
friend class LLVOAvatarSelf;
-protected:
- struct LLVOAvatarXmlInfo;
/********************************************************************************
** **
@@ -111,9 +108,6 @@ public:
virtual void initInstance(); // Called after construction to initialize the class.
protected:
virtual ~LLVOAvatar();
- BOOL loadSkeletonNode();
- BOOL loadMeshNodes();
- virtual BOOL loadLayersets();
/** Initialization
** **
@@ -190,7 +184,7 @@ public:
void dumpAnimationState();
virtual LLJoint* getJoint(const std::string &name);
- virtual LLJoint* getRootJoint() { return &mRoot; }
+ virtual LLJoint* getRootJoint() { return mRoot; }
void resetJointPositions( void );
void resetJointPositionsToDefault( void );
@@ -224,7 +218,6 @@ public:
public:
virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent
/*virtual*/BOOL isUsingBakedTextures() const { return mUseServerBakes; } // e.g. false if in appearance edit mode
- bool isBuilt() const { return mIsBuilt; }
private: //aligned members
LL_ALIGN_16(LLVector4a mImpostorExtents[2]);
@@ -343,7 +336,6 @@ protected:
/** State
** **
*******************************************************************************/
-
/********************************************************************************
** **
** SKELETON
@@ -351,74 +343,22 @@ protected:
public:
void updateHeadOffset();
- F32 getPelvisToFoot() const { return mPelvisToFoot; }
void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ;
bool hasPelvisOffset( void ) { return mHasPelvisOffset; }
void postPelvisSetRecalc( void );
void setPelvisOffset( F32 pelvixFixupAmount );
+ /*virtual*/ BOOL loadSkeletonNode();
+ /*virtual*/ void buildCharacter();
+
bool mHasPelvisOffset;
LLVector3 mPelvisOffset;
F32 mLastPelvisToFoot;
F32 mPelvisFixup;
F32 mLastPelvisFixup;
- LLVector3 mHeadOffset; // current head position
- LLViewerJoint mRoot;
-
- typedef std::map<std::string, LLJoint*> joint_map_t;
- joint_map_t mJointMap;
-
-protected:
- static BOOL parseSkeletonFile(const std::string& filename);
- void buildCharacter();
- virtual BOOL loadAvatar();
-
- BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
- BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info);
-private:
- BOOL mIsBuilt; // state of deferred character building
- S32 mNumJoints;
- LLViewerJoint* mSkeleton;
-
- //--------------------------------------------------------------------
- // Pelvis height adjustment members.
- //--------------------------------------------------------------------
-public:
- LLVector3 mBodySize;
S32 mLastSkeletonSerialNum;
-private:
- F32 mPelvisToFoot;
- //--------------------------------------------------------------------
- // Cached pointers to well known joints
- //--------------------------------------------------------------------
-public:
- LLViewerJoint* mPelvisp;
- LLViewerJoint* mTorsop;
- LLViewerJoint* mChestp;
- LLViewerJoint* mNeckp;
- LLViewerJoint* mHeadp;
- LLViewerJoint* mSkullp;
- LLViewerJoint* mEyeLeftp;
- LLViewerJoint* mEyeRightp;
- LLViewerJoint* mHipLeftp;
- LLViewerJoint* mHipRightp;
- LLViewerJoint* mKneeLeftp;
- LLViewerJoint* mKneeRightp;
- LLViewerJoint* mAnkleLeftp;
- LLViewerJoint* mAnkleRightp;
- LLViewerJoint* mFootLeftp;
- LLViewerJoint* mFootRightp;
- LLViewerJoint* mWristLeftp;
- LLViewerJoint* mWristRightp;
-
- //--------------------------------------------------------------------
- // XML parse tree
- //--------------------------------------------------------------------
-private:
- static LLXmlTree sXMLTree; // avatar config file
- static LLXmlTree sSkeletonXMLTree; // avatar skeleton file
/** Skeleton
** **
@@ -640,8 +580,6 @@ public:
private:
static const LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary *getDictionary() { return sAvatarDictionary; }
static LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* sAvatarDictionary;
- static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo;
- static LLVOAvatarXmlInfo* sAvatarXmlInfo;
//--------------------------------------------------------------------
// Messaging
@@ -671,13 +609,10 @@ protected:
virtual void restoreMeshData();
private:
virtual void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority
+ LLViewerJoint* getViewerJoint(S32 idx);
S32 mDirtyMesh; // 0 -- not dirty, 1 -- morphed, 2 -- LOD
BOOL mMeshTexturesDirty;
- typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t;
- polymesh_map_t mMeshes;
- std::vector<LLViewerJoint *> mMeshLOD;
-
//--------------------------------------------------------------------
// Destroy invisible mesh
//--------------------------------------------------------------------
@@ -698,6 +633,7 @@ public:
void processAvatarAppearance(LLMessageSystem* mesgsys);
void hideSkirt();
void startAppearanceAnimation();
+ /*virtual*/ void bodySizeChanged();
//--------------------------------------------------------------------
// Appearance morphing
@@ -840,15 +776,6 @@ private:
F32 mSpeed; // misc. animation repeated state
//--------------------------------------------------------------------
- // Collision volumes
- //--------------------------------------------------------------------
-public:
- S32 mNumCollisionVolumes;
- LLViewerJointCollisionVolume* mCollisionVolumes;
-protected:
- BOOL allocateCollisionVolumes(U32 num);
-
- //--------------------------------------------------------------------
// Dimensions
//--------------------------------------------------------------------
public:
@@ -858,7 +785,6 @@ public:
void resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm);
void slamPosition(); // Slam position to transmitted position (for teleport);
protected:
- void computeBodySize();
//--------------------------------------------------------------------
// Material being stepped on
@@ -1025,90 +951,6 @@ protected:
protected: // Shared with LLVOAvatarSelf
- struct LLVOAvatarXmlInfo
- {
- LLVOAvatarXmlInfo();
- ~LLVOAvatarXmlInfo();
-
- BOOL parseXmlSkeletonNode(LLXmlTreeNode* root);
- BOOL parseXmlMeshNodes(LLXmlTreeNode* root);
- BOOL parseXmlColorNodes(LLXmlTreeNode* root);
- BOOL parseXmlLayerNodes(LLXmlTreeNode* root);
- BOOL parseXmlDriverNodes(LLXmlTreeNode* root);
- BOOL parseXmlMorphNodes(LLXmlTreeNode* root);
-
- struct LLVOAvatarMeshInfo
- {
- typedef std::pair<LLPolyMorphTargetInfo*,BOOL> morph_info_pair_t;
- typedef std::vector<morph_info_pair_t> morph_info_list_t;
-
- LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {}
- ~LLVOAvatarMeshInfo()
- {
- morph_info_list_t::iterator iter;
- for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++)
- {
- delete iter->first;
- }
- mPolyMorphTargetInfoList.clear();
- }
-
- std::string mType;
- S32 mLOD;
- std::string mMeshFileName;
- std::string mReferenceMeshName;
- F32 mMinPixelArea;
- morph_info_list_t mPolyMorphTargetInfoList;
- };
- typedef std::vector<LLVOAvatarMeshInfo*> mesh_info_list_t;
- mesh_info_list_t mMeshInfoList;
-
- typedef std::vector<LLPolySkeletalDistortionInfo*> skeletal_distortion_info_list_t;
- skeletal_distortion_info_list_t mSkeletalDistortionInfoList;
-
- struct LLVOAvatarAttachmentInfo
- {
- LLVOAvatarAttachmentInfo()
- : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE),
- mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {}
- std::string mName;
- std::string mJointName;
- LLVector3 mPosition;
- LLVector3 mRotationEuler;
- S32 mGroup;
- S32 mAttachmentID;
- S32 mPieMenuSlice;
- BOOL mVisibleFirstPerson;
- BOOL mIsHUDAttachment;
- BOOL mHasPosition;
- BOOL mHasRotation;
- };
- typedef std::vector<LLVOAvatarAttachmentInfo*> attachment_info_list_t;
- attachment_info_list_t mAttachmentInfoList;
-
- LLTexGlobalColorInfo *mTexSkinColorInfo;
- LLTexGlobalColorInfo *mTexHairColorInfo;
- LLTexGlobalColorInfo *mTexEyeColorInfo;
-
- typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t;
- layer_info_list_t mLayerInfoList;
-
- typedef std::vector<LLDriverParamInfo*> driver_info_list_t;
- driver_info_list_t mDriverInfoList;
-
- struct LLVOAvatarMorphInfo
- {
- LLVOAvatarMorphInfo()
- : mInvert(FALSE) {}
- std::string mName;
- std::string mRegion;
- std::string mLayer;
- BOOL mInvert;
- };
-
- typedef std::vector<LLVOAvatarMorphInfo*> morph_info_list_t;
- morph_info_list_t mMorphMaskInfoList;
- };
/** Support classes
** **
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index fc52347041..f832a126bd 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -255,7 +255,7 @@ BOOL LLVOAvatarSelf::loadAvatarSelf()
return success;
}
-BOOL LLVOAvatarSelf::buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info)
+BOOL LLVOAvatarSelf::buildSkeletonSelf(const LLAvatarSkeletonInfo *info)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
@@ -589,7 +589,7 @@ LLVOAvatarSelf::~LLVOAvatarSelf()
BOOL LLVOAvatarSelf::loadLayersets()
{
BOOL success = TRUE;
- for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin();
+ for (LLAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin();
iter != sAvatarXmlInfo->mLayerInfoList.end();
++iter)
{
@@ -952,7 +952,7 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp)
void LLVOAvatarSelf::idleUpdateTractorBeam()
{
// This is only done for yourself (maybe it should be in the agent?)
- if (!needsRenderBeam() || !mIsBuilt)
+ if (!needsRenderBeam() || !isBuilt())
{
mBeam = NULL;
}
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 75c2743ab0..bdc1ccf133 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -67,7 +67,7 @@ public:
protected:
/*virtual*/ BOOL loadAvatar();
BOOL loadAvatarSelf();
- BOOL buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info);
+ BOOL buildSkeletonSelf(const LLAvatarSkeletonInfo *info);
BOOL buildMenus();
/*virtual*/ BOOL loadLayersets();