aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath/m3math.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/llmath/m3math.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 '')
-rw-r--r--linden/indra/llmath/m3math.cpp549
1 files changed, 549 insertions, 0 deletions
diff --git a/linden/indra/llmath/m3math.cpp b/linden/indra/llmath/m3math.cpp
new file mode 100644
index 0000000..c5d2c2d
--- /dev/null
+++ b/linden/indra/llmath/m3math.cpp
@@ -0,0 +1,549 @@
1/**
2 * @file m3math.cpp
3 * @brief LLMatrix3 class implementation.
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#include "linden_common.h"
29
30//#include "vmath.h"
31#include "v3math.h"
32#include "v3dmath.h"
33#include "v4math.h"
34#include "m4math.h"
35#include "m3math.h"
36#include "llquaternion.h"
37
38// LLMatrix3
39
40// ji
41// LLMatrix3 = |00 01 02 |
42// |10 11 12 |
43// |20 21 22 |
44
45// LLMatrix3 = |fx fy fz | forward-axis
46// |lx ly lz | left-axis
47// |ux uy uz | up-axis
48
49
50// Constructors
51
52
53LLMatrix3::LLMatrix3(const LLQuaternion &q)
54{
55 *this = q.getMatrix3();
56}
57
58
59LLMatrix3::LLMatrix3(const F32 angle, const LLVector3 &vec)
60{
61 LLQuaternion quat(angle, vec);
62 *this = setRot(quat);
63}
64
65LLMatrix3::LLMatrix3(const F32 angle, const LLVector3d &vec)
66{
67 LLVector3 vec_f;
68 vec_f.setVec(vec);
69 LLQuaternion quat(angle, vec_f);
70 *this = setRot(quat);
71}
72
73LLMatrix3::LLMatrix3(const F32 angle, const LLVector4 &vec)
74{
75 LLQuaternion quat(angle, vec);
76 *this = setRot(quat);
77}
78
79LLMatrix3::LLMatrix3(const F32 angle, const F32 x, const F32 y, const F32 z)
80{
81 LLVector3 vec(x, y, z);
82 LLQuaternion quat(angle, vec);
83 *this = setRot(quat);
84}
85
86LLMatrix3::LLMatrix3(const F32 roll, const F32 pitch, const F32 yaw)
87{
88 // Rotates RH about x-axis by 'roll' then
89 // rotates RH about the old y-axis by 'pitch' then
90 // rotates RH about the original z-axis by 'yaw'.
91 // .
92 // /|\ yaw axis
93 // | __.
94 // ._ ___| /| pitch axis
95 // _||\ \\ |-. /
96 // \|| \_______\_|__\_/_______
97 // | _ _ o o o_o_o_o o /_\_ ________\ roll axis
98 // // /_______/ /__________> /
99 // /_,-' // /
100 // /__,-'
101
102 F32 cx, sx, cy, sy, cz, sz;
103 F32 cxsy, sxsy;
104
105 cx = (F32)cos(roll); //A
106 sx = (F32)sin(roll); //B
107 cy = (F32)cos(pitch); //C
108 sy = (F32)sin(pitch); //D
109 cz = (F32)cos(yaw); //E
110 sz = (F32)sin(yaw); //F
111
112 cxsy = cx * sy; //AD
113 sxsy = sx * sy; //BD
114
115 mMatrix[0][0] = cy * cz;
116 mMatrix[1][0] = -cy * sz;
117 mMatrix[2][0] = sy;
118 mMatrix[0][1] = sxsy * cz + cx * sz;
119 mMatrix[1][1] = -sxsy * sz + cx * cz;
120 mMatrix[2][1] = -sx * cy;
121 mMatrix[0][2] = -cxsy * cz + sx * sz;
122 mMatrix[1][2] = cxsy * sz + sx * cz;
123 mMatrix[2][2] = cx * cy;
124}
125
126// From Matrix and Quaternion FAQ
127void LLMatrix3::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const
128{
129 F64 angle_x, angle_y, angle_z;
130 F64 cx, cy, cz; // cosine of angle_x, angle_y, angle_z
131 F64 sx, sz; // sine of angle_x, angle_y, angle_z
132
133 angle_y = asin(llclamp(mMatrix[2][0], -1.f, 1.f));
134 cy = cos(angle_y);
135
136 if (fabs(cy) > 0.005) // non-zero
137 {
138 // no gimbal lock
139 cx = mMatrix[2][2] / cy;
140 sx = - mMatrix[2][1] / cy;
141
142 angle_x = (F32) atan2(sx, cx);
143
144 cz = mMatrix[0][0] / cy;
145 sz = - mMatrix[1][0] / cy;
146
147 angle_z = (F32) atan2(sz, cz);
148 }
149 else
150 {
151 // yup, gimbal lock
152 angle_x = 0;
153
154 // some tricky math thereby avoided, see article
155
156 cz = mMatrix[1][1];
157 sz = mMatrix[0][1];
158
159 angle_z = atan2(sz, cz);
160 }
161
162 *roll = (F32)angle_x;
163 *pitch = (F32)angle_y;
164 *yaw = (F32)angle_z;
165}
166
167
168// Clear and Assignment Functions
169
170const LLMatrix3& LLMatrix3::identity()
171{
172 mMatrix[0][0] = 1.f;
173 mMatrix[0][1] = 0.f;
174 mMatrix[0][2] = 0.f;
175
176 mMatrix[1][0] = 0.f;
177 mMatrix[1][1] = 1.f;
178 mMatrix[1][2] = 0.f;
179
180 mMatrix[2][0] = 0.f;
181 mMatrix[2][1] = 0.f;
182 mMatrix[2][2] = 1.f;
183 return (*this);
184}
185
186const LLMatrix3& LLMatrix3::zero()
187{
188 mMatrix[0][0] = 0.f;
189 mMatrix[0][1] = 0.f;
190 mMatrix[0][2] = 0.f;
191
192 mMatrix[1][0] = 0.f;
193 mMatrix[1][1] = 0.f;
194 mMatrix[1][2] = 0.f;
195
196 mMatrix[2][0] = 0.f;
197 mMatrix[2][1] = 0.f;
198 mMatrix[2][2] = 0.f;
199 return (*this);
200}
201
202// various useful mMatrix functions
203
204const LLMatrix3& LLMatrix3::transpose()
205{
206 // transpose the matrix
207 F32 temp;
208 temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp;
209 temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp;
210 temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp;
211 return *this;
212}
213
214
215F32 LLMatrix3::determinant() const
216{
217 // Is this a useful method when we assume the matrices are valid rotation
218 // matrices throughout this implementation?
219 return mMatrix[0][0] * (mMatrix[1][1] * mMatrix[2][2] - mMatrix[1][2] * mMatrix[2][1]) +
220 mMatrix[0][1] * (mMatrix[1][2] * mMatrix[2][0] - mMatrix[1][0] * mMatrix[2][2]) +
221 mMatrix[0][2] * (mMatrix[1][0] * mMatrix[2][1] - mMatrix[1][1] * mMatrix[2][0]);
222}
223
224// This is identical to the transMat3() method because we assume a rotation matrix
225const LLMatrix3& LLMatrix3::invert()
226{
227 // transpose the matrix
228 F32 temp;
229 temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp;
230 temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp;
231 temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp;
232 return *this;
233}
234
235// does not assume a rotation matrix, and does not divide by determinant, assuming results will be renormalized
236const LLMatrix3& LLMatrix3::adjointTranspose()
237{
238 LLMatrix3 adjoint_transpose;
239 adjoint_transpose.mMatrix[VX][VX] = mMatrix[VY][VY] * mMatrix[VZ][VZ] - mMatrix[VY][VZ] * mMatrix[VZ][VY] ;
240 adjoint_transpose.mMatrix[VY][VX] = mMatrix[VY][VZ] * mMatrix[VZ][VX] - mMatrix[VY][VX] * mMatrix[VZ][VZ] ;
241 adjoint_transpose.mMatrix[VZ][VX] = mMatrix[VY][VX] * mMatrix[VZ][VY] - mMatrix[VY][VY] * mMatrix[VZ][VX] ;
242 adjoint_transpose.mMatrix[VX][VY] = mMatrix[VZ][VY] * mMatrix[VX][VZ] - mMatrix[VZ][VZ] * mMatrix[VX][VY] ;
243 adjoint_transpose.mMatrix[VY][VY] = mMatrix[VZ][VZ] * mMatrix[VX][VX] - mMatrix[VZ][VX] * mMatrix[VX][VZ] ;
244 adjoint_transpose.mMatrix[VZ][VY] = mMatrix[VZ][VX] * mMatrix[VX][VY] - mMatrix[VZ][VY] * mMatrix[VX][VX] ;
245 adjoint_transpose.mMatrix[VX][VZ] = mMatrix[VX][VY] * mMatrix[VY][VZ] - mMatrix[VX][VZ] * mMatrix[VY][VY] ;
246 adjoint_transpose.mMatrix[VY][VZ] = mMatrix[VX][VZ] * mMatrix[VY][VX] - mMatrix[VX][VX] * mMatrix[VY][VZ] ;
247 adjoint_transpose.mMatrix[VZ][VZ] = mMatrix[VX][VX] * mMatrix[VY][VY] - mMatrix[VX][VY] * mMatrix[VY][VX] ;
248
249 *this = adjoint_transpose;
250 return *this;
251}
252
253// SJB: This code is correct for a logicly stored (non-transposed) matrix;
254// Our matrices are stored transposed, OpenGL style, so this generates the
255// INVERSE quaternion (-x, -y, -z, w)!
256// Because we use similar logic in LLQuaternion::getMatrix3,
257// we are internally consistant so everything works OK :)
258LLQuaternion LLMatrix3::quaternion() const
259{
260 LLQuaternion quat;
261 F32 tr, s, q[4];
262 U32 i, j, k;
263 U32 nxt[3] = {1, 2, 0};
264
265 tr = mMatrix[0][0] + mMatrix[1][1] + mMatrix[2][2];
266
267 // check the diagonal
268 if (tr > 0.f)
269 {
270 s = (F32)sqrt (tr + 1.f);
271 quat.mQ[VS] = s / 2.f;
272 s = 0.5f / s;
273 quat.mQ[VX] = (mMatrix[1][2] - mMatrix[2][1]) * s;
274 quat.mQ[VY] = (mMatrix[2][0] - mMatrix[0][2]) * s;
275 quat.mQ[VZ] = (mMatrix[0][1] - mMatrix[1][0]) * s;
276 }
277 else
278 {
279 // diagonal is negative
280 i = 0;
281 if (mMatrix[1][1] > mMatrix[0][0])
282 i = 1;
283 if (mMatrix[2][2] > mMatrix[i][i])
284 i = 2;
285
286 j = nxt[i];
287 k = nxt[j];
288
289
290 s = (F32)sqrt ((mMatrix[i][i] - (mMatrix[j][j] + mMatrix[k][k])) + 1.f);
291
292 q[i] = s * 0.5f;
293
294 if (s != 0.f)
295 s = 0.5f / s;
296
297 q[3] = (mMatrix[j][k] - mMatrix[k][j]) * s;
298 q[j] = (mMatrix[i][j] + mMatrix[j][i]) * s;
299 q[k] = (mMatrix[i][k] + mMatrix[k][i]) * s;
300
301 quat.setQuat(q);
302 }
303 return quat;
304}
305
306
307// These functions take Rotation arguments
308const LLMatrix3& LLMatrix3::setRot(const F32 angle, const F32 x, const F32 y, const F32 z)
309{
310 LLMatrix3 mat(angle, x, y, z);
311 *this = mat;
312 return *this;
313}
314
315const LLMatrix3& LLMatrix3::setRot(const F32 angle, const LLVector3 &vec)
316{
317 LLMatrix3 mat(angle, vec);
318 *this = mat;
319 return *this;
320}
321
322const LLMatrix3& LLMatrix3::setRot(const F32 roll, const F32 pitch, const F32 yaw)
323{
324 LLMatrix3 mat(roll, pitch, yaw);
325 *this = mat;
326 return *this;
327}
328
329
330const LLMatrix3& LLMatrix3::setRot(const LLQuaternion &q)
331{
332 LLMatrix3 mat(q);
333 *this = mat;
334 return *this;
335}
336
337
338const LLMatrix3& LLMatrix3::setRows(const LLVector3 &fwd, const LLVector3 &left, const LLVector3 &up)
339{
340 mMatrix[0][0] = fwd.mV[0];
341 mMatrix[0][1] = fwd.mV[1];
342 mMatrix[0][2] = fwd.mV[2];
343
344 mMatrix[1][0] = left.mV[0];
345 mMatrix[1][1] = left.mV[1];
346 mMatrix[1][2] = left.mV[2];
347
348 mMatrix[2][0] = up.mV[0];
349 mMatrix[2][1] = up.mV[1];
350 mMatrix[2][2] = up.mV[2];
351
352 return *this;
353}
354
355
356// Rotate exisitng mMatrix
357const LLMatrix3& LLMatrix3::rotate(const F32 angle, const F32 x, const F32 y, const F32 z)
358{
359 LLMatrix3 mat(angle, x, y, z);
360 *this *= mat;
361 return *this;
362}
363
364
365const LLMatrix3& LLMatrix3::rotate(const F32 angle, const LLVector3 &vec)
366{
367 LLMatrix3 mat(angle, vec);
368 *this *= mat;
369 return *this;
370}
371
372
373const LLMatrix3& LLMatrix3::rotate(const F32 roll, const F32 pitch, const F32 yaw)
374{
375 LLMatrix3 mat(roll, pitch, yaw);
376 *this *= mat;
377 return *this;
378}
379
380
381const LLMatrix3& LLMatrix3::rotate(const LLQuaternion &q)
382{
383 LLMatrix3 mat(q);
384 *this *= mat;
385 return *this;
386}
387
388
389LLVector3 LLMatrix3::getFwdRow() const
390{
391 return LLVector3(mMatrix[VX]);
392}
393
394LLVector3 LLMatrix3::getLeftRow() const
395{
396 return LLVector3(mMatrix[VY]);
397}
398
399LLVector3 LLMatrix3::getUpRow() const
400{
401 return LLVector3(mMatrix[VZ]);
402}
403
404
405
406const LLMatrix3& LLMatrix3::orthogonalize()
407{
408 LLVector3 x_axis(mMatrix[VX]);
409 LLVector3 y_axis(mMatrix[VY]);
410 LLVector3 z_axis(mMatrix[VZ]);
411
412 x_axis.normVec();
413 y_axis -= x_axis * (x_axis * y_axis);
414 y_axis.normVec();
415 z_axis = x_axis % y_axis;
416 setRows(x_axis, y_axis, z_axis);
417 return (*this);
418}
419
420
421// LLMatrix3 Operators
422
423LLMatrix3 operator*(const LLMatrix3 &a, const LLMatrix3 &b)
424{
425 U32 i, j;
426 LLMatrix3 mat;
427 for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
428 {
429 for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
430 {
431 mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] +
432 a.mMatrix[j][1] * b.mMatrix[1][i] +
433 a.mMatrix[j][2] * b.mMatrix[2][i];
434 }
435 }
436 return mat;
437}
438
439/* Not implemented to help enforce code consistency with the syntax of
440 row-major notation. This is a Good Thing.
441LLVector3 operator*(const LLMatrix3 &a, const LLVector3 &b)
442{
443 LLVector3 vec;
444 // matrix operates "from the left" on column vector
445 vec.mV[VX] = a.mMatrix[VX][VX] * b.mV[VX] +
446 a.mMatrix[VX][VY] * b.mV[VY] +
447 a.mMatrix[VX][VZ] * b.mV[VZ];
448
449 vec.mV[VY] = a.mMatrix[VY][VX] * b.mV[VX] +
450 a.mMatrix[VY][VY] * b.mV[VY] +
451 a.mMatrix[VY][VZ] * b.mV[VZ];
452
453 vec.mV[VZ] = a.mMatrix[VZ][VX] * b.mV[VX] +
454 a.mMatrix[VZ][VY] * b.mV[VY] +
455 a.mMatrix[VZ][VZ] * b.mV[VZ];
456 return vec;
457}
458*/
459
460
461LLVector3 operator*(const LLVector3 &a, const LLMatrix3 &b)
462{
463 // matrix operates "from the right" on row vector
464 return LLVector3(
465 a.mV[VX] * b.mMatrix[VX][VX] +
466 a.mV[VY] * b.mMatrix[VY][VX] +
467 a.mV[VZ] * b.mMatrix[VZ][VX],
468
469 a.mV[VX] * b.mMatrix[VX][VY] +
470 a.mV[VY] * b.mMatrix[VY][VY] +
471 a.mV[VZ] * b.mMatrix[VZ][VY],
472
473 a.mV[VX] * b.mMatrix[VX][VZ] +
474 a.mV[VY] * b.mMatrix[VY][VZ] +
475 a.mV[VZ] * b.mMatrix[VZ][VZ] );
476}
477
478LLVector3d operator*(const LLVector3d &a, const LLMatrix3 &b)
479{
480 // matrix operates "from the right" on row vector
481 return LLVector3d(
482 a.mdV[VX] * b.mMatrix[VX][VX] +
483 a.mdV[VY] * b.mMatrix[VY][VX] +
484 a.mdV[VZ] * b.mMatrix[VZ][VX],
485
486 a.mdV[VX] * b.mMatrix[VX][VY] +
487 a.mdV[VY] * b.mMatrix[VY][VY] +
488 a.mdV[VZ] * b.mMatrix[VZ][VY],
489
490 a.mdV[VX] * b.mMatrix[VX][VZ] +
491 a.mdV[VY] * b.mMatrix[VY][VZ] +
492 a.mdV[VZ] * b.mMatrix[VZ][VZ] );
493}
494
495bool operator==(const LLMatrix3 &a, const LLMatrix3 &b)
496{
497 U32 i, j;
498 for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
499 {
500 for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
501 {
502 if (a.mMatrix[j][i] != b.mMatrix[j][i])
503 return FALSE;
504 }
505 }
506 return TRUE;
507}
508
509bool operator!=(const LLMatrix3 &a, const LLMatrix3 &b)
510{
511 U32 i, j;
512 for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
513 {
514 for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
515 {
516 if (a.mMatrix[j][i] != b.mMatrix[j][i])
517 return TRUE;
518 }
519 }
520 return FALSE;
521}
522
523const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b)
524{
525 U32 i, j;
526 LLMatrix3 mat;
527 for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
528 {
529 for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
530 {
531 mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] +
532 a.mMatrix[j][1] * b.mMatrix[1][i] +
533 a.mMatrix[j][2] * b.mMatrix[2][i];
534 }
535 }
536 a = mat;
537 return a;
538}
539
540std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a)
541{
542 s << "{ "
543 << a.mMatrix[VX][VX] << ", " << a.mMatrix[VX][VY] << ", " << a.mMatrix[VX][VZ] << "; "
544 << a.mMatrix[VY][VX] << ", " << a.mMatrix[VY][VY] << ", " << a.mMatrix[VY][VZ] << "; "
545 << a.mMatrix[VZ][VX] << ", " << a.mMatrix[VZ][VY] << ", " << a.mMatrix[VZ][VZ]
546 << " }";
547 return s;
548}
549