diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index d458e2951b3c1fddf34c652b9f08ded1f4631433..172816b3e38340f3da6bd0b8de877551f1630bdd 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -50,6 +50,8 @@ LLControlAvatar::~LLControlAvatar()
 
 void LLControlAvatar::matchVolumeTransform()
 {
+#if 0
+    // AXON - should we be using bind_shape?
     {
         LLVolume *volume = mRootVolp->getVolume();
         if (volume)
@@ -63,16 +65,40 @@ void LLControlAvatar::matchVolumeTransform()
             }
         }
     }
-    
-	setPositionAgent(mRootVolp->getRenderPosition());
-	//slamPosition();
-
-    LLQuaternion fix_axes_rot(-F_PI_BY_TWO, LLVector3(0,0,1));
-    LLQuaternion obj_rot = mRootVolp->getRotation();
-    LLQuaternion result_rot = fix_axes_rot * obj_rot;
-	setRotation(result_rot);
-    mRoot->setWorldRotation(result_rot);
-    mRoot->setPosition(mRootVolp->getRenderPosition());
+#endif
+
+
+    if (mRootVolp)
+    {
+        if (mRootVolp->isAttachment())
+        {
+            LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor();
+            if (attached_av)
+            {
+                LLViewerJointAttachment *attach = attached_av->getTargetAttachmentPoint(mRootVolp);
+                setPositionAgent(mRootVolp->getRenderPosition());
+                LLVector3 pos = attach->getParent()->getWorldPosition();
+                mRoot->setWorldPosition(pos);
+                mRoot->setRotation(attach->getParent()->getWorldRotation());
+            }
+            else
+            {
+                LL_WARNS_ONCE() << "can't find attached av!" << LL_ENDL;
+            }
+        }
+        else
+        {
+            setPositionAgent(mRootVolp->getRenderPosition());
+            //slamPosition();
+        
+            LLQuaternion fix_axes_rot(-F_PI_BY_TWO, LLVector3(0,0,1));
+            LLQuaternion obj_rot = mRootVolp->getRotation();
+            LLQuaternion result_rot = fix_axes_rot * obj_rot;
+            setRotation(result_rot);
+            mRoot->setWorldRotation(result_rot);
+            mRoot->setPosition(mRootVolp->getRenderPosition());
+        }
+    }
 }
 
 void LLControlAvatar::setGlobalScale(F32 scale)
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 8001486b5338c5f947b3252af35b494a3475365a..6799c3f86204705cc44def536050e8fdbfdd1bc4 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -698,11 +698,6 @@ F32 LLDrawable::updateXform(BOOL undamped)
 	mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!)
 	mXform.updateMatrix();
 
-    if (mVObjp && mVObjp->isRootEdit() && mVObjp->getControlAvatar())
-    {
-        mVObjp->getControlAvatar()->matchVolumeTransform();
-    }
-    
 	if (mSpatialBridge)
 	{
 		gPipeline.markMoved(mSpatialBridge, FALSE);
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index e2fbac023a6bd57bb86b9b8edcbcb40f53e63c37..34e7bc0fad2250085394142761e6e2acbba4ef11 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -5188,10 +5188,15 @@ LLVOAvatar* LLViewerObject::asAvatar()
 	return NULL;
 }
 
