aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath/llcoordframe.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmath/llcoordframe.cpp')
-rw-r--r--linden/indra/llmath/llcoordframe.cpp748
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
46LLCoordFrame::LLCoordFrame() :
47 mOrigin(0.f, 0.f, 0.f),
48 mXAxis(X_AXIS),
49 mYAxis(Y_AXIS),
50 mZAxis(Z_AXIS)
51{
52}
53
54LLCoordFrame::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
66LLCoordFrame::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
77LLCoordFrame::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
91LLCoordFrame::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
107LLCoordFrame::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
120LLCoordFrame::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
134LLCoordFrame::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
148LLCoordFrame::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/*
163LLCoordFrame::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/*
177LLCoordFrame::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
191void LLCoordFrame::reset()
192{
193 mOrigin.setVec(0.0f, 0.0f, 0.0f);
194 resetAxes();
195}
196
197
198void 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
207void 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
217void 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
226void 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
238void 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
251void 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
265void 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
277void 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
288void 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
307void 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
322void 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
335void 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
346void 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
361void 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
368void LLCoordFrame::rotate(F32 angle, const LLVector3 &rotation_axis)
369{
370 LLQuaternion q(angle, rotation_axis);
371 rotate(q);
372}
373
374
375void LLCoordFrame::rotate(const LLQuaternion &q)
376{
377 LLMatrix3 rotation_matrix(q);
378 rotate(rotation_matrix);
379}
380
381
382void 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
395void 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
407void 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
419void 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
434LLQuaternion LLCoordFrame::getQuaternion() const
435{
436 LLQuaternion quat(mXAxis, mYAxis, mZAxis);
437 return quat;
438}
439
440
441void 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
453void 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
461size_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
474size_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
495LLVector3 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
504LLVector4 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
521LLVector3 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
537LLVector4 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
554void 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
564LLVector3 LLCoordFrame::transformToLocal(const LLVector3 &absolute_vector) const
565{
566 return rotateToLocal(absolute_vector - mOrigin);
567}
568
569
570LLVector4 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
580LLVector3 LLCoordFrame::transformToAbsolute(const LLVector3 &local_vector) const
581{
582 return (rotateToAbsolute(local_vector) + mOrigin);
583}
584
585
586LLVector4 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
613void 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
637void 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
662void 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
687void 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
705void LLCoordFrame::lookDir(const LLVector3 &xuv)
706{
707 static LLVector3 up_direction(0.0f, 0.0f, 1.0f);
708 lookDir(xuv, up_direction);
709}
710
711void 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
719void 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
732std::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