00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright (c) 2000-2005 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 #ifndef __AxisAlignedBox_H_ 00026 #define __AxisAlignedBox_H_ 00027 00028 // Precompiler options 00029 #include "OgrePrerequisites.h" 00030 00031 #include "OgreVector3.h" 00032 #include "OgreMatrix4.h" 00033 00034 namespace Ogre { 00035 00045 class _OgreExport AxisAlignedBox 00046 { 00047 protected: 00048 Vector3 mMinimum; 00049 Vector3 mMaximum; 00050 bool mNull; 00051 00052 Vector3 mCorners[8]; 00053 00056 void updateCorners(void) 00057 { 00058 // The order of these items is, using right-handed co-ordinates: 00059 // Minimum Z face, starting with Min(all), then anticlockwise 00060 // around face (looking onto the face) 00061 // Maximum Z face, starting with Max(all), then anticlockwise 00062 // around face (looking onto the face) 00063 mCorners[0] = mMinimum; 00064 mCorners[1].x = mMinimum.x; mCorners[1].y = mMaximum.y; mCorners[1].z = mMinimum.z; 00065 mCorners[2].x = mMaximum.x; mCorners[2].y = mMaximum.y; mCorners[2].z = mMinimum.z; 00066 mCorners[3].x = mMaximum.x; mCorners[3].y = mMinimum.y; mCorners[3].z = mMinimum.z; 00067 00068 mCorners[4] = mMaximum; 00069 mCorners[5].x = mMinimum.x; mCorners[5].y = mMaximum.y; mCorners[5].z = mMaximum.z; 00070 mCorners[6].x = mMinimum.x; mCorners[6].y = mMinimum.y; mCorners[6].z = mMaximum.z; 00071 mCorners[7].x = mMaximum.x; mCorners[7].y = mMinimum.y; mCorners[7].z = mMaximum.z; 00072 } 00073 00074 public: 00075 inline AxisAlignedBox() 00076 { 00077 // Default to null box 00078 setMinimum( -0.5, -0.5, -0.5 ); 00079 setMaximum( 0.5, 0.5, 0.5 ); 00080 mNull = true; 00081 } 00082 00083 inline AxisAlignedBox( const Vector3& min, const Vector3& max ) 00084 { 00085 setExtents( min, max ); 00086 } 00087 00088 inline AxisAlignedBox( 00089 Real mx, Real my, Real mz, 00090 Real Mx, Real My, Real Mz ) 00091 { 00092 setExtents( mx, my, mz, Mx, My, Mz ); 00093 } 00094 00097 inline const Vector3& getMinimum(void) const 00098 { 00099 return mMinimum; 00100 } 00101 00104 inline const Vector3& getMaximum(void) const 00105 { 00106 return mMaximum; 00107 } 00108 00111 inline void setMinimum( const Vector3& vec ) 00112 { 00113 mNull = false; 00114 mMinimum = vec; 00115 updateCorners(); 00116 } 00117 00118 inline void setMinimum( Real x, Real y, Real z ) 00119 { 00120 mNull = false; 00121 mMinimum.x = x; 00122 mMinimum.y = y; 00123 mMinimum.z = z; 00124 updateCorners(); 00125 } 00126 00129 inline void setMaximum( const Vector3& vec ) 00130 { 00131 mNull = false; 00132 mMaximum = vec; 00133 updateCorners(); 00134 } 00135 00136 inline void setMaximum( Real x, Real y, Real z ) 00137 { 00138 mNull = false; 00139 mMaximum.x = x; 00140 mMaximum.y = y; 00141 mMaximum.z = z; 00142 updateCorners(); 00143 } 00144 00147 inline void setExtents( const Vector3& min, const Vector3& max ) 00148 { 00149 mNull = false; 00150 mMinimum = min; 00151 mMaximum = max; 00152 updateCorners(); 00153 } 00154 00155 inline void setExtents( 00156 Real mx, Real my, Real mz, 00157 Real Mx, Real My, Real Mz ) 00158 { 00159 mNull = false; 00160 00161 mMinimum.x = mx; 00162 mMinimum.y = my; 00163 mMinimum.z = mz; 00164 00165 mMaximum.x = Mx; 00166 mMaximum.y = My; 00167 mMaximum.z = Mz; 00168 00169 updateCorners(); 00170 } 00171 00195 inline const Vector3* getAllCorners(void) const 00196 { 00197 assert( !mNull && "Can't get corners of a null AAB" ); 00198 return (const Vector3*)mCorners; 00199 } 00200 00201 friend std::ostream& operator<<( std::ostream& o, AxisAlignedBox aab ) 00202 { 00203 if (aab.isNull()) 00204 { 00205 o << "AxisAlignedBox(null)"; 00206 } 00207 else 00208 { 00209 o << "AxisAlignedBox(min=" << aab.mMinimum << ", max=" << aab.mMaximum; 00210 o << ", corners="; 00211 for (int i = 0; i < 7; ++i) 00212 o << aab.mCorners[i] << ", "; 00213 o << aab.mCorners[7] << ")"; 00214 } 00215 return o; 00216 } 00217 00221 void merge( const AxisAlignedBox& rhs ) 00222 { 00223 // Do nothing if rhs null 00224 if (rhs.mNull) 00225 { 00226 return; 00227 } 00228 // Otherwise if current null, just take rhs 00229 else if (mNull) 00230 { 00231 setExtents(rhs.mMinimum, rhs.mMaximum); 00232 } 00233 // Otherwise merge 00234 else 00235 { 00236 Vector3 min = mMinimum; 00237 Vector3 max = mMaximum; 00238 max.makeCeil(rhs.mMaximum); 00239 min.makeFloor(rhs.mMinimum); 00240 00241 setExtents(min, max); 00242 } 00243 00244 } 00245 00248 void merge( const Vector3& point ) 00249 { 00250 if (mNull){ // if null, use this point 00251 setExtents(point, point); 00252 } else { 00253 mMaximum.makeCeil(point); 00254 mMinimum.makeFloor(point); 00255 updateCorners(); 00256 } 00257 } 00258 00268 void transform( const Matrix4& matrix ) 00269 { 00270 // Do nothing if current null 00271 if( mNull ) 00272 return; 00273 00274 Vector3 min, max, temp; 00275 bool first = true; 00276 size_t i; 00277 00278 for( i = 0; i < 8; ++i ) 00279 { 00280 // Transform and check extents 00281 temp = matrix * mCorners[i]; 00282 if( first || temp.x > max.x ) 00283 max.x = temp.x; 00284 if( first || temp.y > max.y ) 00285 max.y = temp.y; 00286 if( first || temp.z > max.z ) 00287 max.z = temp.z; 00288 if( first || temp.x < min.x ) 00289 min.x = temp.x; 00290 if( first || temp.y < min.y ) 00291 min.y = temp.y; 00292 if( first || temp.z < min.z ) 00293 min.z = temp.z; 00294 00295 first = false; 00296 } 00297 00298 setExtents( min,max ); 00299 00300 } 00301 00304 inline void setNull() 00305 { 00306 mNull = true; 00307 } 00308 00311 bool isNull(void) const 00312 { 00313 return mNull; 00314 } 00315 00317 inline bool intersects(const AxisAlignedBox& b2) const 00318 { 00319 // Early-fail for nulls 00320 if (this->isNull() || b2.isNull()) 00321 return false; 00322 00323 // Use up to 6 separating planes 00324 if (mMaximum.x < b2.mMinimum.x) 00325 return false; 00326 if (mMaximum.y < b2.mMinimum.y) 00327 return false; 00328 if (mMaximum.z < b2.mMinimum.z) 00329 return false; 00330 00331 if (mMinimum.x > b2.mMaximum.x) 00332 return false; 00333 if (mMinimum.y > b2.mMaximum.y) 00334 return false; 00335 if (mMinimum.z > b2.mMaximum.z) 00336 return false; 00337 00338 // otherwise, must be intersecting 00339 return true; 00340 00341 } 00342 00344 inline AxisAlignedBox intersection(const AxisAlignedBox& b2) const 00345 { 00346 if (!this->intersects(b2)) 00347 { 00348 return AxisAlignedBox(); 00349 } 00350 Vector3 intMin, intMax; 00351 00352 const Vector3& b2max = b2.getMaximum(); 00353 const Vector3& b2min = b2.getMinimum(); 00354 00355 if (b2max.x > mMaximum.x && mMaximum.x > b2min.x) 00356 intMax.x = mMaximum.x; 00357 else 00358 intMax.x = b2max.x; 00359 if (b2max.y > mMaximum.y && mMaximum.y > b2min.y) 00360 intMax.y = mMaximum.y; 00361 else 00362 intMax.y = b2max.y; 00363 if (b2max.z > mMaximum.z && mMaximum.z > b2min.z) 00364 intMax.z = mMaximum.z; 00365 else 00366 intMax.z = b2max.z; 00367 00368 if (b2min.x < mMinimum.x && mMinimum.x < b2max.x) 00369 intMin.x = mMinimum.x; 00370 else 00371 intMin.x= b2min.x; 00372 if (b2min.y < mMinimum.y && mMinimum.y < b2max.y) 00373 intMin.y = mMinimum.y; 00374 else 00375 intMin.y= b2min.y; 00376 if (b2min.z < mMinimum.z && mMinimum.z < b2max.z) 00377 intMin.z = mMinimum.z; 00378 else 00379 intMin.z= b2min.z; 00380 00381 return AxisAlignedBox(intMin, intMax); 00382 00383 } 00384 00386 Real volume(void) const 00387 { 00388 if (mNull) 00389 { 00390 return 0.0f; 00391 } 00392 else 00393 { 00394 Vector3 diff = mMaximum - mMinimum; 00395 return diff.x * diff.y * diff.z; 00396 } 00397 00398 } 00399 00401 inline void scale(const Vector3& s) 00402 { 00403 // NB assumes centered on origin 00404 Vector3 min = mMinimum * s; 00405 Vector3 max = mMaximum * s; 00406 setExtents(min, max); 00407 } 00408 00410 bool intersects(const Sphere& s) const 00411 { 00412 return Math::intersects(s, *this); 00413 } 00415 bool intersects(const Plane& p) const 00416 { 00417 return Math::intersects(p, *this); 00418 } 00420 bool intersects(const Vector3& v) const 00421 { 00422 return(v.x >= mMinimum.x && v.x <= mMaximum.x && 00423 v.y >= mMinimum.y && v.y <= mMaximum.y && 00424 v.z >= mMinimum.z && v.z <= mMaximum.z); 00425 } 00427 Vector3 getCenter(void) const 00428 { 00429 return Vector3((mMaximum + mMinimum) * 0.5); 00430 } 00431 00432 00433 }; 00434 00435 } // namespace Ogre 00436 00437 #endif
Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Mar 12 14:37:37 2006