Allolib  1.0
C++ Components For Interactive Multimedia
al_Matrix4.hpp
1 #ifndef INCLUDE_AL_MATRIX4_HPP
2 #define INCLUDE_AL_MATRIX4_HPP
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
8  Copyright (C) 2012. The Regents of the University of California.
9  All rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are met:
13 
14  Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16 
17  Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20 
21  Neither the name of the University of California nor the names of its
22  contributors may be used to endorse or promote products derived from
23  this software without specific prior written permission.
24 
25  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  POSSIBILITY OF SUCH DAMAGE.
36 
37 
38  File description:
39  This is a more specialized 4x4 matrix including transformations commonly
40  used in computer graphics.
41 
42  File author(s):
43  Graham Wakefield, 2010, grrrwaaa@gmail.com
44 */
45 
46 #include "al/math/al_Constants.hpp"
47 #include "al/math/al_Mat.hpp"
48 #include "al/math/al_Quat.hpp"
49 #include "al/math/al_Vec.hpp"
50 
51 namespace al {
52 
53 template <class T>
54 class Matrix4;
55 
58 
62 template <typename T = double>
63 class Matrix4 : public Mat<4, T> {
64  public:
65  typedef Mat<4, T> Base;
66 
68  Matrix4() : Base(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) {}
69 
70  /*
71  The constructor will map into memory locations as follows:
72 
73  Matrix4(arg1, arg2, arg3, ...)
74 
75  arg1 ->m[0] arg2 ->m[4] arg3 ->m[8] arg4 ->m[12]
76  arg5 ->m[1] arg6 ->m[5] arg7 ->m[9] arg8 ->m[13]
77  arg9 ->m[2] arg10->m[6] arg11->m[10] arg12->m[14]
78  arg13->m[3] arg14->m[7] arg15->m[11] arg16->m[15]
79 
80  Matrix4(r1c1, r1c2, r1c3, r1c4,
81  r2c1, r2c2, r2c3, r2c4,
82  r3c1, r3c2, r3c3, r3c4,
83  r4c1, r4c2, r4c3, r4c4)
84  */
85  Matrix4(const T& r1c1, const T& r1c2, const T& r1c3, const T& r1c4,
86  const T& r2c1, const T& r2c2, const T& r2c3, const T& r2c4,
87  const T& r3c1, const T& r3c2, const T& r3c3, const T& r3c4,
88  const T& r4c1, const T& r4c2, const T& r4c3, const T& r4c4)
89  : Base(r1c1, r1c2, r1c3, r1c4, r2c1, r2c2, r2c3, r2c4, r3c1, r3c2, r3c3,
90  r3c4, r4c1, r4c2, r4c3, r4c4) {}
91 
92  Matrix4(const Vec<3, T>& xaxis, const Vec<3, T>& yaxis,
93  const Vec<3, T>& zaxis, const Vec<3, T>& position)
94  : Base(xaxis[0], yaxis[0], zaxis[0], position[0], xaxis[1], yaxis[1],
95  zaxis[1], position[1], xaxis[2], yaxis[2], zaxis[2], position[2],
96  0, 0, 0, 1) {}
97 
99  Matrix4(const T* src) : Base(src) {}
100 
102  Matrix4(const Mat<4, T>& src) : Base(src) {}
103 
105  Quat<T> toQuat() const { return Quat<T>().fromMatrix(Base::elems()); }
106 
109  q.toMatrix(Base::elems());
110  return *this;
111  }
112  Matrix4& fromQuatTransposed(Quat<T>& q) {
114  return *this;
115  }
116 
117  static Matrix4 rotate(float angle, float x, float y, float z) {
118  return Matrix4::rotate(angle, Vec3d(x, y, z));
119  }
120 
121  static Matrix4 rotate(float angle, const Vec<3, T>& v) {
122  Vec<3, T> axis(v);
123  axis.normalize();
124 
125  float c = cos(angle);
126  float s = sin(angle);
127 
128  Matrix4 m(axis[0] * axis[0] * (1 - c) + c,
129  axis[1] * axis[0] * (1 - c) + axis[2] * s,
130  axis[0] * axis[2] * (1 - c) - axis[1] * s, 0,
131 
132  axis[0] * axis[1] * (1 - c) - axis[2] * s,
133  axis[1] * axis[1] * (1 - c) + c,
134  axis[1] * axis[2] * (1 - c) + axis[0] * s, 0,
135 
136  axis[0] * axis[2] * (1 - c) + axis[1] * s,
137  axis[1] * axis[2] * (1 - c) - axis[0] * s,
138  axis[2] * axis[2] * (1 - c) + c, 0,
139 
140  0, 0, 0, 1);
141 
142  return m;
143  }
144 
146  static Matrix4 shearXY(T x, T y) {
147  return Matrix4(1, 0, x, 0, 0, 1, y, 0, 0, 0, 1, 0, 0, 0, 0, 1);
148  }
149 
151  static Matrix4 shearYZ(T y, T z) {
152  return Matrix4(1, 0, 0, 0, y, 1, 0, 0, z, 0, 1, 0, 0, 0, 0, 1);
153  }
154 
156  static Matrix4 shearZX(T z, T x) {
157  return Matrix4(1, x, 0, 0, 0, 1, 0, 0, 0, z, 1, 0, 0, 0, 0, 1);
158  }
159 
161 
168  static Matrix4 perspective(T l, T r, T b, T t, T n, T f) {
169  T W = r - l;
170  T W2 = r + l;
171  T H = t - b;
172  T H2 = t + b;
173  T D = f - n;
174  T D2 = f + n;
175  T n2 = n * 2;
176  T fn2 = f * n2;
177  return Matrix4(n2 / W, 0, W2 / W, 0, 0, n2 / H, H2 / H, 0, 0, 0, -D2 / D,
178  -fn2 / D, 0, 0, -1, 0);
179  }
180 
182 
187  static Matrix4 perspective(T fovy, T aspect, T near, T far) {
188  double f = 1. / tan(fovy * M_DEG2RAD / 2.);
189  T D = far - near;
190  T D2 = far + near;
191  T fn2 = far * near * 2;
192  return Matrix4(f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, -D2 / D, -fn2 / D, 0,
193  0, -1, 0);
194  }
195 
197 
208  static Matrix4 perspective(const Vec<3, T>& nearBL, const Vec<3, T>& nearBR,
209  const Vec<3, T>& nearTL, const Vec<3, T>& eye,
210  T near, T far) {
211  Vec<3, T> va, vb, vc;
212  Vec<3, T> vr, vu, vn;
213  T l, r, b, t, d;
214 
215  // compute orthonormal basis for the screen
216  vr = (nearBR - nearBL).normalize(); // right vector
217  vu = (nearTL - nearBL).normalize(); // up vector
218  cross(vn, vr, vu); // normal(forward) vector (out from screen)
219  vn.normalize();
220 
221  // compute vectors from eye to screen corners:
222  va = nearBL - eye;
223  vb = nearBR - eye;
224  vc = nearTL - eye;
225 
226  // distance from eye to screen-plane
227  // = component of va along vector vn (normal to screen)
228  d = -va.dot(vn);
229 
230  // find extent of perpendicular projection
231  T nbyd = near / d;
232  l = vr.dot(va) * nbyd;
233  r = vr.dot(vb) * nbyd;
234  b = vu.dot(va) * nbyd; // not vd?
235  t = vu.dot(vc) * nbyd;
236 
237  return perspective(l, r, b, t, near, far);
238  }
239 
241  static Matrix4 perspectiveLeft(T fovy, T aspect, T near, T far, T eyeSep,
242  T focal) {
243  return perspectiveOffAxis(fovy, aspect, near, far, -0.5 * eyeSep, focal);
244  }
245 
247  static Matrix4 perspectiveRight(T fovy, T aspect, T near, T far, T eyeSep,
248  T focal) {
249  return perspectiveOffAxis(fovy, aspect, near, far, 0.5 * eyeSep, focal);
250  }
251 
253  static Matrix4 perspectiveOffAxis(T fovy, T aspect, T near, T far, T xShift,
254  T focal) {
255  T top = near *
256  tan(fovy * M_DEG2RAD * 0.5); // height of view at distance = near
257  T bottom = -top;
258  T shift = -xShift * near / focal;
259  T left = -aspect * top + shift;
260  T right = aspect * top + shift;
261  return perspective(left, right, bottom, top, near, far);
262  }
263 
265 
273  static Matrix4 perspectiveOffAxis(T fovy, T aspect, T near, T far, T xShift,
274  T yShift, T focal) {
275  double tanfovy = tan(fovy * M_DEG2RAD / 2.);
276  T t = near * tanfovy; // height of view at distance = near
277  T b = -t;
278  T l = -aspect * t;
279  T r = aspect * t;
280 
281  T shift = -xShift * near / focal;
282  l += shift;
283  r += shift;
284  shift = -yShift * near / focal;
285  t += shift;
286  b += shift;
287 
288  return perspective(l, r, b, t, near, far);
289  }
290 
291  static Matrix4 unPerspective(T l, T r, T b, T t, T n, T f) {
292  T W = r - l;
293  T W2 = r + l;
294  T H = t - b;
295  T H2 = t + b;
296  T D = f - n;
297  T D2 = f + n;
298  T n2 = n * 2;
299  T fn2 = f * n2;
300  return Matrix4(W / n2, 0, 0, W2 / n2, 0, H / n2, 0, H2 / n2, 0, 0, 0, -1, 0,
301  0, -D / fn2, D2 / fn2);
302  }
303 
305 
312  static Matrix4 ortho(T l, T r, T b, T t, T n, T f) {
313  T W = r - l;
314  T W2 = r + l;
315  T H = t - b;
316  T H2 = t + b;
317  T D = f - n;
318  T D2 = f + n;
319  return Matrix4(2 / W, 0, 0, -W2 / W, 0, 2 / H, 0, -H2 / H, 0, 0, -2 / D,
320  -D2 / D, 0, 0, 0, 1);
321  }
322 
323  static Matrix4 unOrtho(T l, T r, T b, T t, T n, T f) {
324  T W = r - l;
325  T W2 = r + l;
326  T H = t - b;
327  T H2 = t + b;
328  T D = f - n;
329  T D2 = f + n;
330  return Matrix4(W / 2, 0, 0, W2 / 2, 0, H / 2, 0, H2 / 2, 0, 0, D / -2,
331  D2 / 2, 0, 0, 0, 1);
332  }
333 
335 
341  static Matrix4 ortho2D(T l, T r, T b, T t) {
342  T W = r - l;
343  T W2 = r + l;
344  T H = t - b;
345  T H2 = t + b;
346  return Matrix4(2 / W, 0, 0, -W2 / W, 0, 2 / H, 0, -H2 / H, 0, 0, -1, 0, 0,
347  0, 0, 1);
348  }
349 
351 
356  static Matrix4 lookAt(const Vec<3, T>& ur, const Vec<3, T>& uu,
357  const Vec<3, T>& uf, const Vec<3, T>& eyePos) {
358  return Matrix4(ur[0], ur[1], ur[2], -(ur.dot(eyePos)), uu[0], uu[1], uu[2],
359  -(uu.dot(eyePos)), uf[0], uf[1], uf[2], -(uf.dot(eyePos)), 0,
360  0, 0, 1);
361  }
362 
364 
368  static Matrix4 lookAt(const Vec<3, T>& eyePos, const Vec<3, T>& at,
369  const Vec<3, T>& up) {
370  Vec<3, T> z = (at - eyePos).normalize();
371  Vec<3, T> y = up;
372  y.normalize();
373  Vec<3, T> x = cross(z, up).normalize();
374  return lookAt(x, y, -z, eyePos);
375  }
376 
377  // static Matrix4 lookAtRH(const Vec<3,T>& ux, const Vec<3,T>& uy, const
378  // Vec<3,T>& uz, const Vec<3,T>& pos) {
379  // return Matrix4(
380  // ux[0], ux[1], ux[2], -(ux.dot(pos)),
381  // uy[0], uy[1], uy[2], -(uy.dot(pos)),
382  // uz[0],uz[1],uz[2], -(uz.dot(pos)),
383  // 0, 0, 0, 1
384  // );
385  // }
386  //
387  // static Matrix4 lookAtRH(const Vec<3,T>& eye, const Vec<3,T>& at, const
388  // Vec<3,T>& up) {
389  // Vec<3,T> z = (at - eye).normalize();
390  // Vec<3,T> x = cross(up, z);
391  // Vec<3,T> y = cross(z, x);
392  // return lookAt(x, y, z, eye);
393  // }
394 
396  static Matrix4 lookAtLeft(const Vec<3, T>& ux, const Vec<3, T>& uy,
397  const Vec<3, T>& uz, const Vec<3, T>& pos,
398  double eyeSep) {
399  return lookAtOffAxis(ux, uy, uz, pos, -0.5 * eyeSep);
400  }
401 
403  static Matrix4 lookAtRight(const Vec<3, T>& ux, const Vec<3, T>& uy,
404  const Vec<3, T>& uz, const Vec<3, T>& pos,
405  double eyeSep) {
406  return lookAtOffAxis(ux, uy, uz, pos, 0.5 * eyeSep);
407  }
408 
410  static Matrix4 lookAtOffAxis(const Vec<3, T>& ux, const Vec<3, T>& uy,
411  const Vec<3, T>& uz, const Vec<3, T>& pos,
412  double eyeShift) {
413  return lookAt(ux, uy, uz, pos + (ux * -eyeShift));
414  }
415 
417 
420  Vec<4, T> transform(const Vec<4, T>& vCol) const { return *this * vCol; }
421 
423  Vec<4, T> transform(const Vec<3, T>& vCol) const {
424  return transform(Vec<4, T>(vCol, T(1)));
425  }
426 
428  static Matrix4 inverse(const Mat<4, T>& m) {
429  Matrix4 res(m);
430  invert(res);
431  return res;
432  }
433 
434  // \deprecated Use Mat::translation
435  static Matrix4 translate(T x, T y, T z) {
436  return translation(Vec<3, T>(x, y, z));
437  }
438  // \deprecated Use Mat::translation
439  template <typename V>
440  static Matrix4 translate(const Vec<3, V>& v) {
441  return translation(v);
442  }
443  // \deprecated Use Mat::scaling
444  static Matrix4 scale(T x, T y, T z) { return scaling(x, y, z); }
445  // \deprecated Use Mat::scaling
446  template <typename V>
447  static Matrix4 scale(const Vec<3, V>& v) {
448  return scaling(v);
449  }
450  // \deprecated Use Mat::scaling
451  template <typename V>
452  static Matrix4 scale(const V& v) {
453  return scaling(v);
454  }
455  // \deprecated Use Mat::rotation
456  static Matrix4 rotateXY(T theta) { return rotation(theta, 0, 1); }
457  static Matrix4 rotateYZ(T theta) { return rotation(theta, 1, 2); }
458  static Matrix4 rotateZX(T theta) { return rotation(theta, 2, 0); }
459 };
460 
462 template <class T>
463 inline T frustumFar(const Mat<4, T>& proj) {
464  return proj[14] / (proj[10] + T(1));
465 }
466 
468 template <class T>
469 inline T frustumNear(const Mat<4, T>& proj) {
470  return proj[14] / (proj[10] - T(1));
471 }
472 
474 template <class T>
475 inline T frustumDepth(const Mat<4, T>& proj) {
476  return (T(-2) * proj[14]) / (proj[10] * proj[10] - T(1));
477 }
478 
480 template <class T>
481 inline T frustumAspect(const Mat<4, T>& proj) {
482  return proj[5] / proj[0];
483 }
484 
485 } // namespace al
486 
487 #endif /* include guard */
Fixed-size n-by-n square matrix.
Definition: al_Mat.hpp:78
const T * elems() const
Get read-only pointer to elements.
Definition: al_Mat.hpp:191
static Mat scaling(const Vec< N - 1, V > &v)
Get a scaling transform matrix.
Definition: al_Mat.hpp:146
static Mat translation(const Vec< N - 1, V > &v)
Get a translation transform matrix.
Definition: al_Mat.hpp:167
static Mat rotation(double angle, int dim1, int dim2)
Get a rotation transform matrix.
Definition: al_Mat.hpp:131
static Matrix4 perspective(const Vec< 3, T > &nearBL, const Vec< 3, T > &nearBR, const Vec< 3, T > &nearTL, const Vec< 3, T > &eye, T near, T far)
Calculate perspective projection from near plane and eye coordinates.
Definition: al_Matrix4.hpp:208
static Matrix4 lookAtLeft(const Vec< 3, T > &ux, const Vec< 3, T > &uy, const Vec< 3, T > &uz, const Vec< 3, T > &pos, double eyeSep)
Get a left-eye viewing matrix.
Definition: al_Matrix4.hpp:396
Matrix4 & fromQuat(Quat< T > &q)
Set from quaternion.
Definition: al_Matrix4.hpp:108
static Matrix4 ortho2D(T l, T r, T b, T t)
Get a two-dimensional orthographic projection matrix.
Definition: al_Matrix4.hpp:341
static Matrix4 perspectiveOffAxis(T fovy, T aspect, T near, T far, T xShift, T yShift, T focal)
Get an off-axis perspective projection matrix (for stereographics)
Definition: al_Matrix4.hpp:273
Matrix4()
Default constructor creates an identity matrix.
Definition: al_Matrix4.hpp:68
static Matrix4 perspectiveOffAxis(T fovy, T aspect, T near, T far, T xShift, T focal)
Get an off-axis perspective projection matrix (for stereographics)
Definition: al_Matrix4.hpp:253
static Matrix4 perspective(T fovy, T aspect, T near, T far)
Get a perspective projection matrix.
Definition: al_Matrix4.hpp:187
static Matrix4 perspectiveLeft(T fovy, T aspect, T near, T far, T eyeSep, T focal)
Get a left-eye perspective projection matrix (for stereographics)
Definition: al_Matrix4.hpp:241
static Matrix4 shearYZ(T y, T z)
Get a shear transformation matrix on the yz plane.
Definition: al_Matrix4.hpp:151
static Matrix4 inverse(const Mat< 4, T > &m)
Get the inverse of a matrix.
Definition: al_Matrix4.hpp:428
static Matrix4 lookAtOffAxis(const Vec< 3, T > &ux, const Vec< 3, T > &uy, const Vec< 3, T > &uz, const Vec< 3, T > &pos, double eyeShift)
Get an off-axis viewing matrix.
Definition: al_Matrix4.hpp:410
static Matrix4 perspectiveRight(T fovy, T aspect, T near, T far, T eyeSep, T focal)
Get a right-eye perspective projection matrix (for stereographics)
Definition: al_Matrix4.hpp:247
static Matrix4 ortho(T l, T r, T b, T t, T n, T f)
Get an orthographic projection matrix.
Definition: al_Matrix4.hpp:312
Vec< 4, T > transform(const Vec< 4, T > &vCol) const
Computes product of matrix multiplied by column vector, r = m * vCol.
Definition: al_Matrix4.hpp:420
Vec< 4, T > transform(const Vec< 3, T > &vCol) const
Computes product of matrix multiplied by column vector, r = m * vCol.
Definition: al_Matrix4.hpp:423
static Matrix4 shearZX(T z, T x)
Get a shear transformation matrix on the zx plane.
Definition: al_Matrix4.hpp:156
static Matrix4 lookAt(const Vec< 3, T > &eyePos, const Vec< 3, T > &at, const Vec< 3, T > &up)
Get a viewing matrix based on look-at parameters.
Definition: al_Matrix4.hpp:368
Matrix4(const Mat< 4, T > &src)
Definition: al_Matrix4.hpp:102
static Matrix4 perspective(T l, T r, T b, T t, T n, T f)
Get a perspective projection matrix.
Definition: al_Matrix4.hpp:168
static Matrix4 lookAtRight(const Vec< 3, T > &ux, const Vec< 3, T > &uy, const Vec< 3, T > &uz, const Vec< 3, T > &pos, double eyeSep)
Get a right-eye viewing matrix.
Definition: al_Matrix4.hpp:403
static Matrix4 shearXY(T x, T y)
Get a shear transformation matrix on the xy plane.
Definition: al_Matrix4.hpp:146
Matrix4(const T *src)
Definition: al_Matrix4.hpp:99
Quat< T > toQuat() const
Get a quaternion representation.
Definition: al_Matrix4.hpp:105
static Matrix4 lookAt(const Vec< 3, T > &ur, const Vec< 3, T > &uu, const Vec< 3, T > &uf, const Vec< 3, T > &eyePos)
Get a viewing matrix based on an eye reference frame.
Definition: al_Matrix4.hpp:356
Quat & fromMatrix(const T *matrix)
Definition: al_Quat.hpp:579
void toMatrix(T2 *matrix) const
Convert to column-major 4-by-4 projective space transformation matrix.
Definition: al_Quat.hpp:764
void toMatrixTransposed(T2 *matrix) const
Convert to row-major 4-by-4 projective space transformation matrix.
Definition: al_Quat.hpp:789
Vec & normalize(T scale=T(1))
Set magnitude to one without changing direction.
Definition: al_Vec.hpp:729
T dot(const Vec< N, U > &v) const
Returns dot (inner) product between vectors.
Definition: al_Vec.hpp:406
Definition: al_App.hpp:23
bool invert(Mat< 1, T > &m)
Definition: al_Mat.hpp:643
T frustumNear(const Mat< 4, T > &proj)
Get frustum near plane distance from a projection matrix.
Definition: al_Matrix4.hpp:469
Vec< 3, double > Vec3d
double 3-vector
Definition: al_Vec.hpp:60
T frustumAspect(const Mat< 4, T > &proj)
Get frustum aspect ratio from a projection matrix.
Definition: al_Matrix4.hpp:481
Matrix4< float > Matrix4f
Single-precision 4-by-4 matrix.
Definition: al_Matrix4.hpp:57
T angle(const Vec< N, T > &a, const Vec< N, T > &b)
Returns angle, in interval [0, pi], between two vectors.
Definition: al_Vec.hpp:634
T frustumFar(const Mat< 4, T > &proj)
Get frustum far plane distance from a projection matrix.
Definition: al_Matrix4.hpp:463
void cross(Vec< 3, T > &r, const Vec< 3, T > &a, const Vec< 3, T > &b)
Sets r to cross product, a x b.
Definition: al_Vec.hpp:574
Matrix4< double > Matrix4d
Double-precision 4-by-4 matrix.
Definition: al_Matrix4.hpp:54
T frustumDepth(const Mat< 4, T > &proj)
Get frustum depth from a projection matrix.
Definition: al_Matrix4.hpp:475