lljointsolverrp3.cpp

Go to the documentation of this file.
00001 
00032 //-----------------------------------------------------------------------------
00033 // Header Files
00034 //-----------------------------------------------------------------------------
00035 #include "linden_common.h"
00036 
00037 #include "lljointsolverrp3.h"
00038 
00039 #include "llmath.h"
00040 
00041 #define F_EPSILON 0.00001f
00042 
00043 
00044 //-----------------------------------------------------------------------------
00045 // Constructor
00046 //-----------------------------------------------------------------------------
00047 LLJointSolverRP3::LLJointSolverRP3()
00048 {
00049         mJointA = NULL;
00050         mJointB = NULL;
00051         mJointC = NULL;
00052         mJointGoal = NULL;
00053         mLengthAB = 1.0f;
00054         mLengthBC = 1.0f;
00055         mPoleVector.setVec( 1.0f, 0.0f, 0.0f );
00056         mbUseBAxis = FALSE;
00057         mTwist = 0.0f;
00058         mFirstTime = TRUE;
00059 }
00060 
00061 
00062 //-----------------------------------------------------------------------------
00063 // Destructor
00064 //-----------------------------------------------------------------------------
00065 /*virtual*/ LLJointSolverRP3::~LLJointSolverRP3()
00066 {
00067 }
00068 
00069 
00070 //-----------------------------------------------------------------------------
00071 // setupJoints()
00072 //-----------------------------------------------------------------------------
00073 void LLJointSolverRP3::setupJoints(     LLJoint* jointA,
00074                                                                         LLJoint* jointB,
00075                                                                         LLJoint* jointC,
00076                                                                         LLJoint* jointGoal )
00077 {
00078         mJointA = jointA;
00079         mJointB = jointB;
00080         mJointC = jointC;
00081         mJointGoal = jointGoal;
00082 
00083         mLengthAB = mJointB->getPosition().magVec();
00084         mLengthBC = mJointC->getPosition().magVec();
00085 
00086         mJointABaseRotation = jointA->getRotation();
00087         mJointBBaseRotation = jointB->getRotation();
00088 }
00089 
00090 
00091 //-----------------------------------------------------------------------------
00092 // getPoleVector()
00093 //-----------------------------------------------------------------------------
00094 const LLVector3& LLJointSolverRP3::getPoleVector()
00095 {
00096         return mPoleVector;
00097 }
00098 
00099 
00100 //-----------------------------------------------------------------------------
00101 // setPoleVector()
00102 //-----------------------------------------------------------------------------
00103 void LLJointSolverRP3::setPoleVector( const LLVector3& poleVector )
00104 {
00105         mPoleVector = poleVector;
00106         mPoleVector.normVec();
00107 }
00108 
00109 
00110 //-----------------------------------------------------------------------------
00111 // setPoleVector()
00112 //-----------------------------------------------------------------------------
00113 void LLJointSolverRP3::setBAxis( const LLVector3& bAxis )
00114 {
00115         mBAxis = bAxis;
00116         mBAxis.normVec();
00117         mbUseBAxis = TRUE;
00118 }
00119 
00120 //-----------------------------------------------------------------------------
00121 // getTwist()
00122 //-----------------------------------------------------------------------------
00123 F32 LLJointSolverRP3::getTwist()
00124 {
00125         return mTwist;
00126 }
00127 
00128 
00129 //-----------------------------------------------------------------------------
00130 // setTwist()
00131 //-----------------------------------------------------------------------------
00132 void LLJointSolverRP3::setTwist( F32 twist )
00133 {
00134         mTwist = twist;
00135 }
00136 
00137 
00138 //-----------------------------------------------------------------------------
00139 // solve()
00140 //-----------------------------------------------------------------------------
00141 void LLJointSolverRP3::solve()
00142 {
00143 //      llinfos << llendl;
00144 //      llinfos << "LLJointSolverRP3::solve()" << llendl;
00145 
00146         //-------------------------------------------------------------------------
00147         // setup joints in their base rotations
00148         //-------------------------------------------------------------------------
00149         mJointA->setRotation( mJointABaseRotation );
00150         mJointB->setRotation( mJointBBaseRotation );
00151 
00152         //-------------------------------------------------------------------------
00153         // get joint positions in world space
00154         //-------------------------------------------------------------------------
00155         LLVector3 aPos = mJointA->getWorldPosition();
00156         LLVector3 bPos = mJointB->getWorldPosition();
00157         LLVector3 cPos = mJointC->getWorldPosition();
00158         LLVector3 gPos = mJointGoal->getWorldPosition();
00159 
00160 //      llinfos << "bPosLocal = " << mJointB->getPosition() << llendl;
00161 //      llinfos << "cPosLocal = " << mJointC->getPosition() << llendl;
00162 //      llinfos << "bRotLocal = " << mJointB->getRotation() << llendl;
00163 //      llinfos << "cRotLocal = " << mJointC->getRotation() << llendl;
00164 
00165 //      llinfos << "aPos : " << aPos << llendl;
00166 //      llinfos << "bPos : " << bPos << llendl;
00167 //      llinfos << "cPos : " << cPos << llendl;
00168 //      llinfos << "gPos : " << gPos << llendl;
00169 
00170         //-------------------------------------------------------------------------
00171         // get the poleVector in world space
00172         //-------------------------------------------------------------------------
00173         LLMatrix4 worldJointAParentMat;
00174         if ( mJointA->getParent() )
00175         {
00176                 worldJointAParentMat = mJointA->getParent()->getWorldMatrix();
00177         }
00178         LLVector3 poleVec = rotate_vector( mPoleVector, worldJointAParentMat );
00179 
00180         //-------------------------------------------------------------------------
00181         // compute the following:
00182         // vector from A to B
00183         // vector from B to C
00184         // vector from A to C
00185         // vector from A to G (goal)
00186         //-------------------------------------------------------------------------
00187         LLVector3 abVec = bPos - aPos;
00188         LLVector3 bcVec = cPos - bPos;
00189         LLVector3 acVec = cPos - aPos;
00190         LLVector3 agVec = gPos - aPos;
00191 
00192 //      llinfos << "abVec : " << abVec << llendl;
00193 //      llinfos << "bcVec : " << bcVec << llendl;
00194 //      llinfos << "acVec : " << acVec << llendl;
00195 //      llinfos << "agVec : " << agVec << llendl;
00196 
00197         //-------------------------------------------------------------------------
00198         // compute needed lengths of those vectors
00199         //-------------------------------------------------------------------------
00200         F32 abLen = abVec.magVec();
00201         F32 bcLen = bcVec.magVec();
00202         F32 agLen = agVec.magVec();
00203 
00204 //      llinfos << "abLen : " << abLen << llendl;
00205 //      llinfos << "bcLen : " << bcLen << llendl;
00206 //      llinfos << "agLen : " << agLen << llendl;
00207 
00208         //-------------------------------------------------------------------------
00209         // compute component vector of (A->B) orthogonal to (A->C)
00210         //-------------------------------------------------------------------------
00211         LLVector3 abacCompOrthoVec = abVec - acVec * ((abVec * acVec)/(acVec * acVec));
00212 
00213 //      llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl
00214 
00215         //-------------------------------------------------------------------------
00216         // compute the normal of the original ABC plane (and store for later)
00217         //-------------------------------------------------------------------------
00218         LLVector3 abcNorm;
00219         if (!mbUseBAxis)
00220         {
00221                 if( are_parallel(abVec, bcVec, 0.001f) )
00222                 {
00223                         // the current solution is maxed out, so we use the axis that is
00224                         // orthogonal to both poleVec and A->B
00225                         if ( are_parallel(poleVec, abVec, 0.001f) )
00226                         {
00227                                 // ACK! the problem is singular
00228                                 if ( are_parallel(poleVec, agVec, 0.001f) )
00229                                 {
00230                                         // the solutions is also singular
00231                                         return;
00232                                 }
00233                                 else
00234                                 {
00235                                         abcNorm = poleVec % agVec;
00236                                 }
00237                         }
00238                         else
00239                         {
00240                                 abcNorm = poleVec % abVec;
00241                         }
00242                 }
00243                 else
00244                 {
00245                         abcNorm = abVec % bcVec;
00246                 }
00247         }
00248         else
00249         {
00250                 abcNorm = mBAxis * mJointB->getWorldRotation();
00251         }
00252 
00253         //-------------------------------------------------------------------------
00254         // compute rotation of B
00255         //-------------------------------------------------------------------------
00256         // angle between A->B and B->C
00257         F32 abbcAng = angle_between(abVec, bcVec);
00258 
00259         // vector orthogonal to A->B and B->C
00260         LLVector3 abbcOrthoVec = abVec % bcVec;
00261         if (abbcOrthoVec.magVecSquared() < 0.001f)
00262         {
00263                 abbcOrthoVec = poleVec % abVec;
00264                 abacCompOrthoVec = poleVec;
00265         }
00266         abbcOrthoVec.normVec();
00267 
00268         F32 agLenSq = agLen * agLen;
00269 
00270         // angle arm for extension
00271         F32 cosTheta =  (agLenSq - abLen*abLen - bcLen*bcLen) / (2.0f * abLen * bcLen);
00272         if (cosTheta > 1.0f)
00273                 cosTheta = 1.0f;
00274         else if (cosTheta < -1.0f)
00275                 cosTheta = -1.0f;
00276 
00277         F32 theta = acos(cosTheta);
00278 
00279         LLQuaternion bRot(theta - abbcAng, abbcOrthoVec);
00280 
00281 //      llinfos << "abbcAng      : " << abbcAng << llendl;
00282 //      llinfos << "abbcOrthoVec : " << abbcOrthoVec << llendl;
00283 //      llinfos << "agLenSq      : " << agLenSq << llendl;
00284 //      llinfos << "cosTheta     : " << cosTheta << llendl;
00285 //      llinfos << "theta        : " << theta << llendl;
00286 //      llinfos << "bRot         : " << bRot << llendl;
00287 //      llinfos << "theta abbcAng theta-abbcAng: " << theta*180.0/F_PI << " " << abbcAng*180.0f/F_PI << " " << (theta - abbcAng)*180.0f/F_PI << llendl;
00288 
00289         //-------------------------------------------------------------------------
00290         // compute rotation that rotates new A->C to A->G
00291         //-------------------------------------------------------------------------
00292         // rotate B->C by bRot
00293         bcVec = bcVec * bRot;
00294 
00295         // update A->C
00296         acVec = abVec + bcVec;
00297 
00298         LLQuaternion cgRot;
00299         cgRot.shortestArc( acVec, agVec );
00300 
00301 //      llinfos << "bcVec : " << bcVec << llendl;
00302 //      llinfos << "acVec : " << acVec << llendl;
00303 //      llinfos << "cgRot : " << cgRot << llendl;
00304 
00305         // update A->B and B->C with rotation from C to G
00306         abVec = abVec * cgRot;
00307         bcVec = bcVec * cgRot;
00308         abcNorm = abcNorm * cgRot;
00309         acVec = abVec + bcVec;
00310 
00311         //-------------------------------------------------------------------------
00312         // compute the normal of the APG plane
00313         //-------------------------------------------------------------------------
00314         if (are_parallel(agVec, poleVec, 0.001f))
00315         {
00316                 // the solution plane is undefined ==> we're done
00317                 return;
00318         }
00319         LLVector3 apgNorm = poleVec % agVec;
00320         apgNorm.normVec();
00321 
00322         if (!mbUseBAxis)
00323         {
00324                 //---------------------------------------------------------------------
00325                 // compute the normal of the new ABC plane
00326                 // (only necessary if we're NOT using mBAxis)
00327                 //---------------------------------------------------------------------
00328                 if( are_parallel(abVec, bcVec, 0.001f) )
00329                 {
00330                         // G is either too close or too far away
00331                         // we'll use the old ABCnormal 
00332                 }
00333                 else
00334                 {
00335                         abcNorm = abVec % bcVec;
00336                 }
00337                 abcNorm.normVec();
00338         }
00339 
00340         //-------------------------------------------------------------------------
00341         // calcuate plane rotation
00342         //-------------------------------------------------------------------------
00343         LLQuaternion pRot;
00344         if ( are_parallel( abcNorm, apgNorm, 0.001f) )
00345         {
00346                 if (abcNorm * apgNorm < 0.0f)
00347                 {
00348                         // we must be PI radians off ==> rotate by PI around agVec
00349                         pRot.setQuat(F_PI, agVec);
00350                 }
00351                 else
00352                 {
00353                         // we're done
00354                 }
00355         }
00356         else
00357         {
00358                 pRot.shortestArc( abcNorm, apgNorm );
00359         }
00360 
00361 //      llinfos << "abcNorm = " << abcNorm << llendl;
00362 //      llinfos << "apgNorm = " << apgNorm << llendl;
00363 //      llinfos << "pRot = " << pRot << llendl;
00364 
00365         //-------------------------------------------------------------------------
00366         // compute twist rotation
00367         //-------------------------------------------------------------------------
00368         LLQuaternion twistRot( mTwist, agVec );
00369 
00370 //      llinfos << "twist    : " << mTwist*180.0/F_PI << llendl;
00371 //      llinfos << "agNormVec: " << agNormVec << llendl;
00372 //      llinfos << "twistRot : " << twistRot << llendl;
00373 
00374         //-------------------------------------------------------------------------
00375         // compute rotation of A
00376         //-------------------------------------------------------------------------
00377         LLQuaternion aRot = cgRot * pRot * twistRot;
00378 
00379         //-------------------------------------------------------------------------
00380         // apply the rotations
00381         //-------------------------------------------------------------------------
00382         mJointB->setWorldRotation( mJointB->getWorldRotation() * bRot );
00383         mJointA->setWorldRotation( mJointA->getWorldRotation() * aRot );
00384 }
00385 
00386 
00387 // End

Generated on Thu Jul 1 06:08:47 2010 for Second Life Viewer by  doxygen 1.4.7