Developer Documentation
Loading...
Searching...
No Matches
GLMatrixT_impl.hh
1/*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40\*===========================================================================*/
41
42
43
44
45
46//=============================================================================
47//
48// CLASS GLMatrixT - IMPLEMENTATION
49//
50//=============================================================================
51
52
53#define ACG_GLMATRIX_C
54
55
56//== INCLUDES =================================================================
57
58
59#include "GLMatrixT.hh"
60#include <cmath>
61
62
63//== IMPLEMENTATION ==========================================================
64
65
66namespace ACG {
67
68
69//-----------------------------------------------------------------------------
70
71
72template<typename Scalar>
73void
75scale( Scalar _x, Scalar _y, Scalar _z,
76 MultiplyFrom _mult_from )
77{
79 m.identity();
80
81 m(0,0) = _x;
82 m(1,1) = _y;
83 m(2,2) = _z;
84
85 if (_mult_from == MULT_FROM_RIGHT) *this *= m;
86 else leftMult(m);
87}
88
89
90//-----------------------------------------------------------------------------
91
92
93template<typename Scalar>
94void
96translate( Scalar _x, Scalar _y, Scalar _z,
97 MultiplyFrom _mult_from )
98{
100 m.identity();
101
102 m(0,3) = _x;
103 m(1,3) = _y;
104 m(2,3) = _z;
105
106 if (_mult_from == MULT_FROM_RIGHT) *this *= m;
107 else leftMult(m);
108}
109
110
111//-----------------------------------------------------------------------------
112
113
114template<typename Scalar>
115void
117rotateXYZ( Axis _axis, Scalar _angle,
118 MultiplyFrom _mult_from )
119{
121 m.identity();
122
123 Scalar ca = cos(_angle * (M_PI/180.0));
124 Scalar sa = sin(_angle * (M_PI/180.0));
125
126 switch (_axis)
127 {
128 case X:
129 m(1,1) = m(2,2) = ca; m(2,1) = sa; m(1,2) = -sa;
130 break;
131
132 case Y:
133 m(0,0) = m(2,2) = ca; m(0,2) = sa; m(2,0) = -sa;
134 break;
135
136 case Z:
137 m(0,0) = m(1,1) = ca; m(1,0) = sa; m(0,1) = -sa;
138 break;
139 }
140
141
142 if (_mult_from == MULT_FROM_RIGHT) *this *= m;
143 else leftMult(m);
144}
145
146
147//-----------------------------------------------------------------------------
148
149
150/* Rotation matrix (taken from Mesa3.1)
151 original function contributed by Erich Boleyn (erich@uruk.org) */
152template <typename Scalar>
153void
155rotate( Scalar angle, Scalar x, Scalar y, Scalar z,
156 MultiplyFrom _mult_from )
159 Scalar mag, s, c;
160 Scalar xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
161
162 mag = sqrt( x*x + y*y + z*z );
163 if(mag == 0.) {
164 return;
165 }
166
167 s = sin( angle * ( Scalar(M_PI) / Scalar(180.) ) );
168 c = cos( angle * ( Scalar(M_PI) / Scalar(180.) ) );
169
170 x /= mag;
171 y /= mag;
172 z /= mag;
173
174 xx = x * x;
175 yy = y * y;
176 zz = z * z;
177 xy = x * y;
178 yz = y * z;
179 zx = z * x;
180 xs = x * s;
181 ys = y * s;
182 zs = z * s;
183 one_c = static_cast<Scalar>(1.0) - c;
184
185 m(0,0) = (one_c * xx) + c;
186 m(0,1) = (one_c * xy) - zs;
187 m(0,2) = (one_c * zx) + ys;
188 m(0,3) = static_cast<Scalar>(0.0);
189
190 m(1,0) = (one_c * xy) + zs;
191 m(1,1) = (one_c * yy) + c;
192 m(1,2) = (one_c * yz) - xs;
193 m(1,3) = static_cast<Scalar>(0.0);
194
195 m(2,0) = (one_c * zx) - ys;
196 m(2,1) = (one_c * yz) + xs;
197 m(2,2) = (one_c * zz) + c;
198 m(2,3) = static_cast<Scalar>(0.0);
199
200 m(3,0) = static_cast<Scalar>(0.0);
201 m(3,1) = static_cast<Scalar>(0.0);
202 m(3,2) = static_cast<Scalar>(0.0);
203 m(3,3) = static_cast<Scalar>(1.0);
204
205 if (_mult_from == MULT_FROM_RIGHT) *this *= m;
206 else leftMult(m);
207}
208
209
210//-----------------------------------------------------------------------------
211
212
213template<typename Scalar>
214void
216lookAt(const VectorT<Scalar,3>& eye,
217 const VectorT<Scalar,3>& center,
219{
220 VectorT<Scalar,3> z(eye);
221 z -= center;
222 z.normalize();
223
224 VectorT<Scalar,3> x(up % z);
225 x.normalize();
226
227 VectorT<Scalar,3> y(z % x);
228 y.normalize();
229
231 m(0,0)=x[0]; m(0,1)=x[1]; m(0,2)=x[2]; m(0,3)=0.0;
232 m(1,0)=y[0]; m(1,1)=y[1]; m(1,2)=y[2]; m(1,3)=0.0;
233 m(2,0)=z[0]; m(2,1)=z[1]; m(2,2)=z[2]; m(2,3)=0.0;
234 m(3,0)=static_cast<Scalar>(0.0); m(3,1)=static_cast<Scalar>(0.0); m(3,2)=static_cast<Scalar>(0.0); m(3,3)=static_cast<Scalar>(1.0);
235
236 *this *= m;
237 translate(-eye[0], -eye[1], -eye[2]);
238}
239
240
241//-----------------------------------------------------------------------------
242
243
244template<typename Scalar>
245void
248 const VectorT<Scalar,3>& center,
249 const VectorT<Scalar,3>& up)
250{
252 z -= center;
253 z.normalize();
254
255 VectorT<Scalar,3> x(up % z);
256 x.normalize();
257
258 VectorT<Scalar,3> y(z % x);
259 y.normalize();
260
262 m(0,0)=x[0]; m(0,1)=y[0]; m(0,2)=z[0]; m(0,3)=eye[0];
263 m(1,0)=x[1]; m(1,1)=y[1]; m(1,2)=z[1]; m(1,3)=eye[1];
264 m(2,0)=x[2]; m(2,1)=y[2]; m(2,2)=z[2]; m(2,3)=eye[2];
265 m(3,0)=static_cast<Scalar>(0.0); m(3,1)=static_cast<Scalar>(0.0); m(3,2)=static_cast<Scalar>(0.0); m(3,3)=static_cast<Scalar>(1.0);
267 leftMult(m);
268}
270
271//-----------------------------------------------------------------------------
273
274template<typename Scalar>
275void
277perspective(Scalar fovY, Scalar aspect,
278 Scalar near_plane, Scalar far_plane)
279{
280 Scalar ymax = near_plane * tan( fovY * static_cast<Scalar>(M_PI) / static_cast<Scalar>(360.0) );
281 Scalar ymin = -ymax;
282 Scalar xmin = ymin * aspect;
283 Scalar xmax = ymax * aspect;
284 frustum(xmin, xmax, ymin, ymax, near_plane, far_plane);
285}
286
287
288//-----------------------------------------------------------------------------
289
290
291template<typename Scalar>
292void
294inverse_perspective(Scalar fovY, Scalar aspect,
295 Scalar near_plane, Scalar far_plane)
296{
297 Scalar ymax = near_plane * tan( fovY * static_cast<Scalar>(M_PI) / static_cast<Scalar>(360.0) );
298 Scalar ymin = -ymax;
299 Scalar xmin = ymin * aspect;
300 Scalar xmax = ymax * aspect;
301 inverse_frustum(xmin, xmax, ymin, ymax, near_plane, far_plane);
302}
303
304
305//-----------------------------------------------------------------------------
306
307
308template<typename Scalar>
309void
311frustum( Scalar left,Scalar right,
312 Scalar bottom, Scalar top,
313 Scalar near_plane, Scalar far_plane )
314{
315 assert(near_plane > static_cast<Scalar>(0.0) && far_plane > near_plane);
316
318 Scalar x, y, a, b, c, d;
319
320 x = (static_cast<Scalar>(2.0)*near_plane) / (right-left);
321 y = (static_cast<Scalar>(2.0)*near_plane) / (top-bottom);
322 a = (right+left) / (right-left);
323 b = (top+bottom) / (top-bottom);
324 c = -(far_plane+near_plane) / ( far_plane-near_plane);
325 d = -(static_cast<Scalar>(2.0)*far_plane*near_plane) / (far_plane-near_plane);
326
327 m(0,0) = x; m(0,1) = static_cast<Scalar>(0.0); m(0,2) = a; m(0,3) = static_cast<Scalar>(0.0);
328 m(1,0) = static_cast<Scalar>(0.0); m(1,1) = y; m(1,2) = b; m(1,3) = static_cast<Scalar>(0.0);
329 m(2,0) = static_cast<Scalar>(0.0); m(2,1) = static_cast<Scalar>(0.0); m(2,2) = c; m(2,3) = d;
330 m(3,0) = static_cast<Scalar>(0.0); m(3,1) = static_cast<Scalar>(0.0); m(3,2) = static_cast<Scalar>(-1.0); m(3,3) = static_cast<Scalar>(0.0);
331
332 *this *= m;
333}
334
335
336//-----------------------------------------------------------------------------
337
338
339template<typename Scalar>
340void
342inverse_frustum(Scalar left,Scalar right,
343 Scalar bottom, Scalar top,
344 Scalar near_plane, Scalar far_plane)
345{
346 assert(near_plane > 0.0 && far_plane > near_plane);
347
349 Scalar x, y, a, b, c, d;
350
351 x = (right-left) / (static_cast<Scalar>(2.0)*near_plane);
352 y = (top-bottom) / (static_cast<Scalar>(2.0)*near_plane);
353 a = (right+left) / (static_cast<Scalar>(2.0)*near_plane);
354 b = (top+bottom) / (static_cast<Scalar>(2.0)*near_plane);
355 c = (far_plane+near_plane) / (static_cast<Scalar>(2.0)*far_plane*near_plane);
356 d = (near_plane-far_plane) / (static_cast<Scalar>(2.0)*far_plane*near_plane);
357
358 m(0,0)=x; m(0,1)= static_cast<Scalar>(0.0); m(0,2)= static_cast<Scalar>(0.0); m(0,3)= a;
359 m(1,0)=static_cast<Scalar>(0.0); m(1,1)= y; m(1,2)= static_cast<Scalar>(0.0); m(1,3)= b;
360 m(2,0)=static_cast<Scalar>(0.0); m(2,1)= static_cast<Scalar>(0.0); m(2,2)= static_cast<Scalar>(0.0); m(2,3)= static_cast<Scalar>(-1.0);
361 m(3,0)=static_cast<Scalar>(0.0); m(3,1)= static_cast<Scalar>(0.0); m(3,2)= d; m(3,3)= c;
362
363 leftMult(m);
364}
365
366
367//-----------------------------------------------------------------------------
368
369
370template<typename Scalar>
371void
373ortho(Scalar left, Scalar right,
374 Scalar bottom, Scalar top,
375 Scalar near_plane, Scalar far_plane)
376{
378
379 Scalar r_l = right-left;
380 Scalar t_b = top - bottom;
381 Scalar f_n = far_plane - near_plane;
382
383// assert(r_l > 0.0 && t_b > 0.0 && f_n > 0.0);
384
385 m(1,0) = m(0,1) = m(0,2) =
386 m(2,0) = m(2,1) = m(1,2) =
387 m(3,0) = m(3,1) = m(3,2) = static_cast<Scalar>(0.0);
388
389 m(0,0) = static_cast<Scalar>( 2.0) / r_l;
390 m(1,1) = static_cast<Scalar>( 2.0) / t_b;
391 m(2,2) = static_cast<Scalar>(-2.0) / f_n;
392
393 m(0,3) = -(right + left) / r_l;
394 m(1,3) = -(top + bottom) / t_b;
395 m(2,3) = -(far_plane + near_plane) / f_n;
396
397 m(3,3) = static_cast<Scalar>(1.0);
398
399 *this *= m;
400}
401
402
403//-----------------------------------------------------------------------------
404
405template<typename Scalar>
406void
408inverse_ortho(Scalar left, Scalar right,
409 Scalar bottom, Scalar top,
410 Scalar near_plane, Scalar far_plane)
411{
413
414 m(1,0) = m(0,1) = m(0,2) =
415 m(2,0) = m(2,1) = m(1,2) =
416 m(3,0) = m(3,1) = m(3,2) = static_cast<Scalar>(0.0);
417
418
419 m(0,0) = static_cast<Scalar>( 0.5) * (right - left);
420 m(1,1) = static_cast<Scalar>( 0.5) * (top - bottom);
421 m(2,2) = static_cast<Scalar>(-0.5) * (far_plane - near_plane);
422
423 m(0,3) = static_cast<Scalar>( 0.5) * (right + left);
424 m(1,3) = static_cast<Scalar>( 0.5) * (top + bottom);
425 m(2,3) = static_cast<Scalar>(-0.5) * (far_plane + near_plane);
426
427 m(3,3) = static_cast<Scalar>(1.0);
428
429 leftMult(m);
430}
431
432
433//-----------------------------------------------------------------------------
434
435template<typename Scalar>
439{
440 Scalar a = (*this)(2,2);
441 Scalar b = (*this)(2,3);
442
443 return VectorT<Scalar, 2>(b / (static_cast<Scalar>(-1.0) + a), b / (static_cast<Scalar>(1.0) + a));
444}
445
446//-----------------------------------------------------------------------------
447
448template<typename Scalar>
452{
453 Scalar a = (*this)(2,2);
454 Scalar b = (*this)(2,3);
455
456 return VectorT<Scalar, 2>((1.0 + b) / a, (-1.0 + b) / a);
457}
458
459//-----------------------------------------------------------------------------
460
461template<typename Scalar>
462bool
464 isPerspective() const
465{
466 // check if matrix matches the pattern of frustum()
467
468 // expect at least 5 nonzeros
469 const int nnz = 5;
470
471 // nonzero entries
472 const int nze[] =
473 {
474 0,0,
475 1,1,
476 2,2,
477 2,3,
478 3,2
479 };
480
481 // expect at least 9 zeros
482 const int nz = 9;
483
484 // zero entries
485 const int ze[] =
486 {
487 0,1,
488 0,3,
489 1,0,
490 1,3,
491 2,0,
492 2,1,
493 3,0,
494 3,1,
495 3,3,
496 };
497
498 for (int i = 0; i < nnz; ++i)
499 {
500 if ( checkEpsilon( (*this)(nze[i*2],nze[i*2+1]) ) )
501 return false;
502 }
503
504 // expect -1 at (3,2)
505 if ( !checkEpsilon( (*this)(3,2) + 1.0 ) )
506 return false;
507
508 // check rest for zero
509 for (int i = 0; i < nz; ++i)
510 {
511 if ( !checkEpsilon( (*this)(ze[i*2],ze[i*2+1]) ) )
512 return false;
513 }
514
515 return true;
516}
517
518//-----------------------------------------------------------------------------
519
520template<typename Scalar>
521bool
523 isOrtho() const
524{
525 // check if matrix matches the pattern of ortho()
526
527 // expect at least 5 nonzeros (diagonal) and m(2,3)
528
529 for (int i = 0; i < 3; ++i)
530 {
531 if ( checkEpsilon( (*this)(i,i) ) )
532 return false;
533 }
534
535 // expect 1 at (3,3)
536 if ( !checkEpsilon( (*this)(3,3) - 1.0 ) )
537 return false;
538
539 // m(2,3) must be nonzero
540 if ( checkEpsilon( (*this)(2,3) ) )
541 return false;
542
543
544 // expect at least 9 zeros
545 const int nz = 9;
546
547 // zero entries
548 const int ze[] =
549 {
550 0,1,
551 0,2,
552 1,0,
553 1,2,
554 2,0,
555 2,1,
556 3,0,
557 3,1,
558 3,2,
559 };
560
561 // check rest for zero (except last column)
562 for (int i = 0; i < nz; ++i)
563 {
564 if ( !checkEpsilon( (*this)(ze[i*2],ze[i*2+1]) ) )
565 return false;
566 }
567
568 return true;
569}
570
571//-----------------------------------------------------------------------------
572
573template<typename Scalar>
576 extract_planes() const
577{
578 if (isPerspective())
579 return extract_planes_perspective();
580
581 if (isOrtho())
582 return extract_planes_ortho();
583
584 // return invalid planes
585 return VectorT<Scalar,2>(1.0, -1.0);
586}
587
588//-----------------------------------------------------------------------------
589
590
591#undef MAT
592#undef M
593
594
595//=============================================================================
596} // namespace ACG
597//=============================================================================
4x4 matrix implementing OpenGL commands.
Definition GLMatrixT.hh:80
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
void frustum(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self with a perspective projection matrix
bool isOrtho() const
check if the matrix is an orthographic projection matrix
VectorT< Scalar, 2 > extract_planes_ortho() const
extract near and far clipping planes from an orthographic projection matrix
void inverse_ortho(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self from left with inverse orthographic projection matrix
void inverse_frustum(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self from left with inverse of perspective projection matrix
void lookAt(const Vec3 &eye, const Vec3 &center, const Vec3 &up)
void perspective(Scalar fovY, Scalar aspect, Scalar near_plane, Scalar far_plane)
multiply self with a perspective projection matrix
void ortho(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self with orthographic projection matrix
VectorT< Scalar, 2 > extract_planes_perspective() const
extract near and far clipping planes from a perspective projection matrix
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
void inverse_lookAt(const Vec3 &eye, const Vec3 &center, const Vec3 &up)
multiply self from left with inverse lookAt matrix
void inverse_perspective(Scalar fovY, Scalar aspect, Scalar near_plane, Scalar far_plane)
multiply self from left with inverse of perspective projection matrix
VectorT< Scalar, 2 > extract_planes() const
detect type of projection matrix and extract near and far clipping planes
bool isPerspective() const
check if the matrix is a perspective projection matrix
void identity()
setup an identity matrix
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM > >().norm())
Definition Vector11T.hh:454
Namespace providing different geometric functions concerning angles.
MultiplyFrom
Definition GLMatrixT.hh:73