Developer Documentation
GLMatrixT.cc
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  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 
51 
52 //=============================================================================
53 //
54 // CLASS GLMatrixT - IMPLEMENTATION
55 //
56 //=============================================================================
57 
58 
59 #define ACG_GLMATRIX_C
60 
61 
62 //== INCLUDES =================================================================
63 
64 
65 #include "GLMatrixT.hh"
66 #include <cmath>
67 
68 
69 //== IMPLEMENTATION ==========================================================
70 
71 
72 namespace ACG {
73 
74 
75 //-----------------------------------------------------------------------------
76 
77 
78 template<typename Scalar>
79 void
81 scale( Scalar _x, Scalar _y, Scalar _z,
82  MultiplyFrom _mult_from )
83 {
85  m.identity();
86 
87  m(0,0) = _x;
88  m(1,1) = _y;
89  m(2,2) = _z;
90 
91  if (_mult_from == MULT_FROM_RIGHT) *this *= m;
92  else leftMult(m);
93 }
94 
95 
96 //-----------------------------------------------------------------------------
97 
98 
99 template<typename Scalar>
100 void
102 translate( Scalar _x, Scalar _y, Scalar _z,
103  MultiplyFrom _mult_from )
104 {
106  m.identity();
107 
108  m(0,3) = _x;
109  m(1,3) = _y;
110  m(2,3) = _z;
111 
112  if (_mult_from == MULT_FROM_RIGHT) *this *= m;
113  else leftMult(m);
114 }
115 
116 
117 //-----------------------------------------------------------------------------
118 
119 
120 template<typename Scalar>
121 void
123 rotateXYZ( Axis _axis, Scalar _angle,
124  MultiplyFrom _mult_from )
125 {
127  m.identity();
128 
129  Scalar ca = cos(_angle * (M_PI/180.0));
130  Scalar sa = sin(_angle * (M_PI/180.0));
131 
132  switch (_axis)
133  {
134  case X:
135  m(1,1) = m(2,2) = ca; m(2,1) = sa; m(1,2) = -sa;
136  break;
137 
138  case Y:
139  m(0,0) = m(2,2) = ca; m(0,2) = sa; m(2,0) = -sa;
140  break;
141 
142  case Z:
143  m(0,0) = m(1,1) = ca; m(1,0) = sa; m(0,1) = -sa;
144  break;
145  }
146 
147 
148  if (_mult_from == MULT_FROM_RIGHT) *this *= m;
149  else leftMult(m);
150 }
151 
152 
153 //-----------------------------------------------------------------------------
154 
155 
156 /* Rotation matrix (taken from Mesa3.1)
157  original function contributed by Erich Boleyn (erich@uruk.org) */
158 template <typename Scalar>
159 void
161 rotate( Scalar angle, Scalar x, Scalar y, Scalar z,
162  MultiplyFrom _mult_from )
163 {
165  Scalar mag, s, c;
166  Scalar xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
167 
168  mag = sqrt( x*x + y*y + z*z );
169  if(mag == 0.) {
170  return;
171  }
172 
173  s = sin( angle * ( Scalar(M_PI) / Scalar(180.) ) );
174  c = cos( angle * ( Scalar(M_PI) / Scalar(180.) ) );
175 
176  x /= mag;
177  y /= mag;
178  z /= mag;
179 
180  xx = x * x;
181  yy = y * y;
182  zz = z * z;
183  xy = x * y;
184  yz = y * z;
185  zx = z * x;
186  xs = x * s;
187  ys = y * s;
188  zs = z * s;
189  one_c = 1.0F - c;
190 
191  m(0,0) = (one_c * xx) + c;
192  m(0,1) = (one_c * xy) - zs;
193  m(0,2) = (one_c * zx) + ys;
194  m(0,3) = 0.0F;
195 
196  m(1,0) = (one_c * xy) + zs;
197  m(1,1) = (one_c * yy) + c;
198  m(1,2) = (one_c * yz) - xs;
199  m(1,3) = 0.0F;
200 
201  m(2,0) = (one_c * zx) - ys;
202  m(2,1) = (one_c * yz) + xs;
203  m(2,2) = (one_c * zz) + c;
204  m(2,3) = 0.0F;
205 
206  m(3,0) = 0.0F;
207  m(3,1) = 0.0F;
208  m(3,2) = 0.0F;
209  m(3,3) = 1.0F;
210 
211  if (_mult_from == MULT_FROM_RIGHT) *this *= m;
212  else leftMult(m);
213 }
214 
215 
216 //-----------------------------------------------------------------------------
217 
218 
219 template<typename Scalar>
220 void
223  const VectorT<Scalar,3>& center,
224  const VectorT<Scalar,3>& up)
225 {
226  VectorT<Scalar,3> z(eye);
227  z -= center;
228  z.normalize();
229 
230  VectorT<Scalar,3> x(up % z);
231  x.normalize();
232 
233  VectorT<Scalar,3> y(z % x);
234  y.normalize();
235 
237  m(0,0)=x[0]; m(0,1)=x[1]; m(0,2)=x[2]; m(0,3)=0.0;
238  m(1,0)=y[0]; m(1,1)=y[1]; m(1,2)=y[2]; m(1,3)=0.0;
239  m(2,0)=z[0]; m(2,1)=z[1]; m(2,2)=z[2]; m(2,3)=0.0;
240  m(3,0)=0.0; m(3,1)=0.0; m(3,2)=0.0; m(3,3)=1.0;
241 
242  *this *= m;
243  translate(-eye[0], -eye[1], -eye[2]);
244 }
245 
246 
247 //-----------------------------------------------------------------------------
248 
249 
250 template<typename Scalar>
251 void
254  const VectorT<Scalar,3>& center,
255  const VectorT<Scalar,3>& up)
256 {
257  VectorT<Scalar,3> z(eye);
258  z -= center;
259  z.normalize();
260 
261  VectorT<Scalar,3> x(up % z);
262  x.normalize();
263 
264  VectorT<Scalar,3> y(z % x);
265  y.normalize();
266 
268  m(0,0)=x[0]; m(0,1)=y[0]; m(0,2)=z[0]; m(0,3)=eye[0];
269  m(1,0)=x[1]; m(1,1)=y[1]; m(1,2)=z[1]; m(1,3)=eye[1];
270  m(2,0)=x[2]; m(2,1)=y[2]; m(2,2)=z[2]; m(2,3)=eye[2];
271  m(3,0)=0.0; m(3,1)=0.0; m(3,2)=0.0; m(3,3)=1.0;
272 
273  leftMult(m);
274 }
275 
276 
277 //-----------------------------------------------------------------------------
278 
279 
280 template<typename Scalar>
281 void
283 perspective(Scalar fovY, Scalar aspect,
284  Scalar near_plane, Scalar far_plane)
285 {
286  Scalar ymax = near_plane * tan( fovY * M_PI / 360.0 );
287  Scalar ymin = -ymax;
288  Scalar xmin = ymin * aspect;
289  Scalar xmax = ymax * aspect;
290  frustum(xmin, xmax, ymin, ymax, near_plane, far_plane);
291 }
292 
293 
294 //-----------------------------------------------------------------------------
295 
296 
297 template<typename Scalar>
298 void
300 inverse_perspective(Scalar fovY, Scalar aspect,
301  Scalar near_plane, Scalar far_plane)
302 {
303  Scalar ymax = near_plane * tan( fovY * M_PI / 360.0 );
304  Scalar ymin = -ymax;
305  Scalar xmin = ymin * aspect;
306  Scalar xmax = ymax * aspect;
307  inverse_frustum(xmin, xmax, ymin, ymax, near_plane, far_plane);
308 }
309 
310 
311 //-----------------------------------------------------------------------------
312 
313 
314 template<typename Scalar>
315 void
317 frustum( Scalar left,Scalar right,
318  Scalar bottom, Scalar top,
319  Scalar near_plane, Scalar far_plane )
320 {
321  assert(near_plane > 0.0 && far_plane > near_plane);
322 
324  Scalar x, y, a, b, c, d;
325 
326  x = (2.0*near_plane) / (right-left);
327  y = (2.0*near_plane) / (top-bottom);
328  a = (right+left) / (right-left);
329  b = (top+bottom) / (top-bottom);
330  c = -(far_plane+near_plane) / ( far_plane-near_plane);
331  d = -(2.0*far_plane*near_plane) / (far_plane-near_plane);
332 
333  m(0,0) = x; m(0,1) = 0.0F; m(0,2) = a; m(0,3) = 0.0F;
334  m(1,0) = 0.0F; m(1,1) = y; m(1,2) = b; m(1,3) = 0.0F;
335  m(2,0) = 0.0F; m(2,1) = 0.0F; m(2,2) = c; m(2,3) = d;
336  m(3,0) = 0.0F; m(3,1) = 0.0F; m(3,2) = -1.0F; m(3,3) = 0.0F;
337 
338  *this *= m;
339 }
340 
341 
342 //-----------------------------------------------------------------------------
343 
344 
345 template<typename Scalar>
346 void
348 inverse_frustum(Scalar left,Scalar right,
349  Scalar bottom, Scalar top,
350  Scalar near_plane, Scalar far_plane)
351 {
352  assert(near_plane > 0.0 && far_plane > near_plane);
353 
355  Scalar x, y, a, b, c, d;
356 
357  x = (right-left) / (2.0*near_plane);
358  y = (top-bottom) / (2.0*near_plane);
359  a = (right+left) / (2.0*near_plane);
360  b = (top+bottom) / (2.0*near_plane);
361  c = (far_plane+near_plane) / (2.0*far_plane*near_plane);
362  d = (near_plane-far_plane) / (2.0*far_plane*near_plane);
363 
364  m(0,0)=x; m(0,1)= 0.0F; m(0,2)= 0.0F; m(0,3)= a;
365  m(1,0)=0.0F; m(1,1)= y; m(1,2)= 0.0F; m(1,3)= b;
366  m(2,0)=0.0F; m(2,1)= 0.0F; m(2,2)= 0.0F; m(2,3)= -1.0;
367  m(3,0)=0.0F; m(3,1)= 0.0F; m(3,2)= d; m(3,3)= c;
368 
369  leftMult(m);
370 }
371 
372 
373 //-----------------------------------------------------------------------------
374 
375 
376 template<typename Scalar>
377 void
379 ortho(Scalar left, Scalar right,
380  Scalar bottom, Scalar top,
381  Scalar near_plane, Scalar far_plane)
382 {
384 
385  Scalar r_l = right-left;
386  Scalar t_b = top - bottom;
387  Scalar f_n = far_plane - near_plane;
388 
389 // assert(r_l > 0.0 && t_b > 0.0 && f_n > 0.0);
390 
391  m(1,0) = m(0,1) = m(0,2) =
392  m(2,0) = m(2,1) = m(1,2) =
393  m(3,0) = m(3,1) = m(3,2) = 0.0;
394 
395  m(0,0) = 2.0 / r_l;
396  m(1,1) = 2.0 / t_b;
397  m(2,2) = -2.0 / f_n;
398 
399  m(0,3) = -(right + left) / r_l;
400  m(1,3) = -(top + bottom) / t_b;
401  m(2,3) = -(far_plane + near_plane) / f_n;
402 
403  m(3,3) = 1.0;
404 
405  *this *= m;
406 }
407 
408 
409 //-----------------------------------------------------------------------------
410 
411 template<typename Scalar>
412 void
414 inverse_ortho(Scalar left, Scalar right,
415  Scalar bottom, Scalar top,
416  Scalar near_plane, Scalar far_plane)
417 {
419 
420  m(1,0) = m(0,1) = m(0,2) =
421  m(2,0) = m(2,1) = m(1,2) =
422  m(3,0) = m(3,1) = m(3,2) = 0.0;
423 
424 
425  m(0,0) = 0.5 * (right - left);
426  m(1,1) = 0.5 * (top - bottom);
427  m(2,2) = -0.5 * (far_plane - near_plane);
428 
429  m(0,3) = 0.5 * (right + left);
430  m(1,3) = 0.5 * (top + bottom);
431  m(2,3) = -0.5 * (far_plane + near_plane);
432 
433  m(3,3) = 1.0;
434 
435  leftMult(m);
436 }
437 
438 
439 //-----------------------------------------------------------------------------
440 
441 template<typename Scalar>
445 {
446  Scalar a = (*this)(2,2);
447  Scalar b = (*this)(2,3);
448 
449  return VectorT<Scalar, 2>(b / (-1.0 + a), b / (1.0 + a));
450 }
451 
452 //-----------------------------------------------------------------------------
453 
454 template<typename Scalar>
458 {
459  Scalar a = (*this)(2,2);
460  Scalar b = (*this)(2,3);
461 
462  return VectorT<Scalar, 2>((1.0 + b) / a, (-1.0 + b) / a);
463 }
464 
465 //-----------------------------------------------------------------------------
466 
467 template<typename Scalar>
468 bool
471 {
472  // check if matrix matches the pattern of frustum()
473 
474  // expect at least 5 nonzeros
475  const int nnz = 5;
476 
477  // nonzero entries
478  const int nze[] =
479  {
480  0,0,
481  1,1,
482  2,2,
483  2,3,
484  3,2
485  };
486 
487  // expect at least 9 zeros
488  const int nz = 9;
489 
490  // zero entries
491  const int ze[] =
492  {
493  0,1,
494  0,3,
495  1,0,
496  1,3,
497  2,0,
498  2,1,
499  3,0,
500  3,1,
501  3,3,
502  };
503 
504  for (int i = 0; i < nnz; ++i)
505  {
506  if ( checkEpsilon( (*this)(nze[i*2],nze[i*2+1]) ) )
507  return false;
508  }
509 
510  // expect -1 at (3,2)
511  if ( !checkEpsilon( (*this)(3,2) + 1.0 ) )
512  return false;
513 
514  // check rest for zero
515  for (int i = 0; i < nz; ++i)
516  {
517  if ( !checkEpsilon( (*this)(ze[i*2],ze[i*2+1]) ) )
518  return false;
519  }
520 
521  return true;
522 }
523 
524 //-----------------------------------------------------------------------------
525 
526 template<typename Scalar>
527 bool
529  isOrtho() const
530 {
531  // check if matrix matches the pattern of ortho()
532 
533  // expect at least 5 nonzeros (diagonal) and m(2,3)
534 
535  for (int i = 0; i < 3; ++i)
536  {
537  if ( checkEpsilon( (*this)(i,i) ) )
538  return false;
539  }
540 
541  // expect 1 at (3,3)
542  if ( !checkEpsilon( (*this)(3,3) - 1.0 ) )
543  return false;
544 
545  // m(2,3) must be nonzero
546  if ( checkEpsilon( (*this)(2,3) ) )
547  return false;
548 
549 
550  // expect at least 9 zeros
551  const int nz = 9;
552 
553  // zero entries
554  const int ze[] =
555  {
556  0,1,
557  0,2,
558  1,0,
559  1,2,
560  2,0,
561  2,1,
562  3,0,
563  3,1,
564  3,2,
565  };
566 
567  // check rest for zero (except last column)
568  for (int i = 0; i < nz; ++i)
569  {
570  if ( !checkEpsilon( (*this)(ze[i*2],ze[i*2+1]) ) )
571  return false;
572  }
573 
574  return true;
575 }
576 
577 //-----------------------------------------------------------------------------
578 
579 template<typename Scalar>
583 {
584  if (isPerspective())
585  return extract_planes_perspective();
586 
587  if (isOrtho())
588  return extract_planes_ortho();
589 
590  // return invalid planes
591  return VectorT<Scalar,2>(1.0, -1.0);
592 }
593 
594 //-----------------------------------------------------------------------------
595 
596 
597 #undef MAT
598 #undef M
599 
600 
601 //=============================================================================
602 } // namespace ACG
603 //=============================================================================
void inverse_lookAt(const Vec3 &eye, const Vec3 &center, const Vec3 &up)
multiply self from left with inverse lookAt matrix
Definition: GLMatrixT.cc:253
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
Definition: GLMatrixT.cc:102
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
Definition: GLMatrixT.cc:348
VectorT< Scalar, 2 > extract_planes() const
detect type of projection matrix and extract near and far clipping planes
Definition: GLMatrixT.cc:582
MultiplyFrom
Definition: GLMatrixT.hh:79
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
Definition: GLMatrixT.cc:161
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256
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
Definition: GLMatrixT.cc:414
VectorT< Scalar, 2 > extract_planes_perspective() const
extract near and far clipping planes from a perspective projection matrix
Definition: GLMatrixT.cc:444
4x4 matrix implementing OpenGL commands.
Definition: GLMatrixT.hh:85
void perspective(Scalar fovY, Scalar aspect, Scalar near_plane, Scalar far_plane)
multiply self with a perspective projection matrix
Definition: GLMatrixT.cc:283
VectorT< Scalar, 2 > extract_planes_ortho() const
extract near and far clipping planes from an orthographic projection matrix
Definition: GLMatrixT.cc:457
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
Definition: GLMatrixT.cc:81
void frustum(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self with a perspective projection matrix
Definition: GLMatrixT.cc:317
bool isOrtho() const
check if the matrix is an orthographic projection matrix
Definition: GLMatrixT.cc:529
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:428
void inverse_perspective(Scalar fovY, Scalar aspect, Scalar near_plane, Scalar far_plane)
multiply self from left with inverse of perspective projection matrix
Definition: GLMatrixT.cc:300
void lookAt(const Vec3 &eye, const Vec3 &center, const Vec3 &up)
Definition: GLMatrixT.cc:222
bool isPerspective() const
check if the matrix is a perspective projection matrix
Definition: GLMatrixT.cc:470
void ortho(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self with orthographic projection matrix
Definition: GLMatrixT.cc:379