Visualization Library 2.1.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
Matrix4.hpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #ifndef Matrix4_INCLUDE_ONCE
33 #define Matrix4_INCLUDE_ONCE
34 
35 #include <vlCore/Vector4.hpp>
36 #include <vlCore/Matrix3.hpp>
37 
38 namespace vl
39 {
40  //-----------------------------------------------------------------------------
41  // Matrix4
42  //-----------------------------------------------------------------------------
47  template<typename T_Scalar>
48  class Matrix4
49  {
50  public:
51  typedef T_Scalar scalar_type;
52  //-----------------------------------------------------------------------------
53  template<typename T>
54  explicit Matrix4(const Matrix4<T>& m)
55  {
56  e(0,0) = (T_Scalar)m.e(0,0); e(1,0) = (T_Scalar)m.e(1,0); e(2,0) = (T_Scalar)m.e(2,0); e(3,0) = (T_Scalar)m.e(3,0);
57  e(0,1) = (T_Scalar)m.e(0,1); e(1,1) = (T_Scalar)m.e(1,1); e(2,1) = (T_Scalar)m.e(2,1); e(3,1) = (T_Scalar)m.e(3,1);
58  e(0,2) = (T_Scalar)m.e(0,2); e(1,2) = (T_Scalar)m.e(1,2); e(2,2) = (T_Scalar)m.e(2,2); e(3,2) = (T_Scalar)m.e(3,2);
59  e(0,3) = (T_Scalar)m.e(0,3); e(1,3) = (T_Scalar)m.e(1,3); e(2,3) = (T_Scalar)m.e(2,3); e(3,3) = (T_Scalar)m.e(3,3);
60  }
61  //-----------------------------------------------------------------------------
62  Matrix4(const Matrix4& other)
63  {
64  operator=(other);
65  }
66  //-----------------------------------------------------------------------------
68  {
69  setIdentity();
70  }
71  //-----------------------------------------------------------------------------
72  explicit Matrix4(T_Scalar n)
73  {
74  setIdentity();
75  e(0,0) = e(1,1) = e(2,2) = e(3,3) = n;
76  }
77  //-----------------------------------------------------------------------------
78  explicit Matrix4(T_Scalar* val)
79  {
80  fillPtr(val);
81  }
82  //-----------------------------------------------------------------------------
83  explicit Matrix4( T_Scalar e00, T_Scalar e01, T_Scalar e02, T_Scalar e03,
84  T_Scalar e10, T_Scalar e11, T_Scalar e12, T_Scalar e13,
85  T_Scalar e20, T_Scalar e21, T_Scalar e22, T_Scalar e23,
86  T_Scalar e30, T_Scalar e31, T_Scalar e32, T_Scalar e33)
87  {
88  e(0,0) = e00; e(0,1) = e01; e(0,2) = e02; e(0,3) = e03;
89  e(1,0) = e10; e(1,1) = e11; e(1,2) = e12; e(1,3) = e13;
90  e(2,0) = e20; e(2,1) = e21; e(2,2) = e22; e(2,3) = e23;
91  e(3,0) = e30; e(3,1) = e31; e(3,2) = e32; e(3,3) = e33;
92  }
93  //-----------------------------------------------------------------------------
94  Matrix4& fill(T_Scalar val)
95  {
96  e(0,0) = e(1,0) = e(2,0) = e(3,0) =
97  e(0,1) = e(1,1) = e(2,1) = e(3,1) =
98  e(0,2) = e(1,2) = e(2,2) = e(3,2) =
99  e(0,3) = e(1,3) = e(2,3) = e(3,3) = val;
100  return *this;
101  }
102  //-----------------------------------------------------------------------------
103  Matrix4& fillPtr(T_Scalar* val)
104  {
105  memcpy(ptr(), val, sizeof(T_Scalar)*16);
106  return *this;
107  }
108  //-----------------------------------------------------------------------------
109  T_Scalar diff(const Matrix4& other) const
110  {
111  T_Scalar err = 0;
112  for(int i=0; i<4; ++i)
113  for(int j=0; j<4; ++j)
114  if (e(j,i) > other.e(j,i)) // avoid fabs/abs
115  err += e(j,i) - other.e(j,i);
116  else
117  err += other.e(j,i) - e(j,i);
118  return err;
119  }
120  //-----------------------------------------------------------------------------
122  {
123  return Vector3<T_Scalar>(mVec[0].x(), mVec[0].y(), mVec[0].z());
124  }
125  //-----------------------------------------------------------------------------
127  {
128  return Vector3<T_Scalar>(mVec[1].x(), mVec[1].y(), mVec[1].z());
129  }
130  //-----------------------------------------------------------------------------
132  {
133  return Vector3<T_Scalar>(mVec[2].x(), mVec[2].y(), mVec[2].z());
134  }
135  //-----------------------------------------------------------------------------
137  {
138  return Vector3<T_Scalar>(mVec[3].x(), mVec[3].y(), mVec[3].z());
139  }
140  //-----------------------------------------------------------------------------
142  {
143  mVec[0].x() = v.x();
144  mVec[0].y() = v.y();
145  mVec[0].z() = v.z();
146  return *this;
147  }
148  //-----------------------------------------------------------------------------
150  {
151  mVec[1].x() = v.x();
152  mVec[1].y() = v.y();
153  mVec[1].z() = v.z();
154  return *this;
155  }
156  //-----------------------------------------------------------------------------
158  {
159  mVec[2].x() = v.x();
160  mVec[2].y() = v.y();
161  mVec[2].z() = v.z();
162  return *this;
163  }
164  //-----------------------------------------------------------------------------
166  {
167  mVec[3].x() = v.x();
168  mVec[3].y() = v.y();
169  mVec[3].z() = v.z();
170  return *this;
171  }
172  //-----------------------------------------------------------------------------
173  bool operator==(const Matrix4& m) const
174  {
175  return memcmp(m.mVec, mVec, sizeof(T_Scalar)*4*4) == 0;
176  }
177  //-----------------------------------------------------------------------------
178  bool operator!=(const Matrix4& m) const
179  {
180  return !operator==(m);
181  }
182  //-----------------------------------------------------------------------------
184  {
185  memcpy(mVec, m.mVec, sizeof(T_Scalar)*16);
186  return *this;
187  }
188  //-----------------------------------------------------------------------------
189  Matrix4 operator+(const Matrix4& m) const
190  {
191  Matrix4 t;
192  for(int i=0; i<4; ++i)
193  for(int j=0; j<4; ++j)
194  t.e(j,i) = e(j,i) + m.e(j,i);
195 
196  return t;
197  }
198  //-----------------------------------------------------------------------------
200  {
201  for(int i=0; i<4; ++i)
202  for(int j=0; j<4; ++j)
203  e(j,i) += m.e(i,j);
204  return *this;
205  }
206  //-----------------------------------------------------------------------------
207  Matrix4 operator-(const Matrix4& m) const
208  {
209  Matrix4 t;
210  for(int i=0; i<4; ++i)
211  for(int j=0; j<4; ++j)
212  t.e(j,i) = e(j,i) - m.e(j,i);
213 
214  return t;
215  }
216  //-----------------------------------------------------------------------------
218  {
219  for(int i=0; i<4; ++i)
220  for(int j=0; j<4; ++j)
221  e(j,i) -= m.e(i,j);
222  return *this;
223  }
224  //-----------------------------------------------------------------------------
226  {
227  return postMultiply(m);
228  }
229  //-----------------------------------------------------------------------------
231  {
232  Matrix4 t;
233  for(int i=0; i<4; ++i)
234  for(int j=0; j<4; ++j)
235  t.e(j,i) = -e(j,i);
236  return t;
237  }
238  //-----------------------------------------------------------------------------
239  Matrix4 operator+(T_Scalar d) const
240  {
241  Matrix4 t;
242  for(int i=0; i<4; ++i)
243  for(int j=0; j<4; ++j)
244  t.e(j,i) = e(j,i) + d;
245  return t;
246  }
247  //-----------------------------------------------------------------------------
248  Matrix4& operator+=(T_Scalar d)
249  {
250  for(int i=0; i<4; ++i)
251  for(int j=0; j<4; ++j)
252  e(j,i) += d;
253  return *this;
254  }
255  //-----------------------------------------------------------------------------
256  Matrix4 operator-(T_Scalar d) const
257  {
258  Matrix4 t;
259  for(int i=0; i<4; ++i)
260  for(int j=0; j<4; ++j)
261  t.e(j,i) = e(j,i) - d;
262  return t;
263  }
264  //-----------------------------------------------------------------------------
265  Matrix4& operator-=(T_Scalar d)
266  {
267  for(int i=0; i<4; ++i)
268  for(int j=0; j<4; ++j)
269  e(j,i) -= d;
270  return *this;
271  }
272  //-----------------------------------------------------------------------------
273  Matrix4 operator*(T_Scalar d) const
274  {
275  Matrix4 t;
276  for(int i=0; i<4; ++i)
277  for(int j=0; j<4; ++j)
278  t.e(j,i) = e(j,i) * d;
279  return t;
280  }
281  //-----------------------------------------------------------------------------
282  Matrix4& operator*=(T_Scalar d)
283  {
284  for(int i=0; i<4; ++i)
285  for(int j=0; j<4; ++j)
286  e(j,i) *= d;
287  return *this;
288  }
289  //-----------------------------------------------------------------------------
290  Matrix4 operator/(T_Scalar d) const
291  {
292  d = (T_Scalar)1 / d;
293  Matrix4 t;
294  for(int i=0; i<4; ++i)
295  for(int j=0; j<4; ++j)
296  t.e(j,i) = e(j,i) * d;
297  return t;
298  }
299  //-----------------------------------------------------------------------------
300  Matrix4& operator/=(T_Scalar d)
301  {
302  d = (T_Scalar)1 / d;
303  for(int i=0; i<4; ++i)
304  for(int j=0; j<4; ++j)
305  e(j,i) *= d;
306  return *this;
307  }
308  //-----------------------------------------------------------------------------
309  bool isIdentity() const
310  {
311  Matrix4 i;
312  return memcmp(ptr(), i.ptr(), sizeof(T_Scalar)*16) == 0;
313  }
314  //-----------------------------------------------------------------------------
315  Matrix4 as3x3() const
316  {
317  Matrix4 t = *this;
318  t[0][3] = 0;
319  t[1][3] = 0;
320  t[2][3] = 0;
321  t[3][3] = 1;
322  t[3][0] = 0;
323  t[3][1] = 0;
324  t[3][2] = 0;
325  return t;
326  }
327  //-----------------------------------------------------------------------------
329  {
331  t.e(0,0) = e(0,0); t.e(1,0) = e(1,0); t.e(2,0) = e(2,0);
332  t.e(0,1) = e(0,1); t.e(1,1) = e(1,1); t.e(2,1) = e(2,1);
333  t.e(0,2) = e(0,2); t.e(1,2) = e(1,2); t.e(2,2) = e(2,2);
334  return t;
335  }
336  //-----------------------------------------------------------------------------
338  void set3x3(const Matrix3<T_Scalar>& m)
339  {
340  e(0,0) = m.e(0,0); e(1,0) = m.e(1,0); e(2,0) = m.e(2,0);
341  e(0,1) = m.e(0,1); e(1,1) = m.e(1,1); e(2,1) = m.e(2,1);
342  e(0,2) = m.e(0,2); e(1,2) = m.e(1,2); e(2,2) = m.e(2,2);
343  }
344  //-----------------------------------------------------------------------------
345  T_Scalar* ptr()
346  {
347  return &e(0,0);
348  }
349  //-----------------------------------------------------------------------------
350  const T_Scalar* ptr() const
351  {
352  return &e(0,0);
353  }
354  //-----------------------------------------------------------------------------
356  {
357  T_Scalar tmp;
358  for(int i=0; i<4; ++i)
359  for(int j=i; j<4; ++j)
360  {
361  tmp = e(j,i);
362  e(j,i) = e(i,j);
363  e(i,j) = tmp;
364  }
365  return *this;
366  }
367  //-----------------------------------------------------------------------------
369  {
370  Matrix4 m;
371  for(int i=0; i<4; ++i)
372  for(int j=0; j<4; ++j)
373  m.e(j,i) = e(i,j);
374  return m;
375  }
376  //-----------------------------------------------------------------------------
378  {
379  for(int i=0; i<4; ++i)
380  for(int j=0; j<4; ++j)
381  dest.e(j,i) = e(i,j);
382  return dest;
383  }
384  //-----------------------------------------------------------------------------
385  bool isNull() const
386  {
387  for(int i=0; i<4; ++i)
388  for(int j=0; j<4; ++j)
389  if(e(i,j) != 0)
390  return false;
391  return true;
392  }
393  //-----------------------------------------------------------------------------
395  {
396  fill(0);
397  return *this;
398  }
399  //-----------------------------------------------------------------------------
400  static Matrix4& getNull(Matrix4& out)
401  {
402  out.fill(0);
403  return out;
404  }
405  //-----------------------------------------------------------------------------
406  static Matrix4 getNull()
407  {
408  return Matrix4().fill(0);
409  }
410  //-----------------------------------------------------------------------------
412  {
413  static const T_Scalar I4d[] =
414  {
415  (T_Scalar)1, (T_Scalar)0, (T_Scalar)0, (T_Scalar)0,
416  (T_Scalar)0, (T_Scalar)1, (T_Scalar)0, (T_Scalar)0,
417  (T_Scalar)0, (T_Scalar)0, (T_Scalar)1, (T_Scalar)0,
418  (T_Scalar)0, (T_Scalar)0, (T_Scalar)0, (T_Scalar)1
419  };
420  memcpy(mVec, I4d, sizeof(T_Scalar)*16);
421  return *this;
422  }
423  //-----------------------------------------------------------------------------
425  {
426  return Matrix4();
427  }
428  //-----------------------------------------------------------------------------
430  {
431  out.setIdentity();
432  return out;
433  }
434  //-----------------------------------------------------------------------------
435  T_Scalar getInverse(Matrix4& dest) const;
436  //-----------------------------------------------------------------------------
437  Matrix4 getInverse(T_Scalar *determinant=NULL) const
438  {
439  Matrix4 tmp;
440  T_Scalar det = getInverse(tmp);
441  if (determinant)
442  *determinant = det;
443  return tmp;
444  }
445  //-----------------------------------------------------------------------------
446  Matrix4& invert(T_Scalar *determinant=NULL)
447  {
448  T_Scalar det = getInverse(*this);
449  if (determinant)
450  *determinant = det;
451  return *this;
452  }
453  //-----------------------------------------------------------------------------
454  static Matrix4 getPerspective(T_Scalar fovy, T_Scalar aspect_ratio, T_Scalar znear, T_Scalar zfar);
455  //-----------------------------------------------------------------------------
456  static Matrix4 getFrustum(T_Scalar pleft, T_Scalar pright, T_Scalar pbottom, T_Scalar ptop, T_Scalar pnear, T_Scalar pfar);
457  //-----------------------------------------------------------------------------
458  static Matrix4 getOrtho(T_Scalar pleft, T_Scalar pright, T_Scalar pbottom, T_Scalar ptop, T_Scalar pnear, T_Scalar pfar);
459  //-----------------------------------------------------------------------------
460  static Matrix4 getOrtho2D(T_Scalar pleft, T_Scalar pright, T_Scalar pbottom, T_Scalar ptop);
461  //-----------------------------------------------------------------------------
462  static Matrix4 getLookAtModeling(const Vector3<T_Scalar>& eye, const Vector3<T_Scalar>& at, const Vector3<T_Scalar>& up);
463  //-----------------------------------------------------------------------------
464  static Matrix4 getLookAt(const Vector3<T_Scalar>& eye, const Vector3<T_Scalar>& at, const Vector3<T_Scalar>& up);
465  //-----------------------------------------------------------------------------
467  //-----------------------------------------------------------------------------
469  //-----------------------------------------------------------------------------
470  void getYXRotationAngles(T_Scalar& degrees_y, T_Scalar& degrees_x) const;
471  //-----------------------------------------------------------------------------
472  static Matrix4& getRotation(Matrix4& out, T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z);
473  //-----------------------------------------------------------------------------
474  static Matrix4 getRotation(T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z)
475  {
476  Matrix4 m;
477  return getRotation(m, degrees, x, y, z);
478  }
479  //-----------------------------------------------------------------------------
480  static Matrix4 getRotation(T_Scalar degrees, const Vector3<T_Scalar>& v)
481  {
482  return getRotation(degrees, v.x(), v.y(), v.z());
483  }
484  //-----------------------------------------------------------------------------
485  static Matrix4 getRotation(T_Scalar degrees1, const Vector3<T_Scalar>& v1, T_Scalar degrees2, const Vector3<T_Scalar>& v2)
486  {
487  return getRotation(degrees1, v1.x(), v1.y(), v1.z()) * getRotation(degrees2, v2.x(), v2.y(), v2.z());
488  }
489  //-----------------------------------------------------------------------------
490  static Matrix4 getRotation(T_Scalar degrees1, const Vector3<T_Scalar>& v1, T_Scalar degrees2, const Vector3<T_Scalar>& v2, T_Scalar degrees3, const Vector3<T_Scalar>& v3)
491  {
492  return getRotation(degrees1, v1.x(), v1.y(), v1.z()) * getRotation(degrees2, v2.x(), v2.y(), v2.z()) * getRotation(degrees3, v3.x(), v3.y(), v3.z());
493  }
494  //-----------------------------------------------------------------------------
495  Matrix4& rotate(T_Scalar degrees, const Vector3<T_Scalar>& v)
496  {
497  return rotate(degrees, v.x(), v.y(), v.z());
498  }
499  //-----------------------------------------------------------------------------
500  Matrix4& rotate(T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z)
501  {
502  return preMultiply(getRotation(degrees, x, y, z));
503  }
504  //-----------------------------------------------------------------------------
505  Matrix4& rotate(T_Scalar degrees1, const Vector3<T_Scalar>& v1, T_Scalar degrees2, const Vector3<T_Scalar>& v2)
506  {
507  return preMultiply(getRotation(degrees1, v1, degrees2, v2));
508  }
509  //-----------------------------------------------------------------------------
510  Matrix4& rotate(T_Scalar degrees1, const Vector3<T_Scalar>& v1, T_Scalar degrees2, const Vector3<T_Scalar>& v2, T_Scalar degrees3, const Vector3<T_Scalar>& v3)
511  {
512  return preMultiply(getRotation(degrees1, v1, degrees2, v2, degrees3, v3));
513  }
514  //-----------------------------------------------------------------------------
515  static Matrix4 getRotationXYZ(T_Scalar degX, T_Scalar degY, T_Scalar degZ)
516  {
517  return getRotation(degX, 1,0,0) * getRotation(degY, 0,1,0) * getRotation(degZ, 0,0,1);
518  }
519  //-----------------------------------------------------------------------------
520  Matrix4& rotateXYZ(T_Scalar degX, T_Scalar degY, T_Scalar degZ)
521  {
522  return preMultiply(getRotationXYZ(degX, degY, degZ));
523  }
524  //-----------------------------------------------------------------------------
525  static Matrix4 getRotationZYX(T_Scalar degZ, T_Scalar degY, T_Scalar degX)
526  {
527  return getRotation(degZ, 0,0,1) * getRotation(degY, 0,1,0) * getRotation(degX, 1,0,0);
528  }
529  //-----------------------------------------------------------------------------
530  Matrix4& rotateZYX(T_Scalar degZ, T_Scalar degY, T_Scalar degX)
531  {
532  return preMultiply(getRotationZYX(degZ, degY, degX));
533  }
534  //-----------------------------------------------------------------------------
535  static Matrix4& getRotation(Matrix4& out, const Vector3<T_Scalar>& from, const Vector3<T_Scalar>& to);
536  //-----------------------------------------------------------------------------
538  {
539  Matrix4 m;
540  return getRotation(m, from, to);
541  }
542  //-----------------------------------------------------------------------------
544  {
545  return preMultiply(getRotation(from, to));
546  }
547  //-----------------------------------------------------------------------------
549  {
550  return preMultiply(getRotation(from, to));
551  }
552  //-----------------------------------------------------------------------------
554  {
555  return getTranslation(out, v.x(), v.y(), v.z());
556  }
557  //-----------------------------------------------------------------------------
559  {
560  Matrix4 m;
561  return getTranslation(m, v.x(), v.y(), v.z());
562  }
563  //-----------------------------------------------------------------------------
564  static Matrix4 getTranslation(T_Scalar x, T_Scalar y, T_Scalar z)
565  {
566  Matrix4 m;
567  return getTranslation(m, x, y, z);
568  }
569  //-----------------------------------------------------------------------------
570  static Matrix4& getTranslation(Matrix4& out, T_Scalar x, T_Scalar y, T_Scalar z)
571  {
572  out.setIdentity();
573  out.e(0,3) = x;
574  out.e(1,3) = y;
575  out.e(2,3) = z;
576  return out;
577  }
578  //-----------------------------------------------------------------------------
579  Matrix4& translate(T_Scalar x, T_Scalar y, T_Scalar z)
580  {
581  return preMultiply(getTranslation(x,y,z));
582  }
583  //-----------------------------------------------------------------------------
585  {
586  return preMultiply(getTranslation(v));
587  }
588  //-----------------------------------------------------------------------------
589  static Matrix4& getScaling(Matrix4& out, const Vector3<T_Scalar>& v)
590  {
591  return getScaling(out, v.x(), v.y(), v.z());
592  }
593  //-----------------------------------------------------------------------------
595  {
596  Matrix4 m;
597  return getScaling(m, v.x(), v.y(), v.z());
598  }
599  //-----------------------------------------------------------------------------
600  static Matrix4 getScaling(T_Scalar x, T_Scalar y, T_Scalar z)
601  {
602  Matrix4 m;
603  return getScaling(m, x, y, z);
604  }
605  //-----------------------------------------------------------------------------
606  static Matrix4& getScaling(Matrix4& out, T_Scalar x, T_Scalar y, T_Scalar z)
607  {
608  out.setIdentity();
609  out.e(0,0) = x;
610  out.e(1,1) = y;
611  out.e(2,2) = z;
612  return out;
613  }
614  //-----------------------------------------------------------------------------
615  Matrix4& scale(T_Scalar x, T_Scalar y, T_Scalar z)
616  {
617  return preMultiply(getScaling(x,y,z));
618  }
619  //-----------------------------------------------------------------------------
621  {
622  return preMultiply(getScaling(v.x(), v.y(), v.z()));
623  }
624  //-----------------------------------------------------------------------------
625  static Matrix4& multiply(Matrix4& out, const Matrix4& p, const Matrix4& q)
626  {
627  VL_CHECK(out.ptr() != p.ptr() && out.ptr() != q.ptr());
628 
629  out.e(0,0) = q.e(0,0)*p.e(0,0) + q.e(1,0)*p.e(0,1) + q.e(2,0)*p.e(0,2) + q.e(3,0)*p.e(0,3);
630  out.e(0,1) = q.e(0,1)*p.e(0,0) + q.e(1,1)*p.e(0,1) + q.e(2,1)*p.e(0,2) + q.e(3,1)*p.e(0,3);
631  out.e(0,2) = q.e(0,2)*p.e(0,0) + q.e(1,2)*p.e(0,1) + q.e(2,2)*p.e(0,2) + q.e(3,2)*p.e(0,3);
632  out.e(0,3) = q.e(0,3)*p.e(0,0) + q.e(1,3)*p.e(0,1) + q.e(2,3)*p.e(0,2) + q.e(3,3)*p.e(0,3);
633 
634  out.e(1,0) = q.e(0,0)*p.e(1,0) + q.e(1,0)*p.e(1,1) + q.e(2,0)*p.e(1,2) + q.e(3,0)*p.e(1,3);
635  out.e(1,1) = q.e(0,1)*p.e(1,0) + q.e(1,1)*p.e(1,1) + q.e(2,1)*p.e(1,2) + q.e(3,1)*p.e(1,3);
636  out.e(1,2) = q.e(0,2)*p.e(1,0) + q.e(1,2)*p.e(1,1) + q.e(2,2)*p.e(1,2) + q.e(3,2)*p.e(1,3);
637  out.e(1,3) = q.e(0,3)*p.e(1,0) + q.e(1,3)*p.e(1,1) + q.e(2,3)*p.e(1,2) + q.e(3,3)*p.e(1,3);
638 
639  out.e(2,0) = q.e(0,0)*p.e(2,0) + q.e(1,0)*p.e(2,1) + q.e(2,0)*p.e(2,2) + q.e(3,0)*p.e(2,3);
640  out.e(2,1) = q.e(0,1)*p.e(2,0) + q.e(1,1)*p.e(2,1) + q.e(2,1)*p.e(2,2) + q.e(3,1)*p.e(2,3);
641  out.e(2,2) = q.e(0,2)*p.e(2,0) + q.e(1,2)*p.e(2,1) + q.e(2,2)*p.e(2,2) + q.e(3,2)*p.e(2,3);
642  out.e(2,3) = q.e(0,3)*p.e(2,0) + q.e(1,3)*p.e(2,1) + q.e(2,3)*p.e(2,2) + q.e(3,3)*p.e(2,3);
643 
644  out.e(3,0) = q.e(0,0)*p.e(3,0) + q.e(1,0)*p.e(3,1) + q.e(2,0)*p.e(3,2) + q.e(3,0)*p.e(3,3);
645  out.e(3,1) = q.e(0,1)*p.e(3,0) + q.e(1,1)*p.e(3,1) + q.e(2,1)*p.e(3,2) + q.e(3,1)*p.e(3,3);
646  out.e(3,2) = q.e(0,2)*p.e(3,0) + q.e(1,2)*p.e(3,1) + q.e(2,2)*p.e(3,2) + q.e(3,2)*p.e(3,3);
647  out.e(3,3) = q.e(0,3)*p.e(3,0) + q.e(1,3)*p.e(3,1) + q.e(2,3)*p.e(3,2) + q.e(3,3)*p.e(3,3);
648 
649  return out;
650  }
651  //-----------------------------------------------------------------------------
653  {
655  return *this = multiply(t, *this, m);
656  }
657  //-----------------------------------------------------------------------------
659  {
661  return *this = multiply(t, m, *this);
662  }
663  //-----------------------------------------------------------------------------
664 
665  const T_Scalar& e(int i, int j) const { return mVec[j][i]; }
666  T_Scalar& e(int i, int j) { return mVec[j][i]; }
667 
668  private:
669  const Vector4<T_Scalar>& operator[](unsigned int i) const { VL_CHECK(i<4); return mVec[i]; }
670  Vector4<T_Scalar>& operator[](unsigned int i) { VL_CHECK(i<4); return mVec[i]; }
671 
672  protected:
674  };
675  //-----------------------------------------------------------------------------
676  // OPERATORS
677  //-----------------------------------------------------------------------------
678  template<typename T_Scalar>
680  {
683  return t;
684  }
685  //-----------------------------------------------------------------------------
686  template<typename T_Scalar>
687  inline Matrix4<T_Scalar> operator+(T_Scalar d, const Matrix4<T_Scalar>& m)
688  {
689  return m + d;
690  }
691  //-----------------------------------------------------------------------------
692  template<typename T_Scalar>
693  inline Matrix4<T_Scalar> operator*(T_Scalar d, const Matrix4<T_Scalar>& m)
694  {
695  return m * d;
696  }
697  //-----------------------------------------------------------------------------
699  template<typename T_Scalar>
701  {
702  return Vector4<T_Scalar>(
703  v.x()*m.e(0,0) + v.y()*m.e(0,1) + v.z()*m.e(0,2) + v.w()*m.e(0,3),
704  v.x()*m.e(1,0) + v.y()*m.e(1,1) + v.z()*m.e(1,2) + v.w()*m.e(1,3),
705  v.x()*m.e(2,0) + v.y()*m.e(2,1) + v.z()*m.e(2,2) + v.w()*m.e(2,3),
706  v.x()*m.e(3,0) + v.y()*m.e(3,1) + v.z()*m.e(3,2) + v.w()*m.e(3,3)
707  );
708  }
709  //-----------------------------------------------------------------------------
712  template<typename T_Scalar>
714  {
715  return Vector3<T_Scalar>(
716  v.x()*m.e(0,0) + v.y()*m.e(0,1) + v.z()*m.e(0,2) + /*1**/m.e(0,3),
717  v.x()*m.e(1,0) + v.y()*m.e(1,1) + v.z()*m.e(1,2) + /*1**/m.e(1,3),
718  v.x()*m.e(2,0) + v.y()*m.e(2,1) + v.z()*m.e(2,2) + /*1**/m.e(2,3)
719  );
720  }
721  //-----------------------------------------------------------------------------
724  template<typename T_Scalar>
726  {
727  return Vector2<T_Scalar>(
728  v.x()*m.e(0,0) + v.y()*m.e(0,1) + /*0*m.e(0,2) +*/ /*1**/m.e(0,3),
729  v.x()*m.e(1,0) + v.y()*m.e(1,1) + /*0*m.e(1,2) +*/ /*1**/m.e(1,3)
730  );
731  }
732  //-----------------------------------------------------------------------------
734  template<typename T_Scalar>
736  {
737  return Vector4<T_Scalar>(
738  v.x()*m.e(0,0) + v.y()*m.e(1,0) + v.z()*m.e(2,0) + v.w()*m.e(3,0),
739  v.x()*m.e(0,1) + v.y()*m.e(1,1) + v.z()*m.e(2,1) + v.w()*m.e(3,1),
740  v.x()*m.e(0,2) + v.y()*m.e(1,2) + v.z()*m.e(2,2) + v.w()*m.e(3,2),
741  v.x()*m.e(0,3) + v.y()*m.e(1,3) + v.z()*m.e(2,3) + v.w()*m.e(3,3)
742  );
743  }
744  //-----------------------------------------------------------------------------
747  template<typename T_Scalar>
749  {
750  return Vector3<T_Scalar>(
751  v.x()*m.e(0,0) + v.y()*m.e(1,0) + v.z()*m.e(2,0) + /*1**/m.e(3,0),
752  v.x()*m.e(0,1) + v.y()*m.e(1,1) + v.z()*m.e(2,1) + /*1**/m.e(3,1),
753  v.x()*m.e(0,2) + v.y()*m.e(1,2) + v.z()*m.e(2,2) + /*1**/m.e(3,2)
754  );
755  }
756  //-----------------------------------------------------------------------------
759  template<typename T_Scalar>
761  {
762  return Vector2<T_Scalar>(
763  v.x()*m.e(0,0) + v.y()*m.e(1,0) + /*0*m.e(2,0) +*/ /*1**/m.e(3,0),
764  v.x()*m.e(0,1) + v.y()*m.e(1,1) + /*0*m.e(2,1) +*/ /*1**/m.e(3,1)
765  );
766  }
767  //-----------------------------------------------------------------------------
768  template<typename T_Scalar>
770  {
771  Vector3<T_Scalar> zaxis = (eye-at).normalize();
772  Vector3<T_Scalar> xaxis = cross(up, zaxis).normalize();
773  Vector3<T_Scalar> yaxis = cross(zaxis, xaxis);
774 
775  // look at modeling
776  T_Scalar la_modeling[] =
777  {
778  xaxis.x() , xaxis.y() , xaxis.z() , 0,
779  yaxis.x() , yaxis.y() , yaxis.z() , 0,
780  zaxis.x() , zaxis.y() , zaxis.z() , 0,
781  eye.x() , eye.y() , eye.z() , 1
782  };
783 
784  return Matrix4<T_Scalar>(la_modeling);
785  }
786  //-----------------------------------------------------------------------------
787  template<typename T_Scalar>
789  {
790  Vector3<T_Scalar> zaxis = (eye-at).normalize();
791  Vector3<T_Scalar> xaxis = cross(up, zaxis).normalize();
792  Vector3<T_Scalar> yaxis = cross(zaxis, xaxis);
793 
794  // look at view
795  T_Scalar la_view[] =
796  {
797  xaxis.x() , yaxis.x() , zaxis.x() , 0,
798  xaxis.y() , yaxis.y() , zaxis.y() , 0,
799  xaxis.z() , yaxis.z() , zaxis.z() , 0,
800  -dot(xaxis,eye), -dot(yaxis,eye), -dot(zaxis,eye), 1
801  };
802 
803  return Matrix4<T_Scalar>(la_view);
804  }
805  //-----------------------------------------------------------------------------
806  template<typename T_Scalar>
808  {
809  eye = getT();
810 
811  at = -getZ();
812  // look.normalize();
813 
814  up = getY();
815  // up.normalize();
816 
817  right = getX();
818  // right.normalize();
819  }
820  //-----------------------------------------------------------------------------
821  template<typename T_Scalar>
823  {
824  Matrix4<T_Scalar> m = *this;
825  m.invert();
826  m.getAsLookAtModeling(eye, at, up, right);
827  }
828  //-----------------------------------------------------------------------------
829  template<typename T_Scalar>
830  Matrix4<T_Scalar> Matrix4<T_Scalar>::getPerspective(T_Scalar fovy, T_Scalar aspect_ratio, T_Scalar znear, T_Scalar zfar)
831  {
833 
834  T_Scalar rads = (fovy / ((T_Scalar)2)) * (T_Scalar)dDEG_TO_RAD;
835  T_Scalar dz = zfar - znear;
836  T_Scalar sa = sin(rads);
837  if ((dz == 0) || (sa == 0) || (aspect_ratio == 0))
838  return m * 0;
839  T_Scalar ctan = cos(rads) / sa;
840 
841  m.e(0,0) = (T_Scalar)(ctan / aspect_ratio);
842  m.e(1,1) = (T_Scalar)(ctan);
843  m.e(2,2) = (T_Scalar)(-(zfar + znear) / dz);
844  m.e(3,2) = -((T_Scalar)1);
845  m.e(2,3) = (T_Scalar)(-((T_Scalar)2) * znear * zfar / dz);
846  m.e(3,3) = 0;
847 
848  return m;
849  }
850  //-----------------------------------------------------------------------------
851  template<typename T_Scalar>
852  Matrix4<T_Scalar> Matrix4<T_Scalar>::getFrustum(T_Scalar left, T_Scalar right, T_Scalar bottom, T_Scalar top, T_Scalar pnear, T_Scalar pfar)
853  {
855 
856  if (pnear <= 0 || pfar <= 0 || pnear == pfar || left == right || top == bottom)
857  return m * 0;
858 
859  T_Scalar x = (((T_Scalar)2)*pnear) / (right-left);
860  T_Scalar y = (((T_Scalar)2)*pnear) / (top-bottom);
861  T_Scalar a = (right+left) / (right-left);
862  T_Scalar b = (top+bottom) / (top-bottom);
863  T_Scalar c = -(pfar+pnear) / (pfar-pnear);
864  T_Scalar d = -(((T_Scalar)2)*pfar*pnear) / (pfar-pnear);
865 
866  m.e(0,0) = x; m.e(0,1) = 0; m.e(0,2) = a; m.e(0,3) = 0;
867  m.e(1,0) = 0; m.e(1,1) = y; m.e(1,2) = b; m.e(1,3) = 0;
868  m.e(2,0) = 0; m.e(2,1) = 0; m.e(2,2) = c; m.e(2,3) = d;
869  m.e(3,0) = 0; m.e(3,1) = 0; m.e(3,2) = -((T_Scalar)1); m.e(3,3) = 0;
870 
871  return m;
872  }
873  //-----------------------------------------------------------------------------
874  template<typename T_Scalar>
875  Matrix4<T_Scalar> Matrix4<T_Scalar>::getOrtho(T_Scalar left, T_Scalar right, T_Scalar bottom, T_Scalar top, T_Scalar pnear, T_Scalar pfar)
876  {
878 
879  m.e(0,0) = ((T_Scalar)2) / (right-left);
880  m.e(0,1) = 0;
881  m.e(0,2) = 0;
882  m.e(0,3) = -(right+left) / (right-left);
883 
884  m.e(1,0) = 0;
885  m.e(1,1) = ((T_Scalar)2) / (top-bottom);
886  m.e(1,2) = 0;
887  m.e(1,3) = -(top+bottom) / (top-bottom);
888 
889  m.e(2,0) = 0;
890  m.e(2,1) = 0;
891  m.e(2,2) = -((T_Scalar)2) / (pfar-pnear);
892  m.e(2,3) = -(pfar+pnear) / (pfar-pnear);
893 
894  m.e(3,0) = 0;
895  m.e(3,1) = 0;
896  m.e(3,2) = 0;
897  m.e(3,3) = ((T_Scalar)1);
898 
899  return m;
900  }
901  //-----------------------------------------------------------------------------
902  template<typename T_Scalar>
903  Matrix4<T_Scalar> Matrix4<T_Scalar>::getOrtho2D(T_Scalar left, T_Scalar right, T_Scalar bottom, T_Scalar top)
904  {
905  return getOrtho(left, right, bottom, top, -1, +1);
906  }
907  //-----------------------------------------------------------------------------
908  template<typename T_Scalar>
909  Matrix4<T_Scalar>& Matrix4<T_Scalar>::getRotation(Matrix4<T_Scalar>& out, T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z)
910  {
911  out.setIdentity();
912 
913  if (degrees == 0 || (x == 0 && y ==0 && z == 0))
914  return out;
915 
916  degrees = T_Scalar(degrees * dDEG_TO_RAD);
917 
918  T_Scalar xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
919 
920  s = (T_Scalar) sin(degrees);
921  c = (T_Scalar) cos(degrees);
922 
923  // simple cases
924  if (x == 0)
925  {
926  if (y == 0)
927  {
928  if (z != 0)
929  {
930  // rotate only around z-axis
931  out.e(0,0) = (T_Scalar)c;
932  out.e(1,1) = (T_Scalar)c;
933  if (z < 0)
934  {
935  out.e(1,0) = -(T_Scalar)s;
936  out.e(0,1) = (T_Scalar)s;
937  }
938  else
939  {
940  out.e(1,0) = (T_Scalar)s;
941  out.e(0,1) = -(T_Scalar)s;
942  }
943  return out;
944  }
945  }
946  else if (z == 0)
947  {
948  // rotate only around y-axis
949  out.e(0,0) = (T_Scalar)c;
950  out.e(2,2) = (T_Scalar)c;
951  if (y < 0)
952  {
953  out.e(2,0) = (T_Scalar)s;
954  out.e(0,2) = -(T_Scalar)s;
955  }
956  else
957  {
958  out.e(2,0) = -(T_Scalar)s;
959  out.e(0,2) = (T_Scalar)s;
960  }
961  return out;
962  }
963  }
964  else if (y == 0)
965  {
966  if (z == 0)
967  {
968  // rotate only around x-axis
969  out.e(1,1) = (T_Scalar)c;
970  out.e(2,2) = (T_Scalar)c;
971  if (x < 0)
972  {
973  out.e(2,1) = -(T_Scalar)s;
974  out.e(1,2) = (T_Scalar)s;
975  }
976  else
977  {
978  out.e(2,1) = (T_Scalar)s;
979  out.e(1,2) = -(T_Scalar)s;
980  }
981  return out;
982  }
983  }
984 
985  // Beginning of general axisa to matrix conversion
986  T_Scalar dot = x*x + y*y + z*z;
987 
988  if (dot > (T_Scalar)((T_Scalar)1.0001) || dot < (T_Scalar)0.99999)
989  {
990  T_Scalar mag = (T_Scalar) sqrt(dot);
991  x /= mag;
992  y /= mag;
993  z /= mag;
994  }
995 
996  xx = x *x;
997  yy = y * y;
998  zz = z * z;
999  xy = x * y;
1000  yz = y * z;
1001  zx = z * x;
1002  xs = x * s;
1003  ys = y * s;
1004  zs = z * s;
1005  one_c = ((T_Scalar)1) - c;
1006 
1007  out.e(0,0) = (T_Scalar)((one_c * xx) + c); out.e(1,0) = (T_Scalar)((one_c * xy) + zs); out.e(2,0) = (T_Scalar)((one_c * zx) - ys);
1008  out.e(0,1) = (T_Scalar)((one_c * xy) - zs); out.e(1,1) = (T_Scalar)((one_c * yy) + c); out.e(2,1) = (T_Scalar)((one_c * yz) + xs);
1009  out.e(0,2) = (T_Scalar)((one_c * zx) + ys); out.e(1,2) = (T_Scalar)((one_c * yz) - xs); out.e(2,2) = (T_Scalar)((one_c * zz) + c);
1010  return out;
1011  }
1012  //-----------------------------------------------------------------------------
1013  template<typename T_Scalar>
1015  {
1016  const T_Scalar* in = ptr();
1017  T_Scalar* out = dest.ptr();
1018 
1019  // | 0 | 4 | 8 | 12 |
1020  // | 1 | 5 | 9 | 13 |
1021  // | 2 | 6 | 10 | 14 |
1022  // | 3 | 7 | 11 | 15 |
1023 
1024  // | a | b | c | d |
1025  // | e | f | g | h |
1026  // | i | l | m | n |
1027  // | o | p | q | r |
1028 
1029  const T_Scalar a = in[0]; const T_Scalar b = in[4]; const T_Scalar c = in[ 8]; const T_Scalar d = in[12];
1030  const T_Scalar e = in[1]; const T_Scalar f = in[5]; const T_Scalar g = in[ 9]; const T_Scalar h = in[13];
1031  const T_Scalar i = in[2]; const T_Scalar l = in[6]; const T_Scalar m = in[10]; const T_Scalar n = in[14];
1032  const T_Scalar o = in[3]; const T_Scalar p = in[7]; const T_Scalar q = in[11]; const T_Scalar r = in[15];
1033 
1034  // 3x3 determinant:
1035  //
1036  // [ a b c ]
1037  // [ d e f ] = aei - ahf + dhc - dbi + gbf - gec = (aei + dhc + gbf) - (ahf + dbi + gec)
1038  // [ g h i ]
1039 
1040  const T_Scalar mr = m*r;
1041  const T_Scalar gn = g*n;
1042  const T_Scalar el = e*l;
1043  const T_Scalar ip = i*p;
1044  const T_Scalar mo = m*o;
1045  const T_Scalar hl = h*l;
1046  const T_Scalar mp = m*p;
1047  const T_Scalar nq = n*q;
1048  const T_Scalar gl = g*l;
1049  const T_Scalar no = n*o;
1050  const T_Scalar gi = g*i;
1051  const T_Scalar np = n*p;
1052  const T_Scalar fi = f*i;
1053  const T_Scalar rc = r*c;
1054  const T_Scalar be = b*e;
1055  const T_Scalar af = a*f;
1056  const T_Scalar de = d*e;
1057  const T_Scalar df = d*f;
1058  const T_Scalar ch = c*h;
1059  const T_Scalar qh = q*h;
1060 
1061  // | f | g | h |
1062  // | l | m | n |
1063  // | p | q | r |
1064  T_Scalar Ca = +(( f*mr + gn*p + hl*q ) - ( h*mp + nq*f + r*gl ));
1065 
1066  // | e | g | h |
1067  // | i | m | n |
1068  // | o | q | r |
1069  T_Scalar Cb = -(( e*mr + gn*o + i*qh ) - ( h*mo + gi*r + nq*e ));
1070 
1071  // | e | f | h |
1072  // | i | l | n |
1073  // | o | p | r |
1074  T_Scalar Cc = +(( el*r + ip*h + f*no ) - ( hl*o + np*e + fi*r ));
1075 
1076  // | e | f | g |
1077  // | i | l | m |
1078  // | o | p | q |
1079  T_Scalar Cd = -(( el*q + f*mo + g*ip ) - ( gl*o + mp*e + q*fi ));
1080 
1081  T_Scalar det = a*Ca + b*Cb + c*Cc + d*Cd;
1082 
1083  // singular matrix
1084  if (det == 0)
1085  return det;
1086 
1087  // | b | c | d |
1088  // | l | m | n |
1089  // | p | q | r |
1090  T_Scalar Ce = -(( b*mr + c*np + d*l*q ) - ( d*mp + nq*b + rc*l ));
1091 
1092  // | a | c | d |
1093  // | i | m | n |
1094  // | o | q | r |
1095  T_Scalar Cf = +(( a*mr + c*no + d*i*q ) - ( d*mo + nq*a + rc*i ));
1096 
1097  // | a | b | d |
1098  // | i | l | n |
1099  // | o | p | r |
1100  T_Scalar Cg = -(( a*l*r + b*no + d*ip ) - ( d*l*o + np*a + r*b*i ));
1101 
1102  // | a | b | c |
1103  // | i | l | m |
1104  // | o | p | q |
1105  T_Scalar Ch = +(( a*l*q + b*mo + c*ip ) - ( c*l*o + mp*a + q*b*i ));
1106 
1107 
1108  // | b | c | d |
1109  // | f | g | h |
1110  // | p | q | r |
1111  T_Scalar Ci = +(( b*g*r + ch*p + df*q ) - ( d*g*p + q*h*b + rc*f ));
1112 
1113  // | a | c | d |
1114  // | e | g | h |
1115  // | o | q | r |
1116  T_Scalar Cl = -(( a*g*r + ch*o + de*q ) - ( d*g*o + qh*a + rc*e ));
1117 
1118  // | a | b | d |
1119  // | e | f | h |
1120  // | o | p | r |
1121  T_Scalar Cm = +(( af*r + b*h*o + de*p ) - ( df*o + h*p*a + r*be ));
1122 
1123  // | a | b | c |
1124  // | e | f | g |
1125  // | o | p | q |
1126  T_Scalar Cn = -(( af*q + b*g*o + c*e*p ) - ( c*f*o + g*p*a + q*be ));
1127 
1128 
1129  // | b | c | d |
1130  // | f | g | h |
1131  // | l | m | n |
1132  T_Scalar Co = -(( b*gn + c*hl + df*m ) - ( d*gl + h*m*b + n*c*f ));
1133 
1134  // | a | c | d |
1135  // | e | g | h |
1136  // | i | m | n |
1137  T_Scalar Cp = +(( a*gn + ch*i + de*m ) - ( d*gi + h*m*a + n*c*e ));
1138 
1139  // | a | b | d |
1140  // | e | f | h |
1141  // | i | l | n |
1142  T_Scalar Cq = -(( af*n + b*h*i + d*el ) - ( d*fi + hl*a + n*be ));
1143 
1144  // | a | b | c |
1145  // | e | f | g |
1146  // | i | l | m |
1147  T_Scalar Cr = +(( af*m + b*gi + c*el ) - ( c*fi + gl*a + m*be ));
1148 
1149 #if 0
1150  T_Scalar det2 = e*Ce + f*Cf + g*Cg + h*Ch;
1151  T_Scalar det3 = i*Ci + l*Cl + m*Cm + n*Cn;
1152  T_Scalar det4 = o*Co + p*Cp + q*Cq + r*Cr;
1153  VL_CHECK( fabs(det - det1) < 0.0001 );
1154  VL_CHECK( fabs(det - det3) < 0.0001 );
1155  VL_CHECK( fabs(det - det4) < 0.0001 );
1156 #endif
1157 
1158  T_Scalar inv_det = 1 / det;
1159 
1160  out[0] = inv_det * Ca;
1161  out[1] = inv_det * Cb;
1162  out[2] = inv_det * Cc;
1163  out[3] = inv_det * Cd;
1164  out[4] = inv_det * Ce;
1165  out[5] = inv_det * Cf;
1166  out[6] = inv_det * Cg;
1167  out[7] = inv_det * Ch;
1168  out[8] = inv_det * Ci;
1169  out[9] = inv_det * Cl;
1170  out[10] = inv_det * Cm;
1171  out[11] = inv_det * Cn;
1172  out[12] = inv_det * Co;
1173  out[13] = inv_det * Cp;
1174  out[14] = inv_det * Cq;
1175  out[15] = inv_det * Cr;
1176 
1177  return det;
1178  }
1179  //-----------------------------------------------------------------------------
1180  template<typename T_Scalar>
1182  {
1183  Vector3<T_Scalar> a,b;
1184  a = from;
1185  b = to;
1186  a.normalize();
1187  b.normalize();
1188  T_Scalar cosa = dot(a,b);
1189  cosa = clamp(cosa,-((T_Scalar)1),+((T_Scalar)1));
1190  Vector3<T_Scalar> axis,n2;
1191  axis = cross(a,b);
1192  axis.normalize();
1193  T_Scalar alpha = acos(cosa);
1194  return getRotation(out, alpha*(T_Scalar)dRAD_TO_DEG, axis.x(), axis.y(), axis.z());
1195  }
1196  //-----------------------------------------------------------------------------
1203  template<typename T_Scalar>
1204  void Matrix4<T_Scalar>::getYXRotationAngles(T_Scalar& degrees_y, T_Scalar& degrees_x) const
1205  {
1206  Vector3<T_Scalar> vx = getX();
1207  Vector3<T_Scalar> vy = getY();
1208  Vector3<T_Scalar> vz = getZ();
1209 
1210  vx.normalize();
1211  vy.normalize();
1212  vz.normalize();
1213 
1214  T_Scalar kx = dot(vy,Vector3<T_Scalar>(0,1,0));
1215  kx = clamp(kx,-((T_Scalar)1),+((T_Scalar)1));
1216  degrees_x = acos(kx) * (T_Scalar)dRAD_TO_DEG;
1217  if(dot(vz, Vector3<T_Scalar>(0,1,0)) > 0)
1218  degrees_x = -degrees_x;
1219 
1220  T_Scalar ky = dot(vx, Vector3<T_Scalar>(1,0,0));
1221  ky = clamp(ky,-((T_Scalar)1),+((T_Scalar)1));
1222  degrees_y = acos(ky) * (T_Scalar)dRAD_TO_DEG;
1223  if(dot(vz, Vector3<T_Scalar>(1,0,0)) < 0)
1224  degrees_y = -degrees_y;
1225  if (fabs(degrees_x) > (T_Scalar)90)
1226  degrees_y = -degrees_y;
1227  }
1228 
1229  //-----------------------------------------------------------------------------
1230 
1239 
1240  #if VL_PIPELINE_PRECISION == 2
1241  typedef dmat4 mat4;
1243  #else
1244  typedef fmat4 mat4;
1246  #endif
1247 }
1248 
1249 #endif
const T_Scalar & z() const
Definition: Vector4.hpp:104
float clamp(float x, float minval, float maxval)
Definition: Vector2.hpp:316
Matrix4 & operator-=(const Matrix4 &m)
Definition: Matrix4.hpp:217
const Vector3 & normalize(T_Scalar *len=NULL)
Definition: Vector3.hpp:228
Matrix4 & getTransposed(Matrix4 &dest) const
Definition: Matrix4.hpp:377
Matrix4 & rotate(T_Scalar degrees, const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:495
const T_Scalar & e(int i, int j) const
Definition: Matrix4.hpp:665
const T_Scalar & x() const
Definition: Vector4.hpp:102
Matrix4 getTransposed() const
Definition: Matrix4.hpp:368
T sqrt(T a)
Definition: glsl_math.hpp:592
Matrix4< unsigned int > umat4
A 4x4 matrix using unsigned int precision.
Definition: Matrix4.hpp:1238
Vector3< T_Scalar > getZ() const
Definition: Matrix4.hpp:131
static Matrix4 & getTranslation(Matrix4 &out, T_Scalar x, T_Scalar y, T_Scalar z)
Definition: Matrix4.hpp:570
Matrix4 & rotateZYX(T_Scalar degZ, T_Scalar degY, T_Scalar degX)
Definition: Matrix4.hpp:530
Matrix4(T_Scalar e00, T_Scalar e01, T_Scalar e02, T_Scalar e03, T_Scalar e10, T_Scalar e11, T_Scalar e12, T_Scalar e13, T_Scalar e20, T_Scalar e21, T_Scalar e22, T_Scalar e23, T_Scalar e30, T_Scalar e31, T_Scalar e32, T_Scalar e33)
Definition: Matrix4.hpp:83
static Matrix4 getRotation(T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z)
Definition: Matrix4.hpp:474
Matrix4 & setT(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:165
Matrix4 & setX(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:141
static Matrix4 getPerspective(T_Scalar fovy, T_Scalar aspect_ratio, T_Scalar znear, T_Scalar zfar)
Definition: Matrix4.hpp:830
Matrix4 & rotate(const Vector4< T_Scalar > &from, const Vector4< T_Scalar > &to)
Definition: Matrix4.hpp:543
Matrix4< double > dmat4
A 4x4 matrix using double precision.
Definition: Matrix4.hpp:1232
Matrix4 & transpose()
Definition: Matrix4.hpp:355
T sin(T a)
Definition: glsl_math.hpp:199
T degrees(T radians)
Definition: glsl_math.hpp:173
const T_Scalar & z() const
Definition: Vector3.hpp:92
Matrix4 & translate(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:584
Matrix4(const Matrix4< T > &m)
Definition: Matrix4.hpp:54
Matrix4 & translate(T_Scalar x, T_Scalar y, T_Scalar z)
Definition: Matrix4.hpp:579
Matrix4(T_Scalar *val)
Definition: Matrix4.hpp:78
bool isNull() const
Definition: Matrix4.hpp:385
T_Scalar scalar_type
Definition: Matrix4.hpp:51
Matrix4 & scale(const Vector3< T_Scalar > v)
Definition: Matrix4.hpp:620
Matrix4 operator-() const
Definition: Matrix4.hpp:230
Vector3< T_Scalar > getY() const
Definition: Matrix4.hpp:126
static Matrix4 getTranslation(T_Scalar x, T_Scalar y, T_Scalar z)
Definition: Matrix4.hpp:564
const T_Scalar & e(int i, int j) const
Definition: Matrix3.hpp:524
static Matrix4 getOrtho(T_Scalar pleft, T_Scalar pright, T_Scalar pbottom, T_Scalar ptop, T_Scalar pnear, T_Scalar pfar)
Definition: Matrix4.hpp:875
Matrix4(const Matrix4 &other)
Definition: Matrix4.hpp:62
const double dRAD_TO_DEG
Constant to convert radian into degree using double precision.
Definition: std_types.hpp:68
The Vector4 class is a template class that implements a generic 4 components vector, see also vl::fvec4, vl::dvec4, vl::uvec4, vl::ivec4, vl::svec4, vl::usvec4, vl::bvec4, vl::ubvec4.
Definition: Vector4.hpp:44
Matrix4 & postMultiply(const Matrix4 &m)
Definition: Matrix4.hpp:652
Matrix4 & invert(T_Scalar *determinant=NULL)
Definition: Matrix4.hpp:446
fvec3 cross(const fvec3 &v1, const fvec3 &v2)
Definition: Vector3.hpp:278
static Matrix4 getIdentity()
Definition: Matrix4.hpp:424
Matrix4 & operator+=(T_Scalar d)
Definition: Matrix4.hpp:248
Matrix4< int > imat4
A 4x4 matrix using int precision.
Definition: Matrix4.hpp:1236
Matrix4 getInverse(T_Scalar *determinant=NULL) const
Definition: Matrix4.hpp:437
Visualization Library main namespace.
Vector3< T_Scalar > getX() const
Definition: Matrix4.hpp:121
Matrix4 operator/(T_Scalar d) const
Definition: Matrix4.hpp:290
float dot(float a, float b)
Definition: glsl_math.hpp:1111
const double dDEG_TO_RAD
Constant to convert degree into radian using double precision.
Definition: std_types.hpp:66
static Matrix4 getTranslation(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:558
Matrix4(T_Scalar n)
Definition: Matrix4.hpp:72
The Matrix3 class is a template class that implements a generic 3x3 matrix, see also vl::dmat3...
Definition: Matrix3.hpp:48
T_Scalar getInverse(Matrix4 &dest) const
Definition: Matrix4.hpp:1014
Matrix3< T_Scalar > get3x3() const
Definition: Matrix4.hpp:328
Matrix4 operator*(T_Scalar d) const
Definition: Matrix4.hpp:273
static Matrix4 & getIdentity(Matrix4 &out)
Definition: Matrix4.hpp:429
Matrix4 & setZ(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:157
The Vector3 class is a template class that implements a generic 3 components vector, see also vl::fvec3, vl::dvec3, vl::uvec3, vl::ivec3, vl::svec3, vl::usvec3, vl::bvec3, vl::ubvec3.
Definition: Vector3.hpp:44
Matrix4 & operator=(const Matrix4 &m)
Definition: Matrix4.hpp:183
Matrix4 operator-(T_Scalar d) const
Definition: Matrix4.hpp:256
static Matrix4 getLookAtModeling(const Vector3< T_Scalar > &eye, const Vector3< T_Scalar > &at, const Vector3< T_Scalar > &up)
Definition: Matrix4.hpp:769
static Matrix4 getRotation(T_Scalar degrees1, const Vector3< T_Scalar > &v1, T_Scalar degrees2, const Vector3< T_Scalar > &v2, T_Scalar degrees3, const Vector3< T_Scalar > &v3)
Definition: Matrix4.hpp:490
Matrix4 & operator+=(const Matrix4 &m)
Definition: Matrix4.hpp:199
void set3x3(const Matrix3< T_Scalar > &m)
This writes only on the upper 3x3 part of the matrix without touching the last row and column...
Definition: Matrix4.hpp:338
static Matrix4 getRotation(T_Scalar degrees, const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:480
Matrix4 & fill(T_Scalar val)
Definition: Matrix4.hpp:94
static Matrix4 getRotationXYZ(T_Scalar degX, T_Scalar degY, T_Scalar degZ)
Definition: Matrix4.hpp:515
const T_Scalar & y() const
Definition: Vector3.hpp:91
Matrix4 operator+(const Matrix4 &m) const
Definition: Matrix4.hpp:189
static Matrix4 getNull()
Definition: Matrix4.hpp:406
Matrix4 & rotate(T_Scalar degrees1, const Vector3< T_Scalar > &v1, T_Scalar degrees2, const Vector3< T_Scalar > &v2)
Definition: Matrix4.hpp:505
const T_Scalar & y() const
Definition: Vector4.hpp:103
static Matrix4 & multiply(Matrix4 &out, const Matrix4 &p, const Matrix4 &q)
Definition: Matrix4.hpp:625
Matrix4 operator-(const Matrix4 &m) const
Definition: Matrix4.hpp:207
Matrix4 & operator/=(T_Scalar d)
Definition: Matrix4.hpp:300
Matrix4 & scale(T_Scalar x, T_Scalar y, T_Scalar z)
Definition: Matrix4.hpp:615
bool isIdentity() const
Definition: Matrix4.hpp:309
The Matrix4 class is a template class that implements a generic 4x4 matrix, see also vl::dmat4...
Definition: Matrix4.hpp:48
Matrix4 & fillPtr(T_Scalar *val)
Definition: Matrix4.hpp:103
#define NULL
Definition: OpenGLDefs.hpp:81
const T_Scalar * ptr() const
Definition: Matrix4.hpp:350
Matrix4 & setY(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:149
Vector4< T_Scalar > mVec[4]
Definition: Matrix4.hpp:673
void getYXRotationAngles(T_Scalar &degrees_y, T_Scalar &degrees_x) const
If this matrix can be represented as RY(degrees_y) * RX(degrees_x), where RX and RY are getRotation m...
Definition: Matrix4.hpp:1204
static Matrix4 & getNull(Matrix4 &out)
Definition: Matrix4.hpp:400
static Matrix4 & getRotation(Matrix4 &out, T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z)
Definition: Matrix4.hpp:909
Matrix4 & rotate(T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z)
Definition: Matrix4.hpp:500
The Vector2 class is a template class that implements a generic 2 components vector, see also vl::fvec2, vl::dvec2, vl::uvec2, vl::ivec2, vl::svec2, vl::usvec2, vl::bvec2, vl::ubvec2.
Definition: Vector2.hpp:97
Vector3< T_Scalar > getT() const
Definition: Matrix4.hpp:136
static Matrix4 getFrustum(T_Scalar pleft, T_Scalar pright, T_Scalar pbottom, T_Scalar ptop, T_Scalar pnear, T_Scalar pfar)
Definition: Matrix4.hpp:852
fmat4 mat4
Defined as: &#39;typedef fmat4 mat4&#39;. See also VL_PIPELINE_PRECISION.
Definition: Matrix4.hpp:1245
Matrix4 & setIdentity()
Definition: Matrix4.hpp:411
T_Scalar diff(const Matrix4 &other) const
Definition: Matrix4.hpp:109
Matrix4 & rotate(const Vector3< T_Scalar > &from, const Vector3< T_Scalar > &to)
Definition: Matrix4.hpp:548
void getAsLookAtModeling(Vector3< T_Scalar > &eye, Vector3< T_Scalar > &at, Vector3< T_Scalar > &up, Vector3< T_Scalar > &right) const
Definition: Matrix4.hpp:807
static Matrix4 & getTranslation(Matrix4 &out, const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:553
T_Scalar * ptr()
Definition: Matrix4.hpp:345
static Matrix4 getScaling(T_Scalar x, T_Scalar y, T_Scalar z)
Definition: Matrix4.hpp:600
static Matrix4 & getScaling(Matrix4 &out, T_Scalar x, T_Scalar y, T_Scalar z)
Definition: Matrix4.hpp:606
Matrix4 & operator-=(T_Scalar d)
Definition: Matrix4.hpp:265
static Matrix4 getScaling(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:594
static Matrix4 getOrtho2D(T_Scalar pleft, T_Scalar pright, T_Scalar pbottom, T_Scalar ptop)
Definition: Matrix4.hpp:903
Matrix4 & preMultiply(const Matrix4 &m)
Definition: Matrix4.hpp:658
T cos(T a)
Definition: glsl_math.hpp:225
Matrix4 & setNull()
Definition: Matrix4.hpp:394
Matrix4 & operator*=(T_Scalar d)
Definition: Matrix4.hpp:282
static Matrix4 & getScaling(Matrix4 &out, const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:589
const T_Scalar & x() const
Definition: Vector3.hpp:90
const T_Scalar & x() const
Definition: Vector2.hpp:133
Matrix4 & rotateXYZ(T_Scalar degX, T_Scalar degY, T_Scalar degZ)
Definition: Matrix4.hpp:520
Matrix4< float > fmat4
A 4x4 matrix using float precision.
Definition: Matrix4.hpp:1234
Matrix4 & operator*=(const Matrix4 &m)
Definition: Matrix4.hpp:225
T acos(T a)
Definition: glsl_math.hpp:329
static Matrix4 getRotation(const Vector3< T_Scalar > &from, const Vector3< T_Scalar > &to)
Definition: Matrix4.hpp:537
void getAsLookAt(Vector3< T_Scalar > &eye, Vector3< T_Scalar > &at, Vector3< T_Scalar > &up, Vector3< T_Scalar > &right) const
Definition: Matrix4.hpp:822
Matrix4 operator+(T_Scalar d) const
Definition: Matrix4.hpp:239
Matrix4 as3x3() const
Definition: Matrix4.hpp:315
Matrix4 & rotate(T_Scalar degrees1, const Vector3< T_Scalar > &v1, T_Scalar degrees2, const Vector3< T_Scalar > &v2, T_Scalar degrees3, const Vector3< T_Scalar > &v3)
Definition: Matrix4.hpp:510
const T_Scalar & y() const
Definition: Vector2.hpp:134
T_Scalar & e(int i, int j)
Definition: Matrix4.hpp:666
static Matrix4 getLookAt(const Vector3< T_Scalar > &eye, const Vector3< T_Scalar > &at, const Vector3< T_Scalar > &up)
Definition: Matrix4.hpp:788
#define VL_CHECK(expr)
Definition: checks.hpp:73
static Matrix4 getRotation(T_Scalar degrees1, const Vector3< T_Scalar > &v1, T_Scalar degrees2, const Vector3< T_Scalar > &v2)
Definition: Matrix4.hpp:485
bool operator!=(const Matrix4 &m) const
Definition: Matrix4.hpp:178
bool operator==(const Matrix4 &m) const
Definition: Matrix4.hpp:173
static Matrix4 getRotationZYX(T_Scalar degZ, T_Scalar degY, T_Scalar degX)
Definition: Matrix4.hpp:525
T normalize(T)
Definition: glsl_math.hpp:1128
const T_Scalar & w() const
Definition: Vector4.hpp:105