DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Bounds.h (13695B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #ifndef __BV_BOUNDS_H__
     30 #define __BV_BOUNDS_H__
     31 
     32 /*
     33 ===============================================================================
     34 
     35 	Axis Aligned Bounding Box
     36 
     37 ===============================================================================
     38 */
     39 
     40 class idBounds {
     41 public:
     42 					idBounds();
     43 					explicit idBounds( const idVec3 &mins, const idVec3 &maxs );
     44 					explicit idBounds( const idVec3 &point );
     45 
     46 	const idVec3 &	operator[]( const int index ) const;
     47 	idVec3 &		operator[]( const int index );
     48 	idBounds		operator+( const idVec3 &t ) const;				// returns translated bounds
     49 	idBounds &		operator+=( const idVec3 &t );					// translate the bounds
     50 	idBounds		operator*( const idMat3 &r ) const;				// returns rotated bounds
     51 	idBounds &		operator*=( const idMat3 &r );					// rotate the bounds
     52 	idBounds		operator+( const idBounds &a ) const;
     53 	idBounds &		operator+=( const idBounds &a );
     54 	idBounds		operator-( const idBounds &a ) const;
     55 	idBounds &		operator-=( const idBounds &a );
     56 
     57 	bool			Compare( const idBounds &a ) const;							// exact compare, no epsilon
     58 	bool			Compare( const idBounds &a, const float epsilon ) const;	// compare with epsilon
     59 	bool			operator==(	const idBounds &a ) const;						// exact compare, no epsilon
     60 	bool			operator!=(	const idBounds &a ) const;						// exact compare, no epsilon
     61 
     62 	void			Clear();									// inside out bounds
     63 	void			Zero();									// single point at origin
     64 
     65 	idVec3			GetCenter() const;						// returns center of bounds
     66 	float			GetRadius() const;						// returns the radius relative to the bounds origin
     67 	float			GetRadius( const idVec3 &center ) const;		// returns the radius relative to the given center
     68 	float			GetVolume() const;						// returns the volume of the bounds
     69 	bool			IsCleared() const;						// returns true if bounds are inside out
     70 
     71 	bool			AddPoint( const idVec3 &v );					// add the point, returns true if the bounds expanded
     72 	bool			AddBounds( const idBounds &a );					// add the bounds, returns true if the bounds expanded
     73 	idBounds		Intersect( const idBounds &a ) const;			// return intersection of this bounds with the given bounds
     74 	idBounds &		IntersectSelf( const idBounds &a );				// intersect this bounds with the given bounds
     75 	idBounds		Expand( const float d ) const;					// return bounds expanded in all directions with the given value
     76 	idBounds &		ExpandSelf( const float d );					// expand bounds in all directions with the given value
     77 	idBounds		Translate( const idVec3 &translation ) const;	// return translated bounds
     78 	idBounds &		TranslateSelf( const idVec3 &translation );		// translate this bounds
     79 	idBounds		Rotate( const idMat3 &rotation ) const;			// return rotated bounds
     80 	idBounds &		RotateSelf( const idMat3 &rotation );			// rotate this bounds
     81 
     82 	float			PlaneDistance( const idPlane &plane ) const;
     83 	int				PlaneSide( const idPlane &plane, const float epsilon = ON_EPSILON ) const;
     84 
     85 	bool			ContainsPoint( const idVec3 &p ) const;			// includes touching
     86 	bool			IntersectsBounds( const idBounds &a ) const;	// includes touching
     87 	bool			LineIntersection( const idVec3 &start, const idVec3 &end ) const;
     88 					// intersection point is start + dir * scale
     89 	bool			RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale ) const;
     90 
     91 					// most tight bounds for the given transformed bounds
     92 	void			FromTransformedBounds( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis );
     93 					// most tight bounds for a point set
     94 	void			FromPoints( const idVec3 *points, const int numPoints );
     95 					// most tight bounds for a translation
     96 	void			FromPointTranslation( const idVec3 &point, const idVec3 &translation );
     97 	void			FromBoundsTranslation( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis, const idVec3 &translation );
     98 					// most tight bounds for a rotation
     99 	void			FromPointRotation( const idVec3 &point, const idRotation &rotation );
    100 	void			FromBoundsRotation( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis, const idRotation &rotation );
    101 
    102 	void			ToPoints( idVec3 points[8] ) const;
    103 	idSphere		ToSphere() const;
    104 
    105 	void			AxisProjection( const idVec3 &dir, float &min, float &max ) const;
    106 	void			AxisProjection( const idVec3 &origin, const idMat3 &axis, const idVec3 &dir, float &min, float &max ) const;
    107 
    108 	int				GetDimension() const;
    109 
    110 	const float *	ToFloatPtr() const;
    111 	float *			ToFloatPtr();
    112 
    113 private:
    114 	idVec3			b[2];
    115 };
    116 
    117 extern idBounds	bounds_zero;
    118 extern idBounds bounds_zeroOneCube;
    119 extern idBounds bounds_unitCube;
    120 
    121 ID_INLINE idBounds::idBounds() {
    122 }
    123 
    124 ID_INLINE idBounds::idBounds( const idVec3 &mins, const idVec3 &maxs ) {
    125 	b[0] = mins;
    126 	b[1] = maxs;
    127 }
    128 
    129 ID_INLINE idBounds::idBounds( const idVec3 &point ) {
    130 	b[0] = point;
    131 	b[1] = point;
    132 }
    133 
    134 ID_INLINE const idVec3 &idBounds::operator[]( const int index ) const {
    135 	return b[index];
    136 }
    137 
    138 ID_INLINE idVec3 &idBounds::operator[]( const int index ) {
    139 	return b[index];
    140 }
    141 
    142 ID_INLINE idBounds idBounds::operator+( const idVec3 &t ) const {
    143 	return idBounds( b[0] + t, b[1] + t );
    144 }
    145 
    146 ID_INLINE idBounds &idBounds::operator+=( const idVec3 &t ) {
    147 	b[0] += t;
    148 	b[1] += t;
    149 	return *this;
    150 }
    151 
    152 ID_INLINE idBounds idBounds::operator*( const idMat3 &r ) const {
    153 	idBounds bounds;
    154 	bounds.FromTransformedBounds( *this, vec3_origin, r );
    155 	return bounds;
    156 }
    157 
    158 ID_INLINE idBounds &idBounds::operator*=( const idMat3 &r ) {
    159 	this->FromTransformedBounds( *this, vec3_origin, r );
    160 	return *this;
    161 }
    162 
    163 ID_INLINE idBounds idBounds::operator+( const idBounds &a ) const {
    164 	idBounds newBounds;
    165 	newBounds = *this;
    166 	newBounds.AddBounds( a );
    167 	return newBounds;
    168 }
    169 
    170 ID_INLINE idBounds &idBounds::operator+=( const idBounds &a ) {
    171 	idBounds::AddBounds( a );
    172 	return *this;
    173 }
    174 
    175 ID_INLINE idBounds idBounds::operator-( const idBounds &a ) const {
    176 	assert( b[1][0] - b[0][0] > a.b[1][0] - a.b[0][0] &&
    177 				b[1][1] - b[0][1] > a.b[1][1] - a.b[0][1] &&
    178 					b[1][2] - b[0][2] > a.b[1][2] - a.b[0][2] );
    179 	return idBounds( idVec3( b[0][0] + a.b[1][0], b[0][1] + a.b[1][1], b[0][2] + a.b[1][2] ),
    180 					idVec3( b[1][0] + a.b[0][0], b[1][1] + a.b[0][1], b[1][2] + a.b[0][2] ) );
    181 }
    182 
    183 ID_INLINE idBounds &idBounds::operator-=( const idBounds &a ) {
    184 	assert( b[1][0] - b[0][0] > a.b[1][0] - a.b[0][0] &&
    185 				b[1][1] - b[0][1] > a.b[1][1] - a.b[0][1] &&
    186 					b[1][2] - b[0][2] > a.b[1][2] - a.b[0][2] );
    187 	b[0] += a.b[1];
    188 	b[1] += a.b[0];
    189 	return *this;
    190 }
    191 
    192 ID_INLINE bool idBounds::Compare( const idBounds &a ) const {
    193 	return ( b[0].Compare( a.b[0] ) && b[1].Compare( a.b[1] ) );
    194 }
    195 
    196 ID_INLINE bool idBounds::Compare( const idBounds &a, const float epsilon ) const {
    197 	return ( b[0].Compare( a.b[0], epsilon ) && b[1].Compare( a.b[1], epsilon ) );
    198 }
    199 
    200 ID_INLINE bool idBounds::operator==( const idBounds &a ) const {
    201 	return Compare( a );
    202 }
    203 
    204 ID_INLINE bool idBounds::operator!=( const idBounds &a ) const {
    205 	return !Compare( a );
    206 }
    207 
    208 ID_INLINE void idBounds::Clear() {
    209 	b[0][0] = b[0][1] = b[0][2] = idMath::INFINITY;
    210 	b[1][0] = b[1][1] = b[1][2] = -idMath::INFINITY;
    211 }
    212 
    213 ID_INLINE void idBounds::Zero() {
    214 	b[0][0] = b[0][1] = b[0][2] =
    215 	b[1][0] = b[1][1] = b[1][2] = 0;
    216 }
    217 
    218 ID_INLINE idVec3 idBounds::GetCenter() const {
    219 	return idVec3( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
    220 }
    221 
    222 ID_INLINE float idBounds::GetVolume() const {
    223 	if ( b[0][0] >= b[1][0] || b[0][1] >= b[1][1] || b[0][2] >= b[1][2] ) {
    224 		return 0.0f;
    225 	}
    226 	return ( ( b[1][0] - b[0][0] ) * ( b[1][1] - b[0][1] ) * ( b[1][2] - b[0][2] ) );
    227 }
    228 
    229 ID_INLINE bool idBounds::IsCleared() const {
    230 	return b[0][0] > b[1][0];
    231 }
    232 
    233 ID_INLINE bool idBounds::AddPoint( const idVec3 &v ) {
    234 	bool expanded = false;
    235 	if ( v[0] < b[0][0]) {
    236 		b[0][0] = v[0];
    237 		expanded = true;
    238 	}
    239 	if ( v[0] > b[1][0]) {
    240 		b[1][0] = v[0];
    241 		expanded = true;
    242 	}
    243 	if ( v[1] < b[0][1] ) {
    244 		b[0][1] = v[1];
    245 		expanded = true;
    246 	}
    247 	if ( v[1] > b[1][1]) {
    248 		b[1][1] = v[1];
    249 		expanded = true;
    250 	}
    251 	if ( v[2] < b[0][2] ) {
    252 		b[0][2] = v[2];
    253 		expanded = true;
    254 	}
    255 	if ( v[2] > b[1][2]) {
    256 		b[1][2] = v[2];
    257 		expanded = true;
    258 	}
    259 	return expanded;
    260 }
    261 
    262 ID_INLINE bool idBounds::AddBounds( const idBounds &a ) {
    263 	bool expanded = false;
    264 	if ( a.b[0][0] < b[0][0] ) {
    265 		b[0][0] = a.b[0][0];
    266 		expanded = true;
    267 	}
    268 	if ( a.b[0][1] < b[0][1] ) {
    269 		b[0][1] = a.b[0][1];
    270 		expanded = true;
    271 	}
    272 	if ( a.b[0][2] < b[0][2] ) {
    273 		b[0][2] = a.b[0][2];
    274 		expanded = true;
    275 	}
    276 	if ( a.b[1][0] > b[1][0] ) {
    277 		b[1][0] = a.b[1][0];
    278 		expanded = true;
    279 	}
    280 	if ( a.b[1][1] > b[1][1] ) {
    281 		b[1][1] = a.b[1][1];
    282 		expanded = true;
    283 	}
    284 	if ( a.b[1][2] > b[1][2] ) {
    285 		b[1][2] = a.b[1][2];
    286 		expanded = true;
    287 	}
    288 	return expanded;
    289 }
    290 
    291 ID_INLINE idBounds idBounds::Intersect( const idBounds &a ) const {
    292 	idBounds n;
    293 	n.b[0][0] = ( a.b[0][0] > b[0][0] ) ? a.b[0][0] : b[0][0];
    294 	n.b[0][1] = ( a.b[0][1] > b[0][1] ) ? a.b[0][1] : b[0][1];
    295 	n.b[0][2] = ( a.b[0][2] > b[0][2] ) ? a.b[0][2] : b[0][2];
    296 	n.b[1][0] = ( a.b[1][0] < b[1][0] ) ? a.b[1][0] : b[1][0];
    297 	n.b[1][1] = ( a.b[1][1] < b[1][1] ) ? a.b[1][1] : b[1][1];
    298 	n.b[1][2] = ( a.b[1][2] < b[1][2] ) ? a.b[1][2] : b[1][2];
    299 	return n;
    300 }
    301 
    302 ID_INLINE idBounds &idBounds::IntersectSelf( const idBounds &a ) {
    303 	if ( a.b[0][0] > b[0][0] ) {
    304 		b[0][0] = a.b[0][0];
    305 	}
    306 	if ( a.b[0][1] > b[0][1] ) {
    307 		b[0][1] = a.b[0][1];
    308 	}
    309 	if ( a.b[0][2] > b[0][2] ) {
    310 		b[0][2] = a.b[0][2];
    311 	}
    312 	if ( a.b[1][0] < b[1][0] ) {
    313 		b[1][0] = a.b[1][0];
    314 	}
    315 	if ( a.b[1][1] < b[1][1] ) {
    316 		b[1][1] = a.b[1][1];
    317 	}
    318 	if ( a.b[1][2] < b[1][2] ) {
    319 		b[1][2] = a.b[1][2];
    320 	}
    321 	return *this;
    322 }
    323 
    324 ID_INLINE idBounds idBounds::Expand( const float d ) const {
    325 	return idBounds( idVec3( b[0][0] - d, b[0][1] - d, b[0][2] - d ),
    326 						idVec3( b[1][0] + d, b[1][1] + d, b[1][2] + d ) );
    327 }
    328 
    329 ID_INLINE idBounds &idBounds::ExpandSelf( const float d ) {
    330 	b[0][0] -= d;
    331 	b[0][1] -= d;
    332 	b[0][2] -= d;
    333 	b[1][0] += d;
    334 	b[1][1] += d;
    335 	b[1][2] += d;
    336 	return *this;
    337 }
    338 
    339 ID_INLINE idBounds idBounds::Translate( const idVec3 &translation ) const {
    340 	return idBounds( b[0] + translation, b[1] + translation );
    341 }
    342 
    343 ID_INLINE idBounds &idBounds::TranslateSelf( const idVec3 &translation ) {
    344 	b[0] += translation;
    345 	b[1] += translation;
    346 	return *this;
    347 }
    348 
    349 ID_INLINE idBounds idBounds::Rotate( const idMat3 &rotation ) const {
    350 	idBounds bounds;
    351 	bounds.FromTransformedBounds( *this, vec3_origin, rotation );
    352 	return bounds;
    353 }
    354 
    355 ID_INLINE idBounds &idBounds::RotateSelf( const idMat3 &rotation ) {
    356 	FromTransformedBounds( *this, vec3_origin, rotation );
    357 	return *this;
    358 }
    359 
    360 ID_INLINE bool idBounds::ContainsPoint( const idVec3 &p ) const {
    361 	if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
    362 		|| p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
    363 		return false;
    364 	}
    365 	return true;
    366 }
    367 
    368 ID_INLINE bool idBounds::IntersectsBounds( const idBounds &a ) const {
    369 	if ( a.b[1][0] < b[0][0] || a.b[1][1] < b[0][1] || a.b[1][2] < b[0][2]
    370 		|| a.b[0][0] > b[1][0] || a.b[0][1] > b[1][1] || a.b[0][2] > b[1][2] ) {
    371 		return false;
    372 	}
    373 	return true;
    374 }
    375 
    376 ID_INLINE idSphere idBounds::ToSphere() const {
    377 	idSphere sphere;
    378 	sphere.SetOrigin( ( b[0] + b[1] ) * 0.5f );
    379 	sphere.SetRadius( ( b[1] - sphere.GetOrigin() ).Length() );
    380 	return sphere;
    381 }
    382 
    383 ID_INLINE void idBounds::AxisProjection( const idVec3 &dir, float &min, float &max ) const {
    384 	float d1, d2;
    385 	idVec3 center, extents;
    386 
    387 	center = ( b[0] + b[1] ) * 0.5f;
    388 	extents = b[1] - center;
    389 
    390 	d1 = dir * center;
    391 	d2 = idMath::Fabs( extents[0] * dir[0] ) +
    392 			idMath::Fabs( extents[1] * dir[1] ) +
    393 				idMath::Fabs( extents[2] * dir[2] );
    394 
    395 	min = d1 - d2;
    396 	max = d1 + d2;
    397 }
    398 
    399 ID_INLINE void idBounds::AxisProjection( const idVec3 &origin, const idMat3 &axis, const idVec3 &dir, float &min, float &max ) const {
    400 	float d1, d2;
    401 	idVec3 center, extents;
    402 
    403 	center = ( b[0] + b[1] ) * 0.5f;
    404 	extents = b[1] - center;
    405 	center = origin + center * axis;
    406 
    407 	d1 = dir * center;
    408 	d2 = idMath::Fabs( extents[0] * ( dir * axis[0] ) ) +
    409 			idMath::Fabs( extents[1] * ( dir * axis[1] ) ) +
    410 				idMath::Fabs( extents[2] * ( dir * axis[2] ) );
    411 
    412 	min = d1 - d2;
    413 	max = d1 + d2;
    414 }
    415 
    416 ID_INLINE int idBounds::GetDimension() const {
    417 	return 6;
    418 }
    419 
    420 ID_INLINE const float *idBounds::ToFloatPtr() const {
    421 	return &b[0].x;
    422 }
    423 
    424 ID_INLINE float *idBounds::ToFloatPtr() {
    425 	return &b[0].x;
    426 }
    427 
    428 #endif /* !__BV_BOUNDS_H__ */