Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members

AxisAlignedBox.h

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 "peonstdafx.h"
00030 
00031 #include "Vector3.h"
00032 #include "Matrix44.h"
00033 //#include "Plane.h"
00034 //#include "Sphere.h"
00035 
00036 
00037 namespace peon {
00038 
00048     class _PeonExport AxisAlignedBox
00049     {
00050     protected:
00051             Vector3 mMinimum;
00052             Vector3 mMaximum;
00053             bool mNull;
00054 
00055             Vector3 mCorners[8];
00056 
00059             void updateCorners(void)
00060             {
00061                     // The order of these items is, using right-handed co-ordinates:
00062                     // Minimum Z face, starting with Min(all), then anticlockwise
00063                     //   around face (looking onto the face)
00064                     // Maximum Z face, starting with Max(all), then anticlockwise
00065                     //   around face (looking onto the face)
00066                     mCorners[0] = mMinimum;
00067                     mCorners[1].x = mMinimum.x; mCorners[1].y = mMaximum.y; mCorners[1].z = mMinimum.z;
00068                     mCorners[2].x = mMaximum.x; mCorners[2].y = mMaximum.y; mCorners[2].z = mMinimum.z;
00069                     mCorners[3].x = mMaximum.x; mCorners[3].y = mMinimum.y; mCorners[3].z = mMinimum.z;            
00070 
00071                     mCorners[4] = mMaximum;
00072                     mCorners[5].x = mMinimum.x; mCorners[5].y = mMaximum.y; mCorners[5].z = mMaximum.z;
00073                     mCorners[6].x = mMinimum.x; mCorners[6].y = mMinimum.y; mCorners[6].z = mMaximum.z;
00074                     mCorners[7].x = mMaximum.x; mCorners[7].y = mMinimum.y; mCorners[7].z = mMaximum.z;            
00075             }        
00076 
00077     public:
00078             inline AxisAlignedBox()
00079             {
00080                     // Default to null box
00081                     setMinimum( -0.5, -0.5, -0.5 );
00082                     setMaximum( 0.5, 0.5, 0.5 );
00083                     mNull = true;
00084             }
00085 
00086             inline AxisAlignedBox( const Vector3& min, const Vector3& max )
00087             {
00088                     setExtents( min, max );
00089             }
00090 
00091             inline AxisAlignedBox(
00092                     Real mx, Real my, Real mz,
00093                     Real Mx, Real My, Real Mz )
00094             {
00095                     setExtents( mx, my, mz, Mx, My, Mz );
00096             }
00097 
00100             inline const Vector3& getMinimum(void) const
00101             { 
00102                     return mMinimum; 
00103             }
00104 
00107             inline const Vector3& getMaximum(void) const
00108             { 
00109                     return mMaximum;
00110             }
00111 
00114             inline void setMinimum( const Vector3& vec )
00115             {
00116                     mNull = false;
00117                     mMinimum = vec;
00118                     updateCorners();
00119             }
00120 
00121             inline void setMinimum( Real x, Real y, Real z )
00122             {
00123                     mNull = false;
00124                     mMinimum.x = x;
00125                     mMinimum.y = y;
00126                     mMinimum.z = z;
00127                     updateCorners();
00128             }
00129 
00132             inline void setMaximum( const Vector3& vec )
00133             {
00134                     mNull = false;
00135                     mMaximum = vec;
00136                     updateCorners();
00137             }
00138 
00139             inline void setMaximum( Real x, Real y, Real z )
00140             {
00141                     mNull = false;
00142                     mMaximum.x = x;
00143                     mMaximum.y = y;
00144                     mMaximum.z = z;
00145                     updateCorners();
00146             }
00147 
00150             inline void setExtents( const Vector3& min, const Vector3& max )
00151             {
00152                     mNull = false;
00153                     mMinimum = min;
00154                     mMaximum = max;
00155                     updateCorners();
00156             }
00157 
00158             inline void setExtents(
00159                     Real mx, Real my, Real mz,
00160                     Real Mx, Real My, Real Mz )
00161             {
00162                     mNull = false;
00163 
00164                     mMinimum.x = mx;
00165                     mMinimum.y = my;
00166                     mMinimum.z = mz;
00167 
00168                     mMaximum.x = Mx;
00169                     mMaximum.y = My;
00170                     mMaximum.z = Mz;
00171 
00172                     updateCorners();
00173             }
00174 
00198             inline const Vector3* getAllCorners(void) const
00199             {
00200                     assert( !mNull && "Can't get corners of a null AAB" );
00201                     return (const Vector3*)mCorners;
00202             }
00203 
00204             friend std::ostream& operator<<( std::ostream& o, AxisAlignedBox aab )
00205             {
00206                     if (aab.isNull())
00207                     {
00208                             o << "AxisAlignedBox(null)";
00209                     }
00210                     else
00211                     {
00212                             o << "AxisAlignedBox(min=" << aab.mMinimum << ", max=" << aab.mMaximum;
00213                             o << ", corners=";
00214                             for (int i = 0; i < 7; ++i)
00215                                     o << aab.mCorners[i] << ", ";
00216                             o << aab.mCorners[7] << ")";
00217                     }
00218                     return o;
00219             }
00220 
00224             void merge( const AxisAlignedBox& rhs )
00225             {
00226                     // Do nothing if rhs null
00227                     if (rhs.mNull)
00228                     {
00229                             return;
00230                     }
00231                     // Otherwise if current null, just take rhs
00232                     else if (mNull)
00233                     {
00234                             setExtents(rhs.mMinimum, rhs.mMaximum);
00235                     }
00236                     // Otherwise merge
00237                     else
00238                     {
00239                             Vector3 min = mMinimum;
00240                             Vector3 max = mMaximum;
00241                             max.makeCeil(rhs.mMaximum);
00242                             min.makeFloor(rhs.mMinimum);
00243 
00244                             setExtents(min, max);
00245                     }
00246 
00247             }
00248                 
00251                 void merge( const Vector3& point )
00252                 {
00253                         if (mNull){ // if null, use this point
00254                                 setExtents(point, point);
00255                         } else {
00256                                 mMaximum.makeCeil(point);
00257                                 mMinimum.makeFloor(point);
00258                                 updateCorners();
00259                         }
00260                 }
00261 
00271             void transform( const Matrix44& matrix )
00272             {
00273                     // Do nothing if current null
00274                     if( mNull )
00275                             return;
00276 
00277                     Vector3 min, max, temp;
00278                     bool first = true;
00279                     size_t i;
00280 
00281                     for( i = 0; i < 8; ++i )
00282                     {
00283                             // Transform and check extents
00284                             temp = matrix * mCorners[i];
00285                             if( first || temp.x > max.x )
00286                                     max.x = temp.x;
00287                             if( first || temp.y > max.y )
00288                                     max.y = temp.y;
00289                             if( first || temp.z > max.z )
00290                                     max.z = temp.z;
00291                             if( first || temp.x < min.x )
00292                                     min.x = temp.x;
00293                             if( first || temp.y < min.y )
00294                                     min.y = temp.y;
00295                             if( first || temp.z < min.z )
00296                                     min.z = temp.z;
00297 
00298                             first = false;
00299                     }
00300 
00301                     setExtents( min,max );
00302 
00303             }
00304 
00307             inline void setNull()
00308             {
00309                     mNull = true;
00310             }
00311 
00314             bool isNull(void) const
00315             {
00316                     return mNull;
00317             }
00318 
00320         inline bool intersects(const AxisAlignedBox& b2) const
00321         {
00322             // Early-fail for nulls
00323             if (this->isNull() || b2.isNull())
00324                 return false;
00325 
00326             // Use up to 6 separating planes
00327             if (mMaximum.x < b2.mMinimum.x)
00328                 return false;
00329             if (mMaximum.y < b2.mMinimum.y)
00330                 return false;
00331             if (mMaximum.z < b2.mMinimum.z)
00332                 return false;
00333 
00334             if (mMinimum.x > b2.mMaximum.x)
00335                 return false;
00336             if (mMinimum.y > b2.mMaximum.y)
00337                 return false;
00338             if (mMinimum.z > b2.mMaximum.z)
00339                 return false;
00340 
00341             // otherwise, must be intersecting
00342             return true;
00343 
00344         }
00345 
00347                 inline AxisAlignedBox intersection(const AxisAlignedBox& b2) const
00348                 {
00349                         if (!this->intersects(b2))
00350                         {
00351                                 return AxisAlignedBox();
00352                         }
00353                         Vector3 intMin, intMax;
00354 
00355                         const Vector3& b2max = b2.getMaximum();
00356                         const Vector3& b2min = b2.getMinimum();
00357 
00358                         if (b2max.x > mMaximum.x && mMaximum.x > b2min.x)
00359                                 intMax.x = mMaximum.x;
00360                         else 
00361                                 intMax.x = b2max.x;
00362                         if (b2max.y > mMaximum.y && mMaximum.y > b2min.y)
00363                                 intMax.y = mMaximum.y;
00364                         else 
00365                                 intMax.y = b2max.y;
00366                         if (b2max.z > mMaximum.z && mMaximum.z > b2min.z)
00367                                 intMax.z = mMaximum.z;
00368                         else 
00369                                 intMax.z = b2max.z;
00370 
00371                         if (b2min.x < mMinimum.x && mMinimum.x < b2max.x)
00372                                 intMin.x = mMinimum.x;
00373                         else
00374                                 intMin.x= b2min.x;
00375                         if (b2min.y < mMinimum.y && mMinimum.y < b2max.y)
00376                                 intMin.y = mMinimum.y;
00377                         else
00378                                 intMin.y= b2min.y;
00379                         if (b2min.z < mMinimum.z && mMinimum.z < b2max.z)
00380                                 intMin.z = mMinimum.z;
00381                         else
00382                                 intMin.z= b2min.z;
00383 
00384                         return AxisAlignedBox(intMin, intMax);
00385 
00386                 }
00387 
00389                 Real volume(void) const
00390                 {
00391                         if (mNull)
00392                         {
00393                                 return 0.0f;
00394                         }
00395                         else
00396                         {
00397                                 Vector3 diff = mMaximum - mMinimum;
00398                                 return diff.x * diff.y * diff.z;
00399                         }
00400 
00401                 }
00402 
00404         inline void scale(const Vector3& s)
00405         {
00406             // NB assumes centered on origin
00407             Vector3 min = mMinimum * s;
00408             Vector3 max = mMaximum * s;
00409             setExtents(min, max);
00410         }
00411 
00413                 bool intersects(const Sphere& s) const
00414                 {
00415                         return MathUnit::intersects(s, *this); 
00416                 }
00418                 bool intersects(const Plane& p) const
00419                 {
00420                         return MathUnit::intersects(p, *this);
00421                 }
00423         bool intersects(const Vector3& v) const
00424         {
00425                         return(v.x >= mMinimum.x  &&  v.x <= mMaximum.x  && 
00426                             v.y >= mMinimum.y  &&  v.y <= mMaximum.y  && 
00427                         v.z >= mMinimum.z  &&  v.z <= mMaximum.z);
00428         }
00430                 Vector3 getCenter(void) const
00431                 {
00432                         return Vector3((mMaximum + mMinimum) * 0.5);
00433                 }
00434 
00435 
00436     };
00437 
00438 } // namespace peon
00439 
00440 #endif

Generated on Wed Nov 9 09:37:05 2005 for Peon by  doxygen 1.4.3