diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 0f567ba5ac483d65967a79f442c575bc9c590f6c..9de8c81c2b80762168a8397500c84506857561c9 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -5124,9 +5124,12 @@ void process_object_animation(LLMessageSystem *mesgsys, void **user_data)
     if (num_blocks > 0 && !avatarp->mPlaying)
     {
         avatarp->mPlaying = true;
-		avatarp->updateVolumeGeom();
-        // AXON FIXME need to update all objects in the linkset, not just the one where animation is playing
-        avatarp->mRootVolp->recursiveMarkForUpdate(TRUE);
+        // AXON need to update all objects in the linkset, not just the one where animation is playing
+        if (!avatarp->mRootVolp->isAnySelected())
+        {
+            avatarp->updateVolumeGeom();
+            avatarp->mRootVolp->recursiveMarkForUpdate(TRUE);
+        }
     }
     else if (num_blocks == 0 && avatarp->mPlaying)
     {
@@ -5134,9 +5137,12 @@ void process_object_animation(LLMessageSystem *mesgsys, void **user_data)
         // animations are signalled. Probably don't want to leave this
         // way but helpful for testing.
         avatarp->mPlaying = false;
-		avatarp->updateVolumeGeom();
-        // AXON FIXME need to update all objects in the linkset, not just the one where animation is playing
-        avatarp->mRootVolp->recursiveMarkForUpdate(TRUE);
+        // AXON need to update all objects in the linkset, not just the one where animation is playing
+        if (!avatarp->mRootVolp->isAnySelected())
+        {
+            avatarp->updateVolumeGeom();
+            avatarp->mRootVolp->recursiveMarkForUpdate(TRUE);
+        }
     }
 #endif
 
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index b17d83486fe81b4649da61b612dbc1ef704b5744..404a77157111731ae93a830f3d2d84ae91feb776 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -688,6 +688,18 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list)
 	}
 }
 
