summaryrefslogtreecommitdiff
path: root/indra/llcharacter/lljoint.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llcharacter/lljoint.cpp
Print done when done.
Diffstat (limited to 'indra/llcharacter/lljoint.cpp')
-rw-r--r--indra/llcharacter/lljoint.cpp504
1 files changed, 504 insertions, 0 deletions
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
new file mode 100644
index 0000000000..3924c06adc
--- /dev/null
+++ b/indra/llcharacter/lljoint.cpp
@@ -0,0 +1,504 @@
+/**
+ * @file lljoint.cpp
+ * @brief Implementation of LLJoint class.
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+//-----------------------------------------------------------------------------
+// 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();
+}
+
+
+//-----------------------------------------------------------------------------
+// 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;
+ mJointNum = 0;
+
+ setName(name);
+ if (parent)
+ parent->addChild( this );
+
+ touch();
+}
+
+//-----------------------------------------------------------------------------
+// ~LLJoint()
+// Class Destructor
+//-----------------------------------------------------------------------------
+LLJoint::~LLJoint()
+{
+ 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 ( LLJoint *joint = mChildren.getFirstData();
+ joint != NULL;
+ joint = mChildren.getNextData() )
+ {
+ 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 ( LLJoint *j = mChildren.getFirstData();
+ j != NULL;
+ j = mChildren.getNextData() )
+ {
+ LLJoint *found = j->findJoint(name);
+ if (found)
+ return found;
+ }
+
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------
+// addChild()
+//--------------------------------------------------------------------
+void LLJoint::addChild(LLJoint *joint)
+{
+ if (joint->mParent)
+ joint->mParent->removeChild(joint);
+
+ mChildren.addDataAtEnd(joint);
+ joint->mXform.setParent(&mXform);
+ joint->mParent = this;
+ joint->touch();
+}
+
+
+//--------------------------------------------------------------------
+// removeChild()
+//--------------------------------------------------------------------
+void LLJoint::removeChild(LLJoint *joint)
+{
+ this->mChildren.removeData(joint);
+ joint->mXform.setParent(NULL);
+ joint->mParent = NULL;
+ joint->touch();
+}
+
+
+//--------------------------------------------------------------------
+// removeAllChildren()
+//--------------------------------------------------------------------
+void LLJoint::removeAllChildren()
+{
+ for ( LLJoint *joint = mChildren.getFirstData();
+ joint != NULL;
+ joint = mChildren.getNextData() )
+ {
+ removeChild(joint);
+ }
+}
+
+
+//--------------------------------------------------------------------
+// getPosition()
+//--------------------------------------------------------------------
+const LLVector3& LLJoint::getPosition()
+{
+ return mXform.getPosition();
+}
+
+
+//--------------------------------------------------------------------
+// setPosition()
+//--------------------------------------------------------------------
+void LLJoint::setPosition( const LLVector3& pos )
+{
+ mXform.setPosition(pos);
+ touch(MATRIX_DIRTY | POSITION_DIRTY);
+}
+
+
+//--------------------------------------------------------------------
+// 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())
+ {
+ 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 )
+{
+ 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 (mDirtyFlags & MATRIX_DIRTY)
+ {
+ updateWorldMatrix();
+ }
+ for (LLJoint *child = mChildren.getFirstData(); child; child = mChildren.getNextData())
+ {
+ child->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;
+}
+
+//-----------------------------------------------------------------------------
+// setConstraintSilhouette()
+//-----------------------------------------------------------------------------
+void LLJoint::setConstraintSilhouette(LLDynamicArray<LLVector3>& silhouette)
+{
+ S32 i;
+
+ mConstraintSilhouette.reset();
+ for (i = 0; i < silhouette.count(); i++)
+ {
+ if (i % 2 == 1)
+ {
+ // skip normals
+ continue;
+ }
+ mConstraintSilhouette[i / 2] = silhouette[i];
+ }
+ LLQuaternion inv_parent_rotation = LLQuaternion::DEFAULT;
+
+ if (getParent())
+ {
+ inv_parent_rotation = ~getParent()->getWorldRotation();
+ }
+
+ for (i = 0; i < mConstraintSilhouette.count(); i++)
+ {
+ LLVector3 vert = mConstraintSilhouette[i];
+
+ vert -= getWorldPosition();
+ vert.normVec();
+ vert = vert * inv_parent_rotation;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// clampRotation()
+//-----------------------------------------------------------------------------
+void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot)
+{
+ LLVector3 main_axis(1.f, 0.f, 0.f);
+
+ for (LLJoint* joint = mChildren.getFirstData(); joint; joint = mChildren.getNextData())
+ {
+ 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