vmmlib  1.12.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 <vmmlib/vector.hpp>
36 #include <limits>
37 
38 namespace lunchbox { template< class T > void byteswap( T& ); }
39 
40 namespace vmml
41 {
50 template< typename T > class AABB
51 {
52 public:
54  AABB();
55 
57  AABB( const vector< 3, T >& pMin, const vector< 3, T >& pMax );
58 
60  AABB( const vector< 4, T >& sphere );
61 
63  bool isIn( const vector< 3, T >& point ) const;
64 
66  bool isIn( const vector< 4, T >& sphere ) const;
67 
72  bool isInFront( const vector< 4, T >& plane ) const;
73 
75  const vector< 3, T >& getMin() const;
76 
78  const vector< 3, T >& getMax() const;
79 
81  void merge( const AABB< T >& aabb );
82 
84  void merge( const vector< 3, T >& point );
85 
87  void reset();
88 
90  bool isEmpty() const;
91 
93  bool operator==( const AABB< T >& other ) const;
94 
96  bool operator!=( const AABB< T >& other ) const;
97 
99  vector< 3, T > getCenter() const;
100 
102  vector< 3, T > getSize() const;
103 
108  void computeNearFar( const vector< 4, T >& plane, vector< 3, T >& nearPoint,
109  vector< 3, T >& farPoint ) const;
110 
112  static AABB< T > makeUnitBox();
113 
114 private:
115  vector< 3, T > _min;
116  vector< 3, T > _max;
117  template< class U > friend void lunchbox::byteswap( U& );
118 };
119 
120 template< typename T > inline
121 std::ostream& operator << ( std::ostream& os, const AABB< T >& aabb )
122 {
123  return os << aabb.getMin() << " - " << aabb.getMax();
124 }
125 
126 template< typename T > AABB< T >::AABB()
127  : _min( std::numeric_limits< T >::max( ))
128  , _max( std::numeric_limits< T >::min( ))
129 {}
130 
131 template<> inline AABB< float >::AABB()
132  : _min( std::numeric_limits< float >::max( ))
133  , _max( -std::numeric_limits< float >::max( ))
134 {}
135 
136 template<> inline AABB< double >::AABB()
137  : _min( std::numeric_limits< double >::max( ))
138  , _max( -std::numeric_limits< double >::max( ))
139 {}
140 
141 template< typename T >
143  : _min( vector< 3, T >( std::min( pMin[0], pMax[0] ),
144  std::min( pMin[1], pMax[1] ),
145  std::min( pMin[2], pMax[2] )))
146  , _max( vector< 3, T >( std::max( pMin[0], pMax[0] ),
147  std::max( pMin[1], pMax[1] ),
148  std::max( pMin[2], pMax[2] )))
149 {}
150 
151 template< typename T > AABB< T >::AABB( const vector< 4, T >& sphere )
152 {
153  _max = _min = sphere.getCenter();
154  _max += sphere.getRadius();
155  _min -= sphere.getRadius();
156 }
157 
158 template< typename T > inline bool AABB< T >::isIn( const vector< 3, T >& pos ) const
159 {
160  if ( pos.x() > _max.x() || pos.y() > _max.y() || pos.z() > _max.z() ||
161  pos.x() < _min.x() || pos.y() < _min.y() || pos.z() < _min.z( ))
162  {
163  return false;
164  }
165  return true;
166 }
167 
168 template< typename T > inline
169 bool AABB< T >::isIn( const vector< 4, T >& sphere ) const
170 {
171  const vector< 3, T >& sv = sphere.getCenter();
172  sv += sphere.getRadius();
173  if ( sv.x() > _max.x() || sv.y() > _max.y() || sv.z() > _max.z() )
174  return false;
175  sv -= sphere.getRadius() * 2.0f;
176  if ( sv.x() < _min.x() || sv.y() < _min.y() || sv.z() < _min.z() )
177  return false;
178  return true;
179 }
180 
181 template< typename T > inline
182 bool AABB< T >::isInFront( const vector< 4, T >& plane ) const
183 {
184  const auto& extent = getSize() * 0.5f;
185  const float d = plane.dot( getCenter() );
186  const float n = extent.x() * std::abs( plane.x( )) +
187  extent.y() * std::abs( plane.y( )) +
188  extent.z() * std::abs( plane.z( ));
189 
190  return !( d - n >= 0 || d + n > 0 );
191 }
192 
193 template< typename T > inline const vector< 3, T >& AABB< T >::getMin() const
194 {
195  return _min;
196 }
197 
198 template< typename T > inline const vector< 3, T >& AABB< T >::getMax() const
199 {
200  return _max;
201 }
202 
203 template< typename T > inline
204 bool AABB< T >::operator==( const AABB< T >& other ) const
205 {
206  return _min == other._min && _max == other._max;
207 }
208 
209 template< typename T > inline
210 bool AABB< T >::operator!=( const AABB< T >& other ) const
211 {
212  return _min != other._min || _max != other._max;
213 }
214 
215 template< typename T > vector< 3, T > AABB< T >::getCenter() const
216 {
217  return ( _min + _max ) * 0.5f;
218 }
219 
220 template< typename T > vector< 3, T > AABB< T >::getSize() const
221 {
222  return _max - _min;
223 }
224 
225 template< typename T >
226 void AABB< T >::merge( const AABB<T>& aabb )
227 {
228  const vector< 3, T >& min = aabb.getMin();
229  const vector< 3, T >& max = aabb.getMax();
230 
231  if ( min.x() < _min.x() )
232  _min.x() = min.x();
233  if ( min.y() < _min.y() )
234  _min.y() = min.y();
235  if ( min.z() < _min.z() )
236  _min.z() = min.z();
237 
238  if ( max.x() > _max.x() )
239  _max.x() = max.x();
240  if ( max.y() > _max.y() )
241  _max.y() = max.y();
242  if ( max.z() > _max.z() )
243  _max.z() = max.z();
244 }
245 
246 template< typename T >
247 void AABB< T >::merge( const vector< 3, T >& point )
248 {
249  if ( point.x() < _min.x() )
250  _min.x() = point.x();
251  if ( point.y() < _min.y() )
252  _min.y() = point.y();
253  if ( point.z() < _min.z() )
254  _min.z() = point.z();
255 
256  if ( point.x() > _max.x() )
257  _max.x() = point.x();
258  if ( point.y() > _max.y() )
259  _max.y() = point.y();
260  if ( point.z() > _max.z() )
261  _max.z() = point.z();
262 }
263 
264 template< typename T > inline void AABB< T >::reset()
265 {
266  _min = std::numeric_limits< T >::max();
267  _max = -std::numeric_limits< T >::max();
268 }
269 
270 template< typename T > inline bool AABB< T >::isEmpty() const
271 {
272  return _min.x() >= _max.x() || _min.y() >= _max.y() || _min.z() >= _max.x();
273 }
274 
275 template< typename T > inline void
277  vector< 3, T >& nearPoint,
278  vector< 3, T >& farPoint ) const
279 {
280  for( size_t i = 0; i < 3; ++i )
281  {
282  if( plane[ i ] >= 0.0 )
283  {
284  nearPoint[ i ] = _min[ i ];
285  farPoint[ i ] = _max[ i ];
286  }
287  else
288  {
289  nearPoint[ i ] = _max[ i ];
290  farPoint[ i ] = _min[ i ];
291  }
292  }
293 }
294 
295 template< typename T > AABB< T > AABB< T >::makeUnitBox()
296 {
297  return AABB( vector< 3, T >(), vector< 3, T >( 1 ));
298 }
299 
300 }
301 
302 #endif
bool isIn(const vector< 3, T > &point) const
Definition: aabb.hpp:158
vector< 3, T > getSize() const
Definition: aabb.hpp:220
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:276
static AABB< T > makeUnitBox()
Definition: aabb.hpp:295
bool operator!=(const AABB< T > &other) const
Definition: aabb.hpp:210
heavily inspired by boost::enable_if http://www.boost.org, file: boost/utility/enable_if.hpp, Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine
Definition: aabb.hpp:40
AABB()
Create an empty bounding box.
Definition: aabb.hpp:126
An axis-aligned bounding box.
Definition: aabb.hpp:50
const vector< 3, T > & getMin() const
Definition: aabb.hpp:193
bool operator==(const AABB< T > &other) const
Definition: aabb.hpp:204
bool isInFront(const vector< 4, T > &plane) const
Definition: aabb.hpp:182
bool isEmpty() const
Definition: aabb.hpp:270
void reset()
Clear this bounding box.
Definition: aabb.hpp:264
vector< 3, T > getCenter() const
Definition: aabb.hpp:215
const vector< 3, T > & getMax() const
Definition: aabb.hpp:198
void merge(const AABB< T > &aabb)
Create the union of this and the given bounding box.
Definition: aabb.hpp:226