00001
00002
00008
00009
00011
00012 #ifndef __ICEAABB_H__
00013 #define __ICEAABB_H__
00014
00015
00016 class Sphere;
00017
00019 #define AABB_COMMON_METHODS \
00020 AABB& Add(const AABB& aabb); \
00021 float MakeCube(AABB& cube) const; \
00022 void MakeSphere(Sphere& sphere) const; \
00023 const sbyte* ComputeOutline(const Point& local_eye, sdword& num) const; \
00024 float ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const; \
00025 bool IsInside(const AABB& box) const; \
00026 bool ComputePlanes(Plane* planes) const; \
00027 bool ComputePoints(Point* pts) const; \
00028 const Point* GetVertexNormals() const; \
00029 const udword* GetEdges() const; \
00030 const Point* GetEdgeNormals() const; \
00031 inline_ BOOL ContainsPoint(const Point& p) const \
00032 { \
00033 if(p.x > GetMax(0) || p.x < GetMin(0)) return FALSE; \
00034 if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE; \
00035 if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE; \
00036 return TRUE; \
00037 }
00038
00039 enum AABBType
00040 {
00041 AABB_RENDER = 0,
00042 AABB_UPDATE = 1,
00043
00044 AABB_FORCE_DWORD = 0x7fffffff,
00045 };
00046
00047 #ifdef USE_MINMAX
00048
00049 struct ICEMATHS_API ShadowAABB
00050 {
00051 Point mMin;
00052 Point mMax;
00053 };
00054
00055 class ICEMATHS_API AABB
00056 {
00057 public:
00059 inline_ AABB() {}
00061 inline_ ~AABB() {}
00062
00064 AABB_COMMON_METHODS;
00065
00067
00072
00073 void SetMinMax(const Point& min, const Point& max) { mMin = min; mMax = max; }
00074
00076
00081
00082 void SetCenterExtents(const Point& c, const Point& e) { mMin = c - e; mMax = c + e; }
00083
00085
00088
00089 void SetEmpty() { Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mMin = -p; mMax = p;}
00090
00092
00095
00096 void SetPoint(const Point& pt) { mMin = mMax = pt; }
00097
00099
00103
00104 float GetSize() const { Point e; GetExtents(e); return e.Max(); }
00105
00107
00111
00112 void Extend(const Point& p)
00113 {
00114 if(p.x > mMax.x) mMax.x = p.x;
00115 if(p.x < mMin.x) mMin.x = p.x;
00116
00117 if(p.y > mMax.y) mMax.y = p.y;
00118 if(p.y < mMin.y) mMin.y = p.y;
00119
00120 if(p.z > mMax.z) mMax.z = p.z;
00121 if(p.z < mMin.z) mMin.z = p.z;
00122 }
00123
00124
00126 inline_ void GetMin(Point& min) const { min = mMin; }
00128 inline_ void GetMax(Point& max) const { max = mMax; }
00129
00131 inline_ float GetMin(udword axis) const { return mMin[axis]; }
00133 inline_ float GetMax(udword axis) const { return mMax[axis]; }
00134
00136 inline_ void GetCenter(Point& center) const { center = (mMax + mMin)*0.5f; }
00138 inline_ void GetExtents(Point& extents) const { extents = (mMax - mMin)*0.5f; }
00139
00141 inline_ float GetCenter(udword axis) const { return (mMax[axis] + mMin[axis])*0.5f; }
00143 inline_ float GetExtents(udword axis) const { return (mMax[axis] - mMin[axis])*0.5f; }
00144
00146 inline_ void GetDiagonal(Point& diagonal) const { diagonal = mMax - mMin; }
00147 inline_ float GetWidth() const { return mMax.x - mMin.x; }
00148 inline_ float GetHeight() const { return mMax.y - mMin.y; }
00149 inline_ float GetDepth() const { return mMax.z - mMin.z; }
00150
00152 inline_ float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); }
00153
00155
00160
00161 inline_ BOOL Intersect(const AABB& a) const
00162 {
00163 if(mMax.x < a.mMin.x
00164 || a.mMax.x < mMin.x
00165 || mMax.y < a.mMin.y
00166 || a.mMax.y < mMin.y
00167 || mMax.z < a.mMin.z
00168 || a.mMax.z < mMin.z) return FALSE;
00169
00170 return TRUE;
00171 }
00172
00174
00180
00181 inline_ BOOL Intersect(const AABB& a, udword axis) const
00182 {
00183 if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis]) return FALSE;
00184 return TRUE;
00185 }
00186
00188
00194
00195 inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const
00196 {
00197
00198
00199 Point vx,vy,vz;
00200 mtx.GetRow(0, vx); vx *= (mMax.x - mMin.x);
00201 mtx.GetRow(1, vy); vy *= (mMax.y - mMin.y);
00202 mtx.GetRow(2, vz); vz *= (mMax.z - mMin.z);
00203
00204
00205 aabb.mMin = aabb.mMax = mMin * mtx;
00206
00207
00208
00209 if(IS_NEGATIVE_FLOAT(vx.x)) aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x;
00210 if(IS_NEGATIVE_FLOAT(vx.y)) aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y;
00211 if(IS_NEGATIVE_FLOAT(vx.z)) aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z;
00212 if(IS_NEGATIVE_FLOAT(vy.x)) aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x;
00213 if(IS_NEGATIVE_FLOAT(vy.y)) aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y;
00214 if(IS_NEGATIVE_FLOAT(vy.z)) aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z;
00215 if(IS_NEGATIVE_FLOAT(vz.x)) aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x;
00216 if(IS_NEGATIVE_FLOAT(vz.y)) aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y;
00217 if(IS_NEGATIVE_FLOAT(vz.z)) aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z;
00218 }
00219
00221
00225
00226 inline_ BOOL IsValid() const
00227 {
00228
00229 if(mMin.x > mMax.x) return FALSE;
00230 if(mMin.y > mMax.y) return FALSE;
00231 if(mMin.z > mMax.z) return FALSE;
00232 return TRUE;
00233 }
00234
00236 inline_ AABB& operator*=(float s)
00237 {
00238 Point Center; GetCenter(Center);
00239 Point Extents; GetExtents(Extents);
00240 SetCenterExtents(Center, Extents * s);
00241 return *this;
00242 }
00243
00245 inline_ AABB& operator/=(float s)
00246 {
00247 Point Center; GetCenter(Center);
00248 Point Extents; GetExtents(Extents);
00249 SetCenterExtents(Center, Extents / s);
00250 return *this;
00251 }
00252
00254 inline_ AABB& operator+=(const Point& trans)
00255 {
00256 mMin+=trans;
00257 mMax+=trans;
00258 return *this;
00259 }
00260 private:
00261 Point mMin;
00262 Point mMax;
00263 };
00264
00265 #else
00266
00267 class ICEMATHS_API AABB
00268 {
00269 public:
00271 inline_ AABB() {}
00273 inline_ ~AABB() {}
00274
00276 AABB_COMMON_METHODS;
00277
00279
00284
00285 void SetMinMax(const Point& min, const Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; }
00286
00288
00293
00294 void SetCenterExtents(const Point& c, const Point& e) { mCenter = c; mExtents = e; }
00295
00297
00300
00301 void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);}
00302
00304
00307
00308 void SetPoint(const Point& pt) { mCenter = pt; mExtents.Zero(); }
00309
00311
00315
00316 float GetSize() const { return mExtents.Max(); }
00317
00319
00323
00324 void Extend(const Point& p)
00325 {
00326 Point Max = mCenter + mExtents;
00327 Point Min = mCenter - mExtents;
00328
00329 if(p.x > Max.x) Max.x = p.x;
00330 if(p.x < Min.x) Min.x = p.x;
00331
00332 if(p.y > Max.y) Max.y = p.y;
00333 if(p.y < Min.y) Min.y = p.y;
00334
00335 if(p.z > Max.z) Max.z = p.z;
00336 if(p.z < Min.z) Min.z = p.z;
00337
00338 SetMinMax(Min, Max);
00339 }
00340
00341
00343 inline_ void GetMin(Point& min) const { min = mCenter - mExtents; }
00345 inline_ void GetMax(Point& max) const { max = mCenter + mExtents; }
00346
00348 inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; }
00350 inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; }
00351
00353 inline_ void GetCenter(Point& center) const { center = mCenter; }
00355 inline_ void GetExtents(Point& extents) const { extents = mExtents; }
00356
00358 inline_ float GetCenter(udword axis) const { return mCenter[axis]; }
00360 inline_ float GetExtents(udword axis) const { return mExtents[axis]; }
00361
00363 inline_ void GetDiagonal(Point& diagonal) const { diagonal = mExtents * 2.0f; }
00364 inline_ float GetWidth() const { return mExtents.x * 2.0f; }
00365 inline_ float GetHeight() const { return mExtents.y * 2.0f; }
00366 inline_ float GetDepth() const { return mExtents.z * 2.0f; }
00367
00369 inline_ float GetVolume() const { return mExtents.x * mExtents.y * mExtents.z * 8.0f; }
00370
00372
00377
00378 inline_ BOOL Intersect(const AABB& a) const
00379 {
00380 float tx = mCenter.x - a.mCenter.x; float ex = a.mExtents.x + mExtents.x; if(AIR(tx) > IR(ex)) return FALSE;
00381 float ty = mCenter.y - a.mCenter.y; float ey = a.mExtents.y + mExtents.y; if(AIR(ty) > IR(ey)) return FALSE;
00382 float tz = mCenter.z - a.mCenter.z; float ez = a.mExtents.z + mExtents.z; if(AIR(tz) > IR(ez)) return FALSE;
00383 return TRUE;
00384 }
00385
00387
00392
00393 inline_ bool GomezIntersect(const AABB& a)
00394 {
00395 Point T = mCenter - a.mCenter;
00396 return ((fabsf(T.x) <= (a.mExtents.x + mExtents.x))
00397 && (fabsf(T.y) <= (a.mExtents.y + mExtents.y))
00398 && (fabsf(T.z) <= (a.mExtents.z + mExtents.z)));
00399 }
00400
00402
00408
00409 inline_ BOOL Intersect(const AABB& a, udword axis) const
00410 {
00411 float t = mCenter[axis] - a.mCenter[axis];
00412 float e = a.mExtents[axis] + mExtents[axis];
00413 if(AIR(t) > IR(e)) return FALSE;
00414 return TRUE;
00415 }
00416
00418
00423
00424 inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const
00425 {
00426
00427 aabb.mCenter = mCenter * mtx;
00428
00429
00430 Point Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x);
00431 IR(Ex.x)&=0x7fffffff; IR(Ex.y)&=0x7fffffff; IR(Ex.z)&=0x7fffffff;
00432
00433 Point Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y);
00434 IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff;
00435
00436 Point Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z);
00437 IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff;
00438
00439 aabb.mExtents.x = Ex.x + Ey.x + Ez.x;
00440 aabb.mExtents.y = Ex.y + Ey.y + Ez.y;
00441 aabb.mExtents.z = Ex.z + Ey.z + Ez.z;
00442 }
00443
00445
00449
00450 inline_ BOOL IsValid() const
00451 {
00452
00453 if(IS_NEGATIVE_FLOAT(mExtents.x)) return FALSE;
00454 if(IS_NEGATIVE_FLOAT(mExtents.y)) return FALSE;
00455 if(IS_NEGATIVE_FLOAT(mExtents.z)) return FALSE;
00456 return TRUE;
00457 }
00458
00460 inline_ AABB& operator*=(float s) { mExtents*=s; return *this; }
00461
00463 inline_ AABB& operator/=(float s) { mExtents/=s; return *this; }
00464
00466 inline_ AABB& operator+=(const Point& trans)
00467 {
00468 mCenter+=trans;
00469 return *this;
00470 }
00471 private:
00472 Point mCenter;
00473 Point mExtents;
00474 };
00475
00476 #endif
00477
00478 inline_ void ComputeMinMax(const Point& p, Point& min, Point& max)
00479 {
00480 if(p.x > max.x) max.x = p.x;
00481 if(p.x < min.x) min.x = p.x;
00482
00483 if(p.y > max.y) max.y = p.y;
00484 if(p.y < min.y) min.y = p.y;
00485
00486 if(p.z > max.z) max.z = p.z;
00487 if(p.z < min.z) min.z = p.z;
00488 }
00489
00490 inline_ void ComputeAABB(AABB& aabb, const Point* list, udword nb_pts)
00491 {
00492 if(list)
00493 {
00494 Point Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
00495 Point Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT);
00496 while(nb_pts--)
00497 {
00498
00499 ComputeMinMax(*list++, Mini, Maxi);
00500 }
00501 aabb.SetMinMax(Mini, Maxi);
00502 }
00503 }
00504
00505 #endif // __ICEAABB_H__