diff options
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
-rw-r--r-- | indra/newview/llvoavatar.cpp | 3875 |
1 files changed, 1448 insertions, 2427 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3757923e27..8d20e4e91c 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -32,175 +32,112 @@ #include "llviewerprecompiledheaders.h" -#include <algorithm> -#include <vector> -#include "llstl.h" - #include "llvoavatar.h" -#include "llrender.h" +#include <stdio.h> +#include <ctype.h> + #include "audioengine.h" -#include "imageids.h" -#include "indra_constants.h" -#include "llchat.h" -#include "llfontgl.h" -#include "llprimitive.h" -#include "lltextureentry.h" -#include "message.h" #include "noise.h" -#include "sound_ids.h" -#include "lltimer.h" -#include "timing.h" -#include "llagent.h" // Get state values from here +#include "llagent.h" // Get state values from here #include "llviewercontrol.h" -#include "llcriticaldamp.h" -#include "lldir.h" -#include "lldrawable.h" #include "lldrawpoolavatar.h" -#include "lldrawpoolalpha.h" -#include "lldrawpoolbump.h" #include "lldriverparam.h" #include "lleditingmotion.h" #include "llemote.h" -#include "llface.h" -#include "llfasttimer.h" #include "llfirstuse.h" -#include "llfloatercustomize.h" -#include "llfloatertools.h" -#include "llgldbg.h" -#include "llhandmotion.h" #include "llheadrotmotion.h" -#include "llhudeffectbeam.h" -#include "llhudeffectlookat.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" -#include "llhudtext.h" -#include "llinventorymodel.h" #include "llinventoryview.h" #include "llkeyframefallmotion.h" -#include "llkeyframemotion.h" -#include "llkeyframemotionparam.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" -#include "llmenugl.h" #include "llmutelist.h" -#include "llnetmap.h" -#include "llnotify.h" -#include "llquantize.h" -#include "llregionhandle.h" -#include "llresmgr.h" #include "llselectmgr.h" -#include "llsky.h" #include "llsprite.h" -#include "llstatusbar.h" #include "lltargetingmotion.h" #include "lltexlayer.h" -#include "lltoolgrab.h" // for needsRenderBeam -#include "lltoolmgr.h" // for needsRenderBeam +#include "lltoolgrab.h" // for needsRenderBeam +#include "lltoolmgr.h" // for needsRenderBeam #include "lltoolmorph.h" #include "llviewercamera.h" #include "llviewerimagelist.h" -#include "llviewerinventory.h" #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" -#include "llviewerregion.h" #include "llviewerstats.h" -#include "llviewerwindow.h" -#include "llvosky.h" #include "llvovolume.h" -#include "llwearable.h" -#include "llwearablelist.h" #include "llworld.h" #include "pipeline.h" -#include "llspatialpartition.h" #include "llviewershadermgr.h" -#include "llappviewer.h" #include "llsky.h" #include "llanimstatelabels.h" - -//#include "vtune/vtuneapi.h" - #include "llgesturemgr.h" //needed to trigger the voice gesticulations -#include "llvoicevisualizer.h" #include "llvoiceclient.h" +#include "llvoicevisualizer.h" // Ventrella -LLXmlTree LLVOAvatar::sXMLTree; -LLXmlTree LLVOAvatar::sSkeletonXMLTree; -LLVOAvatarSkeletonInfo* LLVOAvatar::sSkeletonInfo = NULL; -LLVOAvatarInfo* LLVOAvatar::sAvatarInfo = NULL; +#include "boost/lexical_cast.hpp" + +using namespace LLVOAvatarDefines; -BOOL gDebugAvatarRotation = FALSE; -S32 LLVOAvatar::sFreezeCounter = 0 ; +//----------------------------------------------------------------------------- +// 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" -//extern BOOL gVelocityInterpolate; //----------------------------------------------------------------------------- // Constants //----------------------------------------------------------------------------- -const F32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024; +const std::string AVATAR_DEFAULT_CHAR = "avatar"; -F32 SHADOW_OFFSET_AMT = 0.03f; +const S32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024; +const F32 SHADOW_OFFSET_AMT = 0.03f; -#define DELTA_TIME_MIN 0.01f // we clamp measured deltaTime to this -#define DELTA_TIME_MAX 0.2f // range to insure stability of computations. +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! -#define PELVIS_ROT_THRESHOLD_SLOW 60.0f // amount of deviation allowed between -#define PELVIS_ROT_THRESHOLD_FAST 2.0f // the pelvis and the view direction +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 MIN_SPEED_PELVIS_FOLLOW = 0.1f; - -#define TORSO_NOISE_AMOUNT 1.f // Amount of deviation from up-axis, in degrees -#define TORSO_NOISE_SPEED 0.2f // Time scale factor on torso noise. +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; -#define PELVIS_NOISE_FACTOR 0.5f // amount of random noise - -#define AUDIO_STEP_PRI 0xC0000000 -#define AUDIO_STEP_LO_SPEED 0.01f // as average speed goes from lo to hi, -#define AUDIO_STEP_HI_SPEED 3.0f // from lo to hi -#define AUDIO_STEP_LO_GAIN 0.15f // the resulting gain will ramp linearly -#define AUDIO_STEP_HI_GAIN 0.15f - -const F32 DAMPED_MOTION_TIME_SCALE = 0.15f; - -const F32 LOOKAT_CAMERA_DIST_SQUARED = 25.f; - -#define AVATAR_HEADER "Linden Avatar 1.0" -#define AVATAR_SECTION "[avatar]" - -#define AVATAR_DEFAULT_CHAR "avatar" - const F32 MIN_SHADOW_HEIGHT = 0.f; const F32 MAX_SHADOW_HEIGHT = 0.3f; -#define MIN_REQUIRED_PIXEL_AREA_BODY_NOISE (10000.f) -#define MIN_REQUIRED_PIXEL_AREA_BREATHE (10000.f) -#define MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX (40.f) +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 LOCTEX_IMAGE_SIZE_SELF = 512; -const S32 LOCTEX_IMAGE_AREA_SELF = LOCTEX_IMAGE_SIZE_SELF * LOCTEX_IMAGE_SIZE_SELF; -const S32 LOCTEX_IMAGE_SIZE_OTHER = LOCTEX_IMAGE_SIZE_SELF / 4; // The size of local textures for other (!mIsSelf) avatars -const S32 LOCTEX_IMAGE_AREA_OTHER = LOCTEX_IMAGE_SIZE_OTHER * LOCTEX_IMAGE_SIZE_OTHER; +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 = TEX_IMAGE_SIZE_SELF / 4; // The size of local textures for other (!mIsSelf) avatars +const S32 TEX_IMAGE_AREA_OTHER = TEX_IMAGE_SIZE_OTHER * TEX_IMAGE_SIZE_OTHER; const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f; const S32 MORPH_MASK_REQUESTED_DISCARD = 0; -const S32 MIN_PIXEL_AREA_BUMP = 500; // 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 @@ -210,95 +147,34 @@ const F32 FOOT_COLLIDE_FUDGE = 0.04f; const F32 HOVER_EFFECT_MAX_SPEED = 3.f; const F32 HOVER_EFFECT_STRENGTH = 0.f; -F32 UNDERWATER_EFFECT_STRENGTH = 0.1f; +const F32 UNDERWATER_EFFECT_STRENGTH = 0.1f; const F32 UNDERWATER_FREQUENCY_DAMP = 0.33f; const F32 APPEARANCE_MORPH_TIME = 0.65f; -const F32 CAMERA_SHAKE_ACCEL_THRESHOLD_SQUARED = 5.f * 5.f; 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_LOD_CHANGES_PER_FRAME = 2; const S32 MAX_BUBBLE_CHAT_LENGTH = 1023; 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 S32 MAX_BUBBLES = 7; -S32 LLVOAvatar::sMaxVisible = 50; - -LLVOAvatar::ETextureIndex LLVOAvatar::sBakedTextureIndices[BAKED_TEXTURE_COUNT] = +enum ERenderName { - LLVOAvatar::TEX_HEAD_BAKED, - LLVOAvatar::TEX_UPPER_BAKED, - LLVOAvatar::TEX_LOWER_BAKED, - LLVOAvatar::TEX_EYES_BAKED, - LLVOAvatar::TEX_SKIRT_BAKED + RENDER_NAME_NEVER, + RENDER_NAME_FADE, + RENDER_NAME_ALWAYS }; //----------------------------------------------------------------------------- -// Utility functions -//----------------------------------------------------------------------------- - -static F32 calc_bouncy_animation(F32 x) -{ - return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f; -} - -BOOL LLLineSegmentCapsuleIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& p1, const LLVector3& p2, const F32& radius, LLVector3& result) -{ - return FALSE; -} - -//----------------------------------------------------------------------------- -// Static Data +// Callback data //----------------------------------------------------------------------------- -S32 LLVOAvatar::sMaxOtherAvatarsToComposite = 1; // Only this many avatars (other than yourself) can be composited at a time. Set in initClass(). -LLMap< LLGLenum, LLGLuint*> LLVOAvatar::sScratchTexNames; -LLMap< LLGLenum, F32*> LLVOAvatar::sScratchTexLastBindTime; -S32 LLVOAvatar::sScratchTexBytes = 0; -F32 LLVOAvatar::sRenderDistance = 256.f; -S32 LLVOAvatar::sNumVisibleAvatars = 0; -S32 LLVOAvatar::sNumLODChangesThisFrame = 0; - -LLUUID LLVOAvatar::sStepSoundOnLand = LLUUID("e8af4a28-aa83-4310-a7c4-c047e15ea0df"); -LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = -{ - LLUUID(SND_STONE_RUBBER), - LLUUID(SND_METAL_RUBBER), - LLUUID(SND_GLASS_RUBBER), - LLUUID(SND_WOOD_RUBBER), - LLUUID(SND_FLESH_RUBBER), - LLUUID(SND_RUBBER_PLASTIC), - LLUUID(SND_RUBBER_RUBBER) -}; - -// static -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::sShowCollisionVolumes = FALSE; -BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; -F32 LLVOAvatar::sLODFactor = 1.f; -BOOL LLVOAvatar::sUseImpostors = FALSE; -BOOL LLVOAvatar::sJointDebug = FALSE; -S32 LLVOAvatar::sCurJoint = 0; -S32 LLVOAvatar::sCurVolume = 0; -F32 LLVOAvatar::sUnbakedTime = 0.f; -F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; -F32 LLVOAvatar::sGreyTime = 0.f; -F32 LLVOAvatar::sGreyUpdateTime = 0.f; - struct LLAvatarTexData { - LLAvatarTexData( const LLUUID& id, LLVOAvatar::ELocTexIndex index ) + LLAvatarTexData( const LLUUID& id, ETextureIndex index ) : mAvatarID(id), mIndex(index) {} LLUUID mAvatarID; - LLVOAvatar::ELocTexIndex mIndex; + ETextureIndex mIndex; }; struct LLTextureMaskData @@ -309,6 +185,142 @@ struct LLTextureMaskData S32 mLastDiscardLevel; }; +/********************************************************************************* + ** ** + ** Begin 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; +}; + + +//------------------------------------------------------------------------ +// LLVOAvatarXmlInfo +// One instance (in LLVOAvatar) with common data parsed from the XML files +//------------------------------------------------------------------------ +class LLVOAvatarXmlInfo +{ + friend class LLVOAvatar; +public: + LLVOAvatarXmlInfo(); + ~LLVOAvatarXmlInfo(); + +private: + BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); + BOOL parseXmlMeshNodes(LLXmlTreeNode* root); + BOOL parseXmlColorNodes(LLXmlTreeNode* root); + BOOL parseXmlLayerNodes(LLXmlTreeNode* root); + BOOL parseXmlDriverNodes(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; +}; //----------------------------------------------------------------------------- // class LLBodyNoiseMotion @@ -322,7 +334,6 @@ public: : LLMotion(id) { mName = "body_noise"; - mTorsoState = new LLJointState; } @@ -409,7 +420,7 @@ public: // called when a motion is deactivated virtual void onDeactivate() {} -public: +private: //------------------------------------------------------------------------- // joint states to be animated //------------------------------------------------------------------------- @@ -430,12 +441,11 @@ public: mCharacter(NULL) { mName = "breathe_rot"; - mChestState = new LLJointState; } // Destructor - virtual ~LLBreatheMotionRot() { } + virtual ~LLBreatheMotionRot() {} public: //------------------------------------------------------------------------- @@ -518,7 +528,7 @@ public: // called when a motion is deactivated virtual void onDeactivate() {} -public: +private: //------------------------------------------------------------------------- // joint states to be animated //------------------------------------------------------------------------- @@ -615,7 +625,7 @@ public: // called when a motion is deactivated virtual void onDeactivate() {} -public: +private: //------------------------------------------------------------------------- // joint states to be animated //------------------------------------------------------------------------- @@ -623,20 +633,74 @@ public: LLCharacter* mCharacter; }; +/** + ** + ** End LLVOAvatar Support classes + ** ** + *********************************************************************************/ + + +//----------------------------------------------------------------------------- +// Static Data +//----------------------------------------------------------------------------- +LLXmlTree LLVOAvatar::sXMLTree; +LLXmlTree LLVOAvatar::sSkeletonXMLTree; +BOOL LLVOAvatar::sDebugAvatarRotation = FALSE; +LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL; +LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL; +LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; +S32 LLVOAvatar::sFreezeCounter = 0; +S32 LLVOAvatar::sMaxVisible = 50; +LLMap< LLGLenum, LLGLuint*> LLVOAvatar::sScratchTexNames; +LLMap< LLGLenum, F32*> LLVOAvatar::sScratchTexLastBindTime; +S32 LLVOAvatar::sScratchTexBytes = 0; +F32 LLVOAvatar::sRenderDistance = 256.f; +S32 LLVOAvatar::sNumVisibleAvatars = 0; +S32 LLVOAvatar::sNumLODChangesThisFrame = 0; + +const LLUUID LLVOAvatar::sStepSoundOnLand = LLUUID("e8af4a28-aa83-4310-a7c4-c047e15ea0df"); +const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = +{ + LLUUID(SND_STONE_RUBBER), + LLUUID(SND_METAL_RUBBER), + LLUUID(SND_GLASS_RUBBER), + LLUUID(SND_WOOD_RUBBER), + LLUUID(SND_FLESH_RUBBER), + LLUUID(SND_RUBBER_PLASTIC), + LLUUID(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::sShowCollisionVolumes = FALSE; +BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; +F32 LLVOAvatar::sLODFactor = 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); +static U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures); + //----------------------------------------------------------------------------- // LLVOAvatar() //----------------------------------------------------------------------------- -LLVOAvatar::LLVOAvatar( - const LLUUID& id, - const LLPCode pcode, - LLViewerRegion* regionp) - : +LLVOAvatar::LLVOAvatar(const LLUUID& id, + const LLPCode pcode, + LLViewerRegion* regionp) : LLViewerObject(id, pcode, regionp), - mLastHeadBakedID( IMG_DEFAULT_AVATAR ), - mLastUpperBodyBakedID( IMG_DEFAULT_AVATAR ), - mLastLowerBodyBakedID( IMG_DEFAULT_AVATAR ), - mLastEyesBakedID( IMG_DEFAULT_AVATAR ), - mLastSkirtBakedID( IMG_DEFAULT_AVATAR ), mIsDummy(FALSE), mSpecialRenderMode(0), mTurning(FALSE), @@ -654,12 +718,6 @@ LLVOAvatar::LLVOAvatar( mAppearanceAnimSetByUser(FALSE), mLastAppearanceBlendTime(0.f), mAppearanceAnimating(FALSE), - mHeadLayerSet( NULL ), - mUpperBodyLayerSet( NULL ), - mLowerBodyLayerSet( NULL ), - mEyesLayerSet( NULL ), - mSkirtLayerSet( NULL ), - mRenderPriority(1.0f), mNameString(), mTitle(), mNameAway(FALSE), @@ -671,17 +729,6 @@ LLVOAvatar::LLVOAvatar( mRegionCrossingCount(0), mFirstTEMessageReceived( FALSE ), mFirstAppearanceMessageReceived( FALSE ), - mHeadBakedLoaded(FALSE), - mHeadMaskDiscard(-1), - mUpperBakedLoaded(FALSE), - mUpperMaskDiscard(-1), - mLowerBakedLoaded(FALSE), - mLowerMaskDiscard(-1), - mEyesBakedLoaded(FALSE), - mSkirtBakedLoaded(FALSE), - mHeadMaskTexName(0), - mUpperMaskTexName(0), - mLowerMaskTexName(0), mCulled( FALSE ), mVisibilityRank(0), mTexSkinColor( NULL ), @@ -689,24 +736,36 @@ LLVOAvatar::LLVOAvatar( mTexEyeColor( NULL ), mNeedsSkin(FALSE), mUpdatePeriod(1), - mFullyLoadedInitialized(FALSE) + mFullyLoadedInitialized(FALSE), + mHasBakedHair( FALSE ) { LLMemType mt(LLMemType::MTYPE_AVATAR); - //VTResume(); // VTune // mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline - bool needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job + 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; - for( S32 i=0; i<LOCTEX_NUM_ENTRIES; i++ ) + for( S32 i=0; i<TEX_NUM_INDICES; i++ ) + { + if (isIndexLocalTexture((ETextureIndex)i)) + { + mLocalTextureData[(ETextureIndex)i] = LocalTextureData(); + } + } + + mBakedTextureData.resize(BAKED_NUM_INDICES); + for (U32 i = 0; i < mBakedTextureData.size(); i++ ) { - mLocalTextureBaked[i] = FALSE; - mLocalTextureDiscard[i] = MAX_DISCARD_LEVEL+1; + mBakedTextureData[i].mLastTextureIndex = IMG_DEFAULT_AVATAR; + mBakedTextureData[i].mTexLayerSet = NULL; + mBakedTextureData[i].mIsLoaded = false; + mBakedTextureData[i].mMaskTexName = 0; + mBakedTextureData[i].mTextureIndex = getTextureIndex((EBakedTextureIndex)i); } mDirtyMesh = TRUE; // Dirty geometry, need to regenerate. @@ -744,7 +803,7 @@ LLVOAvatar::LLVOAvatar( mImpostorDistance = 0; mImpostorPixelArea = 0; - setNumTEs(TEX_NUM_ENTRIES); + setNumTEs(TEX_NUM_INDICES); mbCanSelect = TRUE; @@ -777,118 +836,71 @@ LLVOAvatar::LLVOAvatar( //------------------------------------------------------------------------- mRoot.setName( "mRoot" ); - // skinned mesh objects - mHairLOD.setName("mHairLOD"); - mHairMesh0.setName("mHairMesh0"); - mHairMesh0.setMeshID(MESH_ID_HAIR); - mHairMesh1.setName("mHairMesh1"); - mHairMesh2.setName("mHairMesh2"); - mHairMesh3.setName("mHairMesh3"); - mHairMesh4.setName("mHairMesh4"); - mHairMesh5.setName("mHairMesh5"); - - mHairMesh0.setIsTransparent(TRUE); - mHairMesh1.setIsTransparent(TRUE); - mHairMesh2.setIsTransparent(TRUE); - mHairMesh3.setIsTransparent(TRUE); - mHairMesh4.setIsTransparent(TRUE); - mHairMesh5.setIsTransparent(TRUE); - - mHeadLOD.setName("mHeadLOD"); - mHeadMesh0.setName("mHeadMesh0"); - mHeadMesh0.setMeshID(MESH_ID_HEAD); - mHeadMesh1.setName("mHeadMesh1"); - mHeadMesh2.setName("mHeadMesh2"); - mHeadMesh3.setName("mHeadMesh3"); - mHeadMesh4.setName("mHeadMesh4"); - - mEyeLashLOD.setName("mEyeLashLOD"); - mEyeLashMesh0.setName("mEyeLashMesh0"); - mEyeLashMesh0.setMeshID(MESH_ID_HEAD); - mEyeLashMesh0.setIsTransparent(TRUE); - - mUpperBodyLOD.setName("mUpperBodyLOD"); - mUpperBodyMesh0.setName("mUpperBodyMesh0"); - mUpperBodyMesh0.setMeshID(MESH_ID_UPPER_BODY); - mUpperBodyMesh1.setName("mUpperBodyMesh1"); - mUpperBodyMesh2.setName("mUpperBodyMesh2"); - mUpperBodyMesh3.setName("mUpperBodyMesh3"); - mUpperBodyMesh4.setName("mUpperBodyMesh4"); - - mLowerBodyLOD.setName("mLowerBodyLOD"); - mLowerBodyMesh0.setName("mLowerBodyMesh0"); - mLowerBodyMesh0.setMeshID(MESH_ID_LOWER_BODY); - mLowerBodyMesh1.setName("mLowerBodyMesh1"); - mLowerBodyMesh2.setName("mLowerBodyMesh2"); - mLowerBodyMesh3.setName("mLowerBodyMesh3"); - mLowerBodyMesh4.setName("mLowerBodyMesh4"); - - mEyeBallLeftLOD.setName("mEyeBallLeftLOD"); - mEyeBallLeftMesh0.setName("mEyeBallLeftMesh0"); - mEyeBallLeftMesh1.setName("mEyeBallLeftMesh1"); - - mEyeBallRightLOD.setName("mEyeBallRightLOD"); - mEyeBallRightMesh0.setName("mEyeBallRightMesh0"); - mEyeBallRightMesh1.setName("mEyeBallRightMesh1"); - - mSkirtLOD.setName("mSkirtLOD"); - mSkirtMesh0.setName("mSkirtMesh0"); - mSkirtMesh0.setMeshID(MESH_ID_SKIRT); - mSkirtMesh1.setName("mSkirtMesh1"); - mSkirtMesh2.setName("mSkirtMesh2"); - mSkirtMesh3.setName("mSkirtMesh3"); - mSkirtMesh4.setName("mSkirtMesh4"); - - mSkirtMesh0.setIsTransparent(TRUE); - mSkirtMesh1.setIsTransparent(TRUE); - mSkirtMesh2.setIsTransparent(TRUE); - mSkirtMesh3.setIsTransparent(TRUE); - mSkirtMesh4.setIsTransparent(TRUE); - - // set the pick names for the avatar - mHeadMesh0.setPickName( LLViewerJoint::PN_0 ); - mHeadMesh1.setPickName( LLViewerJoint::PN_0 ); - mHeadMesh2.setPickName( LLViewerJoint::PN_0 ); - mHeadMesh3.setPickName( LLViewerJoint::PN_0 ); - mHeadMesh4.setPickName( LLViewerJoint::PN_0 ); - mEyeLashMesh0.setPickName( LLViewerJoint::PN_0 ); - - mUpperBodyMesh0.setPickName( LLViewerJoint::PN_1 ); - mUpperBodyMesh1.setPickName( LLViewerJoint::PN_1 ); - mUpperBodyMesh2.setPickName( LLViewerJoint::PN_1 ); - mUpperBodyMesh3.setPickName( LLViewerJoint::PN_1 ); - mUpperBodyMesh4.setPickName( LLViewerJoint::PN_1 ); - - mLowerBodyMesh0.setPickName( LLViewerJoint::PN_2 ); - mLowerBodyMesh1.setPickName( LLViewerJoint::PN_2 ); - mLowerBodyMesh2.setPickName( LLViewerJoint::PN_2 ); - mLowerBodyMesh3.setPickName( LLViewerJoint::PN_2 ); - mLowerBodyMesh4.setPickName( LLViewerJoint::PN_2 ); - - mEyeBallLeftMesh0.setPickName( LLViewerJoint::PN_3 ); - mEyeBallLeftMesh1.setPickName( LLViewerJoint::PN_3 ); - mEyeBallRightMesh0.setPickName( LLViewerJoint::PN_3 ); - mEyeBallRightMesh1.setPickName( LLViewerJoint::PN_3 ); - - mHairMesh0.setPickName( LLViewerJoint::PN_4); - mHairMesh1.setPickName( LLViewerJoint::PN_4); - mHairMesh2.setPickName( LLViewerJoint::PN_4); - mHairMesh3.setPickName( LLViewerJoint::PN_4); - mHairMesh4.setPickName( LLViewerJoint::PN_4); - mHairMesh5.setPickName( LLViewerJoint::PN_4); - - mSkirtMesh0.setPickName( LLViewerJoint::PN_5 ); - mSkirtMesh1.setPickName( LLViewerJoint::PN_5 ); - mSkirtMesh2.setPickName( LLViewerJoint::PN_5 ); - mSkirtMesh3.setPickName( LLViewerJoint::PN_5 ); - mSkirtMesh4.setPickName( LLViewerJoint::PN_5 ); - - // material settings - - mEyeBallLeftMesh0.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); - mEyeBallLeftMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); - mEyeBallRightMesh0.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); - mEyeBallRightMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); + for (LLVOAvatarDictionary::mesh_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); + iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); + iter++) + { + const EMeshIndex mesh_index = iter->first; + const LLVOAvatarDictionary::MeshDictionaryEntry *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); + 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::mesh_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); + iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); + iter++) + { + const EMeshIndex mesh_index = iter->first; + const LLVOAvatarDictionary::MeshDictionaryEntry *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; + mBakedTextureData[(int)baked_texture_index].mMeshes.push_back(mesh); + } + } + //------------------------------------------------------------------------- // register motions @@ -987,20 +999,11 @@ LLVOAvatar::~LLVOAvatar() mNumJoints = 0; - delete mHeadLayerSet; - mHeadLayerSet = NULL; - - delete mUpperBodyLayerSet; - mUpperBodyLayerSet = NULL; - - delete mLowerBodyLayerSet; - mLowerBodyLayerSet = NULL; - - delete mEyesLayerSet; - mEyesLayerSet = NULL; - - delete mSkirtLayerSet; - mSkirtLayerSet = NULL; + for (U32 i = 0; i < mBakedTextureData.size(); i++) + { + delete mBakedTextureData[i].mTexLayerSet; + mBakedTextureData[i].mTexLayerSet = NULL; + } std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); mAttachmentPoints.clear(); @@ -1014,6 +1017,16 @@ LLVOAvatar::~LLVOAvatar() 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; @@ -1045,45 +1058,34 @@ BOOL LLVOAvatar::isFullyBaked() { if (mIsDummy) return TRUE; if (getNumTEs() == 0) return FALSE; - - BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - if (isWearingWearableType(WT_SKIRT)) - { - return head_baked && upper_baked && lower_baked && eyes_baked && skirt_baked; - } - else + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - return head_baked && upper_baked && lower_baked && eyes_baked; + if (!isTextureDefined(mBakedTextureData[i].mTextureIndex) + && ( (i != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ) ) + { + return FALSE; + } } + return TRUE; } -void LLVOAvatar::deleteLayerSetCaches() +void LLVOAvatar::deleteLayerSetCaches(bool clearAll) { - if( mHeadLayerSet ) mHeadLayerSet->deleteCaches(); - if( mUpperBodyLayerSet ) mUpperBodyLayerSet->deleteCaches(); - if( mLowerBodyLayerSet ) mLowerBodyLayerSet->deleteCaches(); - if( mEyesLayerSet ) mEyesLayerSet->deleteCaches(); - if( mSkirtLayerSet ) mSkirtLayerSet->deleteCaches(); - - if(mUpperMaskTexName) - { - glDeleteTextures(1, (GLuint*)&mUpperMaskTexName); - mUpperMaskTexName = 0 ; - } - if(mHeadMaskTexName) - { - glDeleteTextures(1, (GLuint*)&mHeadMaskTexName); - mHeadMaskTexName = 0 ; - } - if(mLowerMaskTexName) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - glDeleteTextures(1, (GLuint*)&mLowerMaskTexName); - mLowerMaskTexName = 0 ; + if (mBakedTextureData[i].mTexLayerSet) + { + if ((i != BAKED_HAIR || mIsSelf) && !clearAll) // Backwards compatibility - can be removed after hair baking is mandatory on the grid + { + mBakedTextureData[i].mTexLayerSet->deleteCaches(); + } + } + if (mBakedTextureData[i].mMaskTexName) + { + glDeleteTextures(1, (GLuint*)&(mBakedTextureData[i].mMaskTexName)); + mBakedTextureData[i].mMaskTexName = 0 ; + } } } @@ -1154,7 +1156,7 @@ void LLVOAvatar::dumpBakedStatus() llcont << " DEAD ("<< inst->getNumRefs() << " refs)"; } - if( inst->mIsSelf ) + if( inst->isSelf() ) { llcont << " (self)"; } @@ -1181,130 +1183,26 @@ void LLVOAvatar::dumpBakedStatus() else { llcont << " Unbaked ("; - if( inst->getTEImage( TEX_HEAD_BAKED )->getID() == IMG_DEFAULT_AVATAR ) - { - llcont << " head"; - } - - if( inst->getTEImage( TEX_UPPER_BAKED )->getID() == IMG_DEFAULT_AVATAR ) - { - llcont << " upper"; - } - - if( inst->getTEImage( TEX_LOWER_BAKED )->getID() == IMG_DEFAULT_AVATAR ) - { - llcont << " lower"; - } - - if( inst->getTEImage( TEX_EYES_BAKED )->getID() == IMG_DEFAULT_AVATAR ) - { - llcont << " eyes"; - } - - if (inst->isWearingWearableType(WT_SKIRT)) + + for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + iter++) { - if( inst->getTEImage( TEX_SKIRT_BAKED )->getID() == IMG_DEFAULT_AVATAR ) + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = iter->second; + const ETextureIndex index = baked_dict->mTextureIndex; + if (!inst->isTextureDefined(index)) { - llcont << " skirt"; + llcont << " " << LLVOAvatarDictionary::getInstance()->getTexture(index)->mName; } } - llcont << " ) " << inst->getUnbakedPixelAreaRank() << "/" << LLVOAvatar::sMaxOtherAvatarsToComposite; + llcont << " ) " << inst->getUnbakedPixelAreaRank(); if( inst->isCulled() ) { llcont << " culled"; } } llcont << llendl; -/* - if( inst->isDead() ) - { - llinfos << "DEAD LIST " << llendl; - - - for( S32 i = 0; i < inst->mOwners.count(); i++ ) - { - llinfos << i << llendl; - LLPointer<LLViewerObject>* owner = (LLPointer<LLViewerObject>*)(inst->mOwners[i]); - LLPointer<LLViewerObject>* cur; - if( !owner->mName.isEmpty() ) - { - llinfos << " " << owner->mName << llendl; - } - - LLViewerObject* key_vo; - for( key_vo = gObjectList.mActiveObjects.getFirstKey(); key_vo; key_vo = gObjectList.mActiveObjects.getNextKey() ) - { - cur = &(gObjectList.mActiveObjects.getCurrentDataWithoutIncrement()); - if( cur == owner ) - { - llinfos << " gObjectList.mActiveObjects" << llendl; - } - } - - for( key_vo = gObjectList.mAvatarObjects.getFirstKey(); key_vo; key_vo = gObjectList.mAvatarObjects.getNextKey() ) - { - cur = &(gObjectList.mAvatarObjects.getCurrentDataWithoutIncrement()); - if( cur == owner ) - { - llinfos << " gObjectList.mAvatarObjects" << llendl; - } - } - - LLUUID id; - for( id = gObjectList.mDeadObjects.getFirstKey(); id; id = gObjectList.mDeadObjects.getNextKey() ) - { - cur = &(gObjectList.mDeadObjects.getCurrentDataWithoutIncrement()); - if( cur == owner ) - { - llinfos << " gObjectList.mDeadObjects" << llendl; - } - } - - - for( id = gObjectList.mUUIDObjectMap.getFirstKey(); id; id = gObjectList.mUUIDObjectMap.getNextKey() ) - { - cur = &(gObjectList.mUUIDObjectMap.getCurrentDataWithoutIncrement()); - if( cur == owner ) - { - llinfos << " gObjectList.mUUIDObjectMap" << llendl; - } - } - - S32 j; - S32 k; - for( j = 0; j < 16; j++ ) - { - for( k = 0; k < 10; k++ ) - { - cur = &(gObjectList.mCloseObjects[j][k]); - if( cur == owner ) - { - llinfos << " gObjectList.mCloseObjects" << llendl; - } - } - } - - for( j = 0; j < gObjectList.mObjects.count(); j++ ) - { - cur = &(gObjectList.mObjects[j]); - if( cur == owner ) - { - llinfos << " gObjectList.mObjects" << llendl; - } - } - - for( j = 0; j < gObjectList.mMapObjects.count(); j++ ) - { - cur = &(gObjectList.mMapObjects[j]); - if( cur == owner ) - { - llinfos << " gObjectList.mMapObjects" << llendl; - } - } - } - } - */ } } @@ -1316,11 +1214,10 @@ void LLVOAvatar::restoreGL() { LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->setCompositeUpdatesEnabled( TRUE ); - inst->invalidateComposite( inst->mHeadLayerSet, FALSE ); - inst->invalidateComposite( inst->mLowerBodyLayerSet, FALSE ); - inst->invalidateComposite( inst->mUpperBodyLayerSet, FALSE ); - inst->invalidateComposite( inst->mEyesLayerSet, FALSE ); - inst->invalidateComposite( inst->mSkirtLayerSet, FALSE ); + for (U32 i = 0; i < inst->mBakedTextureData.size(); i++) + { + inst->invalidateComposite( inst->mBakedTextureData[i].mTexLayerSet, FALSE ); + } inst->updateMeshTextures(); } } @@ -1345,7 +1242,7 @@ void LLVOAvatar::resetImpostors() } // static -void LLVOAvatar::deleteCachedImages() +void LLVOAvatar::deleteCachedImages(bool clearAll) { if (LLTexLayerSet::sHasCaches) { @@ -1354,12 +1251,12 @@ void LLVOAvatar::deleteCachedImages() iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; - inst->deleteLayerSetCaches(); + inst->deleteLayerSetCaches(clearAll); } LLTexLayerSet::sHasCaches = FALSE; } - for( LLGLuint * namep = sScratchTexNames.getFirstData(); + for( LLGLuint* namep = sScratchTexNames.getFirstData(); namep; namep = sScratchTexNames.getNextData() ) { @@ -1387,8 +1284,6 @@ void LLVOAvatar::deleteCachedImages() //------------------------------------------------------------------------ void LLVOAvatar::initClass() { - LLVOAvatar::sMaxOtherAvatarsToComposite = gSavedSettings.getS32("AvatarCompositeLimit"); - std::string xmlFile; xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml"; @@ -1452,44 +1347,45 @@ void LLVOAvatar::initClass() // Process XML data // avatar_skeleton.xml - llassert(!sSkeletonInfo); - sSkeletonInfo = new LLVOAvatarSkeletonInfo; - if (!sSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) + llassert(!sAvatarSkeletonInfo); + sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; + if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) { llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; } // parse avatar_lad.xml - llassert(!sAvatarInfo); - sAvatarInfo = new LLVOAvatarInfo; - if (!sAvatarInfo->parseXmlSkeletonNode(root)) + llassert(!sAvatarXmlInfo); + sAvatarXmlInfo = new LLVOAvatarXmlInfo; + if (!sAvatarXmlInfo->parseXmlSkeletonNode(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } - if (!sAvatarInfo->parseXmlMeshNodes(root)) + if (!sAvatarXmlInfo->parseXmlMeshNodes(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } - if (!sAvatarInfo->parseXmlColorNodes(root)) + if (!sAvatarXmlInfo->parseXmlColorNodes(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } - if (!sAvatarInfo->parseXmlLayerNodes(root)) + if (!sAvatarXmlInfo->parseXmlLayerNodes(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } - if (!sAvatarInfo->parseXmlDriverNodes(root)) + if (!sAvatarXmlInfo->parseXmlDriverNodes(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } + } void LLVOAvatar::cleanupClass() { - delete sAvatarInfo; - sAvatarInfo = NULL; - delete sSkeletonInfo; - sSkeletonInfo = NULL; + delete sAvatarXmlInfo; + sAvatarXmlInfo = NULL; + delete sAvatarSkeletonInfo; + sAvatarSkeletonInfo = NULL; sSkeletonXMLTree.cleanup(); sXMLTree.cleanup(); } @@ -1552,7 +1448,7 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax) newMax = pos + buffer; //stretch bounding box by joint positions - for (mesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i) + 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++) @@ -1571,7 +1467,7 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax) { LLViewerJointAttachment* attachment = iter->second; - if(!attachment->getValid()) + if (!attachment->getValid()) { continue ; } @@ -1688,7 +1584,6 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e return FALSE; } - //----------------------------------------------------------------------------- // parseSkeletonFile() //----------------------------------------------------------------------------- @@ -1732,7 +1627,7 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) //----------------------------------------------------------------------------- // setupBone() //----------------------------------------------------------------------------- -BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) +BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) { LLMemType mt(LLMemType::MTYPE_AVATAR); @@ -1740,7 +1635,7 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) if (info->mIsJoint) { - joint = (LLViewerJoint*)getCharacterJoint(sCurJoint); + joint = (LLViewerJoint*)getCharacterJoint(joint_num); if (!joint) { llwarns << "Too many bones" << llendl; @@ -1750,12 +1645,12 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) } else // collision volume { - if (sCurVolume >= (S32)mNumCollisionVolumes) + if (volume_num >= (S32)mNumCollisionVolumes) { llwarns << "Too many bones" << llendl; return FALSE; } - joint = (LLViewerJoint*)(&mCollisionVolumes[sCurVolume]); + joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]); joint->setName( info->mName ); } @@ -1777,19 +1672,19 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) if (info->mIsJoint) { joint->setSkinOffset( info->mPivot ); - sCurJoint++; + joint_num++; } else // collision volume { - sCurVolume++; + volume_num++; } // setup children - LLVOAvatarBoneInfo::child_list_t::iterator iter; + 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)) + if (!setupBone(child_info, joint, volume_num, joint_num)) { return FALSE; } @@ -1801,7 +1696,7 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) //----------------------------------------------------------------------------- // buildSkeleton() //----------------------------------------------------------------------------- -BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info) +BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) { LLMemType mt(LLMemType::MTYPE_AVATAR); @@ -1826,14 +1721,13 @@ BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info) } } - sCurJoint = 0; - sCurVolume = 0; - - LLVOAvatarSkeletonInfo::bone_info_list_t::iterator iter; + 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)) + if (!setupBone(info, NULL, current_volume_num, current_joint_num)) { llerrs << "Error parsing bone in skeleton file" << llendl; return FALSE; @@ -1899,43 +1793,17 @@ void LLVOAvatar::buildCharacter() //------------------------------------------------------------------------- // clear mesh data //------------------------------------------------------------------------- - mHairMesh0.setMesh(NULL); - mHairMesh1.setMesh(NULL); - mHairMesh2.setMesh(NULL); - mHairMesh3.setMesh(NULL); - mHairMesh4.setMesh(NULL); - mHairMesh5.setMesh(NULL); - - mHeadMesh0.setMesh(NULL); - mHeadMesh1.setMesh(NULL); - mHeadMesh2.setMesh(NULL); - mHeadMesh3.setMesh(NULL); - mHeadMesh4.setMesh(NULL); - - mEyeLashMesh0.setMesh(NULL); - - mUpperBodyMesh0.setMesh(NULL); - mUpperBodyMesh1.setMesh(NULL); - mUpperBodyMesh2.setMesh(NULL); - mUpperBodyMesh3.setMesh(NULL); - mUpperBodyMesh4.setMesh(NULL); - - mLowerBodyMesh0.setMesh(NULL); - mLowerBodyMesh1.setMesh(NULL); - mLowerBodyMesh2.setMesh(NULL); - mLowerBodyMesh3.setMesh(NULL); - mLowerBodyMesh4.setMesh(NULL); - - mEyeBallLeftMesh0.setMesh(NULL); - mEyeBallLeftMesh1.setMesh(NULL); - mEyeBallRightMesh0.setMesh(NULL); - mEyeBallRightMesh1.setMesh(NULL); - - mSkirtMesh0.setMesh(NULL); - mSkirtMesh1.setMesh(NULL); - mSkirtMesh2.setMesh(NULL); - mSkirtMesh3.setMesh(NULL); - mSkirtMesh4.setMesh(NULL); + 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 @@ -2046,7 +1914,12 @@ void LLVOAvatar::buildCharacter() } startDefaultMotions(); - + + //------------------------------------------------------------------------- + // restart any currently active motions + //------------------------------------------------------------------------- + processAnimationStateChanges(); + mIsBuilt = TRUE; stop_glerror(); @@ -2260,21 +2133,18 @@ void LLVOAvatar::releaseMeshData() //llinfos << "Releasing" << llendl; // cleanup mesh data - mHairLOD.setValid(FALSE, TRUE); - mHeadLOD.setValid(FALSE, TRUE); - mEyeLashLOD.setValid(FALSE, TRUE); - mUpperBodyLOD.setValid(FALSE, TRUE); - mLowerBodyLOD.setValid(FALSE, TRUE); - mEyeBallLeftLOD.setValid(FALSE, TRUE); - mEyeBallRightLOD.setValid(FALSE, TRUE); - mSkirtLOD.setValid(FALSE, TRUE); + 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); @@ -2337,34 +2207,25 @@ void LLVOAvatar::updateMeshData() { stop_glerror(); - LLViewerJoint* av_parts[8] ; - av_parts[0] = &mEyeBallLeftLOD ; - av_parts[1] = &mEyeBallRightLOD ; - av_parts[2] = &mEyeLashLOD ; - av_parts[3] = &mHeadLOD ; - av_parts[4] = &mLowerBodyLOD ; - av_parts[5] = &mSkirtLOD ; - av_parts[6] = &mUpperBodyLOD ; - av_parts[7] = &mHairLOD ; - 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 < 8 ;) + 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 < 8 && num_vertices < VERTEX_NUMBER_THRESHOLD) + while(part_index < num_parts && num_vertices < VERTEX_NUMBER_THRESHOLD) { last_v_num = num_vertices ; last_i_num = num_indices ; - av_parts[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mMeshLOD[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); } if(num_vertices < 1)//skip empty meshes { @@ -2412,7 +2273,7 @@ void LLVOAvatar::updateMeshData() for(S32 k = j ; k < part_index ; k++) { - av_parts[k]->updateFaceData(facep, mAdjustedPixelArea, (k == 7)); + mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR); } stop_glerror(); @@ -2536,27 +2397,6 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, //llinfos << getRotation() << llendl; //llinfos << getPosition() << llendl; - if (update_type == OUT_FULL ) - { - if( !mIsSelf || !mFirstTEMessageReceived ) - { -// dumpAvatarTEs( "PRE processUpdateMessage()" ); - unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); -// dumpAvatarTEs( "POST processUpdateMessage()" ); - - if( !mFirstTEMessageReceived ) - { - onFirstTEMessageReceived(); - } - - // Disable updates to composites. We'll decide whether we need to do - // any updates after we find out whether this update message has any - // "baked" (pre-composited) textures. - setCompositeUpdatesEnabled( FALSE ); - updateMeshTextures(); - setCompositeUpdatesEnabled( TRUE ); - } - } return retval; } @@ -2566,7 +2406,7 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) { // The core setTETexture() method requests images, so we need // to redirect certain avatar texture requests to different sims. - if (isTextureIndexBaked(te)) + if (isIndexBakedTexture((ETextureIndex)te)) { LLHost target_host = getObjectHost(); return setTETextureCore(te, uuid, target_host); @@ -2865,15 +2705,12 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } } - if (mDrawable.notNull()) + mDrawable->movePartition(); + + //force a move if sitting on an active object + if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) { - mDrawable->movePartition(); - - //force a move if sitting on an active object - if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) - { - gPipeline.markMoved(mDrawable, TRUE); - } + gPipeline.markMoved(mDrawable, TRUE); } } @@ -3765,7 +3602,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) F32 root_roll, root_pitch, root_yaw; root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw); - if (gDebugAvatarRotation) + if (sDebugAvatarRotation) { llinfos << "root_roll " << RAD_TO_DEG * root_roll << " root_pitch " << RAD_TO_DEG * root_pitch @@ -3955,7 +3792,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); const F32 STEP_VOLUME = 0.5f; - LLUUID& step_sound_id = getStepSound(); + const LLUUID& step_sound_id = getStepSound(); LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); @@ -4189,19 +4026,19 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (mNeedsSkin) { //generate animated mesh - mLowerBodyLOD.updateJointGeometry(); - mUpperBodyLOD.updateJointGeometry(); + mMeshLOD[MESH_ID_LOWER_BODY]->updateJointGeometry(); + mMeshLOD[MESH_ID_UPPER_BODY]->updateJointGeometry(); if( isWearingWearableType( WT_SKIRT ) ) { - mSkirtLOD.updateJointGeometry(); + mMeshLOD[MESH_ID_SKIRT]->updateJointGeometry(); } if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { - mEyeLashLOD.updateJointGeometry(); - mHeadLOD.updateJointGeometry(); - mHairLOD.updateJointGeometry(); + mMeshLOD[MESH_ID_EYELASH]->updateJointGeometry(); + mMeshLOD[MESH_ID_HEAD]->updateJointGeometry(); + mMeshLOD[MESH_ID_HAIR]->updateJointGeometry(); } mNeedsSkin = FALSE; @@ -4289,7 +4126,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) gGL.flush(); } //-------------------------------------------------------------------- - // render all geomety attached to the skeleton + // render all geometry attached to the skeleton //-------------------------------------------------------------------- static LLStat render_stat; @@ -4297,18 +4134,42 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (pass == AVATAR_RENDER_PASS_SINGLE) { + bool should_alpha_mask = mHasBakedHair && isTextureDefined(TEX_HEAD_BAKED) && isTextureDefined(TEX_UPPER_BAKED) + && isTextureDefined(TEX_LOWER_BAKED) && mBakedTextureData[BAKED_HEAD].mIsLoaded + && mBakedTextureData[BAKED_UPPER].mIsLoaded && mBakedTextureData[BAKED_LOWER].mIsLoaded; + LLGLState test(GL_ALPHA_TEST, should_alpha_mask); + + if (should_alpha_mask) + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + } + BOOL first_pass = TRUE; if (!LLDrawPoolAvatar::sSkipOpaque) { if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { - num_indices += mHeadLOD.render(mAdjustedPixelArea); + if (isTextureVisible(TEX_HEAD_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea); + first_pass = FALSE; + } + } + if (isTextureVisible(TEX_UPPER_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass); + first_pass = FALSE; + } + + if (isTextureVisible(TEX_LOWER_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass); first_pass = FALSE; } - num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass); - num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE); } + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) { LLGLEnable blend(GL_BLEND); @@ -4329,10 +4190,10 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) U32 LLVOAvatar::renderTransparent(BOOL first_pass) { U32 num_indices = 0; - if( isWearingWearableType( WT_SKIRT ) ) + if( isWearingWearableType( WT_SKIRT ) && isTextureVisible(TEX_SKIRT_BAKED) ) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); - num_indices += mSkirtLOD.render(mAdjustedPixelArea, FALSE); + num_indices += mMeshLOD[MESH_ID_SKIRT]->render(mAdjustedPixelArea, FALSE); first_pass = FALSE; gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } @@ -4343,8 +4204,17 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } - num_indices += mEyeLashLOD.render(mAdjustedPixelArea, first_pass); - num_indices += mHairLOD.render(mAdjustedPixelArea, FALSE); + + if (isTextureVisible(TEX_HEAD_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_EYELASH]->render(mAdjustedPixelArea, first_pass); + first_pass = FALSE; + } + if (isTextureVisible(TEX_HAIR_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass); + first_pass = FALSE; + } if (LLPipeline::sImpostorRender) { gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); @@ -4376,8 +4246,22 @@ U32 LLVOAvatar::renderRigid() return 0; } - num_indices += mEyeBallLeftLOD.render(mAdjustedPixelArea); - num_indices += mEyeBallRightLOD.render(mAdjustedPixelArea); + if (isTextureVisible(TEX_EYES_BAKED)) + { + // If the meshes need to be drawn, enable alpha masking but not blending + bool should_alpha_mask = mHasBakedHair && mBakedTextureData[BAKED_EYES].mIsLoaded; + LLGLState test(GL_ALPHA_TEST, should_alpha_mask); + + if (should_alpha_mask) + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + } + + num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea); + num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea); + + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } return num_indices; } @@ -4400,6 +4284,13 @@ U32 LLVOAvatar::renderFootShadows() { return 0; } + + // Don't render foot shadows if your lower body is completely invisible. + // (non-humanoid avatars rule!) + if (! isTextureVisible(TEX_LOWER_BAKED)) + { + return 0; + } // Update the shadow, tractor, and text label geometry. if (mDrawable->isState(LLDrawable::REBUILD_SHADOW) && !isImpostor()) @@ -4470,12 +4361,6 @@ void LLVOAvatar::updateTextures(LLAgent &agent) { return; } - - BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); if( mIsSelf ) { @@ -4486,30 +4371,18 @@ void LLVOAvatar::updateTextures(LLAgent &agent) render_avatar = isVisible() && !mCulled; } - // bind the texture so that they'll be decoded - // slightly inefficient, we can short-circuit this - // if we have to - if( render_avatar && !gGLManager.mIsDisabled ) + std::vector<bool> layer_baked; + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - if( head_baked && ! mHeadBakedLoaded ) - { - gGL.getTexUnit(0)->bind(getTEImage( TEX_HEAD_BAKED )); - } - if( upper_baked && ! mUpperBakedLoaded ) - { - gGL.getTexUnit(0)->bind(getTEImage( TEX_UPPER_BAKED )); - } - if( lower_baked && ! mLowerBakedLoaded ) - { - gGL.getTexUnit(0)->bind(getTEImage( TEX_LOWER_BAKED )); - } - if( eyes_baked && ! mEyesBakedLoaded ) - { - gGL.getTexUnit(0)->bind(getTEImage( TEX_EYES_BAKED )); - } - if( skirt_baked && ! mSkirtBakedLoaded ) + layer_baked.push_back(isTextureDefined(mBakedTextureData[i].mTextureIndex)); + // bind the texture so that they'll be decoded slightly + // inefficient, we can short-circuit this if we have to + if( render_avatar && !gGLManager.mIsDisabled ) { - gGL.getTexUnit(0)->bind(getTEImage( TEX_SKIRT_BAKED )); + if (layer_baked[i] && !mBakedTextureData[i].mIsLoaded) + { + gGL.getTexUnit(0)->bind(getTEImage( mBakedTextureData[i].mTextureIndex )); + } } } @@ -4541,9 +4414,9 @@ void LLVOAvatar::updateTextures(LLAgent &agent) mMaxPixelArea = 0.f; mMinPixelArea = 99999999.f; mHasGrey = FALSE; // debug - for (U32 i = 0; i < getNumTEs(); i++) + for (U32 index = 0; index < getNumTEs(); index++) { - LLViewerImage *imagep = getTEImage(i); + LLViewerImage *imagep = getTEImage(index); if (imagep) { // Debugging code - maybe non-self avatars are downloading textures? @@ -4555,131 +4428,39 @@ void LLVOAvatar::updateTextures(LLAgent &agent) // << " desired " << imagep->getDesiredDiscardLevel() // << llendl; - const LLTextureEntry *te = getTE(i); + const LLTextureEntry *te = getTE(index); F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT); S32 boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_BAKED_SELF : LLViewerImage::BOOST_AVATAR_BAKED; // Spam if this is a baked texture, not set to default image, without valid host info - if (isTextureIndexBaked(i) + if (isIndexBakedTexture((ETextureIndex)index) && imagep->getID() != IMG_DEFAULT_AVATAR && !imagep->getTargetHost().isOk()) { - llwarns << "LLVOAvatar::updateTextures No host for texture " + LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture " << imagep->getID() << " for avatar " << (mIsSelf ? "<myself>" : getID().asString()) << " on host " << getRegion()->getHost() << llendl; } - - switch( i ) - { - // Head - case TEX_HEAD_BODYPAINT: - addLocalTextureStats( LOCTEX_HEAD_BODYPAINT, imagep, texel_area_ratio, render_avatar, head_baked ); - break; - - // Upper - case TEX_UPPER_JACKET: - addLocalTextureStats( LOCTEX_UPPER_JACKET, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - - case TEX_UPPER_SHIRT: - addLocalTextureStats( LOCTEX_UPPER_SHIRT, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - - case TEX_UPPER_GLOVES: - addLocalTextureStats( LOCTEX_UPPER_GLOVES, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - - case TEX_UPPER_UNDERSHIRT: - addLocalTextureStats( LOCTEX_UPPER_UNDERSHIRT, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - - case TEX_UPPER_BODYPAINT: - addLocalTextureStats( LOCTEX_UPPER_BODYPAINT, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - // Lower - case TEX_LOWER_JACKET: - addLocalTextureStats( LOCTEX_LOWER_JACKET, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_PANTS: - addLocalTextureStats( LOCTEX_LOWER_PANTS, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_SHOES: - addLocalTextureStats( LOCTEX_LOWER_SHOES, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_SOCKS: - addLocalTextureStats( LOCTEX_LOWER_SOCKS, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_UNDERPANTS: - addLocalTextureStats( LOCTEX_LOWER_UNDERPANTS, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_BODYPAINT: - addLocalTextureStats( LOCTEX_LOWER_BODYPAINT, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - // Eyes - case TEX_EYES_IRIS: - addLocalTextureStats( LOCTEX_EYES_IRIS, imagep, texel_area_ratio, render_avatar, eyes_baked ); - break; - - // Skirt - case TEX_SKIRT: - addLocalTextureStats( LOCTEX_SKIRT, imagep, texel_area_ratio, render_avatar, skirt_baked ); - break; - - // Baked - case TEX_HEAD_BAKED: - if (head_baked) - { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); - } - break; - - case TEX_UPPER_BAKED: - if (upper_baked) - { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); - } - break; - - case TEX_LOWER_BAKED: - if (lower_baked) - { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); - } - break; - - case TEX_EYES_BAKED: - if (eyes_baked) + /* switch(index) + case TEX_HEAD_BODYPAINT: + addLocalTextureStats( LOCTEX_HEAD_BODYPAINT, imagep, texel_area_ratio, render_avatar, head_baked ); */ + const LLVOAvatarDictionary::TextureDictionaryEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)index); + if (texture_dict->mIsUsedByBakedTexture) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + if (texture_dict->mIsLocalTexture) { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); + addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); } - break; - - case TEX_SKIRT_BAKED: - if (skirt_baked) + else if (texture_dict->mIsBakedTexture) { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); + if (layer_baked[baked_index]) + { + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); + } } - break; - - case TEX_HAIR: - // Hair is neither a local texture used for baking, nor the output - // of the baking process. It's just a texture that happens to be - // used to draw avatars. Hence BOOST_AVATAR. JC - boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_SELF : LLViewerImage::BOOST_AVATAR; - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); - break; - - default: - llassert(0); - break; } } } @@ -4696,22 +4477,24 @@ void LLVOAvatar::updateTextures(LLAgent &agent) } -void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerImage* imagep, +void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerImage* imagep, F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked ) { + if (!isIndexLocalTexture(idx)) return; + if (!covered_by_baked && render_avatar) // render_avatar is always true if mIsSelf { - if (mLocalTexture[ idx ].notNull() && mLocalTexture[idx]->getID() != IMG_DEFAULT_AVATAR) + if (getLocalTextureID(idx) != IMG_DEFAULT_AVATAR) { F32 desired_pixels; if( mIsSelf ) { - desired_pixels = llmin(mPixelArea, (F32)LOCTEX_IMAGE_AREA_SELF ); + desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_SELF ); imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR_SELF); } else { - desired_pixels = llmin(mPixelArea, (F32)LOCTEX_IMAGE_AREA_OTHER ); + desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_OTHER ); imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR); } imagep->addTextureStats( desired_pixels / texel_area_ratio ); @@ -4722,11 +4505,8 @@ void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerIma } else { - if (mLocalTexture[idx]->getID() == IMG_DEFAULT_AVATAR) - { - // texture asset is missing - mHasGrey = TRUE; // for statistics gathering - } + // texture asset is missing + mHasGrey = TRUE; // for statistics gathering } } } @@ -4794,7 +4574,7 @@ void LLVOAvatar::resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos //----------------------------------------------------------------------------- // getStepSound() //----------------------------------------------------------------------------- -LLUUID& LLVOAvatar::getStepSound() +const LLUUID& LLVOAvatar::getStepSound() const { if ( mStepOnLand ) { @@ -5232,7 +5012,7 @@ F32 LLVOAvatar::getPixelArea() const //----------------------------------------------------------------------------- LLPolyMesh* LLVOAvatar::getHeadMesh() { - return mHeadMesh0.getMesh(); + return mMeshLOD[MESH_ID_HEAD]->mMeshParts[0]->getMesh(); } @@ -5241,7 +5021,7 @@ LLPolyMesh* LLVOAvatar::getHeadMesh() //----------------------------------------------------------------------------- LLPolyMesh* LLVOAvatar::getUpperBodyMesh() { - return mUpperBodyMesh0.getMesh(); + return mMeshLOD[MESH_ID_UPPER_BODY]->mMeshParts[0]->getMesh(); } @@ -5340,7 +5120,7 @@ BOOL LLVOAvatar::loadAvatar() // LLFastTimer t(LLFastTimer::FTM_LOAD_AVATAR); // avatar_skeleton.xml - if( !buildSkeleton(sSkeletonInfo) ) + if( !buildSkeleton(sAvatarSkeletonInfo) ) { llwarns << "avatar file: buildSkeleton() failed" << llendl; return FALSE; @@ -5361,10 +5141,10 @@ BOOL LLVOAvatar::loadAvatar() } // avatar_lad.xml : <global_color> - if( sAvatarInfo->mTexSkinColorInfo ) + if( sAvatarXmlInfo->mTexSkinColorInfo ) { mTexSkinColor = new LLTexGlobalColor( this ); - if( !mTexSkinColor->setInfo( sAvatarInfo->mTexSkinColorInfo ) ) + if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) { llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl; return FALSE; @@ -5375,10 +5155,10 @@ BOOL LLVOAvatar::loadAvatar() llwarns << "<global_color> name=\"skin_color\" not found" << llendl; return FALSE; } - if( sAvatarInfo->mTexHairColorInfo ) + if( sAvatarXmlInfo->mTexHairColorInfo ) { mTexHairColor = new LLTexGlobalColor( this ); - if( !mTexHairColor->setInfo( sAvatarInfo->mTexHairColorInfo ) ) + if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) { llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl; return FALSE; @@ -5389,10 +5169,10 @@ BOOL LLVOAvatar::loadAvatar() llwarns << "<global_color> name=\"hair_color\" not found" << llendl; return FALSE; } - if( sAvatarInfo->mTexEyeColorInfo ) + if( sAvatarXmlInfo->mTexEyeColorInfo ) { mTexEyeColor = new LLTexGlobalColor( this ); - if( !mTexEyeColor->setInfo( sAvatarInfo->mTexEyeColorInfo ) ) + if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) { llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl; return FALSE; @@ -5405,15 +5185,15 @@ BOOL LLVOAvatar::loadAvatar() } // avatar_lad.xml : <layer_set> - if (sAvatarInfo->mLayerInfoList.empty()) + if (sAvatarXmlInfo->mLayerInfoList.empty()) { llwarns << "avatar file: missing <layer_set> node" << llendl; } else { - LLVOAvatarInfo::layer_info_list_t::iterator iter; - for (iter = sAvatarInfo->mLayerInfoList.begin(); - iter != sAvatarInfo->mLayerInfoList.end(); iter++) + LLVOAvatarXmlInfo::layer_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mLayerInfoList.begin(); + iter != sAvatarXmlInfo->mLayerInfoList.end(); iter++) { LLTexLayerSetInfo *info = *iter; LLTexLayerSet* layer_set = new LLTexLayerSet( this ); @@ -5424,27 +5204,20 @@ BOOL LLVOAvatar::loadAvatar() llwarns << "avatar file: layer_set->parseData() failed" << llendl; return FALSE; } - if( layer_set->isBodyRegion( "head" ) ) + bool found_baked_entry = false; + for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + baked_iter++) { - mHeadLayerSet = layer_set; - } - else if( layer_set->isBodyRegion( "upper_body" ) ) - { - mUpperBodyLayerSet = layer_set; - } - else if( layer_set->isBodyRegion( "lower_body" ) ) - { - mLowerBodyLayerSet = layer_set; - } - else if( layer_set->isBodyRegion( "eyes" ) ) - { - mEyesLayerSet = layer_set; - } - else if( layer_set->isBodyRegion( "skirt" ) ) - { - mSkirtLayerSet = layer_set; + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second; + if (layer_set->isBodyRegion(baked_dict->mName)) + { + mBakedTextureData[baked_iter->first].mTexLayerSet = layer_set; + found_baked_entry = true; + break; + } } - else + if (!found_baked_entry) { llwarns << "<layer_set> has invalid body_region attribute" << llendl; delete layer_set; @@ -5455,9 +5228,9 @@ BOOL LLVOAvatar::loadAvatar() // avatar_lad.xml : <driver_parameters> { - LLVOAvatarInfo::driver_info_list_t::iterator iter; - for (iter = sAvatarInfo->mDriverInfoList.begin(); - iter != sAvatarInfo->mDriverInfoList.end(); iter++) + LLVOAvatarXmlInfo::driver_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mDriverInfoList.begin(); + iter != sAvatarXmlInfo->mDriverInfoList.end(); iter++) { LLDriverParamInfo *info = *iter; LLDriverParam* driver_param = new LLDriverParam( this ); @@ -5484,78 +5257,44 @@ BOOL LLVOAvatar::loadSkeletonNode () { mRoot.addChild( &mSkeleton[0] ); - mRoot.addChild( &mHeadLOD ); - mHeadLOD.mUpdateXform = FALSE; - mHeadLOD.addChild( &mHeadMesh0 ); - mHeadLOD.addChild( &mHeadMesh1 ); - mHeadLOD.addChild( &mHeadMesh2 ); - mHeadLOD.addChild( &mHeadMesh3 ); - mHeadLOD.addChild( &mHeadMesh4 ); - - mRoot.addChild( &mEyeLashLOD ); - mEyeLashLOD.mUpdateXform = FALSE; - mEyeLashLOD.addChild( &mEyeLashMesh0 ); - - mRoot.addChild( &mUpperBodyLOD ); - mUpperBodyLOD.mUpdateXform = FALSE; - mUpperBodyLOD.addChild( &mUpperBodyMesh0 ); - mUpperBodyLOD.addChild( &mUpperBodyMesh1 ); - mUpperBodyLOD.addChild( &mUpperBodyMesh2 ); - mUpperBodyLOD.addChild( &mUpperBodyMesh3 ); - mUpperBodyLOD.addChild( &mUpperBodyMesh4 ); - - mRoot.addChild( &mLowerBodyLOD ); - mLowerBodyLOD.mUpdateXform = FALSE; - mLowerBodyLOD.addChild( &mLowerBodyMesh0 ); - mLowerBodyLOD.addChild( &mLowerBodyMesh1 ); - mLowerBodyLOD.addChild( &mLowerBodyMesh2 ); - mLowerBodyLOD.addChild( &mLowerBodyMesh3 ); - mLowerBodyLOD.addChild( &mLowerBodyMesh4 ); - - mRoot.addChild( &mSkirtLOD ); - mSkirtLOD.mUpdateXform = FALSE; - mSkirtLOD.addChild( &mSkirtMesh0 ); - mSkirtLOD.addChild( &mSkirtMesh1 ); - mSkirtLOD.addChild( &mSkirtMesh2 ); - mSkirtLOD.addChild( &mSkirtMesh3 ); - mSkirtLOD.addChild( &mSkirtMesh4 ); + for (std::vector<LLViewerJoint *>::iterator iter = mMeshLOD.begin(); + iter != mMeshLOD.end(); iter++) + { + LLViewerJoint *joint = (LLViewerJoint *) *iter; + joint->mUpdateXform = FALSE; + 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( &mHairLOD ); - mHairLOD.mUpdateXform = FALSE; - mHairLOD.addChild( &mHairMesh0 ); - mHairLOD.addChild( &mHairMesh1 ); - mHairLOD.addChild( &mHairMesh2 ); - mHairLOD.addChild( &mHairMesh3 ); - mHairLOD.addChild( &mHairMesh4 ); - mHairLOD.addChild( &mHairMesh5 ); + skull->addChild(mMeshLOD[MESH_ID_HAIR] ); } LLViewerJoint *eyeL = (LLViewerJoint*)mRoot.findJoint("mEyeLeft"); if (eyeL) { - eyeL->addChild( &mEyeBallLeftLOD ); - mEyeBallLeftLOD.mUpdateXform = FALSE; - mEyeBallLeftLOD.addChild( &mEyeBallLeftMesh0 ); - mEyeBallLeftLOD.addChild( &mEyeBallLeftMesh1 ); + eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] ); } LLViewerJoint *eyeR = (LLViewerJoint*)mRoot.findJoint("mEyeRight"); if (eyeR) { - eyeR->addChild( &mEyeBallRightLOD ); - mEyeBallRightLOD.mUpdateXform = FALSE; - mEyeBallRightLOD.addChild( &mEyeBallRightMesh0 ); - mEyeBallRightLOD.addChild( &mEyeBallRightMesh1 ); + eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] ); } // SKELETAL DISTORTIONS { - LLVOAvatarInfo::skeletal_distortion_info_list_t::iterator iter; - for (iter = sAvatarInfo->mSkeletalDistortionInfoList.begin(); - iter != sAvatarInfo->mSkeletalDistortionInfoList.end(); iter++) + 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); @@ -5573,11 +5312,11 @@ BOOL LLVOAvatar::loadSkeletonNode () // ATTACHMENTS { - LLVOAvatarInfo::attachment_info_list_t::iterator iter; - for (iter = sAvatarInfo->mAttachmentInfoList.begin(); - iter != sAvatarInfo->mAttachmentInfoList.end(); iter++) + LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin(); + iter != sAvatarXmlInfo->mAttachmentInfoList.end(); iter++) { - LLVOAvatarInfo::LLVOAvatarAttachmentInfo *info = *iter; + LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter; if (!isSelf() && info->mJointName == "mScreen") { //don't process screen joint for other avatars continue; @@ -5654,174 +5393,49 @@ BOOL LLVOAvatar::loadSkeletonNode () //----------------------------------------------------------------------------- BOOL LLVOAvatar::loadMeshNodes() { - LLVOAvatarInfo::mesh_info_list_t::iterator iter; - for (iter = sAvatarInfo->mMeshInfoList.begin(); - iter != sAvatarInfo->mMeshInfoList.end(); iter++) + for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin(); + meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end(); + meshinfo_iter++) { - LLVOAvatarInfo::LLVOAvatarMeshInfo *info = *iter; - std::string &type = info->mType; + const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter; + const std::string &type = info->mType; S32 lod = info->mLOD; LLViewerJointMesh* mesh = NULL; - if (type == "hairMesh") - { - switch (lod) - { - case 0: - mesh = &mHairMesh0; - break; - case 1: - mesh = &mHairMesh1; - break; - case 2: - mesh = &mHairMesh2; - break; - case 3: - mesh = &mHairMesh3; - break; - case 4: - mesh = &mHairMesh4; - break; - case 5: - mesh = &mHairMesh5; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else if (type == "headMesh") - { - switch (lod) - { + U8 mesh_id = 0; + BOOL found_mesh_id = FALSE; + + /* if (type == "hairMesh") + switch(lod) case 0: - mesh = &mHeadMesh0; - break; - case 1: - mesh = &mHeadMesh1; - break; - case 2: - mesh = &mHeadMesh2; - break; - case 3: - mesh = &mHeadMesh3; - break; - case 4: - mesh = &mHeadMesh4; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else if (type == "upperBodyMesh") + mesh = &mHairMesh0; */ + for (LLVOAvatarDictionary::mesh_map_t::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); + mesh_iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); + mesh_iter++) { - switch (lod) + const EMeshIndex mesh_index = mesh_iter->first; + const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = mesh_iter->second; + if (type.compare(mesh_dict->mName) == 0) { - case 0: - mesh = &mUpperBodyMesh0; - break; - case 1: - mesh = &mUpperBodyMesh1; - break; - case 2: - mesh = &mUpperBodyMesh2; - break; - case 3: - mesh = &mUpperBodyMesh3; - break; - case 4: - mesh = &mUpperBodyMesh4; + mesh_id = mesh_index; + found_mesh_id = TRUE; break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; } } - else if (type == "lowerBodyMesh") - { - switch (lod) - { - case 0: - mesh = &mLowerBodyMesh0; - break; - case 1: - mesh = &mLowerBodyMesh1; - break; - case 2: - mesh = &mLowerBodyMesh2; - break; - case 3: - mesh = &mLowerBodyMesh3; - break; - case 4: - mesh = &mLowerBodyMesh4; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else if (type == "skirtMesh") - { - switch (lod) - { - case 0: - mesh = &mSkirtMesh0; - break; - case 1: - mesh = &mSkirtMesh1; - break; - case 2: - mesh = &mSkirtMesh2; - break; - case 3: - mesh = &mSkirtMesh3; - break; - case 4: - mesh = &mSkirtMesh4; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else if (type == "eyelashMesh") - { - mesh = &mEyeLashMesh0; - } - else if (type == "eyeBallLeftMesh") + + if (found_mesh_id) { - switch (lod) + if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size()) { - case 0: - mesh = &mEyeBallLeftMesh0; - break; - case 1: - mesh = &mEyeBallLeftMesh1; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; + mesh = mMeshLOD[mesh_id]->mMeshParts[lod]; } - } - else if (type == "eyeBallRightMesh") - { - switch (lod) + else { - case 0: - mesh = &mEyeBallRightMesh0; - break; - case 1: - mesh = &mEyeBallRightMesh1; - break; - default: llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; return FALSE; } } - - if( !mesh ) + else { llwarns << "Ignoring unrecognized mesh type: " << type << llendl; return FALSE; @@ -5837,15 +5451,16 @@ BOOL LLVOAvatar::loadMeshNodes() if (!info->mReferenceMeshName.empty()) { - mesh_map_t::iterator iter = mMeshes.find(info->mReferenceMeshName); - if (iter != mMeshes.end()) + polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName); + if (polymesh_iter != mMeshes.end()) { - poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, iter->second); + 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 @@ -5864,14 +5479,13 @@ BOOL LLVOAvatar::loadMeshNodes() mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); mesh->setMesh( poly_mesh ); - mesh->setLOD( info->mMinPixelArea ); - LLVOAvatarInfo::LLVOAvatarMeshInfo::morph_info_list_t::iterator iter; - for (iter = info->mPolyMorphTargetInfoList.begin(); - iter != info->mPolyMorphTargetInfoList.end(); iter++) + for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin(); + xmlinfo_iter != info->mPolyMorphTargetInfoList.end(); + xmlinfo_iter++) { - LLVOAvatarInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*iter); + const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter); LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh()); if (!param->setInfo(info_pair->first)) { @@ -5961,7 +5575,7 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) // We always want to look good to ourselves if( mIsSelf ) { - mPixelArea = llmax( mPixelArea, F32(LOCTEX_IMAGE_SIZE_SELF / 16) ); + mPixelArea = llmax( mPixelArea, F32(TEX_IMAGE_SIZE_SELF / 16) ); } } @@ -6078,7 +5692,7 @@ void LLVOAvatar::updateShadowFaces() // // render avatar shadows // - if (mInAir || mUpdatePeriod >= VOAVATAR_IMPOSTOR_PERIOD) + if (mInAir || mUpdatePeriod >= IMPOSTOR_PERIOD) { face0p->setSize(0, 0); face1p->setSize(0, 0); @@ -6173,9 +5787,9 @@ void LLVOAvatar::updateShadowFaces() //----------------------------------------------------------------------------- void LLVOAvatar::updateSexDependentLayerSets( BOOL set_by_user ) { - invalidateComposite( mHeadLayerSet, set_by_user ); - invalidateComposite( mLowerBodyLayerSet, set_by_user ); - invalidateComposite( mUpperBodyLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet, set_by_user ); updateMeshTextures(); } @@ -6188,74 +5802,32 @@ void LLVOAvatar::dirtyMesh() } //----------------------------------------------------------------------------- -// requestLayerSetUpdate() +// hideSkirt() //----------------------------------------------------------------------------- -void LLVOAvatar::requestLayerSetUpdate( LLVOAvatar::ELocTexIndex i ) +void LLVOAvatar::hideSkirt() { - switch( i ) - { - case LOCTEX_HEAD_BODYPAINT: - if( mHeadLayerSet ) - { - mHeadLayerSet->requestUpdate(); - } - break; - - case LOCTEX_UPPER_BODYPAINT: - case LOCTEX_UPPER_SHIRT: - case LOCTEX_UPPER_GLOVES: - case LOCTEX_UPPER_UNDERSHIRT: - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->requestUpdate(); - } - break; - - case LOCTEX_LOWER_BODYPAINT: - case LOCTEX_LOWER_PANTS: - case LOCTEX_LOWER_SHOES: - case LOCTEX_LOWER_SOCKS: - case LOCTEX_LOWER_UNDERPANTS: - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->requestUpdate(); - } - break; - - case LOCTEX_EYES_IRIS: - if( mEyesLayerSet ) - { - mEyesLayerSet->requestUpdate(); - } - break; - - - case LOCTEX_SKIRT: - if( mSkirtLayerSet ) - { - mSkirtLayerSet->requestUpdate(); - } - break; - - - case LOCTEX_UPPER_JACKET: - case LOCTEX_LOWER_JACKET: - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->requestUpdate(); - } + mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE); +} - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->requestUpdate(); - } - break; - case LOCTEX_NUM_ENTRIES: - llerrs << "Bogus texture value " << i << llendl; - break; +//----------------------------------------------------------------------------- +// requestLayerSetUpdate() +//----------------------------------------------------------------------------- +void LLVOAvatar::requestLayerSetUpdate(ETextureIndex index ) +{ + /* switch(index) + case LOCTEX_UPPER_BODYPAINT: + case LOCTEX_UPPER_SHIRT: + if( mUpperBodyLayerSet ) + mUpperBodyLayerSet->requestUpdate(); */ + const LLVOAvatarDictionary::TextureDictionaryEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) + return; + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + if (mBakedTextureData[baked_index].mTexLayerSet) + { + mBakedTextureData[baked_index].mTexLayerSet->requestUpdate(); } - } void LLVOAvatar::setParent(LLViewerObject* parent) @@ -6616,6 +6188,7 @@ const std::string LLVOAvatar::getAttachedPointName(const LLUUID& inv_item_id) // static // onLocalTextureLoaded() //----------------------------------------------------------------------------- + void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { //llinfos << "onLocalTextureLoaded: " << src_vi->getID() << llendl; @@ -6625,37 +6198,47 @@ void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLIm if (success) { LLVOAvatar *self = (LLVOAvatar *)gObjectList.findObject(data->mAvatarID); - LLVOAvatar::ELocTexIndex idx = data->mIndex; - if( self && - (!self->mLocalTextureBaked[ idx ]) && - (self->mLocalTexture[ idx ].notNull()) && - (self->mLocalTexture[ idx ]->getID() == src_id) && - (discard_level < self->mLocalTextureDiscard[idx])) - { - self->mLocalTextureDiscard[idx] = discard_level; - self->requestLayerSetUpdate( idx ); - if( self->mIsSelf && gAgent.cameraCustomizeAvatar() ) - { - LLVisualParamHint::requestHintUpdates(); + if (self) + { + ETextureIndex index = data->mIndex; + if (!self->isIndexLocalTexture(index)) return; + LocalTextureData &local_tex_data = self->mLocalTextureData[index]; + if(!local_tex_data.mIsBakedReady && + local_tex_data.mImage.notNull() && + (local_tex_data.mImage->getID() == src_id) && + discard_level < local_tex_data.mDiscard) + { + local_tex_data.mDiscard = discard_level; + if ( self->isSelf() && !gAgent.cameraCustomizeAvatar() ) + { + self->requestLayerSetUpdate( index ); + } + else if( self->isSelf() && gAgent.cameraCustomizeAvatar() ) + { + LLVisualParamHint::requestHintUpdates(); + } + self->updateMeshTextures(); } - self->updateMeshTextures(); } } else if (final) { LLVOAvatar *self = (LLVOAvatar *)gObjectList.findObject(data->mAvatarID); - LLVOAvatar::ELocTexIndex idx = data->mIndex; - // Failed: asset is missing - if( self && - (!self->mLocalTextureBaked[ idx ]) && - (self->mLocalTexture[ idx ].notNull()) && - (self->mLocalTexture[ idx ]->getID() == src_id)) + if (self) { - self->mLocalTextureDiscard[idx] = 0; // we check that it's missing later - self->requestLayerSetUpdate( idx ); - self->updateMeshTextures(); + ETextureIndex index = data->mIndex; + if (!self->isIndexLocalTexture(index)) return; + LocalTextureData &local_tex_data = self->mLocalTextureData[index]; + // Failed: asset is missing + if(!local_tex_data.mIsBakedReady && + local_tex_data.mImage.notNull() && + local_tex_data.mImage->getID() == src_id) + { + local_tex_data.mDiscard = 0; + self->requestLayerSetUpdate( index ); + self->updateMeshTextures(); + } } - } if( final || !success ) @@ -6666,29 +6249,13 @@ void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLIm void LLVOAvatar::updateComposites() { - if( mHeadLayerSet ) - { - mHeadLayerSet->updateComposite(); - } - - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->updateComposite(); - } - - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->updateComposite(); - } - - if( mEyesLayerSet ) - { - mEyesLayerSet->updateComposite(); - } - - if( mSkirtLayerSet && isWearingWearableType( WT_SKIRT )) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mSkirtLayerSet->updateComposite(); + if ( mBakedTextureData[i].mTexLayerSet + && ((i != BAKED_SKIRT) || isWearingWearableType( WT_SKIRT )) ) + { + mBakedTextureData[i].mTexLayerSet->updateComposite(); + } } } @@ -6740,6 +6307,10 @@ void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user { layer_name = "eyes"; } + else if (layerset == mHairLayerSet) + { + layer_name = "hair"; + } else if (layerset == mSkirtLayerSet) { layer_name = "skirt"; @@ -6758,47 +6329,52 @@ void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user llassert( mIsSelf ); ETextureIndex baked_te = getBakedTE( layerset ); - if( gAgent.cameraCustomizeAvatar() ) - { - mSavedTE[ baked_te ].setNull(); - } - else - { - setTEImage( baked_te, gImageList.getImage(IMG_DEFAULT_AVATAR) ); - layerset->requestUpload(); - } + setTEImage( baked_te, gImageList.getImage(IMG_DEFAULT_AVATAR) ); + layerset->requestUpload(); } } +void LLVOAvatar::invalidateAll() +{ + for (U32 i = 0; i < mBakedTextureData.size(); i++) + { + invalidateComposite(mBakedTextureData[i].mTexLayerSet, TRUE); + } + updateMeshTextures(); +} void LLVOAvatar::onGlobalColorChanged( LLTexGlobalColor* global_color, BOOL set_by_user ) { if( global_color == mTexSkinColor ) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( skin color )" << llendl; - invalidateComposite( mHeadLayerSet, set_by_user ); - invalidateComposite( mUpperBodyLayerSet, set_by_user ); - invalidateComposite( mLowerBodyLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet, set_by_user ); } else if( global_color == mTexHairColor ) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( hair color )" << llendl; - invalidateComposite( mHeadLayerSet, set_by_user ); - - LLColor4 color = mTexHairColor->getColor(); - mHairMesh0.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh1.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh2.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh3.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh4.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh5.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_HAIR].mTexLayerSet, set_by_user ); + + // ! BACKWARDS COMPATIBILITY ! + // Fix for dealing with avatars from viewers that don't bake hair. + if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex)) + { + LLColor4 color = mTexHairColor->getColor(); + for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) + { + mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + } + } } else if( global_color == mTexEyeColor ) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl; - invalidateComposite( mEyesLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_EYES].mTexLayerSet, set_by_user ); } updateMeshTextures(); } @@ -6807,9 +6383,9 @@ void LLVOAvatar::forceBakeAllTextures(bool slam_for_debug) { llinfos << "TAT: forced full rebake. " << llendl; - for (S32 i = 0; i < BAKED_TEXTURE_COUNT; i++) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - ETextureIndex baked_index = sBakedTextureIndices[i]; + ETextureIndex baked_index = mBakedTextureData[i].mTextureIndex; LLTexLayerSet* layer_set = getLayerSet(baked_index); if (layer_set) { @@ -6846,20 +6422,30 @@ void LLVOAvatar::processRebakeAvatarTextures(LLMessageSystem* msg, void**) // If this is a texture corresponding to one of our baked entries, // just rebake that layer set. BOOL found = FALSE; - for (S32 i = 0; i < BAKED_TEXTURE_COUNT; i++) + + /* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] = + TEX_HEAD_BAKED, + TEX_UPPER_BAKED, */ + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) { - ETextureIndex baked_index = sBakedTextureIndices[i]; - if (texture_id == self->getTEImage(baked_index)->getID()) + const ETextureIndex index = iter->first; + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + if (text_dict->mIsBakedTexture) { - LLTexLayerSet* layer_set = self->getLayerSet(baked_index); - if (layer_set) + if (texture_id == self->getTEImage(index)->getID()) { - llinfos << "TAT: rebake - matched entry " << (S32)baked_index << llendl; - // Apparently set_by_user == force upload - BOOL set_by_user = TRUE; - self->invalidateComposite(layer_set, set_by_user); - found = TRUE; - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); + LLTexLayerSet* layer_set = self->getLayerSet(index); + if (layer_set) + { + llinfos << "TAT: rebake - matched entry " << (S32)index << llendl; + // Apparently set_by_user == force upload + BOOL set_by_user = TRUE; + self->invalidateComposite(layer_set, set_by_user); + found = TRUE; + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); + } } } } @@ -6877,48 +6463,48 @@ void LLVOAvatar::processRebakeAvatarTextures(LLMessageSystem* msg, void**) } -BOOL LLVOAvatar::getLocalTextureRaw(S32 index, LLImageRaw* image_raw) +BOOL LLVOAvatar::getLocalTextureRaw(ETextureIndex index, LLImageRaw* image_raw) { + if (!isIndexLocalTexture(index)) return FALSE; + BOOL success = FALSE; - if( (0 <= index) && (index < LOCTEX_NUM_ENTRIES) ) + if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR) { - if (mLocalTexture[ index ].isNull() || mLocalTexture[ index ]->getID() == IMG_DEFAULT_AVATAR ) + success = TRUE; + } + else + { + LocalTextureData &local_tex_data = mLocalTextureData[index]; + if(local_tex_data.mImage->readBackRaw(-1, image_raw, false)) { success = TRUE; } else { - if( mLocalTexture[ index ]->readBackRaw(-1, image_raw, false) ) - { - success = TRUE; - } - else - { - // No data loaded yet - setLocalTexture( (ELocTexIndex)index, getTEImage( index ), FALSE ); - } + // No data loaded yet + setLocalTexture( (ETextureIndex)index, getTEImage( index ), FALSE ); } } return success; } -BOOL LLVOAvatar::getLocalTextureGL(S32 index, LLImageGL** image_gl_pp) +BOOL LLVOAvatar::getLocalTextureGL(ETextureIndex index, LLImageGL** image_gl_pp) { + if (!isIndexLocalTexture(index)) return FALSE; + BOOL success = FALSE; *image_gl_pp = NULL; - if( (0 <= index) && (index < LOCTEX_NUM_ENTRIES) ) + if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR) { - if( mLocalTexture[ index ].isNull() || mLocalTexture[ index ]->getID() == IMG_DEFAULT_AVATAR) - { - success = TRUE; - } - else - { - *image_gl_pp = mLocalTexture[ index ]; - success = TRUE; - } + success = TRUE; + } + else + { + LocalTextureData &local_tex_data = mLocalTextureData[index]; + *image_gl_pp = local_tex_data.mImage; + success = TRUE; } if( !success ) @@ -6928,11 +6514,13 @@ BOOL LLVOAvatar::getLocalTextureGL(S32 index, LLImageGL** image_gl_pp) return success; } -const LLUUID& LLVOAvatar::getLocalTextureID( S32 index ) +const LLUUID& LLVOAvatar::getLocalTextureID(ETextureIndex index) { - if (index >= 0 && mLocalTexture[index].notNull()) + if (!isIndexLocalTexture(index)) return IMG_DEFAULT_AVATAR; + + if (mLocalTextureData[index].mImage.notNull()) { - return mLocalTexture[index]->getID(); + return mLocalTextureData[index].mImage->getID(); } else { @@ -6977,8 +6565,15 @@ BOOL LLVOAvatar::updateIsFullyLoaded() loading = TRUE; } - // are our texture settings still default? - if ((getTEImage( TEX_HAIR )->getID() == IMG_DEFAULT)) + // + if (mIsSelf) + { + if (!isTextureDefined(TEX_HAIR)) + { + loading = TRUE; + } + } + else if (!isTextureDefined(TEX_LOWER_BAKED) || !isTextureDefined(TEX_UPPER_BAKED) || !isTextureDefined(TEX_HEAD_BAKED)) { loading = TRUE; } @@ -6998,14 +6593,14 @@ BOOL LLVOAvatar::updateIsFullyLoaded() // texture info for our shirt/pants, stay unloaded: if (!mPreviousFullyLoaded) { - if ((!isLocalTextureDataAvailable(mLowerBodyLayerSet)) && - (getTEImage(TEX_LOWER_BAKED)->getID() == IMG_DEFAULT_AVATAR)) + if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_LOWER].mTexLayerSet)) && + (!isTextureDefined(TEX_LOWER_BAKED))) { loading = TRUE; } - if ((!isLocalTextureDataAvailable(mUpperBodyLayerSet)) && - (getTEImage(TEX_UPPER_BAKED)->getID() == IMG_DEFAULT_AVATAR)) + if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_UPPER].mTexLayerSet)) && + (!isTextureDefined(TEX_UPPER_BAKED))) { loading = TRUE; } @@ -7057,9 +6652,10 @@ LLMotion* LLVOAvatar::findMotion(const LLUUID& id) void LLVOAvatar::getLocalTextureByteCount( S32* gl_bytes ) { *gl_bytes = 0; - for( S32 i = 0; i < LOCTEX_NUM_ENTRIES; i++ ) + for( S32 i = 0; i < TEX_NUM_INDICES; i++ ) { - LLViewerImage* image_gl = mLocalTexture[i]; + if (!isIndexLocalTexture((ETextureIndex)i)) continue; + LLViewerImage* image_gl = mLocalTextureData[(ETextureIndex)i].mImage; if( image_gl ) { S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); @@ -7122,7 +6718,7 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) default: llassert(0); components = 4; internal_format = GL_RGBA8; break; } - *texture_bytes = components * VOAVATAR_SCRATCH_TEX_WIDTH * VOAVATAR_SCRATCH_TEX_HEIGHT; + *texture_bytes = components * SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT; if( LLVOAvatar::sScratchTexNames.checkData( format ) ) { @@ -7142,7 +6738,7 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) LLImageGL::setManualImage( GL_TEXTURE_2D, 0, internal_format, - VOAVATAR_SCRATCH_TEX_WIDTH, VOAVATAR_SCRATCH_TEX_HEIGHT, + SCRATCH_TEX_WIDTH, SCRATCH_TEX_HEIGHT, format, GL_UNSIGNED_BYTE, NULL ); stop_glerror(); @@ -7174,7 +6770,7 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user ) return; } - if( te >= TEX_NUM_ENTRIES ) + if( te >= TEX_NUM_INDICES ) { llassert(0); return; @@ -7185,7 +6781,7 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user ) return; } - if (isTextureIndexBaked(te)) + if (isIndexBakedTexture((ETextureIndex)te)) { llassert(0); return; @@ -7208,32 +6804,13 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user ) void LLVOAvatar::setupComposites() { - // Don't invalidate the baked textures we had on start-up. - BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - - if (mHeadLayerSet) - { - mHeadLayerSet->setUpdatesEnabled( !head_baked ); - } - if (mUpperBodyLayerSet) - { - mUpperBodyLayerSet->setUpdatesEnabled( !upper_baked ); - } - if (mLowerBodyLayerSet) - { - mLowerBodyLayerSet->setUpdatesEnabled( !lower_baked ); - } - if (mEyesLayerSet) - { - mEyesLayerSet->setUpdatesEnabled( !eyes_baked ); - } - if (mSkirtLayerSet) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mSkirtLayerSet->setUpdatesEnabled( !skirt_baked ); + bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex); + if (mBakedTextureData[i].mTexLayerSet) + { + mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( !layer_baked ); + } } } @@ -7243,447 +6820,193 @@ void LLVOAvatar::setupComposites() //----------------------------------------------------------------------------- void LLVOAvatar::updateMeshTextures() { -// llinfos << "updateMeshTextures" << llendl; - if (gNoRender) - { - return; - } + // llinfos << "updateMeshTextures" << llendl; + if (gNoRender) return; + // if user has never specified a texture, assign the default - LLViewerImage* default_tex = gImageList.getImage(IMG_DEFAULT); - U8 num_TEs = getNumTEs(); - for (U32 i=0; i<num_TEs; i++) + for (U32 i=0; i < getNumTEs(); i++) { - LLViewerImage* te_image = getTEImage(i); - if( (NULL == te_image) || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT) ) + const LLViewerImage* te_image = getTEImage(i); + if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT)) { - if( TEX_HAIR == i ) - { - setTEImage(i, default_tex ); - } - else - { - setTEImage(i, gImageList.getImage(IMG_DEFAULT_AVATAR)); // a special texture that's never rendered. - } + setTEImage(i, gImageList.getImage(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR)); // IMG_DEFAULT_AVATAR = a special texture that's never rendered. } } - // During face edit mode, we don't use baked textures - BOOL self_customize = mIsSelf && gAgent.cameraCustomizeAvatar(); - - BOOL head_baked = (getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = (getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = (getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = (getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = (getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - - // Nothing should be baked if we're in customize avatar mode. - llassert( !( self_customize && - ( head_baked || upper_baked || lower_baked || eyes_baked ) ) ); - - BOOL use_lkg_head_baked = FALSE; - BOOL use_lkg_upper_baked = FALSE; - BOOL use_lkg_lower_baked = FALSE; - BOOL use_lkg_eyes_baked = FALSE; - BOOL use_lkg_skirt_baked = FALSE; - - BOOL other_culled = !mIsSelf && mCulled; - if( other_culled ) - { - use_lkg_head_baked = !head_baked && (mLastHeadBakedID != IMG_DEFAULT_AVATAR); - use_lkg_upper_baked = !upper_baked && (mLastUpperBodyBakedID != IMG_DEFAULT_AVATAR); - use_lkg_lower_baked = !lower_baked && (mLastLowerBodyBakedID != IMG_DEFAULT_AVATAR); - use_lkg_eyes_baked = !eyes_baked && (mLastEyesBakedID != IMG_DEFAULT_AVATAR); - use_lkg_skirt_baked = !skirt_baked && (mLastSkirtBakedID != IMG_DEFAULT_AVATAR); - - if( mHeadLayerSet ) - { - mHeadLayerSet->destroyComposite(); - } - - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->destroyComposite(); - } - - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->destroyComposite(); - } + const BOOL self_customizing = mIsSelf && gAgent.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures + const BOOL other_culled = !mIsSelf && mCulled; - if( mEyesLayerSet ) - { - mEyesLayerSet->destroyComposite(); - } + std::vector<bool> is_layer_baked; + is_layer_baked.resize(mBakedTextureData.size(), false); - if( mSkirtLayerSet ) - { - mSkirtLayerSet->destroyComposite(); - } + std::vector<bool> use_lkg_baked_layer; // lkg = "last known good" + use_lkg_baked_layer.resize(mBakedTextureData.size(), false); - } - else - if( !self_customize ) + for (U32 i=0; i < mBakedTextureData.size(); i++) { - // When you're changing clothes and you're not in Appearance mode, - // use the last-known good baked texture until you finish the first - // render of the new layerset. - use_lkg_head_baked = !head_baked && (mLastHeadBakedID != IMG_DEFAULT_AVATAR) && mHeadLayerSet && !mHeadLayerSet->getComposite()->isInitialized(); - use_lkg_upper_baked = !upper_baked && (mLastUpperBodyBakedID != IMG_DEFAULT_AVATAR) && mUpperBodyLayerSet && !mUpperBodyLayerSet->getComposite()->isInitialized(); - use_lkg_lower_baked = !lower_baked && (mLastLowerBodyBakedID != IMG_DEFAULT_AVATAR) && mLowerBodyLayerSet && !mLowerBodyLayerSet->getComposite()->isInitialized(); - use_lkg_eyes_baked = !eyes_baked && (mLastEyesBakedID != IMG_DEFAULT_AVATAR) && mEyesLayerSet && !mEyesLayerSet->getComposite()->isInitialized(); - use_lkg_skirt_baked = !skirt_baked && (mLastSkirtBakedID != IMG_DEFAULT_AVATAR) && mSkirtLayerSet && !mSkirtLayerSet->getComposite()->isInitialized(); - - if( use_lkg_head_baked ) - { - mHeadLayerSet->setUpdatesEnabled( TRUE ); - } + is_layer_baked[i] = isTextureDefined(mBakedTextureData[i].mTextureIndex); - if( use_lkg_upper_baked ) + if (!other_culled) { - mUpperBodyLayerSet->setUpdatesEnabled( TRUE ); - } - - if( use_lkg_lower_baked ) - { - mLowerBodyLayerSet->setUpdatesEnabled( TRUE ); + // When an avatar is changing clothes and not in Appearance mode, + // use the last-known good baked texture until it finish the first + // render of the new layerset. + use_lkg_baked_layer[i] = (!is_layer_baked[i] + && (mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) + && mBakedTextureData[i].mTexLayerSet + && !mBakedTextureData[i].mTexLayerSet->getComposite()->isInitialized()); + if (use_lkg_baked_layer[i]) + { + mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled(TRUE); + } } - - if( use_lkg_eyes_baked ) + else { - mEyesLayerSet->setUpdatesEnabled( TRUE ); + use_lkg_baked_layer[i] = (!is_layer_baked[i] + && mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR); + if (mBakedTextureData[i].mTexLayerSet) + { + mBakedTextureData[i].mTexLayerSet->destroyComposite(); + } } - if( use_lkg_skirt_baked ) - { - mSkirtLayerSet->setUpdatesEnabled( TRUE ); - } } // Baked textures should be requested from the sim this avatar is on. JC - LLHost target_host = getObjectHost(); + const LLHost target_host = getObjectHost(); if (!target_host.isOk()) { llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl; } - - // Head - if( use_lkg_head_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastHeadBakedID, target_host ); - mHeadMesh0.setTexture( baked ); - mHeadMesh1.setTexture( baked ); - mHeadMesh2.setTexture( baked ); - mHeadMesh3.setTexture( baked ); - mHeadMesh4.setTexture( baked ); - mEyeLashMesh0.setTexture( baked ); - } - else - if( !self_customize && head_baked ) - { - LLViewerImage* baked = getTEImage( TEX_HEAD_BAKED ); - if( baked->getID() == mLastHeadBakedID ) - { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); - } - else - { - mHeadBakedLoaded = FALSE; - mHeadMaskDiscard = -1; - baked->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); - } - } - else - if( mHeadLayerSet && !other_culled ) - { - mHeadLayerSet->createComposite(); - mHeadLayerSet->setUpdatesEnabled( TRUE ); - mHeadMesh0.setLayerSet( mHeadLayerSet ); - mHeadMesh1.setLayerSet( mHeadLayerSet ); - mHeadMesh2.setLayerSet( mHeadLayerSet ); - mHeadMesh3.setLayerSet( mHeadLayerSet ); - mHeadMesh4.setLayerSet( mHeadLayerSet ); - mEyeLashMesh0.setLayerSet( mHeadLayerSet ); - } - else - { - mHeadMesh0.setTexture( default_tex ); - mHeadMesh1.setTexture( default_tex ); - mHeadMesh2.setTexture( default_tex ); - mHeadMesh3.setTexture( default_tex ); - mHeadMesh4.setTexture( default_tex ); - mEyeLashMesh0.setTexture( default_tex ); - } - // Upper body - if( use_lkg_upper_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastUpperBodyBakedID, target_host ); - mUpperBodyMesh0.setTexture( baked ); - mUpperBodyMesh1.setTexture( baked ); - mUpperBodyMesh2.setTexture( baked ); - mUpperBodyMesh3.setTexture( baked ); - mUpperBodyMesh4.setTexture( baked ); - } - else - if( !self_customize && upper_baked ) + for (U32 i=0; i < mBakedTextureData.size(); i++) { - LLViewerImage* baked = getTEImage( TEX_UPPER_BAKED ); - - if( baked->getID() == mLastUpperBodyBakedID ) + if (use_lkg_baked_layer[i]) { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); - } - else - { - mUpperBakedLoaded = FALSE; - mUpperMaskDiscard = -1; - baked->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + LLViewerImage* baked_img = gImageList.getImageFromHost( mBakedTextureData[i].mLastTextureIndex, target_host ); + for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) + { + mBakedTextureData[i].mMeshes[k]->setTexture( baked_img ); + } } - } - else - if( mUpperBodyLayerSet && !other_culled ) - { - mUpperBodyLayerSet->createComposite(); - mUpperBodyLayerSet->setUpdatesEnabled( TRUE ); - mUpperBodyMesh0.setLayerSet( mUpperBodyLayerSet ); - mUpperBodyMesh1.setLayerSet( mUpperBodyLayerSet ); - mUpperBodyMesh2.setLayerSet( mUpperBodyLayerSet ); - mUpperBodyMesh3.setLayerSet( mUpperBodyLayerSet ); - mUpperBodyMesh4.setLayerSet( mUpperBodyLayerSet ); - } - else - { - mUpperBodyMesh0.setTexture( default_tex ); - mUpperBodyMesh1.setTexture( default_tex ); - mUpperBodyMesh2.setTexture( default_tex ); - mUpperBodyMesh3.setTexture( default_tex ); - mUpperBodyMesh4.setTexture( default_tex ); - } - - // Lower body - if( use_lkg_lower_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastLowerBodyBakedID, target_host ); - mLowerBodyMesh0.setTexture( baked ); - mLowerBodyMesh1.setTexture( baked ); - mLowerBodyMesh2.setTexture( baked ); - mLowerBodyMesh3.setTexture( baked ); - mLowerBodyMesh4.setTexture( baked ); - } - else - if( !self_customize && lower_baked ) - { - LLViewerImage* baked = getTEImage( TEX_LOWER_BAKED ); - if( baked->getID() == mLastLowerBodyBakedID ) + else if (!self_customizing && is_layer_baked[i]) { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); + LLViewerImage* baked_img = getTEImage( mBakedTextureData[i].mTextureIndex ); + if( baked_img->getID() == mBakedTextureData[i].mLastTextureIndex ) + { + // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). + useBakedTexture( baked_img->getID() ); + } + else + { + mBakedTextureData[i].mIsLoaded = FALSE; + if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) ) + { + baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); + } + baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + } } - else + else if (mBakedTextureData[i].mTexLayerSet + && !other_culled + && (i != BAKED_HAIR || is_layer_baked[i] || mIsSelf)) // ! BACKWARDS COMPATIBILITY ! workaround for old viewers. { - mLowerBakedLoaded = FALSE; - mLowerMaskDiscard = -1; - baked->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + mBakedTextureData[i].mTexLayerSet->createComposite(); + mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( TRUE ); + for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) + { + mBakedTextureData[i].mMeshes[k]->setLayerSet( mBakedTextureData[i].mTexLayerSet ); + } } } - else - if( mLowerBodyLayerSet && !other_culled ) - { - mLowerBodyLayerSet->createComposite(); - mLowerBodyLayerSet->setUpdatesEnabled( TRUE ); - mLowerBodyMesh0.setLayerSet( mLowerBodyLayerSet ); - mLowerBodyMesh1.setLayerSet( mLowerBodyLayerSet ); - mLowerBodyMesh2.setLayerSet( mLowerBodyLayerSet ); - mLowerBodyMesh3.setLayerSet( mLowerBodyLayerSet ); - mLowerBodyMesh4.setLayerSet( mLowerBodyLayerSet ); - } - else - { - mLowerBodyMesh0.setTexture( default_tex ); - mLowerBodyMesh1.setTexture( default_tex ); - mLowerBodyMesh2.setTexture( default_tex ); - mLowerBodyMesh3.setTexture( default_tex ); - mLowerBodyMesh4.setTexture( default_tex ); - } - - // Eyes - if( use_lkg_eyes_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastEyesBakedID, target_host ); - mEyeBallLeftMesh0.setTexture( baked ); - mEyeBallLeftMesh1.setTexture( baked ); - mEyeBallRightMesh0.setTexture( baked ); - mEyeBallRightMesh1.setTexture( baked ); - } - else - if( !self_customize && eyes_baked ) + + // ! BACKWARDS COMPATIBILITY ! + // Workaround for viewing avatars from old viewers that haven't baked hair textures. + // if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex)) + if (!is_layer_baked[BAKED_HAIR]) { - LLViewerImage* baked = getTEImage( TEX_EYES_BAKED ); - if( baked->getID() == mLastEyesBakedID ) - { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); - } - else + const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1); + LLViewerImage* hair_img = getTEImage( TEX_HAIR ); + for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) { - mEyesBakedLoaded = FALSE; - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + mBakedTextureData[BAKED_HAIR].mMeshes[i]->setTexture( hair_img ); } - } - else - if( mEyesLayerSet && !other_culled ) - { - mEyesLayerSet->createComposite(); - mEyesLayerSet->setUpdatesEnabled( TRUE ); - mEyeBallLeftMesh0.setLayerSet( mEyesLayerSet ); - mEyeBallLeftMesh1.setLayerSet( mEyesLayerSet ); - mEyeBallRightMesh0.setLayerSet( mEyesLayerSet ); - mEyeBallRightMesh1.setLayerSet( mEyesLayerSet ); - } - else + mHasBakedHair = FALSE; + } + else { - mEyeBallLeftMesh0.setTexture( default_tex ); - mEyeBallLeftMesh1.setTexture( default_tex ); - mEyeBallRightMesh0.setTexture( default_tex ); - mEyeBallRightMesh1.setTexture( default_tex ); - } - - // Skirt - if( use_lkg_skirt_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastSkirtBakedID, target_host ); - mSkirtMesh0.setTexture( baked ); - mSkirtMesh1.setTexture( baked ); - mSkirtMesh2.setTexture( baked ); - mSkirtMesh3.setTexture( baked ); - mSkirtMesh4.setTexture( baked ); - } - else - if( !self_customize && skirt_baked ) - { - LLViewerImage* baked = getTEImage( TEX_SKIRT_BAKED ); - if( baked->getID() == mLastSkirtBakedID ) + for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); + mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f ); } - else + mHasBakedHair = TRUE; + } + + /* // Head + BOOL head_baked_ready = (is_layer_baked[BAKED_HEAD] && mBakedTextureData[BAKED_HEAD].mIsLoaded) || other_culled; + setLocalTexture( TEX_HEAD_BODYPAINT, getTEImage( TEX_HEAD_BODYPAINT ), head_baked_ready ); */ + for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + baked_iter++) + { + const EBakedTextureIndex baked_index = baked_iter->first; + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second; + + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + local_tex_iter++) { - mSkirtBakedLoaded = FALSE; - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + const ETextureIndex texture_index = *local_tex_iter; + const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureData[baked_index].mIsLoaded) || other_culled; + setLocalTexture(texture_index, getTEImage(texture_index), is_baked_ready ); } } - else - if( mSkirtLayerSet && !other_culled) - { - mSkirtLayerSet->createComposite(); - mSkirtLayerSet->setUpdatesEnabled( TRUE ); - mSkirtMesh0.setLayerSet( mSkirtLayerSet ); - mSkirtMesh1.setLayerSet( mSkirtLayerSet ); - mSkirtMesh2.setLayerSet( mSkirtLayerSet ); - mSkirtMesh3.setLayerSet( mSkirtLayerSet ); - mSkirtMesh4.setLayerSet( mSkirtLayerSet ); - } - else - { - mSkirtMesh0.setTexture( default_tex ); - mSkirtMesh1.setTexture( default_tex ); - mSkirtMesh2.setTexture( default_tex ); - mSkirtMesh3.setTexture( default_tex ); - mSkirtMesh4.setTexture( default_tex ); - } - - mHairMesh0.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh1.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh2.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh3.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh4.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh5.setTexture( getTEImage( TEX_HAIR ) ); - - if( mTexHairColor ) - { - LLColor4 color = mTexHairColor->getColor(); - mHairMesh0.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh1.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh2.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh3.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh4.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh5.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - } - - // Head - BOOL head_baked_ready = (head_baked && mHeadBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_HEAD_BODYPAINT, getTEImage( TEX_HEAD_BODYPAINT ), head_baked_ready ); - - // Upper body - BOOL upper_baked_ready = (upper_baked && mUpperBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_UPPER_SHIRT, getTEImage( TEX_UPPER_SHIRT ), upper_baked_ready ); - setLocalTexture( LOCTEX_UPPER_BODYPAINT, getTEImage( TEX_UPPER_BODYPAINT ), upper_baked_ready ); - setLocalTexture( LOCTEX_UPPER_JACKET, getTEImage( TEX_UPPER_JACKET ), upper_baked_ready ); - setLocalTexture( LOCTEX_UPPER_GLOVES, getTEImage( TEX_UPPER_GLOVES ), upper_baked_ready ); - setLocalTexture( LOCTEX_UPPER_UNDERSHIRT, getTEImage( TEX_UPPER_UNDERSHIRT ), upper_baked_ready ); - - // Lower body - BOOL lower_baked_ready = (lower_baked && mLowerBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_LOWER_PANTS, getTEImage( TEX_LOWER_PANTS ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_BODYPAINT, getTEImage( TEX_LOWER_BODYPAINT ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_SHOES, getTEImage( TEX_LOWER_SHOES ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_SOCKS, getTEImage( TEX_LOWER_SOCKS ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_JACKET, getTEImage( TEX_LOWER_JACKET ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_UNDERPANTS, getTEImage( TEX_LOWER_UNDERPANTS ), lower_baked_ready ); - - // Eyes - BOOL eyes_baked_ready = (eyes_baked && mEyesBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_EYES_IRIS, getTEImage( TEX_EYES_IRIS ), eyes_baked_ready ); - - // Skirt - BOOL skirt_baked_ready = (skirt_baked && mSkirtBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_SKIRT, getTEImage( TEX_SKIRT ), skirt_baked_ready ); - removeMissingBakedTextures(); } //----------------------------------------------------------------------------- // setLocalTexture() //----------------------------------------------------------------------------- -void LLVOAvatar::setLocalTexture( ELocTexIndex idx, LLViewerImage* tex, BOOL baked_version_ready ) +void LLVOAvatar::setLocalTexture( ETextureIndex index, LLViewerImage* tex, BOOL baked_version_ready ) { + if (!isIndexLocalTexture(index)) return; + S32 desired_discard = mIsSelf ? 0 : 2; + LocalTextureData &local_tex_data = mLocalTextureData[index]; if (!baked_version_ready) { - if (tex != mLocalTexture[idx] || mLocalTextureBaked[idx]) + if (tex != local_tex_data.mImage || local_tex_data.mIsBakedReady) { - mLocalTextureDiscard[idx] = MAX_DISCARD_LEVEL+1; + local_tex_data.mDiscard = MAX_DISCARD_LEVEL+1; } if (tex->getID() != IMG_DEFAULT_AVATAR) { - if (mLocalTextureDiscard[idx] > desired_discard) + if (local_tex_data.mDiscard > desired_discard) { S32 tex_discard = tex->getDiscardLevel(); if (tex_discard >= 0 && tex_discard <= desired_discard) { - mLocalTextureDiscard[idx] = tex_discard; - requestLayerSetUpdate( idx ); - if( mIsSelf && gAgent.cameraCustomizeAvatar() ) + local_tex_data.mDiscard = tex_discard; + if( mIsSelf && !gAgent.cameraCustomizeAvatar() ) + { + requestLayerSetUpdate( index ); + } + else if( mIsSelf && gAgent.cameraCustomizeAvatar() ) { LLVisualParamHint::requestHintUpdates(); } } else { - tex->setLoadedCallback( onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), idx) ); + tex->setLoadedCallback( onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), index) ); } } tex->setMinDiscardLevel(desired_discard); } } - mLocalTextureBaked[idx] = baked_version_ready; - mLocalTexture[idx] = tex; + local_tex_data.mIsBakedReady = baked_version_ready; + local_tex_data.mImage = tex; } //----------------------------------------------------------------------------- @@ -7691,35 +7014,13 @@ void LLVOAvatar::setLocalTexture( ELocTexIndex idx, LLViewerImage* tex, BOOL bak //----------------------------------------------------------------------------- void LLVOAvatar::requestLayerSetUploads() { - BOOL upper_baked = (getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = (getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL head_baked = (getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = (getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = (getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - - if( !head_baked && mHeadLayerSet ) - { - mHeadLayerSet->requestUpload(); - } - - if( !upper_baked && mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->requestUpload(); - } - - if( !lower_baked && mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->requestUpload(); - } - - if( !eyes_baked && mEyesLayerSet ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mEyesLayerSet->requestUpload(); - } - - if( !skirt_baked && mSkirtLayerSet ) - { - mSkirtLayerSet->requestUpload(); + bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex); + if ( !layer_baked && mBakedTextureData[i].mTexLayerSet ) + { + mBakedTextureData[i].mTexLayerSet->requestUpload(); + } } } @@ -7729,31 +7030,13 @@ void LLVOAvatar::requestLayerSetUploads() //----------------------------------------------------------------------------- void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b ) { - if( mHeadLayerSet ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mHeadLayerSet->setUpdatesEnabled( b ); - } - - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->setUpdatesEnabled( b ); - } - - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->setUpdatesEnabled( b ); - } - - if( mEyesLayerSet ) - { - mEyesLayerSet->setUpdatesEnabled( b ); - } - - if( mSkirtLayerSet ) - { - mSkirtLayerSet->setUpdatesEnabled( b ); + if (mBakedTextureData[i].mTexLayerSet ) + { + mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( b ); + } } - } void LLVOAvatar::addChat(const LLChat& chat) @@ -7785,14 +7068,16 @@ void LLVOAvatar::clearChat() mChats.clear(); } -S32 LLVOAvatar::getLocalDiscardLevel( S32 index ) +S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index ) { + if (!isIndexLocalTexture(index)) return FALSE; + + LocalTextureData &local_tex_data = mLocalTextureData[index]; if (index >= 0 - && mLocalTexture[index].notNull() - && (mLocalTexture[index]->getID() != IMG_DEFAULT_AVATAR) - && !mLocalTexture[index]->isMissingAsset()) + && getLocalTextureID(index) != IMG_DEFAULT_AVATAR + && !local_tex_data.mImage->isMissingAsset()) { - return mLocalTexture[index]->getDiscardLevel(); + return local_tex_data.mImage->getDiscardLevel(); } else { @@ -7803,39 +7088,27 @@ S32 LLVOAvatar::getLocalDiscardLevel( S32 index ) //----------------------------------------------------------------------------- // isLocalTextureDataFinal() -// Returns true is the highest quality discard level exists for every texture +// Returns true if the highest quality discard level exists for every texture // in the layerset. //----------------------------------------------------------------------------- BOOL LLVOAvatar::isLocalTextureDataFinal( LLTexLayerSet* layerset ) { - if( layerset == mHeadLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_HEAD_BODYPAINT ) == 0; - } - else if( layerset == mUpperBodyLayerSet ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - return getLocalDiscardLevel( LOCTEX_UPPER_SHIRT ) == 0 && - getLocalDiscardLevel( LOCTEX_UPPER_BODYPAINT ) == 0 && - getLocalDiscardLevel( LOCTEX_UPPER_JACKET ) == 0 && - getLocalDiscardLevel( LOCTEX_UPPER_GLOVES ) == 0 && - getLocalDiscardLevel( LOCTEX_UPPER_UNDERSHIRT ) == 0; - } - else if( layerset == mLowerBodyLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_LOWER_PANTS ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_BODYPAINT ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_SHOES ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_SOCKS ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_JACKET ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_UNDERPANTS ) == 0; - } - else if( layerset == mEyesLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_EYES_IRIS ) == 0; - } - else if( layerset == mSkirtLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_SKIRT ) == 0; + if (layerset == mBakedTextureData[i].mTexLayerSet) + { + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + local_tex_iter++) + { + if (getLocalDiscardLevel(*local_tex_iter) != 0) + { + return FALSE; + } + } + return TRUE; + } } llassert(0); @@ -7844,41 +7117,31 @@ BOOL LLVOAvatar::isLocalTextureDataFinal( LLTexLayerSet* layerset ) //----------------------------------------------------------------------------- // isLocalTextureDataAvailable() -// Returns true is at least the lowest quality discard level exists for every texture +// Returns true if at least the lowest quality discard level exists for every texture // in the layerset. //----------------------------------------------------------------------------- BOOL LLVOAvatar::isLocalTextureDataAvailable( LLTexLayerSet* layerset ) { - if( layerset == mHeadLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_HEAD_BODYPAINT ) >= 0; - } - else if( layerset == mUpperBodyLayerSet ) + /* if( layerset == mBakedTextureData[BAKED_HEAD].mTexLayerSet ) + return getLocalDiscardLevel( TEX_HEAD_BODYPAINT ) >= 0; */ + for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + baked_iter++) { - return getLocalDiscardLevel( LOCTEX_UPPER_SHIRT ) >= 0 && - getLocalDiscardLevel( LOCTEX_UPPER_BODYPAINT ) >= 0 && - getLocalDiscardLevel( LOCTEX_UPPER_JACKET ) >= 0 && - getLocalDiscardLevel( LOCTEX_UPPER_GLOVES ) >= 0 && - getLocalDiscardLevel( LOCTEX_UPPER_UNDERSHIRT ) >= 0; - } - else if( layerset == mLowerBodyLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_LOWER_PANTS ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_BODYPAINT ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_SHOES ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_SOCKS ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_JACKET ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_UNDERPANTS ) >= 0; - } - else if( layerset == mEyesLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_EYES_IRIS ) >= 0; - } - else if( layerset == mSkirtLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_SKIRT ) >= 0; + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureData[baked_index].mTexLayerSet) + { + bool ret = true; + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second; + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + local_tex_iter++) + { + ret &= (getLocalDiscardLevel(*local_tex_iter) >= 0); + } + return ret; + } } - llassert(0); return FALSE; } @@ -7888,31 +7151,14 @@ BOOL LLVOAvatar::isLocalTextureDataAvailable( LLTexLayerSet* layerset ) // getBakedTE() // Used by the LayerSet. (Layer sets don't in general know what textures depend on them.) //----------------------------------------------------------------------------- -LLVOAvatar::ETextureIndex LLVOAvatar::getBakedTE( LLTexLayerSet* layerset ) +ETextureIndex LLVOAvatar::getBakedTE( LLTexLayerSet* layerset ) { - if( layerset == mHeadLayerSet ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - return TEX_HEAD_BAKED; - } - else - if( layerset == mUpperBodyLayerSet ) - { - return TEX_UPPER_BAKED; - } - else - if( layerset == mLowerBodyLayerSet ) - { - return TEX_LOWER_BAKED; - } - else - if( layerset == mEyesLayerSet ) - { - return TEX_EYES_BAKED; - } - else - if( layerset == mSkirtLayerSet ) - { - return TEX_SKIRT_BAKED; + if (layerset == mBakedTextureData[i].mTexLayerSet ) + { + return mBakedTextureData[i].mTextureIndex; + } } llassert(0); @@ -7933,26 +7179,17 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) LLVOAvatar::cullAvatarsByPixelArea(); - switch( te ) + /* switch(te) + case TEX_HEAD_BAKED: + llinfos << "New baked texture: HEAD" << llendl; */ + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(te); + if (text_dict->mIsBakedTexture) + { + llinfos << "New baked texture: " << text_dict->mName << " UUID: " << uuid <<llendl; + } + else { - case TEX_HEAD_BAKED: - llinfos << "New baked texture: HEAD" << llendl; - break; - case TEX_UPPER_BAKED: - llinfos << "New baked texture: UPPER" << llendl; - break; - case TEX_LOWER_BAKED: - llinfos << "New baked texture: LOWER" << llendl; - break; - case TEX_EYES_BAKED: - llinfos << "New baked texture: EYES" << llendl; - break; - case TEX_SKIRT_BAKED: - llinfos << "New baked texture: SKIRT" << llendl; - break; - default: llwarns << "New baked texture: unknown te " << te << llendl; - break; } // dumpAvatarTEs( "setNewBakedTexture() send" ); @@ -7965,28 +7202,15 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) bool LLVOAvatar::hasPendingBakedUploads() { - bool head_pending = (mHeadLayerSet && mHeadLayerSet->getComposite()->uploadPending()); - bool upper_pending = (mUpperBodyLayerSet && mUpperBodyLayerSet->getComposite()->uploadPending()); - bool lower_pending = (mLowerBodyLayerSet && mLowerBodyLayerSet->getComposite()->uploadPending()); - bool eyes_pending = (mEyesLayerSet && mEyesLayerSet->getComposite()->uploadPending()); - bool skirt_pending = (mSkirtLayerSet && mSkirtLayerSet->getComposite()->uploadPending()); - - //llinfos << "TAT: LLVOAvatar::hasPendingBakedUploads()" - // << " head_pending " << head_pending - // << " upper_pending " << upper_pending - // << " lower_pending " << lower_pending - // << " eyes_pending " << eyes_pending - // << " skirt_pending " << skirt_pending - // << llendl; - - if (head_pending || upper_pending || lower_pending || eyes_pending || skirt_pending) - { - return true; - } - else + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - return false; + bool upload_pending = (mBakedTextureData[i].mTexLayerSet && mBakedTextureData[i].mTexLayerSet->getComposite()->uploadPending()); + if (upload_pending) + { + return true; + } } + return false; } //----------------------------------------------------------------------------- @@ -7997,56 +7221,50 @@ void LLVOAvatar::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid ) { setTETexture( te, uuid ); - switch(te) + /* switch(te) + case TEX_HEAD_BAKED: + if( mHeadLayerSet ) + mHeadLayerSet->cancelUpload(); */ + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - case TEX_HEAD_BAKED: - if( mHeadLayerSet ) + if ( mBakedTextureData[i].mTextureIndex == te && mBakedTextureData[i].mTexLayerSet) { - mHeadLayerSet->cancelUpload(); - } - break; - case TEX_UPPER_BAKED: - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->cancelUpload(); + mBakedTextureData[i].mTexLayerSet->cancelUpload(); } - break; - case TEX_LOWER_BAKED: - if( mLowerBodyLayerSet ) + } +} + +//----------------------------------------------------------------------------- +// releaseUnneccesaryTextures() +// release any component texture UUIDs for which we have a baked texture +//----------------------------------------------------------------------------- +void LLVOAvatar::releaseUnnecessaryTextures() +{ + // Backwards Compat: detect if the baked hair texture actually wasn't sent, and if so set to default + if (isTextureDefined(TEX_HAIR_BAKED) && getTEImage(TEX_HAIR_BAKED)->getID() == getTEImage(TEX_SKIRT_BAKED)->getID()) + { + if (getTEImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE) { - mLowerBodyLayerSet->cancelUpload(); + // Regression case of messaging system. Expected 21 textures, received 20. last texture is not valid so set to default + setTETexture(TEX_HAIR_BAKED, IMG_DEFAULT_AVATAR); } - break; - case TEX_EYES_BAKED: - if( mEyesLayerSet ) + } + + for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) + { + const LLVOAvatarDictionary::BakedDictionaryEntry * bakedDicEntry = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + // skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID + if (!isTextureDefined(bakedDicEntry->mTextureIndex) + && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) )) { - mEyesLayerSet->cancelUpload(); + continue; } - break; - case TEX_SKIRT_BAKED: - if( mSkirtLayerSet ) + + for (U8 texture = 0; texture < bakedDicEntry->mLocalTextures.size(); texture++) { - mSkirtLayerSet->cancelUpload(); + const U8 te = (ETextureIndex)bakedDicEntry->mLocalTextures[texture]; + setTETexture(te, IMG_DEFAULT_AVATAR); } - break; - - case TEX_HEAD_BODYPAINT: - case TEX_UPPER_SHIRT: - case TEX_LOWER_PANTS: - case TEX_EYES_IRIS: - case TEX_HAIR: - case TEX_UPPER_BODYPAINT: - case TEX_LOWER_BODYPAINT: - case TEX_LOWER_SHOES: - case TEX_LOWER_SOCKS: - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: - case TEX_UPPER_GLOVES: - case TEX_UPPER_UNDERSHIRT: - case TEX_LOWER_UNDERPANTS: - case TEX_SKIRT: - case TEX_NUM_ENTRIES: - break; } } @@ -8056,21 +7274,9 @@ void LLVOAvatar::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid ) //----------------------------------------------------------------------------- void LLVOAvatar::onCustomizeStart() { - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if( avatar ) - { - for( S32 i = 0; i < BAKED_TEXTURE_COUNT; i++ ) - { - S32 tex_index = sBakedTextureIndices[i]; - avatar->mSavedTE[ tex_index ] = avatar->getTEImage(tex_index)->getID(); - avatar->setTEImage( tex_index, gImageList.getImage(IMG_DEFAULT_AVATAR) ); - } - - avatar->updateMeshTextures(); - -// avatar->dumpAvatarTEs( "onCustomizeStart() send" ); - gAgent.sendAgentSetAppearance(); - } + // We're no longer doing any baking or invalidating on entering + // appearance editing mode. Leaving function in place in case + // further changes require us to do something at this point - Nyx } //----------------------------------------------------------------------------- @@ -8079,29 +7285,31 @@ void LLVOAvatar::onCustomizeStart() //----------------------------------------------------------------------------- void LLVOAvatar::onCustomizeEnd() { - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if( !avatar ) return; + LLVOAvatar *avatarp = gAgent.getAvatarObject(); + if (avatarp) + { + avatarp->invalidateAll(); + avatarp->requestLayerSetUploads(); + } +} - LLHost target_host = avatar->getObjectHost(); - for( S32 i = 0; i < BAKED_TEXTURE_COUNT; i++ ) +void LLVOAvatar::onChangeSelfInvisible(BOOL newvalue) +{ + LLVOAvatar *avatarp = gAgent.getAvatarObject(); + if (avatarp) + { + if (newvalue) { - S32 tex_index = sBakedTextureIndices[i]; - const LLUUID& saved = avatar->mSavedTE[ tex_index ]; - if( !saved.isNull() ) - { - avatar->setTEImage( tex_index, gImageList.getImageFromHost( saved, target_host ) ); - } + // we have just requested to set the avatar's baked textures to invisible + avatarp->setInvisible(TRUE); } - - avatar->updateMeshTextures(); - - if( !LLApp::isExiting()) + else { - avatar->requestLayerSetUploads(); + avatarp->setInvisible(FALSE); } - - gAgent.sendAgentSetAppearance(); } +} + BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] ) { @@ -8181,7 +7389,7 @@ void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, B } } -LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te ) +LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te ) { LLColor4 color; const char* param_name[3]; @@ -8198,56 +7406,36 @@ LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te ) void LLVOAvatar::dumpAvatarTEs( const std::string& context ) -{ +{ + /* const char* te_name[] = { + "TEX_HEAD_BODYPAINT ", + "TEX_UPPER_SHIRT ", */ llinfos << (mIsSelf ? "Self: " : "Other: ") << context << llendl; - for( S32 i=0; i<TEX_NUM_ENTRIES; i++ ) + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) { - const char* te_name[] = { - "TEX_HEAD_BODYPAINT ", - "TEX_UPPER_SHIRT ", - "TEX_LOWER_PANTS ", - "TEX_EYES_IRIS ", - "TEX_HAIR ", - "TEX_UPPER_BODYPAINT ", - "TEX_LOWER_BODYPAINT ", - "TEX_LOWER_SHOES ", - "TEX_HEAD_BAKED ", - "TEX_UPPER_BAKED ", - "TEX_LOWER_BAKED ", - "TEX_EYES_BAKED ", - "TEX_LOWER_SOCKS ", - "TEX_UPPER_JACKET ", - "TEX_LOWER_JACKET ", - "TEX_UPPER_GLOVES ", - "TEX_UPPER_UNDERSHIRT ", - "TEX_LOWER_UNDERPANTS ", - "TEX_SKIRT ", - "TEX_SKIRT_BAKED " - }; - - LLViewerImage* te_image = getTEImage(i); + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + const LLViewerImage* te_image = getTEImage(iter->first); if( !te_image ) { - llinfos << " " << te_name[i] << ": null ptr" << llendl; + llinfos << " " << text_dict->mName << ": null ptr" << llendl; } - else - if( te_image->getID().isNull() ) + else if( te_image->getID().isNull() ) { - llinfos << " " << te_name[i] << ": null UUID" << llendl; + llinfos << " " << text_dict->mName << ": null UUID" << llendl; } - else - if( te_image->getID() == IMG_DEFAULT ) + else if( te_image->getID() == IMG_DEFAULT ) { - llinfos << " " << te_name[i] << ": IMG_DEFAULT" << llendl; + llinfos << " " << text_dict->mName << ": IMG_DEFAULT" << llendl; } - else - if( te_image->getID() == IMG_DEFAULT_AVATAR ) + else if( te_image->getID() == IMG_DEFAULT_AVATAR ) { - llinfos << " " << te_name[i] << ": IMG_DEFAULT_AVATAR" << llendl; + llinfos << " " << text_dict->mName << ": IMG_DEFAULT_AVATAR" << llendl; } else { - llinfos << " " << te_name[i] << ": " << te_image->getID() << llendl; + llinfos << " " << text_dict->mName << ": " << te_image->getID() << llendl; } } } @@ -8290,80 +7478,51 @@ void LLVOAvatar::updateAttachmentVisibility(U32 camera_mode) // Given a texture entry, determine which wearable type owns it. // static -LLUUID LLVOAvatar::getDefaultTEImageID( S32 te ) +LLUUID LLVOAvatar::getDefaultTEImageID(ETextureIndex index ) { - switch( te ) + /* switch( index ) + case TEX_UPPER_SHIRT: return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") ); */ + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + const std::string &default_image_name = text_dict->mDefaultImageName; + if (default_image_name == "") { - case TEX_UPPER_SHIRT: return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") ); - case TEX_LOWER_PANTS: return LLUUID( gSavedSettings.getString("UIImgDefaultPantsUUID") ); - case TEX_EYES_IRIS: return LLUUID( gSavedSettings.getString("UIImgDefaultEyesUUID") ); - case TEX_HAIR: return LLUUID( gSavedSettings.getString("UIImgDefaultHairUUID") ); - case TEX_LOWER_SHOES: return LLUUID( gSavedSettings.getString("UIImgDefaultShoesUUID") ); - case TEX_LOWER_SOCKS: return LLUUID( gSavedSettings.getString("UIImgDefaultSocksUUID") ); - case TEX_UPPER_GLOVES: return LLUUID( gSavedSettings.getString("UIImgDefaultGlovesUUID") ); - - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: return LLUUID( gSavedSettings.getString("UIImgDefaultJacketUUID") ); - - case TEX_UPPER_UNDERSHIRT: - case TEX_LOWER_UNDERPANTS: return LLUUID( gSavedSettings.getString("UIImgDefaultUnderwearUUID") ); - - case TEX_SKIRT: return LLUUID( gSavedSettings.getString("UIImgDefaultSkirtUUID") ); - - default: return IMG_DEFAULT_AVATAR; + return IMG_DEFAULT_AVATAR; + } + else + { + return LLUUID(gSavedSettings.getString(default_image_name)); } } +void LLVOAvatar::setInvisible(BOOL newvalue) +{ + if (newvalue) + { + setCompositeUpdatesEnabled(FALSE); + for (U32 i = 0; i < mBakedTextureData.size(); i++ ) + { + setNewBakedTexture(mBakedTextureData[i].mTextureIndex, IMG_INVISIBLE); + } + gAgent.sendAgentSetAppearance(); + } + else + { + setCompositeUpdatesEnabled(TRUE); + invalidateAll(); + requestLayerSetUploads(); + gAgent.sendAgentSetAppearance(); + } +} // Given a texture entry, determine which wearable type owns it. // static -EWearableType LLVOAvatar::getTEWearableType( S32 te ) +EWearableType LLVOAvatar::getTEWearableType(ETextureIndex index ) { - switch( te ) - { - case TEX_UPPER_SHIRT: - return WT_SHIRT; - - case TEX_LOWER_PANTS: - return WT_PANTS; - - case TEX_EYES_IRIS: - return WT_EYES; - - case TEX_HAIR: - return WT_HAIR; - - case TEX_HEAD_BODYPAINT: - case TEX_UPPER_BODYPAINT: - case TEX_LOWER_BODYPAINT: - return WT_SKIN; - - case TEX_LOWER_SHOES: - return WT_SHOES; - - case TEX_LOWER_SOCKS: - return WT_SOCKS; - - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: - return WT_JACKET; - - case TEX_UPPER_GLOVES: - return WT_GLOVES; - - case TEX_UPPER_UNDERSHIRT: - return WT_UNDERSHIRT; - - case TEX_LOWER_UNDERPANTS: - return WT_UNDERPANTS; - - case TEX_SKIRT: - return WT_SKIRT; - - default: - return WT_INVALID; - } + /* switch(index) + case TEX_UPPER_SHIRT: + return WT_SHIRT; */ + return LLVOAvatarDictionary::getInstance()->getTexture(index)->mWearableType; } // Unlike most wearable functions, this works for both self and other. @@ -8371,57 +7530,68 @@ BOOL LLVOAvatar::isWearingWearableType( EWearableType type ) { if (mIsDummy) return TRUE; - ETextureIndex indicator_te; switch( type ) { - case WT_SHIRT: - indicator_te = TEX_UPPER_SHIRT; - break; - - case WT_PANTS: - indicator_te = TEX_LOWER_PANTS; - break; - - case WT_SHOES: - indicator_te = TEX_LOWER_SHOES; - break; - - case WT_SOCKS: - indicator_te = TEX_LOWER_SOCKS; - break; - - case WT_JACKET: - indicator_te = TEX_UPPER_JACKET; - // Note: no need to test both upper and lower jacket - break; - - case WT_GLOVES: - indicator_te = TEX_UPPER_GLOVES; - break; - - case WT_UNDERSHIRT: - indicator_te = TEX_UPPER_UNDERSHIRT; - break; - - case WT_UNDERPANTS: - indicator_te = TEX_LOWER_UNDERPANTS; - break; - - case WT_SKIRT: - indicator_te = TEX_SKIRT; - break; - case WT_SHAPE: case WT_SKIN: case WT_HAIR: case WT_EYES: return TRUE; // everyone has all bodyparts - default: - return FALSE; + break; // Do nothing } - return ( getTEImage(indicator_te)->getID() != IMG_DEFAULT_AVATAR ); + /* switch(type) + case WT_SHIRT: + indicator_te = TEX_UPPER_SHIRT; */ + for (LLVOAvatarDictionary::texture_map_t::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + tex_iter++) + { + const LLVOAvatarDefines::ETextureIndex index = tex_iter->first; + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = tex_iter->second; + if (text_dict->mWearableType == type) + { + // If you're checking your own clothing, check the component texture + if (mIsSelf) + { + if (isTextureDefined(index)) + { + return TRUE; + } + else + { + return FALSE; + } + } + + // If you're checking another avatar's clothing, you don't have component textures. + // Thus, you must check to see if the corresponding baked texture is defined. + // NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing + // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that + // gets baked into a texture that always exists (upper or lower). + const std::string name = text_dict->mName; + for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + iter++) + { + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = iter->second; + if (baked_dict->mName == name) + { + if (isTextureDefined(baked_dict->mTextureIndex)) + { + return TRUE; + } + else + { + return FALSE; + } + } + } + return FALSE; + } + } + return FALSE; } @@ -8446,12 +7616,12 @@ void LLVOAvatar::clampAttachmentPositions() } } -BOOL LLVOAvatar::hasHUDAttachment() +BOOL LLVOAvatar::hasHUDAttachment() const { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ) { - attachment_map_t::iterator curiter = iter++; + attachment_map_t::const_iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; if (attachment->getIsHUDAttachment() && attachment->getObject()) { @@ -8461,13 +7631,13 @@ BOOL LLVOAvatar::hasHUDAttachment() return FALSE; } -LLBBox LLVOAvatar::getHUDBBox() +LLBBox LLVOAvatar::getHUDBBox() const { LLBBox bbox; - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ) { - attachment_map_t::iterator curiter = iter++; + attachment_map_t::const_iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; if (attachment->getIsHUDAttachment() && attachment->getObject()) { @@ -8503,50 +7673,23 @@ void LLVOAvatar::onFirstTEMessageReceived() { mFirstTEMessageReceived = TRUE; - BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - - // Use any baked textures that we have even if they haven't downloaded yet. - // (That is, don't do a transition from unbaked to baked.) - if( head_baked ) - { - mLastHeadBakedID = getTEImage( TEX_HEAD_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_HEAD_BAKED ); - image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); - } - - if( upper_baked ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mLastUpperBodyBakedID = getTEImage( TEX_UPPER_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_UPPER_BAKED ); - image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); - } - - if( lower_baked ) - { - mLastLowerBodyBakedID = getTEImage( TEX_LOWER_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_LOWER_BAKED ); - image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); - } - - if( eyes_baked ) - { - mLastEyesBakedID = getTEImage( TEX_EYES_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_EYES_BAKED ); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); - } + bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex); - if( skirt_baked ) - { - mLastSkirtBakedID = getTEImage( TEX_SKIRT_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_SKIRT_BAKED ); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); + // Use any baked textures that we have even if they haven't downloaded yet. + // (That is, don't do a transition from unbaked to baked.) + if (layer_baked) + { + LLViewerImage* image = getTEImage( mBakedTextureData[i].mTextureIndex ); + mBakedTextureData[i].mLastTextureIndex = image->getID(); + // If we have more than one texture for the other baked layers, we'll want to call this for them too. + if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) ) + { + image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); + } + image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); + } } updateMeshTextures(); @@ -8593,11 +7736,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) unpackTEMessage(mesgsys, _PREHASH_ObjectData); // dumpAvatarTEs( "POST processAvatarAppearance()" ); -// llinfos << "Received AvatarAppearance: " << (mIsSelf ? "(self): " : "(other): " ) << -// (( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "HEAD " : "head " ) << -// (( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "UPPER " : "upper " ) << -// (( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "LOWER " : "lower " ) << -// (( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "EYES" : "eyes" ) << llendl; + //llinfos << "Received AvatarAppearance: " << (mIsSelf ? "(self): " : "(other): ") << std::endl << + // (isTextureDefined(TEX_HEAD_BAKED) ? "HEAD " : "head " ) << (getTEImage(TEX_HEAD_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_UPPER_BAKED) ? "UPPER " : "upper " ) << (getTEImage(TEX_UPPER_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_LOWER_BAKED) ? "LOWER " : "lower " ) << (getTEImage(TEX_LOWER_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_SKIRT_BAKED) ? "SKIRT " : "skirt " ) << (getTEImage(TEX_SKIRT_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_HAIR_BAKED) ? "HAIR" : "hair " ) << (getTEImage(TEX_HAIR_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_EYES_BAKED) ? "EYES" : "eyes" ) << (getTEImage(TEX_EYES_BAKED)->getID()) << llendl ; if( !mFirstTEMessageReceived ) { @@ -8605,6 +7750,12 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } setCompositeUpdatesEnabled( FALSE ); + + if (!mIsSelf) + { + releaseUnnecessaryTextures(); + } + updateMeshTextures(); // enables updates for laysets without baked textures. // parse visual params @@ -8652,7 +7803,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) param->setAnimationTarget(newWeight, FALSE); } } - param = getNextVisualParam(); } } @@ -8726,28 +7876,20 @@ void LLVOAvatar::getAnimNames( LLDynamicArray<std::string>* names ) void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { - //llinfos << "onBakedTextureMasksLoaded: " << src_vi->getID() << llendl; - LLMemType mt(LLMemType::MTYPE_AVATAR); - - LLUUID id = src_vi->getID(); + if (!userdata) return; - if (!userdata) - { - return; - } + //llinfos << "onBakedTextureMasksLoaded: " << src_vi->getID() << llendl; + const LLMemType mt(LLMemType::MTYPE_AVATAR); + const LLUUID id = src_vi->getID(); LLTextureMaskData* maskData = (LLTextureMaskData*) userdata; LLVOAvatar* self = (LLVOAvatar*) gObjectList.findObject( maskData->mAvatarID ); // if discard level is 2 less than last discard level we processed, or we hit 0, // then generate morph masks - if( self && success && (discard_level < maskData->mLastDiscardLevel - 2 || discard_level == 0) ) + if(self && success && (discard_level < maskData->mLastDiscardLevel - 2 || discard_level == 0)) { - LLViewerImage* head_baked = self->getTEImage( TEX_HEAD_BAKED ); - LLViewerImage* upper_baked = self->getTEImage( TEX_UPPER_BAKED ); - LLViewerImage* lower_baked = self->getTEImage( TEX_LOWER_BAKED ); - - if( aux_src && aux_src->getComponents() == 1 ) + if(aux_src && aux_src->getComponents() == 1) { if (!aux_src->getData()) { @@ -8770,70 +7912,49 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - if( id == head_baked->getID() ) - { - if (self->mHeadLayerSet) - { - //llinfos << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << llendl; - self->mHeadLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); - maskData->mLastDiscardLevel = discard_level; - self->mHeadMaskDiscard = discard_level; - if (self->mHeadMaskTexName) - { - LLImageGL::deleteTextures(1, &self->mHeadMaskTexName); - } - self->mHeadMaskTexName = gl_name; - } - else - { - llwarns << "onBakedTextureMasksLoaded: no mHeadLayerSet." << llendl; - } - } - else - if( id == upper_baked->getID() ) - { - if ( self->mUpperBodyLayerSet) - { - //llinfos << "onBakedTextureMasksLoaded for upper body " << id << " discard = " << discard_level << llendl; - self->mUpperBodyLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); - maskData->mLastDiscardLevel = discard_level; - self->mUpperMaskDiscard = discard_level; - if (self->mUpperMaskTexName) - { - LLImageGL::deleteTextures(1, &self->mUpperMaskTexName); - } - self->mUpperMaskTexName = gl_name; - } - else - { - llwarns << "onBakedTextureMasksLoaded: no mHeadLayerSet." << llendl; - } - } - else - if( id == lower_baked->getID() ) + /* if( id == head_baked->getID() ) + if (self->mBakedTextureData[BAKED_HEAD].mTexLayerSet) + //llinfos << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << llendl; + self->mBakedTextureData[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); + maskData->mLastDiscardLevel = discard_level; */ + bool found_texture_id = false; + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) { - if ( self->mLowerBodyLayerSet ) + + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + if (text_dict->mIsUsedByBakedTexture) { - //llinfos << "onBakedTextureMasksLoaded for lower body " << id << " discard = " << discard_level << llendl; - self->mLowerBodyLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); - maskData->mLastDiscardLevel = discard_level; - self->mLowerMaskDiscard = discard_level; - if (self->mLowerMaskTexName) + const ETextureIndex texture_index = iter->first; + const LLViewerImage *baked_img = self->getTEImage(texture_index); + if (id == baked_img->getID()) { - LLImageGL::deleteTextures(1, &self->mLowerMaskTexName); + const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; + if (self->mBakedTextureData[baked_index].mTexLayerSet) + { + //llinfos << "onBakedTextureMasksLoaded for " << text_dict->mName << " " << id << " discard = " << discard_level << llendl; + self->mBakedTextureData[baked_index].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); + maskData->mLastDiscardLevel = discard_level; + if (self->mBakedTextureData[baked_index].mMaskTexName) + { + LLImageGL::deleteTextures(1, &(self->mBakedTextureData[baked_index].mMaskTexName)); + } + self->mBakedTextureData[baked_index].mMaskTexName = gl_name; + } + else + { + llwarns << "onBakedTextureMasksLoaded: no LayerSet for " << text_dict->mName << "." << llendl; + } + found_texture_id = true; + break; } - self->mLowerMaskTexName = gl_name; - } - else - { - llwarns << "onBakedTextureMasksLoaded: no mHeadLayerSet." << llendl; } } - else + if (!found_texture_id) { llinfos << "onBakedTextureMasksLoaded(): unexpected image id: " << id << llendl; } - self->dirtyMesh(); } else @@ -8848,7 +7969,6 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, { delete maskData; } - } // static @@ -8895,109 +8015,34 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLIma // Called when baked texture is loaded and also when we start up with a baked texture void LLVOAvatar::useBakedTexture( const LLUUID& id ) { -// llinfos << "useBakedTexture" << llendl; - LLViewerImage* head_baked = getTEImage( TEX_HEAD_BAKED ); - LLViewerImage* upper_baked = getTEImage( TEX_UPPER_BAKED ); - LLViewerImage* lower_baked = getTEImage( TEX_LOWER_BAKED ); - LLViewerImage* eyes_baked = getTEImage( TEX_EYES_BAKED ); - LLViewerImage* skirt_baked = getTEImage( TEX_SKIRT_BAKED ); - - if( id == head_baked->getID() ) - { - mHeadBakedLoaded = TRUE; - - mLastHeadBakedID = id; - mHeadMesh0.setTexture( head_baked ); - mHeadMesh1.setTexture( head_baked ); - mHeadMesh2.setTexture( head_baked ); - mHeadMesh3.setTexture( head_baked ); - mHeadMesh4.setTexture( head_baked ); - mEyeLashMesh0.setTexture( head_baked ); - if( mHeadLayerSet ) - { - mHeadLayerSet->destroyComposite(); - } - setLocalTexture( LOCTEX_HEAD_BODYPAINT, getTEImage( TEX_HEAD_BODYPAINT ), TRUE ); - } - else - if( id == upper_baked->getID() ) - { - mUpperBakedLoaded = TRUE; - - mLastUpperBodyBakedID = id; - mUpperBodyMesh0.setTexture( upper_baked ); - mUpperBodyMesh1.setTexture( upper_baked ); - mUpperBodyMesh2.setTexture( upper_baked ); - mUpperBodyMesh3.setTexture( upper_baked ); - mUpperBodyMesh4.setTexture( upper_baked ); - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->destroyComposite(); - } - - setLocalTexture( LOCTEX_UPPER_SHIRT, getTEImage( TEX_UPPER_SHIRT ), TRUE ); - setLocalTexture( LOCTEX_UPPER_BODYPAINT, getTEImage( TEX_UPPER_BODYPAINT ), TRUE ); - setLocalTexture( LOCTEX_UPPER_JACKET, getTEImage( TEX_UPPER_JACKET ), TRUE ); - setLocalTexture( LOCTEX_UPPER_GLOVES, getTEImage( TEX_UPPER_GLOVES ), TRUE ); - setLocalTexture( LOCTEX_UPPER_UNDERSHIRT, getTEImage( TEX_UPPER_UNDERSHIRT ), TRUE ); - } - else - if( id == lower_baked->getID() ) - { - mLowerBakedLoaded = TRUE; - - mLastLowerBodyBakedID = id; - mLowerBodyMesh0.setTexture( lower_baked ); - mLowerBodyMesh1.setTexture( lower_baked ); - mLowerBodyMesh2.setTexture( lower_baked ); - mLowerBodyMesh3.setTexture( lower_baked ); - mLowerBodyMesh4.setTexture( lower_baked ); - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->destroyComposite(); - } - - setLocalTexture( LOCTEX_LOWER_PANTS, getTEImage( TEX_LOWER_PANTS ), TRUE ); - setLocalTexture( LOCTEX_LOWER_BODYPAINT, getTEImage( TEX_LOWER_BODYPAINT ), TRUE ); - setLocalTexture( LOCTEX_LOWER_SHOES, getTEImage( TEX_LOWER_SHOES ), TRUE ); - setLocalTexture( LOCTEX_LOWER_SOCKS, getTEImage( TEX_LOWER_SOCKS ), TRUE ); - setLocalTexture( LOCTEX_LOWER_JACKET, getTEImage( TEX_LOWER_JACKET ), TRUE ); - setLocalTexture( LOCTEX_LOWER_UNDERPANTS, getTEImage( TEX_LOWER_UNDERPANTS ), TRUE ); - } - else - if( id == eyes_baked->getID() ) - { - mEyesBakedLoaded = TRUE; - - mLastEyesBakedID = id; - mEyeBallLeftMesh0.setTexture( eyes_baked ); - mEyeBallLeftMesh1.setTexture( eyes_baked ); - mEyeBallRightMesh0.setTexture( eyes_baked ); - mEyeBallRightMesh1.setTexture( eyes_baked ); - if( mEyesLayerSet ) - { - mEyesLayerSet->destroyComposite(); - } - - setLocalTexture( LOCTEX_EYES_IRIS, getTEImage( TEX_EYES_IRIS ), TRUE ); - } - else - if( id == skirt_baked->getID() ) + /* if(id == head_baked->getID()) + mHeadBakedLoaded = TRUE; + mLastHeadBakedID = id; + mHeadMesh0.setTexture( head_baked ); + mHeadMesh1.setTexture( head_baked ); */ + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mSkirtBakedLoaded = TRUE; - - mLastSkirtBakedID = id; - mSkirtMesh0.setTexture( skirt_baked ); - mSkirtMesh1.setTexture( skirt_baked ); - mSkirtMesh2.setTexture( skirt_baked ); - mSkirtMesh3.setTexture( skirt_baked ); - mSkirtMesh4.setTexture( skirt_baked ); - if( mSkirtLayerSet ) + LLViewerImage* image_baked = getTEImage( mBakedTextureData[i].mTextureIndex ); + if (id == image_baked->getID()) { - mSkirtLayerSet->destroyComposite(); + mBakedTextureData[i].mIsLoaded = true; + mBakedTextureData[i].mLastTextureIndex = id; + for (U32 k = 0; k < mBakedTextureData[i].mMeshes.size(); k++) + { + mBakedTextureData[i].mMeshes[k]->setTexture( image_baked ); + } + if (mBakedTextureData[i].mTexLayerSet) + { + mBakedTextureData[i].mTexLayerSet->destroyComposite(); + } + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + local_tex_iter++) + { + setLocalTexture(*local_tex_iter, getTEImage(*local_tex_iter), TRUE); + } } - - setLocalTexture( LOCTEX_SKIRT, getTEImage( TEX_SKIRT ), TRUE ); } dirtyMesh(); @@ -9036,11 +8081,11 @@ void LLVOAvatar::dumpArchetypeXML( void* ) } } - for( S32 te = 0; te < TEX_NUM_ENTRIES; te++ ) + for(U8 te = 0; te < TEX_NUM_INDICES; te++) { - if( LLVOAvatar::getTEWearableType( te ) == type ) + if( LLVOAvatar::getTEWearableType((ETextureIndex)te) == type ) { - LLViewerImage* te_image = avatar->getTEImage( te ); + LLViewerImage* te_image = avatar->getTEImage((ETextureIndex)te); if( te_image ) { std::string uuid_str; @@ -9093,39 +8138,39 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank() return 0; } +struct CompareScreenAreaGreater +{ + bool operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs) + { + return lhs->getPixelArea() > rhs->getPixelArea(); + } +}; + // static void LLVOAvatar::cullAvatarsByPixelArea() { std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater()); // Update the avatars that have changed status - S32 comp_rank = 1; U32 rank = 0; for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; BOOL culled; - if( inst->isDead() ) - { - culled = TRUE; - } - else if( inst->isSelf() || inst->isFullyBaked() ) + if (inst->isSelf() || inst->isFullyBaked()) { culled = FALSE; } - else + else { - culled = (comp_rank > LLVOAvatar::sMaxOtherAvatarsToComposite) || (inst->mPixelArea < MIN_PIXEL_AREA_FOR_COMPOSITE); - comp_rank++; + culled = TRUE; } - if( inst->mCulled != culled ) + if (inst->mCulled != culled) { inst->mCulled = culled; - lldebugs << "avatar " << inst->getID() << (culled ? " start culled" : " start not culled" ) << llendl; - inst->updateMeshTextures(); } @@ -9140,9 +8185,9 @@ void LLVOAvatar::cullAvatarsByPixelArea() } S32 grey_avatars = 0; - if( LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars) ) + if ( LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars) ) { - LLVOAvatar::deleteCachedImages(); + LLVOAvatar::deleteCachedImages(false); } else { @@ -9174,52 +8219,31 @@ const LLUUID& LLVOAvatar::grabLocalTexture(ETextureIndex index) BOOL LLVOAvatar::canGrabLocalTexture(ETextureIndex index) { // Check if the texture hasn't been baked yet. - if ( getTEImage( index )->getID() == IMG_DEFAULT_AVATAR ) + if (!isTextureDefined(index)) { lldebugs << "getTEImage( " << (U32) index << " )->getID() == IMG_DEFAULT_AVATAR" << llendl; return FALSE; } + if (gAgent.isGodlike()) + return TRUE; + // Check permissions of textures that show up in the // baked texture. We don't want people copying people's // work via baked textures. - std::vector<ETextureIndex> textures; - switch (index) - { - case TEX_EYES_BAKED: - textures.push_back(TEX_EYES_IRIS); - break; - case TEX_HEAD_BAKED: - textures.push_back(TEX_HEAD_BODYPAINT); - break; - case TEX_UPPER_BAKED: - textures.push_back(TEX_UPPER_BODYPAINT); - textures.push_back(TEX_UPPER_UNDERSHIRT); - textures.push_back(TEX_UPPER_SHIRT); - textures.push_back(TEX_UPPER_JACKET); - textures.push_back(TEX_UPPER_GLOVES); - break; - case TEX_LOWER_BAKED: - textures.push_back(TEX_LOWER_BODYPAINT); - textures.push_back(TEX_LOWER_UNDERPANTS); - textures.push_back(TEX_LOWER_PANTS); - textures.push_back(TEX_LOWER_JACKET); - textures.push_back(TEX_LOWER_SOCKS); - textures.push_back(TEX_LOWER_SHOES); - break; - case TEX_SKIRT_BAKED: - textures.push_back(TEX_SKIRT); - break; - default: - return FALSE; - break; - } - - std::vector<ETextureIndex>::iterator iter = textures.begin(); - std::vector<ETextureIndex>::iterator end = textures.end(); - for (; iter != end; ++iter) - { - ETextureIndex t_index = (*iter); + /* switch(index) + case TEX_EYES_BAKED: + textures.push_back(TEX_EYES_IRIS); */ + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + if (!text_dict->mIsUsedByBakedTexture) return FALSE; + + const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index); + for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); + iter != baked_dict->mLocalTextures.end(); + iter++) + { + const ETextureIndex t_index = (*iter); lldebugs << "Checking index " << (U32) t_index << llendl; const LLUUID& texture_id = getTEImage( t_index )->getID(); if (texture_id != IMG_DEFAULT_AVATAR) @@ -9266,62 +8290,43 @@ void LLVOAvatar::dumpLocalTextures() { llinfos << "Local Textures:" << llendl; - const char* names[] = { - "Shirt ", - "UpperTatoo", - "Pants ", - "LowerTatoo", - "Head Tatoo", - "Shoes ", - "Socks ", - "Upper Jckt", - "Lower Jckt", - "Gloves ", - "Undershirt", - "Underpants", - "Iris ", - "Skirt "}; - - ETextureIndex baked_equiv[] = { - TEX_UPPER_BAKED, - TEX_UPPER_BAKED, - TEX_LOWER_BAKED, - TEX_LOWER_BAKED, - TEX_HEAD_BAKED, - TEX_LOWER_BAKED, - TEX_LOWER_BAKED, - TEX_UPPER_BAKED, - TEX_LOWER_BAKED, - TEX_UPPER_BAKED, + /* ETextureIndex baked_equiv[] = { TEX_UPPER_BAKED, - TEX_LOWER_BAKED, - TEX_EYES_BAKED, - TEX_SKIRT_BAKED }; + if (isTextureDefined(baked_equiv[i])) */ + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) + { + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + if (!text_dict->mIsLocalTexture || !text_dict->mIsUsedByBakedTexture) + continue; + const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; + const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; - for( S32 i = 0; i < LOCTEX_NUM_ENTRIES; i++ ) - { - if( getTEImage( baked_equiv[i] )->getID() != IMG_DEFAULT_AVATAR ) + const std::string &name = text_dict->mName; + const LocalTextureData &local_tex_data = mLocalTextureData[iter->first]; + if (isTextureDefined(baked_equiv)) { #if LL_RELEASE_FOR_DOWNLOAD // End users don't get to trivially see avatar texture IDs, makes textures // easier to steal. JC - llinfos << "LocTex " << names[i] << ": Baked " << llendl; + llinfos << "LocTex " << name << ": Baked " << llendl; #else - llinfos << "LocTex " << names[i] << ": Baked " << getTEImage( baked_equiv[i] )->getID() << llendl; + llinfos << "LocTex " << name << ": Baked " << getTEImage( baked_equiv )->getID() << llendl; #endif } - else if (mLocalTexture[i].notNull()) + else if (local_tex_data.mImage.notNull()) { - if( mLocalTexture[i]->getID() == IMG_DEFAULT_AVATAR ) + if( local_tex_data.mImage->getID() == IMG_DEFAULT_AVATAR ) { - llinfos << "LocTex " << names[i] << ": None" << llendl; + llinfos << "LocTex " << name << ": None" << llendl; } else { - LLViewerImage* image = mLocalTexture[i]; + const LLViewerImage* image = local_tex_data.mImage; - llinfos << "LocTex " << names[i] << ": " + llinfos << "LocTex " << name << ": " << "Discard " << image->getDiscardLevel() << ", " << "(" << image->getWidth() << ", " << image->getHeight() << ") " #if !LL_RELEASE_FOR_DOWNLOAD @@ -9335,7 +8340,7 @@ void LLVOAvatar::dumpLocalTextures() } else { - llinfos << "LocTex " << names[i] << ": No LLViewerImage" << llendl; + llinfos << "LocTex " << name << ": No LLViewerImage" << llendl; } } } @@ -9354,30 +8359,25 @@ void LLVOAvatar::startAppearanceAnimation(BOOL set_by_user, BOOL play_sound) void LLVOAvatar::removeMissingBakedTextures() { - if (!mIsSelf) - { - return; - } - BOOL removed = FALSE; + if (!mIsSelf) return; - for( S32 i = 0; i < BAKED_TEXTURE_COUNT; i++ ) + BOOL removed = FALSE; + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - S32 te = sBakedTextureIndices[i]; - - if( getTEImage( te )->isMissingAsset() ) + const S32 te = mBakedTextureData[i].mTextureIndex; + if (getTEImage(te)->isMissingAsset()) { - setTEImage( te, gImageList.getImage(IMG_DEFAULT_AVATAR) ); + setTEImage(te, gImageList.getImage(IMG_DEFAULT_AVATAR)); removed = TRUE; } } - if( removed ) + if (removed) { - invalidateComposite( mEyesLayerSet, FALSE ); - invalidateComposite( mHeadLayerSet, FALSE ); - invalidateComposite( mUpperBodyLayerSet, FALSE ); - invalidateComposite( mLowerBodyLayerSet, FALSE ); - invalidateComposite( mSkirtLayerSet, FALSE ); + for(U32 i = 0; i < mBakedTextureData.size(); i++) + { + invalidateComposite(mBakedTextureData[i].mTexLayerSet, FALSE); + } updateMeshTextures(); requestLayerSetUploads(); } @@ -9385,15 +8385,15 @@ void LLVOAvatar::removeMissingBakedTextures() //----------------------------------------------------------------------------- -// LLVOAvatarInfo +// LLVOAvatarXmlInfo //----------------------------------------------------------------------------- -LLVOAvatarInfo::LLVOAvatarInfo() +LLVOAvatarXmlInfo::LLVOAvatarXmlInfo() : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0) { } -LLVOAvatarInfo::~LLVOAvatarInfo() +LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() { std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); @@ -9514,7 +8514,7 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) //----------------------------------------------------------------------------- // parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) { LLXmlTreeNode* node = root->getChildByName( "skeleton" ); if( !node ) @@ -9620,7 +8620,7 @@ BOOL LLVOAvatarInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlMeshNodes(): parses <mesh> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlMeshNodes(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); node; @@ -9710,7 +8710,7 @@ BOOL LLVOAvatarInfo::parseXmlMeshNodes(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlColorNodes(): parses <global_color> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlColorNodes(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); color_node; @@ -9772,7 +8772,7 @@ BOOL LLVOAvatarInfo::parseXmlColorNodes(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlLayerNodes(): parses <layer_set> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlLayerNodes(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); layer_node; @@ -9796,7 +8796,7 @@ BOOL LLVOAvatarInfo::parseXmlLayerNodes(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlDriverNodes(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) { LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); if( driver ) @@ -9874,41 +8874,17 @@ std::string LLVOAvatar::getFullname() const LLTexLayerSet* LLVOAvatar::getLayerSet(ETextureIndex index) const { - switch( index ) + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + if (text_dict->mIsUsedByBakedTexture) { - case TEX_HEAD_BAKED: - case TEX_HEAD_BODYPAINT: - return mHeadLayerSet; - - case TEX_UPPER_BAKED: - case TEX_UPPER_SHIRT: - case TEX_UPPER_BODYPAINT: - case TEX_UPPER_JACKET: - case TEX_UPPER_GLOVES: - case TEX_UPPER_UNDERSHIRT: - return mUpperBodyLayerSet; - - case TEX_LOWER_BAKED: - case TEX_LOWER_PANTS: - case TEX_LOWER_BODYPAINT: - case TEX_LOWER_SHOES: - case TEX_LOWER_SOCKS: - case TEX_LOWER_JACKET: - case TEX_LOWER_UNDERPANTS: - return mLowerBodyLayerSet; - - case TEX_EYES_BAKED: - case TEX_EYES_IRIS: - return mEyesLayerSet; - - case TEX_SKIRT_BAKED: - case TEX_SKIRT: - return mSkirtLayerSet; - - case TEX_HAIR: - default: - return NULL; + const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; + return mBakedTextureData[baked_index].mTexLayerSet; } + return NULL; } LLHost LLVOAvatar::getObjectHost() const @@ -9929,15 +8905,15 @@ void LLVOAvatar::updateFreezeCounter(S32 counter) { if(counter) { - sFreezeCounter = counter ; + sFreezeCounter = counter; } else if(sFreezeCounter > 0) { - sFreezeCounter-- ; + sFreezeCounter--; } else { - sFreezeCounter = 0 ; + sFreezeCounter = 0; } } @@ -9989,7 +8965,7 @@ void LLVOAvatar::updateImpostors() BOOL LLVOAvatar::isImpostor() const { - return (sUseImpostors && mUpdatePeriod >= VOAVATAR_IMPOSTOR_PERIOD) ? TRUE : FALSE; + return (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD) ? TRUE : FALSE; } @@ -10018,7 +8994,7 @@ void LLVOAvatar::cacheImpostorValues() getImpostorValues(mImpostorExtents, mImpostorAngle, mImpostorDistance); } -void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) +void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const { const LLVector3* ext = mDrawable->getSpatialExtents(); extents[0] = ext[0]; @@ -10032,6 +9008,85 @@ void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& di angle.mV[2] = da; } +void LLVOAvatar::idleUpdateRenderCost() +{ + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) + { + return; + } + + U32 shame = 1; + + std::set<LLUUID> textures; + + attachment_map_t::const_iterator iter; + for (iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + LLViewerObject* object = attachment->getObject(); + if (object && !object->isHUDAttachment()) + { + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + shame += 10; + LLVOVolume* volume = drawable->getVOVolume(); + if (volume) + { + shame += calc_shame(volume, textures); + } + } + } + } + + shame += textures.size() * 5; + + setDebugText(llformat("%d", shame)); + F32 green = 1.f-llclamp(((F32) shame-1024.f)/1024.f, 0.f, 1.f); + F32 red = llmin((F32) shame/1024.f, 1.f); + mText->setColor(LLColor4(red,green,0,1)); +} + +// static +BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) +{ + if (index < 0 || index >= TEX_NUM_INDICES) return false; + return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsLocalTexture; +} + +// static +BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index) +{ + if (index < 0 || index >= TEX_NUM_INDICES) return false; + return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsBakedTexture; +} + +const std::string LLVOAvatar::getBakedStatusForPrintout() const +{ + std::string line; + + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) + { + const ETextureIndex index = iter->first; + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + if (text_dict->mIsBakedTexture) + { + line += text_dict->mName; + if (isTextureDefined(index)) + { + line += "_baked"; + } + line += " "; + } + } + return line; +} + + U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures) { if (!volume) @@ -10136,45 +9191,11 @@ U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures) return shame; } -void LLVOAvatar::idleUpdateRenderCost() -{ - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) - { - return; - } - - U32 shame = 1; - - std::set<LLUUID> textures; - - attachment_map_t::const_iterator iter; - for (iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - LLViewerObject* object = attachment->getObject(); - if (object && !object->isHUDAttachment()) - { - LLDrawable* drawable = object->mDrawable; - if (drawable) - { - shame += 10; - LLVOVolume* volume = drawable->getVOVolume(); - if (volume) - { - shame += calc_shame(volume, textures); - } - } - } - } - - shame += textures.size() * 5; +//----------------------------------------------------------------------------- +// Utility functions +//----------------------------------------------------------------------------- - setDebugText(llformat("%d", shame)); - F32 green = 1.f-llclamp(((F32) shame-1024.f)/1024.f, 0.f, 1.f); - F32 red = llmin((F32) shame/1024.f, 1.f); - mText->setColor(LLColor4(red,green,0,1)); +F32 calc_bouncy_animation(F32 x) +{ + return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f; } - - |