From 228525aa27b05cc1aa8be27de4ae59f5ec590ae3 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 4 Jun 2018 14:43:06 +0100
Subject: [PATCH] SL-915 - tracking joint is rigged state

---
 indra/llcharacter/lljoint.cpp    | 53 ------------------
 indra/llcharacter/lljoint.h      | 22 --------
 indra/llmath/CMakeLists.txt      |  2 +
 indra/llmath/llrigginginfo.cpp   | 96 ++++++++++++++++++++++++++++++++
 indra/llmath/llrigginginfo.h     | 55 ++++++++++++++++++
 indra/newview/llskinningutil.cpp | 25 +++++++++
 indra/newview/llskinningutil.h   |  4 ++
 indra/newview/llviewerobject.h   |  5 ++
 indra/newview/llvoavatar.cpp     | 91 +++++++++++++++++++++++++++---
 indra/newview/llvoavatar.h       |  6 ++
 indra/newview/llvovolume.cpp     | 15 +++++
 indra/newview/llvovolume.h       |  3 +
 12 files changed, 295 insertions(+), 82 deletions(-)
 create mode 100644 indra/llmath/llrigginginfo.cpp
 create mode 100644 indra/llmath/llrigginginfo.h

diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 68355cbbdcf..07fcd997012 100644
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -96,46 +96,6 @@ void LLVector3OverrideMap::clear()
 	m_map.clear();
 }
 
-//-----------------------------------------------------------------------------
-// LLJointRiggingInfo
-//-----------------------------------------------------------------------------
-LLJointRiggingInfo::LLJointRiggingInfo()
-{
-    mRiggedExtents[0].clear();
-    mRiggedExtents[1].clear();
-    mIsRiggedTo = false;
-}
-
-bool LLJointRiggingInfo::isRiggedTo() const
-{
-    return mIsRiggedTo;
-}
-
-void LLJointRiggingInfo::setIsRiggedTo(bool val)
-{
-    mIsRiggedTo = val;
-}
-    
-LLVector4a *LLJointRiggingInfo::getRiggedExtents()
-{
-    return mRiggedExtents;
-}
-
-const LLVector4a *LLJointRiggingInfo::getRiggedExtents() const
-{
-    return mRiggedExtents;
-}
-
-// Combine two rigging info states.
-// - isRiggedTo if either of the source infos are rigged to
-// - box is union of the two sources
-void LLJointRiggingInfo::merge(const LLJointRiggingInfo& other)
-{
-    mIsRiggedTo = mIsRiggedTo || other.mIsRiggedTo;
-    update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[0]);
-    update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[1]);
-}
-
 //-----------------------------------------------------------------------------
 // LLJoint()
 // Class Constructor
@@ -637,19 +597,6 @@ void LLJoint::showAttachmentPosOverrides(const std::string& av_info) const
 	}
 }
 
-//--------------------------------------------------------------------
-// getRiggingInfo()
-//--------------------------------------------------------------------
-LLJointRiggingInfo& LLJoint::getRiggingInfo()
-{
-    return mRiggingInfo;
-}
-
-const LLJointRiggingInfo& LLJoint::getRiggingInfo() const
-{
-    return mRiggingInfo;
-}
-
 //--------------------------------------------------------------------
 // updatePos()
 //--------------------------------------------------------------------
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index ff1e9671889..8112d246f28 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -70,23 +70,6 @@ class LLVector3OverrideMap
 	map_type m_map;
 };
 
