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/llmath/llquaternion.h | |
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/llmath/llquaternion.h')
-rw-r--r-- | linden/indra/llmath/llquaternion.h | 461 |
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 | |||
33 | class LLVector4; | ||
34 | class LLVector3; | ||
35 | class LLVector3d; | ||
36 | class LLMatrix4; | ||
37 | class 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 | |||
44 | static const U32 LENGTHOFQUAT = 4; | ||
45 | |||
46 | class LLQuaternion | ||
47 | { | ||
48 | public: | ||
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 | ||
147 | inline BOOL LLQuaternion::isFinite() const | ||
148 | { | ||
149 | return (llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) && llfinite(mQ[VS])); | ||
150 | } | ||
151 | |||
152 | inline 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 | |||
161 | inline 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 | |||
172 | inline 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 | |||
180 | inline 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 | |||
197 | inline 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 | |||
214 | inline 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 | |||
223 | inline 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 | |||
233 | inline 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 | |||
243 | inline 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 | ||
256 | inline 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 | |||
275 | inline 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 | ||
284 | inline 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 | |||
293 | inline 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 | |||
303 | inline 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 | |||
313 | inline 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 | |||
323 | inline 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 | |||
333 | inline 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 | |||
342 | inline LLQuaternion operator~(const LLQuaternion &a) | ||
343 | { | ||
344 | LLQuaternion q(a); | ||
345 | q.conjQuat(); | ||
346 | return q; | ||
347 | } | ||
348 | |||
349 | inline 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 | |||
357 | inline 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 | |||
365 | inline 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 | |||
381 | inline 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 | |||
404 | LLQuaternion::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 | ||