diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index cab3a7d619d4ceb47b14639dab8185d0f83bca30..6615a430ab2227609ea32689201d46812e36b7fd 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -89,6 +89,11 @@ bool LLPosOverrideMap::remove(const LLUUID& mesh_id)
 	return (remove_count > 0);
 }
 
+void LLPosOverrideMap::clear()
+{
+	m_map.clear();
+}
+
 //-----------------------------------------------------------------------------
 // LLJoint()
 // Class Constructor
@@ -367,6 +372,18 @@ bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const
 	return m_attachmentOverrides.findActiveOverride(mesh_id,pos);
 }
 
+//--------------------------------------------------------------------
+// clearAttachmentPosOverrides()
+//--------------------------------------------------------------------
+void LLJoint::clearAttachmentPosOverrides()
+{
+	if (m_attachmentOverrides.count())
+	{
+		m_attachmentOverrides.clear();
+		setPosition(m_posBeforeOverrides);
+	}
+}
+
 //--------------------------------------------------------------------
 // updatePos()
 //--------------------------------------------------------------------
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 56da8e83b20b2e007d8c8f5844fd97cb19c0a444..2abe1d6db1510cb6da94adf987e473a271c6da73 100755
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -55,6 +55,7 @@ class LLPosOverrideMap
 	U32 count() const;
 	void add(const LLUUID& mesh_id, const LLVector3& pos);
 	bool remove(const LLUUID& mesh_id);
+	void clear();
 private:
 	typedef std::map<LLUUID,LLVector3> map_type;
 	map_type m_map;
@@ -202,6 +203,7 @@ class LLJoint
 	void addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info );
 	void removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info );
 	bool hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const;
+	void clearAttachmentPosOverrides();
 
 	//Accessor for the joint id
 	LLUUID getId( void ) { return mId; }
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 964c5110d16ed5a600c0beda2ca3b753145a984c..585f14df3dd2e670ab1312515b4c4cc0821d823c 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1257,6 +1257,7 @@ void LLAgentWearables::userRemoveWearablesOfType(const LLWearableType::EType &ty
 // removed, and what additional inventory items need to be added.
 void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array,
 													llvo_vec_t& objects_to_remove,
+													llvo_vec_t& objects_to_retain,
 													LLInventoryModel::item_array_t& items_to_add)
 {
 	// Possible cases:
@@ -1310,6 +1311,7 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array
 				{
 					// LL_INFOS() << "found object to keep, id " << objectp->getID() << ", item " << objectp->getAttachmentItemID() << LL_ENDL;
 					current_item_ids.insert(object_item_id);
+					objects_to_retain.push_back(objectp);
 				}
 			}
 		}
@@ -1335,23 +1337,6 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array
 	// LL_INFOS() << "remove " << remove_count << " add " << add_count << LL_ENDL;
 }
 
-// Combines userRemoveMulipleAttachments() and userAttachMultipleAttachments() logic to
-// get attachments into desired state with minimal number of adds/removes.
-void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array)
-{
-	llvo_vec_t objects_to_remove;
-	LLInventoryModel::item_array_t items_to_add;
-	findAttachmentsAddRemoveInfo(obj_item_array,
-								 objects_to_remove,
-								 items_to_add);
-
-	// Remove everything in objects_to_remove
-	userRemoveMultipleAttachments(objects_to_remove);
-
-	// Add everything in items_to_add
-	userAttachMultipleAttachments(items_to_add);
-}
-
 void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove)
 {
 	if (!isAgentAvatarValid()) return;
@@ -1369,7 +1354,7 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo
 		 ++it)
 	{
 		LLViewerObject *objectp = *it;
-		gAgentAvatarp->resetJointPositionsOnDetach(objectp);
+		//gAgentAvatarp->resetJointPositionsOnDetach(objectp);
 		gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
 		gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID());
 	}
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 10e3dbf8c6e01cf40c8d14c222d1af6ac6655c09..100448202080c8a2f6ecdfae5dd086e01dc4a5b5 100755
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -180,8 +180,8 @@ class LLAgentWearables : public LLInitClass<LLAgentWearables>, public LLWearable
 
 	static void     findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array,
 												 llvo_vec_t& objects_to_remove,
