From 94f945c2c65fcd791bf86c58168fd457837e2acd Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 27 Aug 2014 16:52:52 -0400
Subject: [PATCH] WIP on attachment offset management in joints

---
 indra/llcharacter/lljoint.cpp           | 82 +++++++++++++++++--------
 indra/llcharacter/lljoint.h             | 29 ++++++---
 indra/newview/llfloatermodelpreview.cpp |  3 +-
 indra/newview/llviewerobject.cpp        | 11 ++++
 indra/newview/llviewerobject.h          |  2 +
 indra/newview/llvoavatar.cpp            | 14 ++---
 indra/newview/llvoavatar.h              |  2 +-
 indra/newview/llvovolume.cpp            |  4 +-
 8 files changed, 105 insertions(+), 42 deletions(-)

diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index c78c38c3a7e..f6e95fdc8d4 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -52,7 +52,6 @@ void LLJoint::init()
 	mOldXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
 	mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
 	mUpdateXform = TRUE;
-	mResetAfterRestoreOldXform = false;	
 }
 
 LLJoint::LLJoint() :
@@ -245,7 +244,7 @@ void LLJoint::setPosition( const LLVector3& pos )
 
 
 //--------------------------------------------------------------------
-// setPosition()
+// setDefaultFromCurrentXform()
 //--------------------------------------------------------------------
 void LLJoint::setDefaultFromCurrentXform( void )
 {		
@@ -253,14 +252,62 @@ void LLJoint::setDefaultFromCurrentXform( void )
 }
 
 //--------------------------------------------------------------------
-// storeCurrentXform()
+// addAttachmentPosOverride()
 //--------------------------------------------------------------------
-void LLJoint::storeCurrentXform( const LLVector3& pos )
-{	
-	mOldXform = mXform;
-	mResetAfterRestoreOldXform = true;	
-	setPosition( pos );
-	touch(ALL_DIRTY);	
+void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const std::string& attachment_name )
+{
+	if (attachment_name.empty())
+	{
+		return;
+	}
+	if (m_attachmentOverrides.empty())
+	{
+		LL_WARNS() << "saving m_posBeforeOverrides " << getPosition() << LL_ENDL;
+		m_posBeforeOverrides = getPosition();
+	}
+	AttachmentOverrideRecord rec;
+	rec.name = attachment_name;
+	rec.pos = pos;
+	m_attachmentOverrides[attachment_name] = rec;
+	LL_WARNS() << "addAttachmentPosOverride for " << attachment_name << " pos " << pos << LL_ENDL;
+	updatePos();
+}
+
+//--------------------------------------------------------------------
+// removeAttachmentPosOverride()
+//--------------------------------------------------------------------
+void LLJoint::removeAttachmentPosOverride( const std::string& attachment_name )
+{
+	if (attachment_name.empty())
+	{
+		return;
+	}
+	attachment_map_t::iterator it = m_attachmentOverrides.find(attachment_name);
+	if (it != m_attachmentOverrides.end())
+	{
+		LL_WARNS() << "removeAttachmentPosOverride for " << attachment_name << LL_ENDL;
+		m_attachmentOverrides.erase(it);
+	}
+	updatePos();
+}
+
+void LLJoint::updatePos()
+{
+	LLVector3 pos;
+	attachment_map_t::iterator it = std::max_element(m_attachmentOverrides.begin(),
+													 m_attachmentOverrides.end());
+	if (it != m_attachmentOverrides.end())
+	{
+		AttachmentOverrideRecord& rec = it->second;
+		LL_WARNS() << "updatePos, winner is attachment " << rec.name << " pos " << rec.pos << LL_ENDL;
+		pos = rec.pos;
+	}
+	else
+	{
+		LL_WARNS() << "updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL;
+		pos = m_posBeforeOverrides;
+	}
+	setPosition(pos);
 }
 
 //--------------------------------------------------------------------
