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