00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef __AXISALIGNEDBOX_H_
00026 #define __AXISALIGNEDBOX_H_
00027
00028
00029 #include "peonstdafx.h"
00030
00031 #include "Vector3.h"
00032 #include "Matrix44.h"
00033
00034
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
00062
00063
00064
00065
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
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
00227 if (rhs.mNull)
00228 {
00229 return;
00230 }
00231
00232 else if (mNull)
00233 {
00234 setExtents(rhs.mMinimum, rhs.mMaximum);
00235 }
00236
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){
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
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
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
00323 if (this->isNull() || b2.isNull())
00324 return false;
00325
00326
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
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
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 }
00439
00440 #endif