+BOOL LLViewerObject::isAnySelected() const
+{
+    bool any_selected = isSelected();
+    for (child_list_t::const_iterator iter = mChildList.begin();
+         iter != mChildList.end(); iter++)
+    {
+        const LLViewerObject* child = *iter;
+        any_selected = any_selected || child->isSelected();
+    }
+    return any_selected;
+}
+
 void LLViewerObject::setSelected(BOOL sel)
 {
 	mUserSelected = sel;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index a3a9a075bab3f5e331003008ed0d5312e81e45d7..0bfc513dc9084bce9b10727f4cca0e9339ebf96c 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -221,6 +221,8 @@ class LLViewerObject
 	LLViewerRegion* getRegion() const				{ return mRegionp; }
 
 	BOOL isSelected() const							{ return mUserSelected; }
+    // Check whole linkset
+    BOOL isAnySelected() const;
 	virtual void setSelected(BOOL sel);
 
 	const LLUUID &getID() const						{ return mID; }
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 0fc95de6183935a1f1473d4e7352bf67fd2ffa9e..abef31257260398c400690661407e9fc92d807f1 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1349,6 +1349,15 @@ BOOL LLVOVolume::updateLOD()
 
 	if (lod_changed)
 	{
+#if 1
+        // AXON debugging
+        if (isAnimatedObject() && isRiggedMesh())
+        {
+            std::string vobj_name = llformat("Vol%u", (U32) this);
+            F32 est_tris = getEstTrianglesMax();
+            LL_DEBUGS("AXONLinkset") << vobj_name << " updateLOD to " << getLOD() << ", tris " << est_tris << LL_ENDL; 
+        }
+#endif
 		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
 		mLODChanged = TRUE;
 	}
@@ -3350,14 +3359,15 @@ U32 LLVOVolume::getExtendedMeshFlags() const
 
 void LLVOVolume::onSetExtendedMeshFlags(U32 flags)
 {
-    // AXON - the check against mUserSelected is "empirically
+    // AXON - the check against isAnySelected() is "empirically
     // derived": doing rebuildGeom() while in selection trashes the
     // graphics state of animated objects. Skipping this update is OK
     // because we get another one on deselect.
-    if (mDrawable.notNull() && !mUserSelected)
+
+	if (!getRootEdit()->isAnySelected() && mDrawable.notNull())
     {
         // Need to trigger rebuildGeom(), which is where control avatars get created/removed
-        markForUpdate(TRUE);
+        getRootEdit()->recursiveMarkForUpdate(TRUE);
     }
     if (isAttachment() && getAvatarAncestor())
     {
@@ -4130,6 +4140,21 @@ const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const
 	return xform->getWorldMatrix();
 }
 
+void LLVOVolume::markForUpdate(BOOL priority)
+{ 
+#if 1
+	// AXON debugging
+    if (isAnimatedObject() && isRiggedMesh())
+    {
+        std::string vobj_name = llformat("Vol%u", (U32) this);
+        F32 est_tris = getEstTrianglesMax();
+        LL_DEBUGS("AXONLinkset") << vobj_name << " markForUpdate, tris " << est_tris << LL_ENDL; 
+    }
+#endif
+    LLViewerObject::markForUpdate(priority); 
+    mVolumeChanged = TRUE; 
+}
+
 LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const
 {
 	LLVector3 ret = pos - getRenderPosition();
@@ -5082,15 +5107,19 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 			}
 
             bool is_mesh = vobj->isMesh();
-            
-            LL_DEBUGS("AXON") << vobj_name << " rebuilding, isAttachment: " << (U32) vobj->isAttachment()
+            F32 est_tris = vobj->getEstTrianglesMax();
+
+#if 1
+            LL_DEBUGS("AXONLinkset") << vobj_name << " rebuilding, isAttachment: " << (U32) vobj->isAttachment()
                               << " is_mesh " << is_mesh
+                              << " est_tris " << est_tris
                               << " is_animated " << vobj->isAnimatedObject()
                               << " can_animate " << vobj->canBeAnimatedObject() 
                               << " cav " << vobj->getControlAvatar() 
                               << " playing " << (U32) (vobj->getControlAvatar() ? vobj->getControlAvatar()->mPlaying : false)
                               << " frame " << LLFrameTimer::getFrameCount()
                               << LL_ENDL;
+#endif
 
 			llassert_always(vobj);
 			vobj->updateTextureVirtualSize(true);
@@ -5633,6 +5662,15 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 			if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )
 			{
 				LLVOVolume* vobj = drawablep->getVOVolume();
+#if 1 
+                // AXON debugging
+                if (vobj->isAnimatedObject() && vobj->isRiggedMesh())
+                {
+                    std::string vobj_name = llformat("Vol%u", (U32) vobj);
+                    F32 est_tris = vobj->getEstTrianglesMax();
+                    LL_DEBUGS("AXONLinkset") << vobj_name << " rebuildMesh, tris " << est_tris << LL_ENDL; 
+        }
+#endif
 				vobj->preRebuild();
 
 				if (drawablep->isState(LLDrawable::ANIMATED_CHILD))
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 0a11074a667f7064c33758b2b7757c6f787be2bb..f12eb168f6cc69702b39f7a907f60cb30d4459e2 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -162,7 +162,7 @@ class LLVOVolume : public LLViewerObject
 	/*virtual*/ F32  	getRadius() const						{ return mVObjRadius; };
 				const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
 
-				void	markForUpdate(BOOL priority)			{ LLViewerObject::markForUpdate(priority); mVolumeChanged = TRUE; }
+				void	markForUpdate(BOOL priority);
 				void    faceMappingChanged()                    { mFaceMappingChanged=TRUE; };
 
 	/*virtual*/ void	onShift(const LLVector4a &shift_vector); // Called when the drawable shifts
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 19487c3230ef638163f2d2e88644c6b9fd2086f3..436c0cbf432cf814d39f07ec0d3ac8b9fdb2efb5 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -3350,6 +3350,19 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f
 {
 	if (drawablep && !drawablep->isDead() && assertInitialized())
 	{
+#if 1
+        // AXON debugging
+        
+        LLVOVolume *vol_obj = drawablep->getVOVolume();
+        if (vol_obj && vol_obj->isAnimatedObject() && vol_obj->isRiggedMesh())
+        {
+            std::string vobj_name = llformat("Vol%u", (U32) vol_obj);
+            F32 est_tris = vol_obj->getEstTrianglesMax();
+            LL_DEBUGS("AXONLinkset") << vobj_name << " markRebuild, tris " << est_tris 
+                                     << " priority " << (S32) priority << " flag " << std::hex << flag << LL_ENDL; 
+        }
+#endif
+    
 		if (!drawablep->isState(LLDrawable::BUILT))
 		{
 			priority = TRUE;