aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcharacter/lljointsolverrp3.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llcharacter/lljointsolverrp3.cpp
parentREADME.txt (diff)
downloadmeta-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.cpp385
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//-----------------------------------------------------------------------------
45LLJointSolverRP3::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//-----------------------------------------------------------------------------
71void 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//-----------------------------------------------------------------------------
92const LLVector3& LLJointSolverRP3::getPoleVector()
93{
94 return mPoleVector;
95}
96
97
98//-----------------------------------------------------------------------------
99// setPoleVector()
100//-----------------------------------------------------------------------------
101void LLJointSolverRP3::setPoleVector( const LLVector3& poleVector )
102{
103 mPoleVector = poleVector;
104 mPoleVector.normVec();
105}
106
107
108//-----------------------------------------------------------------------------
109// setPoleVector()
110//-----------------------------------------------------------------------------
111void LLJointSolverRP3::setBAxis( const LLVector3& bAxis )
112{
113 mBAxis = bAxis;
114 mBAxis.normVec();
115 mbUseBAxis = TRUE;
116}
117
118//-----------------------------------------------------------------------------
119// getTwist()
120//-----------------------------------------------------------------------------
121F32 LLJointSolverRP3::getTwist()
122{
123 return mTwist;
124}
125
126
127//-----------------------------------------------------------------------------
128// setTwist()
129//-----------------------------------------------------------------------------
130void LLJointSolverRP3::setTwist( F32 twist )
131{
132 mTwist = twist;
133}
134
135
136//-----------------------------------------------------------------------------
137// solve()
138//-----------------------------------------------------------------------------
139void 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