diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 5a6b66df52b0213e17a35829d88ec919e3f8b4ff..f732f369bdf3a5cf99ecfb5d10c2da950c73f7dd 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -360,7 +360,38 @@ void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time)
     }
 }
 
-BOOL LLControlAvatar::updateCharacter(LLAgent &agent)
+bool LLControlAvatar::computeNeedsUpdate()
+{
+	computeUpdatePeriod();
+
+	// Animesh attachments are a special case. Should have the same update cadence as their attached parent avatar.
+	bool is_attachment = mRootVolp && mRootVolp->isAttachment(); // For attached animated objects
+	if (is_attachment)
+	{
+		LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor();
+		if (attached_av)
+		{
+			// Have to run computeNeedsUpdate() for attached av in
+			// case it hasn't run updateCharacter() already this
+			// frame.  Note this means that the attached av will
+			// run computeNeedsUpdate() multiple times per frame
+			// if it has animesh attachments. Results will be
+			// consistent except for the corner case of exceeding
+			// MAX_IMPOSTOR_INTERVAL in one call but not another,
+			// which should be rare.
+			attached_av->computeNeedsUpdate();
+			mNeedsImpostorUpdate = attached_av->mNeedsImpostorUpdate;
+			if (mNeedsImpostorUpdate)
+			{
+				mLastImpostorUpdateReason = 12;
+			}
+			return mNeedsImpostorUpdate;
+		}
+	}
+	return LLVOAvatar::computeNeedsUpdate();
+}
+
+bool LLControlAvatar::updateCharacter(LLAgent &agent)
 {
     return LLVOAvatar::updateCharacter(agent);
 }
diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h
index 288d07cd48aed31bbd261558ff66da4b6db9eb15..2c688501403b85df70f7d4514f0cf6095d8e8e2e 100644
--- a/indra/newview/llcontrolavatar.h
+++ b/indra/newview/llcontrolavatar.h
@@ -53,7 +53,8 @@ class LLControlAvatar:
     void markForDeath();
 
     virtual void idleUpdate(LLAgent &agent, const F64 &time);
-	virtual BOOL updateCharacter(LLAgent &agent);
+	virtual bool computeNeedsUpdate();
+	virtual bool updateCharacter(LLAgent &agent);
 
     void getAnimatedVolumes(std::vector<LLVOVolume*>& volumes);
     void updateAnimations();  
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 357bbecb5aedaeebdd953435face6602e0091ae6..c5bf6ab307bfd1bebbd60c70f79568b553bee10c 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2139,7 +2139,15 @@ void LLVOAvatar::resetSkeleton(bool reset_animations)
 	}
 	else
 	{
+		// Stripped down approximation of
+		// applyParsedAppearanceMessage, but with alternative default
+		// (jellydoll) params
+		setCompositeUpdatesEnabled( FALSE );
+		gPipeline.markGLRebuild(this);
 		applyDefaultParams();
+		setCompositeUpdatesEnabled( TRUE );
+		updateMeshTextures();
+		updateMeshVisibility();
 	}
     updateVisualParams();
 
@@ -4418,6 +4426,37 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w
 }
 
 //------------------------------------------------------------------------
+// LLVOAvatar::computeNeedsUpdate()
+// 
+// Most of the logic here is to figure out when to periodically update impostors.
+// Non-impostors have mUpdatePeriod == 1 and will need update every frame.
+//------------------------------------------------------------------------
+bool LLVOAvatar::computeNeedsUpdate()
+{
+	const F32 MAX_IMPOSTOR_INTERVAL = 4.0f;
+	computeUpdatePeriod();
+
+	bool needs_update_by_frame_count = ((LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0);
+
+    bool needs_update_by_max_time = ((gFrameTimeSeconds-mLastImpostorUpdateFrameTime)> MAX_IMPOSTOR_INTERVAL);
+	bool needs_update = needs_update_by_frame_count || needs_update_by_max_time;
+
+	if (needs_update && !isSelf())
+	{
+		if (needs_update_by_max_time)
+		{
+			mNeedsImpostorUpdate = TRUE;
+			mLastImpostorUpdateReason = 11;
+		}
+		else
+		{
+			//mNeedsImpostorUpdate = TRUE;
+			//mLastImpostorUpdateReason = 10;
+		}
+	}
+	return needs_update;
+}
+
 // updateCharacter()
 //
 // This is called for all avatars, so there are 4 possible situations:
@@ -4440,7 +4479,7 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w
 // simulator.
 //
 //------------------------------------------------------------------------
-BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
+bool LLVOAvatar::updateCharacter(LLAgent &agent)
 {	
 	updateDebugText();
 	
@@ -4452,6 +4491,7 @@ 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);
@@ -4474,25 +4514,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
     // Set mUpdatePeriod and visible based on distance and other criteria,
 	// and flag for impostor update if needed.
 	//--------------------------------------------------------------------
-	const F32 MAX_IMPOSTOR_INTERVAL = 4.0f;
-	computeUpdatePeriod();
-	bool needs_update_by_frame_count = ((LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0);
-    bool needs_update_by_max_time = ((mLastImpostorUpdateFrameTime-gFrameTimeSeconds)> MAX_IMPOSTOR_INTERVAL);
-	bool needs_update = needs_update_by_frame_count || needs_update_by_max_time;
-
-	if (needs_update && !isSelf())
-	{
-		if (needs_update_by_max_time)
-		{
-			mNeedsImpostorUpdate = TRUE;
-			mLastImpostorUpdateReason = 11;
-		}
-		else
-		{
-			mNeedsImpostorUpdate = TRUE;
-			mLastImpostorUpdateReason = 10;
-		}
-	}
+	bool needs_update = computeNeedsUpdate();
 	
 	//--------------------------------------------------------------------
 	// Early out if does not need update and not self
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 14badda48e4370a92d6549d1e64ffa7d8592efc9..b815b3b2cd2f27ecc05e11f8afc35cd1f4d24242 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -263,7 +263,8 @@ class LLVOAvatar :
     void			updateAppearanceMessageDebugText();
 	void 			updateAnimationDebugText();
 	virtual void	updateDebugText();
-	virtual BOOL 	updateCharacter(LLAgent &agent);
+	virtual bool 	computeNeedsUpdate();
+	virtual bool 	updateCharacter(LLAgent &agent);
     void			updateFootstepSounds();
     void			computeUpdatePeriod();
     void			updateOrientation(LLAgent &agent, F32 speed, F32 delta_time);
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index aea12380e84c47ec87779c090ec4ba355bf45b6f..d72fc6b9aaf5cff79510b9370239a858f188c272 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -668,7 +668,7 @@ LLVOAvatarSelf::~LLVOAvatarSelf()
  *********************************************************************************/
 
 // virtual
-BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent)
+bool LLVOAvatarSelf::updateCharacter(LLAgent &agent)
 {
 	// update screen joint size
 	if (mScreenp)
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index b0fdae9bf0e24678bd9c6b8c2d84e24eb346fded..279dbd61a6dee8083d467e8235fe5f6e3159797c 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -116,7 +116,7 @@ class LLVOAvatarSelf :
 	// Updates
 	//--------------------------------------------------------------------
 public:
-	/*virtual*/ BOOL 	updateCharacter(LLAgent &agent);
+	/*virtual*/ bool 	updateCharacter(LLAgent &agent);
 	/*virtual*/ void 	idleUpdateTractorBeam();
 	bool				checkStuckAppearance();