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__
17 //! Axis aligned bounding box in 3d dimensional space.
18 /** Has some useful methods used with occlusion culling or clipping.
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
) {}
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
);};
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
)
63 //! Resets the bounding box.
64 void reset(const aabbox3d
<T
>& initValue
)
69 //! Resets the bounding box.
70 void reset(const vector3d
<T
>& 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,
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
,
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
)) )
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
)
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
)
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
)
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
;
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.
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.
251 return MinEdge
.equals ( MaxEdge
);
254 //! repairs the box, if for example MinEdge and MaxEdge are swapped.
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
273 return aabbox3d
<T
>((other
.MinEdge
*inv
) + (MinEdge
*d
),
274 (other
.MaxEdge
*inv
) + (MaxEdge
*d
));
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