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