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 ¢er ) 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__ */