diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 18f45d3b202aa8ceae1ae6bd1e5c938a994d6a4b..2a55838a4bd5d1d71745115ca1ccb2e63415c195 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -1392,7 +1392,8 @@ bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
 LLMeshSkinInfo::LLMeshSkinInfo():
     mPelvisOffset(0.0),
     mLockScaleIfJointPosition(false),
-    mInvalidJointsScrubbed(false)
+    mInvalidJointsScrubbed(false),
+    mJointNumsInitialized(false)
 {
 }
 
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 53585d2e0418567f578ad529eb03c9663bbd2321..d7f006753fa52848d0d4453b909013b62ba674f5 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -56,6 +56,7 @@ class LLMeshSkinInfo
 	float mPelvisOffset;
     bool mLockScaleIfJointPosition;
     bool mInvalidJointsScrubbed;
+    bool mJointNumsInitialized;
 };
 
 class LLModel : public LLVolume
diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp
index 6484775c40ce227fa152aeb10a62c175c70a3999..49d05262453701f33d596ed571f2b0be7e16941c 100644
--- a/indra/newview/llskinningutil.cpp
+++ b/indra/newview/llskinningutil.cpp
@@ -79,21 +79,10 @@ void LLSkinningUtil::initSkinningMatrixPalette(
     const LLMeshSkinInfo* skin,
     LLVOAvatar *avatar)
 {
+    initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);
     for (U32 j = 0; j < count; ++j)
     {
-        LLJoint *joint = NULL;
-        if (skin->mJointNums[j] == -1)
-        {
-            joint = avatar->getJoint(skin->mJointNames[j]);
-            if (joint)
-            {
-                skin->mJointNums[j] = joint->getJointNum();
-            }
-        }
-		else
-		{
-			joint = avatar->getJoint(skin->mJointNums[j]);
-		}
+        LLJoint *joint = avatar->getJoint(skin->mJointNums[j]);
         if (joint)
         {
 #define MAT_USE_SSE
@@ -218,76 +207,84 @@ void LLSkinningUtil::getPerVertexSkinMatrix(
 // AXON need to remember this has been done
 void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar)
 {
-    for (U32 j = 0; j < skin->mJointNames.size(); ++j)
+    if (!skin->mJointNumsInitialized)
     {
-        LLJoint *joint = NULL;
-        if (skin->mJointNums[j] == -1)
+        for (U32 j = 0; j < skin->mJointNames.size(); ++j)
         {
-            joint = avatar->getJoint(skin->mJointNames[j]);
-            if (joint)
+            LLJoint *joint = NULL;
+            if (skin->mJointNums[j] == -1)
             {
-                skin->mJointNums[j] = joint->getJointNum();
+                joint = avatar->getJoint(skin->mJointNames[j]);
+                if (joint)
+                {
+                    skin->mJointNums[j] = joint->getJointNum();
+                }
             }
         }
+        skin->mJointNumsInitialized = true;
     }
 }
 
 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.mJointRiggingInfoTab.needsUpdate())
     {
-        if (vol_face.mJointRiggingInfoTab.size()==0)
+        S32 num_verts = vol_face.mNumVertices;
+        if (num_verts>0 && vol_face.mWeights && (skin->mJointNames.size()>0))
         {
-            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++)
+            initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);
+            if (vol_face.mJointRiggingInfoTab.size()==0)
             {
-                LLVector4a& pos = vol_face.mPositions[i];
-                F32 *w = vol_face.mWeights[i].getF32ptr();
-                for (U32 k=0; k<4; ++k)
+                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++)
                 {
-                    S32 joint_index = llfloor(w[k]);
-                    S32 joint_num = skin->mJointNums[joint_index];
-                    if (joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS)
+                    LLVector4a& pos = vol_face.mPositions[i];
+                    F32 *w = vol_face.mWeights[i].getF32ptr();
+                    for (U32 k=0; k<4; ++k)
                     {
-                        rig_info_tab[joint_num].setIsRiggedTo(true);
-                        active_joints.insert(joint_num);
-                        active_verts++;
+                        S32 joint_index = llfloor(w[k]);
+                        S32 joint_num = skin->mJointNums[joint_index];
+                        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 these matMuls.
-                        LLMatrix4a bind_shape;
-                        bind_shape.loadu(skin->mBindShapeMatrix);
-                        LLMatrix4a inv_bind;
-                        inv_bind.loadu(skin->mInvBindMatrix[joint_index]);
-                        LLMatrix4a mat;
-                        matMul(bind_shape, inv_bind, mat);
-                        LLVector4a pos_joint_space;
-                        mat.affineTransform(pos, pos_joint_space);
-                        LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents();
-                        update_min_max(extents[0], extents[1], pos_joint_space);
+                            // AXON can precompute these matMuls.
+                            LLMatrix4a bind_shape;
+                            bind_shape.loadu(skin->mBindShapeMatrix);
+                            LLMatrix4a inv_bind;
+                            inv_bind.loadu(skin->mInvBindMatrix[joint_index]);
+                            LLMatrix4a mat;
+                            matMul(bind_shape, inv_bind, mat);
+                            LLVector4a pos_joint_space;
+                            mat.affineTransform(pos, pos_joint_space);
+                            LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents();
+                            update_min_max(extents[0], extents[1], pos_joint_space);
+                        }
                     }
                 }
+                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; 
+                vol_face.mJointRiggingInfoTab.setNeedsUpdate(false);
             }
