summaryrefslogtreecommitdiff
path: root/indra/llcharacter/lljoint.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 21:25:21 +0200
committerAndrey Lihatskiy <alihatskiy@productengine.com>2024-05-22 22:40:26 +0300
commite2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch)
tree1bb897489ce524986f6196201c10ac0d8861aa5f /indra/llcharacter/lljoint.cpp
parent069ea06848f766466f1a281144c82a0f2bd79f3a (diff)
Fix line endlings
Diffstat (limited to 'indra/llcharacter/lljoint.cpp')
-rw-r--r--indra/llcharacter/lljoint.cpp2086
1 files changed, 1043 insertions, 1043 deletions
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 888980ac11..34aea19d6c 100644
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -1,1043 +1,1043 @@
-/**
- * @file lljoint.cpp
- * @brief Implementation of LLJoint class.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-//-----------------------------------------------------------------------------
-// Header Files
-//-----------------------------------------------------------------------------
-#include "linden_common.h"
-
-#include "lljoint.h"
-
-#include "llmath.h"
-#include "llcallstack.h"
-#include <boost/algorithm/string.hpp>
-
-S32 LLJoint::sNumUpdates = 0;
-S32 LLJoint::sNumTouches = 0;
-
-template <class T>
-bool attachment_map_iter_compare_key(const T& a, const T& b)
-{
- return a.first < b.first;
-}
-
-bool LLVector3OverrideMap::findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const
-{
- pos = LLVector3(0,0,0);
- mesh_id = LLUUID();
- bool found = false;
-
- map_type::const_iterator it = std::max_element(m_map.begin(),
- m_map.end(),
- attachment_map_iter_compare_key<map_type::value_type>);
- if (it != m_map.end())
- {
- found = true;
- pos = it->second;
- mesh_id = it->first;
- }
- return found;
-}
-
-void LLVector3OverrideMap::showJointVector3Overrides( std::ostringstream& os ) const
-{
- map_type::const_iterator max_it = std::max_element(m_map.begin(),
- m_map.end(),
- attachment_map_iter_compare_key<map_type::value_type>);
- for (const map_type::value_type& pos_pair : m_map)
- {
- const LLVector3& pos = pos_pair.second;
- os << " " << "[" << pos_pair.first <<": " << pos << "]" << ((pos_pair==(*max_it)) ? "*" : "");
- }
-}
-
-U32 LLVector3OverrideMap::count() const
-{
- return m_map.size();
-}
-
-void LLVector3OverrideMap::add(const LLUUID& mesh_id, const LLVector3& pos)
-{
- m_map[mesh_id] = pos;
-}
-
-bool LLVector3OverrideMap::remove(const LLUUID& mesh_id)
-{
- U32 remove_count = m_map.erase(mesh_id);
- return (remove_count > 0);
-}
-
-void LLVector3OverrideMap::clear()
-{
- m_map.clear();
-}
-
-//-----------------------------------------------------------------------------
-// LLJoint()
-// Class Constructor
-//-----------------------------------------------------------------------------
-
-
-void LLJoint::init()
-{
- mName = "unnamed";
- mParent = NULL;
- mXform.setScaleChildOffset(true);
- mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
- mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
- mUpdateXform = true;
- mSupport = SUPPORT_BASE;
- mEnd = LLVector3(0.0f, 0.0f, 0.0f);
-}
-
-LLJoint::LLJoint() :
- mJointNum(-1)
-{
- init();
- touch();
-}
-
-LLJoint::LLJoint(S32 joint_num) :
- mJointNum(joint_num)
-{
- init();
- touch();
-}
-
-//-----------------------------------------------------------------------------
-// LLJoint()
-// Class Constructor
-//-----------------------------------------------------------------------------
-LLJoint::LLJoint(const std::string &name, LLJoint *parent) :
- mJointNum(-2)
-{
- init();
- mUpdateXform = false;
-
- setName(name);
- if (parent)
- {
- parent->addChild( this );
- }
- touch();
-}
-
-//-----------------------------------------------------------------------------
-// ~LLJoint()
-// Class Destructor
-//-----------------------------------------------------------------------------
-LLJoint::~LLJoint()
-{
- if (mParent)
- {
- mParent->removeChild( this );
- }
- removeAllChildren();
-}
-
-
-//-----------------------------------------------------------------------------
-// setup()
-//-----------------------------------------------------------------------------
-void LLJoint::setup(const std::string &name, LLJoint *parent)
-{
- setName(name);
- if (parent)
- {
- parent->addChild( this );
- }
-}
-
-//-----------------------------------------------------------------------------
-// setSupport()
-//-----------------------------------------------------------------------------
-void LLJoint::setSupport(const std::string& support_name)
-{
- if (support_name == "extended")
- {
- setSupport(SUPPORT_EXTENDED);
- }
- else if (support_name == "base")
- {
- setSupport(SUPPORT_BASE);
- }
- else
- {
- LL_WARNS() << "unknown support string " << support_name << LL_ENDL;
- setSupport(SUPPORT_BASE);
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// touch()
-// Sets all dirty flags for all children, recursively.
-//-----------------------------------------------------------------------------
-void LLJoint::touch(U32 flags)
-{
- if ((flags | mDirtyFlags) != mDirtyFlags)
- {
- sNumTouches++;
- mDirtyFlags |= flags;
- U32 child_flags = flags;
- if (flags & ROTATION_DIRTY)
- {
- child_flags |= POSITION_DIRTY;
- }
-
- for (LLJoint* joint : mChildren)
- {
- joint->touch(child_flags);
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// setJointNum()
-//-----------------------------------------------------------------------------
-void LLJoint::setJointNum(S32 joint_num)
-{
- mJointNum = joint_num;
- if (mJointNum + 2 >= LL_CHARACTER_MAX_ANIMATED_JOINTS)
- {
- LL_INFOS() << "LL_CHARACTER_MAX_ANIMATED_JOINTS needs to be increased" << LL_ENDL;
- LL_ERRS() << "joint_num " << joint_num << " + 2 is too large for " << LL_CHARACTER_MAX_ANIMATED_JOINTS << LL_ENDL;
- }
-}
-//-----------------------------------------------------------------------------
-// getRoot()
-//-----------------------------------------------------------------------------
-LLJoint *LLJoint::getRoot()
-{
- if ( getParent() == NULL )
- {
- return this;
- }
- return getParent()->getRoot();
-}
-
-
-//-----------------------------------------------------------------------------
-// findJoint()
-//-----------------------------------------------------------------------------
-LLJoint *LLJoint::findJoint( const std::string &name )
-{
- if (name == getName())
- return this;
-
- for (LLJoint* joint : mChildren)
- {
- LLJoint *found = joint->findJoint(name);
- if (found)
- {
- return found;
- }
- }
-
- return NULL;
-}
-
-
-//--------------------------------------------------------------------
-// addChild()
-//--------------------------------------------------------------------
-void LLJoint::addChild(LLJoint* joint)
-{
- if (joint->mParent)
- joint->mParent->removeChild(joint);
-
- mChildren.push_back(joint);
- joint->mXform.setParent(&mXform);
- joint->mParent = this;
- joint->touch();
-}
-
-
-//--------------------------------------------------------------------
-// removeChild()
-//--------------------------------------------------------------------
-void LLJoint::removeChild(LLJoint* joint)
-{
- joints_t::iterator iter = std::find(mChildren.begin(), mChildren.end(), joint);
- if (iter != mChildren.end())
- {
- mChildren.erase(iter);
-
- joint->mXform.setParent(NULL);
- joint->mParent = NULL;
- joint->touch();
- }
-}
-
-
-//--------------------------------------------------------------------
-// removeAllChildren()
-//--------------------------------------------------------------------
-void LLJoint::removeAllChildren()
-{
- for (LLJoint* joint : mChildren)
- {
- if (joint)
- {
- joint->mXform.setParent(NULL);
- joint->mParent = NULL;
- joint->touch();
- //delete joint;
- }
- }
- mChildren.clear();
-}
-
-
-//--------------------------------------------------------------------
-// getPosition()
-//--------------------------------------------------------------------
-const LLVector3& LLJoint::getPosition()
-{
- return mXform.getPosition();
-}
-
-bool do_debug_joint(const std::string& name)
-{
- if (std::find(LLJoint::s_debugJointNames.begin(), LLJoint::s_debugJointNames.end(),name) != LLJoint::s_debugJointNames.end())
- {
- return true;
- }
- return false;
-}
-
-//--------------------------------------------------------------------
-// setPosition()
-//--------------------------------------------------------------------
-void LLJoint::setPosition( const LLVector3& requested_pos, bool apply_attachment_overrides )
-{
- LLVector3 pos(requested_pos);
-
- LLVector3 active_override;
- LLUUID mesh_id;
- if (apply_attachment_overrides && m_attachmentPosOverrides.findActiveOverride(mesh_id,active_override))
- {
- if (pos != active_override && do_debug_joint(getName()))
- {
- LLScopedContextString str("setPosition");
- LL_DEBUGS("Avatar") << " joint " << getName() << " requested_pos " << requested_pos
- << " overriden by attachment " << active_override << LL_ENDL;
- }
- pos = active_override;
- }
- if ((pos != getPosition()) && do_debug_joint(getName()))
- {
- LLScopedContextString str("setPosition");
- LLCallStack cs;
- LLContextStatus con_status;
- LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL;
- LL_DEBUGS("Avatar") << "CONTEXT:\n" << "====================\n" << con_status << "====================" << LL_ENDL;
- LL_DEBUGS("Avatar") << "STACK:\n" << "====================\n" << cs << "====================" << LL_ENDL;
- }
- if (pos != getPosition())
- {
- mXform.setPosition(pos);
- touch(MATRIX_DIRTY | POSITION_DIRTY);
- }
-}
-
-void LLJoint::setDefaultPosition( const LLVector3& pos )
-{
- mDefaultPosition = pos;
-}
-
-const LLVector3& LLJoint::getDefaultPosition() const
-{
- return mDefaultPosition;
-}
-
-void LLJoint::setDefaultScale( const LLVector3& scale )
-{
- mDefaultScale = scale;
-}
-
-const LLVector3& LLJoint::getDefaultScale() const
-{
- return mDefaultScale;
-}
-
-void showJointPosOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info )
-{
- std::ostringstream os;
- os << joint.m_posBeforeOverrides;
- joint.m_attachmentPosOverrides.showJointVector3Overrides(os);
- LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL;
-}
-
-void showJointScaleOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info )
-{
- std::ostringstream os;
- os << joint.m_scaleBeforeOverrides;
- joint.m_attachmentScaleOverrides.showJointVector3Overrides(os);
- LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL;
-}
-
-bool LLJoint::aboveJointPosThreshold(const LLVector3& pos) const
-{
- LLVector3 diff = pos - getDefaultPosition();
- const F32 max_joint_pos_offset = LL_JOINT_TRESHOLD_POS_OFFSET; // 0.1 mm
- return diff.lengthSquared() > max_joint_pos_offset * max_joint_pos_offset;
-}
-
-bool LLJoint::aboveJointScaleThreshold(const LLVector3& scale) const
-{
- LLVector3 diff = scale - getDefaultScale();
- const F32 max_joint_scale_offset = 0.0001f; // 0.1 mm
- return diff.lengthSquared() > max_joint_scale_offset * max_joint_scale_offset;
-}
-
-//--------------------------------------------------------------------
-// addAttachmentPosOverride()
-//--------------------------------------------------------------------
-void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed )
-{
- active_override_changed = false;
- if (mesh_id.isNull())
- {
- return;
- }
- LLVector3 before_pos;
- LLUUID before_mesh_id;
- bool has_active_override_before = hasAttachmentPosOverride( before_pos, before_mesh_id );
- if (!m_attachmentPosOverrides.count())
- {
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_posBeforeOverrides " << getPosition() << LL_ENDL;
- }
- m_posBeforeOverrides = getPosition();
- }
- m_attachmentPosOverrides.add(mesh_id,pos);
- LLVector3 after_pos;
- LLUUID after_mesh_id;
- hasAttachmentPosOverride(after_pos, after_mesh_id);
- if (!has_active_override_before || (after_pos != before_pos))
- {
- active_override_changed = true;
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentPosOverride for mesh " << mesh_id << " pos " << pos << LL_ENDL;
- }
- updatePos(av_info);
- }
-}
-
-//--------------------------------------------------------------------
-// removeAttachmentPosOverride()
-//--------------------------------------------------------------------
-void LLJoint::removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed )
-{
- active_override_changed = false;
- if (mesh_id.isNull())
- {
- return;
- }
- LLVector3 before_pos;
- LLUUID before_mesh_id;
- hasAttachmentPosOverride( before_pos, before_mesh_id );
- if (m_attachmentPosOverrides.remove(mesh_id))
- {
- LLVector3 after_pos;
- LLUUID after_mesh_id;
- bool has_active_override_after = hasAttachmentPosOverride(after_pos, after_mesh_id);
- if (!has_active_override_after || (after_pos != before_pos))
- {
- active_override_changed = true;
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
- << " removeAttachmentPosOverride for " << mesh_id << LL_ENDL;
- showJointPosOverrides(*this, "remove", av_info);
- }
- updatePos(av_info);
- }
- }
-}
-
-//--------------------------------------------------------------------
- // hasAttachmentPosOverride()
- //--------------------------------------------------------------------
-bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const
-{
- return m_attachmentPosOverrides.findActiveOverride(mesh_id,pos);
-}
-
-//--------------------------------------------------------------------
-// clearAttachmentPosOverrides()
-//--------------------------------------------------------------------
-void LLJoint::clearAttachmentPosOverrides()
-{
- if (m_attachmentPosOverrides.count())
- {
- m_attachmentPosOverrides.clear();
- setPosition(m_posBeforeOverrides);
- }
-}
-
-//--------------------------------------------------------------------
-// getAllAttachmentPosOverrides()
-//--------------------------------------------------------------------
-void LLJoint::getAllAttachmentPosOverrides(S32& num_pos_overrides,
- std::set<LLVector3>& distinct_pos_overrides) const
-{
- num_pos_overrides = m_attachmentPosOverrides.count();
- for (const LLVector3OverrideMap::map_type::value_type& pos_override_pair : m_attachmentPosOverrides.getMap())
- {
- distinct_pos_overrides.insert(pos_override_pair.second);
- }
-}
-
-//--------------------------------------------------------------------
-// getAllAttachmentScaleOverrides()
-//--------------------------------------------------------------------
-void LLJoint::getAllAttachmentScaleOverrides(S32& num_scale_overrides,
- std::set<LLVector3>& distinct_scale_overrides) const
-{
- num_scale_overrides = m_attachmentScaleOverrides.count();
- for (const LLVector3OverrideMap::map_type::value_type& scale_override_pair : m_attachmentScaleOverrides.getMap())
- {
- distinct_scale_overrides.insert(scale_override_pair.second);
- }
-}
-
-//--------------------------------------------------------------------
-// showAttachmentPosOverrides()
-//--------------------------------------------------------------------
-void LLJoint::showAttachmentPosOverrides(const std::string& av_info) const
-{
- LLVector3 active_override;
- bool has_active_override;
- LLUUID mesh_id;
- has_active_override = m_attachmentPosOverrides.findActiveOverride(mesh_id,active_override);
- U32 count = m_attachmentPosOverrides.count();
- if (count==1)
- {
- LLVector3OverrideMap::map_type::const_iterator it = m_attachmentPosOverrides.getMap().begin();
- std::string highlight = (has_active_override && (it->second == active_override)) ? "*" : "";
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
- << " has single attachment pos override " << highlight << "" << it->second << " default " << mDefaultPosition << LL_ENDL;
- }
- else if (count>1)
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " has " << count << " attachment pos overrides" << LL_ENDL;
- std::set<LLVector3> distinct_offsets;
- for (const LLVector3OverrideMap::map_type::value_type& pos_override_pair : m_attachmentPosOverrides.getMap())
- {
- distinct_offsets.insert(pos_override_pair.second);
- }
- if (distinct_offsets.size()>1)
- {
- LL_DEBUGS("Avatar") << "CONFLICTS, " << distinct_offsets.size() << " different values" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("Avatar") << "no conflicts" << LL_ENDL;
- }
- for (const LLVector3& offset : distinct_offsets)
- {
- std::string highlight = (has_active_override && offset == active_override) ? "*" : "";
- LL_DEBUGS("Avatar") << " POS " << highlight << "" << offset << " default " << mDefaultPosition << LL_ENDL;
- }
- }
-}
-
-//--------------------------------------------------------------------
-// updatePos()
-//--------------------------------------------------------------------
-void LLJoint::updatePos(const std::string& av_info)
-{
- LLVector3 pos, found_pos;
- LLUUID mesh_id;
- if (m_attachmentPosOverrides.findActiveOverride(mesh_id,found_pos))
- {
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentPosOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL;
- }
- pos = found_pos;
- }
- else
- {
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL;
- }
- pos = m_posBeforeOverrides;
- }
- setPosition(pos);
-}
-
-//--------------------------------------------------------------------
-// updateScale()
-//--------------------------------------------------------------------
-void LLJoint::updateScale(const std::string& av_info)
-{
- LLVector3 scale, found_scale;
- LLUUID mesh_id;
- if (m_attachmentScaleOverrides.findActiveOverride(mesh_id,found_scale))
- {
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updateScale, winner of " << m_attachmentScaleOverrides.count() << " is mesh " << mesh_id << " scale " << found_scale << LL_ENDL;
- }
- scale = found_scale;
- }
- else
- {
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updateScale, winner is scaleBeforeOverrides " << m_scaleBeforeOverrides << LL_ENDL;
- }
- scale = m_scaleBeforeOverrides;
- }
- setScale(scale);
-}
-
-//--------------------------------------------------------------------
-// addAttachmentScaleOverride()
-//--------------------------------------------------------------------
-void LLJoint::addAttachmentScaleOverride( const LLVector3& scale, const LLUUID& mesh_id, const std::string& av_info )
-{
- if (mesh_id.isNull())
- {
- return;
- }
- if (!m_attachmentScaleOverrides.count())
- {
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_scaleBeforeOverrides " << getScale() << LL_ENDL;
- }
- m_scaleBeforeOverrides = getScale();
- }
- m_attachmentScaleOverrides.add(mesh_id,scale);
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentScaleOverride for mesh " << mesh_id << " scale " << scale << LL_ENDL;
- }
- updateScale(av_info);
-}
-
-//--------------------------------------------------------------------
-// removeAttachmentScaleOverride()
-//--------------------------------------------------------------------
-void LLJoint::removeAttachmentScaleOverride( const LLUUID& mesh_id, const std::string& av_info )
-{
- if (mesh_id.isNull())
- {
- return;
- }
- if (m_attachmentScaleOverrides.remove(mesh_id))
- {
- if (do_debug_joint(getName()))
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
- << " removeAttachmentScaleOverride for " << mesh_id << LL_ENDL;
- showJointScaleOverrides(*this, "remove", av_info);
- }
- updateScale(av_info);
- }
-}
-
-//--------------------------------------------------------------------
- // hasAttachmentScaleOverride()
- //--------------------------------------------------------------------
-bool LLJoint::hasAttachmentScaleOverride( LLVector3& scale, LLUUID& mesh_id ) const
-{
- return m_attachmentScaleOverrides.findActiveOverride(mesh_id,scale);
-}
-
-//--------------------------------------------------------------------
-// clearAttachmentScaleOverrides()
-//--------------------------------------------------------------------
-void LLJoint::clearAttachmentScaleOverrides()
-{
- if (m_attachmentScaleOverrides.count())
- {
- m_attachmentScaleOverrides.clear();
- setScale(m_scaleBeforeOverrides);
- }
-}
-
-//--------------------------------------------------------------------
-// showAttachmentScaleOverrides()
-//--------------------------------------------------------------------
-void LLJoint::showAttachmentScaleOverrides(const std::string& av_info) const
-{
- LLVector3 active_override;
- bool has_active_override;
- LLUUID mesh_id;
- has_active_override = m_attachmentScaleOverrides.findActiveOverride(mesh_id,active_override);
- U32 count = m_attachmentScaleOverrides.count();
- if (count==1)
- {
- LLVector3OverrideMap::map_type::const_iterator it = m_attachmentScaleOverrides.getMap().begin();
- std::string highlight = (has_active_override && (it->second == active_override)) ? "*" : "";
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
- << " has single attachment scale override " << highlight << "" << it->second << " default " << mDefaultScale << LL_ENDL;
- }
- else if (count>1)
- {
- LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " has " << count << " attachment scale overrides" << LL_ENDL;
- std::set<LLVector3> distinct_offsets;
- for (const LLVector3OverrideMap::map_type::value_type& scale_override_pair : m_attachmentScaleOverrides.getMap())
- {
- distinct_offsets.insert(scale_override_pair.second);
- }
- if (distinct_offsets.size()>1)
- {
- LL_DEBUGS("Avatar") << "CONFLICTS, " << distinct_offsets.size() << " different values" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("Avatar") << "no conflicts" << LL_ENDL;
- }
- for (const LLVector3& offset : distinct_offsets)
- {
- std::string highlight = (has_active_override && offset == active_override) ? "*" : "";
- LL_DEBUGS("Avatar") << " POS " << highlight << "" << offset << " default " << mDefaultScale << LL_ENDL;
- }
- }
-}
-
-// init static
-LLJoint::debug_joint_name_t LLJoint::s_debugJointNames = debug_joint_name_t();
-
-//--------------------------------------------------------------------
-// setDebugJointNames
-//--------------------------------------------------------------------
-void LLJoint::setDebugJointNames(const debug_joint_name_t& names)
-{
- s_debugJointNames = names;
-}
-void LLJoint::setDebugJointNames(const std::string& names_string)
-{
- debug_joint_name_t names;
- boost::split(names, names_string, boost::is_any_of(" :,"));
- setDebugJointNames(names);
-}
-
-//--------------------------------------------------------------------
-// getWorldPosition()
-//--------------------------------------------------------------------
-LLVector3 LLJoint::getWorldPosition()
-{
- updateWorldPRSParent();
- return mXform.getWorldPosition();
-}
-
-//-----------------------------------------------------------------------------
-// getLastWorldPosition()
-//-----------------------------------------------------------------------------
-LLVector3 LLJoint::getLastWorldPosition()
-{
- return mXform.getWorldPosition();
-}
-//--------------------------------------------------------------------
-// setWorldPosition()
-//--------------------------------------------------------------------
-void LLJoint::setWorldPosition( const LLVector3& pos )
-{
- if (mParent == NULL)
- {
- this->setPosition( pos );
- return;
- }
-
- LLMatrix4 temp_matrix = getWorldMatrix();
- temp_matrix.mMatrix[VW][VX] = pos.mV[VX];
- temp_matrix.mMatrix[VW][VY] = pos.mV[VY];
- temp_matrix.mMatrix[VW][VZ] = pos.mV[VZ];
-
- LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
- LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
-
- temp_matrix *= invParentWorldMatrix;
-
- LLVector3 localPos( temp_matrix.mMatrix[VW][VX],
- temp_matrix.mMatrix[VW][VY],
- temp_matrix.mMatrix[VW][VZ] );
-
- setPosition( localPos );
-}
-
-
-//--------------------------------------------------------------------
-// getRotation()
-//--------------------------------------------------------------------
-const LLQuaternion& LLJoint::getRotation()
-{
- return mXform.getRotation();
-}
-
-
-//--------------------------------------------------------------------
-// setRotation()
-//--------------------------------------------------------------------
-void LLJoint::setRotation( const LLQuaternion& rot )
-{
- if (rot.isFinite())
- {
- // if (mXform.getRotation() != rot)
- {
- mXform.setRotation(rot);
- touch(MATRIX_DIRTY | ROTATION_DIRTY);
- }
- }
-}
-
-
-//--------------------------------------------------------------------
-// getWorldRotation()
-//--------------------------------------------------------------------
-LLQuaternion LLJoint::getWorldRotation()
-{
- updateWorldPRSParent();
-
- return mXform.getWorldRotation();
-}
-
-//-----------------------------------------------------------------------------
-// getLastWorldRotation()
-//-----------------------------------------------------------------------------
-LLQuaternion LLJoint::getLastWorldRotation()
-{
- return mXform.getWorldRotation();
-}
-
-//--------------------------------------------------------------------
-// setWorldRotation()
-//--------------------------------------------------------------------
-void LLJoint::setWorldRotation( const LLQuaternion& rot )
-{
- if (mParent == NULL)
- {
- this->setRotation( rot );
- return;
- }
-
- LLMatrix4 temp_mat(rot);
-
- LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
- parentWorldMatrix.mMatrix[VW][VX] = 0;
- parentWorldMatrix.mMatrix[VW][VY] = 0;
- parentWorldMatrix.mMatrix[VW][VZ] = 0;
-
- LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
-
- temp_mat *= invParentWorldMatrix;
-
- setRotation(LLQuaternion(temp_mat));
-}
-
-
-//--------------------------------------------------------------------
-// getScale()
-//--------------------------------------------------------------------
-const LLVector3& LLJoint::getScale()
-{
- return mXform.getScale();
-}
-
-//--------------------------------------------------------------------
-// setScale()
-//--------------------------------------------------------------------
-void LLJoint::setScale( const LLVector3& requested_scale, bool apply_attachment_overrides )
-{
- LLVector3 scale(requested_scale);
- LLUUID mesh_id;
- LLVector3 active_override;
- if (apply_attachment_overrides && m_attachmentScaleOverrides.findActiveOverride(mesh_id,active_override))
- {
- if (scale != active_override && do_debug_joint(getName()))
- {
- LLScopedContextString str("setScale");
- LL_DEBUGS("Avatar") << " joint " << getName() << " requested_scale " << requested_scale
- << " overriden by attachment " << active_override << LL_ENDL;
- }
- scale = active_override;
- }
- if ((mXform.getScale() != scale) && do_debug_joint(getName()))
- {
- LLScopedContextString str("setScale");
- LLCallStack cs;
- LLContextStatus con_status;
- LL_DEBUGS("Avatar") << " joint " << getName() << " set scale " << scale << LL_ENDL;
- LL_DEBUGS("Avatar") << "CONTEXT:\n" << "====================\n" << con_status << LL_ENDL;
- LL_DEBUGS("Avatar") << "STACK:\n" << "====================\n" << cs << "====================" << LL_ENDL;
- }
- mXform.setScale(scale);
- touch();
-
-}
-
-
-
-//--------------------------------------------------------------------
-// getWorldMatrix()
-//--------------------------------------------------------------------
-const LLMatrix4 &LLJoint::getWorldMatrix()
-{
- updateWorldMatrixParent();
-
- return mXform.getWorldMatrix();
-}
-
-const LLMatrix4a& LLJoint::getWorldMatrix4a()
-{
- updateWorldMatrixParent();
-
- return mWorldMatrix;
-}
-
-
-//--------------------------------------------------------------------
-// setWorldMatrix()
-//--------------------------------------------------------------------
-void LLJoint::setWorldMatrix( const LLMatrix4& mat )
-{
- LL_INFOS() << "WARNING: LLJoint::setWorldMatrix() not correctly implemented yet" << LL_ENDL;
- // extract global translation
- LLVector3 trans( mat.mMatrix[VW][VX],
- mat.mMatrix[VW][VY],
- mat.mMatrix[VW][VZ] );
-
- // extract global rotation
- LLQuaternion rot( mat );
-
- setWorldPosition( trans );
- setWorldRotation( rot );
-}
-
-//-----------------------------------------------------------------------------
-// updateWorldMatrixParent()
-//-----------------------------------------------------------------------------
-void LLJoint::updateWorldMatrixParent()
-{
- if (mDirtyFlags & MATRIX_DIRTY)
- {
- LLJoint *parent = getParent();
- if (parent)
- {
- parent->updateWorldMatrixParent();
- }
- updateWorldMatrix();
- }
-}
-
-//-----------------------------------------------------------------------------
-// updateWorldPRSParent()
-//-----------------------------------------------------------------------------
-void LLJoint::updateWorldPRSParent()
-{
- if (mDirtyFlags & (ROTATION_DIRTY | POSITION_DIRTY))
- {
- LLJoint *parent = getParent();
- if (parent)
- {
- parent->updateWorldPRSParent();
- }
-
- mXform.update();
- mDirtyFlags &= ~(ROTATION_DIRTY | POSITION_DIRTY);
- }
-}
-
-//-----------------------------------------------------------------------------
-// updateWorldMatrixChildren()
-//-----------------------------------------------------------------------------
-void LLJoint::updateWorldMatrixChildren()
-{
- if (!this->mUpdateXform) return;
-
- if (mDirtyFlags & MATRIX_DIRTY)
- {
- updateWorldMatrix();
- }
- for (LLJoint* joint : mChildren)
- {
- joint->updateWorldMatrixChildren();
- }
-}
-
-//-----------------------------------------------------------------------------
-// updateWorldMatrix()
-//-----------------------------------------------------------------------------
-void LLJoint::updateWorldMatrix()
-{
- if (mDirtyFlags & MATRIX_DIRTY)
- {
- sNumUpdates++;
- mXform.updateMatrix(false);
- mWorldMatrix.loadu(mXform.getWorldMatrix());
- mDirtyFlags = 0x0;
- }
-}
-
-//--------------------------------------------------------------------
-// getSkinOffset()
-//--------------------------------------------------------------------
-const LLVector3 &LLJoint::getSkinOffset()
-{
- return mSkinOffset;
-}
-
-
-//--------------------------------------------------------------------
-// setSkinOffset()
-//--------------------------------------------------------------------
-void LLJoint::setSkinOffset( const LLVector3& offset )
-{
- mSkinOffset = offset;
-}
-
-
-//-----------------------------------------------------------------------------
-// clampRotation()
-//-----------------------------------------------------------------------------
-void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot)
-{
- LLVector3 main_axis(1.f, 0.f, 0.f);
-
- for (LLJoint* joint : mChildren)
- {
- if (joint->isAnimatable())
- {
- main_axis = joint->getPosition();
- main_axis.normVec();
- // only care about first animatable child
- break;
- }
- }
-}
-
-// End
-
+/**
+ * @file lljoint.cpp
+ * @brief Implementation of LLJoint class.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "linden_common.h"
+
+#include "lljoint.h"
+
+#include "llmath.h"
+#include "llcallstack.h"
+#include <boost/algorithm/string.hpp>
+
+S32 LLJoint::sNumUpdates = 0;
+S32 LLJoint::sNumTouches = 0;
+
+template <class T>
+bool attachment_map_iter_compare_key(const T& a, const T& b)
+{
+ return a.first < b.first;
+}
+
+bool LLVector3OverrideMap::findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const
+{
+ pos = LLVector3(0,0,0);
+ mesh_id = LLUUID();
+ bool found = false;
+
+ map_type::const_iterator it = std::max_element(m_map.begin(),
+ m_map.end(),
+ attachment_map_iter_compare_key<map_type::value_type>);
+ if (it != m_map.end())
+ {
+ found = true;
+ pos = it->second;
+ mesh_id = it->first;
+ }
+ return found;
+}
+
+void LLVector3OverrideMap::showJointVector3Overrides( std::ostringstream& os ) const
+{
+ map_type::const_iterator max_it = std::max_element(m_map.begin(),
+ m_map.end(),
+ attachment_map_iter_compare_key<map_type::value_type>);
+ for (const map_type::value_type& pos_pair : m_map)
+ {
+ const LLVector3& pos = pos_pair.second;
+ os << " " << "[" << pos_pair.first <<": " << pos << "]" << ((pos_pair==(*max_it)) ? "*" : "");
+ }
+}
+
+U32 LLVector3OverrideMap::count() const
+{
+ return m_map.size();
+}
+
+void LLVector3OverrideMap::add(const LLUUID& mesh_id, const LLVector3& pos)
+{
+ m_map[mesh_id] = pos;
+}
+
+bool LLVector3OverrideMap::remove(const LLUUID& mesh_id)
+{
+ U32 remove_count = m_map.erase(mesh_id);
+ return (remove_count > 0);
+}
+
+void LLVector3OverrideMap::clear()
+{
+ m_map.clear();
+}
+
+//-----------------------------------------------------------------------------
+// LLJoint()
+// Class Constructor
+//-----------------------------------------------------------------------------
+
+
+void LLJoint::init()
+{
+ mName = "unnamed";
+ mParent = NULL;
+ mXform.setScaleChildOffset(true);
+ mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
+ mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
+ mUpdateXform = true;
+ mSupport = SUPPORT_BASE;
+ mEnd = LLVector3(0.0f, 0.0f, 0.0f);
+}
+
+LLJoint::LLJoint() :
+ mJointNum(-1)
+{
+ init();
+ touch();
+}
+
+LLJoint::LLJoint(S32 joint_num) :
+ mJointNum(joint_num)
+{
+ init();
+ touch();
+}
+
+//-----------------------------------------------------------------------------
+// LLJoint()
+// Class Constructor
+//-----------------------------------------------------------------------------
+LLJoint::LLJoint(const std::string &name, LLJoint *parent) :
+ mJointNum(-2)
+{
+ init();
+ mUpdateXform = false;
+
+ setName(name);
+ if (parent)
+ {
+ parent->addChild( this );
+ }
+ touch();
+}
+
+//-----------------------------------------------------------------------------
+// ~LLJoint()
+// Class Destructor
+//-----------------------------------------------------------------------------
+LLJoint::~LLJoint()
+{
+ if (mParent)
+ {
+ mParent->removeChild( this );
+ }
+ removeAllChildren();
+}
+
+
+//-----------------------------------------------------------------------------
+// setup()
+//-----------------------------------------------------------------------------
+void LLJoint::setup(const std::string &name, LLJoint *parent)
+{
+ setName(name);
+ if (parent)
+ {
+ parent->addChild( this );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// setSupport()
+//-----------------------------------------------------------------------------
+void LLJoint::setSupport(const std::string& support_name)
+{
+ if (support_name == "extended")
+ {
+ setSupport(SUPPORT_EXTENDED);
+ }
+ else if (support_name == "base")
+ {
+ setSupport(SUPPORT_BASE);
+ }
+ else
+ {
+ LL_WARNS() << "unknown support string " << support_name << LL_ENDL;
+ setSupport(SUPPORT_BASE);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// touch()
+// Sets all dirty flags for all children, recursively.
+//-----------------------------------------------------------------------------
+void LLJoint::touch(U32 flags)
+{
+ if ((flags | mDirtyFlags) != mDirtyFlags)
+ {
+ sNumTouches++;
+ mDirtyFlags |= flags;
+ U32 child_flags = flags;
+ if (flags & ROTATION_DIRTY)
+ {
+ child_flags |= POSITION_DIRTY;
+ }
+
+ for (LLJoint* joint : mChildren)
+ {
+ joint->touch(child_flags);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// setJointNum()
+//-----------------------------------------------------------------------------
+void LLJoint::setJointNum(S32 joint_num)
+{
+ mJointNum = joint_num;
+ if (mJointNum + 2 >= LL_CHARACTER_MAX_ANIMATED_JOINTS)
+ {
+ LL_INFOS() << "LL_CHARACTER_MAX_ANIMATED_JOINTS needs to be increased" << LL_ENDL;
+ LL_ERRS() << "joint_num " << joint_num << " + 2 is too large for " << LL_CHARACTER_MAX_ANIMATED_JOINTS << LL_ENDL;
+ }
+}
+//-----------------------------------------------------------------------------
+// getRoot()
+//-----------------------------------------------------------------------------
+LLJoint *LLJoint::getRoot()
+{
+ if ( getParent() == NULL )
+ {
+ return this;
+ }
+ return getParent()->getRoot();
+}
+
+
+//-----------------------------------------------------------------------------
+// findJoint()
+//-----------------------------------------------------------------------------
+LLJoint *LLJoint::findJoint( const std::string &name )
+{
+ if (name == getName())
+ return this;
+
+ for (LLJoint* joint : mChildren)
+ {
+ LLJoint *found = joint->findJoint(name);
+ if (found)
+ {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------
+// addChild()
+//--------------------------------------------------------------------
+void LLJoint::addChild(LLJoint* joint)
+{
+ if (joint->mParent)
+ joint->mParent->removeChild(joint);
+
+ mChildren.push_back(joint);
+ joint->mXform.setParent(&mXform);
+ joint->mParent = this;
+ joint->touch();
+}
+
+
+//--------------------------------------------------------------------
+// removeChild()
+//--------------------------------------------------------------------
+void LLJoint::removeChild(LLJoint* joint)
+{
+ joints_t::iterator iter = std::find(mChildren.begin(), mChildren.end(), joint);
+ if (iter != mChildren.end())
+ {
+ mChildren.erase(iter);
+
+ joint->mXform.setParent(NULL);
+ joint->mParent = NULL;
+ joint->touch();
+ }
+}
+
+
+//--------------------------------------------------------------------
+// removeAllChildren()
+//--------------------------------------------------------------------
+void LLJoint::removeAllChildren()
+{
+ for (LLJoint* joint : mChildren)
+ {
+ if (joint)
+ {
+ joint->mXform.setParent(NULL);
+ joint->mParent = NULL;
+ joint->touch();
+ //delete joint;
+ }
+ }
+ mChildren.clear();
+}
+
+
+//--------------------------------------------------------------------
+// getPosition()
+//--------------------------------------------------------------------
+const LLVector3& LLJoint::getPosition()
+{
+ return mXform.getPosition();
+}
+
+bool do_debug_joint(const std::string& name)
+{
+ if (std::find(LLJoint::s_debugJointNames.begin(), LLJoint::s_debugJointNames.end(),name) != LLJoint::s_debugJointNames.end())
+ {
+ return true;
+ }
+ return false;
+}
+
+//--------------------------------------------------------------------
+// setPosition()
+//--------------------------------------------------------------------
+void LLJoint::setPosition( const LLVector3& requested_pos, bool apply_attachment_overrides )
+{
+ LLVector3 pos(requested_pos);
+
+ LLVector3 active_override;
+ LLUUID mesh_id;
+ if (apply_attachment_overrides && m_attachmentPosOverrides.findActiveOverride(mesh_id,active_override))
+ {
+ if (pos != active_override && do_debug_joint(getName()))
+ {
+ LLScopedContextString str("setPosition");
+ LL_DEBUGS("Avatar") << " joint " << getName() << " requested_pos " << requested_pos
+ << " overriden by attachment " << active_override << LL_ENDL;
+ }
+ pos = active_override;
+ }
+ if ((pos != getPosition()) && do_debug_joint(getName()))
+ {
+ LLScopedContextString str("setPosition");
+ LLCallStack cs;
+ LLContextStatus con_status;
+ LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL;
+ LL_DEBUGS("Avatar") << "CONTEXT:\n" << "====================\n" << con_status << "====================" << LL_ENDL;
+ LL_DEBUGS("Avatar") << "STACK:\n" << "====================\n" << cs << "====================" << LL_ENDL;
+ }
+ if (pos != getPosition())
+ {
+ mXform.setPosition(pos);
+ touch(MATRIX_DIRTY | POSITION_DIRTY);
+ }
+}
+
+void LLJoint::setDefaultPosition( const LLVector3& pos )
+{
+ mDefaultPosition = pos;
+}
+
+const LLVector3& LLJoint::getDefaultPosition() const
+{
+ return mDefaultPosition;
+}
+
+void LLJoint::setDefaultScale( const LLVector3& scale )
+{
+ mDefaultScale = scale;
+}
+
+const LLVector3& LLJoint::getDefaultScale() const
+{
+ return mDefaultScale;
+}
+
+void showJointPosOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info )
+{
+ std::ostringstream os;
+ os << joint.m_posBeforeOverrides;
+ joint.m_attachmentPosOverrides.showJointVector3Overrides(os);
+ LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL;
+}
+
+void showJointScaleOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info )
+{
+ std::ostringstream os;
+ os << joint.m_scaleBeforeOverrides;
+ joint.m_attachmentScaleOverrides.showJointVector3Overrides(os);
+ LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL;
+}
+
+bool LLJoint::aboveJointPosThreshold(const LLVector3& pos) const
+{
+ LLVector3 diff = pos - getDefaultPosition();
+ const F32 max_joint_pos_offset = LL_JOINT_TRESHOLD_POS_OFFSET; // 0.1 mm
+ return diff.lengthSquared() > max_joint_pos_offset * max_joint_pos_offset;
+}
+
+bool LLJoint::aboveJointScaleThreshold(const LLVector3& scale) const
+{
+ LLVector3 diff = scale - getDefaultScale();
+ const F32 max_joint_scale_offset = 0.0001f; // 0.1 mm
+ return diff.lengthSquared() > max_joint_scale_offset * max_joint_scale_offset;
+}
+
+//--------------------------------------------------------------------
+// addAttachmentPosOverride()
+//--------------------------------------------------------------------
+void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed )
+{
+ active_override_changed = false;
+ if (mesh_id.isNull())
+ {
+ return;
+ }
+ LLVector3 before_pos;
+ LLUUID before_mesh_id;
+ bool has_active_override_before = hasAttachmentPosOverride( before_pos, before_mesh_id );
+ if (!m_attachmentPosOverrides.count())
+ {
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_posBeforeOverrides " << getPosition() << LL_ENDL;
+ }
+ m_posBeforeOverrides = getPosition();
+ }
+ m_attachmentPosOverrides.add(mesh_id,pos);
+ LLVector3 after_pos;
+ LLUUID after_mesh_id;
+ hasAttachmentPosOverride(after_pos, after_mesh_id);
+ if (!has_active_override_before || (after_pos != before_pos))
+ {
+ active_override_changed = true;
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentPosOverride for mesh " << mesh_id << " pos " << pos << LL_ENDL;
+ }
+ updatePos(av_info);
+ }
+}
+
+//--------------------------------------------------------------------
+// removeAttachmentPosOverride()
+//--------------------------------------------------------------------
+void LLJoint::removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info, bool& active_override_changed )
+{
+ active_override_changed = false;
+ if (mesh_id.isNull())
+ {
+ return;
+ }
+ LLVector3 before_pos;
+ LLUUID before_mesh_id;
+ hasAttachmentPosOverride( before_pos, before_mesh_id );
+ if (m_attachmentPosOverrides.remove(mesh_id))
+ {
+ LLVector3 after_pos;
+ LLUUID after_mesh_id;
+ bool has_active_override_after = hasAttachmentPosOverride(after_pos, after_mesh_id);
+ if (!has_active_override_after || (after_pos != before_pos))
+ {
+ active_override_changed = true;
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
+ << " removeAttachmentPosOverride for " << mesh_id << LL_ENDL;
+ showJointPosOverrides(*this, "remove", av_info);
+ }
+ updatePos(av_info);
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+ // hasAttachmentPosOverride()
+ //--------------------------------------------------------------------
+bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const
+{
+ return m_attachmentPosOverrides.findActiveOverride(mesh_id,pos);
+}
+
+//--------------------------------------------------------------------
+// clearAttachmentPosOverrides()
+//--------------------------------------------------------------------
+void LLJoint::clearAttachmentPosOverrides()
+{
+ if (m_attachmentPosOverrides.count())
+ {
+ m_attachmentPosOverrides.clear();
+ setPosition(m_posBeforeOverrides);
+ }
+}
+
+//--------------------------------------------------------------------
+// getAllAttachmentPosOverrides()
+//--------------------------------------------------------------------
+void LLJoint::getAllAttachmentPosOverrides(S32& num_pos_overrides,
+ std::set<LLVector3>& distinct_pos_overrides) const
+{
+ num_pos_overrides = m_attachmentPosOverrides.count();
+ for (const LLVector3OverrideMap::map_type::value_type& pos_override_pair : m_attachmentPosOverrides.getMap())
+ {
+ distinct_pos_overrides.insert(pos_override_pair.second);
+ }
+}
+
+//--------------------------------------------------------------------
+// getAllAttachmentScaleOverrides()
+//--------------------------------------------------------------------
+void LLJoint::getAllAttachmentScaleOverrides(S32& num_scale_overrides,
+ std::set<LLVector3>& distinct_scale_overrides) const
+{
+ num_scale_overrides = m_attachmentScaleOverrides.count();
+ for (const LLVector3OverrideMap::map_type::value_type& scale_override_pair : m_attachmentScaleOverrides.getMap())
+ {
+ distinct_scale_overrides.insert(scale_override_pair.second);
+ }
+}
+
+//--------------------------------------------------------------------
+// showAttachmentPosOverrides()
+//--------------------------------------------------------------------
+void LLJoint::showAttachmentPosOverrides(const std::string& av_info) const
+{
+ LLVector3 active_override;
+ bool has_active_override;
+ LLUUID mesh_id;
+ has_active_override = m_attachmentPosOverrides.findActiveOverride(mesh_id,active_override);
+ U32 count = m_attachmentPosOverrides.count();
+ if (count==1)
+ {
+ LLVector3OverrideMap::map_type::const_iterator it = m_attachmentPosOverrides.getMap().begin();
+ std::string highlight = (has_active_override && (it->second == active_override)) ? "*" : "";
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
+ << " has single attachment pos override " << highlight << "" << it->second << " default " << mDefaultPosition << LL_ENDL;
+ }
+ else if (count>1)
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " has " << count << " attachment pos overrides" << LL_ENDL;
+ std::set<LLVector3> distinct_offsets;
+ for (const LLVector3OverrideMap::map_type::value_type& pos_override_pair : m_attachmentPosOverrides.getMap())
+ {
+ distinct_offsets.insert(pos_override_pair.second);
+ }
+ if (distinct_offsets.size()>1)
+ {
+ LL_DEBUGS("Avatar") << "CONFLICTS, " << distinct_offsets.size() << " different values" << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("Avatar") << "no conflicts" << LL_ENDL;
+ }
+ for (const LLVector3& offset : distinct_offsets)
+ {
+ std::string highlight = (has_active_override && offset == active_override) ? "*" : "";
+ LL_DEBUGS("Avatar") << " POS " << highlight << "" << offset << " default " << mDefaultPosition << LL_ENDL;
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+// updatePos()
+//--------------------------------------------------------------------
+void LLJoint::updatePos(const std::string& av_info)
+{
+ LLVector3 pos, found_pos;
+ LLUUID mesh_id;
+ if (m_attachmentPosOverrides.findActiveOverride(mesh_id,found_pos))
+ {
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentPosOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL;
+ }
+ pos = found_pos;
+ }
+ else
+ {
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL;
+ }
+ pos = m_posBeforeOverrides;
+ }
+ setPosition(pos);
+}
+
+//--------------------------------------------------------------------
+// updateScale()
+//--------------------------------------------------------------------
+void LLJoint::updateScale(const std::string& av_info)
+{
+ LLVector3 scale, found_scale;
+ LLUUID mesh_id;
+ if (m_attachmentScaleOverrides.findActiveOverride(mesh_id,found_scale))
+ {
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updateScale, winner of " << m_attachmentScaleOverrides.count() << " is mesh " << mesh_id << " scale " << found_scale << LL_ENDL;
+ }
+ scale = found_scale;
+ }
+ else
+ {
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updateScale, winner is scaleBeforeOverrides " << m_scaleBeforeOverrides << LL_ENDL;
+ }
+ scale = m_scaleBeforeOverrides;
+ }
+ setScale(scale);
+}
+
+//--------------------------------------------------------------------
+// addAttachmentScaleOverride()
+//--------------------------------------------------------------------
+void LLJoint::addAttachmentScaleOverride( const LLVector3& scale, const LLUUID& mesh_id, const std::string& av_info )
+{
+ if (mesh_id.isNull())
+ {
+ return;
+ }
+ if (!m_attachmentScaleOverrides.count())
+ {
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_scaleBeforeOverrides " << getScale() << LL_ENDL;
+ }
+ m_scaleBeforeOverrides = getScale();
+ }
+ m_attachmentScaleOverrides.add(mesh_id,scale);
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentScaleOverride for mesh " << mesh_id << " scale " << scale << LL_ENDL;
+ }
+ updateScale(av_info);
+}
+
+//--------------------------------------------------------------------
+// removeAttachmentScaleOverride()
+//--------------------------------------------------------------------
+void LLJoint::removeAttachmentScaleOverride( const LLUUID& mesh_id, const std::string& av_info )
+{
+ if (mesh_id.isNull())
+ {
+ return;
+ }
+ if (m_attachmentScaleOverrides.remove(mesh_id))
+ {
+ if (do_debug_joint(getName()))
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
+ << " removeAttachmentScaleOverride for " << mesh_id << LL_ENDL;
+ showJointScaleOverrides(*this, "remove", av_info);
+ }
+ updateScale(av_info);
+ }
+}
+
+//--------------------------------------------------------------------
+ // hasAttachmentScaleOverride()
+ //--------------------------------------------------------------------
+bool LLJoint::hasAttachmentScaleOverride( LLVector3& scale, LLUUID& mesh_id ) const
+{
+ return m_attachmentScaleOverrides.findActiveOverride(mesh_id,scale);
+}
+
+//--------------------------------------------------------------------
+// clearAttachmentScaleOverrides()
+//--------------------------------------------------------------------
+void LLJoint::clearAttachmentScaleOverrides()
+{
+ if (m_attachmentScaleOverrides.count())
+ {
+ m_attachmentScaleOverrides.clear();
+ setScale(m_scaleBeforeOverrides);
+ }
+}
+
+//--------------------------------------------------------------------
+// showAttachmentScaleOverrides()
+//--------------------------------------------------------------------
+void LLJoint::showAttachmentScaleOverrides(const std::string& av_info) const
+{
+ LLVector3 active_override;
+ bool has_active_override;
+ LLUUID mesh_id;
+ has_active_override = m_attachmentScaleOverrides.findActiveOverride(mesh_id,active_override);
+ U32 count = m_attachmentScaleOverrides.count();
+ if (count==1)
+ {
+ LLVector3OverrideMap::map_type::const_iterator it = m_attachmentScaleOverrides.getMap().begin();
+ std::string highlight = (has_active_override && (it->second == active_override)) ? "*" : "";
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
+ << " has single attachment scale override " << highlight << "" << it->second << " default " << mDefaultScale << LL_ENDL;
+ }
+ else if (count>1)
+ {
+ LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " has " << count << " attachment scale overrides" << LL_ENDL;
+ std::set<LLVector3> distinct_offsets;
+ for (const LLVector3OverrideMap::map_type::value_type& scale_override_pair : m_attachmentScaleOverrides.getMap())
+ {
+ distinct_offsets.insert(scale_override_pair.second);
+ }
+ if (distinct_offsets.size()>1)
+ {
+ LL_DEBUGS("Avatar") << "CONFLICTS, " << distinct_offsets.size() << " different values" << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("Avatar") << "no conflicts" << LL_ENDL;
+ }
+ for (const LLVector3& offset : distinct_offsets)
+ {
+ std::string highlight = (has_active_override && offset == active_override) ? "*" : "";
+ LL_DEBUGS("Avatar") << " POS " << highlight << "" << offset << " default " << mDefaultScale << LL_ENDL;
+ }
+ }
+}
+
+// init static
+LLJoint::debug_joint_name_t LLJoint::s_debugJointNames = debug_joint_name_t();
+
+//--------------------------------------------------------------------
+// setDebugJointNames
+//--------------------------------------------------------------------
+void LLJoint::setDebugJointNames(const debug_joint_name_t& names)
+{
+ s_debugJointNames = names;
+}
+void LLJoint::setDebugJointNames(const std::string& names_string)
+{
+ debug_joint_name_t names;
+ boost::split(names, names_string, boost::is_any_of(" :,"));
+ setDebugJointNames(names);
+}
+
+//--------------------------------------------------------------------
+// getWorldPosition()
+//--------------------------------------------------------------------
+LLVector3 LLJoint::getWorldPosition()
+{
+ updateWorldPRSParent();
+ return mXform.getWorldPosition();
+}
+
+//-----------------------------------------------------------------------------
+// getLastWorldPosition()
+//-----------------------------------------------------------------------------
+LLVector3 LLJoint::getLastWorldPosition()
+{
+ return mXform.getWorldPosition();
+}
+//--------------------------------------------------------------------
+// setWorldPosition()
+//--------------------------------------------------------------------
+void LLJoint::setWorldPosition( const LLVector3& pos )
+{
+ if (mParent == NULL)
+ {
+ this->setPosition( pos );
+ return;
+ }
+
+ LLMatrix4 temp_matrix = getWorldMatrix();
+ temp_matrix.mMatrix[VW][VX] = pos.mV[VX];
+ temp_matrix.mMatrix[VW][VY] = pos.mV[VY];
+ temp_matrix.mMatrix[VW][VZ] = pos.mV[VZ];
+
+ LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
+ LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
+
+ temp_matrix *= invParentWorldMatrix;
+
+ LLVector3 localPos( temp_matrix.mMatrix[VW][VX],
+ temp_matrix.mMatrix[VW][VY],
+ temp_matrix.mMatrix[VW][VZ] );
+
+ setPosition( localPos );
+}
+
+
+//--------------------------------------------------------------------
+// getRotation()
+//--------------------------------------------------------------------
+const LLQuaternion& LLJoint::getRotation()
+{
+ return mXform.getRotation();
+}
+
+
+//--------------------------------------------------------------------
+// setRotation()
+//--------------------------------------------------------------------
+void LLJoint::setRotation( const LLQuaternion& rot )
+{
+ if (rot.isFinite())
+ {
+ // if (mXform.getRotation() != rot)
+ {
+ mXform.setRotation(rot);
+ touch(MATRIX_DIRTY | ROTATION_DIRTY);
+ }
+ }
+}
+
+
+//--------------------------------------------------------------------
+// getWorldRotation()
+//--------------------------------------------------------------------
+LLQuaternion LLJoint::getWorldRotation()
+{
+ updateWorldPRSParent();
+
+ return mXform.getWorldRotation();
+}
+
+//-----------------------------------------------------------------------------
+// getLastWorldRotation()
+//-----------------------------------------------------------------------------
+LLQuaternion LLJoint::getLastWorldRotation()
+{
+ return mXform.getWorldRotation();
+}
+
+//--------------------------------------------------------------------
+// setWorldRotation()
+//--------------------------------------------------------------------
+void LLJoint::setWorldRotation( const LLQuaternion& rot )
+{
+ if (mParent == NULL)
+ {
+ this->setRotation( rot );
+ return;
+ }
+
+ LLMatrix4 temp_mat(rot);
+
+ LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
+ parentWorldMatrix.mMatrix[VW][VX] = 0;
+ parentWorldMatrix.mMatrix[VW][VY] = 0;
+ parentWorldMatrix.mMatrix[VW][VZ] = 0;
+
+ LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
+
+ temp_mat *= invParentWorldMatrix;
+
+ setRotation(LLQuaternion(temp_mat));
+}
+
+
+//--------------------------------------------------------------------
+// getScale()
+//--------------------------------------------------------------------
+const LLVector3& LLJoint::getScale()
+{
+ return mXform.getScale();
+}
+
+//--------------------------------------------------------------------
+// setScale()
+//--------------------------------------------------------------------
+void LLJoint::setScale( const LLVector3& requested_scale, bool apply_attachment_overrides )
+{
+ LLVector3 scale(requested_scale);
+ LLUUID mesh_id;
+ LLVector3 active_override;
+ if (apply_attachment_overrides && m_attachmentScaleOverrides.findActiveOverride(mesh_id,active_override))
+ {
+ if (scale != active_override && do_debug_joint(getName()))
+ {
+ LLScopedContextString str("setScale");
+ LL_DEBUGS("Avatar") << " joint " << getName() << " requested_scale " << requested_scale
+ << " overriden by attachment " << active_override << LL_ENDL;
+ }
+ scale = active_override;
+ }
+ if ((mXform.getScale() != scale) && do_debug_joint(getName()))
+ {
+ LLScopedContextString str("setScale");
+ LLCallStack cs;
+ LLContextStatus con_status;
+ LL_DEBUGS("Avatar") << " joint " << getName() << " set scale " << scale << LL_ENDL;
+ LL_DEBUGS("Avatar") << "CONTEXT:\n" << "====================\n" << con_status << LL_ENDL;
+ LL_DEBUGS("Avatar") << "STACK:\n" << "====================\n" << cs << "====================" << LL_ENDL;
+ }
+ mXform.setScale(scale);
+ touch();
+
+}
+
+
+
+//--------------------------------------------------------------------
+// getWorldMatrix()
+//--------------------------------------------------------------------
+const LLMatrix4 &LLJoint::getWorldMatrix()
+{
+ updateWorldMatrixParent();
+
+ return mXform.getWorldMatrix();
+}
+
+const LLMatrix4a& LLJoint::getWorldMatrix4a()
+{
+ updateWorldMatrixParent();
+
+ return mWorldMatrix;
+}
+
+
+//--------------------------------------------------------------------
+// setWorldMatrix()
+//--------------------------------------------------------------------
+void LLJoint::setWorldMatrix( const LLMatrix4& mat )
+{
+ LL_INFOS() << "WARNING: LLJoint::setWorldMatrix() not correctly implemented yet" << LL_ENDL;
+ // extract global translation
+ LLVector3 trans( mat.mMatrix[VW][VX],
+ mat.mMatrix[VW][VY],
+ mat.mMatrix[VW][VZ] );
+
+ // extract global rotation
+ LLQuaternion rot( mat );
+
+ setWorldPosition( trans );
+ setWorldRotation( rot );
+}
+
+//-----------------------------------------------------------------------------
+// updateWorldMatrixParent()
+//-----------------------------------------------------------------------------
+void LLJoint::updateWorldMatrixParent()
+{
+ if (mDirtyFlags & MATRIX_DIRTY)
+ {
+ LLJoint *parent = getParent();
+ if (parent)
+ {
+ parent->updateWorldMatrixParent();
+ }
+ updateWorldMatrix();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// updateWorldPRSParent()
+//-----------------------------------------------------------------------------
+void LLJoint::updateWorldPRSParent()
+{
+ if (mDirtyFlags & (ROTATION_DIRTY | POSITION_DIRTY))
+ {
+ LLJoint *parent = getParent();
+ if (parent)
+ {
+ parent->updateWorldPRSParent();
+ }
+
+ mXform.update();
+ mDirtyFlags &= ~(ROTATION_DIRTY | POSITION_DIRTY);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// updateWorldMatrixChildren()
+//-----------------------------------------------------------------------------
+void LLJoint::updateWorldMatrixChildren()
+{
+ if (!this->mUpdateXform) return;
+
+ if (mDirtyFlags & MATRIX_DIRTY)
+ {
+ updateWorldMatrix();
+ }
+ for (LLJoint* joint : mChildren)
+ {
+ joint->updateWorldMatrixChildren();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// updateWorldMatrix()
+//-----------------------------------------------------------------------------
+void LLJoint::updateWorldMatrix()
+{
+ if (mDirtyFlags & MATRIX_DIRTY)
+ {
+ sNumUpdates++;
+ mXform.updateMatrix(false);
+ mWorldMatrix.loadu(mXform.getWorldMatrix());
+ mDirtyFlags = 0x0;
+ }
+}
+
+//--------------------------------------------------------------------
+// getSkinOffset()
+//--------------------------------------------------------------------
+const LLVector3 &LLJoint::getSkinOffset()
+{
+ return mSkinOffset;
+}
+
+
+//--------------------------------------------------------------------
+// setSkinOffset()
+//--------------------------------------------------------------------
+void LLJoint::setSkinOffset( const LLVector3& offset )
+{
+ mSkinOffset = offset;
+}
+
+
+//-----------------------------------------------------------------------------
+// clampRotation()
+//-----------------------------------------------------------------------------
+void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot)
+{
+ LLVector3 main_axis(1.f, 0.f, 0.f);
+
+ for (LLJoint* joint : mChildren)
+ {
+ if (joint->isAnimatable())
+ {
+ main_axis = joint->getPosition();
+ main_axis.normVec();
+ // only care about first animatable child
+ break;
+ }
+ }
+}
+
+// End
+