Mitsuba Renderer  0.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
aabb.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_AABB_H_)
21 #define __MITSUBA_CORE_AABB_H_
22 
23 #include <mitsuba/core/bsphere.h>
24 
26 
27 /**
28  * \brief Generic multi-dimensional bounding box data structure
29  *
30  * Maintains a component-wise minimum and maximum position and provides
31  * various convenience functions to query or change them.
32  *
33  * \tparam T Underlying point data type (e.g. \c TPoint3<float>)
34  * \ingroup libcore
35  */
36 template <typename T> struct TAABB {
37  typedef T PointType;
38  typedef typename T::Scalar Scalar;
39  typedef typename T::VectorType VectorType;
41 
42  /**
43  * \brief Create a new invalid bounding box
44  *
45  * Initializes the components of the minimum
46  * and maximum position to \f$\infty\f$ and \f$-\infty\f$,
47  * respectively.
48  */
49  inline TAABB() {
50  reset();
51  }
52 
53  /// Unserialize a bounding box from a binary data stream
54  inline TAABB(Stream *stream) {
55  min = PointType(stream);
56  max = PointType(stream);
57  }
58 
59  /// Create a collapsed AABB from a single point
60  inline TAABB(const PointType &p)
61  : min(p), max(p) { }
62 
63  /// Create a bounding box from two positions
64  inline TAABB(const PointType &min, const PointType &max)
65  : min(min), max(max) {
66 #if defined(MTS_DEBUG)
67  for (int i=0; i<PointType::dim; ++i)
68  SAssert(min[i] <= max[i]);
69 #endif
70  }
71 
72  /// Copy constructor
73  inline TAABB(const TAABB &aabb)
74  : min(aabb.min), max(aabb.max) { }
75 
76  /// Equality test
77  inline bool operator==(const TAABB &aabb) const {
78  return min == aabb.min && max == aabb.max;
79  }
80 
81  /// Inequality test
82  inline bool operator!=(const TAABB &aabb) const {
83  return min != aabb.min || max != aabb.max;
84  }
85 
86  /// Clip to another bounding box
87  inline void clip(const TAABB &aabb) {
88  for (int i=0; i<PointType::dim; ++i) {
89  min[i] = std::max(min[i], aabb.min[i]);
90  max[i] = std::min(max[i], aabb.max[i]);
91  }
92  }
93 
94  /**
95  * \brief Mark the bounding box as invalid.
96  *
97  * This operation sets the components of the minimum
98  * and maximum position to \f$\infty\f$ and \f$-\infty\f$,
99  * respectively.
100  */
101  inline void reset() {
102  min = PointType( std::numeric_limits<Scalar>::infinity());
103  max = PointType(-std::numeric_limits<Scalar>::infinity());
104  }
105 
106  /// Calculate the n-dimensional volume of the bounding box
107  inline Scalar getVolume() const {
108  VectorType diff = max-min;
109  Scalar result = diff[0];
110  for (int i=1; i<PointType::dim; ++i)
111  result *= diff[i];
112  return result;
113  }
114 
115  /// Calculate the n-1 dimensional volume of the boundary
116  inline Float getSurfaceArea() const {
117  VectorType d = max - min;
118  Float result = 0.0f;
119  for (int i=0; i<PointType::dim; ++i) {
120  Float term = 1.0f;
121  for (int j=0; j<PointType::dim; ++j) {
122  if (i == j)
123  continue;
124  term *= d[j];
125  }
126  result += term;
127  }
128  return 2.0f * result;
129  }
130 
131  /// Return the center point
132  inline PointType getCenter() const {
133  return (max + min) * (Scalar) 0.5;
134  }
135 
136  /// Return the position of one of the corners (in <tt>0..2^dim-1</tt>)
137  inline PointType getCorner(int index) const {
138  PointType result;
139  for (int d=0; d<PointType::dim; ++d) {
140  if (index & (1 << d))
141  result[d] = max[d];
142  else
143  result[d] = min[d];
144  }
145  return result;
146  }
147 
148  /// Return a child bounding box in a interval-, quad-, octree, etc.
149  inline TAABB getChild(int index) const {
150  TAABB result(getCenter());
151 
152  for (int d=0; d<PointType::dim; ++d) {
153  if (index & (1 << d))
154  result.max[d] = max[d];
155  else
156  result.min[d] = min[d];
157  }
158 
159  return result;
160  }
161 
162  /// Check whether a point lies on or inside the bounding box
163  inline bool contains(const PointType &p) const {
164  for (int i=0; i<PointType::dim; ++i)
165  if (p[i] < min[i] || p[i] > max[i])
166  return false;
167  return true;
168  }
169 
170  /// Check whether a given bounding box is contained within this one
171  inline bool contains(const TAABB &aabb) const {
172  if (!isValid())
173  return false;
174  for (int i=0; i<PointType::dim; ++i)
175  if (aabb.min[i] < min[i] || aabb.max[i] > max[i])
176  return false;
177  return true;
178  }
179 
180  /// Axis-aligned bounding box overlap test
181  inline bool overlaps(const TAABB &aabb) const {
182  for (int i=0; i<PointType::dim; ++i)
183  if (max[i] < aabb.min[i] || min[i] > aabb.max[i])
184  return false;
185  return true;
186  }
187 
188  /// Expand the bounding box to contain another point
189  inline void expandBy(const PointType &p) {
190  for (int i=0; i<PointType::dim; ++i) {
191  min[i] = std::min(min[i], p[i]);
192  max[i] = std::max(max[i], p[i]);
193  }
194  }
195 
196  /// Expand the bounding box to contain another bounding box
197  inline void expandBy(const TAABB &aabb) {
198  for (int i=0; i<PointType::dim; ++i) {
199  min[i] = std::min(min[i], aabb.min[i]);
200  max[i] = std::max(max[i], aabb.max[i]);
201  }
202  }
203 
204  /// Calculate the squared point-AABB distance
205  inline Scalar squaredDistanceTo(const PointType &p) const {
206  Scalar result = 0;
207  for (int i=0; i<PointType::dim; ++i) {
208  Scalar value = 0;
209  if (p[i] < min[i])
210  value = min[i] - p[i];
211  else if (p[i] > max[i])
212  value = p[i] - max[i];
213  result += value*value;
214  }
215  return result;
216  }
217 
218  /// Calculate the point-AABB distance
219  inline Scalar distanceTo(const PointType &p) const {
220  return std::sqrt(squaredDistanceTo(p));
221  }
222 
223  /// Calculate the minimum squared AABB-AABB distance
224  inline Scalar squaredDistanceTo(const TAABB &aabb) const {
225  Scalar result = 0;
226 
227  for (int i=0; i<PointType::dim; ++i) {
228  Scalar value = 0;
229  if (aabb.max[i] < min[i])
230  value = min[i] - aabb.max[i];
231  else if (aabb.min[i] > max[i])
232  value = aabb.min[i] - max[i];
233  result += value*value;
234  }
235  return result;
236  }
237 
238  /// Calculate the minimum AABB-AABB distance
239  inline Scalar distanceTo(const TAABB &aabb) const {
240  return std::sqrt(squaredDistanceTo(aabb));
241  }
242 
243  /// Return whether this bounding box is valid
244  inline bool isValid() const {
245  for (int i=0; i<PointType::dim; ++i)
246  if (max[i] < min[i])
247  return false;
248  return true;
249  }
250 
251  /**
252  * \brief Return whether or not this bounding box
253  * covers anything at all.
254  *
255  * A bounding box which only covers a single point
256  * is considered nonempty.
257  */
258  inline bool isEmpty() const {
259  for (int i=0; i<PointType::dim; ++i) {
260  if (max[i] > min[i])
261  return false;
262  }
263  return true;
264  }
265 
266  /// Return the axis index with the largest associated side length
267  inline int getLargestAxis() const {
268  VectorType d = max - min;
269  int largest = 0;
270 
271  for (int i=1; i<PointType::dim; ++i)
272  if (d[i] > d[largest])
273  largest = i;
274  return largest;
275  }
276 
277  /// Return the axis index with the shortest associated side length
278  inline int getShortestAxis() const {
279  VectorType d = max - min;
280  int shortest = 0;
281 
282  for (int i=1; i<PointType::dim; ++i)
283  if (d[i] < d[shortest])
284  shortest = i;
285  return shortest;
286  }
287 
288  /**
289  * \brief Calculate the bounding box extents
290  * \return max-min
291  */
292  inline VectorType getExtents() const {
293  return max - min;
294  }
295 
296  /** \brief Calculate the near and far ray-AABB intersection
297  * points (if they exist).
298  *
299  * The parameters \c nearT and \c farT are used to return the
300  * ray distances to the intersections (including negative distances).
301  * Any previously contained value is overwritten, even if there was
302  * no intersection.
303  *
304  * \remark In the Python bindings, this function returns the
305  * \c nearT and \c farT values as a tuple (or \c None, when no
306  * intersection was found)
307  */
308  FINLINE bool rayIntersect(const RayType &ray, Float &nearT, Float &farT) const {
309  nearT = -std::numeric_limits<Float>::infinity();
310  farT = std::numeric_limits<Float>::infinity();
311 
312  /* For each pair of AABB planes */
313  for (int i=0; i<PointType::dim; i++) {
314  const Float origin = ray.o[i];
315  const Float minVal = min[i], maxVal = max[i];
316 
317  if (ray.d[i] == 0) {
318  /* The ray is parallel to the planes */
319  if (origin < minVal || origin > maxVal)
320  return false;
321  } else {
322  /* Calculate intersection distances */
323  Float t1 = (minVal - origin) * ray.dRcp[i];
324  Float t2 = (maxVal - origin) * ray.dRcp[i];
325 
326  if (t1 > t2)
327  std::swap(t1, t2);
328 
329  nearT = std::max(t1, nearT);
330  farT = std::min(t2, farT);
331 
332  if (!(nearT <= farT))
333  return false;
334  }
335  }
336 
337  return true;
338  }
339 
340  /** \brief Calculate the overlap between an axis-aligned bounding box
341  * and a ray segment
342  *
343  * This function is an extended version of the simpler \ref rayIntersect command
344  * provided above. The first change is that input values passed via
345  * the \c nearT and \c farT parameters are considered to specify a query interval.
346  *
347  * This interval is intersected against the bounding box, returning the remaining
348  * interval using the \c nearT and \c farT parameters. Furthermore, the
349  * interval endpoints are also returned as 3D positions via the \c near and
350  * \c far parameters. Special care is taken to reduce round-off errors.
351  *
352  * \remark In the Python bindings, this function has the signature
353  * <tt>(nearT, farT, near, far) = rayIntersect(ray, nearT, farT)</tt>.
354  * It returns \c None when no intersection was found.
355  */
356  FINLINE bool rayIntersect(const RayType &ray, Float &nearT, Float &farT, PointType &near, PointType &far) const {
357  int nearAxis = -1, farAxis = -1;
358 
359  /* For each pair of AABB planes */
360  for (int i=0; i<PointType::dim; i++) {
361  const Float origin = ray.o[i];
362  const Float minVal = min[i], maxVal = max[i];
363 
364  if (ray.d[i] == 0) {
365  /* The ray is parallel to the planes */
366  if (origin < minVal || origin > maxVal)
367  return false;
368  } else {
369  /* Calculate intersection distances */
370  Float t1 = (minVal - origin) * ray.dRcp[i];
371  Float t2 = (maxVal - origin) * ray.dRcp[i];
372 
373  bool flip = t1 > t2;
374  if (flip)
375  std::swap(t1, t2);
376 
377  if (t1 > nearT) {
378  nearT = t1;
379  nearAxis = flip ? (i + PointType::dim) : i;
380  }
381 
382  if (t2 < farT) {
383  farT = t2;
384  farAxis = flip ? i : (i + PointType::dim);
385  }
386  }
387  }
388 
389  if (!(nearT <= farT))
390  return false;
391 
392  near = ray(nearT); far = ray(farT);
393 
394  /* Avoid roundoff errors on the component where the intersection took place */
395  if (nearAxis >= 0)
396  near[nearAxis % PointType::dim] = ((Float *) this)[nearAxis];
397 
398  if (farAxis >= 0)
399  far[farAxis % PointType::dim] = ((Float *) this)[farAxis];
400 
401  return true;
402  }
403 
404  /// Serialize this bounding box to a binary data stream
405  inline void serialize(Stream *stream) const {
406  min.serialize(stream);
407  max.serialize(stream);
408  }
409 
410  /// Return a string representation of the bounding box
411  std::string toString() const {
412  std::ostringstream oss;
413  oss << "AABB" << PointType::dim << "[";
414  if (!isValid()) {
415  oss << "invalid";
416  } else {
417  oss << "min=" << min.toString()
418  << ", max=" << max.toString();
419  }
420  oss << "]";
421  return oss.str();
422  }
423 
424  PointType min; ///< Component-wise minimum
425  PointType max; ///< Component-wise maximum
426 };
427 
428 /**
429  * \brief Axis-aligned bounding box data structure in three dimensions
430  *
431  * Maintains a component-wise minimum and maximum position and provides
432  * various convenience functions to query or change them.
433  *
434  * \ingroup libcore
435  * \ingroup libpython
436  */
437 struct AABB : public TAABB<Point> {
438 public:
439  /**
440  * \brief Create a new invalid bounding box
441  *
442  * Initializes the components of the minimum
443  * and maximum position to \f$\infty\f$ and \f$-\infty\f$,
444  * respectively.
445  */
446  inline AABB() : TAABB<Point>() { }
447 
448  /// Unserialize a bounding box from a binary data stream
449  inline AABB(Stream *stream) : TAABB<Point>(stream) { }
450 
451  /// Create a collapsed AABB from a single point
452  inline AABB(const Point &p) : TAABB<Point>(p) { }
453 
454  /// Create a bounding box from two positions
455  inline AABB(const PointType &min, const PointType &max)
456  : TAABB<Point>(min, max) {
457  }
458 
459  /// Construct from a TAABB<Point>
460  inline AABB(const TAABB<Point> &aabb)
461  : TAABB<Point>(aabb) { }
462 
463  /// Calculate the surface area of the bounding box
464  inline Float getSurfaceArea() const {
465  Vector d = max - min;
466  return (Float) 2.0 * (d.x*d.y + d.x*d.z + d.y*d.z);
467  }
468 
469  /**
470  * \brief Return the position of a bounding box corner
471  * \param corner Requested corner index (0..7)
472  */
473  MTS_EXPORT_CORE Point getCorner(uint8_t corner) const;
474 
475  /**
476  * \brief Bounding sphere-box overlap test
477  *
478  * Implements the technique proposed by Jim Arvo in
479  * "A simple method for box-sphere intersection testing"
480  * (Graphics Gems, 1990)
481  */
482  MTS_EXPORT_CORE bool overlaps(const BSphere &sphere) const;
483 
484 #ifdef MTS_SSE
485  /**
486  * \brief Intersect against a packet of four rays.
487  * \return \c false if none of the rays intersect.
488  */
489  FINLINE bool rayIntersectPacket(const RayPacket4 &ray, RayInterval4 &interval) const;
490 #endif
491 
492  /// Create a bounding sphere, which contains the axis-aligned box
493  MTS_EXPORT_CORE BSphere getBSphere() const;
494 };
495 
497 
498 #endif /* __MITSUBA_CORE_AABB_H_ */
TAABB(Stream *stream)
Unserialize a bounding box from a binary data stream.
Definition: aabb.h:54
TAABB(const TAABB &aabb)
Copy constructor.
Definition: aabb.h:73
Float getSurfaceArea() const
Calculate the n-1 dimensional volume of the boundary.
Definition: aabb.h:116
bool operator==(const TAABB &aabb) const
Equality test.
Definition: aabb.h:77
FINLINE bool rayIntersect(const RayType &ray, Float &nearT, Float &farT, PointType &near, PointType &far) const
Calculate the overlap between an axis-aligned bounding box and a ray segment.
Definition: aabb.h:356
Definition: fwd.h:101
bool isEmpty() const
Return whether or not this bounding box covers anything at all.
Definition: aabb.h:258
FINLINE __m128 rayIntersectPacket(const TriAccel &tri, const RayPacket4 &packet, __m128 mint, __m128 maxt, __m128 inactive, Intersection4 &its)
Definition: triaccel_sse.h:27
PointType max
Component-wise maximum.
Definition: aabb.h:425
T PointType
Definition: aabb.h:37
Generic multi-dimensional bounding box data structure.
Definition: aabb.h:36
void expandBy(const PointType &p)
Expand the bounding box to contain another point.
Definition: aabb.h:189
AABB(const PointType &min, const PointType &max)
Create a bounding box from two positions.
Definition: aabb.h:455
void serialize(Stream *stream) const
Serialize this bounding box to a binary data stream.
Definition: aabb.h:405
void reset()
Mark the bounding box as invalid.
Definition: aabb.h:101
void clip(const TAABB &aabb)
Clip to another bounding box.
Definition: aabb.h:87
std::string toString() const
Return a string representation of the bounding box.
Definition: aabb.h:411
Float getSurfaceArea() const
Calculate the surface area of the bounding box.
Definition: aabb.h:464
Bounding sphere data structure in three dimensions.
Definition: bsphere.h:32
#define MTS_EXPORT_CORE
Definition: getopt.h:29
Scalar distanceTo(const TAABB &aabb) const
Calculate the minimum AABB-AABB distance.
Definition: aabb.h:239
TAABB()
Create a new invalid bounding box.
Definition: aabb.h:49
#define MTS_NAMESPACE_BEGIN
Definition: platform.h:137
T::Scalar Scalar
Definition: aabb.h:38
VectorType d
Ray direction.
Definition: ray.h:46
PointType o
Ray origin.
Definition: ray.h:44
TAABB getChild(int index) const
Return a child bounding box in a interval-, quad-, octree, etc.
Definition: aabb.h:149
bool contains(const TAABB &aabb) const
Check whether a given bounding box is contained within this one.
Definition: aabb.h:171
AABB(const Point &p)
Create a collapsed AABB from a single point.
Definition: aabb.h:452
AABB(const TAABB< Point > &aabb)
Construct from a TAABB&lt;Point&gt;
Definition: aabb.h:460
Definition: ray_sse.h:57
Axis-aligned bounding box data structure in three dimensions.
Definition: aabb.h:437
Simple n-dimensional ray data structure with minimum / maximum extent information.
Definition: ray.h:36
void expandBy(const TAABB &aabb)
Expand the bounding box to contain another bounding box.
Definition: aabb.h:197
SIMD quad-packed ray for coherent ray tracing.
Definition: ray_sse.h:34
#define SAssert(cond)
``Static&#39;&#39; assertion (to be used outside of classes that derive from Object)
Definition: logger.h:79
TRay< PointType, VectorType > RayType
Definition: aabb.h:40
Abstract seekable stream class.
Definition: stream.h:58
bool overlaps(const TAABB &aabb) const
Axis-aligned bounding box overlap test.
Definition: aabb.h:181
Scalar squaredDistanceTo(const PointType &p) const
Calculate the squared point-AABB distance.
Definition: aabb.h:205
AABB()
Create a new invalid bounding box.
Definition: aabb.h:446
Definition: fwd.h:96
PointType getCenter() const
Return the center point.
Definition: aabb.h:132
AABB(Stream *stream)
Unserialize a bounding box from a binary data stream.
Definition: aabb.h:449
VectorType getExtents() const
Calculate the bounding box extents.
Definition: aabb.h:292
bool operator!=(const TAABB &aabb) const
Inequality test.
Definition: aabb.h:82
Scalar distanceTo(const PointType &p) const
Calculate the point-AABB distance.
Definition: aabb.h:219
PointType min
Component-wise minimum.
Definition: aabb.h:424
int getLargestAxis() const
Return the axis index with the largest associated side length.
Definition: aabb.h:267
PointType getCorner(int index) const
Return the position of one of the corners (in 0..2^dim-1)
Definition: aabb.h:137
bool contains(const PointType &p) const
Check whether a point lies on or inside the bounding box.
Definition: aabb.h:163
int getShortestAxis() const
Return the axis index with the shortest associated side length.
Definition: aabb.h:278
bool isValid() const
Return whether this bounding box is valid.
Definition: aabb.h:244
Definition: fwd.h:100
Scalar getVolume() const
Calculate the n-dimensional volume of the bounding box.
Definition: aabb.h:107
TAABB(const PointType &min, const PointType &max)
Create a bounding box from two positions.
Definition: aabb.h:64
TAABB(const PointType &p)
Create a collapsed AABB from a single point.
Definition: aabb.h:60
T::VectorType VectorType
Definition: aabb.h:39
#define MTS_NAMESPACE_END
Definition: platform.h:138
VectorType dRcp
Componentwise reciprocals of the ray direction.
Definition: ray.h:48
Scalar squaredDistanceTo(const TAABB &aabb) const
Calculate the minimum squared AABB-AABB distance.
Definition: aabb.h:224
FINLINE bool rayIntersect(const RayType &ray, Float &nearT, Float &farT) const
Calculate the near and far ray-AABB intersection points (if they exist).
Definition: aabb.h:308