diff options
Diffstat (limited to 'linden/indra/llmath/llcoordframe.cpp')
-rw-r--r-- | linden/indra/llmath/llcoordframe.cpp | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/linden/indra/llmath/llcoordframe.cpp b/linden/indra/llmath/llcoordframe.cpp new file mode 100644 index 0000000..552854d --- /dev/null +++ b/linden/indra/llmath/llcoordframe.cpp | |||
@@ -0,0 +1,748 @@ | |||
1 | /** | ||
2 | * @file llcoordframe.cpp | ||
3 | * @brief LLCoordFrame 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 "m3math.h" | ||
33 | #include "v4math.h" | ||
34 | #include "m4math.h" | ||
35 | #include "llquaternion.h" | ||
36 | #include "llcoordframe.h" | ||
37 | |||
38 | #ifndef X_AXIS | ||
39 | #define X_AXIS 1.0f,0.0f,0.0f | ||
40 | #define Y_AXIS 0.0f,1.0f,0.0f | ||
41 | #define Z_AXIS 0.0f,0.0f,1.0f | ||
42 | #endif | ||
43 | |||
44 | // Constructors | ||
45 | |||
46 | LLCoordFrame::LLCoordFrame() : | ||
47 | mOrigin(0.f, 0.f, 0.f), | ||
48 | mXAxis(X_AXIS), | ||
49 | mYAxis(Y_AXIS), | ||
50 | mZAxis(Z_AXIS) | ||
51 | { | ||
52 | } | ||
53 | |||
54 | LLCoordFrame::LLCoordFrame(const LLVector3 &origin) : | ||
55 | mOrigin(origin), | ||
56 | mXAxis(X_AXIS), | ||
57 | mYAxis(Y_AXIS), | ||
58 | mZAxis(Z_AXIS) | ||
59 | { | ||
60 | if( !mOrigin.isFinite() ) | ||
61 | { | ||
62 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLVector3 &direction) : | ||
67 | mOrigin(origin) | ||
68 | { | ||
69 | lookDir(direction); | ||
70 | |||
71 | if( !isFinite() ) | ||
72 | { | ||
73 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | LLCoordFrame::LLCoordFrame(const LLVector3 &x_axis, | ||
78 | const LLVector3 &y_axis, | ||
79 | const LLVector3 &z_axis) : | ||
80 | mOrigin(0.f, 0.f, 0.f), | ||
81 | mXAxis(x_axis), | ||
82 | mYAxis(y_axis), | ||
83 | mZAxis(z_axis) | ||
84 | { | ||
85 | if( !isFinite() ) | ||
86 | { | ||
87 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | LLCoordFrame::LLCoordFrame(const LLVector3 &origin, | ||
92 | const LLVector3 &x_axis, | ||
93 | const LLVector3 &y_axis, | ||
94 | const LLVector3 &z_axis) : | ||
95 | mOrigin(origin), | ||
96 | mXAxis(x_axis), | ||
97 | mYAxis(y_axis), | ||
98 | mZAxis(z_axis) | ||
99 | { | ||
100 | if( !isFinite() ) | ||
101 | { | ||
102 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | |||
107 | LLCoordFrame::LLCoordFrame(const LLVector3 &origin, | ||
108 | const LLMatrix3 &rotation) : | ||
109 | mOrigin(origin), | ||
110 | mXAxis(rotation.mMatrix[VX]), | ||
111 | mYAxis(rotation.mMatrix[VY]), | ||
112 | mZAxis(rotation.mMatrix[VZ]) | ||
113 | { | ||
114 | if( !isFinite() ) | ||
115 | { | ||
116 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | LLCoordFrame::LLCoordFrame(const LLQuaternion &q) : | ||
121 | mOrigin(0.f, 0.f, 0.f) | ||
122 | { | ||
123 | LLMatrix3 rotation_matrix(q); | ||
124 | mXAxis.setVec(rotation_matrix.mMatrix[VX]); | ||
125 | mYAxis.setVec(rotation_matrix.mMatrix[VY]); | ||
126 | mZAxis.setVec(rotation_matrix.mMatrix[VZ]); | ||
127 | |||
128 | if( !isFinite() ) | ||
129 | { | ||
130 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLQuaternion &q) : | ||
135 | mOrigin(origin) | ||
136 | { | ||
137 | LLMatrix3 rotation_matrix(q); | ||
138 | mXAxis.setVec(rotation_matrix.mMatrix[VX]); | ||
139 | mYAxis.setVec(rotation_matrix.mMatrix[VY]); | ||
140 | mZAxis.setVec(rotation_matrix.mMatrix[VZ]); | ||
141 | |||
142 | if( !isFinite() ) | ||
143 | { | ||
144 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | LLCoordFrame::LLCoordFrame(const LLMatrix4 &mat) : | ||
149 | mOrigin(mat.mMatrix[VW]), | ||
150 | mXAxis(mat.mMatrix[VX]), | ||
151 | mYAxis(mat.mMatrix[VY]), | ||
152 | mZAxis(mat.mMatrix[VZ]) | ||
153 | { | ||
154 | if( !isFinite() ) | ||
155 | { | ||
156 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | |||
161 | // The folowing two constructors are dangerous due to implicit casting and have been disabled - SJB | ||
162 | /* | ||
163 | LLCoordFrame::LLCoordFrame(const F32 *origin, const F32 *rotation) : | ||
164 | mOrigin(origin), | ||
165 | mXAxis(rotation+3*VX), | ||
166 | mYAxis(rotation+3*VY), | ||
167 | mZAxis(rotation+3*VZ) | ||
168 | { | ||
169 | if( !isFinite() ) | ||
170 | { | ||
171 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
172 | } | ||
173 | } | ||
174 | */ | ||
175 | |||
176 | /* | ||
177 | LLCoordFrame::LLCoordFrame(const F32 *origin_and_rotation) : | ||
178 | mOrigin(origin_and_rotation), | ||
179 | mXAxis(origin_and_rotation + 3*(VX+1)), | ||
180 | mYAxis(origin_and_rotation + 3*(VY+1)), | ||
181 | mZAxis(origin_and_rotation + 3*(VZ+1)) | ||
182 | { | ||
183 | if( !isFinite() ) | ||
184 | { | ||
185 | llerrs << "Non Finite in LLCoordFrame::LLCoordFrame()" << llendl; | ||
186 | } | ||
187 | } | ||
188 | */ | ||
189 | |||
190 | |||
191 | void LLCoordFrame::reset() | ||
192 | { | ||
193 | mOrigin.setVec(0.0f, 0.0f, 0.0f); | ||
194 | resetAxes(); | ||
195 | } | ||
196 | |||
197 | |||
198 | void LLCoordFrame::resetAxes() | ||
199 | { | ||
200 | mXAxis.setVec(1.0f, 0.0f, 0.0f); | ||
201 | mYAxis.setVec(0.0f, 1.0f, 0.0f); | ||
202 | mZAxis.setVec(0.0f, 0.0f, 1.0f); | ||
203 | } | ||
204 | |||
205 | // setOrigin() member functions set mOrigin | ||
206 | |||
207 | void LLCoordFrame::setOrigin(F32 x, F32 y, F32 z) | ||
208 | { | ||
209 | mOrigin.setVec(x, y, z); | ||
210 | |||
211 | if( !mOrigin.isFinite() ) | ||
212 | { | ||
213 | llerrs << "Non Finite in LLCoordFrame::setOrigin()" << llendl; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | void LLCoordFrame::setOrigin(const LLVector3 &new_origin) | ||
218 | { | ||
219 | mOrigin = new_origin; | ||
220 | if( !mOrigin.isFinite() ) | ||
221 | { | ||
222 | llerrs << "Non Finite in LLCoordFrame::setOrigin()" << llendl; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | void LLCoordFrame::setOrigin(const F32 *origin) | ||
227 | { | ||
228 | mOrigin.mV[VX] = *(origin + VX); | ||
229 | mOrigin.mV[VY] = *(origin + VY); | ||
230 | mOrigin.mV[VZ] = *(origin + VZ); | ||
231 | |||
232 | if( !mOrigin.isFinite() ) | ||
233 | { | ||
234 | llerrs << "Non Finite in LLCoordFrame::setOrigin()" << llendl; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | void LLCoordFrame::setOrigin(const LLCoordFrame &frame) | ||
239 | { | ||
240 | mOrigin = frame.getOrigin(); | ||
241 | |||
242 | if( !mOrigin.isFinite() ) | ||
243 | { | ||
244 | llerrs << "Non Finite in LLCoordFrame::setOrigin()" << llendl; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | // setAxes() member functions set the axes, and assume that | ||
249 | // the arguments are orthogonal and normalized. | ||
250 | |||
251 | void LLCoordFrame::setAxes(const LLVector3 &x_axis, | ||
252 | const LLVector3 &y_axis, | ||
253 | const LLVector3 &z_axis) | ||
254 | { | ||
255 | mXAxis = x_axis; | ||
256 | mYAxis = y_axis; | ||
257 | mZAxis = z_axis; | ||
258 | if( !isFinite() ) | ||
259 | { | ||
260 | llerrs << "Non Finite in LLCoordFrame::setAxes()" << llendl; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | |||
265 | void LLCoordFrame::setAxes(const LLMatrix3 &rotation_matrix) | ||
266 | { | ||
267 | mXAxis.setVec(rotation_matrix.mMatrix[VX]); | ||
268 | mYAxis.setVec(rotation_matrix.mMatrix[VY]); | ||
269 | mZAxis.setVec(rotation_matrix.mMatrix[VZ]); | ||
270 | if( !isFinite() ) | ||
271 | { | ||
272 | llerrs << "Non Finite in LLCoordFrame::setAxes()" << llendl; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | |||
277 | void LLCoordFrame::setAxes(const LLQuaternion &q ) | ||
278 | { | ||
279 | LLMatrix3 rotation_matrix(q); | ||
280 | setAxes(rotation_matrix); | ||
281 | if( !isFinite() ) | ||
282 | { | ||
283 | llerrs << "Non Finite in LLCoordFrame::setAxes()" << llendl; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | |||
288 | void LLCoordFrame::setAxes( const F32 *rotation_matrix ) | ||
289 | { | ||
290 | mXAxis.mV[VX] = *(rotation_matrix + 3*VX + VX); | ||
291 | mXAxis.mV[VY] = *(rotation_matrix + 3*VX + VY); | ||
292 | mXAxis.mV[VZ] = *(rotation_matrix + 3*VX + VZ); | ||
293 | mYAxis.mV[VX] = *(rotation_matrix + 3*VY + VX); | ||
294 | mYAxis.mV[VY] = *(rotation_matrix + 3*VY + VY); | ||
295 | mYAxis.mV[VZ] = *(rotation_matrix + 3*VY + VZ); | ||
296 | mZAxis.mV[VX] = *(rotation_matrix + 3*VZ + VX); | ||
297 | mZAxis.mV[VY] = *(rotation_matrix + 3*VZ + VY); | ||
298 | mZAxis.mV[VZ] = *(rotation_matrix + 3*VZ + VZ); | ||
299 | |||
300 | if( !isFinite() ) | ||
301 | { | ||
302 | llerrs << "Non Finite in LLCoordFrame::setAxes()" << llendl; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | |||
307 | void LLCoordFrame::setAxes(const LLCoordFrame &frame) | ||
308 | { | ||
309 | mXAxis = frame.getXAxis(); | ||
310 | mYAxis = frame.getYAxis(); | ||
311 | mZAxis = frame.getZAxis(); | ||
312 | |||
313 | if( !isFinite() ) | ||
314 | { | ||
315 | llerrs << "Non Finite in LLCoordFrame::setAxes()" << llendl; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | |||
320 | // translate() member functions move mOrigin to a relative position | ||
321 | |||
322 | void LLCoordFrame::translate(F32 x, F32 y, F32 z) | ||
323 | { | ||
324 | mOrigin.mV[VX] += x; | ||
325 | mOrigin.mV[VY] += y; | ||
326 | mOrigin.mV[VZ] += z; | ||
327 | |||
328 | if( !mOrigin.isFinite() ) | ||
329 | { | ||
330 | llerrs << "Non Finite in LLCoordFrame::translate()" << llendl; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | |||
335 | void LLCoordFrame::translate(const LLVector3 &v) | ||
336 | { | ||
337 | mOrigin += v; | ||
338 | |||
339 | if( !mOrigin.isFinite() ) | ||
340 | { | ||
341 | llerrs << "Non Finite in LLCoordFrame::translate()" << llendl; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | |||
346 | void LLCoordFrame::translate(const F32 *origin) | ||
347 | { | ||
348 | mOrigin.mV[VX] += *(origin + VX); | ||
349 | mOrigin.mV[VY] += *(origin + VY); | ||
350 | mOrigin.mV[VZ] += *(origin + VZ); | ||
351 | |||
352 | if( !mOrigin.isFinite() ) | ||
353 | { | ||
354 | llerrs << "Non Finite in LLCoordFrame::translate()" << llendl; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | |||
359 | // Rotate move the axes to a relative rotation | ||
360 | |||
361 | void LLCoordFrame::rotate(F32 angle, F32 x, F32 y, F32 z) | ||
362 | { | ||
363 | LLQuaternion q(angle, LLVector3(x,y,z)); | ||
364 | rotate(q); | ||
365 | } | ||
366 | |||
367 | |||
368 | void LLCoordFrame::rotate(F32 angle, const LLVector3 &rotation_axis) | ||
369 | { | ||
370 | LLQuaternion q(angle, rotation_axis); | ||
371 | rotate(q); | ||
372 | } | ||
373 | |||
374 | |||
375 | void LLCoordFrame::rotate(const LLQuaternion &q) | ||
376 | { | ||
377 | LLMatrix3 rotation_matrix(q); | ||
378 | rotate(rotation_matrix); | ||
379 | } | ||
380 | |||
381 | |||
382 | void LLCoordFrame::rotate(const LLMatrix3 &rotation_matrix) | ||
383 | { | ||
384 | mXAxis.rotVec(rotation_matrix); | ||
385 | mYAxis.rotVec(rotation_matrix); | ||
386 | orthonormalize(); | ||
387 | |||
388 | if( !isFinite() ) | ||
389 | { | ||
390 | llerrs << "Non Finite in LLCoordFrame::rotate()" << llendl; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | |||
395 | void LLCoordFrame::roll(F32 angle) | ||
396 | { | ||
397 | LLQuaternion q(angle, mXAxis); | ||
398 | LLMatrix3 rotation_matrix(q); | ||
399 | rotate(rotation_matrix); | ||
400 | |||
401 | if( !mYAxis.isFinite() || !mZAxis.isFinite() ) | ||
402 | { | ||
403 | llerrs << "Non Finite in LLCoordFrame::roll()" << llendl; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | void LLCoordFrame::pitch(F32 angle) | ||
408 | { | ||
409 | LLQuaternion q(angle, mYAxis); | ||
410 | LLMatrix3 rotation_matrix(q); | ||
411 | rotate(rotation_matrix); | ||
412 | |||
413 | if( !mXAxis.isFinite() || !mZAxis.isFinite() ) | ||
414 | { | ||
415 | llerrs << "Non Finite in LLCoordFrame::pitch()" << llendl; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | void LLCoordFrame::yaw(F32 angle) | ||
420 | { | ||
421 | LLQuaternion q(angle, mZAxis); | ||
422 | LLMatrix3 rotation_matrix(q); | ||
423 | rotate(rotation_matrix); | ||
424 | |||
425 | if( !mXAxis.isFinite() || !mYAxis.isFinite() ) | ||
426 | { | ||
427 | llerrs << "Non Finite in LLCoordFrame::yaw()" << llendl; | ||
428 | } | ||
429 | } | ||
430 | |||
431 | // get*() routines | ||
432 | |||
433 | |||
434 | LLQuaternion LLCoordFrame::getQuaternion() const | ||
435 | { | ||
436 | LLQuaternion quat(mXAxis, mYAxis, mZAxis); | ||
437 | return quat; | ||
438 | } | ||
439 | |||
440 | |||
441 | void LLCoordFrame::getMatrixToLocal(LLMatrix4& mat) const | ||
442 | { | ||
443 | mat.setFwdCol(mXAxis); | ||
444 | mat.setLeftCol(mYAxis); | ||
445 | mat.setUpCol(mZAxis); | ||
446 | |||
447 | mat.mMatrix[3][0] = -(mOrigin * LLVector3(mat.mMatrix[0][0], mat.mMatrix[1][0], mat.mMatrix[2][0])); | ||
448 | mat.mMatrix[3][1] = -(mOrigin * LLVector3(mat.mMatrix[0][1], mat.mMatrix[1][1], mat.mMatrix[2][1])); | ||
449 | mat.mMatrix[3][2] = -(mOrigin * LLVector3(mat.mMatrix[0][2], mat.mMatrix[1][2], mat.mMatrix[2][2])); | ||
450 | } | ||
451 | |||
452 | |||
453 | void LLCoordFrame::getRotMatrixToParent(LLMatrix4& mat) const | ||
454 | { | ||
455 | // Note: moves into CFR | ||
456 | mat.setFwdRow( -mYAxis ); | ||
457 | mat.setLeftRow( mZAxis ); | ||
458 | mat.setUpRow( -mXAxis ); | ||
459 | } | ||
460 | |||
461 | size_t LLCoordFrame::writeOrientation(char *buffer) const | ||
462 | { | ||
463 | memcpy(buffer, mOrigin.mV, 3*sizeof(F32)); | ||
464 | buffer += 3*sizeof(F32); | ||
465 | memcpy(buffer, mXAxis.mV, 3*sizeof(F32)); | ||
466 | buffer += 3*sizeof(F32); | ||
467 | memcpy(buffer, mYAxis.mV, 3*sizeof(F32)); | ||
468 | buffer += 3*sizeof(F32); | ||
469 | memcpy(buffer, mZAxis.mV, 3*sizeof(F32)); | ||
470 | return 12*sizeof(F32); | ||
471 | } | ||
472 | |||
473 | |||
474 | size_t LLCoordFrame::readOrientation(const char *buffer) | ||
475 | { | ||
476 | memcpy(mOrigin.mV, buffer, 3*sizeof(F32)); | ||
477 | buffer += 3*sizeof(F32); | ||
478 | memcpy(mXAxis.mV, buffer, 3*sizeof(F32)); | ||
479 | buffer += 3*sizeof(F32); | ||
480 | memcpy(mYAxis.mV, buffer, 3*sizeof(F32)); | ||
481 | buffer += 3*sizeof(F32); | ||
482 | memcpy(mZAxis.mV, buffer, 3*sizeof(F32)); | ||
483 | |||
484 | if( !isFinite() ) | ||
485 | { | ||
486 | llerrs << "Non Finite in LLCoordFrame::readOrientation()" << llendl; | ||
487 | } | ||
488 | |||
489 | return 12*sizeof(F32); | ||
490 | } | ||
491 | |||
492 | |||
493 | // rotation and transform vectors between reference frames | ||
494 | |||
495 | LLVector3 LLCoordFrame::rotateToLocal(const LLVector3 &absolute_vector) const | ||
496 | { | ||
497 | LLVector3 local_vector(mXAxis * absolute_vector, | ||
498 | mYAxis * absolute_vector, | ||
499 | mZAxis * absolute_vector); | ||
500 | return local_vector; | ||
501 | } | ||
502 | |||
503 | |||
504 | LLVector4 LLCoordFrame::rotateToLocal(const LLVector4 &absolute_vector) const | ||
505 | { | ||
506 | LLVector4 local_vector; | ||
507 | local_vector.mV[VX] = mXAxis.mV[VX] * absolute_vector.mV[VX] + | ||
508 | mXAxis.mV[VY] * absolute_vector.mV[VY] + | ||
509 | mXAxis.mV[VZ] * absolute_vector.mV[VZ]; | ||
510 | local_vector.mV[VY] = mYAxis.mV[VX] * absolute_vector.mV[VX] + | ||
511 | mYAxis.mV[VY] * absolute_vector.mV[VY] + | ||
512 | mYAxis.mV[VZ] * absolute_vector.mV[VZ]; | ||
513 | local_vector.mV[VZ] = mZAxis.mV[VX] * absolute_vector.mV[VX] + | ||
514 | mZAxis.mV[VY] * absolute_vector.mV[VY] + | ||
515 | mZAxis.mV[VZ] * absolute_vector.mV[VZ]; | ||
516 | local_vector.mV[VW] = absolute_vector.mV[VW]; | ||
517 | return local_vector; | ||
518 | } | ||
519 | |||
520 | |||
521 | LLVector3 LLCoordFrame::rotateToAbsolute(const LLVector3 &local_vector) const | ||
522 | { | ||
523 | LLVector3 absolute_vector; | ||
524 | absolute_vector.mV[VX] = mXAxis.mV[VX] * local_vector.mV[VX] + | ||
525 | mYAxis.mV[VX] * local_vector.mV[VY] + | ||
526 | mZAxis.mV[VX] * local_vector.mV[VZ]; | ||
527 | absolute_vector.mV[VY] = mXAxis.mV[VY] * local_vector.mV[VX] + | ||
528 | mYAxis.mV[VY] * local_vector.mV[VY] + | ||
529 | mZAxis.mV[VY] * local_vector.mV[VZ]; | ||
530 | absolute_vector.mV[VZ] = mXAxis.mV[VZ] * local_vector.mV[VX] + | ||
531 | mYAxis.mV[VZ] * local_vector.mV[VY] + | ||
532 | mZAxis.mV[VZ] * local_vector.mV[VZ]; | ||
533 | return absolute_vector; | ||
534 | } | ||
535 | |||
536 | |||
537 | LLVector4 LLCoordFrame::rotateToAbsolute(const LLVector4 &local_vector) const | ||
538 | { | ||
539 | LLVector4 absolute_vector; | ||
540 | absolute_vector.mV[VX] = mXAxis.mV[VX] * local_vector.mV[VX] + | ||
541 | mYAxis.mV[VX] * local_vector.mV[VY] + | ||
542 | mZAxis.mV[VX] * local_vector.mV[VZ]; | ||
543 | absolute_vector.mV[VY] = mXAxis.mV[VY] * local_vector.mV[VX] + | ||
544 | mYAxis.mV[VY] * local_vector.mV[VY] + | ||
545 | mZAxis.mV[VY] * local_vector.mV[VZ]; | ||
546 | absolute_vector.mV[VZ] = mXAxis.mV[VZ] * local_vector.mV[VX] + | ||
547 | mYAxis.mV[VZ] * local_vector.mV[VY] + | ||
548 | mZAxis.mV[VZ] * local_vector.mV[VZ]; | ||
549 | absolute_vector.mV[VW] = local_vector[VW]; | ||
550 | return absolute_vector; | ||
551 | } | ||
552 | |||
553 | |||
554 | void LLCoordFrame::orthonormalize() | ||
555 | // Makes sure the axes are orthogonal and normalized. | ||
556 | { | ||
557 | mXAxis.normVec(); // X is renormalized | ||
558 | mYAxis -= mXAxis * (mXAxis * mYAxis); // Y remains in X-Y plane | ||
559 | mYAxis.normVec(); // Y is normalized | ||
560 | mZAxis = mXAxis % mYAxis; // Z = X cross Y | ||
561 | } | ||
562 | |||
563 | |||
564 | LLVector3 LLCoordFrame::transformToLocal(const LLVector3 &absolute_vector) const | ||
565 | { | ||
566 | return rotateToLocal(absolute_vector - mOrigin); | ||
567 | } | ||
568 | |||
569 | |||
570 | LLVector4 LLCoordFrame::transformToLocal(const LLVector4 &absolute_vector) const | ||
571 | { | ||
572 | LLVector4 local_vector(absolute_vector); | ||
573 | local_vector.mV[VX] -= mOrigin.mV[VX]; | ||
574 | local_vector.mV[VY] -= mOrigin.mV[VY]; | ||
575 | local_vector.mV[VZ] -= mOrigin.mV[VZ]; | ||
576 | return rotateToLocal(local_vector); | ||
577 | } | ||
578 | |||
579 | |||
580 | LLVector3 LLCoordFrame::transformToAbsolute(const LLVector3 &local_vector) const | ||
581 | { | ||
582 | return (rotateToAbsolute(local_vector) + mOrigin); | ||
583 | } | ||
584 | |||
585 | |||
586 | LLVector4 LLCoordFrame::transformToAbsolute(const LLVector4 &local_vector) const | ||
587 | { | ||
588 | LLVector4 absolute_vector; | ||
589 | absolute_vector = rotateToAbsolute(local_vector); | ||
590 | absolute_vector.mV[VX] += mOrigin.mV[VX]; | ||
591 | absolute_vector.mV[VY] += mOrigin.mV[VY]; | ||
592 | absolute_vector.mV[VZ] += mOrigin.mV[VZ]; | ||
593 | return absolute_vector; | ||
594 | } | ||
595 | |||
596 | |||
597 | // This is how you combine a translation and rotation of a | ||
598 | // coordinate frame to get an OpenGL transformation matrix: | ||
599 | // | ||
600 | // translation * rotation = transformation matrix | ||
601 | // | ||
602 | // (i)-> | ||
603 | // (j)| 1 0 0 0 | | a d g 0 | | a d g 0 | | ||
604 | // | | 0 1 0 0 | * | b e h 0 | = | b e h 0 | | ||
605 | // V | 0 0 1 0 | | c f i 0 | | c f i 0 | | ||
606 | // |-x -y -z 1 | | 0 0 0 1 | |-(ax+by+cz) -(dx+ey+fz) -(gx+hy+iz) 1 | | ||
607 | // | ||
608 | // where {a,b,c} = x-axis | ||
609 | // {d,e,f} = y-axis | ||
610 | // {g,h,i} = z-axis | ||
611 | // {x,y,z} = origin | ||
612 | |||
613 | void LLCoordFrame::getOpenGLTranslation(F32 *ogl_matrix) const | ||
614 | { | ||
615 | *(ogl_matrix + 0) = 1.0f; | ||
616 | *(ogl_matrix + 1) = 0.0f; | ||
617 | *(ogl_matrix + 2) = 0.0f; | ||
618 | *(ogl_matrix + 3) = 0.0f; | ||
619 | |||
620 | *(ogl_matrix + 4) = 0.0f; | ||
621 | *(ogl_matrix + 5) = 1.0f; | ||
622 | *(ogl_matrix + 6) = 0.0f; | ||
623 | *(ogl_matrix + 7) = 0.0f; | ||
624 | |||
625 | *(ogl_matrix + 8) = 0.0f; | ||
626 | *(ogl_matrix + 9) = 0.0f; | ||
627 | *(ogl_matrix + 10) = 1.0f; | ||
628 | *(ogl_matrix + 11) = 0.0f; | ||
629 | |||
630 | *(ogl_matrix + 12) = -mOrigin.mV[VX]; | ||
631 | *(ogl_matrix + 13) = -mOrigin.mV[VY]; | ||
632 | *(ogl_matrix + 14) = -mOrigin.mV[VZ]; | ||
633 | *(ogl_matrix + 15) = 1.0f; | ||
634 | } | ||
635 | |||
636 | |||
637 | void LLCoordFrame::getOpenGLRotation(F32 *ogl_matrix) const | ||
638 | { | ||
639 | *(ogl_matrix + 0) = mXAxis.mV[VX]; | ||
640 | *(ogl_matrix + 4) = mXAxis.mV[VY]; | ||
641 | *(ogl_matrix + 8) = mXAxis.mV[VZ]; | ||
642 | |||
643 | *(ogl_matrix + 1) = mYAxis.mV[VX]; | ||
644 | *(ogl_matrix + 5) = mYAxis.mV[VY]; | ||
645 | *(ogl_matrix + 9) = mYAxis.mV[VZ]; | ||
646 | |||
647 | *(ogl_matrix + 2) = mZAxis.mV[VX]; | ||
648 | *(ogl_matrix + 6) = mZAxis.mV[VY]; | ||
649 | *(ogl_matrix + 10) = mZAxis.mV[VZ]; | ||
650 | |||
651 | *(ogl_matrix + 3) = 0.0f; | ||
652 | *(ogl_matrix + 7) = 0.0f; | ||
653 | *(ogl_matrix + 11) = 0.0f; | ||
654 | |||
655 | *(ogl_matrix + 12) = 0.0f; | ||
656 | *(ogl_matrix + 13) = 0.0f; | ||
657 | *(ogl_matrix + 14) = 0.0f; | ||
658 | *(ogl_matrix + 15) = 1.0f; | ||
659 | } | ||
660 | |||
661 | |||
662 | void LLCoordFrame::getOpenGLTransform(F32 *ogl_matrix) const | ||
663 | { | ||
664 | *(ogl_matrix + 0) = mXAxis.mV[VX]; | ||
665 | *(ogl_matrix + 4) = mXAxis.mV[VY]; | ||
666 | *(ogl_matrix + 8) = mXAxis.mV[VZ]; | ||
667 | *(ogl_matrix + 12) = -mOrigin * mXAxis; | ||
668 | |||
669 | *(ogl_matrix + 1) = mYAxis.mV[VX]; | ||
670 | *(ogl_matrix + 5) = mYAxis.mV[VY]; | ||
671 | *(ogl_matrix + 9) = mYAxis.mV[VZ]; | ||
672 | *(ogl_matrix + 13) = -mOrigin * mYAxis; | ||
673 | |||
674 | *(ogl_matrix + 2) = mZAxis.mV[VX]; | ||
675 | *(ogl_matrix + 6) = mZAxis.mV[VY]; | ||
676 | *(ogl_matrix + 10) = mZAxis.mV[VZ]; | ||
677 | *(ogl_matrix + 14) = -mOrigin * mZAxis; | ||
678 | |||
679 | *(ogl_matrix + 3) = 0.0f; | ||
680 | *(ogl_matrix + 7) = 0.0f; | ||
681 | *(ogl_matrix + 11) = 0.0f; | ||
682 | *(ogl_matrix + 15) = 1.0f; | ||
683 | } | ||
684 | |||
685 | |||
686 | // at and up_direction are presumed to be normalized | ||
687 | void LLCoordFrame::lookDir(const LLVector3 &at, const LLVector3 &up_direction) | ||
688 | { | ||
689 | // Make sure 'at' and 'up_direction' are not parallel | ||
690 | // and that neither are zero-length vectors | ||
691 | LLVector3 left(up_direction % at); | ||
692 | if (left.isNull()) | ||
693 | { | ||
694 | //tweak lookat pos so we don't get a degenerate matrix | ||
695 | LLVector3 tempat(at[VX] + 0.01f, at[VY], at[VZ]); | ||
696 | tempat.normVec(); | ||
697 | left = (up_direction % tempat); | ||
698 | } | ||
699 | left.normVec(); | ||
700 | |||
701 | LLVector3 up = at % left; | ||
702 | setAxes(at, left, up); | ||
703 | } | ||
704 | |||
705 | void LLCoordFrame::lookDir(const LLVector3 &xuv) | ||
706 | { | ||
707 | static LLVector3 up_direction(0.0f, 0.0f, 1.0f); | ||
708 | lookDir(xuv, up_direction); | ||
709 | } | ||
710 | |||
711 | void LLCoordFrame::lookAt(const LLVector3 &origin, const LLVector3 &point_of_interest, const LLVector3 &up_direction) | ||
712 | { | ||
713 | setOrigin(origin); | ||
714 | LLVector3 at(point_of_interest - origin); | ||
715 | at.normVec(); | ||
716 | lookDir(at, up_direction); | ||
717 | } | ||
718 | |||
719 | void LLCoordFrame::lookAt(const LLVector3 &origin, const LLVector3 &point_of_interest) | ||
720 | { | ||
721 | static LLVector3 up_direction(0.0f, 0.0f, 1.0f); | ||
722 | |||
723 | setOrigin(origin); | ||
724 | LLVector3 at(point_of_interest - origin); | ||
725 | at.normVec(); | ||
726 | lookDir(at, up_direction); | ||
727 | } | ||
728 | |||
729 | |||
730 | // Operators and friends | ||
731 | |||
732 | std::ostream& operator<<(std::ostream &s, const LLCoordFrame &C) | ||
733 | { | ||
734 | s << "{ " | ||
735 | << " origin = " << C.mOrigin | ||
736 | << " x_axis = " << C.mXAxis | ||
737 | << " y_axis = " << C.mYAxis | ||
738 | << " z_axis = " << C.mZAxis | ||
739 | << " }"; | ||
740 | return s; | ||
741 | } | ||
742 | |||
743 | |||
744 | |||
745 | // Private member functions | ||
746 | |||
747 | |||
748 | //EOF | ||