diff options
Diffstat (limited to 'linden/indra/llmath/m3math.cpp')
-rw-r--r-- | linden/indra/llmath/m3math.cpp | 549 |
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 | |||
53 | LLMatrix3::LLMatrix3(const LLQuaternion &q) | ||
54 | { | ||
55 | *this = q.getMatrix3(); | ||
56 | } | ||
57 | |||
58 | |||
59 | LLMatrix3::LLMatrix3(const F32 angle, const LLVector3 &vec) | ||
60 | { | ||
61 | LLQuaternion quat(angle, vec); | ||
62 | *this = setRot(quat); | ||
63 | } | ||
64 | |||
65 | LLMatrix3::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 | |||
73 | LLMatrix3::LLMatrix3(const F32 angle, const LLVector4 &vec) | ||
74 | { | ||
75 | LLQuaternion quat(angle, vec); | ||
76 | *this = setRot(quat); | ||
77 | } | ||
78 | |||
79 | LLMatrix3::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 | |||
86 | LLMatrix3::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 | ||
127 | void 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 | |||
170 | const 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 | |||
186 | const 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 | |||
204 | const 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 | |||
215 | F32 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 | ||
225 | const 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 | ||
236 | const 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 :) | ||
258 | LLQuaternion 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 | ||
308 | const 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 | |||
315 | const LLMatrix3& LLMatrix3::setRot(const F32 angle, const LLVector3 &vec) | ||
316 | { | ||
317 | LLMatrix3 mat(angle, vec); | ||
318 | *this = mat; | ||
319 | return *this; | ||
320 | } | ||
321 | |||
322 | const 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 | |||
330 | const LLMatrix3& LLMatrix3::setRot(const LLQuaternion &q) | ||
331 | { | ||
332 | LLMatrix3 mat(q); | ||
333 | *this = mat; | ||
334 | return *this; | ||
335 | } | ||
336 | |||
337 | |||
338 | const 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 | ||
357 | const 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 | |||
365 | const LLMatrix3& LLMatrix3::rotate(const F32 angle, const LLVector3 &vec) | ||
366 | { | ||
367 | LLMatrix3 mat(angle, vec); | ||
368 | *this *= mat; | ||
369 | return *this; | ||
370 | } | ||
371 | |||
372 | |||
373 | const 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 | |||
381 | const LLMatrix3& LLMatrix3::rotate(const LLQuaternion &q) | ||
382 | { | ||
383 | LLMatrix3 mat(q); | ||
384 | *this *= mat; | ||
385 | return *this; | ||
386 | } | ||
387 | |||
388 | |||
389 | LLVector3 LLMatrix3::getFwdRow() const | ||
390 | { | ||
391 | return LLVector3(mMatrix[VX]); | ||
392 | } | ||
393 | |||
394 | LLVector3 LLMatrix3::getLeftRow() const | ||
395 | { | ||
396 | return LLVector3(mMatrix[VY]); | ||
397 | } | ||
398 | |||
399 | LLVector3 LLMatrix3::getUpRow() const | ||
400 | { | ||
401 | return LLVector3(mMatrix[VZ]); | ||
402 | } | ||
403 | |||
404 | |||
405 | |||
406 | const 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 | |||
423 | LLMatrix3 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. | ||
441 | LLVector3 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 | |||
461 | LLVector3 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 | |||
478 | LLVector3d 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 | |||
495 | bool 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 | |||
509 | bool 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 | |||
523 | const 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 | |||
540 | std::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 | |||