vmmlib  1.13.0
Templatized C++ vector and matrix math library
aabb.hpp
1 /*
2  * Copyright (c) 2006-2016, Visualization and Multimedia Lab,
3  * University of Zurich <http://vmml.ifi.uzh.ch>,
4  * Eyescale Software GmbH,
5  * Blue Brain Project, EPFL
6  *
7  * This file is part of VMMLib <https://github.com/VMML/vmmlib/>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, 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. Redistributions in binary
14  * form must reproduce the above copyright notice, this list of conditions and
15  * the following disclaimer in the documentation and/or other materials provided
16  * with the distribution. Neither the name of the Visualization and Multimedia
17  * Lab, University of Zurich nor the names of its contributors may be used to
18  * endorse or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 #ifndef __VMML__AXIS_ALIGNED_BOUNDING_BOX__HPP__
33 #define __VMML__AXIS_ALIGNED_BOUNDING_BOX__HPP__
34 
35 #include <limits>
36 #include <vmmlib/vector.hpp>
37 
38 namespace lunchbox
39 {
40 template <class T>
41 void byteswap(T&);
42 }
43 
44 namespace vmml
45 {
46 template <typename T>
47 class AABB;
48 }
49 namespace staticjson
50 {
51 class ObjectHandler;
52 template <typename U>
53 void init(vmml::AABB<U>*, ObjectHandler*);
54 }
55 
56 namespace vmml
57 {
66 template <typename T>
67 class AABB
68 {
69 public:
71  AABB();
72 
74  AABB(const vector<3, T>& pMin, const vector<3, T>& pMax);
75 
77  AABB(const vector<4, T>& sphere);
78 
80  bool isIn(const vector<3, T>& point) const;
81 
83  bool isIn(const vector<4, T>& sphere) const;
84 
89  bool isInFront(const vector<4, T>& plane) const;
90 
92  const vector<3, T>& getMin() const;
93 
95  const vector<3, T>& getMax() const;
96 
98  void merge(const AABB<T>& aabb);
99 
101  void merge(const vector<3, T>& point);
102 
104  void reset();
105 
107  bool isEmpty() const;
108 
110  bool operator==(const AABB<T>& other) const;
111 
113  bool operator!=(const AABB<T>& other) const;
114 
116  vector<3, T> getCenter() const;
117 
119  vector<3, T> getSize() const;
120 
125  void computeNearFar(const vector<4, T>& plane, vector<3, T>& nearPoint,
126  vector<3, T>& farPoint) const;
127 
129  static AABB<T> makeUnitBox();
130 
131 #ifdef __INTEL_COMPILER
132  // For some reason, ICC does not understand the friend declarations and
133  // generates compilation issues. Making the attributes public is not great
134  // but it still is consistent with the rest of the vmmlib library (Vectors
135  // and Quaternions also expose public class members)
136 public:
137  vector<3, T> _min;
138  vector<3, T> _max;
139 #else
140 private:
141  vector<3, T> _min;
142  vector<3, T> _max;
143  template <class U>
144  friend void lunchbox::byteswap(U&);
145  friend void staticjson::init(AABB<float>*, staticjson::ObjectHandler*);
146  friend void staticjson::init(AABB<double>*, staticjson::ObjectHandler*);
147 #endif
148 };
149 
150 template <typename T>
151 inline std::ostream& operator<<(std::ostream& os, const AABB<T>& aabb)
152 {
153  return os << aabb.getMin() << " - " << aabb.getMax();
154 }
155 
156 template <typename T>
158  : _min(std::numeric_limits<T>::max())
159  , _max(std::numeric_limits<T>::min())
160 {
161 }
162 
163 template <>
164 inline AABB<float>::AABB()
165  : _min(std::numeric_limits<float>::max())
166  , _max(-std::numeric_limits<float>::max())
167 {
168 }
169 
170 template <>
171 inline AABB<double>::AABB()
172  : _min(std::numeric_limits<double>::max())
173  , _max(-std::numeric_limits<double>::max())
174 {
175 }
176 
177 template <typename T>
178 AABB<T>::AABB(const vector<3, T>& pMin, const vector<3, T>& pMax)
179  : _min(vector<3, T>(std::min(pMin[0], pMax[0]), std::min(pMin[1], pMax[1]),
180  std::min(pMin[2], pMax[2])))
181  , _max(vector<3, T>(std::max(pMin[0], pMax[0]), std::max(pMin[1], pMax[1]),
182  std::max(pMin[2], pMax[2])))
183 {
184 }
185 
186 template <typename T>
188 {
189  _max = _min = sphere.getCenter();
190  _max += sphere.getRadius();
191  _min -= sphere.getRadius();
192 }
193 
194 template <typename T>
195 inline bool AABB<T>::isIn(const vector<3, T>& pos) const
196 {
197  if (pos.x() > _max.x() || pos.y() > _max.y() || pos.z() > _max.z() ||
198  pos.x() < _min.x() || pos.y() < _min.y() || pos.z() < _min.z())
199  {
200  return false;
201  }
202  return true;
203 }
204 
205 template <typename T>
206 inline bool AABB<T>::isIn(const vector<4, T>& sphere) const
207 {
208  const vector<3, T>& sv = sphere.getCenter();
209  sv += sphere.getRadius();
210  if (sv.x() > _max.x() || sv.y() > _max.y() || sv.z() > _max.z())
211  return false;
212  sv -= sphere.getRadius() * 2.0f;
213  if (sv.x() < _min.x() || sv.y() < _min.y() || sv.z() < _min.z())
214  return false;
215  return true;
216 }
217 
218 template <typename T>
219 inline bool AABB<T>::isInFront(const vector<4, T>& plane) const
220 {
221  const auto& extent = getSize() * 0.5f;
222  const float d = plane.dot(getCenter());
223  const float n = extent.x() * std::abs(plane.x()) +
224  extent.y() * std::abs(plane.y()) +
225  extent.z() * std::abs(plane.z());
226 
227  return !(d - n >= 0 || d + n > 0);
228 }
229 
230 template <typename T>
231 inline const vector<3, T>& AABB<T>::getMin() const
232 {
233  return _min;
234 }
235 
236 template <typename T>
237 inline const vector<3, T>& AABB<T>::getMax() const
238 {
239  return _max;
240 }
241 
242 template <typename T>
243 inline bool AABB<T>::operator==(const AABB<T>& other) const
244 {
245  return _min == other._min && _max == other._max;
246 }
247 
248 template <typename T>
249 inline bool AABB<T>::operator!=(const AABB<T>& other) const
250 {
251  return _min != other._min || _max != other._max;
252 }
253 
254 template <typename T>
256 {
257  return (_min + _max) * 0.5f;
258 }
259 
260 template <typename T>
262 {
263  return _max - _min;
264 }
265 
266 template <typename T>
267 void AABB<T>::merge(const AABB<T>& aabb)
268 {
269  const vector<3, T>& min = aabb.getMin();
270  const vector<3, T>& max = aabb.getMax();
271 
272  if (min.x() < _min.x())
273  _min.x() = min.x();
274  if (min.y() < _min.y())
275  _min.y() = min.y();
276  if (min.z() < _min.z())
277  _min.z() = min.z();
278 
279  if (max.x() > _max.x())
280  _max.x() = max.x();
281  if (max.y() > _max.y())
282  _max.y() = max.y();
283  if (max.z() > _max.z())
284  _max.z() = max.z();
285 }
286 
287 template <typename T>
288 void AABB<T>::merge(const vector<3, T>& point)
289 {
290  if (point.x() < _min.x())
291  _min.x() = point.x();
292  if (point.y() < _min.y())
293  _min.y() = point.y();
294  if (point.z() < _min.z())
295  _min.z() = point.z();
296 
297  if (point.x() > _max.x())
298  _max.x() = point.x();
299  if (point.y() > _max.y())
300  _max.y() = point.y();
301  if (point.z() > _max.z())
302  _max.z() = point.z();
303 }
304 
305 template <typename T>
306 inline void AABB<T>::reset()
307 {
308  _min = std::numeric_limits<T>::max();
309  _max = -std::numeric_limits<T>::max();
310 }
311 
312 template <typename T>
313 inline bool AABB<T>::isEmpty() const
314 {
315  return _min.x() >= _max.x() || _min.y() >= _max.y() || _min.z() >= _max.x();
316 }
317 
318 template <typename T>
319 inline void AABB<T>::computeNearFar(const vector<4, T>& plane,
320  vector<3, T>& nearPoint,
321  vector<3, T>& farPoint) const
322 {
323  for (size_t i = 0; i < 3; ++i)
324  {
325  if (plane[i] >= 0.0)
326  {
327  nearPoint[i] = _min[i];
328  farPoint[i] = _max[i];
329  }
330  else
331  {
332  nearPoint[i] = _max[i];
333  farPoint[i] = _min[i];
334  }
335  }
336 }
337 
338 template <typename T>
340 {
341  return AABB(vector<3, T>(), vector<3, T>(1));
342 }
343 }
344 
345 #endif
bool isIn(const vector< 3, T > &point) const
Definition: aabb.hpp:195
vector< 3, T > getSize() const
Definition: aabb.hpp:261
STL namespace.
void computeNearFar(const vector< 4, T > &plane, vector< 3, T > &nearPoint, vector< 3, T > &farPoint) const
Compute the nearest and furthest point of this box relative to the given plane.
Definition: aabb.hpp:319
static AABB< T > makeUnitBox()
Definition: aabb.hpp:339
bool operator!=(const AABB< T > &other) const
Definition: aabb.hpp:249
Definition: aabb.hpp:44
AABB()
Create an empty bounding box.
Definition: aabb.hpp:157
An axis-aligned bounding box.
Definition: aabb.hpp:47
const vector< 3, T > & getMin() const
Definition: aabb.hpp:231
bool operator==(const AABB< T > &other) const
Definition: aabb.hpp:243
bool isInFront(const vector< 4, T > &plane) const
Definition: aabb.hpp:219
bool isEmpty() const
Definition: aabb.hpp:313
void reset()
Clear this bounding box.
Definition: aabb.hpp:306
vector< 3, T > getCenter() const
Definition: aabb.hpp:255
const vector< 3, T > & getMax() const
Definition: aabb.hpp:237
void merge(const AABB< T > &aabb)
Create the union of this and the given bounding box.
Definition: aabb.hpp:267