Developer Documentation
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 
66 namespace ACG {
67 
68 
69 //-----------------------------------------------------------------------------
70 
71 
72 template<typename Scalar>
73 void
75 scale( 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 
93 template<typename Scalar>
94 void
96 translate( 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 
114 template<typename Scalar>
115 void
117 rotateXYZ( 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) */
152 template <typename Scalar>
153 void
155 rotate( Scalar angle, Scalar x, Scalar y, Scalar z,
156  MultiplyFrom _mult_from )
157 {
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 
213 template<typename Scalar>
214 void
217  const VectorT<Scalar,3>& center,
218  const VectorT<Scalar,3>& up)
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 
244 template<typename Scalar>
245 void
248  const VectorT<Scalar,3>& center,
249  const VectorT<Scalar,3>& up)
250 {
251  VectorT<Scalar,3> z(eye);
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);
266 
267  leftMult(m);
268 }
269 
270 
271 //-----------------------------------------------------------------------------
272 
273 
274 template<typename Scalar>
275 void
277 perspective(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 
291 template<typename Scalar>
292 void
294 inverse_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 
308 template<typename Scalar>
309 void
311 frustum( 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 
339 template<typename Scalar>
340 void
342 inverse_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 
370 template<typename Scalar>
371 void
373 ortho(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 
405 template<typename Scalar>
406 void
408 inverse_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 
435 template<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 
448 template<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 
461 template<typename Scalar>
462 bool
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 
520 template<typename Scalar>
521 bool
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 
573 template<typename Scalar>
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 //=============================================================================
void frustum(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self with a perspective projection matrix
Namespace providing different geometric functions concerning angles.
bool isPerspective() const
check if the matrix is a perspective projection matrix
void inverse_perspective(Scalar fovY, Scalar aspect, 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 inverse_lookAt(const Vec3 &eye, const Vec3 &center, const Vec3 &up)
multiply self from left with inverse lookAt matrix
MultiplyFrom
Definition: GLMatrixT.hh:73
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:429
VectorT< Scalar, 2 > extract_planes_perspective() const
extract near and far clipping planes from a perspective 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 scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
4x4 matrix implementing OpenGL commands.
Definition: GLMatrixT.hh:79
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 ortho(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self with orthographic projection matrix
void perspective(Scalar fovY, Scalar aspect, Scalar near_plane, Scalar far_plane)
multiply self with a perspective projection matrix
void identity()
setup an identity matrix
VectorT< Scalar, 2 > extract_planes_ortho() const
extract near and far clipping planes from an orthographic projection matrix
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
VectorT< Scalar, 2 > extract_planes() const
detect type of projection matrix and extract near and far clipping planes
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
bool isOrtho() const
check if the matrix is an orthographic projection matrix