-// If this object is directly or indirectly parented by an avatar, return it.
+// If this object is directly or indirectly parented by an avatar,
+// return it.  Normally getAvatar() is the correct function to call;
+// it will give the avatar used for skinning.  The exception is with
+// animated objects that are also attachments; in that case,
+// getAvatar() will return the control avatar, used for skinning, and
+// getAvatarAncestor will return the avatar to which the object is
+// attached.
 LLVOAvatar* LLViewerObject::getAvatarAncestor()
 {
-    LL_ERRS("AXON") << "this method has been targetted for termination. Use getAvatar()." << LL_ENDL;
 	LLViewerObject *pobj = (LLViewerObject*) getParent();
 	while (pobj)
 	{
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 1f99119d8271e65d394d4bcf7745bf4dc4a5ee66..63e6560d981066f81cb6334d5eca85399f4a7139 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -862,8 +862,8 @@ void LLViewerObjectList::update(LLAgent &agent)
 			{
 				if (idle_count >= idle_list.size())
 				{
-				idle_list.push_back( objectp );
-			}
+                    idle_list.push_back( objectp );
+                }
 			else
 				{
 					idle_list[idle_count] = objectp;
@@ -900,7 +900,7 @@ void LLViewerObjectList::update(LLAgent &agent)
 		{
 			objectp = *idle_iter;
 			llassert(objectp->isActive());
-			objectp->idleUpdate(agent, frame_time);
+                objectp->idleUpdate(agent, frame_time);
 		}
 
 		//update flexible objects
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index eab5206828efb900adee2df972be107aa8164806..34ca69d6e083cadea386e49953f670a4431719e9 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -110,6 +110,8 @@
 #include "llcallstack.h"
 #include "llrendersphere.h"
 
+#include <boost/lexical_cast.hpp>
+
 extern F32 SPEED_ADJUST_MAX;
 extern F32 SPEED_ADJUST_MAX_SEC;
 extern F32 ANIM_SPEED_MAX;
@@ -3518,6 +3520,17 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	}
 
 	BOOL visible = isVisible();
+    bool is_control_avatar = isControlAvatar(); // capture state to simplify tracing
+	bool is_attachment = false;
+	if (is_control_avatar)
+	{
+        LLControlAvatar *cav = dynamic_cast<LLControlAvatar*>(this);
+		is_attachment = cav && cav->mRootVolp && cav->mRootVolp->isAttachment(); // For attached animated objects
+	}
+
+    LLScopedContextString str("updateCharacter " + getFullname() + " is_control_avatar "
+                              + boost::lexical_cast<std::string>(is_control_avatar) 
+                              + " is_attachment " + boost::lexical_cast<std::string>(is_attachment));
 
 	// For fading out the names above heads, only let the timer
 	// run if we're visible.
@@ -3532,21 +3545,25 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 
 	bool visually_muted = isVisuallyMuted();
     // AXON FIXME this expression is a crawling horror
-	if (mDrawable.notNull() && visible && (!isSelf() || visually_muted) && 
-        !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
+	if (mDrawable.notNull()
+        && visible 
+        && (!isSelf() || visually_muted) // AXON would the self ever be visually muted?
+        && !mIsDummy
+        && sUseImpostors
+        && !mNeedsAnimUpdate 
+        && !sFreezeCounter)
 	{
 		const LLVector4a* ext = mDrawable->getSpatialExtents();
 		LLVector4a size;
 		size.setSub(ext[1],ext[0]);
 		F32 mag = size.getLength3().getF32()*0.5f;
-
 		
 		F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
 		if (visually_muted)
 		{ // visually muted avatars update at 16 hz
 			mUpdatePeriod = 16;
 		}
-		else if (   ! shouldImpostor()
+		else if (! shouldImpostor()
 				 || mDrawable->mDistanceWRTCamera < 1.f + mag)
 		{   // first 25% of max visible avatars are not impostored
 			// also, don't impostor avatars whose bounding box may be penetrating the 
@@ -3590,7 +3607,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 
 	// change animation time quanta based on avatar render load
     // AXON how should control avs be handled here?
-    bool is_pure_dummy = mIsDummy && !isControlAvatar();
+    bool is_pure_dummy = mIsDummy && !is_control_avatar;
 	if (!isSelf() && !is_pure_dummy)
 	{
 		F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f);
@@ -3602,6 +3619,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 			stopMotion(ANIM_AGENT_WALK_ADJUST);
 			removeAnimationData("Walk Speed");
 		}
+        // AXON: see SL-763 - playback with altered time step does not
+        // appear to work correctly, odd behavior for distant avatars.
 		mMotionController.setTimeStep(time_step);
 		//		LL_INFOS() << "Setting timestep to " << time_quantum * pixel_area_scale << LL_ENDL;
 	}
@@ -3698,23 +3717,28 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 		{
 			root_pos += LLVector3d(getHoverOffset());
 		}
-		
-		LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
-
-
-		if (newPosition != mRoot->getXform()->getWorldPosition())
-		{		
-			mRoot->touch();
-			// SL-315
-			mRoot->setWorldPosition( newPosition ); // regular update				
-		}
 
+        LLControlAvatar *cav = dynamic_cast<LLControlAvatar*>(this);
+        if (cav)
+        {
+            cav->matchVolumeTransform();
+        }
+        else
+        {
+            LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
+            if (newPosition != mRoot->getXform()->getWorldPosition())
+            {		
+                mRoot->touch();
+                // SL-315
+                mRoot->setWorldPosition( newPosition ); // regular update				
+            }
+        }
 
 		//--------------------------------------------------------------------
 		// Propagate viewer object rotation to root of avatar
 		//--------------------------------------------------------------------
-        // AXON - also skip for control avatars
-		if (!isControlAvatar() && !isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS))
+        // AXON - also skip for control avatars? Rotation fixups for avatars in motion, some may be relevant.
+		if (!is_control_avatar && !isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS))
 		{
 			LLQuaternion iQ;
 			LLVector3 upDir( 0.0f, 0.0f, 1.0f );
@@ -3868,6 +3892,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	}
 	else if (mDrawable.notNull())
 	{
+        // Sitting on an object - mRoot is slaved to mDrawable orientation.
 		LLVector3 pos = mDrawable->getPosition();
 		pos += getHoverOffset() * mDrawable->getRotation();
 		// SL-315
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 8b22024e0a46dd9f6bca27a2aa918b2c67702eae..acecc6118cd889102b82f51e8ac651f8bbbe413b 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -749,9 +749,9 @@ class LLVOAvatar :
 	static LLVOAvatar*  findAvatarFromAttachment(LLViewerObject* obj);
 	/*virtual*/ BOOL	isWearingWearableType(LLWearableType::EType type ) const;
 	LLViewerObject *	findAttachmentByID( const LLUUID & target_id ) const;
+	LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object);
 
 protected:
-	LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object);
 	void 				lazyAttach();
 	void				rebuildRiggedAttachments( void );