|
IrrlichtEngine
|
00001 // Copyright (C) 2002-2011 Nikolaus Gebhardt 00002 // This file is part of the "Irrlicht Engine". 00003 // For conditions of distribution and use, see copyright notice in irrlicht.h 00004 00005 #ifndef __IRR_AABBOX_3D_H_INCLUDED__ 00006 #define __IRR_AABBOX_3D_H_INCLUDED__ 00007 00008 #include "irrMath.h" 00009 #include "plane3d.h" 00010 #include "line3d.h" 00011 00012 namespace irr 00013 { 00014 namespace core 00015 { 00016 00018 00020 template <class T> 00021 class aabbox3d 00022 { 00023 public: 00024 00026 aabbox3d(): MinEdge(-1,-1,-1), MaxEdge(1,1,1) {} 00028 aabbox3d(const vector3d<T>& min, const vector3d<T>& max): MinEdge(min), MaxEdge(max) {} 00030 aabbox3d(const vector3d<T>& init): MinEdge(init), MaxEdge(init) {} 00032 aabbox3d(T minx, T miny, T minz, T maxx, T maxy, T maxz): MinEdge(minx, miny, minz), MaxEdge(maxx, maxy, maxz) {} 00033 00034 // operators 00036 00038 inline bool operator==(const aabbox3d<T>& other) const { return (MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);} 00040 00042 inline bool operator!=(const aabbox3d<T>& other) const { return !(MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);} 00043 00044 // functions 00045 00047 00050 void reset(T x, T y, T z) 00051 { 00052 MaxEdge.set(x,y,z); 00053 MinEdge = MaxEdge; 00054 } 00055 00057 00058 void reset(const aabbox3d<T>& initValue) 00059 { 00060 *this = initValue; 00061 } 00062 00064 00065 void reset(const vector3d<T>& initValue) 00066 { 00067 MaxEdge = initValue; 00068 MinEdge = initValue; 00069 } 00070 00072 00074 void addInternalPoint(const vector3d<T>& p) 00075 { 00076 addInternalPoint(p.X, p.Y, p.Z); 00077 } 00078 00080 00082 void addInternalBox(const aabbox3d<T>& b) 00083 { 00084 addInternalPoint(b.MaxEdge); 00085 addInternalPoint(b.MinEdge); 00086 } 00087 00089 00093 void addInternalPoint(T x, T y, T z) 00094 { 00095 if (x>MaxEdge.X) MaxEdge.X = x; 00096 if (y>MaxEdge.Y) MaxEdge.Y = y; 00097 if (z>MaxEdge.Z) MaxEdge.Z = z; 00098 00099 if (x<MinEdge.X) MinEdge.X = x; 00100 if (y<MinEdge.Y) MinEdge.Y = y; 00101 if (z<MinEdge.Z) MinEdge.Z = z; 00102 } 00103 00105 00106 vector3d<T> getCenter() const 00107 { 00108 return (MinEdge + MaxEdge) / 2; 00109 } 00110 00112 00113 vector3d<T> getExtent() const 00114 { 00115 return MaxEdge - MinEdge; 00116 } 00117 00119 00121 bool isEmpty() const 00122 { 00123 return MinEdge.equals ( MaxEdge ); 00124 } 00125 00127 T getVolume() const 00128 { 00129 const vector3d<T> e = getExtent(); 00130 return e.X * e.Y * e.Z; 00131 } 00132 00134 T getArea() const 00135 { 00136 const vector3d<T> e = getExtent(); 00137 return 2*(e.X*e.Y + e.X*e.Z + e.Y*e.Z); 00138 } 00139 00141 00142 void getEdges(vector3d<T> *edges) const 00143 { 00144 const core::vector3d<T> middle = getCenter(); 00145 const core::vector3d<T> diag = middle - MaxEdge; 00146 00147 /* 00148 Edges are stored in this way: 00149 Hey, am I an ascii artist, or what? :) niko. 00150 /3--------/7 00151 / | / | 00152 / | / | 00153 1---------5 | 00154 | /2- - -|- -6 00155 | / | / 00156 |/ | / 00157 0---------4/ 00158 */ 00159 00160 edges[0].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z + diag.Z); 00161 edges[1].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z + diag.Z); 00162 edges[2].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z - diag.Z); 00163 edges[3].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z - diag.Z); 00164 edges[4].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z + diag.Z); 00165 edges[5].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z + diag.Z); 00166 edges[6].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z - diag.Z); 00167 edges[7].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z - diag.Z); 00168 } 00169 00171 00172 void repair() 00173 { 00174 T t; 00175 00176 if (MinEdge.X > MaxEdge.X) 00177 { t=MinEdge.X; MinEdge.X = MaxEdge.X; MaxEdge.X=t; } 00178 if (MinEdge.Y > MaxEdge.Y) 00179 { t=MinEdge.Y; MinEdge.Y = MaxEdge.Y; MaxEdge.Y=t; } 00180 if (MinEdge.Z > MaxEdge.Z) 00181 { t=MinEdge.Z; MinEdge.Z = MaxEdge.Z; MaxEdge.Z=t; } 00182 } 00183 00185 00190 aabbox3d<T> getInterpolated(const aabbox3d<T>& other, f32 d) const 00191 { 00192 f32 inv = 1.0f - d; 00193 return aabbox3d<T>((other.MinEdge*inv) + (MinEdge*d), 00194 (other.MaxEdge*inv) + (MaxEdge*d)); 00195 } 00196 00198 00201 bool isPointInside(const vector3d<T>& p) const 00202 { 00203 return (p.X >= MinEdge.X && p.X <= MaxEdge.X && 00204 p.Y >= MinEdge.Y && p.Y <= MaxEdge.Y && 00205 p.Z >= MinEdge.Z && p.Z <= MaxEdge.Z); 00206 } 00207 00209 00212 bool isPointTotalInside(const vector3d<T>& p) const 00213 { 00214 return (p.X > MinEdge.X && p.X < MaxEdge.X && 00215 p.Y > MinEdge.Y && p.Y < MaxEdge.Y && 00216 p.Z > MinEdge.Z && p.Z < MaxEdge.Z); 00217 } 00218 00220 00223 bool isFullInside(const aabbox3d<T>& other) const 00224 { 00225 return (MinEdge.X >= other.MinEdge.X && MinEdge.Y >= other.MinEdge.Y && MinEdge.Z >= other.MinEdge.Z && 00226 MaxEdge.X <= other.MaxEdge.X && MaxEdge.Y <= other.MaxEdge.Y && MaxEdge.Z <= other.MaxEdge.Z); 00227 } 00228 00230 00233 bool intersectsWithBox(const aabbox3d<T>& other) const 00234 { 00235 return (MinEdge.X <= other.MaxEdge.X && MinEdge.Y <= other.MaxEdge.Y && MinEdge.Z <= other.MaxEdge.Z && 00236 MaxEdge.X >= other.MinEdge.X && MaxEdge.Y >= other.MinEdge.Y && MaxEdge.Z >= other.MinEdge.Z); 00237 } 00238 00240 00242 bool intersectsWithLine(const line3d<T>& line) const 00243 { 00244 return intersectsWithLine(line.getMiddle(), line.getVector().normalize(), 00245 (T)(line.getLength() * 0.5)); 00246 } 00247 00249 00253 bool intersectsWithLine(const vector3d<T>& linemiddle, 00254 const vector3d<T>& linevect, T halflength) const 00255 { 00256 const vector3d<T> e = getExtent() * (T)0.5; 00257 const vector3d<T> t = getCenter() - linemiddle; 00258 00259 if ((fabs(t.X) > e.X + halflength * fabs(linevect.X)) || 00260 (fabs(t.Y) > e.Y + halflength * fabs(linevect.Y)) || 00261 (fabs(t.Z) > e.Z + halflength * fabs(linevect.Z)) ) 00262 return false; 00263 00264 T r = e.Y * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.Y); 00265 if (fabs(t.Y*linevect.Z - t.Z*linevect.Y) > r ) 00266 return false; 00267 00268 r = e.X * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.X); 00269 if (fabs(t.Z*linevect.X - t.X*linevect.Z) > r ) 00270 return false; 00271 00272 r = e.X * (T)fabs(linevect.Y) + e.Y * (T)fabs(linevect.X); 00273 if (fabs(t.X*linevect.Y - t.Y*linevect.X) > r) 00274 return false; 00275 00276 return true; 00277 } 00278 00280 00284 EIntersectionRelation3D classifyPlaneRelation(const plane3d<T>& plane) const 00285 { 00286 vector3d<T> nearPoint(MaxEdge); 00287 vector3d<T> farPoint(MinEdge); 00288 00289 if (plane.Normal.X > (T)0) 00290 { 00291 nearPoint.X = MinEdge.X; 00292 farPoint.X = MaxEdge.X; 00293 } 00294 00295 if (plane.Normal.Y > (T)0) 00296 { 00297 nearPoint.Y = MinEdge.Y; 00298 farPoint.Y = MaxEdge.Y; 00299 } 00300 00301 if (plane.Normal.Z > (T)0) 00302 { 00303 nearPoint.Z = MinEdge.Z; 00304 farPoint.Z = MaxEdge.Z; 00305 } 00306 00307 if (plane.Normal.dotProduct(nearPoint) + plane.D > (T)0) 00308 return ISREL3D_FRONT; 00309 00310 if (plane.Normal.dotProduct(farPoint) + plane.D > (T)0) 00311 return ISREL3D_CLIPPED; 00312 00313 return ISREL3D_BACK; 00314 } 00315 00317 vector3d<T> MinEdge; 00318 00320 vector3d<T> MaxEdge; 00321 }; 00322 00324 typedef aabbox3d<f32> aabbox3df; 00326 typedef aabbox3d<s32> aabbox3di; 00327 00328 } // end namespace core 00329 } // end namespace irr 00330 00331 #endif 00332