-            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; 
+        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/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 8c3a1805707acc52bc41d82a9976fa2a6c0759df..8a457e1e5354b583b388157f04e97999fffaac2e 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -671,8 +671,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mCachedInMuteList(false),
     mIsControlAvatar(false),
     mIsUIAvatar(false),
-    mEnableDefaultMotions(true),
-    mRiggingInfoNeedsUpdate(true)
+    mEnableDefaultMotions(true)
 {
 	LL_DEBUGS("AvatarRender") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL;
 
@@ -1371,10 +1370,10 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
     {
         // AXON try to cache unless something has changed about attached rigged meshes.
         // Needs more logic based on volume states.
-        //if (mRiggingInfoNeedsUpdate)
+        //if (mRiggingInfoTab.needsUpdate())
         {
             updateRiggingInfo();
-            mRiggingInfoNeedsUpdate = false;
+            mJointRiggingInfoTab.setNeedsUpdate(false);
         }
         for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++)
         {
@@ -9479,12 +9478,10 @@ void showRigInfoTabExtents(LLVOAvatar *avatar, LLJointRiggingInfoTab& tab, S32&
     }
 }
 
-// virtual
-void LLVOAvatar::updateRiggingInfo()
+// AXON move to member
+void getAssociatedVolumes(LLVOAvatar *av, std::vector<LLVOVolume*>& volumes)
 {
-    mJointRiggingInfoTab.clear();
-    //LL_INFOS() << "starting update rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
-	for ( attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter )
+	for ( LLVOAvatar::attachment_map_t::iterator iter = av->mAttachmentPoints.begin(); iter != av->mAttachmentPoints.end(); ++iter )
 	{
 		LLViewerJointAttachment* attachment = iter->second;
 		LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_end = attachment->mAttachedObjects.end();
@@ -9493,51 +9490,59 @@ void LLVOAvatar::updateRiggingInfo()
 			 attach_iter != attach_end; ++attach_iter)
 		{
 			LLViewerObject* attached_object =  *attach_iter;
-            attached_object->updateRiggingInfo();
-            mJointRiggingInfoTab.merge(attached_object->mJointRiggingInfoTab);
-            //LL_INFOS() << "after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
-            
-
+            LLVOVolume *volume = dynamic_cast<LLVOVolume*>(attached_object);
+            if (volume)
+            {
+                volumes.push_back(volume);
+            }
             LLViewerObject::const_child_list_t& children = attached_object->getChildren();
             for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
                  it != children.end(); ++it)
             {
                 LLViewerObject *childp = *it;
-                childp->updateRiggingInfo();
-                mJointRiggingInfoTab.merge(childp->mJointRiggingInfoTab);
-                //LL_INFOS() << "after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
+                LLVOVolume *volume = dynamic_cast<LLVOVolume*>(childp);
+                if (volume)
+                {
+                    volumes.push_back(volume);
+                }
             }
         }
 	}
-    LLControlAvatar *control_av = dynamic_cast<LLControlAvatar*>(this);
+    LLControlAvatar *control_av = dynamic_cast<LLControlAvatar*>(av);
     if (control_av)
     {
         LLVOVolume *volp = control_av->mRootVolp;
         if (volp && !volp->isAttachment())
         {
-            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;
-            //LL_INFOS() << "cav after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
-
+            volumes.push_back(volp);
             LLViewerObject::const_child_list_t& children = volp->getChildren();
             for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
                  it != children.end(); ++it)
             {
                 LLViewerObject *childp = *it;
-                childp->updateRiggingInfo();
-                mJointRiggingInfoTab.merge(childp->mJointRiggingInfoTab);
-
-                LL_DEBUGS("RigSpammish") << getFullname() << " after cav child 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;
-                //LL_INFOS() << "cav after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
+                LLVOVolume *volume = dynamic_cast<LLVOVolume*>(childp);
+                if (volume)
+                {
+                    volumes.push_back(volume);
+                }
             }
         }
     }
+}
+
+// virtual
+void LLVOAvatar::updateRiggingInfo()
+{
+    LL_DEBUGS("RigSpammish") << getFullname() << " updating rig tab" << LL_ENDL;
+    mJointRiggingInfoTab.clear();
+    std::vector<LLVOVolume*> volumes;
+    getAssociatedVolumes(this, volumes);
+    for (std::vector<LLVOVolume*>::iterator it = volumes.begin(); it != volumes.end(); ++it)
+    {
+        LLVOVolume *vol = *it;
+        vol->updateRiggingInfo();
+        mJointRiggingInfoTab.merge(vol->mJointRiggingInfoTab);
+    }
 
     //LL_INFOS() << "done update rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
     LL_DEBUGS("RigSpammish") << getFullname() << " after update rig tab:" << LL_ENDL;
@@ -9549,7 +9554,7 @@ void LLVOAvatar::updateRiggingInfo()
 // virtual
 void LLVOAvatar::onActiveOverrideMeshesChanged()
 {
-    mRiggingInfoNeedsUpdate = true;
+    mJointRiggingInfoTab.setNeedsUpdate(true);
 }
 
 U32 LLVOAvatar::getPartitionType() const
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 924b361f59920d0106d1c3e716a7ab326b100032..09712e6d84d1a9dbc5ea5d163f514cf4f356a85c 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -219,7 +219,6 @@ class LLVOAvatar :
 
     // virtual
     void 					updateRiggingInfo();
-    bool					mRiggingInfoNeedsUpdate;
 
     std::set<LLUUID>		mActiveOverrideMeshes;
     virtual void			onActiveOverrideMeshesChanged();