Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
transformutils.cc
Go to the documentation of this file.
1 
19 
20 #include <cmath>
21 
22 #include "ion/base/logging.h"
23 #include "ion/base/static_assert.h"
24 #include "ion/math/angleutils.h"
25 #include "ion/math/matrixutils.h"
26 #include "ion/math/utils.h"
27 #include "ion/math/vectorutils.h"
28 
29 namespace ion {
30 namespace math {
31 
33 
36 
37 
38 namespace {
39 
41 template <int Dimension, typename T>
42 void RotationMatrix3x3(const Rotation<T>& r, Matrix<Dimension, T>* matrix) {
43  ION_STATIC_ASSERT(Dimension >= 3, "Bad Dimension in RotationMatrix3x3");
44  DCHECK(matrix);
45 
51  2ab + 2cd -a^2 + b^2 - c^2 + d^2 2bc - 2ad
52  2ac - 2bd 2bc + 2ad -a^2 - b^2 + c^2 + d^2
54  const Vector<4, T>& quat = r.GetQuaternion();
55  const T aa = Square(quat[0]);
56  const T bb = Square(quat[1]);
57  const T cc = Square(quat[2]);
58  const T dd = Square(quat[3]);
59 
60  const T ab = quat[0] * quat[1];
61  const T ac = quat[0] * quat[2];
62  const T bc = quat[1] * quat[2];
63 
64  const T ad = quat[0] * quat[3];
65  const T bd = quat[1] * quat[3];
66  const T cd = quat[2] * quat[3];
67 
68  Matrix<Dimension, T>& m = *matrix;
69  m[0][0] = aa - bb - cc + dd;
70  m[0][1] = 2 * ab - 2 * cd;
71  m[0][2] = 2 * ac + 2 * bd;
72  m[1][0] = 2 * ab + 2 * cd;
73  m[1][1] = -aa + bb - cc + dd;
74  m[1][2] = 2 * bc - 2 * ad;
75  m[2][0] = 2 * ac - 2 * bd;
76  m[2][1] = 2 * bc + 2 * ad;
77  m[2][2] = -aa - bb + cc + dd;
78 }
79 
80 } // anonymous namespace
81 
83 
86 
87 
88 template <typename T>
90  static const T kZero = static_cast<T>(0);
91  static const T kOne = static_cast<T>(1);
92  static const Vector<4, T> kZeroZeroZeroOne(kZero, kZero, kZero, kOne);
93 
97  DCHECK(MatrixAlmostOrthogonal(nh, std::numeric_limits<T>::epsilon() *
98  static_cast<T>(10)))
99  << "Non-orthogonal matrix received in OrthoInverseH: " << m;
100  DCHECK(VectorsAlmostEqual(kZeroZeroZeroOne, Row(m, 3),
101  std::numeric_limits<T>::epsilon()))
102  << "Invalid 4th row in OrthoInverseH: " << Row(m, 3);
103 
113  -(Transpose(nh) * Vector<3, T>(m(0, 3), m(1, 3), m(2, 3)));
114  return Matrix<4, T>(m(0, 0), m(1, 0), m(2, 0), translation[0],
115  m(0, 1), m(1, 1), m(2, 1), translation[1],
116  m(0, 2), m(1, 2), m(2, 2), translation[2],
117  kZero, kZero, kZero, kOne);
118 }
119 
120 template <typename T> ION_API
122  Matrix<4, T> m;
123  RotationMatrix3x3(r, &m);
124  for (int i = 0; i < 3; ++i)
125  m[i][3] = m[3][i] = static_cast<T>(0);
126  m[3][3] = static_cast<T>(1);
127  return m;
128 }
129 
130 template <typename T> ION_API
132  Matrix<3, T> m;
133  RotationMatrix3x3(r, &m);
134  return m;
135 }
136 
137 template <typename T> ION_API
139  const Point<3, T>& eye, const Point<3, T>& center, const Vector<3, T>& up) {
140  const Vector<3, T> dir = center - eye;
142  return LookAtMatrixFromDir(eye, dir, up);
143 }
144 
145 template <typename T> ION_API
147  const Point<3, T>& eye, const Vector<3, T>& dir, const Vector<3, T>& up) {
149  DCHECK(eye == eye);
150  DCHECK(dir == dir);
151  DCHECK(up == up);
152  DCHECK_GE(LengthSquared(Cross(dir, up)),
153  std::numeric_limits<T>::epsilon())
154  << "LookAtMatrixFromDir received front and up vectors that have "
155  << "either zero length or are parallel to each other. "
156  << "[dir: " << dir << " up: " << up << "]";
157 
158  const Vector<3, T> front = Normalized(dir);
159  const Vector<3, T> right = Normalized(Cross(front, up));
160  const Vector<3, T> new_up = Normalized(Cross(right, front));
161  math::Matrix<4, T> mat(right[0], right[1], right[2], 0,
162  new_up[0], new_up[1], new_up[2], 0,
163  -front[0], -front[1], -front[2], 0,
164  0, 0, 0, 1);
165 
166  return mat * TranslationMatrix(-eye);
167 }
168 
169 template <typename T> ION_API
171  T x_left, T x_right, T y_bottom, T y_top, T z_near, T z_far) {
172  if (x_left == x_right || y_bottom == y_top || z_near == z_far) {
173  return Matrix<4, T>::Identity();
174  }
175 
176  const T X = 2 / (x_right - x_left);
177  const T Y = 2 / (y_top - y_bottom);
178  const T Z = 2 / (z_near - z_far);
179  const T A = (x_right + x_left) / (x_left - x_right);
180  const T B = (y_top + y_bottom) / (y_bottom - y_top);
181  const T C = (z_near + z_far) / (z_near - z_far);
182 
183  return math::Matrix<4, T>(X, 0, 0, A,
184  0, Y, 0, B,
185  0, 0, Z, C,
186  0, 0, 0, 1);
187 }
188 
189 template <typename T> ION_API
191  T x_left, T x_right, T y_bottom, T y_top, T z_near, T z_far) {
192  const T zero = static_cast<T>(0);
193  if (x_left == x_right || y_bottom == y_top || z_near == z_far ||
194  z_near <= zero || z_far <= zero) {
195  return Matrix<4, T>::Identity();
196  }
197 
198  const T X = (2 * z_near) / (x_right - x_left);
199  const T Y = (2 * z_near) / (y_top - y_bottom);
200  const T A = (x_right + x_left) / (x_right - x_left);
201  const T B = (y_top + y_bottom) / (y_top - y_bottom);
202  const T C = (z_near + z_far) / (z_near - z_far);
203  const T D = (2 * z_near * z_far) / (z_near - z_far);
204 
205  return math::Matrix<4, T>(X, 0, A, 0,
206  0, Y, B, 0,
207  0, 0, C, D,
208  0, 0, -1, 0);
209 }
210 
211 template <typename T> ION_API
213  T z_near, T z_far) {
214  const T zero = static_cast<T>(0);
215  if (fovy.Radians() <= zero || aspect <= zero ||
216  z_near <= zero || z_far <= zero || z_near == z_far) {
217  return Matrix<4, T>::Identity();
218  }
219 
220  const T tan_fov = Tangent(fovy / 2) * z_near;
221  const T x_left = -tan_fov * aspect;
222  const T x_right = tan_fov * aspect;
223  const T y_bottom = -tan_fov;
224  const T y_top = tan_fov;
225  return PerspectiveMatrixFromFrustum<T>(
226  x_left, x_right, y_bottom, y_top, z_near, z_far);
227 }
228 
229 template <typename T> ION_API
231  static const T kZero = static_cast<T>(0);
232  static const T kOne = static_cast<T>(1);
241  DCHECK_LE(fabs(m(0, 1)), std::numeric_limits<T>::epsilon());
242  DCHECK_LE(fabs(m(0, 3)), std::numeric_limits<T>::epsilon());
243  DCHECK_LE(fabs(m(1, 0)), std::numeric_limits<T>::epsilon());
244  DCHECK_LE(fabs(m(1, 3)), std::numeric_limits<T>::epsilon());
245  DCHECK_LE(fabs(m(2, 0)), std::numeric_limits<T>::epsilon());
246  DCHECK_LE(fabs(m(2, 1)), std::numeric_limits<T>::epsilon());
247  DCHECK_LE(fabs(m(3, 0)), std::numeric_limits<T>::epsilon());
248  DCHECK_LE(fabs(m(3, 1)), std::numeric_limits<T>::epsilon());
249  DCHECK_LE(fabs(m(3, 3)), std::numeric_limits<T>::epsilon());
250  DCHECK_LE(fabs(m(3, 2) + kOne), std::numeric_limits<T>::epsilon());
251 
253  const T a = m(0, 2);
254  const T b = m(1, 2);
255  const T c = m(2, 2);
256  const T inv_d = kOne / m(2, 3);
257  const T inv_x = kOne / m(0, 0);
258  const T inv_y = kOne / m(1, 1);
259  return math::Matrix<4, T>(inv_x, kZero, kZero, a * inv_x,
260  kZero, inv_y, kZero, b * inv_y,
261  kZero, kZero, kZero, -kOne,
262  kZero, kZero, inv_d, c * inv_d);
263 }
264 
266 
269 
270 
271 #define ION_INSTANTIATE_FUNCTIONS(type) \
272 template const Matrix<4, type> ION_API OrthoInverseH( \
273  const Matrix<4, type>& r); \
274 template const Matrix<4, type> ION_API RotationMatrixH( \
275  const Rotation<type>& r); \
276 template const Matrix<3, type> ION_API RotationMatrixNH( \
277  const Rotation<type>& r); \
278 template const Matrix<4, type> ION_API LookAtMatrixFromCenter( \
279  const Point<3, type>& eye, const Point<3, type>& center, \
280  const Vector<3, type>& up); \
281 template const Matrix<4, type> ION_API LookAtMatrixFromDir( \
282  const Point<3, type>& eye, const Vector<3, type>& dir, \
283  const Vector<3, type>& up); \
284 template const Matrix<4, type> ION_API OrthographicMatrixFromFrustum( \
285  type x_left, type x_right, type y_bottom, type y_top, \
286  type z_near, type z_far); \
287 template const Matrix<4, type> ION_API PerspectiveMatrixFromFrustum( \
288  type x_left, type x_right, type y_bottom, type y_top, \
289  type z_near, type z_far); \
290 template const Matrix<4, type> ION_API PerspectiveMatrixFromView( \
291  const Angle<type>& fovy, type aspect, type z_near, type z_far); \
292 template const Matrix<4, type> ION_API PerspectiveMatrixInverse( \
293  const Matrix<4, type>& m)
294 
295 ION_INSTANTIATE_FUNCTIONS(double); // NOLINT
296 ION_INSTANTIATE_FUNCTIONS(float); // NOLINT
297 
298 #undef ION_INSTANTIATE_FUNCTIONS
299 
300 } // namespace math
301 } // namespace ion
Vector< Dimension, T > Row(const Matrix< Dimension, T > &m, int row)
Returns a particular row of a matrix as a vector.
Definition: matrixutils.h:92
T Tangent(const ion::math::Angle< T > &angle)
ion::math::Angle specialization of Tangent.
Definition: angleutils.h:92
#define DCHECK(expr)
Definition: logging.h:331
ION_API const Matrix< 4, T > RotationMatrixH(const Rotation< T > &r)
Returns a 4x4 Matrix representing a 3D rotation.
bool MatrixAlmostOrthogonal(const Matrix< Dimension, T > &m, T tolerance)
Returns true if the dot product of all column vector pairs in the matrix is less than a provided tole...
Definition: matrixutils.cc:257
A simple class to represent angles.
Definition: angle.h:33
ION_API const Matrix< 4, T > LookAtMatrixFromDir(const Point< 3, T > &eye, const Vector< 3, T > &dir, const Vector< 3, T > &up)
Returns a 4x4 viewing matrix based on the given camera parameters, which use a view direction rather ...
ION_API const Matrix< 4, T > LookAtMatrixFromCenter(const Point< 3, T > &eye, const Point< 3, T > &center, const Vector< 3, T > &up)
View matrices.
T Radians() const
Get the angle in degrees or radians.
Definition: angle.h:55
Vector2d translation
Definition: coretextfont.mm:62
static Matrix Identity()
Returns an identity Matrix.
Definition: matrix.h:276
The Matrix class defines a square N-dimensional matrix.
Definition: matrix.h:35
ION_API const Matrix< 4, T > PerspectiveMatrixFromFrustum(T x_left, T x_right, T y_bottom, T y_top, T z_near, T z_far)
Returns a 4x4 perspective projection matrix based on the given parameters, which follow the conventio...
const Matrix< Dimension+1, T > TranslationMatrix(const VectorBase< Dimension, T > &t)
Affine transformation matrices.
ION_INSTANTIATE_FUNCTIONS(double)
ION_API const Matrix< 3, T > RotationMatrixNH(const Rotation< T > &r)
Returns a 3x3 Matrix representing a 3D rotation.
ION_API const Matrix< 4, T > PerspectiveMatrixFromView(const Angle< T > &fovy, T aspect, T z_near, T z_far)
Returns a 4x4 perspective projection matrix based on the given parameters, which follow the conventio...
const Vector< Dimension, T > Normalized(const Vector< Dimension, T > &v)
Returns a unit-length version of a Vector.
Definition: vectorutils.h:104
#define DCHECK_GE(val1, val2)
Definition: logging.h:336
const Matrix< 4, T > OrthoInverseH(const Matrix< 4, T > &m)
Public functions.
Copyright 2016 Google Inc.
The Rotation class represents a rotation around a 3-dimensional axis.
Definition: rotation.h:37
ION_API const Matrix< 4, T > OrthographicMatrixFromFrustum(T x_left, T x_right, T y_bottom, T y_top, T z_near, T z_far)
Projection matrices.
#define DCHECK_LE(val1, val2)
Definition: logging.h:334
ION_API const Matrix< 4, T > PerspectiveMatrixInverse(const Matrix< 4, T > &m)
Returns the inverse of m iff m is a perspective projection matrix, i.e., iff it has the following for...
bool VectorsAlmostEqual(const Vector< Dimension, T > &v0, const Vector< Dimension, T > &v1, T tolerance)
Returns true if all elements of two Vectors are equal within a tolerance.
Definition: vectorutils.h:164
const T Square(const T &val)
Squares a value.
Definition: utils.h:48
Point.
Definition: vector.h:296
#define ION_STATIC_ASSERT(expr, message)
Copyright 2016 Google Inc.
Definition: static_assert.h:35
Vector< 3, T > Cross(const Vector< 3, T > &v0, const Vector< 3, T > &v1)
Returns the 3-dimensional cross product of 2 Vectors.
Definition: vectorutils.h:48
Matrix< Dimension, T > Transpose(const Matrix< Dimension, T > &m)
Public functions.
Definition: matrixutils.h:65
Matrix< 3, T > NonhomogeneousSubmatrixH(const Matrix< 4, T > &m)
Homogeneous matrices.
T LengthSquared(const Vector< Dimension, T > &v)
Returns the square of the length of a Vector.
Definition: vectorutils.h:64