Mitsuba Renderer  0.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
transform.h
Go to the documentation of this file.
1 /*
2  This file is part of Mitsuba, a physically based rendering system.
3 
4  Copyright (c) 2007-2014 by Wenzel Jakob and others.
5 
6  Mitsuba is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Mitsuba is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #pragma once
20 #if !defined(__MITSUBA_CORE_TRANSFORM_H_)
21 #define __MITSUBA_CORE_TRANSFORM_H_
22 
23 #include <mitsuba/core/matrix.h>
24 #include <mitsuba/core/ray.h>
25 
27 
28 /**
29  * \brief Encapsulates a 4x4 linear transformation and its inverse
30  * \ingroup libcore
31  * \ingroup libpython
32  */
34 public:
35  /// Create an identity transformation
37  m_transform.setIdentity();
38  m_invTransform.setIdentity();
39  }
40 
41  /// Unserialize a transformation from a stream
42  inline Transform(Stream *stream) {
43  m_transform = Matrix4x4(stream);
44  m_invTransform = Matrix4x4(stream);
45  }
46 
47  /** \brief Create a transform from the given matrix
48  * and calculate the inverse
49  */
50  Transform(const Matrix4x4 &trafo)
51  : m_transform(trafo) {
52  bool success = m_transform.invert(m_invTransform);
53  if (!success)
54  SLog(EError, "Unable to invert singular matrix %s", trafo.toString().c_str());
55  }
56 
57  /// Create a transform from the given matrices
58  Transform(const Matrix4x4 &trafo, const Matrix4x4 &invTrafo)
59  : m_transform(trafo), m_invTransform(invTrafo) {
60  }
61 
62  /// Return the inverse transform
63  Transform inverse() const {
64  return Transform(m_invTransform, m_transform);
65  }
66 
67  /// Matrix-matrix multiplication
68  Transform operator*(const Transform &t) const;
69 
70  /// Return the determinant of the upper left 3x3 submatrix
71  inline Float det3x3() const {
72  return m_transform.det3x3();
73  }
74 
75  /// Test for a scale component
76  inline bool hasScale() const {
77  for (int i=0; i<3; ++i) {
78  for (int j=i; j<3; ++j) {
79  Float sum = 0;
80  for (int k=0; k<3; ++k)
81  sum += m_transform.m[i][k] * m_transform.m[j][k];
82 
83  if (i == j && std::abs(sum-1) > 1e-3f)
84  return true;
85  else if (i != j && std::abs(sum) > 1e-3f)
86  return true;
87  }
88  }
89  return false;
90  }
91 
92  /// Test if this is the identity transformation
93  inline bool isIdentity() const {
94  return m_transform.isIdentity();
95  }
96 
97  /// Test if this is the zero transformation
98  inline bool isZero() const {
99  return m_transform.isZero();
100  }
101 
102  /**
103  * \brief Matrix-vector multiplication for points in 3d space
104  *
105  * \remark In the Python bindings, this is function implemented as
106  * the multiplication operator (\c __mul__).
107  */
108  inline Point operator()(const Point &p) const {
109  Float x = m_transform.m[0][0] * p.x + m_transform.m[0][1] * p.y
110  + m_transform.m[0][2] * p.z + m_transform.m[0][3];
111  Float y = m_transform.m[1][0] * p.x + m_transform.m[1][1] * p.y
112  + m_transform.m[1][2] * p.z + m_transform.m[1][3];
113  Float z = m_transform.m[2][0] * p.x + m_transform.m[2][1] * p.y
114  + m_transform.m[2][2] * p.z + m_transform.m[2][3];
115  Float w = m_transform.m[3][0] * p.x + m_transform.m[3][1] * p.y
116  + m_transform.m[3][2] * p.z + m_transform.m[3][3];
117 #ifdef MTS_DEBUG
118  if (w == 0)
119  SLog(EWarn, "w==0 in Transform::operator(Point &)");
120 #endif
121  if (w == 1.0f)
122  return Point(x, y, z);
123  else
124  return Point(x, y, z) / w;
125  }
126 
127  /// Transform a point by an affine / non-projective matrix
128  inline Point transformAffine(const Point &p) const {
129  Float x = m_transform.m[0][0] * p.x + m_transform.m[0][1] * p.y
130  + m_transform.m[0][2] * p.z + m_transform.m[0][3];
131  Float y = m_transform.m[1][0] * p.x + m_transform.m[1][1] * p.y
132  + m_transform.m[1][2] * p.z + m_transform.m[1][3];
133  Float z = m_transform.m[2][0] * p.x + m_transform.m[2][1] * p.y
134  + m_transform.m[2][2] * p.z + m_transform.m[2][3];
135  return Point(x,y,z);
136  }
137 
138  /// Transform a point by a affine / non-projective matrix (no temporaries)
139  inline void transformAffine(const Point &p, Point &dest) const {
140  dest.x = m_transform.m[0][0] * p.x + m_transform.m[0][1] * p.y
141  + m_transform.m[0][2] * p.z + m_transform.m[0][3];
142  dest.y = m_transform.m[1][0] * p.x + m_transform.m[1][1] * p.y
143  + m_transform.m[1][2] * p.z + m_transform.m[1][3];
144  dest.z = m_transform.m[2][0] * p.x + m_transform.m[2][1] * p.y
145  + m_transform.m[2][2] * p.z + m_transform.m[2][3];
146  }
147 
148  /**
149  * \brief Matrix-vector multiplication for points in 3d space (no temporaries)
150  * \remark This function is not available in the Python bindings
151  */
152  inline void operator()(const Point &p, Point &dest) const {
153  dest.x = m_transform.m[0][0] * p.x + m_transform.m[0][1] * p.y
154  + m_transform.m[0][2] * p.z + m_transform.m[0][3];
155  dest.y = m_transform.m[1][0] * p.x + m_transform.m[1][1] * p.y
156  + m_transform.m[1][2] * p.z + m_transform.m[1][3];
157  dest.z = m_transform.m[2][0] * p.x + m_transform.m[2][1] * p.y
158  + m_transform.m[2][2] * p.z + m_transform.m[2][3];
159  Float w = m_transform.m[3][0] * p.x + m_transform.m[3][1] * p.y
160  + m_transform.m[3][2] * p.z + m_transform.m[3][3];
161 
162 #ifdef MTS_DEBUG
163  if (w == 0)
164  SLog(EWarn, "w==0 in Transform::operator(Point &, Point &)");
165 #endif
166  if (w != 1.0f)
167  dest /= w;
168  }
169 
170  /**
171  * \brief Matrix-vector multiplication for vectors in 3d space
172  * \remark In the Python bindings, this is function implemented as
173  * the multiplication operator (\c __mul__).
174  */
175  inline Vector operator()(const Vector &v) const {
176  Float x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y
177  + m_transform.m[0][2] * v.z;
178  Float y = m_transform.m[1][0] * v.x + m_transform.m[1][1] * v.y
179  + m_transform.m[1][2] * v.z;
180  Float z = m_transform.m[2][0] * v.x + m_transform.m[2][1] * v.y
181  + m_transform.m[2][2] * v.z;
182  return Vector(x, y, z);
183  }
184 
185  /**
186  * \brief Matrix-vector multiplication for vectors in 3d space (no temporaries)
187  * \remark This function is not available in the Python bindings
188  */
189  inline void operator()(const Vector &v, Vector &dest) const {
190  dest.x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y
191  + m_transform.m[0][2] * v.z;
192  dest.y = m_transform.m[1][0] * v.x + m_transform.m[1][1] * v.y
193  + m_transform.m[1][2] * v.z;
194  dest.z = m_transform.m[2][0] * v.x + m_transform.m[2][1] * v.y
195  + m_transform.m[2][2] * v.z;
196  }
197 
198  /**
199  * \brief Matrix-normal multiplication
200  * \remark In the Python bindings, this is function implemented as
201  * the multiplication operator (\c __mul__).
202  */
203  inline Normal operator()(const Normal &v) const {
204  Float x = m_invTransform.m[0][0] * v.x + m_invTransform.m[1][0] * v.y
205  + m_invTransform.m[2][0] * v.z;
206  Float y = m_invTransform.m[0][1] * v.x + m_invTransform.m[1][1] * v.y
207  + m_invTransform.m[2][1] * v.z;
208  Float z = m_invTransform.m[0][2] * v.x + m_invTransform.m[1][2] * v.y
209  + m_invTransform.m[2][2] * v.z;
210  return Normal(x, y, z);
211  }
212 
213  /**
214  * \brief Matrix-normal multiplication (no temporaries)
215  * \remark This function is not available in the Python bindings
216  */
217  inline void operator()(const Normal &v, Normal &dest) const {
218  dest.x = m_invTransform.m[0][0] * v.x + m_invTransform.m[1][0] * v.y
219  + m_invTransform.m[2][0] * v.z;
220  dest.y = m_invTransform.m[0][1] * v.x + m_invTransform.m[1][1] * v.y
221  + m_invTransform.m[2][1] * v.z;
222  dest.z = m_invTransform.m[0][2] * v.x + m_invTransform.m[1][2] * v.y
223  + m_invTransform.m[2][2] * v.z;
224  }
225 
226  /**
227  * \brief 4D matrix-vector multiplication
228  * \remark In the Python bindings, this is function implemented as
229  * the multiplication operator (\c __mul__).
230  */
231  inline Vector4 operator()(const Vector4 &v) const {
232  Float x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y
233  + m_transform.m[0][2] * v.z + m_transform.m[0][3] * v.w;
234  Float y = m_transform.m[1][0] * v.x + m_transform.m[1][1] * v.y
235  + m_transform.m[1][2] * v.z + m_transform.m[1][3] * v.w;
236  Float z = m_transform.m[2][0] * v.x + m_transform.m[2][1] * v.y
237  + m_transform.m[2][2] * v.z + m_transform.m[2][3] * v.w;
238  Float w = m_transform.m[3][0] * v.x + m_transform.m[3][1] * v.y
239  + m_transform.m[3][2] * v.z + m_transform.m[3][3] * v.w;
240  return Vector4(x,y,z,w);
241  }
242 
243  /**
244  * \brief 4D matrix-vector multiplication (no temporaries)
245  * \remark This function is not available in the Python bindings
246  */
247  inline void operator()(const Vector4 &v, Vector4 &dest) const {
248  dest.x = m_transform.m[0][0] * v.x + m_transform.m[0][1] * v.y
249  + m_transform.m[0][2] * v.z + m_transform.m[0][3] * v.w;
250  dest.y = m_transform.m[1][0] * v.x + m_transform.m[1][1] * v.y
251  + m_transform.m[1][2] * v.z + m_transform.m[1][3] * v.w;
252  dest.z = m_transform.m[2][0] * v.x + m_transform.m[2][1] * v.y
253  + m_transform.m[2][2] * v.z + m_transform.m[2][3] * v.w;
254  dest.w = m_transform.m[3][0] * v.x + m_transform.m[3][1] * v.y
255  + m_transform.m[3][2] * v.z + m_transform.m[3][3] * v.w;
256  }
257 
258  /**
259  * \brief Transform a ray. Assumes that there is no scaling (no temporaries)
260  * \remark This function is not available in the Python bindings
261  */
262  inline void operator()(const Ray &a, Ray &b) const {
263  b.mint = a.mint;
264  b.maxt = a.maxt;
265  operator()(a.o, b.o);
266  operator()(a.d, b.d);
267 #ifdef MTS_DEBUG_FP
268  bool state = disableFPExceptions();
269 #endif
270  /* Re-compute the reciprocal */
271  b.dRcp.x = 1.0f / b.d.x;
272  b.dRcp.y = 1.0f / b.d.y;
273  b.dRcp.z = 1.0f / b.d.z;
274 #ifdef MTS_DEBUG_FP
275  restoreFPExceptions(state);
276 #endif
277  b.time = a.time;
278  }
279 
280  /**
281  * \brief Transform a ray
282  * \remark In the Python bindings, this is function implemented as
283  * the multiplication operator (\c __mul__).
284  */
285  inline Ray operator()(const Ray &ray) const {
286  Ray result;
287  operator()(ray, result);
288  return result;
289  }
290 
291  /// Transform a ray by an affine / non-projective matrix (no temporaries)
292  inline void transformAffine(const Ray &a, Ray &b) const {
293  b.mint = a.mint;
294  b.maxt = a.maxt;
295  transformAffine(a.o, b.o);
296  operator()(a.d, b.d);
297 #ifdef MTS_DEBUG_FP
298  bool state = disableFPExceptions();
299 #endif
300  /* Re-compute the reciprocal */
301  b.dRcp.x = 1.0f / b.d.x;
302  b.dRcp.y = 1.0f / b.d.y;
303  b.dRcp.z = 1.0f / b.d.z;
304 #ifdef MTS_DEBUG_FP
305  restoreFPExceptions(state);
306 #endif
307  }
308 
309  /// Transform a ray by an affine / non-projective matrix (no temporaries)
310  inline Ray transformAffine(const Ray &ray) const {
311  Ray result;
312  transformAffine(ray, result);
313  return result;
314  }
315 
316  /// Return the underlying matrix
317  inline const Matrix4x4 &getMatrix() const { return m_transform; }
318 
319  /// Return the underlying inverse matrix (const version)
320  inline const Matrix4x4 &getInverseMatrix() const { return m_invTransform; }
321 
322  /// Create a translation transformation
323  static Transform translate(const Vector &v);
324 
325  /// Create a rotation transformation around an arbitrary axis. The angle is specified in degrees
326  static Transform rotate(const Vector &axis, Float angle);
327 
328  /// Create a scale transformation
329  static Transform scale(const Vector &v);
330 
331  /** \brief Create a perspective transformation.
332  * (Maps [near, far] to [0, 1])
333  * \param fov Field of view in degrees
334  * \param clipNear Near clipping plane
335  * \param clipFar Far clipping plane
336  */
337  static Transform perspective(Float fov, Float clipNear, Float clipFar);
338 
339  /** \brief Create a perspective transformation for OpenGL.
340  * (Maps [-near, -far] to [-1, 1])
341  * \param fov Field of view in degrees
342  * \param clipNear Near clipping plane distance
343  * \param clipFar Far clipping plane distance
344  */
345  static Transform glPerspective(Float fov, Float clipNear, Float clipFar);
346 
347  /** \brief Create a perspective transformation for OpenGL.
348  * \param left Left clipping plane coordinate
349  * \param right Right clipping plane coordinate
350  * \param top Top clipping plane coordinate
351  * \param bottom Bottom clipping plane coordinate
352  * \param nearVal Near clipping plane distance
353  * \param farVal Far clipping plane distance
354  */
355  static Transform glFrustum(Float left, Float right, Float bottom, Float top, Float nearVal, Float farVal);
356 
357  /** \brief Create an orthographic transformation, which maps Z to [0,1]
358  * and leaves the X and Y coordinates untouched.
359  * \param clipNear Near clipping plane
360  * \param clipFar Far clipping plane
361  */
362  static Transform orthographic(Float clipNear, Float clipFar);
363 
364  /** \brief Create an orthographic transformation for OpenGL
365  * \param clipNear Near clipping plane
366  * \param clipFar Far clipping plane
367  */
368  static Transform glOrthographic(Float clipNear, Float clipFar);
369 
370  /** \brief Create an orthographic transformation for OpenGL
371  *
372  * Slightly extended variant which also handles non-unity clipping
373  * planes on the X and Y axes and matches the 'glOrtho' spec.
374  */
375  static Transform glOrthographic(Float clipLeft, Float clipRight,
376  Float clipBottom, Float clipTop, Float clipNear, Float clipFar);
377 
378  /** \brief Create a look-at camera transformation
379  * \param p Camera position
380  * \param t Target vector
381  * \param u Up vector
382  */
383  static Transform lookAt(const Point &p, const Point &t, const Vector &u);
384 
385  /** \brief Create an orthogonal transformation that takes
386  * the standard to the supplied frame
387  */
388  static Transform fromFrame(const Frame &frame);
389 
390  /// Serialize a transformation to a stream
391  inline void serialize(Stream *stream) const {
392  m_transform.serialize(stream);
393  m_invTransform.serialize(stream);
394  }
395 
396  /// Equality comparison operator
397  inline bool operator==(const Transform &trafo) const {
398  return m_transform == trafo.m_transform;
399  }
400 
401  /// Inequality comparison operator
402  inline bool operator!=(const Transform &trafo) const {
403  return m_transform != trafo.m_transform;
404  }
405 
406  /// Return a string representation
407  std::string toString() const;
408 private:
409  Matrix4x4 m_transform;
410  Matrix4x4 m_invTransform;
411 };
412 
414 
415 #endif /* __MITSUBA_CORE_TRANSFORM_H_ */
std::string toString() const
Return a string representation.
Definition: matrix.h:426
void operator()(const Vector &v, Vector &dest) const
Matrix-vector multiplication for vectors in 3d space (no temporaries)
Definition: transform.h:189
Three-dimensional normal data structure.
Definition: normal.h:39
Matrix< M1, N2, T > operator*(const Matrix< M1, N1, T > &mat1, const Matrix< M2, N2, T > &mat2)
Matrix multiplication (creates a temporary)
Definition: matrix.h:745
Transform(const Matrix4x4 &trafo, const Matrix4x4 &invTrafo)
Create a transform from the given matrices.
Definition: transform.h:58
const Matrix4x4 & getInverseMatrix() const
Return the underlying inverse matrix (const version)
Definition: transform.h:320
Stores a three-dimensional orthonormal coordinate frame.
Definition: frame.h:37
MTS_EXPORT_CORE void restoreFPExceptions(bool state)
Restore floating point exceptions to the specified state.
T y
Definition: vector.h:455
TVector3< Float > Vector
Definition: fwd.h:113
bool operator==(const Transform &trafo) const
Equality comparison operator.
Definition: transform.h:397
#define MTS_EXPORT_CORE
Definition: getopt.h:29
#define SLog(level, fmt,...)
Write a Log message to the console (static version - to be used outside of classes that derive from O...
Definition: logger.h:49
Vector4 operator()(const Vector4 &v) const
4D matrix-vector multiplication
Definition: transform.h:231
Normal operator()(const Normal &v) const
Matrix-normal multiplication.
Definition: transform.h:203
#define MTS_NAMESPACE_BEGIN
Definition: platform.h:137
Transform(const Matrix4x4 &trafo)
Create a transform from the given matrix and calculate the inverse.
Definition: transform.h:50
Transform inverse() const
Return the inverse transform.
Definition: transform.h:63
Float det3x3() const
Return the determinant of the upper left 3x3 submatrix.
Definition: transform.h:71
void serialize(Stream *stream) const
Serialize a transformation to a stream.
Definition: transform.h:391
void transformAffine(const Ray &a, Ray &b) const
Transform a ray by an affine / non-projective matrix (no temporaries)
Definition: transform.h:292
void operator()(const Point &p, Point &dest) const
Matrix-vector multiplication for points in 3d space (no temporaries)
Definition: transform.h:152
TPoint3< Float > Point
Definition: fwd.h:136
T z
Definition: vector.h:455
Ray transformAffine(const Ray &ray) const
Transform a ray by an affine / non-projective matrix (no temporaries)
Definition: transform.h:310
Transform(Stream *stream)
Unserialize a transformation from a stream.
Definition: transform.h:42
bool hasScale() const
Test for a scale component.
Definition: transform.h:76
const Matrix4x4 & getMatrix() const
Return the underlying matrix.
Definition: transform.h:317
Ray operator()(const Ray &ray) const
Transform a ray.
Definition: transform.h:285
TVector4< Float > Vector4
Definition: fwd.h:122
Abstract seekable stream class.
Definition: stream.h:58
void transformAffine(const Point &p, Point &dest) const
Transform a point by a affine / non-projective matrix (no temporaries)
Definition: transform.h:139
Warning message.
Definition: formatter.h:32
T x
Definition: vector.h:455
bool isZero() const
Test if this is the zero transformation.
Definition: transform.h:98
Encapsulates a 4x4 linear transformation and its inverse.
Definition: transform.h:33
void operator()(const Normal &v, Normal &dest) const
Matrix-normal multiplication (no temporaries)
Definition: transform.h:217
void operator()(const Ray &a, Ray &b) const
Transform a ray. Assumes that there is no scaling (no temporaries)
Definition: transform.h:262
Definition: fwd.h:65
Definition: fwd.h:96
void operator()(const Vector4 &v, Vector4 &dest) const
4D matrix-vector multiplication (no temporaries)
Definition: transform.h:247
Error message, causes an exception to be thrown.
Definition: formatter.h:33
Basic 4x4 matrix data type.
Definition: matrix.h:656
Point operator()(const Point &p) const
Matrix-vector multiplication for points in 3d space.
Definition: transform.h:108
bool isIdentity() const
Test if this is the identity transformation.
Definition: transform.h:93
Definition: fwd.h:100
Transform()
Create an identity transformation.
Definition: transform.h:36
Definition: fwd.h:97
Vector operator()(const Vector &v) const
Matrix-vector multiplication for vectors in 3d space.
Definition: transform.h:175
bool operator!=(const Transform &trafo) const
Inequality comparison operator.
Definition: transform.h:402
Point transformAffine(const Point &p) const
Transform a point by an affine / non-projective matrix.
Definition: transform.h:128
#define MTS_NAMESPACE_END
Definition: platform.h:138
MTS_EXPORT_CORE bool disableFPExceptions()
Disable floating point exceptions.