diff options
| -rw-r--r-- | indra/llcommon/llerror.cpp | 9 | ||||
| -rw-r--r-- | indra/llmath/llrigginginfo.cpp | 78 | ||||
| -rw-r--r-- | indra/llmath/llrigginginfo.h | 32 | ||||
| -rw-r--r-- | indra/llmath/llvolume.cpp | 12 | ||||
| -rw-r--r-- | indra/llmath/llvolume.h | 2 | ||||
| -rw-r--r-- | indra/newview/llskinningutil.cpp | 54 | ||||
| -rw-r--r-- | indra/newview/llskinningutil.h | 1 | ||||
| -rw-r--r-- | indra/newview/llviewerobject.h | 2 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.cpp | 61 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.h | 4 | ||||
| -rw-r--r-- | indra/newview/llvovolume.cpp | 52 | 
11 files changed, 245 insertions, 62 deletions
| diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index f31a054139..916555a71d 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -51,6 +51,10 @@  #include "llstl.h"  #include "lltimer.h" +//#if LL_WINDOWS +//#pragma optimize("", off) +//#endif +  namespace {  #if LL_WINDOWS  	void debugger_print(const std::string& s) @@ -361,6 +365,7 @@ namespace  			}  		} +		LL_INFOS("LogControlFile") << "logging reconfiguring from " << filename() << LL_ENDL;  		LLError::configure(configuration);  		LL_INFOS("LogControlFile") << "logging reconfigured from " << filename() << LL_ENDL;  		return true; @@ -1292,7 +1297,7 @@ namespace LLError  #if LL_WINDOWS  		// VC80 was optimizing the error away. -		#pragma optimize("", off) +//		#pragma optimize("", off)  #endif  	void crashAndLoop(const std::string& message)  	{ @@ -1310,7 +1315,7 @@ namespace LLError  		exit(EXIT_FAILURE);  	}  #if LL_WINDOWS -		#pragma optimize("", on) +//		#pragma optimize("", on)  #endif  	std::string utcTime() diff --git a/indra/llmath/llrigginginfo.cpp b/indra/llmath/llrigginginfo.cpp index 925179c2ba..73e1b096cb 100644 --- a/indra/llmath/llrigginginfo.cpp +++ b/indra/llmath/llrigginginfo.cpp @@ -27,6 +27,10 @@  #include "llmath.h"  #include "llrigginginfo.h" +//#if LL_WINDOWS +//#pragma optimize("", off) +//#endif +  //-----------------------------------------------------------------------------  // LLJointRiggingInfo  //----------------------------------------------------------------------------- @@ -80,17 +84,79 @@ void LLJointRiggingInfo::merge(const LLJointRiggingInfo& other)      }  } -void mergeRigInfoTab(joint_rig_info_tab& dst, const joint_rig_info_tab& src) +LLJointRiggingInfoTab::LLJointRiggingInfoTab(): +    mRigInfoPtr(NULL), +    mSize(0) +{ +} + +LLJointRiggingInfoTab::~LLJointRiggingInfoTab() +{ +    clear(); +} + +// This doesn't preserve data if the size changes. In practice +// this doesn't matter because the size is always either +// LL_CHARACTER_MAX_ANIMATED_JOINTS or 0. +void LLJointRiggingInfoTab::resize(S32 size) +{ +    if (size != mSize) +    { +        clear(); +        if (size > 0) +        { +            mRigInfoPtr = new LLJointRiggingInfo[size]; +            mSize = size; +        } +    } +} + +void LLJointRiggingInfoTab::clear()  { +    if (mRigInfoPtr) +    { +        delete[](mRigInfoPtr); +        mRigInfoPtr = NULL; +        mSize = 0; +    } +} + +void showDetails(const LLJointRiggingInfoTab& src, const std::string& str) +{ +	S32 count_rigged = 0; +	S32 count_box = 0; +    LLVector4a zero_vec; +    zero_vec.clear(); +    for (S32 i=0; i<src.size(); i++) +    { +        if (src[i].isRiggedTo()) +        { +            count_rigged++; +            if ((!src[i].getRiggedExtents()[0].equals3(zero_vec)) || +                (!src[i].getRiggedExtents()[1].equals3(zero_vec))) +            { +                count_box++; +            } +       } +    } +    LL_DEBUGS("RigSpammish") << "details: " << str << " has " << count_rigged << " rigged joints, of which " << count_box << " are non-empty" << LL_ENDL; +} + +void LLJointRiggingInfoTab::merge(const LLJointRiggingInfoTab& src) +{ +    //showDetails(*this, "input this");      // Size should be either LL_CHARACTER_MAX_ANIMATED_JOINTS, or 0 if      // no data. Not necessarily the same for both inputs. -    if (src.size() > dst.size()) +    if (src.size() > size())      { -        dst.resize(src.size()); +        resize(src.size());      } -    S32 size = llmin(src.size(), dst.size()); -    for (S32 i=0; i<size; i++) +    S32 min_size = llmin(size(), src.size()); +    for (S32 i=0; i<min_size; i++)      { -        dst[i].merge(src[i]); +        (*this)[i].merge(src[i]);      } +    //showDetails(src, "input src"); +    //showDetails(*this, "output this"); +  } diff --git a/indra/llmath/llrigginginfo.h b/indra/llmath/llrigginginfo.h index 7b36880a39..b09746a5b7 100644 --- a/indra/llmath/llrigginginfo.h +++ b/indra/llmath/llrigginginfo.h @@ -44,6 +44,17 @@ public:      LLVector4a *getRiggedExtents();      const LLVector4a *getRiggedExtents() const;      void merge(const LLJointRiggingInfo& other); + +	void* operator new(size_t size) +	{ +		return ll_aligned_malloc_16(size); +	} + +	void operator delete(void* ptr) +	{ +		ll_aligned_free_16(ptr); +	} +  private:  	LL_ALIGN_16(LLVector4a mRiggedExtents[2]);      bool mIsRiggedTo; @@ -51,8 +62,25 @@ private:  // For storing all the rigging info associated with a given avatar or  // object, keyed by joint_num. -typedef std::vector<LLJointRiggingInfo> joint_rig_info_tab; +// Using direct memory management instead of std::vector<> to avoid alignment issues. +class LLJointRiggingInfoTab +{ +public: +    LLJointRiggingInfoTab(); +    ~LLJointRiggingInfoTab(); +    void resize(S32 size); +    void clear(); +    S32 size() const { return mSize; } +    void merge(const LLJointRiggingInfoTab& src); +    LLJointRiggingInfo& operator[](S32 i) { return mRigInfoPtr[i]; } +    const LLJointRiggingInfo& operator[](S32 i) const { return mRigInfoPtr[i]; }; +private: +    // Not implemented +    LLJointRiggingInfoTab& operator=(const LLJointRiggingInfoTab& src); +    LLJointRiggingInfoTab(const LLJointRiggingInfoTab& src); -void mergeRigInfoTab(joint_rig_info_tab& dst, const joint_rig_info_tab& src); +    LLJointRiggingInfo *mRigInfoPtr; +    S32 mSize; +};  #endif diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 8f08394ce9..2654e204c2 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4644,7 +4644,6 @@ LLVolumeFace::LLVolumeFace() :  	mNumVertices(0),  	mNumAllocatedVertices(0),  	mNumIndices(0), -    mJointRiggingInfoTabPtr(NULL),  	mPositions(NULL),  	mNormals(NULL),  	mTangents(NULL), @@ -4676,7 +4675,6 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)  	mTangents(NULL),  	mTexCoords(NULL),  	mIndices(NULL), -    mJointRiggingInfoTabPtr(NULL),  	mWeights(NULL),      mWeightsScrubbed(FALSE),  	mOctree(NULL) @@ -4791,9 +4789,6 @@ void LLVolumeFace::freeData()  	ll_aligned_free_16(mWeights);  	mWeights = NULL; -    free(mJointRiggingInfoTabPtr); -    mJointRiggingInfoTabPtr = NULL; -      	delete mOctree;  	mOctree = NULL;  } @@ -4955,7 +4950,7 @@ void LLVolumeFace::optimize(F32 angle_cutoff)  	//  	if (new_face.mNumVertices <= mNumVertices)  	{ -	llassert(new_face.mNumIndices == mNumIndices); +        llassert(new_face.mNumIndices == mNumIndices);  		swapData(new_face);  	} @@ -6292,6 +6287,9 @@ void LLVolumeFace::resizeVertices(S32 num_verts)  	mNumVertices = num_verts;  	mNumAllocatedVertices = num_verts; + +    // Force update +    mJointRiggingInfoTab.clear();  }  void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv) @@ -6413,6 +6411,8 @@ void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v,  	}  } +// AXON appendFace/appendFaces not used - referenced by corresponding functions in +// LLModel but these are not called anywhere.  void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMatrix4& norm_mat_in)  {  	U16 offset = mNumVertices; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index d518bcf3ef..f92b43e77d 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -962,7 +962,7 @@ public:      // Which joints are rigged to, and the bounding box of any rigged      // vertices per joint. -    joint_rig_info_tab *mJointRiggingInfoTabPtr; +    LLJointRiggingInfoTab mJointRiggingInfoTab;  	LLOctreeNode<LLVolumeTriangle>* mOctree; diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index 14abe9d89a..6484775c40 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -34,6 +34,10 @@  #include "llvolume.h"  #include "llrigginginfo.h" +//#if LL_WINDOWS +//#pragma optimize("", off) +//#endif +  void LLSkinningUtil::initClass()  {  } @@ -211,15 +215,36 @@ void LLSkinningUtil::getPerVertexSkinMatrix(      llassert(valid_weights);  } +// AXON need to remember this has been done +void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar) +{ +    for (U32 j = 0; j < skin->mJointNames.size(); ++j) +    { +        LLJoint *joint = NULL; +        if (skin->mJointNums[j] == -1) +        { +            joint = avatar->getJoint(skin->mJointNames[j]); +            if (joint) +            { +                skin->mJointNums[j] = joint->getJointNum(); +            } +        } +    } +} +  void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, LLVolumeFace& vol_face)  { +    // AXON cast +    initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);      S32 num_verts = vol_face.mNumVertices;      if (num_verts>0 && vol_face.mWeights && (skin->mJointNames.size()>0))      { -        if (!vol_face.mJointRiggingInfoTabPtr) +        if (vol_face.mJointRiggingInfoTab.size()==0)          { -            vol_face.mJointRiggingInfoTabPtr = new joint_rig_info_tab(LL_CHARACTER_MAX_ANIMATED_JOINTS); -            joint_rig_info_tab& rig_info_tab = *vol_face.mJointRiggingInfoTabPtr; +            std::set<S32> active_joints; +            S32 active_verts = 0; +            vol_face.mJointRiggingInfoTab.resize(LL_CHARACTER_MAX_ANIMATED_JOINTS); +            LLJointRiggingInfoTab &rig_info_tab = vol_face.mJointRiggingInfoTab;              for (S32 i=0; i<vol_face.mNumVertices; i++)              {                  LLVector4a& pos = vol_face.mPositions[i]; @@ -228,11 +253,13 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a                  {                      S32 joint_index = llfloor(w[k]);                      S32 joint_num = skin->mJointNums[joint_index]; -                    if (joint_num != -1) +                    if (joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS)                      {                          rig_info_tab[joint_num].setIsRiggedTo(true); +                        active_joints.insert(joint_num); +                        active_verts++; -                        // AXON can precompute that matMuls. +                        // AXON can precompute these matMuls.                          LLMatrix4a bind_shape;                          bind_shape.loadu(skin->mBindShapeMatrix);                          LLMatrix4a inv_bind; @@ -246,8 +273,21 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a                      }                  }              } -            LL_DEBUGS("RigSpammish") << "updated rigging info for vf " << &vol_face  -                                     << " num_verts " << vol_face.mNumVertices << LL_ENDL;  +            LL_DEBUGS("RigSpammish") << "built rigging info for vf " << &vol_face  +                                     << " num_verts " << vol_face.mNumVertices +                                     << " active joints " << active_joints.size() +                                     << " active verts " << active_verts +                                     << LL_ENDL;           }      } +    if (vol_face.mJointRiggingInfoTab.size()!=0) +    { +        LL_DEBUGS("RigSpammish") << "we have rigging info for vf " << &vol_face  +                                 << " num_verts " << vol_face.mNumVertices << LL_ENDL;  +    } +    else +    { +        LL_DEBUGS("RigSpammish") << "no rigging info for vf " << &vol_face  +                                 << " num_verts " << vol_face.mNumVertices << LL_ENDL;  +    }  } diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h index 47e12f8adc..e730ef014b 100644 --- a/indra/newview/llskinningutil.h +++ b/indra/newview/llskinningutil.h @@ -42,6 +42,7 @@ namespace LLSkinningUtil      void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);      void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);      void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); +    void initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar);      void updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, LLVolumeFace& vol_face);  }; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index eac3f1bbe8..d6c8b76147 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -881,7 +881,7 @@ public:      virtual void updateRiggingInfo() {} -    joint_rig_info_tab mJointRiggingInfoTab; +    LLJointRiggingInfoTab mJointRiggingInfoTab;  private:  	LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory. diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 93e470e0fb..8c3a180570 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -671,7 +671,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mCachedInMuteList(false),      mIsControlAvatar(false),      mIsUIAvatar(false), -    mEnableDefaultMotions(true) +    mEnableDefaultMotions(true), +    mRiggingInfoNeedsUpdate(true)  {  	LL_DEBUGS("AvatarRender") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; @@ -1279,8 +1280,12 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)  	}  } +static LLTrace::BlockTimerStatHandle FTM_AVATAR_EXTENT_UPDATE("Avatar Update Extent"); +  void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)  { +    LL_RECORD_BLOCK_TIME(FTM_AVATAR_EXTENT_UPDATE); +      S32 box_detail = gSavedSettings.getS32("AvatarBoundingBoxComplexity");  	LLVector4a buffer(0.0);  	LLVector4a pos; @@ -1364,7 +1369,13 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)      // Stretch bounding box by rigged mesh joint boxes      if (box_detail>=3)      { -        updateRiggingInfo(); +        // AXON try to cache unless something has changed about attached rigged meshes. +        // Needs more logic based on volume states. +        //if (mRiggingInfoNeedsUpdate) +        { +            updateRiggingInfo(); +            mRiggingInfoNeedsUpdate = false; +        }          for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++)          {              LLJoint *joint = getJoint(joint_num); @@ -5854,8 +5865,6 @@ void LLVOAvatar::clearAttachmentOverrides()  {      LLScopedContextString str("clearAttachmentOverrides " + getFullname()); -    mActiveOverrideMeshes.clear(); -          for (S32 i=0; i<LL_CHARACTER_MAX_ANIMATED_JOINTS; i++)      {          LLJoint *pJoint = getJoint(i); @@ -5876,6 +5885,9 @@ void LLVOAvatar::clearAttachmentOverrides()          }          postPelvisSetRecalc();	      } + +    mActiveOverrideMeshes.clear(); +    onActiveOverrideMeshesChanged();  }  //----------------------------------------------------------------------------- @@ -6130,8 +6142,6 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::set<LL  			bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false;								  			if ( fullRig && !mesh_overrides_loaded )  			{								 -                mActiveOverrideMeshes.insert(mesh_id); -                  				for ( int i=0; i<jointCnt; ++i )  				{  					std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); @@ -6174,6 +6184,8 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::set<LL                      }  				} +                mActiveOverrideMeshes.insert(mesh_id); +                onActiveOverrideMeshesChanged();  			}							  		}  	} @@ -6335,8 +6347,6 @@ void LLVOAvatar::removeAttachmentOverridesForObject(LLViewerObject *vo)  //-----------------------------------------------------------------------------  void LLVOAvatar::removeAttachmentOverridesForObject(const LLUUID& mesh_id)  {	 -    mActiveOverrideMeshes.erase(mesh_id); -  	LLJoint* pJointPelvis = getJoint("mPelvis");      const std::string av_string = avString();      for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++) @@ -6357,6 +6367,9 @@ void LLVOAvatar::removeAttachmentOverridesForObject(const LLUUID& mesh_id)  	}	  	postPelvisSetRecalc();	 + +    mActiveOverrideMeshes.erase(mesh_id); +    onActiveOverrideMeshesChanged();  }  //-----------------------------------------------------------------------------  // getCharacterPosition() @@ -9444,20 +9457,7 @@ void LLVOAvatar::updateLODRiggedAttachments()  	rebuildRiggedAttachments();  } -S32 countRigInfoTab(joint_rig_info_tab& tab) -{ -    S32 count=0; -    for (S32 i=0; i<tab.size(); i++) -    { -        if (tab[i].isRiggedTo()) -        { -            count++; -        } -    } -    return count; -} - -void showRigInfoTabExtents(LLVOAvatar *avatar, joint_rig_info_tab& tab, S32& count_rigged, S32& count_box) +void showRigInfoTabExtents(LLVOAvatar *avatar, LLJointRiggingInfoTab& tab, S32& count_rigged, S32& count_box)  {      count_rigged = count_box = 0;      LLVector4a zero_vec; @@ -9494,7 +9494,7 @@ void LLVOAvatar::updateRiggingInfo()  		{  			LLViewerObject* attached_object =  *attach_iter;              attached_object->updateRiggingInfo(); -            mergeRigInfoTab(mJointRiggingInfoTab, attached_object->mJointRiggingInfoTab); +            mJointRiggingInfoTab.merge(attached_object->mJointRiggingInfoTab);              //LL_INFOS() << "after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL; @@ -9504,7 +9504,7 @@ void LLVOAvatar::updateRiggingInfo()              {                  LLViewerObject *childp = *it;                  childp->updateRiggingInfo(); -                mergeRigInfoTab(mJointRiggingInfoTab, childp->mJointRiggingInfoTab); +                mJointRiggingInfoTab.merge(childp->mJointRiggingInfoTab);                  //LL_INFOS() << "after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;              }          } @@ -9515,9 +9515,8 @@ void LLVOAvatar::updateRiggingInfo()          LLVOVolume *volp = control_av->mRootVolp;          if (volp && !volp->isAttachment())          { -            volp->updateRiggingInfo(); -            mergeRigInfoTab(mJointRiggingInfoTab, volp->mJointRiggingInfoTab); -            LL_DEBUGS("RigSpammish") << getFullname() << " after cav update rig tab:" << LL_ENDL; +            mJointRiggingInfoTab.merge(volp->mJointRiggingInfoTab); +            LL_DEBUGS("RigSpammish") << getFullname() << " mRootVolp " << control_av->mRootVolp << " after cav update rig tab:" << LL_ENDL;              S32 joint_count, box_count;              showRigInfoTabExtents(this, mJointRiggingInfoTab, joint_count, box_count);              LL_DEBUGS("RigSpammish") << "uses " << joint_count << " joints " << " nonzero boxes: " << box_count << LL_ENDL; @@ -9529,7 +9528,7 @@ void LLVOAvatar::updateRiggingInfo()              {                  LLViewerObject *childp = *it;                  childp->updateRiggingInfo(); -                mergeRigInfoTab(mJointRiggingInfoTab, childp->mJointRiggingInfoTab); +                mJointRiggingInfoTab.merge(childp->mJointRiggingInfoTab);                  LL_DEBUGS("RigSpammish") << getFullname() << " after cav child update rig tab:" << LL_ENDL;                  S32 joint_count, box_count; @@ -9547,6 +9546,12 @@ void LLVOAvatar::updateRiggingInfo()      LL_DEBUGS("RigSpammish") << "uses " << joint_count << " joints " << " nonzero boxes: " << box_count << LL_ENDL;  } +// virtual +void LLVOAvatar::onActiveOverrideMeshesChanged() +{ +    mRiggingInfoNeedsUpdate = true; +} +  U32 LLVOAvatar::getPartitionType() const  {   	// Avatars merely exist as drawables in the bridge partition diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 59f88490d0..924b361f59 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -219,10 +219,10 @@ public:      // virtual      void 					updateRiggingInfo(); +    bool					mRiggingInfoNeedsUpdate;      std::set<LLUUID>		mActiveOverrideMeshes; - -     +    virtual void			onActiveOverrideMeshesChanged();  	/*virtual*/ const LLUUID&	getID() const;  	/*virtual*/ void			addDebugText(const std::string& text); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 2f2a28daff..70c4efb5b8 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3597,26 +3597,64 @@ void LLVOVolume::updateRiggingInfo()      {          const LLMeshSkinInfo* skin = getSkinInfo();          LLVOAvatar *avatar = getAvatar(); -        if (skin && avatar && getLOD()>mLastRiggingInfoLOD) +        LLVolume *volume = getVolume(); +        if (skin && avatar && volume)          { -            LLVolume *volume = getVolume(); -            if (volume) +            LL_DEBUGS("RigSpammish") << "starting, vovol " << this << " lod " << getLOD() << " last " << mLastRiggingInfoLOD << LL_ENDL; +            // AXON SPAM +            for (S32 f = 0; f < volume->getNumVolumeFaces(); ++f)              { +                LLVolumeFace& vol_face = volume->getVolumeFace(f); +                if (vol_face.mJointRiggingInfoTab.size()>0) +                { +                    LL_DEBUGS("RigSpammish") << "vovol " << this << " lod " << getLOD() << " face " << f << " vf " << &vol_face << " has rig info" << LL_ENDL; +                } +                else +                { +                    LL_DEBUGS("RigSpammish") << "vovol " << this << " lod " << getLOD() << " face " << f << " vf " << &vol_face << " needs update" << LL_ENDL; +                } +            } +            // We maintain rigging info based on the highest LOD +            // handled so far. Need to update if either the LOD is +            // the same but some faces need to be updated, or if +            // the LOD has increased. +            bool any_face_needs_rebuild = false; +            if (getLOD()==mLastRiggingInfoLOD) +            { +                // See if any volume face needs its rigging info built. +                for (S32 f = 0; f < volume->getNumVolumeFaces(); ++f) +                { +                    LLVolumeFace& vol_face = volume->getVolumeFace(f); +                    if (vol_face.mJointRiggingInfoTab.size()==0) +                    { +                        // AXON this is overkill since some faces don't contain any valid weights/rigged verts. +                        any_face_needs_rebuild = true; +                        break; +                    } +                } +            } + +            //if (getLOD()>mLastRiggingInfoLOD || +            //    (getLOD()==mLastRiggingInfoLOD && any_face_needs_rebuild)) +            if (getLOD()==3) +            { +                // Rigging info has changed                  mJointRiggingInfoTab.clear();                  for (S32 f = 0; f < volume->getNumVolumeFaces(); ++f)                  {                      LLVolumeFace& vol_face = volume->getVolumeFace(f);                      LLSkinningUtil::updateRiggingInfo(skin, avatar, vol_face); -                    if (vol_face.mJointRiggingInfoTabPtr) +                    if (vol_face.mJointRiggingInfoTab.size()>0)                      { -                        mergeRigInfoTab(mJointRiggingInfoTab, *vol_face.mJointRiggingInfoTabPtr); +                        mJointRiggingInfoTab.merge(vol_face.mJointRiggingInfoTab);                      }                  }                  // Keep the highest LOD info available. -                // AXON would this ever need to be forced to refresh? Set to -1 if so.                  mLastRiggingInfoLOD = getLOD();                  LL_DEBUGS("RigSpammish") << "updated rigging info for LLVOVolume "  -                                         << this << " lod " << mLastRiggingInfoLOD << LL_ENDL; +                                         << this << " lod " << mLastRiggingInfoLOD  +                                         << " any faces rebuilt? " << any_face_needs_rebuild +                                         << LL_ENDL;              }          }      } | 