-// Stores information related to associated rigged mesh vertices
-// Extents are in joint space
-// isRiggedTo is based on the state of all currently associated rigged meshes
-class LLJointRiggingInfo
-{
-public:
-    LLJointRiggingInfo();
-    bool isRiggedTo() const;
-    void setIsRiggedTo(bool val);
-    LLVector4a *getRiggedExtents();
-    const LLVector4a *getRiggedExtents() const;
-    void merge(const LLJointRiggingInfo& other);
-private:
-	LL_ALIGN_16(LLVector4a mRiggedExtents[2]);
-    bool mIsRiggedTo;
-};
-
 inline bool operator==(const LLVector3OverrideMap& a, const LLVector3OverrideMap& b)
 {
     return a.getMap() == b.getMap();
@@ -175,11 +158,6 @@ class LLJoint
 	LLVector3OverrideMap m_attachmentScaleOverrides;
 	LLVector3 m_scaleBeforeOverrides;
 
-    // Rigging Info
-    LLJointRiggingInfo mRiggingInfo;
-    LLJointRiggingInfo& getRiggingInfo();
-    const LLJointRiggingInfo& getRiggingInfo() const;
-    
 	void updatePos(const std::string& av_info);
 	void updateScale(const std::string& av_info);
 
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index dab566da564..379c3ee9eaf 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -25,6 +25,7 @@ set(llmath_SOURCE_FILES
     lloctree.cpp
     llperlin.cpp
     llquaternion.cpp
+    llrigginginfo.cpp
     llrect.cpp
     llsphere.cpp
     llvector4a.cpp
@@ -71,6 +72,7 @@ set(llmath_HEADER_FILES
     llquaternion2.h
     llquaternion2.inl
     llrect.h
+    llrigginginfo.h
     llsimdmath.h
     llsimdtypes.h
     llsimdtypes.inl
diff --git a/indra/llmath/llrigginginfo.cpp b/indra/llmath/llrigginginfo.cpp
new file mode 100644
index 00000000000..925179c2baa
--- /dev/null
+++ b/indra/llmath/llrigginginfo.cpp
@@ -0,0 +1,96 @@
+/**
+* @file llrigginginfo.cpp
+* @brief  Functions for tracking rigged box extents
+*
+* $LicenseInfo:firstyear=2018&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llmath.h"
+#include "llrigginginfo.h"
+
+//-----------------------------------------------------------------------------
+// LLJointRiggingInfo
+//-----------------------------------------------------------------------------
+LLJointRiggingInfo::LLJointRiggingInfo()
+{
+    mRiggedExtents[0].clear();
+    mRiggedExtents[1].clear();
+    mIsRiggedTo = false;
+}
+
+bool LLJointRiggingInfo::isRiggedTo() const
+{
+    return mIsRiggedTo;
+}
+
+void LLJointRiggingInfo::setIsRiggedTo(bool val)
+{
+    mIsRiggedTo = val;
+}
+    
+LLVector4a *LLJointRiggingInfo::getRiggedExtents()
+{
+    return mRiggedExtents;
+}
+
+const LLVector4a *LLJointRiggingInfo::getRiggedExtents() const
+{
+    return mRiggedExtents;
+}
+
+// Combine two rigging info states.
+// - isRiggedTo if either of the source infos are rigged to
+// - box is union of the two sources
+void LLJointRiggingInfo::merge(const LLJointRiggingInfo& other)
+{
+    if (other.mIsRiggedTo)
+    {
+        if (mIsRiggedTo)
+        {
+            // Combine existing boxes
+            update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[0]);
+            update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[1]);
+        }
+        else
+        {
+            // Initialize box
+            mIsRiggedTo = true;
+            mRiggedExtents[0] = other.mRiggedExtents[0];
+            mRiggedExtents[1] = other.mRiggedExtents[1];
+        }
+    }
+}
+
+void mergeRigInfoTab(joint_rig_info_tab& dst, const joint_rig_info_tab& src)
+{
+    // Size should be either LL_CHARACTER_MAX_ANIMATED_JOINTS, or 0 if
+    // no data. Not necessarily the same for both inputs.
+    if (src.size() > dst.size())
+    {
+        dst.resize(src.size());
+    }
+    S32 size = llmin(src.size(), dst.size());
+    for (S32 i=0; i<size; i++)
+    {
+        dst[i].merge(src[i]);
+    }
+}
diff --git a/indra/llmath/llrigginginfo.h b/indra/llmath/llrigginginfo.h
new file mode 100644
index 00000000000..18da905abb6
--- /dev/null
+++ b/indra/llmath/llrigginginfo.h
@@ -0,0 +1,55 @@
+/**
+* @file llrigginginfo.h
+* @brief  Functions for tracking rigged box extents
+*
+* $LicenseInfo:firstyear=2018&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+// Stores information related to associated rigged mesh vertices
+// This lives in llmath because llvolume lives in llmath.
+
+#ifndef	LL_LLRIGGINGINFO_H
+#define	LL_LLRIGGINGINFO_H
+
+// Extents are in joint space
+// isRiggedTo is based on the state of all currently associated rigged meshes
+class LLJointRiggingInfo
+{
+public:
+    LLJointRiggingInfo();
+    bool isRiggedTo() const;
+    void setIsRiggedTo(bool val);
+    LLVector4a *getRiggedExtents();
+    const LLVector4a *getRiggedExtents() const;
+    void merge(const LLJointRiggingInfo& other);
+private:
+	LL_ALIGN_16(LLVector4a mRiggedExtents[2]);
+    bool mIsRiggedTo;
+};
+
+// For storing all the rigging info associated with a given avatar or
+// object, keyed by joint_num.
+typedef std::vector<LLJointRiggingInfo> joint_rig_info_tab;
+
+void mergeRigInfoTab(joint_rig_info_tab& dst, const joint_rig_info_tab& src);
+
+#endif
diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp
index dba690242ad..7adb2fa8d25 100644
--- a/indra/newview/llskinningutil.cpp
+++ b/indra/newview/llskinningutil.cpp
@@ -216,3 +216,28 @@ void LLSkinningUtil::getPerVertexSkinMatrix(
     llassert(valid_weights);
 }
 
+//static
+void LLSkinningUtil::initIsRiggedTo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, joint_rig_info_tab& rig_info_tab) 
+{
+    S32 rigged_count = 0;
+    rig_info_tab.resize(LL_CHARACTER_MAX_ANIMATED_JOINTS);
+    for (U32 j = 0; j < skin->mJointNames.size(); ++j)
+    {
+        LLJoint *joint = NULL;
+        if (skin->mJointNums[j] == -1)
+        {
+            joint = avatar->getJoint(skin->mJointNames[j]);
+            if (joint)
+            {
+                skin->mJointNums[j] = joint->getJointNum();
+            }
+        }
+        S32 joint_num = skin->mJointNums[j];
+        if (joint_num != -1)
+        {
+            rig_info_tab[joint_num].setIsRiggedTo(true);
+            rigged_count++;
+        }
+    }
+    //LL_INFOS() << "rigged_count " << rigged_count << LL_ENDL;
+}
diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h
index 135b25d4d21..3eba3dc93af 100644
--- a/indra/newview/llskinningutil.h
+++ b/indra/newview/llskinningutil.h
@@ -31,6 +31,9 @@ class LLVOAvatar;
 class LLMeshSkinInfo;
 class LLMatrix4a;
 
+#include "llrigginginfo.h"
+
+// This should probably just be a namespace
 class LLSkinningUtil
 {
 public:
@@ -42,6 +45,7 @@ class LLSkinningUtil
     static void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
     static void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
     static void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints);
+    static void initIsRiggedTo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, joint_rig_info_tab& rig_info_tab); 
 };
 
 #endif
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 9552d4e99eb..b9840f629b7 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -42,6 +42,7 @@
 #include "v3math.h"
 #include "llvertexbuffer.h"
 #include "llbbox.h"
+#include "llrigginginfo.h"
 
 class LLAgent;			// TODO: Get rid of this.
 class LLAudioSource;
@@ -877,6 +878,10 @@ class LLViewerObject
 	BOOL getLastUpdateCached() const;
 	void setLastUpdateCached(BOOL last_update_cached);
 
+    virtual void updateRiggingInfo() {}
+
+    joint_rig_info_tab mJointRiggingInfoTab;
+
 private:
 	LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.
 	EObjectUpdateType	mLastUpdateType;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 277f8e45332..50a012ad82b 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1355,17 +1355,23 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
 	}
 
     // Stretch bounding box by rigged mesh joint boxes
+    updateRiggingInfo();
     for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++)
     {
         LLJoint *joint = getJoint(joint_num);
-
-        // FIXME TEMP HACK FOR TESTING
-        if (joint)
+        LLJointRiggingInfo *rig_info = NULL;
+        if (joint_num < mJointRiggingInfoTab.size())
         {
-            joint->getRiggingInfo().setIsRiggedTo(true);
+            rig_info = &mJointRiggingInfoTab[joint_num];
         }
 
-        if (joint && joint->getRiggingInfo().isRiggedTo())
+        // FIXME TEMP HACK FOR TESTING
+        //if (joint)
+        //{
+        //    rig_info.setIsRiggedTo(true);
+        //}
+
+        if (joint && rig_info && rig_info->isRiggedTo())
         {
             LLViewerJointAttachment *as_joint_attach = dynamic_cast<LLViewerJointAttachment*>(joint);
             if (as_joint_attach && as_joint_attach->getIsHUDAttachment())
@@ -1376,7 +1382,7 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
             LLMatrix4a mat;
             LLVector4a new_extents[2];
             mat.loadu(joint->getWorldMatrix());
-            matMulBoundBox(mat, joint->getRiggingInfo().getRiggedExtents(), new_extents);
+            matMulBoundBox(mat, rig_info->getRiggedExtents(), new_extents);
             update_min_max(newMin, newMax, new_extents[0]);
             update_min_max(newMin, newMax, new_extents[1]);
             //if (isSelf())
@@ -5777,6 +5783,7 @@ bool LLVOAvatar::getRiggedMeshID(LLViewerObject* pVO, LLUUID& mesh_id)
 	return false;
 }
 
+// AXON update to use LLRiggingInfo
 bool LLVOAvatar::jointIsRiggedTo(const std::string& joint_name)
 {
 	for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
@@ -5798,6 +5805,7 @@ bool LLVOAvatar::jointIsRiggedTo(const std::string& joint_name)
     return false;
 }
 
+// AXON update to use LLRiggingInfo
 bool LLVOAvatar::jointIsRiggedTo(const std::string& joint_name, const LLViewerObject *vo)
 {
 	// Process all children
@@ -9420,11 +9428,80 @@ BOOL LLVOAvatar::updateLOD()
 	return res;
 }
 
-void LLVOAvatar::updateLODRiggedAttachments( void )
+void LLVOAvatar::updateLODRiggedAttachments()
 {
 	updateLOD();
 	rebuildRiggedAttachments();
 }
+
+S32 countRigInfoTab(joint_rig_info_tab& tab)
+{
+    S32 count=0;
+    for (S32 i=0; i<tab.size(); i++)
+    {
+        if (tab[i].isRiggedTo())
+        {
+            count++;
+        }
+    }
+    return count;
+}
+
+// virtual
+void LLVOAvatar::updateRiggingInfo()
+{
+    mJointRiggingInfoTab.clear();
+    //LL_INFOS() << "starting update rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
+	for ( attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter )
+	{
+		LLViewerJointAttachment* attachment = iter->second;
+		LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_end = attachment->mAttachedObjects.end();
+		
+		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_iter = attachment->mAttachedObjects.begin();
+			 attach_iter != attach_end; ++attach_iter)
+		{
+			LLViewerObject* attached_object =  *attach_iter;
+            attached_object->updateRiggingInfo();
+            mergeRigInfoTab(mJointRiggingInfoTab, attached_object->mJointRiggingInfoTab);
+            //LL_INFOS() << "after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
+            
+
+            LLViewerObject::const_child_list_t& children = attached_object->getChildren();
+            for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
+                 it != children.end(); ++it)
+            {
+                LLViewerObject *childp = *it;
+                childp->updateRiggingInfo();
+                mergeRigInfoTab(mJointRiggingInfoTab, childp->mJointRiggingInfoTab);
+                //LL_INFOS() << "after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
+            }
+        }
+	}
+    LLControlAvatar *control_av = dynamic_cast<LLControlAvatar*>(this);
+    if (control_av)
+    {
+        LLVOVolume *volp = control_av->mRootVolp;
+        if (volp && !volp->isAttachment())
+        {
+            volp->updateRiggingInfo();
+            mergeRigInfoTab(mJointRiggingInfoTab, volp->mJointRiggingInfoTab);
+            //LL_INFOS() << "cav after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
+
+            LLViewerObject::const_child_list_t& children = volp->getChildren();
+            for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
+                 it != children.end(); ++it)
+            {
+                LLViewerObject *childp = *it;
+                childp->updateRiggingInfo();
+                mergeRigInfoTab(mJointRiggingInfoTab, childp->mJointRiggingInfoTab);
+                //LL_INFOS() << "cav after merge rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
+            }
+        }
+    }
+
+    //LL_INFOS() << "done update rig count is " << countRigInfoTab(mJointRiggingInfoTab) << LL_ENDL;
+}
+
 U32 LLVOAvatar::getPartitionType() const
 { 
 	// Avatars merely exist as drawables in the bridge partition
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index cccf857eba8..59f88490d0a 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -49,6 +49,7 @@
 #include "lldriverparam.h"
 #include "llviewertexlayer.h"
 #include "material_codes.h"		// LL_MCODE_END
+#include "llrigginginfo.h"
 #include "llviewerstats.h"
 #include "llvovolume.h"
 #include "llavatarrendernotifier.h"
@@ -216,7 +217,12 @@ class LLVOAvatar :
     void                    getAttachmentOverrideNames(std::set<std::string>& pos_names, 
                                                        std::set<std::string>& scale_names) const;
 
+    // virtual
+    void 					updateRiggingInfo();
+
     std::set<LLUUID>		mActiveOverrideMeshes;
+
+    
     
 	/*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 b60ff6d2805..321ea22ff9a 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3564,6 +3564,21 @@ void LLVOVolume::afterReparent()
     }
 }
 
+//----------------------------------------------------------------------------
+void LLVOVolume::updateRiggingInfo()
+{
+    if (isRiggedMesh())
+    {
+        const LLMeshSkinInfo* skin = getSkinInfo();
+        LLVOAvatar *avatar = getAvatar();
+        if (skin && avatar)
+        {
+            LLSkinningUtil::initIsRiggedTo(skin, avatar, mJointRiggingInfoTab);
+        }
+        // AXON add bbox processing from volume faces.
+    }
+}
+
 //----------------------------------------------------------------------------
 
 void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point)
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index ebf92acc4fe..d77c2f231b4 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -282,6 +282,9 @@ class LLVOVolume : public LLViewerObject
     virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent);
     virtual void afterReparent();
 
+    //virtual
+    void updateRiggingInfo();
+    
     // Functions that deal with media, or media navigation
     
     // Update this object's media data with the given media data array
-- 
GitLab