Imported more code from the old engine.
[peakengine.git] / engine / include / support / aabbox3d.h
blob2827badb2e891a302c72d8227cba348b04b2f4ed
1 // Copyright (C) 2002-2007 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
5 #ifndef __IRR_AABBOX_3D_H_INCLUDED__
6 #define __IRR_AABBOX_3D_H_INCLUDED__
8 #include "irrMath.h"
9 #include "plane3d.h"
10 #include "line3d.h"
12 namespace irr
14 namespace core
17 //! Axis aligned bounding box in 3d dimensional space.
18 /** Has some useful methods used with occlusion culling or clipping.
20 template <class T>
21 class aabbox3d
23 public:
25 // Constructors
27 aabbox3d(): MinEdge(-1,-1,-1), MaxEdge(1,1,1) {}
28 aabbox3d(const vector3d<T>& min, const vector3d<T>& max): MinEdge(min), MaxEdge(max) {}
29 aabbox3d(const vector3d<T>& init): MinEdge(init), MaxEdge(init) {}
30 aabbox3d(T minx, T miny, T minz, T maxx, T maxy, T maxz): MinEdge(minx, miny, minz), MaxEdge(maxx, maxy, maxz) {}
32 // operators
34 inline bool operator==(const aabbox3d<T>& other) const { return (MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);};
35 inline bool operator!=(const aabbox3d<T>& other) const { return !(MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);};
37 // functions
39 //! Adds a point to the bounding box, causing it to grow bigger,
40 //! if point is outside of the box
41 //! \param p: Point to add into the box.
42 void addInternalPoint(const vector3d<T>& p)
44 addInternalPoint(p.X, p.Y, p.Z);
47 //! Adds an other bounding box to the bounding box, causing it to grow bigger,
48 //! if the box is outside of the box
49 //! \param b: Other bounding box to add into this box.
50 void addInternalBox(const aabbox3d<T>& b)
52 addInternalPoint(b.MaxEdge);
53 addInternalPoint(b.MinEdge);
56 //! Resets the bounding box.
57 void reset(T x, T y, T z)
59 MaxEdge.set(x,y,z);
60 MinEdge = MaxEdge;
63 //! Resets the bounding box.
64 void reset(const aabbox3d<T>& initValue)
66 *this = initValue;
69 //! Resets the bounding box.
70 void reset(const vector3d<T>& initValue)
72 MaxEdge = initValue;
73 MinEdge = initValue;
76 //! Adds a point to the bounding box, causing it to grow bigger,
77 //! if point is outside of the box.
78 //! \param x: X Coordinate of the point to add to this box.
79 //! \param y: Y Coordinate of the point to add to this box.
80 //! \param z: Z Coordinate of the point to add to this box.
81 void addInternalPoint(T x, T y, T z)
83 if (x>MaxEdge.X) MaxEdge.X = x;
84 if (y>MaxEdge.Y) MaxEdge.Y = y;
85 if (z>MaxEdge.Z) MaxEdge.Z = z;
87 if (x<MinEdge.X) MinEdge.X = x;
88 if (y<MinEdge.Y) MinEdge.Y = y;
89 if (z<MinEdge.Z) MinEdge.Z = z;
92 //! Determinates if a point is within this box.
93 //! \param p: Point to check.
94 //! \return Returns true if the point is withing the box, and false if it is not.
95 bool isPointInside(const vector3d<T>& p) const
97 return (p.X >= MinEdge.X && p.X <= MaxEdge.X &&
98 p.Y >= MinEdge.Y && p.Y <= MaxEdge.Y &&
99 p.Z >= MinEdge.Z && p.Z <= MaxEdge.Z);
102 //! Determinates if a point is within this box and its borders.
103 //! \param p: Point to check.
104 //! \return Returns true if the point is withing the box, and false if it is not.
105 bool isPointTotalInside(const vector3d<T>& p) const
107 return (p.X > MinEdge.X && p.X < MaxEdge.X &&
108 p.Y > MinEdge.Y && p.Y < MaxEdge.Y &&
109 p.Z > MinEdge.Z && p.Z < MaxEdge.Z);
112 //! Determinates if the box intersects with an other box.
113 //! \param other: Other box to check a intersection with.
114 //! \return Returns true if there is a intersection with the other box,
115 //! otherwise false.
116 bool intersectsWithBox(const aabbox3d<T>& other) const
118 return (MinEdge <= other.MaxEdge && MaxEdge >= other.MinEdge);
121 //! Returns if this box is completely inside the 'other' box.
122 bool isFullInside(const aabbox3d<T>& other) const
124 return MinEdge >= other.MinEdge && MaxEdge <= other.MaxEdge;
127 //! Tests if the box intersects with a line
128 //! \param line: Line to test intersection with.
129 //! \return Returns true if there is an intersection and false if not.
130 bool intersectsWithLine(const line3d<T>& line) const
132 return intersectsWithLine(line.getMiddle(), line.getVector().normalize(),
133 (T)(line.getLength() * 0.5));
136 //! Tests if the box intersects with a line
137 //! \return Returns true if there is an intersection and false if not.
138 bool intersectsWithLine(const vector3d<T>& linemiddle,
139 const vector3d<T>& linevect,
140 T halflength) const
142 const vector3d<T> e = getExtent() * (T)0.5;
143 const vector3d<T> t = getCenter() - linemiddle;
145 if ((fabs(t.X) > e.X + halflength * fabs(linevect.X)) ||
146 (fabs(t.Y) > e.Y + halflength * fabs(linevect.Y)) ||
147 (fabs(t.Z) > e.Z + halflength * fabs(linevect.Z)) )
148 return false;
150 T r = e.Y * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.Y);
151 if (fabs(t.Y*linevect.Z - t.Z*linevect.Y) > r )
152 return false;
154 r = e.X * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.X);
155 if (fabs(t.Z*linevect.X - t.X*linevect.Z) > r )
156 return false;
158 r = e.X * (T)fabs(linevect.Y) + e.Y * (T)fabs(linevect.X);
159 if (fabs(t.X*linevect.Y - t.Y*linevect.X) > r)
160 return false;
162 return true;
165 //! Classifies a relation with a plane.
166 //! \param plane: Plane to classify relation to.
167 //! \return Returns ISREL3D_FRONT if the box is in front of the plane,
168 //! ISREL3D_BACK if the box is behind the plane, and
169 //! ISREL3D_CLIPPED if it is on both sides of the plane.
170 EIntersectionRelation3D classifyPlaneRelation(const plane3d<T>& plane) const
172 vector3d<T> nearPoint(MaxEdge);
173 vector3d<T> farPoint(MinEdge);
175 if (plane.Normal.X > (T)0)
177 nearPoint.X = MinEdge.X;
178 farPoint.X = MaxEdge.X;
181 if (plane.Normal.Y > (T)0)
183 nearPoint.Y = MinEdge.Y;
184 farPoint.Y = MaxEdge.Y;
187 if (plane.Normal.Z > (T)0)
189 nearPoint.Z = MinEdge.Z;
190 farPoint.Z = MaxEdge.Z;
193 if (plane.Normal.dotProduct(nearPoint) + plane.D > (T)0)
194 return ISREL3D_FRONT;
196 if (plane.Normal.dotProduct(farPoint) + plane.D > (T)0)
197 return ISREL3D_CLIPPED;
199 return ISREL3D_BACK;
203 //! returns center of the bounding box
204 vector3d<T> getCenter() const
206 return (MinEdge + MaxEdge) / 2;
209 //! returns extend of the box
210 vector3d<T> getExtent() const
212 return MaxEdge - MinEdge;
216 //! stores all 8 edges of the box into a array
217 //! \param edges: Pointer to array of 8 edges
218 void getEdges(vector3d<T> *edges) const
220 const core::vector3d<T> middle = getCenter();
221 const core::vector3d<T> diag = middle - MaxEdge;
224 Edges are stored in this way:
225 Hey, am I an ascii artist, or what? :) niko.
226 /3--------/7
227 / | / |
228 / | / |
229 1---------5 |
230 | 2- - -| -6
231 | / | /
232 |/ | /
233 0---------4/
236 edges[0].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z + diag.Z);
237 edges[1].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z + diag.Z);
238 edges[2].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z - diag.Z);
239 edges[3].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z - diag.Z);
240 edges[4].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z + diag.Z);
241 edges[5].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z + diag.Z);
242 edges[6].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z - diag.Z);
243 edges[7].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z - diag.Z);
247 //! returns if the box is empty, which means that there is
248 //! no space within the min and the max edge.
249 bool isEmpty() const
251 return MinEdge.equals ( MaxEdge );
254 //! repairs the box, if for example MinEdge and MaxEdge are swapped.
255 void repair()
257 T t;
259 if (MinEdge.X > MaxEdge.X)
260 { t=MinEdge.X; MinEdge.X = MaxEdge.X; MaxEdge.X=t; }
261 if (MinEdge.Y > MaxEdge.Y)
262 { t=MinEdge.Y; MinEdge.Y = MaxEdge.Y; MaxEdge.Y=t; }
263 if (MinEdge.Z > MaxEdge.Z)
264 { t=MinEdge.Z; MinEdge.Z = MaxEdge.Z; MaxEdge.Z=t; }
267 //! Calculates a new interpolated bounding box.
268 //! \param other: other box to interpolate between
269 //! \param d: value between 0.0f and 1.0f.
270 aabbox3d<T> getInterpolated(const aabbox3d<T>& other, f32 d) const
272 f32 inv = 1.0f - d;
273 return aabbox3d<T>((other.MinEdge*inv) + (MinEdge*d),
274 (other.MaxEdge*inv) + (MaxEdge*d));
277 // member variables
279 vector3d<T> MinEdge;
280 vector3d<T> MaxEdge;
283 //! Typedef for a f32 3d bounding box.
284 typedef aabbox3d<f32> aabbox3df;
285 //! Typedef for an integer 3d bounding box.
286 typedef aabbox3d<s32> aabbox3di;
288 } // end namespace core
289 } // end namespace irr
291 #endif