diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index f31a054139ee23cf9268dab395055b3b7cf981ef..916555a71d840c0a79e15577e3d5af846dc24073 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 925179c2baadf0e0223ea66cbf8b5b4b416d4c0f..73e1b096cbf4f50d1347828af225c783e5daf3ad 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 7b36880a391c90012b0b96d8c8220b8d380a2743..b09746a5b75349d0eb87148d74ab87699e1d3e0d 100644
--- a/indra/llmath/llrigginginfo.h
+++ b/indra/llmath/llrigginginfo.h
@@ -44,6 +44,17 @@ class LLJointRiggingInfo
     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 @@ class LLJointRiggingInfo
 
 // 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 8f08394ce939226537b04c017eb50b1bcaf5b782..2654e204c254abd307070b1e0fc88a423e570faa 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 d518bcf3efe830058f340cf7016c1946e00156c1..f92b43e77dddb64656426e3f0d396860cd486f78 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -962,7 +962,7 @@ class LLVolumeFace
 
     // 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 14abe9d89acf507fc85c19b917cf38792e0c4e59..6484775c40ce227fa152aeb10a62c175c70a3999 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 47e12f8adc35e88390797643b28f4afc6aa6c427..e730ef014bd6874dab979fa9456fd8a07a0ed545 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 eac3f1bbe83a440ce0a1489345a004f22bf85b4f..d6c8b761479d7bd8101be4a1bd6aa6d1b9f94ade 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -881,7 +881,7 @@ class LLViewerObject
 
     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 93e470e0fbb49a4e8f3be4dbd4a3ca016cf8e3a8..8c3a1805707acc52bc41d82a9976fa2a6c0759df 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 59f88490d0a277f5d3c2ced8c218047d98de752e..924b361f59920d0106d1c3e716a7ab326b100032 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -219,10 +219,10 @@ class LLVOAvatar :
 
     // 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 2f2a28daff703a221e104f36e944578f9b92b9c1..70c4efb5b8d8228e0f3656163cb4d1194164807c 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;
             }
         }
     }