From ef9fbe2193edcca43e5990c50a27f071c85a1951 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Wed, 24 Apr 2013 17:52:17 -0500 Subject: [PATCH] Attempt to speed up agent idle update by optimizing wearable/visualparam related lookups/iterations a bit more. Generalized several templates in llstl.h in order to support more containers. Removed several instances of is_in_map/getWearableCount being followed immediately by another lookup with the same key. find is more efficient, as we get an iterator to use instead of a simple boolean. --- indra/llappearance/llwearable.cpp | 9 ++- indra/llappearance/llwearable.h | 3 +- indra/llappearance/llwearabledata.cpp | 49 +++++++++++++---- indra/llappearance/llwearabledata.h | 31 ++++++++++- indra/llcharacter/llcharacter.cpp | 3 + indra/llcharacter/llcharacter.h | 30 +++++----- indra/llcharacter/llmotioncontroller.cpp | 8 +-- indra/llcommon/llsortedvector.h | 10 ++++ indra/llcommon/llstl.h | 70 ++++++++++++------------ indra/newview/llagentcamera.cpp | 8 ++- indra/newview/llinventorymodel.cpp | 5 +- indra/newview/llvoavatar.cpp | 60 ++++++++++++++++---- indra/newview/llvoavatar.h | 4 +- indra/newview/pipeline.cpp | 9 ++- 14 files changed, 210 insertions(+), 89 deletions(-) diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 44e0bdef8..c4704bf06 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -731,6 +731,7 @@ LLVisualParam* LLWearable::getVisualParam(S32 index) const void LLWearable::getVisualParams(visual_param_vec_t &list) { + list.reserve(mVisualParamIndexMap.size()); visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); visual_param_index_map_t::iterator end = mVisualParamIndexMap.end(); @@ -783,7 +784,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) if (!avatarp) return; // Pull params - for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) + /*for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) { // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. @@ -794,6 +795,12 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) avatarp->setVisualParamWeight( param_id, weight, FALSE ); } + }*/ + for( visual_param_index_map_t::iterator it = mVisualParamIndexMap.begin(); it != mVisualParamIndexMap.end(); ++it ) + { + LLVisualParam* param = it->second; + if(!((LLViewerVisualParam*)param)->getCrossWearable()) + avatarp->setVisualParamWeight( param->getID(), param->getWeight(), FALSE ); } } diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index ac25cec2f..e3f54b60e 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -31,6 +31,7 @@ #include "llextendedstatus.h" #include "llpermissions.h" #include "llsaleinfo.h" +#include "llsortedvector.h" #include "llwearabletype.h" #include "lllocaltextureobject.h" @@ -136,7 +137,7 @@ protected: typedef std::map param_map_t; param_map_t mSavedVisualParamMap; // last saved version of visual params - typedef std::map visual_param_index_map_t; + typedef LLSortedVector visual_param_index_map_t; visual_param_index_map_t mVisualParamIndexMap; te_map_t mTEMap; // maps TE to LocalTextureObject diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 4ade2b33a..61b45a94d 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -267,8 +267,7 @@ BOOL LLWearableData::isOnTop(LLWearable* wearable) const const LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) const { - //llassert_always(index == 0); - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + /*wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); if (wearable_iter == mWearableDatas.end()) { return NULL; @@ -281,49 +280,79 @@ const LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, else { return wearable_vec[index]; + }*/ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter != mWearableDatas.end() && index < wearable_iter->second.size()) + { + return wearable_iter->second[index]; } + return NULL; } LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) { - U32 count = getWearableCount(type); + /*U32 count = getWearableCount(type); if ( count == 0) { return NULL; } - return getWearable(type, count-1); + return getWearable(type, count-1);*/ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter != mWearableDatas.end() && !wearable_iter->second.empty()) + { + return wearable_iter->second.back(); + } + return NULL; } const LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) const { - U32 count = getWearableCount(type); + /*U32 count = getWearableCount(type); if ( count == 0) { return NULL; } - return getWearable(type, count-1); + return getWearable(type, count-1);*/ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter != mWearableDatas.end() && !wearable_iter->second.empty()) + { + return wearable_iter->second.back(); + } + return NULL; } LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) { - if (getWearableCount(type) == 0) + /*if (getWearableCount(type) == 0) { return NULL; } - return getWearable(type, 0); + return getWearable(type, 0);*/ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter != mWearableDatas.end() && !wearable_iter->second.empty()) + { + return wearable_iter->second.front(); + } + return NULL; } const LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) const { - if (getWearableCount(type) == 0) + /*if (getWearableCount(type) == 0) { return NULL; } - return getWearable(type, 0); + return getWearable(type, 0);*/ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter != mWearableDatas.end() && !wearable_iter->second.empty()) + { + return wearable_iter->second.front(); + } + return NULL; } U32 LLWearableData::getWearableCount(const LLWearableType::EType type) const diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h index 7c90dbde8..683f461e9 100644 --- a/indra/llappearance/llwearabledata.h +++ b/indra/llappearance/llwearabledata.h @@ -30,6 +30,7 @@ #include "llavatarappearancedefines.h" #include "llwearable.h" #include "llerror.h" +#include "boost/array.hpp" class LLAvatarAppearance; @@ -98,8 +99,34 @@ protected: protected: LLAvatarAppearance* mAvatarAppearance; typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts) - typedef std::map wearableentry_map_t; // wearable "categories" arranged by wearable type - wearableentry_map_t mWearableDatas; + //typedef std::map wearableentry_map_t; // wearable "categories" arranged by wearable type + + //Why this weird structure? LLWearableType::WT_COUNT small and known, therefore it's more efficient to make an array of vectors, indexed + //by wearable type. This allows O(1) lookups. This structure simply lets us plug in this optimization without touching any code elsewhere. + typedef boost::array,LLWearableType::WT_COUNT> wearable_array_t; + struct wearableentry_map_t : public wearable_array_t + { + wearableentry_map_t() + { + for(wearable_array_t::size_type i=0;i= (S32)size()) + return end(); + return begin() + index; + } + wearable_array_t::const_iterator find(const LLWearableType::EType& index) const + { + if(index < 0 || index >= (S32)size()) + return end(); + return begin() + index; + } + wearableentry_vec_t& operator [] (const S32 index) { return at(index).second; } + const wearableentry_vec_t& operator [] (const S32 index) const { return at(index).second; } + }; + wearableentry_map_t mWearableDatas; //Array for quicker lookups. }; diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 8ffebfd21..888c20cd4 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -469,6 +469,7 @@ void LLCharacter::addSharedVisualParam(LLVisualParam *param) void LLCharacter::addVisualParam(LLVisualParam *param) { S32 index = param->getID(); + // Add Index map std::pair idxres; idxres = mVisualParamIndexMap.insert(visual_param_index_map_t::value_type(index, param)); @@ -479,6 +480,8 @@ void LLCharacter::addVisualParam(LLVisualParam *param) visual_param_index_map_t::iterator index_iter = idxres.first; index_iter->second = param; } + + mVisualParamSortedVector[index] = param; if (param->getInfo()) { diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 0d66b1d52..2b872effa 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -38,6 +38,8 @@ #include "string_table.h" #include "llpointer.h" #include "llthread.h" +#include "llsortedvector.h" +#include class LLPolyMesh; @@ -208,21 +210,21 @@ public: // visual parameter accessors LLVisualParam* getFirstVisualParam() { - mCurIterator = mVisualParamIndexMap.begin(); + mCurIterator = mVisualParamSortedVector.begin(); return getNextVisualParam(); } LLVisualParam* getNextVisualParam() { - if (mCurIterator == mVisualParamIndexMap.end()) + if (mCurIterator == mVisualParamSortedVector.end()) return 0; return (mCurIterator++)->second; } - + S32 getVisualParamCountInGroup(const EVisualParamGroup group) const { S32 rtn = 0; - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); - iter != mVisualParamIndexMap.end(); + for (visual_param_sorted_vec_t::const_iterator iter = mVisualParamSortedVector.begin(); + iter != mVisualParamSortedVector.end(); /* */ ) { if ((iter++)->second->getGroup() == group) @@ -238,7 +240,7 @@ public: visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(id); return (iter == mVisualParamIndexMap.end()) ? 0 : iter->second; } - S32 getVisualParamID(LLVisualParam *id) + /*S32 getVisualParamID(LLVisualParam *id) { visual_param_index_map_t::iterator iter; for (iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) @@ -247,7 +249,7 @@ public: return iter->first; } return 0; - } + }*/ S32 getVisualParamCount() const { return (S32)mVisualParamIndexMap.size(); } LLVisualParam* getVisualParam(const char *name); @@ -278,13 +280,15 @@ protected: private: // visual parameter stuff - typedef std::map visual_param_index_map_t; - typedef std::map visual_param_name_map_t; - - visual_param_index_map_t::iterator mCurIterator; - visual_param_index_map_t mVisualParamIndexMap; - visual_param_name_map_t mVisualParamNameMap; + //typedef std::map visual_param_index_map_t; + typedef boost::unordered_map visual_param_index_map_t; //Hash map for fast lookup. + typedef LLSortedVector visual_param_sorted_vec_t; //Contiguous sorted array. + typedef std::map visual_param_name_map_t; + visual_param_sorted_vec_t::iterator mCurIterator; + visual_param_sorted_vec_t mVisualParamSortedVector; + visual_param_index_map_t mVisualParamIndexMap; + visual_param_name_map_t mVisualParamNameMap; static LLStringTable sVisualParamNames; }; diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index 39260582a..35dcc1057 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -83,13 +83,7 @@ LLMotionRegistry::~LLMotionRegistry() BOOL LLMotionRegistry::registerMotion( const LLUUID& id, LLMotionConstructor constructor ) { // llinfos << "Registering motion: " << name << llendl; - if (!is_in_map(mMotionTable, id)) - { - mMotionTable[id] = constructor; - return TRUE; - } - - return FALSE; + return mMotionTable.insert(std::make_pair(id,constructor)).second; } //----------------------------------------------------------------------------- diff --git a/indra/llcommon/llsortedvector.h b/indra/llcommon/llsortedvector.h index 391b82ee4..bb779e519 100644 --- a/indra/llcommon/llsortedvector.h +++ b/indra/llcommon/llsortedvector.h @@ -109,6 +109,16 @@ public: return const_cast(this)->find(key); } + //For easy insertion shorthand. Eases std::map => LLSortedVector drop-in replacement. + mapped_type& operator[] (const key_type& key) + { + return insert(std::make_pair(key,mapped_type())).first->second; + } + const mapped_type& operator[] (const key_type& key) const + { + return insert(std::make_pair(key,mapped_type())).first->second; + } + private: // Define our own 'less' comparator so we can specialize without messing // with std::less. diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 105b69d34..5c0e04fc7 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -175,35 +175,12 @@ struct CopyNewPointer } }; -// Simple function to help with finding pointers in maps. -// For example: -// typedef map_t; -// std::map foo; -// foo[18] = "there"; -// foo[2] = "hello"; -// const char* bar = get_ptr_in_map(foo, 2); // bar -> "hello" -// const char* baz = get_ptr_in_map(foo, 3); // baz == NULL -template -inline T* get_ptr_in_map(const std::map& inmap, const K& key) -{ - // Typedef here avoids warnings because of new c++ naming rules. - typedef typename std::map::const_iterator map_iter; - map_iter iter = inmap.find(key); - if(iter == inmap.end()) - { - return NULL; - } - else - { - return iter->second; - } -}; - // helper function which returns true if key is in inmap. -template -inline bool is_in_map(const std::map& inmap, const K& key) +template +//Singu note: This has been generalized to support a broader range of map-esque containers +inline bool is_in_map(const T& inmap, typename const T::key_type& key) { - typedef typename std::map::const_iterator map_iter; + typedef typename T::const_iterator map_iter; if(inmap.find(key) == inmap.end()) { return false; @@ -218,11 +195,13 @@ inline bool is_in_map(const std::map& inmap, const K& key) // To replace LLSkipMap getIfThere, use: // get_if_there(map, key, 0) // WARNING: Make sure default_value (generally 0) is not a valid map entry! -template -inline T get_if_there(const std::map& inmap, const K& key, T default_value) +// +//Singu note: This has been generalized to support a broader range of map-esque containers. +template +inline typename T::mapped_type get_if_there(const T& inmap, typename const T::key_type& key, typename T::mapped_type default_value) { // Typedef here avoids warnings because of new c++ naming rules. - typedef typename std::map::const_iterator map_iter; + typedef typename T::const_iterator map_iter; map_iter iter = inmap.find(key); if(iter == inmap.end()) { @@ -234,6 +213,21 @@ inline T get_if_there(const std::map& inmap, const K& key, T default_value) } }; +// Simple function to help with finding pointers in maps. +// For example: +// typedef map_t; +// std::map foo; +// foo[18] = "there"; +// foo[2] = "hello"; +// const char* bar = get_ptr_in_map(foo, 2); // bar -> "hello" +// const char* baz = get_ptr_in_map(foo, 3); // baz == NULL +//Singu note: This has been generalized to support a broader range of map-esque containers +template +inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename const T::key_type& key) +{ + return get_if_there(inmap,key,NULL); +}; + // Useful for replacing the removeObj() functionality of LLDynamicArray // Example: // for (std::vector::iterator iter = mList.begin(); iter != mList.end(); ) @@ -243,10 +237,12 @@ inline T get_if_there(const std::map& inmap, const K& key, T default_value) // else // ++iter; // } -template -inline Iter vector_replace_with_last(std::vector& invec, Iter iter) +// +//Singu note: This has been generalized to support a broader range of sequence containers +template +inline typename T::iterator vector_replace_with_last(T& invec, typename T::iterator& iter) { - typename std::vector::iterator last = invec.end(); --last; + typename T::iterator last = invec.end(); --last; if (iter == invec.end()) { return iter; @@ -267,13 +263,15 @@ inline Iter vector_replace_with_last(std::vector& invec, Iter iter) // Useful for replacing the removeObj() functionality of LLDynamicArray // Example: // vector_replace_with_last(mList, x); +// +//Singu note: This has been generalized to support a broader range of sequence containers template -inline bool vector_replace_with_last(std::vector& invec, const T& val) +inline bool vector_replace_with_last(T& invec, typename const T::value_type& val) { - typename std::vector::iterator iter = std::find(invec.begin(), invec.end(), val); + typename T::iterator iter = std::find(invec.begin(), invec.end(), val); if (iter != invec.end()) { - typename std::vector::iterator last = invec.end(); --last; + typename T::iterator last = invec.end(); --last; *iter = *last; invec.pop_back(); return true; diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index dc3cb6f1b..b49d59044 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -1495,7 +1495,7 @@ void LLAgentCamera::updateCamera() gAgentAvatarp->mRoot->updateWorldMatrixChildren(); - for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + /*for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); //Can be an array. iter != gAgentAvatarp->mAttachmentPoints.end(); ) { LLVOAvatar::attachment_map_t::iterator curiter = iter++; @@ -1504,7 +1504,11 @@ void LLAgentCamera::updateCamera() attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { - LLViewerObject *attached_object = (*attachment_iter); + LLViewerObject *attached_object = (*attachment_iter);*/ + std::vector >::iterator attachment_iter = gAgentAvatarp->mAttachedObjectsVector.begin(); + for(;attachment_iter!=gAgentAvatarp->mAttachedObjectsVector.end();++attachment_iter) + {{ + LLViewerObject* attached_object = attachment_iter->first; if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) { // clear any existing "early" movements of attachment diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index c795e6c57..e863b878e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1063,13 +1063,14 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id) return; } - if((object_id == cat_id) || !is_in_map(mCategoryMap, cat_id)) + cat_map_t::iterator it; + if((object_id == cat_id) || (it = mCategoryMap.find(cat_id))==mCategoryMap.end()) { llwarns << "Could not move inventory object " << object_id << " to " << cat_id << llendl; return; } - LLViewerInventoryCategory* cat = getCategory(object_id); + LLViewerInventoryCategory* cat = it->second; if(cat && (cat->getParentUUID() != cat_id)) { cat_array_t* cat_array; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index a2f40854e..0ff0697d2 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1006,6 +1006,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mCCSChatTextOverride(false) // { + mAttachedObjectsVector.reserve(MAX_AGENT_ATTACHMENTS); + static LLCachedControl const freeze_time("FreezeTime", false); mFreezeTimeLangolier = freeze_time; @@ -1115,7 +1117,7 @@ LLVOAvatar::~LLVOAvatar() lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); - mAttachmentPoints.clear(); + //mAttachmentPoints.clear(); mDead = TRUE; @@ -1645,7 +1647,7 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) mPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); //stretch bounding box by attachments - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + /*for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) { @@ -1660,7 +1662,13 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { - const LLViewerObject* attached_object = (*attachment_iter); + const LLViewerObject* attached_object = (*attachment_iter);*/ + std::vector >::iterator attachment_iter = mAttachedObjectsVector.begin(); + for(;attachment_iter!=mAttachedObjectsVector.end();++attachment_iter) + { + if(attachment_iter->second->getValid()) + { + const LLViewerObject* attached_object = attachment_iter->first; if (attached_object && !attached_object->isHUDAttachment()) { LLDrawable* drawable = attached_object->mDrawable; @@ -2494,7 +2502,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (detailed_update || !sUseImpostors) { LLFastTimer t(FTM_ATTACHMENT_UPDATE); - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + /*for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) { @@ -2504,7 +2512,12 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { - LLViewerObject* attached_object = (*attachment_iter); + LLViewerObject* attached_object = (*attachment_iter);*/ + std::vector >::iterator attachment_iter = mAttachedObjectsVector.begin(); + for(;attachment_iter!=mAttachedObjectsVector.end();++attachment_iter) + {{ + LLViewerJointAttachment* attachment = attachment_iter->second; + LLViewerObject* attached_object = attachment_iter->first; BOOL visibleAttachment = visible || (attached_object && !(attached_object->mDrawable->getSpatialBridge() && attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0)); @@ -2964,7 +2977,7 @@ void LLVOAvatar::idleCCSUpdateAttachmentText(bool render_name) if(!mCCSUpdateAttachmentTimer.checkExpirationAndReset(SECS_BETWEEN_UPDATES)) return; - for (attachment_map_t::iterator it=mAttachmentPoints.begin(); it!=mAttachmentPoints.end(); ++it) + /*for (attachment_map_t::iterator it=mAttachmentPoints.begin(); it!=mAttachmentPoints.end(); ++it) { // get attached object LLViewerJointAttachment *joint = it->second; @@ -2973,8 +2986,14 @@ void LLVOAvatar::idleCCSUpdateAttachmentText(bool render_name) for(std::vector::const_iterator parent_it = joint->mAttachedObjects.begin(); parent_it != joint->mAttachedObjects.end(); ++parent_it) { - LLViewerObject* pObject = (*parent_it); - const LLTextureEntry *te = pObject ? pObject->getTE(0) : NULL; + LLViewerObject* pObject = (*parent_it);*/ + std::vector >::iterator parent_it = mAttachedObjectsVector.begin(); + for(;parent_it!=mAttachedObjectsVector.end();++parent_it) + {{ + LLViewerObject* pObject = parent_it->first; + if(!pObject) + continue; + const LLTextureEntry *te = pObject->getTE(0); if(!te) continue; const LLColor4 &col = te->getColor(); if( (fabs(col[0] - 0.012f) < 0.001f) && @@ -6228,6 +6247,8 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o LLSelectMgr::getInstance()->updatePointAt(); } + mAttachedObjectsVector.push_back(std::make_pair(viewer_object,attachment)); + return attachment; } @@ -6382,6 +6403,13 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) { cleanupAttachedMesh( viewer_object ); attachment->removeObject(viewer_object); + std::vector >::iterator it = std::find(mAttachedObjectsVector.begin(),mAttachedObjectsVector.end(),std::make_pair(viewer_object,attachment)); + if(it != mAttachedObjectsVector.end()) + { + (*it) = mAttachedObjectsVector.back(); + mAttachedObjectsVector.pop_back(); + } + lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl; return TRUE; } @@ -8755,7 +8783,7 @@ void LLVOAvatar::idleUpdateRenderCost() std::set textures; - attachment_map_t::const_iterator iter; + /*attachment_map_t::const_iterator iter; for (iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -8765,7 +8793,11 @@ void LLVOAvatar::idleUpdateRenderCost() attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { - const LLViewerObject* object = (*attachment_iter); + const LLViewerObject* object = (*attachment_iter);*/ + std::vector >::iterator attachment_iter = mAttachedObjectsVector.begin(); + for(;attachment_iter!=mAttachedObjectsVector.end();++attachment_iter) + {{ + const LLViewerObject* object = attachment_iter->first; if (object && !object->isHUDAttachment()) { LLDrawable* drawable = object->mDrawable; @@ -8817,7 +8849,7 @@ void LLVOAvatar::idleUpdateRenderCost() } - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + /*for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) { @@ -8826,7 +8858,11 @@ void LLVOAvatar::idleUpdateRenderCost() attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { - const LLViewerObject* attached_object = (*attachment_iter); + const LLViewerObject* attached_object = (*attachment_iter);*/ + std::vector >::iterator attachment_iter = mAttachedObjectsVector.begin(); + for(;attachment_iter!=mAttachedObjectsVector.end();++attachment_iter) + {{ + const LLViewerObject* attached_object = attachment_iter->first; if (attached_object && !attached_object->isHUDAttachment()) { textures.clear(); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 8423fe723..9362f5f7c 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -745,9 +745,11 @@ protected: //-------------------------------------------------------------------- public: S32 getAttachmentCount(); // Warning: order(N) not order(1) // currently used only by -self - typedef std::map attachment_map_t; + //typedef std::map attachment_map_t; + typedef LLSortedVector attachment_map_t; attachment_map_t mAttachmentPoints; std::vector > mPendingAttachment; + std::vector > mAttachedObjectsVector; //A vector of all current attachments for fast iteration. //-------------------------------------------------------------------- // HUD functions diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9e9f785c7..cd242f0a5 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -9616,7 +9616,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) markVisible(avatar->mDrawable, *viewer_camera); LLVOAvatar::sUseImpostors = FALSE; - LLVOAvatar::attachment_map_t::iterator iter; + /*LLVOAvatar::attachment_map_t::iterator iter; for (iter = avatar->mAttachmentPoints.begin(); iter != avatar->mAttachmentPoints.end(); ++iter) @@ -9626,7 +9626,12 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { - if (LLViewerObject* attached_object = (*attachment_iter)) + if (LLViewerObject* attached_object = (*attachment_iter))*/ + std::vector >::iterator attachment_iter = avatar->mAttachedObjectsVector.begin(); + std::vector >::iterator end = avatar->mAttachedObjectsVector.end(); + for(;attachment_iter != end;++attachment_iter) + {{ + if (LLViewerObject* attached_object = attachment_iter->first) { markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); }