+												 llvo_vec_t& objects_to_retain,
 												 LLInventoryModel::item_array_t& items_to_add);
-	static void 	userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array);
 	static void		userRemoveMultipleAttachments(llvo_vec_t& llvo_array);
 	static void		userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
 
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 69efb20f79e276b6707dd3d681513fda1e0e9f70..943190e7b1cdbdf967147d32567a52e0036e5b82 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -809,22 +809,34 @@ void LLWearableHoldingPattern::onAllComplete()
 
 	LL_DEBUGS("Avatar") << self_av_string() << "Updating " << mObjItems.size() << " attachments" << LL_ENDL;
 	LLAgentWearables::llvo_vec_t objects_to_remove;
+	LLAgentWearables::llvo_vec_t objects_to_retain;
 	LLInventoryModel::item_array_t items_to_add;
 	if (isAgentAvatarValid())
 	{
 		LLAgentWearables::findAttachmentsAddRemoveInfo(mObjItems,
 													   objects_to_remove,
+													   objects_to_retain,
 													   items_to_add);
 
 		LL_DEBUGS("Avatar") << self_av_string() << "Removing " << objects_to_remove.size()
 							<< " attachments" << LL_ENDL;
+		gAgentAvatarp->clearAttachmentPosOverrides();
 		LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove);
 	}
 
 	// Update wearables.
 	LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with " << mResolved << " wearable items " << LL_ENDL;
 	LLAppearanceMgr::instance().updateAgentWearables(this);
-	
+
+	// Restore attachment pos overrides for the attachments that aren't going away.
+	for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin();
+		it != objects_to_retain.end();
+		++it)
+	{
+		LLViewerObject *objectp = *it;
+		gAgentAvatarp->addAttachmentPosOverridesForObject(objectp);
+	}
+
 	// Update attachments to match those requested.
 	if (isAgentAvatarValid())
 	{
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 646ca25a0e358b35b6ee3720e12f3983da4a8727..835c4e61764c7b46e9790dba3336b24edd9977af 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5061,6 +5061,99 @@ bool LLVOAvatar::getRiggedMeshID(LLViewerObject* pVO, LLUUID& mesh_id)
 	return false;
 }
 
+void LLVOAvatar::clearAttachmentPosOverrides()
+{
+	//Subsequent joints are relative to pelvis
+	avatar_joint_list_t::iterator iter = mSkeleton.begin();
+	avatar_joint_list_t::iterator end  = mSkeleton.end();
+
+	for (; iter != end; ++iter)
+	{
+		LLJoint* pJoint = (*iter);
+		pJoint->clearAttachmentPosOverrides();
+	}
+}
+
+//-----------------------------------------------------------------------------
+// addAttachmentPosOverridesForObject
+//-----------------------------------------------------------------------------
+void LLVOAvatar::addAttachmentPosOverridesForObject(LLViewerObject *vo)
+{
+	LLVOAvatar *av = vo->getAvatarAncestor();
+	if (!av || (av != this))
+	{
+		LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL;
+	}
+		
+	// Process all children
+	LLViewerObject::const_child_list_t& children = vo->getChildren();
+	for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
+		 it != children.end(); ++it)
+	{
+		LLViewerObject *childp = *it;
+		addAttachmentPosOverridesForObject(childp);
+	}
+
+	LLVOVolume *vobj = dynamic_cast<LLVOVolume*>(vo);
+	bool pelvisGotSet = false;
+
+	if (!vobj)
+	{
+		return;
+	}
+	if (vobj->isMesh() &&
+		((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled()))
+	{
+		return;
+	}
+	LLUUID currentId = vobj->getVolume()->getParams().getSculptID();						
+	const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
+
+	if ( vobj && vobj->isAttachment() && vobj->isMesh() && pSkinData )
+	{
+		const int bindCnt = pSkinData->mAlternateBindMatrix.size();								
+		if ( bindCnt > 0 )
+		{					
+			const int jointCnt = pSkinData->mJointNames.size();
+			const F32 pelvisZOffset = pSkinData->mPelvisOffset;
+			const LLUUID& mesh_id = pSkinData->mMeshID;
+			bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false;								
+			if ( fullRig )
+			{								
+				for ( int i=0; i<jointCnt; ++i )
+				{
+					std::string lookingForJoint = pSkinData->mJointNames[i].c_str();
+					LLJoint* pJoint = getJoint( lookingForJoint );
+					if ( pJoint && pJoint->getId() != currentId )
+					{   									
+						pJoint->setId( currentId );
+						const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();									
+						//Set the joint position
+						pJoint->addAttachmentPosOverride( jointPos, mesh_id, avString() );
+									
+						//If joint is a pelvis then handle old/new pelvis to foot values
+						if ( lookingForJoint == "mPelvis" )
+						{	
+							pelvisGotSet = true;											
+						}										
+					}										
+				}																
+				if (pelvisZOffset != 0.0F)
+				{
+					addPelvisFixup( pelvisZOffset, mesh_id );
+					pelvisGotSet = true;											
+				}
+			}							
+		}
+	}
+					
+	//Rebuild body data if we altered joints/pelvis
+	if ( pelvisGotSet ) 
+	{
+		postPelvisSetRecalc();
+	}		
+}
+
 //-----------------------------------------------------------------------------
 // resetJointPositionsOnDetach
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index ce1f0dd15272a5b47396181c9986be0165272815..9a2aaf8aa302e09847a1de8c34b37ea83cbce7ee 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -199,8 +199,10 @@ class LLVOAvatar :
 
 	virtual LLJoint*		getJoint(const std::string &name);
 	