@@ -276,7 +323,6 @@ void LLJoint::storeScaleForReset( const LLVector3& scale )
 void LLJoint::restoreOldXform( void )
 {	
 	mXform = mOldXform;
-	mResetAfterRestoreOldXform = false;
 	mDirtyFlags = ALL_DIRTY;	
 }
 //--------------------------------------------------------------------
@@ -325,7 +371,7 @@ void LLJoint::setWorldPosition( const LLVector3& pos )
 
 
 //--------------------------------------------------------------------
-// mXform.getRotation()
+// getRotation()
 //--------------------------------------------------------------------
 const LLQuaternion& LLJoint::getRotation()
 {
@@ -548,20 +594,6 @@ void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot)
 			break;
 		}
 	}
-
-	// 2003.03.26 - This code was just using up cpu cycles. AB
-
-//	LLVector3 old_axis = main_axis * old_rot;
-//	LLVector3 new_axis = main_axis * new_rot;
-
-//	for (S32 i = 0; i < mConstraintSilhouette.size() - 1; i++)
-//	{
-//		LLVector3 vert1 = mConstraintSilhouette[i];
-//		LLVector3 vert2 = mConstraintSilhouette[i + 1];
-
-		// figure out how to clamp rotation to line on 3-sphere
-
-//	}
 }
 
 // End
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index b65d6979d4a..f6f1cd2fe46 100755
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -88,8 +88,6 @@ class LLJoint
 	U32				mDirtyFlags;
 	BOOL			mUpdateXform;
 
-	BOOL			mResetAfterRestoreOldXform;
-
 	// describes the skin binding pose
 	LLVector3		mSkinOffset;
 
@@ -103,6 +101,25 @@ class LLJoint
 	static S32		sNumTouches;
 	static S32		sNumUpdates;
 
+	struct AttachmentOverrideRecord
+	{
+		AttachmentOverrideRecord()
+		{
+		}
+		LLVector3 pos;
+		std::string name;
+
+		bool operator<(const AttachmentOverrideRecord& other) const
+		{
+			return name < other.name;
+		}
+	};
+	typedef std::map<std::string,AttachmentOverrideRecord> attachment_map_t;
+	attachment_map_t m_attachmentOverrides;
+	LLVector3 m_posBeforeOverrides;
+
+	void updatePos();
+
 public:
 	LLJoint();
 	LLJoint(S32 joint_num);
@@ -188,15 +205,13 @@ class LLJoint
 	void setDefaultFromCurrentXform( void );
 	void storeCurrentXform( const LLVector3& pos );
 
+	void addAttachmentPosOverride( const LLVector3& pos, const std::string& attachment_name );
+	void removeAttachmentPosOverride( const std::string& attachment_name );
+
 	//Accessor for the joint id
 	LLUUID getId( void ) { return mId; }
 	//Setter for the joints id
 	void setId( const LLUUID& id ) { mId = id;}
-
-	//If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it
-	const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; }
-	void setJointResetFlag( bool val ) { mResetAfterRestoreOldXform = val; }
-	
 };
 #endif // LL_LLJOINT_H
 
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index b17ce97a2e6..039ff848cb3 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -1935,7 +1935,8 @@ bool LLModelLoader::doLoadModel()
 										LLJoint* pJoint = mPreview->getPreviewAvatar()->getJoint( lookingForJoint );
 										if ( pJoint )
 										{   
-											pJoint->storeCurrentXform( jointTransform.getTranslation() );												
+											LL_WARNS() << "Aieee, now what!" << LL_ENDL;
+											//pJoint->storeCurrentXform( jointTransform.getTranslation() );												
 										}
 										else
 										{
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 80592f01ce6..2d42c683575 100755
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -6190,6 +6190,17 @@ const LLUUID &LLViewerObject::extractAttachmentItemID()
 	return getAttachmentItemID();
 }
 
