diff options
Diffstat (limited to 'indra/llcharacter/lljoint.cpp')
-rw-r--r-- | indra/llcharacter/lljoint.cpp | 2086 |
1 files changed, 1043 insertions, 1043 deletions
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 3597f3b63f..888980ac11 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
+
|