+	void 					addAttachmentPosOverridesForObject(LLViewerObject *vo);
 	void					resetJointPositionsOnDetach(const LLUUID& mesh_id);
 	void					resetJointPositionsOnDetach(LLViewerObject *vo);
+	void					clearAttachmentPosOverrides();
 	
 	/*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 aebd9f470dd1bf2714b13fa3b82692d987fc46aa..5707d373bfb2cec786cf6d7a1748d0c44ae42967 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4517,7 +4517,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 	//Determine if we've received skininfo that contains an
 	//alternate bind matrix - if it does then apply the translational component
 	//to the joints of the avatar.
+#if 0
 	bool pelvisGotSet = false;
+#endif
 
 	{
 		LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST);
@@ -4602,55 +4604,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 					//get drawpool of avatar with rigged face
 					LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);				
 					
+					// FIXME should this be inside the face loop?
+					// doesn't seem to depend on any per-face state.
 					if ( pAvatarVO )
 					{
-						LLUUID currentId = vobj->getVolume()->getParams().getSculptID();						
-						const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
-						if ( pSkinData )
-						{
-							const int bindCnt = pSkinData->mAlternateBindMatrix.size();								
-							if ( bindCnt > 0 )
-							{					
-								const int jointCnt = pSkinData->mJointNames.size();
-								const F32 pelvisZOffset = pSkinData->mPelvisOffset;
-								const LLUUID& mesh_id = pSkinData->mMeshID;
-								bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false;								
-								if ( fullRig )
-								{								
-									for ( int i=0; i<jointCnt; ++i )
-									{
-										std::string lookingForJoint = pSkinData->mJointNames[i].c_str();
-										LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint );
-										if ( pJoint && pJoint->getId() != currentId )
-										{   									
-											pJoint->setId( currentId );
-											const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();									
-											
-											//Set the joint position
-											pJoint->addAttachmentPosOverride( jointPos, mesh_id, pAvatarVO->avString() );
-									
-											//If joint is a pelvis then handle old/new pelvis to foot values
-											if ( lookingForJoint == "mPelvis" )
-											{	
-												pelvisGotSet = true;											
-											}										
-										}										
-									}																
-									if (pelvisZOffset != 0.0F)
-									{
-										pAvatarVO->addPelvisFixup( pelvisZOffset, mesh_id );
-										pelvisGotSet = true;											
-									}
-								}							
-							}
-						}
+						pAvatarVO->addAttachmentPosOverridesForObject(vobj);
 					}
-					
-					//Rebuild body data if we altered joints/pelvis
-					if ( pelvisGotSet && pAvatarVO ) 
-					{
-						pAvatarVO->postPelvisSetRecalc();
-					}		
 
 					if (pool)
 					{
@@ -5008,14 +4967,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 			}
 			
 		}
-
-		
-		
-			
-		
-					
-
-		
 	}
 
 	group->mBufferUsage = useage;