+const std::string& LLViewerObject::getAttachmentItemName()
+{
+	static std::string empty;
+	LLInventoryItem *item = gInventory.getItem(getAttachmentItemID());
+	if (isAttachment() && item)
+	{
+		return item->getName();
+	}
+	return empty;
+}
+
 //virtual
 LLVOAvatar* LLViewerObject::getAvatar() const
 {
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index bab107cc570..22ac4ce0db1 100755
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -170,6 +170,8 @@ class LLViewerObject
 	void			setOnActiveList(BOOL on_active)		{ mOnActiveList = on_active; }
 
 	virtual BOOL	isAttachment() const { return FALSE; }
+	const std::string& getAttachmentItemName();
+
 	virtual LLVOAvatar* getAvatar() const;  //get the avatar this object is attached to, or NULL if object is not an attachment
 	virtual BOOL	isHUDAttachment() const { return FALSE; }
 	virtual BOOL	isTempAttachment() const;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index e5473e92d93..fea1c0f5213 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5058,9 +5058,9 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
 	return jointp;
 }
 //-----------------------------------------------------------------------------
-// resetJointPositionsToDefault
+// resetJointPositionsOnDetach
 //-----------------------------------------------------------------------------
-void LLVOAvatar::resetJointPositionsToDefault( void )
+void LLVOAvatar::resetJointPositionsOnDetach(const std::string& attachment_name)
 {	
 	//Subsequent joints are relative to pelvis
 	avatar_joint_list_t::iterator iter = mSkeleton.begin();
@@ -5072,17 +5072,16 @@ void LLVOAvatar::resetJointPositionsToDefault( void )
 	{
 		LLJoint* pJoint = (*iter);
 		//Reset joints except for pelvis
-		if ( pJoint && pJoint != pJointPelvis && pJoint->doesJointNeedToBeReset() )
+		if ( pJoint && pJoint != pJointPelvis)
 		{			
 			pJoint->setId( LLUUID::null );
-			pJoint->restoreOldXform();
+			pJoint->removeAttachmentPosOverride(attachment_name);
 		}		
 		else
-		if ( pJoint && pJoint == pJointPelvis && pJoint->doesJointNeedToBeReset() )
+		if ( pJoint && pJoint == pJointPelvis)
 		{
 			pJoint->setId( LLUUID::null );
 			pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) );
-			pJoint->setJointResetFlag( false );
 		}		
 	}	
 		
@@ -5746,7 +5745,8 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
 				&& pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG	// full rig
 				&& pSkinData->mAlternateBindMatrix.size() > 0 )
 					{				
-						LLVOAvatar::resetJointPositionsToDefault();							
+						const std::string& attachment_name = pVO->getAttachmentItemName();
+						LLVOAvatar::resetJointPositionsOnDetach(attachment_name);							
 						//Need to handle the repositioning of the cam, updating rig data etc during outfit editing 
 						//This handles the case where we detach a replacement rig.
 						if ( gAgentCamera.cameraCustomizeAvatar() )
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 42ff7bff92f..66a357ff628 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -199,7 +199,7 @@ class LLVOAvatar :
 
 	virtual LLJoint*		getJoint(const std::string &name);
 	
-	void					resetJointPositionsToDefault( void );
+	void					resetJointPositionsOnDetach(const std::string& attachment_name);
 	
 	/*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 a83e2e020ea..0ef48c4c70a 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4626,7 +4626,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 											const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();									
 											
 											//Set the joint position
-											pJoint->storeCurrentXform( jointPos );					
+											const std::string& attachment_name = drawablep->getVObj()->getAttachmentItemName();
+											//pJoint->storeCurrentXform( jointPos );					
+											pJoint->addAttachmentPosOverride( jointPos, attachment_name );
 									
 											//If joint is a pelvis then handle old/new pelvis to foot values
 											if ( lookingForJoint == "mPelvis" )
-- 
GitLab