00001 
00032 
00033 
00034 
00035 #include "linden_common.h"
00036 
00037 #include "lljoint.h"
00038 
00039 #include "llmath.h"
00040 
00041 S32 LLJoint::sNumUpdates = 0;
00042 S32 LLJoint::sNumTouches = 0;
00043 
00044 
00045 
00046 
00047 
00048 LLJoint::LLJoint()
00049 {
00050         mName = "unnamed";
00051         mParent = NULL;
00052         mXform.setScaleChildOffset(TRUE);
00053         mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
00054         mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
00055         mUpdateXform = TRUE;
00056         mJointNum = -1;
00057         touch();
00058 }
00059 
00060 
00061 
00062 
00063 
00064 
00065 LLJoint::LLJoint(const std::string &name, LLJoint *parent)
00066 {
00067         mName = "unnamed";
00068         mParent = NULL;
00069         mXform.setScaleChildOffset(TRUE);
00070         mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
00071         mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
00072         mJointNum = 0;
00073 
00074         setName(name);
00075         if (parent)
00076         {
00077                 parent->addChild( this );
00078         }
00079         touch();
00080 }
00081 
00082 
00083 
00084 
00085 
00086 LLJoint::~LLJoint()
00087 {
00088         if (mParent)
00089         {
00090                 mParent->removeChild( this );
00091         }
00092         removeAllChildren();
00093 }
00094 
00095 
00096 
00097 
00098 
00099 void LLJoint::setup(const std::string &name, LLJoint *parent)
00100 {
00101         setName(name);
00102         if (parent)
00103         {
00104                 parent->addChild( this );
00105         }
00106 }
00107 
00108 
00109 
00110 
00111 
00112 void LLJoint::touch(U32 flags)
00113 {
00114         if ((flags | mDirtyFlags) != mDirtyFlags)
00115         {
00116                 sNumTouches++;
00117                 mDirtyFlags |= flags;
00118                 U32 child_flags = flags;
00119                 if (flags & ROTATION_DIRTY)
00120                 {
00121                         child_flags |= POSITION_DIRTY;
00122                 }
00123 
00124                 for (child_list_t::iterator iter = mChildren.begin();
00125                          iter != mChildren.end(); ++iter)
00126                 {
00127                         LLJoint* joint = *iter;
00128                         joint->touch(child_flags);
00129                 }
00130         }
00131 }
00132 
00133 
00134 
00135 
00136 LLJoint *LLJoint::getRoot()
00137 {
00138         if ( getParent() == NULL )
00139         {
00140                 return this;
00141         }
00142         return getParent()->getRoot();
00143 }
00144 
00145 
00146 
00147 
00148 
00149 LLJoint *LLJoint::findJoint( const std::string &name )
00150 {
00151         if (name == getName())
00152                 return this;
00153 
00154         for (child_list_t::iterator iter = mChildren.begin();
00155                  iter != mChildren.end(); ++iter)
00156         {
00157                 LLJoint* joint = *iter;
00158                 LLJoint *found = joint->findJoint(name);
00159                 if (found)
00160                 {
00161                         return found;
00162                 }
00163         }
00164 
00165         return NULL;    
00166 }
00167 
00168 
00169 
00170 
00171 
00172 void LLJoint::addChild(LLJoint* joint)
00173 {
00174         if (joint->mParent)
00175                 joint->mParent->removeChild(joint);
00176 
00177         mChildren.push_back(joint);
00178         joint->mXform.setParent(&mXform);
00179         joint->mParent = this;  
00180         joint->touch();
00181 }
00182 
00183 
00184 
00185 
00186 
00187 void LLJoint::removeChild(LLJoint* joint)
00188 {
00189         child_list_t::iterator iter = std::find(mChildren.begin(), mChildren.end(), joint);
00190         if (iter != mChildren.end())
00191         {
00192                 this->mChildren.erase(iter);
00193         }
00194         joint->mXform.setParent(NULL);
00195         joint->mParent = NULL;
00196         joint->touch();
00197 }
00198 
00199 
00200 
00201 
00202 
00203 void LLJoint::removeAllChildren()
00204 {
00205         for (child_list_t::iterator iter = mChildren.begin();
00206                  iter != mChildren.end();)
00207         {
00208                 child_list_t::iterator curiter = iter++;
00209                 LLJoint* joint = *curiter;
00210                 mChildren.erase(curiter);
00211                 joint->mXform.setParent(NULL);
00212                 joint->mParent = NULL;
00213                 joint->touch();
00214         }
00215 }
00216 
00217 
00218 
00219 
00220 
00221 const LLVector3& LLJoint::getPosition()
00222 {
00223         return mXform.getPosition();
00224 }
00225 
00226 
00227 
00228 
00229 
00230 void LLJoint::setPosition( const LLVector3& pos )
00231 {
00232 
00233         {
00234                 mXform.setPosition(pos);
00235                 touch(MATRIX_DIRTY | POSITION_DIRTY);
00236         }
00237 }
00238 
00239 
00240 
00241 
00242 
00243 LLVector3 LLJoint::getWorldPosition()
00244 {
00245         updateWorldPRSParent();
00246         return mXform.getWorldPosition();
00247 }
00248 
00249 
00250 
00251 
00252 LLVector3 LLJoint::getLastWorldPosition()
00253 {
00254         return mXform.getWorldPosition();
00255 }
00256 
00257 
00258 
00259 
00260 
00261 void LLJoint::setWorldPosition( const LLVector3& pos )
00262 {
00263         if (mParent == NULL)
00264         {
00265                 this->setPosition( pos );
00266                 return;
00267         }
00268 
00269         LLMatrix4 temp_matrix = getWorldMatrix();
00270         temp_matrix.mMatrix[VW][VX] = pos.mV[VX];
00271         temp_matrix.mMatrix[VW][VY] = pos.mV[VY];
00272         temp_matrix.mMatrix[VW][VZ] = pos.mV[VZ];
00273 
00274         LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
00275         LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
00276 
00277         temp_matrix *= invParentWorldMatrix;
00278 
00279         LLVector3 localPos(     temp_matrix.mMatrix[VW][VX],
00280                                                 temp_matrix.mMatrix[VW][VY],
00281                                                 temp_matrix.mMatrix[VW][VZ] );
00282 
00283         setPosition( localPos );
00284 }
00285 
00286 
00287 
00288 
00289 
00290 const LLQuaternion& LLJoint::getRotation()
00291 {
00292         return mXform.getRotation();
00293 }
00294 
00295 
00296 
00297 
00298 
00299 void LLJoint::setRotation( const LLQuaternion& rot )
00300 {
00301         if (rot.isFinite())
00302         {
00303         
00304                 {
00305                         mXform.setRotation(rot);
00306                         touch(MATRIX_DIRTY | ROTATION_DIRTY);
00307                 }
00308         }
00309 }
00310 
00311 
00312 
00313 
00314 
00315 LLQuaternion LLJoint::getWorldRotation()
00316 {
00317         updateWorldPRSParent();
00318 
00319         return mXform.getWorldRotation();
00320 }
00321 
00322 
00323 
00324 
00325 LLQuaternion LLJoint::getLastWorldRotation()
00326 {
00327         return mXform.getWorldRotation();
00328 }
00329 
00330 
00331 
00332 
00333 void LLJoint::setWorldRotation( const LLQuaternion& rot )
00334 {
00335         if (mParent == NULL)
00336         {
00337                 this->setRotation( rot );
00338                 return;
00339         }
00340 
00341         LLMatrix4 temp_mat(rot);
00342 
00343         LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
00344         parentWorldMatrix.mMatrix[VW][VX] = 0;
00345         parentWorldMatrix.mMatrix[VW][VY] = 0;
00346         parentWorldMatrix.mMatrix[VW][VZ] = 0;
00347 
00348         LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
00349 
00350         temp_mat *= invParentWorldMatrix;
00351 
00352         setRotation(LLQuaternion(temp_mat));
00353 }
00354 
00355 
00356 
00357 
00358 
00359 const LLVector3& LLJoint::getScale()
00360 {
00361         return mXform.getScale();
00362 }
00363 
00364 
00365 
00366 
00367 void LLJoint::setScale( const LLVector3& scale )
00368 {
00369 
00370         {
00371                 mXform.setScale(scale);
00372                 touch();
00373         }
00374 
00375 }
00376 
00377 
00378 
00379 
00380 
00381 
00382 const LLMatrix4 &LLJoint::getWorldMatrix()
00383 {
00384         updateWorldMatrixParent();
00385 
00386         return mXform.getWorldMatrix();
00387 }
00388 
00389 
00390 
00391 
00392 
00393 void LLJoint::setWorldMatrix( const LLMatrix4& mat )
00394 {
00395 llinfos << "WARNING: LLJoint::setWorldMatrix() not correctly implemented yet" << llendl;
00396         
00397         LLVector3 trans(        mat.mMatrix[VW][VX],
00398                                                 mat.mMatrix[VW][VY],
00399                                                 mat.mMatrix[VW][VZ] );
00400 
00401         
00402         LLQuaternion rot( mat );
00403 
00404         setWorldPosition( trans );
00405         setWorldRotation( rot );
00406 }
00407 
00408 
00409 
00410 
00411 void LLJoint::updateWorldMatrixParent()
00412 {
00413         if (mDirtyFlags & MATRIX_DIRTY)
00414         {
00415                 LLJoint *parent = getParent();
00416                 if (parent)
00417                 {
00418                         parent->updateWorldMatrixParent();
00419                 }
00420                 updateWorldMatrix();
00421         }
00422 }
00423 
00424 
00425 
00426 
00427 void LLJoint::updateWorldPRSParent()
00428 {
00429         if (mDirtyFlags & (ROTATION_DIRTY | POSITION_DIRTY))
00430         {
00431                 LLJoint *parent = getParent();
00432                 if (parent)
00433                 {
00434                         parent->updateWorldPRSParent();
00435                 }
00436 
00437                 mXform.update();
00438                 mDirtyFlags &= ~(ROTATION_DIRTY | POSITION_DIRTY);
00439         }
00440 }
00441 
00442 
00443 
00444 
00445 void LLJoint::updateWorldMatrixChildren()
00446 {       
00447         if (!this->mUpdateXform) return;
00448 
00449         if (mDirtyFlags & MATRIX_DIRTY)
00450         {
00451                 updateWorldMatrix();
00452         }
00453         for (child_list_t::iterator iter = mChildren.begin();
00454                  iter != mChildren.end(); ++iter)
00455         {
00456                 LLJoint* joint = *iter;
00457                 joint->updateWorldMatrixChildren();
00458         }
00459 }
00460 
00461 
00462 
00463 
00464 void LLJoint::updateWorldMatrix()
00465 {
00466         if (mDirtyFlags & MATRIX_DIRTY)
00467         {
00468                 sNumUpdates++;
00469                 mXform.updateMatrix(FALSE);
00470                 mDirtyFlags = 0x0;
00471         }
00472 }
00473 
00474 
00475 
00476 
00477 const LLVector3 &LLJoint::getSkinOffset()
00478 {
00479         return mSkinOffset;
00480 }
00481 
00482 
00483 
00484 
00485 
00486 void LLJoint::setSkinOffset( const LLVector3& offset )
00487 {
00488         mSkinOffset = offset;
00489 }
00490 
00491 
00492 
00493 
00494 
00495 void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot)
00496 {
00497         LLVector3 main_axis(1.f, 0.f, 0.f);
00498 
00499         for (child_list_t::iterator iter = mChildren.begin();
00500                  iter != mChildren.end(); ++iter)
00501         {
00502                 LLJoint* joint = *iter;
00503                 if (joint->isAnimatable())
00504                 {
00505                         main_axis = joint->getPosition();
00506                         main_axis.normVec();
00507                         
00508                         break;
00509                 }
00510         }
00511 
00512         
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522                 
00523 
00524 
00525 }
00526 
00527