/indra/llcharacter/lljoint.cpp
C++ | 562 lines | 321 code | 88 blank | 153 comment | 37 complexity | 3e4df5466e602246ddef2933a4bb1013 MD5 | raw file
Possible License(s): LGPL-2.1
- /**
- * @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"
- S32 LLJoint::sNumUpdates = 0;
- S32 LLJoint::sNumTouches = 0;
- //-----------------------------------------------------------------------------
- // LLJoint()
- // Class Constructor
- //-----------------------------------------------------------------------------
- LLJoint::LLJoint()
- {
- 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;
- mJointNum = -1;
- touch();
- mResetAfterRestoreOldXform = false;
- }
- //-----------------------------------------------------------------------------
- // LLJoint()
- // Class Constructor
- //-----------------------------------------------------------------------------
- LLJoint::LLJoint(const std::string &name, LLJoint *parent)
- {
- mName = "unnamed";
- mParent = NULL;
- mXform.setScaleChildOffset(TRUE);
- mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
- mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
- mUpdateXform = FALSE;
- mJointNum = 0;
- 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 );
- }
- }
- //-----------------------------------------------------------------------------
- // 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 (child_list_t::iterator iter = mChildren.begin();
- iter != mChildren.end(); ++iter)
- {
- LLJoint* joint = *iter;
- joint->touch(child_flags);
- }
- }
- }
- //-----------------------------------------------------------------------------
- // 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 (child_list_t::iterator iter = mChildren.begin();
- iter != mChildren.end(); ++iter)
- {
- LLJoint* joint = *iter;
- 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)
- {
- child_list_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 (child_list_t::iterator iter = mChildren.begin();
- iter != mChildren.end();)
- {
- child_list_t::iterator curiter = iter++;
- LLJoint* joint = *curiter;
- mChildren.erase(curiter);
- joint->mXform.setParent(NULL);
- joint->mParent = NULL;
- joint->touch();
- }
- }
- //--------------------------------------------------------------------
- // getPosition()
- //--------------------------------------------------------------------
- const LLVector3& LLJoint::getPosition()
- {
- return mXform.getPosition();
- }
- //--------------------------------------------------------------------
- // setPosition()
- //--------------------------------------------------------------------
- void LLJoint::setPosition( const LLVector3& pos )
- {
- // if (mXform.getPosition() != pos)
- {
- mXform.setPosition(pos);
- touch(MATRIX_DIRTY | POSITION_DIRTY);
- }
- }
- //--------------------------------------------------------------------
- // setPosition()
- //--------------------------------------------------------------------
- void LLJoint::setDefaultFromCurrentXform( void )
- {
- mDefaultXform = mXform;
- touch(MATRIX_DIRTY | POSITION_DIRTY);
-
- }
- //--------------------------------------------------------------------
- // storeCurrentXform()
- //--------------------------------------------------------------------
- void LLJoint::storeCurrentXform( const LLVector3& pos )
- {
- mOldXform = mXform;
- mResetAfterRestoreOldXform = true;
- setPosition( pos );
- }
- //--------------------------------------------------------------------
- // restoreOldXform()
- //--------------------------------------------------------------------
- void LLJoint::restoreOldXform( void )
- {
- mResetAfterRestoreOldXform = false;
- mXform = mOldXform;
- }
- //--------------------------------------------------------------------
- // restoreOldXform()
- //--------------------------------------------------------------------
- void LLJoint::restoreToDefaultXform( void )
- {
- mXform = mDefaultXform;
- setPosition( mXform.getPosition() );
- }
- //--------------------------------------------------------------------
- // 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 );
- }
- //--------------------------------------------------------------------
- // mXform.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& scale )
- {
- // if (mXform.getScale() != scale)
- {
- mXform.setScale(scale);
- touch();
- }
- }
- //--------------------------------------------------------------------
- // getWorldMatrix()
- //--------------------------------------------------------------------
- const LLMatrix4 &LLJoint::getWorldMatrix()
- {
- updateWorldMatrixParent();
- return mXform.getWorldMatrix();
- }
- //--------------------------------------------------------------------
- // setWorldMatrix()
- //--------------------------------------------------------------------
- void LLJoint::setWorldMatrix( const LLMatrix4& mat )
- {
- llinfos << "WARNING: LLJoint::setWorldMatrix() not correctly implemented yet" << llendl;
- // 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 (child_list_t::iterator iter = mChildren.begin();
- iter != mChildren.end(); ++iter)
- {
- LLJoint* joint = *iter;
- joint->updateWorldMatrixChildren();
- }
- }
- //-----------------------------------------------------------------------------
- // updateWorldMatrix()
- //-----------------------------------------------------------------------------
- void LLJoint::updateWorldMatrix()
- {
- if (mDirtyFlags & MATRIX_DIRTY)
- {
- sNumUpdates++;
- mXform.updateMatrix(FALSE);
- 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 (child_list_t::iterator iter = mChildren.begin();
- iter != mChildren.end(); ++iter)
- {
- LLJoint* joint = *iter;
- if (joint->isAnimatable())
- {
- main_axis = joint->getPosition();
- main_axis.normVec();
- // only care about first animatable child
- break;
- }
- }
- // 2003.03.26 - This code was just using up cpu cycles. AB
- // LLVector3 old_axis = main_axis * old_rot;
- // LLVector3 new_axis = main_axis * new_rot;
- // for (S32 i = 0; i < mConstraintSilhouette.count() - 1; i++)
- // {
- // LLVector3 vert1 = mConstraintSilhouette[i];
- // LLVector3 vert2 = mConstraintSilhouette[i + 1];
- // figure out how to clamp rotation to line on 3-sphere
- // }
- }
- // End