lljointsolverrp3.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:12k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lljointsolverrp3.cpp
  3.  * @brief Implementation of LLJointSolverRP3 class.
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. //-----------------------------------------------------------------------------
  33. // Header Files
  34. //-----------------------------------------------------------------------------
  35. #include "linden_common.h"
  36. #include "lljointsolverrp3.h"
  37. #include "llmath.h"
  38. #define F_EPSILON 0.00001f
  39. //-----------------------------------------------------------------------------
  40. // Constructor
  41. //-----------------------------------------------------------------------------
  42. LLJointSolverRP3::LLJointSolverRP3()
  43. {
  44. mJointA = NULL;
  45. mJointB = NULL;
  46. mJointC = NULL;
  47. mJointGoal = NULL;
  48. mLengthAB = 1.0f;
  49. mLengthBC = 1.0f;
  50. mPoleVector.setVec( 1.0f, 0.0f, 0.0f );
  51. mbUseBAxis = FALSE;
  52. mTwist = 0.0f;
  53. mFirstTime = TRUE;
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Destructor
  57. //-----------------------------------------------------------------------------
  58. /*virtual*/ LLJointSolverRP3::~LLJointSolverRP3()
  59. {
  60. }
  61. //-----------------------------------------------------------------------------
  62. // setupJoints()
  63. //-----------------------------------------------------------------------------
  64. void LLJointSolverRP3::setupJoints( LLJoint* jointA,
  65. LLJoint* jointB,
  66. LLJoint* jointC,
  67. LLJoint* jointGoal )
  68. {
  69. mJointA = jointA;
  70. mJointB = jointB;
  71. mJointC = jointC;
  72. mJointGoal = jointGoal;
  73. mLengthAB = mJointB->getPosition().magVec();
  74. mLengthBC = mJointC->getPosition().magVec();
  75. mJointABaseRotation = jointA->getRotation();
  76. mJointBBaseRotation = jointB->getRotation();
  77. }
  78. //-----------------------------------------------------------------------------
  79. // getPoleVector()
  80. //-----------------------------------------------------------------------------
  81. const LLVector3& LLJointSolverRP3::getPoleVector()
  82. {
  83. return mPoleVector;
  84. }
  85. //-----------------------------------------------------------------------------
  86. // setPoleVector()
  87. //-----------------------------------------------------------------------------
  88. void LLJointSolverRP3::setPoleVector( const LLVector3& poleVector )
  89. {
  90. mPoleVector = poleVector;
  91. mPoleVector.normVec();
  92. }
  93. //-----------------------------------------------------------------------------
  94. // setPoleVector()
  95. //-----------------------------------------------------------------------------
  96. void LLJointSolverRP3::setBAxis( const LLVector3& bAxis )
  97. {
  98. mBAxis = bAxis;
  99. mBAxis.normVec();
  100. mbUseBAxis = TRUE;
  101. }
  102. //-----------------------------------------------------------------------------
  103. // getTwist()
  104. //-----------------------------------------------------------------------------
  105. F32 LLJointSolverRP3::getTwist()
  106. {
  107. return mTwist;
  108. }
  109. //-----------------------------------------------------------------------------
  110. // setTwist()
  111. //-----------------------------------------------------------------------------
  112. void LLJointSolverRP3::setTwist( F32 twist )
  113. {
  114. mTwist = twist;
  115. }
  116. //-----------------------------------------------------------------------------
  117. // solve()
  118. //-----------------------------------------------------------------------------
  119. void LLJointSolverRP3::solve()
  120. {
  121. // llinfos << llendl;
  122. // llinfos << "LLJointSolverRP3::solve()" << llendl;
  123. //-------------------------------------------------------------------------
  124. // setup joints in their base rotations
  125. //-------------------------------------------------------------------------
  126. mJointA->setRotation( mJointABaseRotation );
  127. mJointB->setRotation( mJointBBaseRotation );
  128. //-------------------------------------------------------------------------
  129. // get joint positions in world space
  130. //-------------------------------------------------------------------------
  131. LLVector3 aPos = mJointA->getWorldPosition();
  132. LLVector3 bPos = mJointB->getWorldPosition();
  133. LLVector3 cPos = mJointC->getWorldPosition();
  134. LLVector3 gPos = mJointGoal->getWorldPosition();
  135. // llinfos << "bPosLocal = " << mJointB->getPosition() << llendl;
  136. // llinfos << "cPosLocal = " << mJointC->getPosition() << llendl;
  137. // llinfos << "bRotLocal = " << mJointB->getRotation() << llendl;
  138. // llinfos << "cRotLocal = " << mJointC->getRotation() << llendl;
  139. // llinfos << "aPos : " << aPos << llendl;
  140. // llinfos << "bPos : " << bPos << llendl;
  141. // llinfos << "cPos : " << cPos << llendl;
  142. // llinfos << "gPos : " << gPos << llendl;
  143. //-------------------------------------------------------------------------
  144. // get the poleVector in world space
  145. //-------------------------------------------------------------------------
  146. LLMatrix4 worldJointAParentMat;
  147. if ( mJointA->getParent() )
  148. {
  149. worldJointAParentMat = mJointA->getParent()->getWorldMatrix();
  150. }
  151. LLVector3 poleVec = rotate_vector( mPoleVector, worldJointAParentMat );
  152. //-------------------------------------------------------------------------
  153. // compute the following:
  154. // vector from A to B
  155. // vector from B to C
  156. // vector from A to C
  157. // vector from A to G (goal)
  158. //-------------------------------------------------------------------------
  159. LLVector3 abVec = bPos - aPos;
  160. LLVector3 bcVec = cPos - bPos;
  161. LLVector3 acVec = cPos - aPos;
  162. LLVector3 agVec = gPos - aPos;
  163. // llinfos << "abVec : " << abVec << llendl;
  164. // llinfos << "bcVec : " << bcVec << llendl;
  165. // llinfos << "acVec : " << acVec << llendl;
  166. // llinfos << "agVec : " << agVec << llendl;
  167. //-------------------------------------------------------------------------
  168. // compute needed lengths of those vectors
  169. //-------------------------------------------------------------------------
  170. F32 abLen = abVec.magVec();
  171. F32 bcLen = bcVec.magVec();
  172. F32 agLen = agVec.magVec();
  173. // llinfos << "abLen : " << abLen << llendl;
  174. // llinfos << "bcLen : " << bcLen << llendl;
  175. // llinfos << "agLen : " << agLen << llendl;
  176. //-------------------------------------------------------------------------
  177. // compute component vector of (A->B) orthogonal to (A->C)
  178. //-------------------------------------------------------------------------
  179. LLVector3 abacCompOrthoVec = abVec - acVec * ((abVec * acVec)/(acVec * acVec));
  180. // llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl;
  181. //-------------------------------------------------------------------------
  182. // compute the normal of the original ABC plane (and store for later)
  183. //-------------------------------------------------------------------------
  184. LLVector3 abcNorm;
  185. if (!mbUseBAxis)
  186. {
  187. if( are_parallel(abVec, bcVec, 0.001f) )
  188. {
  189. // the current solution is maxed out, so we use the axis that is
  190. // orthogonal to both poleVec and A->B
  191. if ( are_parallel(poleVec, abVec, 0.001f) )
  192. {
  193. // ACK! the problem is singular
  194. if ( are_parallel(poleVec, agVec, 0.001f) )
  195. {
  196. // the solutions is also singular
  197. return;
  198. }
  199. else
  200. {
  201. abcNorm = poleVec % agVec;
  202. }
  203. }
  204. else
  205. {
  206. abcNorm = poleVec % abVec;
  207. }
  208. }
  209. else
  210. {
  211. abcNorm = abVec % bcVec;
  212. }
  213. }
  214. else
  215. {
  216. abcNorm = mBAxis * mJointB->getWorldRotation();
  217. }
  218. //-------------------------------------------------------------------------
  219. // compute rotation of B
  220. //-------------------------------------------------------------------------
  221. // angle between A->B and B->C
  222. F32 abbcAng = angle_between(abVec, bcVec);
  223. // vector orthogonal to A->B and B->C
  224. LLVector3 abbcOrthoVec = abVec % bcVec;
  225. if (abbcOrthoVec.magVecSquared() < 0.001f)
  226. {
  227. abbcOrthoVec = poleVec % abVec;
  228. abacCompOrthoVec = poleVec;
  229. }
  230. abbcOrthoVec.normVec();
  231. F32 agLenSq = agLen * agLen;
  232. // angle arm for extension
  233. F32 cosTheta = (agLenSq - abLen*abLen - bcLen*bcLen) / (2.0f * abLen * bcLen);
  234. if (cosTheta > 1.0f)
  235. cosTheta = 1.0f;
  236. else if (cosTheta < -1.0f)
  237. cosTheta = -1.0f;
  238. F32 theta = acos(cosTheta);
  239. LLQuaternion bRot(theta - abbcAng, abbcOrthoVec);
  240. // llinfos << "abbcAng      : " << abbcAng << llendl;
  241. // llinfos << "abbcOrthoVec : " << abbcOrthoVec << llendl;
  242. // llinfos << "agLenSq      : " << agLenSq << llendl;
  243. // llinfos << "cosTheta     : " << cosTheta << llendl;
  244. // llinfos << "theta        : " << theta << llendl;
  245. // llinfos << "bRot         : " << bRot << llendl;
  246. // llinfos << "theta abbcAng theta-abbcAng: " << theta*180.0/F_PI << " " << abbcAng*180.0f/F_PI << " " << (theta - abbcAng)*180.0f/F_PI << llendl;
  247. //-------------------------------------------------------------------------
  248. // compute rotation that rotates new A->C to A->G
  249. //-------------------------------------------------------------------------
  250. // rotate B->C by bRot
  251. bcVec = bcVec * bRot;
  252. // update A->C
  253. acVec = abVec + bcVec;
  254. LLQuaternion cgRot;
  255. cgRot.shortestArc( acVec, agVec );
  256. // llinfos << "bcVec : " << bcVec << llendl;
  257. // llinfos << "acVec : " << acVec << llendl;
  258. // llinfos << "cgRot : " << cgRot << llendl;
  259. // update A->B and B->C with rotation from C to G
  260. abVec = abVec * cgRot;
  261. bcVec = bcVec * cgRot;
  262. abcNorm = abcNorm * cgRot;
  263. acVec = abVec + bcVec;
  264. //-------------------------------------------------------------------------
  265. // compute the normal of the APG plane
  266. //-------------------------------------------------------------------------
  267. if (are_parallel(agVec, poleVec, 0.001f))
  268. {
  269. // the solution plane is undefined ==> we're done
  270. return;
  271. }
  272. LLVector3 apgNorm = poleVec % agVec;
  273. apgNorm.normVec();
  274. if (!mbUseBAxis)
  275. {
  276. //---------------------------------------------------------------------
  277. // compute the normal of the new ABC plane
  278. // (only necessary if we're NOT using mBAxis)
  279. //---------------------------------------------------------------------
  280. if( are_parallel(abVec, bcVec, 0.001f) )
  281. {
  282. // G is either too close or too far away
  283. // we'll use the old ABCnormal 
  284. }
  285. else
  286. {
  287. abcNorm = abVec % bcVec;
  288. }
  289. abcNorm.normVec();
  290. }
  291. //-------------------------------------------------------------------------
  292. // calcuate plane rotation
  293. //-------------------------------------------------------------------------
  294. LLQuaternion pRot;
  295. if ( are_parallel( abcNorm, apgNorm, 0.001f) )
  296. {
  297. if (abcNorm * apgNorm < 0.0f)
  298. {
  299. // we must be PI radians off ==> rotate by PI around agVec
  300. pRot.setQuat(F_PI, agVec);
  301. }
  302. else
  303. {
  304. // we're done
  305. }
  306. }
  307. else
  308. {
  309. pRot.shortestArc( abcNorm, apgNorm );
  310. }
  311. // llinfos << "abcNorm = " << abcNorm << llendl;
  312. // llinfos << "apgNorm = " << apgNorm << llendl;
  313. // llinfos << "pRot = " << pRot << llendl;
  314. //-------------------------------------------------------------------------
  315. // compute twist rotation
  316. //-------------------------------------------------------------------------
  317. LLQuaternion twistRot( mTwist, agVec );
  318. // llinfos << "twist    : " << mTwist*180.0/F_PI << llendl;
  319. // llinfos << "agNormVec: " << agNormVec << llendl;
  320. // llinfos << "twistRot : " << twistRot << llendl;
  321. //-------------------------------------------------------------------------
  322. // compute rotation of A
  323. //-------------------------------------------------------------------------
  324. LLQuaternion aRot = cgRot * pRot * twistRot;
  325. //-------------------------------------------------------------------------
  326. // apply the rotations
  327. //-------------------------------------------------------------------------
  328. mJointB->setWorldRotation( mJointB->getWorldRotation() * bRot );
  329. mJointA->setWorldRotation( mJointA->getWorldRotation() * aRot );
  330. }
  331. // End