aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath/llquaternion.h
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/llmath/llquaternion.h
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/llmath/llquaternion.h')
-rw-r--r--linden/indra/llmath/llquaternion.h461
1 files changed, 461 insertions, 0 deletions
diff --git a/linden/indra/llmath/llquaternion.h b/linden/indra/llmath/llquaternion.h
new file mode 100644
index 0000000..1e3f2b6
--- /dev/null
+++ b/linden/indra/llmath/llquaternion.h
@@ -0,0 +1,461 @@
1/**
2 * @file llquaternion.h
3 * @brief LLQuaternion class header file.
4 *
5 * Copyright (c) 2000-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#ifndef LLQUATERNION_H
29#define LLQUATERNION_H
30
31#include "llmath.h"
32
33class LLVector4;
34class LLVector3;
35class LLVector3d;
36class LLMatrix4;
37class LLMatrix3;
38
39// NOTA BENE: Quaternion code is written assuming Unit Quaternions!!!!
40// Moreover, it is written assuming that all vectors and matricies
41// passed as arguments are normalized and unitary respectively.
42// VERY VERY VERY VERY BAD THINGS will happen if these assumptions fail.
43
44static const U32 LENGTHOFQUAT = 4;
45
46class LLQuaternion
47{
48public:
49 F32 mQ[LENGTHOFQUAT];
50
51 static const LLQuaternion DEFAULT;
52
53 LLQuaternion(); // Initializes Quaternion to (0,0,0,1)
54 explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4
55 explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3
56 LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normQuat(x, y, z, w)
57 LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec)
58 LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec)
59 LLQuaternion(const F32 *q); // Initializes Quaternion to normQuat(x, y, z, w)
60 LLQuaternion(const LLVector3 &x_axis,
61 const LLVector3 &y_axis,
62 const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis]
63
64 BOOL isIdentity() const;
65 BOOL isNotIdentity() const;
66 BOOL isFinite() const; // checks to see if all values of LLQuaternion are finite
67 void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization
68 void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization
69 void loadIdentity(); // Loads the quaternion that represents the identity rotation
70 const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normQuat(x, y, z, w)
71 const LLQuaternion& setQuat(const LLQuaternion &quat); // Copies Quaternion
72 const LLQuaternion& setQuat(const F32 *q); // Sets Quaternion to normQuat(quat[VX], quat[VY], quat[VZ], quat[VW])
73 const LLQuaternion& setQuat(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat)
74 const LLQuaternion& setQuat(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat)
75 const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z)
76 const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec)
77 const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec)
78 const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll)
79
80 LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion
81 LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion
82 void getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const; // returns rotation in radians about axis x,y,z
83 void getAngleAxis(F32* angle, LLVector3 &vec) const;
84 void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const;
85
86 F32 normQuat(); // Normalizes Quaternion and returns magnitude
87 const LLQuaternion& conjQuat(void); // Conjugates Quaternion and returns result
88
89 // Other useful methods
90 const LLQuaternion& transQuat(); // Transpose
91 void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b
92 const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians
93
94 // Standard operators
95 friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a); // Prints a
96 friend LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b); // Addition
97 friend LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b); // Subtraction
98 friend LLQuaternion operator-(const LLQuaternion &a); // Negation
99 friend LLQuaternion operator*(F32 a, const LLQuaternion &q); // Scale
100 friend LLQuaternion operator*(const LLQuaternion &q, F32 b); // Scale
101 friend LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b); // Returns a * b
102 friend LLQuaternion operator~(const LLQuaternion &a); // Returns a* (Conjugate of a)
103 bool operator==(const LLQuaternion &b) const; // Returns a == b
104 bool operator!=(const LLQuaternion &b) const; // Returns a != b
105
106 friend const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b); // Returns a * b
107
108 friend LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot); // Rotates a by rot
109 friend LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot); // Rotates a by rot
110 friend LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot); // Rotates a by rot
111
112 // Non-standard operators
113 friend F32 dot(const LLQuaternion &a, const LLQuaternion &b);
114 friend LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from p to q
115 friend LLQuaternion lerp(F32 t, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from identity to q
116 friend LLQuaternion slerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // spherical linear interpolation from p to q
117 friend LLQuaternion slerp(F32 t, const LLQuaternion &q); // spherical linear interpolation from identity to q
118 friend LLQuaternion nlerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // normalized linear interpolation from p to q
119 friend LLQuaternion nlerp(F32 t, const LLQuaternion &q); // normalized linear interpolation from p to q
120
121 LLVector3 packToVector3() const; // Saves space by using the fact that our quaternions are normalized
122 void unpackFromVector3(const LLVector3& vec); // Saves space by using the fact that our quaternions are normalized
123
124 enum Order {
125 XYZ = 0,
126 YZX = 1,
127 ZXY = 2,
128 XZY = 3,
129 YXZ = 4,
130 ZYX = 5
131 };
132 // Creates a quaternions from maya's rotation representation,
133 // which is 3 rotations (in DEGREES) in the specified order
134 friend LLQuaternion mayaQ(F32 x, F32 y, F32 z, Order order);
135
136 // Conversions between Order and strings like "xyz" or "ZYX"
137 friend const char *OrderToString( const Order order );
138 friend Order StringToOrder( const char *str );
139
140 static BOOL parseQuat(const char* buf, LLQuaternion* value);
141
142 // For debugging, only
143 //static U32 mMultCount;
144};
145
146// checker
147inline BOOL LLQuaternion::isFinite() const
148{
149 return (llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) && llfinite(mQ[VS]));
150}
151
152inline BOOL LLQuaternion::isIdentity() const
153{
154 return
155 ( mQ[VX] == 0.f ) &&
156 ( mQ[VY] == 0.f ) &&
157 ( mQ[VZ] == 0.f ) &&
158 ( mQ[VS] == 1.f );
159}
160
161inline BOOL LLQuaternion::isNotIdentity() const
162{
163 return
164 ( mQ[VX] != 0.f ) ||
165 ( mQ[VY] != 0.f ) ||
166 ( mQ[VZ] != 0.f ) ||
167 ( mQ[VS] != 1.f );
168}
169
170
171
172inline LLQuaternion::LLQuaternion(void)
173{
174 mQ[VX] = 0.f;
175 mQ[VY] = 0.f;
176 mQ[VZ] = 0.f;
177 mQ[VS] = 1.f;
178}
179
180inline LLQuaternion::LLQuaternion(F32 x, F32 y, F32 z, F32 w)
181{
182 mQ[VX] = x;
183 mQ[VY] = y;
184 mQ[VZ] = z;
185 mQ[VS] = w;
186
187 //RN: don't normalize this case as its used mainly for temporaries during calculations
188 //normQuat();
189 /*
190 F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
191 mag -= 1.f;
192 mag = fabs(mag);
193 llassert(mag < 10.f*FP_MAG_THRESHOLD);
194 */
195}
196
197inline LLQuaternion::LLQuaternion(const F32 *q)
198{
199 mQ[VX] = q[VX];
200 mQ[VY] = q[VY];
201 mQ[VZ] = q[VZ];
202 mQ[VS] = q[VW];
203
204 normQuat();
205 /*
206 F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
207 mag -= 1.f;
208 mag = fabs(mag);
209 llassert(mag < FP_MAG_THRESHOLD);
210 */
211}
212
213
214inline void LLQuaternion::loadIdentity()
215{
216 mQ[VX] = 0.0f;
217 mQ[VY] = 0.0f;
218 mQ[VZ] = 0.0f;
219 mQ[VW] = 1.0f;
220}
221
222
223inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w)
224{
225 mQ[VX] = x;
226 mQ[VY] = y;
227 mQ[VZ] = z;
228 mQ[VS] = w;
229 normQuat();
230 return (*this);
231}
232
233inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat)
234{
235 mQ[VX] = quat.mQ[VX];
236 mQ[VY] = quat.mQ[VY];
237 mQ[VZ] = quat.mQ[VZ];
238 mQ[VW] = quat.mQ[VW];
239 normQuat();
240 return (*this);
241}
242
243inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q)
244{
245 mQ[VX] = q[VX];
246 mQ[VY] = q[VY];
247 mQ[VZ] = q[VZ];
248 mQ[VS] = q[VW];
249 normQuat();
250 return (*this);
251}
252
253// There may be a cheaper way that avoids the sqrt.
254// Does sin_a = VX*VX + VY*VY + VZ*VZ?
255// Copied from Matrix and Quaternion FAQ 1.12
256inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const
257{
258 F32 cos_a = mQ[VW];
259 if (cos_a > 1.0f) cos_a = 1.0f;
260 if (cos_a < -1.0f) cos_a = -1.0f;
261
262 F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a );
263
264 if ( fabs( sin_a ) < 0.0005f )
265 sin_a = 1.0f;
266 else
267 sin_a = 1.f/sin_a;
268
269 *angle = 2.0f * (F32) acos( cos_a );
270 *x = mQ[VX] * sin_a;
271 *y = mQ[VY] * sin_a;
272 *z = mQ[VZ] * sin_a;
273}
274
275inline const LLQuaternion& LLQuaternion::conjQuat()
276{
277 mQ[VX] *= -1.f;
278 mQ[VY] *= -1.f;
279 mQ[VZ] *= -1.f;
280 return (*this);
281}
282
283// Transpose
284inline const LLQuaternion& LLQuaternion::transQuat()
285{
286 mQ[VX] = -mQ[VX];
287 mQ[VY] = -mQ[VY];
288 mQ[VZ] = -mQ[VZ];
289 return *this;
290}
291
292
293inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b)
294{
295 return LLQuaternion(
296 a.mQ[VX] + b.mQ[VX],
297 a.mQ[VY] + b.mQ[VY],
298 a.mQ[VZ] + b.mQ[VZ],
299 a.mQ[VW] + b.mQ[VW] );
300}
301
302
303inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b)
304{
305 return LLQuaternion(
306 a.mQ[VX] - b.mQ[VX],
307 a.mQ[VY] - b.mQ[VY],
308 a.mQ[VZ] - b.mQ[VZ],
309 a.mQ[VW] - b.mQ[VW] );
310}
311
312
313inline LLQuaternion operator-(const LLQuaternion &a)
314{
315 return LLQuaternion(
316 -a.mQ[VX],
317 -a.mQ[VY],
318 -a.mQ[VZ],
319 -a.mQ[VW] );
320}
321
322
323inline LLQuaternion operator*(F32 a, const LLQuaternion &q)
324{
325 return LLQuaternion(
326 a * q.mQ[VX],
327 a * q.mQ[VY],
328 a * q.mQ[VZ],
329 a * q.mQ[VW] );
330}
331
332
333inline LLQuaternion operator*(const LLQuaternion &q, F32 a)
334{
335 return LLQuaternion(
336 a * q.mQ[VX],
337 a * q.mQ[VY],
338 a * q.mQ[VZ],
339 a * q.mQ[VW] );
340}
341
342inline LLQuaternion operator~(const LLQuaternion &a)
343{
344 LLQuaternion q(a);
345 q.conjQuat();
346 return q;
347}
348
349inline bool LLQuaternion::operator==(const LLQuaternion &b) const
350{
351 return ( (mQ[VX] == b.mQ[VX])
352 &&(mQ[VY] == b.mQ[VY])
353 &&(mQ[VZ] == b.mQ[VZ])
354 &&(mQ[VS] == b.mQ[VS]));
355}
356
357inline bool LLQuaternion::operator!=(const LLQuaternion &b) const
358{
359 return ( (mQ[VX] != b.mQ[VX])
360 ||(mQ[VY] != b.mQ[VY])
361 ||(mQ[VZ] != b.mQ[VZ])
362 ||(mQ[VS] != b.mQ[VS]));
363}
364
365inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b)
366{
367#if 1
368 LLQuaternion q(
369 b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1],
370 b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2],
371 b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0],
372 b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2]
373 );
374 a = q;
375#else
376 a = a * b;
377#endif
378 return a;
379}
380
381inline F32 LLQuaternion::normQuat()
382{
383 F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
384
385 if (mag > FP_MAG_THRESHOLD)
386 {
387 F32 oomag = 1.f/mag;
388 mQ[VX] *= oomag;
389 mQ[VY] *= oomag;
390 mQ[VZ] *= oomag;
391 mQ[VS] *= oomag;
392 }
393 else
394 {
395 mQ[VX] = 0.f;
396 mQ[VY] = 0.f;
397 mQ[VZ] = 0.f;
398 mQ[VS] = 1.f;
399 }
400
401 return mag;
402}
403
404LLQuaternion::Order StringToOrder( const char *str );
405
406// Some notes about Quaternions
407
408// What is a Quaternion?
409// ---------------------
410// A quaternion is a point in 4-dimensional complex space.
411// Q = { Qx, Qy, Qz, Qw }
412//
413//
414// Why Quaternions?
415// ----------------
416// The set of quaternions that make up the the 4-D unit sphere
417// can be mapped to the set of all rotations in 3-D space. Sometimes
418// it is easier to describe/manipulate rotations in quaternion space
419// than rotation-matrix space.
420//
421//
422// How Quaternions?
423// ----------------
424// In order to take advantage of quaternions we need to know how to
425// go from rotation-matricies to quaternions and back. We also have
426// to agree what variety of rotations we're generating.
427//
428// Consider the equation... v' = v * R
429//
430// There are two ways to think about rotations of vectors.
431// 1) v' is the same vector in a different reference frame
432// 2) v' is a new vector in the same reference frame
433//
434// bookmark -- which way are we using?
435//
436//
437// Quaternion from Angle-Axis:
438// ---------------------------
439// Suppose we wanted to represent a rotation of some angle (theta)
440// about some axis ({Ax, Ay, Az})...
441//
442// axis of rotation = {Ax, Ay, Az}
443// angle_of_rotation = theta
444//
445// s = sin(0.5 * theta)
446// c = cos(0.5 * theta)
447// Q = { s * Ax, s * Ay, s * Az, c }
448//
449//
450// 3x3 Matrix from Quaternion
451// --------------------------
452//
453// | |
454// | 1 - 2 * (y^2 + z^2) 2 * (x * y + z * w) 2 * (y * w - x * z) |
455// | |
456// M = | 2 * (x * y - z * w) 1 - 2 * (x^2 + z^2) 2 * (y * z + x * w) |
457// | |
458// | 2 * (x * z + y * w) 2 * (y * z - x * w) 1 - 2 * (x^2 + y^2) |
459// | |
460
461#endif