Line data Source code
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 : {
42 : /**
43 : * An axis-aligned bounding box.
44 : *
45 : * An empty bounding box has undefined, implementation-specific values. Read
46 : * operations (getMin(), getMax(), getSize(), isIn(), etc.) have undefined
47 : * semantics on an empty bounding box. set() and merge() operations will define
48 : * the bounding box correctly.
49 : */
50 : template< typename T > class AABB
51 : {
52 : public:
53 : /** Create an empty bounding box. */
54 : AABB();
55 :
56 : /** Create a new bounding box from two corner points */
57 : AABB( const vector< 3, T >& pMin, const vector< 3, T >& pMax );
58 :
59 : /** Create a new bounding box from a bounding sphere */
60 : AABB( const vector< 4, T >& sphere );
61 :
62 : /** @return true if the given point is within this bounding box. */
63 : bool isIn( const vector< 3, T >& point ) const;
64 :
65 : /** @return true if the given sphere is within this bounding box. */
66 : bool isIn( const vector< 4, T >& sphere ) const;
67 :
68 : /** @return the minimum corner point */
69 : const vector< 3, T >& getMin() const;
70 :
71 : /** @return the maximum corner point */
72 : const vector< 3, T >& getMax() const;
73 :
74 : /** Create the union of this and the given bounding box */
75 : void merge( const AABB< T >& aabb );
76 :
77 : /** Create the union of this and the given point */
78 : void merge( const vector< 3, T >& point );
79 :
80 : /** Clear this bounding box */
81 : void reset();
82 :
83 : /** @return true if this bounding box has not been set */
84 : bool isEmpty() const;
85 :
86 : /** @return true if this and the other bounding box are identical */
87 : bool operator==( const AABB< T >& other ) const;
88 :
89 : /** @return true if this and the other bounding box are not identical */
90 : bool operator!=( const AABB< T >& other ) const;
91 :
92 : /** @return the center of this bounding box */
93 : vector< 3, T > getCenter() const;
94 :
95 : /** @return the size of this bounding box */
96 : vector< 3, T > getSize() const;
97 :
98 : /**
99 : * Compute the nearest and furthest point of this box relative to the given
100 : * plane.
101 : */
102 : void computeNearFar( const vector< 4, T >& plane, vector< 3, T >& nearPoint,
103 : vector< 3, T >& farPoint ) const;
104 :
105 : /** @return a bouding box of size one with the minimum point at zero. */
106 : static AABB< T > makeUnitBox();
107 :
108 : private:
109 : vector< 3, T > _min;
110 : vector< 3, T > _max;
111 : template< class U > friend void lunchbox::byteswap( U& );
112 : };
113 :
114 : template< typename T > inline
115 0 : std::ostream& operator << ( std::ostream& os, const AABB< T >& aabb )
116 : {
117 0 : return os << aabb.getMin() << " - " << aabb.getMax();
118 : }
119 :
120 : template< typename T > AABB< T >::AABB()
121 : : _min( std::numeric_limits< T >::max( ))
122 : , _max( std::numeric_limits< T >::min( ))
123 : {}
124 :
125 1 : template<> inline AABB< float >::AABB()
126 1 : : _min( std::numeric_limits< float >::max( ))
127 1 : , _max( -std::numeric_limits< float >::max( ))
128 1 : {}
129 :
130 : template<> inline AABB< double >::AABB()
131 : : _min( std::numeric_limits< double >::max( ))
132 : , _max( -std::numeric_limits< double >::max( ))
133 : {}
134 :
135 : template< typename T >
136 7 : AABB< T >::AABB( const vector< 3, T >& pMin, const vector< 3, T >& pMax)
137 7 : : _min( vector< 3, T >( std::min( pMin[0], pMax[0] ),
138 7 : std::min( pMin[1], pMax[1] ),
139 7 : std::min( pMin[2], pMax[2] )))
140 7 : , _max( vector< 3, T >( std::max( pMin[0], pMax[0] ),
141 7 : std::max( pMin[1], pMax[1] ),
142 14 : std::max( pMin[2], pMax[2] )))
143 7 : {}
144 :
145 : template< typename T > AABB< T >::AABB( const vector< 4, T >& sphere )
146 : {
147 : _max = _min = sphere.getCenter();
148 : _max += sphere.getRadius();
149 : _min -= sphere.getRadius();
150 : }
151 :
152 : template< typename T > inline bool AABB< T >::isIn( const vector< 3, T >& pos ) const
153 : {
154 : if ( pos.x() > _max.x() || pos.y() > _max.y() || pos.z() > _max.z() ||
155 : pos.x() < _min.x() || pos.y() < _min.y() || pos.z() < _min.z( ))
156 : {
157 : return false;
158 : }
159 : return true;
160 : }
161 :
162 : template< typename T > inline
163 : bool AABB< T >::isIn( const vector< 4, T >& sphere ) const
164 : {
165 : const vector< 3, T >& sv = sphere.getCenter();
166 : sv += sphere.getRadius();
167 : if ( sv.x() > _max.x() || sv.y() > _max.y() || sv.z() > _max.z() )
168 : return false;
169 : sv -= sphere.getRadius() * 2.0f;
170 : if ( sv.x() < _min.x() || sv.y() < _min.y() || sv.z() < _min.z() )
171 : return false;
172 : return true;
173 : }
174 :
175 4 : template< typename T > inline const vector< 3, T >& AABB< T >::getMin() const
176 : {
177 4 : return _min;
178 : }
179 :
180 4 : template< typename T > inline const vector< 3, T >& AABB< T >::getMax() const
181 : {
182 4 : return _max;
183 : }
184 :
185 : template< typename T > inline
186 1 : bool AABB< T >::operator==( const AABB< T >& other ) const
187 : {
188 1 : return _min == other._min && _max == other._max;
189 : }
190 :
191 : template< typename T > inline
192 : bool AABB< T >::operator!=( const AABB< T >& other ) const
193 : {
194 : return _min != other._min || _max != other._max;
195 : }
196 :
197 6 : template< typename T > vector< 3, T > AABB< T >::getCenter() const
198 : {
199 6 : return ( _min + _max ) * 0.5f;
200 : }
201 :
202 8 : template< typename T > vector< 3, T > AABB< T >::getSize() const
203 : {
204 8 : return _max - _min;
205 : }
206 :
207 : template< typename T >
208 1 : void AABB< T >::merge( const AABB<T>& aabb )
209 : {
210 1 : const vector< 3, T >& min = aabb.getMin();
211 1 : const vector< 3, T >& max = aabb.getMax();
212 :
213 1 : if ( min.x() < _min.x() )
214 1 : _min.x() = min.x();
215 1 : if ( min.y() < _min.y() )
216 1 : _min.y() = min.y();
217 1 : if ( min.z() < _min.z() )
218 1 : _min.z() = min.z();
219 :
220 1 : if ( max.x() > _max.x() )
221 0 : _max.x() = max.x();
222 1 : if ( max.y() > _max.y() )
223 0 : _max.y() = max.y();
224 1 : if ( max.z() > _max.z() )
225 0 : _max.z() = max.z();
226 1 : }
227 :
228 : template< typename T >
229 2 : void AABB< T >::merge( const vector< 3, T >& point )
230 : {
231 2 : if ( point.x() < _min.x() )
232 1 : _min.x() = point.x();
233 2 : if ( point.y() < _min.y() )
234 1 : _min.y() = point.y();
235 2 : if ( point.z() < _min.z() )
236 1 : _min.z() = point.z();
237 :
238 2 : if ( point.x() > _max.x() )
239 2 : _max.x() = point.x();
240 2 : if ( point.y() > _max.y() )
241 2 : _max.y() = point.y();
242 2 : if ( point.z() > _max.z() )
243 2 : _max.z() = point.z();
244 2 : }
245 :
246 : template< typename T > inline void AABB< T >::reset()
247 : {
248 : _min = std::numeric_limits< T >::max();
249 : _max = -std::numeric_limits< T >::max();
250 : }
251 :
252 4 : template< typename T > inline bool AABB< T >::isEmpty() const
253 : {
254 4 : return _min.x() >= _max.x() || _min.y() >= _max.y() || _min.z() >= _max.x();
255 : }
256 :
257 : template< typename T > inline void
258 : AABB< T >::computeNearFar( const vector< 4, T >& plane, vector< 3, T >& nearPoint,
259 : vector< 3, T >& farPoint ) const
260 : {
261 : for( size_t i = 0; i < 3; ++i )
262 : {
263 : if( plane[ i ] >= 0.0 )
264 : {
265 : nearPoint[ i ] = _min[ i ];
266 : farPoint[ i ] = _max[ i ];
267 : }
268 : else
269 : {
270 : nearPoint[ i ] = _max[ i ];
271 : farPoint[ i ] = _min[ i ];
272 : }
273 : }
274 : }
275 :
276 : template< typename T > AABB< T > AABB< T >::makeUnitBox()
277 : {
278 : return AABB( vector< 3, T >::ZERO, vector< 3, T >::ONE );
279 : }
280 :
281 : }
282 :
283 : #endif
|