/indra/newview/llvoavatar.cpp
C++ | 2117 lines | 1501 code | 311 blank | 305 comment | 187 complexity | b8371880310954f4104c8e87c8f309e3 MD5 | raw file
Possible License(s): LGPL-2.1
- /**
- * @File llvoavatar.cpp
- * @brief Implementation of LLVOAvatar class which is a derivation of LLViewerObject
- *
- * $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$
- */
- #if LL_MSVC
- // disable warning about boost::lexical_cast returning uninitialized data
- // when it fails to parse the string
- #pragma warning (disable:4701)
- #endif
- #include "llviewerprecompiledheaders.h"
- #include "llvoavatar.h"
- #include <stdio.h>
- #include <ctype.h>
- #include "llaudioengine.h"
- #include "noise.h"
- #include "sound_ids.h"
- #include "raytrace.h"
- #include "llagent.h" // Get state values from here
- #include "llagentcamera.h"
- #include "llagentwearables.h"
- #include "llanimationstates.h"
- #include "llavatarnamecache.h"
- #include "llavatarpropertiesprocessor.h"
- #include "llphysicsmotion.h"
- #include "llviewercontrol.h"
- #include "llcallingcard.h" // IDEVO for LLAvatarTracker
- #include "lldrawpoolavatar.h"
- #include "lldriverparam.h"
- #include "lleditingmotion.h"
- #include "llemote.h"
- //#include "llfirstuse.h"
- #include "llfloatertools.h"
- #include "llheadrotmotion.h"
- #include "llhudeffecttrail.h"
- #include "llhudmanager.h"
- #include "llhudnametag.h"
- #include "llhudtext.h" // for mText/mDebugText
- #include "llkeyframefallmotion.h"
- #include "llkeyframestandmotion.h"
- #include "llkeyframewalkmotion.h"
- #include "llmanipscale.h" // for get_default_max_prim_scale()
- #include "llmeshrepository.h"
- #include "llmutelist.h"
- #include "llmoveview.h"
- #include "llnotificationsutil.h"
- #include "llquantize.h"
- #include "llrand.h"
- #include "llregionhandle.h"
- #include "llresmgr.h"
- #include "llselectmgr.h"
- #include "llsprite.h"
- #include "lltargetingmotion.h"
- #include "lltexlayer.h"
- #include "lltoolmorph.h"
- #include "llviewercamera.h"
- #include "llviewertexturelist.h"
- #include "llviewermenu.h"
- #include "llviewerobjectlist.h"
- #include "llviewerparcelmgr.h"
- #include "llviewershadermgr.h"
- #include "llviewerstats.h"
- #include "llvoavatarself.h"
- #include "llvovolume.h"
- #include "llworld.h"
- #include "pipeline.h"
- #include "llviewershadermgr.h"
- #include "llsky.h"
- #include "llanimstatelabels.h"
- #include "lltrans.h"
- #include "llappearancemgr.h"
- #include "llgesturemgr.h" //needed to trigger the voice gesticulations
- #include "llvoiceclient.h"
- #include "llvoicevisualizer.h" // Ventrella
- #include "lldebugmessagebox.h"
- extern F32 SPEED_ADJUST_MAX;
- extern F32 SPEED_ADJUST_MAX_SEC;
- extern F32 ANIM_SPEED_MAX;
- extern F32 ANIM_SPEED_MIN;
- #if LL_MSVC
- // disable boost::lexical_cast warning
- #pragma warning (disable:4702)
- #endif
- #include <boost/lexical_cast.hpp>
- // #define OUTPUT_BREAST_DATA
- using namespace LLVOAvatarDefines;
- //-----------------------------------------------------------------------------
- // Global constants
- //-----------------------------------------------------------------------------
- const LLUUID ANIM_AGENT_BODY_NOISE = LLUUID("9aa8b0a6-0c6f-9518-c7c3-4f41f2c001ad"); //"body_noise"
- const LLUUID ANIM_AGENT_BREATHE_ROT = LLUUID("4c5a103e-b830-2f1c-16bc-224aa0ad5bc8"); //"breathe_rot"
- const LLUUID ANIM_AGENT_EDITING = LLUUID("2a8eba1d-a7f8-5596-d44a-b4977bf8c8bb"); //"editing"
- const LLUUID ANIM_AGENT_EYE = LLUUID("5c780ea8-1cd1-c463-a128-48c023f6fbea"); //"eye"
- const LLUUID ANIM_AGENT_FLY_ADJUST = LLUUID("db95561f-f1b0-9f9a-7224-b12f71af126e"); //"fly_adjust"
- const LLUUID ANIM_AGENT_HAND_MOTION = LLUUID("ce986325-0ba7-6e6e-cc24-b17c4b795578"); //"hand_motion"
- const LLUUID ANIM_AGENT_HEAD_ROT = LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a68d"); //"head_rot"
- const LLUUID ANIM_AGENT_PELVIS_FIX = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b"); //"pelvis_fix"
- const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55"); //"target"
- const LLUUID ANIM_AGENT_WALK_ADJUST = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust"
- const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987"); //"physics_motion"
- //-----------------------------------------------------------------------------
- // Constants
- //-----------------------------------------------------------------------------
- const std::string AVATAR_DEFAULT_CHAR = "avatar";
- const S32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024;
- const F32 SHADOW_OFFSET_AMT = 0.03f;
- const F32 DELTA_TIME_MIN = 0.01f; // we clamp measured deltaTime to this
- const F32 DELTA_TIME_MAX = 0.2f; // range to insure stability of computations.
- const F32 PELVIS_LAG_FLYING = 0.22f;// pelvis follow half life while flying
- const F32 PELVIS_LAG_WALKING = 0.4f; // ...while walking
- const F32 PELVIS_LAG_MOUSELOOK = 0.15f;
- const F32 MOUSELOOK_PELVIS_FOLLOW_FACTOR = 0.5f;
- const F32 PELVIS_LAG_WHEN_FOLLOW_CAM_IS_ON = 0.0001f; // not zero! - something gets divided by this!
- const F32 PELVIS_ROT_THRESHOLD_SLOW = 60.0f; // amount of deviation allowed between
- const F32 PELVIS_ROT_THRESHOLD_FAST = 2.0f; // the pelvis and the view direction
- // when moving fast & slow
- const F32 TORSO_NOISE_AMOUNT = 1.0f; // Amount of deviation from up-axis, in degrees
- const F32 TORSO_NOISE_SPEED = 0.2f; // Time scale factor on torso noise.
- const F32 BREATHE_ROT_MOTION_STRENGTH = 0.05f;
- const F32 BREATHE_SCALE_MOTION_STRENGTH = 0.005f;
- const F32 MIN_SHADOW_HEIGHT = 0.f;
- const F32 MAX_SHADOW_HEIGHT = 0.3f;
- const S32 MIN_REQUIRED_PIXEL_AREA_BODY_NOISE = 10000;
- const S32 MIN_REQUIRED_PIXEL_AREA_BREATHE = 10000;
- const S32 MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX = 40;
- const S32 TEX_IMAGE_SIZE_SELF = 512;
- const S32 TEX_IMAGE_AREA_SELF = TEX_IMAGE_SIZE_SELF * TEX_IMAGE_SIZE_SELF;
- const S32 TEX_IMAGE_SIZE_OTHER = 512 / 4; // The size of local textures for other (!isSelf()) avatars
- const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f;
- const S32 MORPH_MASK_REQUESTED_DISCARD = 0;
- // Discard level at which to switch to baked textures
- // Should probably be 4 or 3, but didn't want to change it while change other logic - SJB
- const S32 SWITCH_TO_BAKED_DISCARD = 5;
- const F32 FOOT_COLLIDE_FUDGE = 0.04f;
- const F32 HOVER_EFFECT_MAX_SPEED = 3.f;
- const F32 HOVER_EFFECT_STRENGTH = 0.f;
- const F32 UNDERWATER_EFFECT_STRENGTH = 0.1f;
- const F32 UNDERWATER_FREQUENCY_DAMP = 0.33f;
- const F32 APPEARANCE_MORPH_TIME = 0.65f;
- const F32 TIME_BEFORE_MESH_CLEANUP = 5.f; // seconds
- const S32 AVATAR_RELEASE_THRESHOLD = 10; // number of avatar instances before releasing memory
- const F32 FOOT_GROUND_COLLISION_TOLERANCE = 0.25f;
- const F32 AVATAR_LOD_TWEAK_RANGE = 0.7f;
- const S32 MAX_BUBBLE_CHAT_LENGTH = DB_CHAT_MSG_STR_LEN;
- const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12;
- const F32 CHAT_FADE_TIME = 8.0;
- const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f;
- const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0);
- enum ERenderName
- {
- RENDER_NAME_NEVER,
- RENDER_NAME_ALWAYS,
- RENDER_NAME_FADE
- };
- //-----------------------------------------------------------------------------
- // Callback data
- //-----------------------------------------------------------------------------
- struct LLTextureMaskData
- {
- LLTextureMaskData( const LLUUID& id ) :
- mAvatarID(id),
- mLastDiscardLevel(S32_MAX)
- {}
- LLUUID mAvatarID;
- S32 mLastDiscardLevel;
- };
- /*********************************************************************************
- ** **
- ** Begin private LLVOAvatar Support classes
- **
- **/
- //------------------------------------------------------------------------
- // 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
- //-----------------------------------------------------------------------------
- class LLBodyNoiseMotion :
- public LLMotion
- {
- public:
- // Constructor
- LLBodyNoiseMotion(const LLUUID &id)
- : LLMotion(id)
- {
- mName = "body_noise";
- mTorsoState = new LLJointState;
- }
- // Destructor
- virtual ~LLBodyNoiseMotion() { }
- public:
- //-------------------------------------------------------------------------
- // functions to support MotionController and MotionRegistry
- //-------------------------------------------------------------------------
- // static constructor
- // all subclasses must implement such a function and register it
- static LLMotion *create(const LLUUID &id) { return new LLBodyNoiseMotion(id); }
- public:
- //-------------------------------------------------------------------------
- // animation callbacks to be implemented by subclasses
- //-------------------------------------------------------------------------
- // motions must specify whether or not they loop
- virtual BOOL getLoop() { return TRUE; }
- // motions must report their total duration
- virtual F32 getDuration() { return 0.0; }
- // motions must report their "ease in" duration
- virtual F32 getEaseInDuration() { return 0.0; }
- // motions must report their "ease out" duration.
- virtual F32 getEaseOutDuration() { return 0.0; }
- // motions must report their priority
- virtual LLJoint::JointPriority getPriority() { return LLJoint::HIGH_PRIORITY; }
- virtual LLMotionBlendType getBlendType() { return ADDITIVE_BLEND; }
- // called to determine when a motion should be activated/deactivated based on avatar pixel coverage
- virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_BODY_NOISE; }
- // run-time (post constructor) initialization,
- // called after parameters have been set
- // must return true to indicate success and be available for activation
- virtual LLMotionInitStatus onInitialize(LLCharacter *character)
- {
- if( !mTorsoState->setJoint( character->getJoint("mTorso") ))
- {
- return STATUS_FAILURE;
- }
- mTorsoState->setUsage(LLJointState::ROT);
- addJointState( mTorsoState );
- return STATUS_SUCCESS;
- }
- // called when a motion is activated
- // must return TRUE to indicate success, or else
- // it will be deactivated
- virtual BOOL onActivate() { return TRUE; }
- // called per time step
- // must return TRUE while it is active, and
- // must return FALSE when the motion is completed.
- virtual BOOL onUpdate(F32 time, U8* joint_mask)
- {
- F32 nx[2];
- nx[0]=time*TORSO_NOISE_SPEED;
- nx[1]=0.0f;
- F32 ny[2];
- ny[0]=0.0f;
- ny[1]=time*TORSO_NOISE_SPEED;
- F32 noiseX = noise2(nx);
- F32 noiseY = noise2(ny);
- F32 rx = TORSO_NOISE_AMOUNT * DEG_TO_RAD * noiseX / 0.42f;
- F32 ry = TORSO_NOISE_AMOUNT * DEG_TO_RAD * noiseY / 0.42f;
- LLQuaternion tQn;
- tQn.setQuat( rx, ry, 0.0f );
- mTorsoState->setRotation( tQn );
- return TRUE;
- }
- // called when a motion is deactivated
- virtual void onDeactivate() {}
- private:
- //-------------------------------------------------------------------------
- // joint states to be animated
- //-------------------------------------------------------------------------
- LLPointer<LLJointState> mTorsoState;
- };
- //-----------------------------------------------------------------------------
- // class LLBreatheMotionRot
- //-----------------------------------------------------------------------------
- class LLBreatheMotionRot :
- public LLMotion
- {
- public:
- // Constructor
- LLBreatheMotionRot(const LLUUID &id) :
- LLMotion(id),
- mBreatheRate(1.f),
- mCharacter(NULL)
- {
- mName = "breathe_rot";
- mChestState = new LLJointState;
- }
- // Destructor
- virtual ~LLBreatheMotionRot() {}
- public:
- //-------------------------------------------------------------------------
- // functions to support MotionController and MotionRegistry
- //-------------------------------------------------------------------------
- // static constructor
- // all subclasses must implement such a function and register it
- static LLMotion *create(const LLUUID &id) { return new LLBreatheMotionRot(id); }
- public:
- //-------------------------------------------------------------------------
- // animation callbacks to be implemented by subclasses
- //-------------------------------------------------------------------------
- // motions must specify whether or not they loop
- virtual BOOL getLoop() { return TRUE; }
- // motions must report their total duration
- virtual F32 getDuration() { return 0.0; }
- // motions must report their "ease in" duration
- virtual F32 getEaseInDuration() { return 0.0; }
- // motions must report their "ease out" duration.
- virtual F32 getEaseOutDuration() { return 0.0; }
- // motions must report their priority
- virtual LLJoint::JointPriority getPriority() { return LLJoint::MEDIUM_PRIORITY; }
- virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; }
- // called to determine when a motion should be activated/deactivated based on avatar pixel coverage
- virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_BREATHE; }
- // run-time (post constructor) initialization,
- // called after parameters have been set
- // must return true to indicate success and be available for activation
- virtual LLMotionInitStatus onInitialize(LLCharacter *character)
- {
- mCharacter = character;
- BOOL success = true;
- if ( !mChestState->setJoint( character->getJoint( "mChest" ) ) ) { success = false; }
- if ( success )
- {
- mChestState->setUsage(LLJointState::ROT);
- addJointState( mChestState );
- }
- if ( success )
- {
- return STATUS_SUCCESS;
- }
- else
- {
- return STATUS_FAILURE;
- }
- }
- // called when a motion is activated
- // must return TRUE to indicate success, or else
- // it will be deactivated
- virtual BOOL onActivate() { return TRUE; }
- // called per time step
- // must return TRUE while it is active, and
- // must return FALSE when the motion is completed.
- virtual BOOL onUpdate(F32 time, U8* joint_mask)
- {
- mBreatheRate = 1.f;
- F32 breathe_amt = (sinf(mBreatheRate * time) * BREATHE_ROT_MOTION_STRENGTH);
- mChestState->setRotation(LLQuaternion(breathe_amt, LLVector3(0.f, 1.f, 0.f)));
- return TRUE;
- }
- // called when a motion is deactivated
- virtual void onDeactivate() {}
- private:
- //-------------------------------------------------------------------------
- // joint states to be animated
- //-------------------------------------------------------------------------
- LLPointer<LLJointState> mChestState;
- F32 mBreatheRate;
- LLCharacter* mCharacter;
- };
- //-----------------------------------------------------------------------------
- // class LLPelvisFixMotion
- //-----------------------------------------------------------------------------
- class LLPelvisFixMotion :
- public LLMotion
- {
- public:
- // Constructor
- LLPelvisFixMotion(const LLUUID &id)
- : LLMotion(id), mCharacter(NULL)
- {
- mName = "pelvis_fix";
- mPelvisState = new LLJointState;
- }
- // Destructor
- virtual ~LLPelvisFixMotion() { }
- public:
- //-------------------------------------------------------------------------
- // functions to support MotionController and MotionRegistry
- //-------------------------------------------------------------------------
- // static constructor
- // all subclasses must implement such a function and register it
- static LLMotion *create(const LLUUID& id) { return new LLPelvisFixMotion(id); }
- public:
- //-------------------------------------------------------------------------
- // animation callbacks to be implemented by subclasses
- //-------------------------------------------------------------------------
- // motions must specify whether or not they loop
- virtual BOOL getLoop() { return TRUE; }
- // motions must report their total duration
- virtual F32 getDuration() { return 0.0; }
- // motions must report their "ease in" duration
- virtual F32 getEaseInDuration() { return 0.5f; }
- // motions must report their "ease out" duration.
- virtual F32 getEaseOutDuration() { return 0.5f; }
- // motions must report their priority
- virtual LLJoint::JointPriority getPriority() { return LLJoint::LOW_PRIORITY; }
- virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; }
- // called to determine when a motion should be activated/deactivated based on avatar pixel coverage
- virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX; }
- // run-time (post constructor) initialization,
- // called after parameters have been set
- // must return true to indicate success and be available for activation
- virtual LLMotionInitStatus onInitialize(LLCharacter *character)
- {
- mCharacter = character;
- if (!mPelvisState->setJoint( character->getJoint("mPelvis")))
- {
- return STATUS_FAILURE;
- }
- mPelvisState->setUsage(LLJointState::POS);
- addJointState( mPelvisState );
- return STATUS_SUCCESS;
- }
- // called when a motion is activated
- // must return TRUE to indicate success, or else
- // it will be deactivated
- virtual BOOL onActivate() { return TRUE; }
- // called per time step
- // must return TRUE while it is active, and
- // must return FALSE when the motion is completed.
- virtual BOOL onUpdate(F32 time, U8* joint_mask)
- {
- mPelvisState->setPosition(LLVector3::zero);
- return TRUE;
- }
- // called when a motion is deactivated
- virtual void onDeactivate() {}
- private:
- //-------------------------------------------------------------------------
- // joint states to be animated
- //-------------------------------------------------------------------------
- LLPointer<LLJointState> mPelvisState;
- LLCharacter* mCharacter;
- };
- /**
- **
- ** End LLVOAvatar Support classes
- ** **
- *********************************************************************************/
- //-----------------------------------------------------------------------------
- // Static Data
- //-----------------------------------------------------------------------------
- LLXmlTree LLVOAvatar::sXMLTree;
- LLXmlTree LLVOAvatar::sSkeletonXMLTree;
- LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL;
- LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL;
- LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL;
- S32 LLVOAvatar::sFreezeCounter = 0;
- U32 LLVOAvatar::sMaxVisible = 12;
- F32 LLVOAvatar::sRenderDistance = 256.f;
- S32 LLVOAvatar::sNumVisibleAvatars = 0;
- S32 LLVOAvatar::sNumLODChangesThisFrame = 0;
- const LLUUID LLVOAvatar::sStepSoundOnLand("e8af4a28-aa83-4310-a7c4-c047e15ea0df");
- const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] =
- {
- SND_STONE_RUBBER,
- SND_METAL_RUBBER,
- SND_GLASS_RUBBER,
- SND_WOOD_RUBBER,
- SND_FLESH_RUBBER,
- SND_RUBBER_PLASTIC,
- SND_RUBBER_RUBBER
- };
- S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS;
- BOOL LLVOAvatar::sRenderGroupTitles = TRUE;
- S32 LLVOAvatar::sNumVisibleChatBubbles = 0;
- BOOL LLVOAvatar::sDebugInvisible = FALSE;
- BOOL LLVOAvatar::sShowAttachmentPoints = FALSE;
- BOOL LLVOAvatar::sShowAnimationDebug = FALSE;
- BOOL LLVOAvatar::sShowFootPlane = FALSE;
- BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE;
- F32 LLVOAvatar::sLODFactor = 1.f;
- F32 LLVOAvatar::sPhysicsLODFactor = 1.f;
- BOOL LLVOAvatar::sUseImpostors = FALSE;
- BOOL LLVOAvatar::sJointDebug = FALSE;
- F32 LLVOAvatar::sUnbakedTime = 0.f;
- F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
- F32 LLVOAvatar::sGreyTime = 0.f;
- F32 LLVOAvatar::sGreyUpdateTime = 0.f;
- //-----------------------------------------------------------------------------
- // Helper functions
- //-----------------------------------------------------------------------------
- static F32 calc_bouncy_animation(F32 x);
- //-----------------------------------------------------------------------------
- // LLVOAvatar()
- //-----------------------------------------------------------------------------
- LLVOAvatar::LLVOAvatar(const LLUUID& id,
- const LLPCode pcode,
- LLViewerRegion* regionp) :
- LLViewerObject(id, pcode, regionp),
- mIsDummy(FALSE),
- mSpecialRenderMode(0),
- mTurning(FALSE),
- mPelvisToFoot(0.f),
- mLastSkeletonSerialNum( 0 ),
- mHeadOffset(),
- mIsSitting(FALSE),
- mTimeVisible(),
- mTyping(FALSE),
- mMeshValid(FALSE),
- mVisible(FALSE),
- mWindFreq(0.f),
- mRipplePhase( 0.f ),
- mBelowWater(FALSE),
- mLastAppearanceBlendTime(0.f),
- mAppearanceAnimating(FALSE),
- mNameString(),
- mTitle(),
- mNameAway(false),
- mNameBusy(false),
- mNameMute(false),
- mNameAppearance(false),
- mNameFriend(false),
- mNameAlpha(0.f),
- mRenderGroupTitles(sRenderGroupTitles),
- mNameCloud(false),
- mFirstTEMessageReceived( FALSE ),
- mFirstAppearanceMessageReceived( FALSE ),
- mCulled( FALSE ),
- mVisibilityRank(0),
- mTexSkinColor( NULL ),
- mTexHairColor( NULL ),
- mTexEyeColor( NULL ),
- mNeedsSkin(FALSE),
- mLastSkinTime(0.f),
- mUpdatePeriod(1),
- mFullyLoaded(FALSE),
- mPreviousFullyLoaded(FALSE),
- mFullyLoadedInitialized(FALSE),
- mSupportsAlphaLayers(FALSE),
- mLoadedCallbacksPaused(FALSE),
- mHasPelvisOffset( FALSE ),
- mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar"))
- {
- LLMemType mt(LLMemType::MTYPE_AVATAR);
- //VTResume(); // VTune
-
- // mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline
- const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
- mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim );
- lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl;
- mPelvisp = NULL;
- mBakedTextureDatas.resize(BAKED_NUM_INDICES);
- for (U32 i = 0; i < mBakedTextureDatas.size(); i++ )
- {
- mBakedTextureDatas[i].mLastTextureIndex = IMG_DEFAULT_AVATAR;
- mBakedTextureDatas[i].mTexLayerSet = NULL;
- mBakedTextureDatas[i].mIsLoaded = false;
- mBakedTextureDatas[i].mIsUsed = false;
- mBakedTextureDatas[i].mMaskTexName = 0;
- mBakedTextureDatas[i].mTextureIndex = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i);
- }
- mDirtyMesh = 2; // Dirty geometry, need to regenerate.
- mMeshTexturesDirty = FALSE;
- mHeadp = NULL;
- mIsBuilt = FALSE;
- mNumJoints = 0;
- mSkeleton = NULL;
- mNumCollisionVolumes = 0;
- mCollisionVolumes = NULL;
- // set up animation variables
- mSpeed = 0.f;
- setAnimationData("Speed", &mSpeed);
- mNeedsImpostorUpdate = TRUE;
- mNeedsAnimUpdate = TRUE;
- mImpostorDistance = 0;
- mImpostorPixelArea = 0;
- setNumTEs(TEX_NUM_INDICES);
- mbCanSelect = TRUE;
- mSignaledAnimations.clear();
- mPlayingAnimations.clear();
- mWasOnGroundLeft = FALSE;
- mWasOnGroundRight = FALSE;
- mTimeLast = 0.0f;
- mSpeedAccum = 0.0f;
- mRippleTimeLast = 0.f;
- mInAir = FALSE;
- mStepOnLand = TRUE;
- mStepMaterial = 0;
- mLipSyncActive = false;
- mOohMorph = NULL;
- mAahMorph = NULL;
- mCurrentGesticulationLevel = 0;
- mRuthTimer.reset();
- mRuthDebugTimer.reset();
- mDebugExistenceTimer.reset();
- mPelvisOffset = LLVector3(0.0f,0.0f,0.0f);
- mLastPelvisToFoot = 0.0f;
- mPelvisFixup = 0.0f;
- mLastPelvisFixup = 0.0f;
- }
- //------------------------------------------------------------------------
- // LLVOAvatar::~LLVOAvatar()
- //------------------------------------------------------------------------
- LLVOAvatar::~LLVOAvatar()
- {
- if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
- {
- if (!mFullyLoaded)
- {
- llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left after " << (U32)mRuthDebugTimer.getElapsedTimeF32() << " seconds as cloud." << llendl;
- LLSD args;
- args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
- args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32());
- args["NAME"] = getFullname();
- LLNotificationsUtil::add("AvatarRezLeftCloudNotification",args);
- }
- else
- {
- llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left." << llendl;
- LLSD args;
- args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
- args["NAME"] = getFullname();
- LLNotificationsUtil::add("AvatarRezLeftNotification",args);
- }
- }
- lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl;
- mRoot.removeAllChildren();
- deleteAndClearArray(mSkeleton);
- deleteAndClearArray(mCollisionVolumes);
- mNumJoints = 0;
- for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
- {
- deleteAndClear(mBakedTextureDatas[i].mTexLayerSet);
- mBakedTextureDatas[i].mMeshes.clear();
- for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin();
- iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++)
- {
- LLMaskedMorph* masked_morph = (*iter2);
- delete masked_morph;
- }
- }
- 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();
- LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
- lldebugs << "LLVOAvatar Destructor end" << llendl;
- }
- void LLVOAvatar::markDead()
- {
- if (mNameText)
- {
- mNameText->markDead();
- mNameText = NULL;
- sNumVisibleChatBubbles--;
- }
- mVoiceVisualizer->markDead();
- LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
- LLViewerObject::markDead();
- }
- BOOL LLVOAvatar::isFullyBaked()
- {
- if (mIsDummy) return TRUE;
- if (getNumTEs() == 0) return FALSE;
- for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
- {
- if (!isTextureDefined(mBakedTextureDatas[i].mTextureIndex)
- && ( (i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) ) )
- {
- return FALSE;
- }
- }
- return TRUE;
- }
- void LLVOAvatar::deleteLayerSetCaches(bool clearAll)
- {
- for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
- {
- if (mBakedTextureDatas[i].mTexLayerSet)
- {
- // ! BACKWARDS COMPATIBILITY !
- // Can be removed after hair baking is mandatory on the grid
- if ((i != BAKED_HAIR || isSelf()) && !clearAll)
- {
- mBakedTextureDatas[i].mTexLayerSet->deleteCaches();
- }
- }
- if (mBakedTextureDatas[i].mMaskTexName)
- {
- glDeleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName));
- mBakedTextureDatas[i].mMaskTexName = 0 ;
- }
- }
- }
- // static
- BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars)
- {
- BOOL res = TRUE;
- grey_avatars = 0;
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* inst = (LLVOAvatar*) *iter;
- if( inst->isDead() )
- {
- continue;
- }
- else if( !inst->isFullyBaked() )
- {
- res = FALSE;
- if (inst->mHasGrey)
- {
- ++grey_avatars;
- }
- }
- }
- return res;
- }
- // static
- void LLVOAvatar::dumpBakedStatus()
- {
- LLVector3d camera_pos_global = gAgentCamera.getCameraPositionGlobal();
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* inst = (LLVOAvatar*) *iter;
- llinfos << "Avatar ";
- LLNameValue* firstname = inst->getNVPair("FirstName");
- LLNameValue* lastname = inst->getNVPair("LastName");
- if( firstname )
- {
- llcont << firstname->getString();
- }
- if( lastname )
- {
- llcont << " " << lastname->getString();
- }
- llcont << " " << inst->mID;
- if( inst->isDead() )
- {
- llcont << " DEAD ("<< inst->getNumRefs() << " refs)";
- }
- if( inst->isSelf() )
- {
- llcont << " (self)";
- }
- F64 dist_to_camera = (inst->getPositionGlobal() - camera_pos_global).length();
- llcont << " " << dist_to_camera << "m ";
- llcont << " " << inst->mPixelArea << " pixels";
- if( inst->isVisible() )
- {
- llcont << " (visible)";
- }
- else
- {
- llcont << " (not visible)";
- }
- if( inst->isFullyBaked() )
- {
- llcont << " Baked";
- }
- else
- {
- llcont << " Unbaked (";
-
- for (LLVOAvatarDictionary::BakedTextures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
- iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- ++iter)
- {
- const LLVOAvatarDictionary::BakedEntry *baked_dict = iter->second;
- const ETextureIndex index = baked_dict->mTextureIndex;
- if (!inst->isTextureDefined(index))
- {
- llcont << " " << LLVOAvatarDictionary::getInstance()->getTexture(index)->mName;
- }
- }
- llcont << " ) " << inst->getUnbakedPixelAreaRank();
- if( inst->isCulled() )
- {
- llcont << " culled";
- }
- }
- llcont << llendl;
- }
- }
- //static
- void LLVOAvatar::restoreGL()
- {
- if (!isAgentAvatarValid()) return;
- gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
- for (U32 i = 0; i < gAgentAvatarp->mBakedTextureDatas.size(); i++)
- {
- gAgentAvatarp->invalidateComposite(gAgentAvatarp->mBakedTextureDatas[i].mTexLayerSet, FALSE);
- }
- gAgentAvatarp->updateMeshTextures();
- }
- //static
- void LLVOAvatar::destroyGL()
- {
- deleteCachedImages();
- resetImpostors();
- }
- //static
- void LLVOAvatar::resetImpostors()
- {
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* avatar = (LLVOAvatar*) *iter;
- avatar->mImpostor.release();
- }
- }
- // static
- void LLVOAvatar::deleteCachedImages(bool clearAll)
- {
- if (LLTexLayerSet::sHasCaches)
- {
- lldebugs << "Deleting layer set caches" << llendl;
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* inst = (LLVOAvatar*) *iter;
- inst->deleteLayerSetCaches(clearAll);
- }
- LLTexLayerSet::sHasCaches = FALSE;
- }
- LLVOAvatarSelf::deleteScratchTextures();
- LLTexLayerStaticImageList::getInstance()->deleteCachedImages();
- }
- //------------------------------------------------------------------------
- // static
- // LLVOAvatar::initClass()
- //------------------------------------------------------------------------
- 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");
- gAnimLibrary.animStateSetString(ANIM_AGENT_EDITING,"editing");
- gAnimLibrary.animStateSetString(ANIM_AGENT_EYE,"eye");
- gAnimLibrary.animStateSetString(ANIM_AGENT_FLY_ADJUST,"fly_adjust");
- gAnimLibrary.animStateSetString(ANIM_AGENT_HAND_MOTION,"hand_motion");
- gAnimLibrary.animStateSetString(ANIM_AGENT_HEAD_ROT,"head_rot");
- gAnimLibrary.animStateSetString(ANIM_AGENT_PELVIS_FIX,"pelvis_fix");
- gAnimLibrary.animStateSetString(ANIM_AGENT_TARGET,"target");
- gAnimLibrary.animStateSetString(ANIM_AGENT_WALK_ADJUST,"walk_adjust");
- }
- void LLVOAvatar::cleanupClass()
- {
- deleteAndClear(sAvatarXmlInfo);
- sSkeletonXMLTree.cleanup();
- sXMLTree.cleanup();
- }
- void LLVOAvatar::initInstance(void)
- {
- //-------------------------------------------------------------------------
- // initialize joint, mesh and shape members
- //-------------------------------------------------------------------------
- mRoot.setName( "mRoot" );
-
- for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
- iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- ++iter)
- {
- const EMeshIndex mesh_index = iter->first;
- const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second;
- LLViewerJoint* joint = new LLViewerJoint();
- joint->setName(mesh_dict->mName);
- joint->setMeshID(mesh_index);
- mMeshLOD.push_back(joint);
-
- /* mHairLOD.setName("mHairLOD");
- mHairMesh0.setName("mHairMesh0");
- mHairMesh0.setMeshID(MESH_ID_HAIR);
- mHairMesh1.setName("mHairMesh1"); */
- for (U32 lod = 0; lod < mesh_dict->mLOD; lod++)
- {
- LLViewerJointMesh* mesh = new LLViewerJointMesh();
- std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast<std::string>(lod);
- // We pre-pended an m - need to capitalize first character for camelCase
- mesh_name[1] = toupper(mesh_name[1]);
- mesh->setName(mesh_name);
- mesh->setMeshID(mesh_index);
- mesh->setPickName(mesh_dict->mPickName);
- mesh->setIsTransparent(FALSE);
- switch((int)mesh_index)
- {
- case MESH_ID_HAIR:
- mesh->setIsTransparent(TRUE);
- break;
- case MESH_ID_SKIRT:
- mesh->setIsTransparent(TRUE);
- break;
- case MESH_ID_EYEBALL_LEFT:
- case MESH_ID_EYEBALL_RIGHT:
- mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
- break;
- }
-
- joint->mMeshParts.push_back(mesh);
- }
- }
-
- //-------------------------------------------------------------------------
- // associate baked textures with meshes
- //-------------------------------------------------------------------------
- for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
- iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- ++iter)
- {
- const EMeshIndex mesh_index = iter->first;
- const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second;
- const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID;
- // 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();
- iter != mMeshLOD[mesh_index]->mMeshParts.end();
- ++iter)
- {
- LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter;
- mBakedTextureDatas[(int)baked_texture_index].mMeshes.push_back(mesh);
- }
- }
-
-
- //-------------------------------------------------------------------------
- // register motions
- //-------------------------------------------------------------------------
- if (LLCharacter::sInstances.size() == 1)
- {
- LLKeyframeMotion::setVFS(gStaticVFS);
- registerMotion( ANIM_AGENT_BUSY, LLNullMotion::create );
- registerMotion( ANIM_AGENT_CROUCH, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_CROUCHWALK, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_EXPRESS_AFRAID, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_ANGER, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_BORED, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_CRY, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_DISDAIN, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_EMBARRASSED, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_FROWN, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_KISS, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_LAUGH, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_OPEN_MOUTH, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_REPULSED, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_SAD, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_SHRUG, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_SMILE, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_SURPRISE, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_TONGUE_OUT, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_TOOTHSMILE, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_WINK, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_WORRY, LLEmote::create );
- registerMotion( ANIM_AGENT_FEMALE_RUN_NEW, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_FEMALE_WALK_NEW, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_RUN, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_RUN_NEW, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_STAND, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STAND_1, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STAND_2, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STAND_3, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STAND_4, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STANDUP, LLKeyframeFallMotion::create );
- registerMotion( ANIM_AGENT_TURNLEFT, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_TURNRIGHT, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_WALK, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_WALK_NEW, LLKeyframeWalkMotion::create );
-
- // motions without a start/stop bit
- registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create );
- registerMotion( ANIM_AGENT_BREATHE_ROT, LLBreatheMotionRot::create );
- registerMotion( ANIM_AGENT_PHYSICS_MOTION, LLPhysicsMotionController::create );
- registerMotion( ANIM_AGENT_EDITING, LLEditingMotion::create );
- registerMotion( ANIM_AGENT_EYE, LLEyeMotion::create );
- registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_FLY_ADJUST, LLFlyAdjustMotion::create );
- registerMotion( ANIM_AGENT_HAND_MOTION, LLHandMotion::create );
- registerMotion( ANIM_AGENT_HEAD_ROT, LLHeadRotMotion::create );
- registerMotion( ANIM_AGENT_PELVIS_FIX, LLPelvisFixMotion::create );
- registerMotion( ANIM_AGENT_SIT_FEMALE, LLKeyframeMotion::create );
- registerMotion( ANIM_AGENT_TARGET, LLTargetingMotion::create );
- registerMotion( ANIM_AGENT_WALK_ADJUST, LLWalkAdjustMotion::create );
-
- }
-
- buildCharacter();
-
- // preload specific motions here
- createMotion( ANIM_AGENT_CUSTOMIZE);
- createMotion( ANIM_AGENT_CUSTOMIZE_DONE);
-
- //VTPause(); // VTune
-
- mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) );
- }
- const LLVector3 LLVOAvatar::getRenderPosition() const
- {
- if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
- {
- return getPositionAgent();
- }
- else if (isRoot())
- {
- if ( !mHasPelvisOffset )
- {
- return mDrawable->getPositionAgent();
- }
- else
- {
- //Apply a pelvis fixup (as defined by the avs skin)
- LLVector3 pos = mDrawable->getPositionAgent();
- pos[VZ] += mPelvisFixup;
- return pos;
- }
- }
- else
- {
- return getPosition() * mDrawable->getParent()->getRenderMatrix();
- }
- }
- void LLVOAvatar::updateDrawable(BOOL force_damped)
- {
- clearChanged(SHIFTED);
- }
- void LLVOAvatar::onShift(const LLVector4a& shift_vector)
- {
- const LLVector3& shift = reinterpret_cast<const LLVector3&>(shift_vector);
- mLastAnimExtents[0] += shift;
- mLastAnimExtents[1] += shift;
- mNeedsImpostorUpdate = TRUE;
- mNeedsAnimUpdate = TRUE;
- }
- void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
- {
- if (isImpostor() && !needsImpostorUpdate())
- {
- LLVector3 delta = getRenderPosition() -
- ((LLVector3(mDrawable->getPositionGroup().getF32ptr())-mImpostorOffset));
-
- newMin.load3( (mLastAnimExtents[0] + delta).mV);
- newMax.load3( (mLastAnimExtents[1] + delta).mV);
- }
- else
- {
- getSpatialExtents(newMin,newMax);
- mLastAnimExtents[0].set(newMin.getF32ptr());
- mLastAnimExtents[1].set(newMax.getF32ptr());
- LLVector4a pos_group;
- pos_group.setAdd(newMin,newMax);
- pos_group.mul(0.5f);
- mImpostorOffset = LLVector3(pos_group.getF32ptr())-getRenderPosition();
- mDrawable->setPositionGroup(pos_group);
- }
- }
- void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
- {
- LLVector4a buffer(0.25f);
- LLVector4a pos;
- pos.load3(getRenderPosition().mV);
- newMin.setSub(pos, buffer);
- newMax.setAdd(pos, buffer);
- float max_attachment_span = get_default_max_prim_scale() * 5.0f;
-
- //stretch bounding box by joint positions
- for (polymesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i)
- {
- LLPolyMesh* mesh = i->second;
- for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.count(); joint_num++)
- {
- LLVector4a trans;
- trans.load3( mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation().mV);
- update_min_max(newMin, newMax, trans);
- }
- }
- LLVector4a center, size;
- center.setAdd(newMin, newMax);
- center.mul(0.5f);
- size.setSub(newMax,newMin);
- size.mul(0.5f);
- mPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance());
- //stretch bounding box by attachments
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- if (!attachment->getValid())
- {
- continue ;
- }
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- const LLViewerObject* attached_object = (*attachment_iter);
- if (attached_object && !attached_object->isHUDAttachment())
- {
- LLDrawable* drawable = attached_object->mDrawable;
- if (drawable && !drawable->isState(LLDrawable::RIGGED))
- {
- LLSpatialBridge* bridge = drawable->getSpatialBridge();
- if (bridge)
- {
- const LLVector4a* ext = bridge->getSpatialExtents();
- LLVector4a distance;
- distance.setSub(ext[1], ext[0]);
- LLVector4a max_span(max_attachment_span);
- S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7;
-
- // Only add the prim to spatial extents calculations if it isn't a megaprim.
- // max_attachment_span calculated at the start of the function
- // (currently 5 times our max prim size)
- if (lt == 0x7)
- {
- update_min_max(newMin,newMax,ext[0]);
- update_min_max(newMin,newMax,ext[1]);
- }
- }
- }
- }
- }
- }
- //pad bounding box
- newMin.sub(buffer);
- newMax.add(buffer);
- }
- //-----------------------------------------------------------------------------
- // renderCollisionVolumes()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::renderCollisionVolumes()
- {
- for (S32 i = 0; i < mNumCollisionVolumes; i++)
- {
- mCollisionVolumes[i].renderCollision();
- }
- if (mNameText.notNull())
- {
- LLVector3 unused;
- mNameText->lineSegmentIntersect(LLVector3(0,0,0), LLVector3(0,0,1), unused, TRUE);
- }
- }
- BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
- S32 face,
- BOOL pick_transparent,
- S32* face_hit,
- LLVector3* intersection,
- LLVector2* tex_coord,
- LLVector3* normal,
- LLVector3* bi_normal)
- {
- if ((isSelf() && !gAgent.needsRenderAvatar()) || !LLPipeline::sPickAvatar)
- {
- return FALSE;
- }
- if (lineSegmentBoundingBox(start, end))
- {
- for (S32 i = 0; i < mNumCollisionVolumes; ++i)
- {
- mCollisionVolumes[i].updateWorldMatrix();
- glh::matrix4f mat((F32*) mCollisionVolumes[i].getXform()->getWorldMatrix().mMatrix);
- glh::matrix4f inverse = mat.inverse();
- glh::matrix4f norm_mat = inverse.transpose();
- glh::vec3f p1(start.mV);
- glh::vec3f p2(end.mV);
- inverse.mult_matrix_vec(p1);
- inverse.mult_matrix_vec(p2);
- LLVector3 position;
- LLVector3 norm;
- if (linesegment_sphere(LLVector3(p1.v), LLVector3(p2.v), LLVector3(0,0,0), 1.f, position, norm))
- {
- glh::vec3f res_pos(position.mV);
- mat.mult_matrix_vec(res_pos);
-
- norm.normalize();
- glh::vec3f res_norm(norm.mV);
- norm_mat.mult_matrix_dir(res_norm);
- if (intersection)
- {
- *intersection = LLVector3(res_pos.v);
- }
- if (normal)
- {
- *normal = LLVector3(res_norm.v);
- }
- return TRUE;
- }
- }
- if (isSelf())
- {
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- LLViewerObject* attached_object = (*attachment_iter);
-
- if (attached_object && !attached_object->isDead() && attachment->getValid())
- {
- LLDrawable* drawable = attached_object->mDrawable;
- if (drawable->isState(LLDrawable::RIGGED))
- { //regenerate octree for rigged attachment
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE);
- }
- }
- }
- }
- }
- }
-
-
- LLVector3 position;
- if (mNameText.notNull() && mNameText->lineSegmentIntersect(start, end, position))
- {
- if (intersection)
- {
- *intersection = position;
- }
- return TRUE;
- }
- return FALSE;
- }
- LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector3& start, const LLVector3& end,
- S32 face,
- BOOL pick_transparent,
- S32* face_hit,
- LLVector3* intersection,
- LLVector2* tex_coord,
- LLVector3* normal,
- LLVector3* bi_normal)
- {
- if (isSelf() && !gAgent.needsRenderAvatar())
- {
- return NULL;
- }
- LLViewerObject* hit = NULL;
- if (lineSegmentBoundingBox(start, end))
- {
- LLVector3 local_end = end;
- LLVector3 local_intersection;
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- LLViewerObject* attached_object = (*attachment_iter);
-
- if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, face_hit, &local_intersection, tex_coord, normal, bi_normal))
- {
- local_end = local_intersection;
- if (intersection)
- {
- *intersection = local_intersection;
- }
-
- hit = attached_object;
- }
- }
- }
- }
-
- 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;
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::startDefaultMotions()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::startDefaultMotions()
- {
- //-------------------------------------------------------------------------
- // start default motions
- //-------------------------------------------------------------------------
- startMotion( ANIM_AGENT_HEAD_ROT );
- startMotion( ANIM_AGENT_EYE );
- startMotion( ANIM_AGENT_BODY_NOISE );
- startMotion( ANIM_AGENT_BREATHE_ROT );
- startMotion( ANIM_AGENT_PHYSICS_MOTION );
- startMotion( ANIM_AGENT_HAND_MOTION );
- startMotion( ANIM_AGENT_PELVIS_FIX );
- //-------------------------------------------------------------------------
- // restart any currently active motions
- //-------------------------------------------------------------------------
- processAnimationStateChanges();
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::buildCharacter()
- // Deferred initialization and rebuild of the avatar.
- //-----------------------------------------------------------------------------
- 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();
- mIsBuilt = FALSE;
- //-------------------------------------------------------------------------
- // clear mesh data
- //-------------------------------------------------------------------------
- for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin();
- jointIter != mMeshLOD.end(); ++jointIter)
- {
- LLViewerJoint* joint = (LLViewerJoint*) *jointIter;
- for (std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin();
- meshIter != joint->mMeshParts.end(); ++meshIter)
- {
- LLViewerJointMesh * mesh = (LLViewerJointMesh *) *meshIter;
- mesh->setMesh(NULL);
- }
- }
- //-------------------------------------------------------------------------
- // (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");
- //-------------------------------------------------------------------------
- // 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();
- //-------------------------------------------------------------------------
- // initialize lip sync morph pointers
- //-------------------------------------------------------------------------
- mOohMorph = getVisualParam( "Lipsync_Ooh" );
- mAahMorph = getVisualParam( "Lipsync_Aah" );
- // If we don't have the Ooh morph, use the Kiss morph
- if (!mOohMorph)
- {
- llwarns << "Missing 'Ooh' morph for lipsync, using fallback." << llendl;
- mOohMorph = getVisualParam( "Express_Kiss" );
- }
- // If we don't have the Aah morph, use the Open Mouth morph
- if (!mAahMorph)
- {
- llwarns << "Missing 'Aah' morph for lipsync, using fallback." << llendl;
- mAahMorph = getVisualParam( "Express_Open_Mouth" );
- }
- startDefaultMotions();
- //-------------------------------------------------------------------------
- // restart any currently active motions
- //-------------------------------------------------------------------------
- processAnimationStateChanges();
- mIsBuilt = TRUE;
- stop_glerror();
- mMeshValid = TRUE;
- }
- //-----------------------------------------------------------------------------
- // releaseMeshData()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::releaseMeshData()
- {
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || mIsDummy)
- {
- return;
- }
- //llinfos << "Releasing" << llendl;
- // cleanup mesh data
- for (std::vector<LLViewerJoint*>::iterator iter = mMeshLOD.begin();
- iter != mMeshLOD.end();
- ++iter)
- {
- LLViewerJoint* joint = (LLViewerJoint*) *iter;
- joint->setValid(FALSE, TRUE);
- }
- //cleanup data
- if (mDrawable.notNull())
- {
- LLFace* facep = mDrawable->getFace(0);
- facep->setSize(0, 0);
- for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++)
- {
- facep = mDrawable->getFace(i);
- facep->setSize(0, 0);
- }
- }
-
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- if (!attachment->getIsHUDAttachment())
- {
- attachment->setAttachmentVisibility(FALSE);
- }
- }
- mMeshValid = FALSE;
- }
- //-----------------------------------------------------------------------------
- // restoreMeshData()
- //-----------------------------------------------------------------------------
- // virtual
- void LLVOAvatar::restoreMeshData()
- {
- llassert(!isSelf());
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- //llinfos << "Restoring" << llendl;
- mMeshValid = TRUE;
- updateJointLODs();
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- if (!attachment->getIsHUDAttachment())
- {
- attachment->setAttachmentVisibility(TRUE);
- }
- }
- // force mesh update as LOD might not have changed to trigger this
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
- }
- //-----------------------------------------------------------------------------
- // updateMeshData()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::updateMeshData()
- {
- if (mDrawable.notNull())
- {
- stop_glerror();
- S32 f_num = 0 ;
- const U32 VERTEX_NUMBER_THRESHOLD = 128 ;//small number of this means each part of an avatar has its own vertex buffer.
- const S32 num_parts = mMeshLOD.size();
- // this order is determined by number of LODS
- // if a mesh earlier in this list changed LODs while a later mesh doesn't,
- // the later mesh's index offset will be inaccurate
- for(S32 part_index = 0 ; part_index < num_parts ;)
- {
- S32 j = part_index ;
- U32 last_v_num = 0, num_vertices = 0 ;
- U32 last_i_num = 0, num_indices = 0 ;
- while(part_index < num_parts && num_vertices < VERTEX_NUMBER_THRESHOLD)
- {
- last_v_num = num_vertices ;
- last_i_num = num_indices ;
- mMeshLOD[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
- }
- if(num_vertices < 1)//skip empty meshes
- {
- continue ;
- }
- if(last_v_num > 0)//put the last inserted part into next vertex buffer.
- {
- num_vertices = last_v_num ;
- num_indices = last_i_num ;
- part_index-- ;
- }
-
- LLFace* facep ;
- if(f_num < mDrawable->getNumFaces())
- {
- facep = mDrawable->getFace(f_num);
- }
- else
- {
- facep = mDrawable->addFace(mDrawable->getFace(0)->getPool(), mDrawable->getFace(0)->getTexture()) ;
- }
-
- // resize immediately
- facep->setSize(num_vertices, num_indices);
- bool terse_update = false;
- facep->setGeomIndex(0);
- facep->setIndicesIndex(0);
-
- LLVertexBuffer* buff = facep->getVertexBuffer();
- if(!facep->getVertexBuffer())
- {
- buff = new LLVertexBufferAvatar();
- buff->allocateBuffer(num_vertices, num_indices, TRUE);
- facep->se