1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3 * Contains AABB-related code. (axis-aligned bounding box)
5 * \author Pierre Terdiman
6 * \date January, 13, 2000
8 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
15 // Forward declarations
18 //! Declarations of type-independent methods (most of them implemented in the .cpp)
19 #define AABB_COMMON_METHODS \
20 AABB& Add(const AABB& aabb); \
21 float MakeCube(AABB& cube) const; \
22 void MakeSphere(Sphere& sphere) const; \
23 const sbyte* ComputeOutline(const Point& local_eye, sdword& num) const; \
24 float ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const; \
25 bool IsInside(const AABB& box) const; \
26 bool ComputePlanes(Plane* planes) const; \
27 bool ComputePoints(Point* pts) const; \
28 const Point* GetVertexNormals() const; \
29 const udword* GetEdges() const; \
30 const Point* GetEdgeNormals() const; \
31 inline_ BOOL ContainsPoint(const Point& p) const \
33 if(p.x > GetMax(0) || p.x < GetMin(0)) return FALSE; \
34 if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE; \
35 if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE; \
41 AABB_RENDER
= 0, //!< AABB used for rendering. Not visible == not rendered.
42 AABB_UPDATE
= 1, //!< AABB used for dynamic updates. Not visible == not updated.
44 AABB_FORCE_DWORD
= 0x7fffffff,
49 struct ICEMATHS_API ShadowAABB
55 class ICEMATHS_API AABB
63 //! Type-independent methods
66 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
68 * Setups an AABB from min & max vectors.
69 * \param min [in] the min point
70 * \param max [in] the max point
72 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
73 void SetMinMax(const Point
& min
, const Point
& max
) { mMin
= min
; mMax
= max
; }
75 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
77 * Setups an AABB from center & extents vectors.
78 * \param c [in] the center point
79 * \param e [in] the extents vector
81 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
82 void SetCenterExtents(const Point
& c
, const Point
& e
) { mMin
= c
- e
; mMax
= c
+ e
; }
84 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
86 * Setups an empty AABB.
88 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89 void SetEmpty() { Point
p(MIN_FLOAT
, MIN_FLOAT
, MIN_FLOAT
); mMin
= -p
; mMax
= p
;}
91 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93 * Setups a point AABB.
95 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
96 void SetPoint(const Point
& pt
) { mMin
= mMax
= pt
; }
98 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
100 * Gets the size of the AABB. The size is defined as the longest extent.
101 * \return the size of the AABB
103 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104 float GetSize() const { Point e
; GetExtents(e
); return e
.Max(); }
106 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
109 * \param p [in] the next point
111 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112 void Extend(const Point
& p
)
114 if(p
.x
> mMax
.x
) mMax
.x
= p
.x
;
115 if(p
.x
< mMin
.x
) mMin
.x
= p
.x
;
117 if(p
.y
> mMax
.y
) mMax
.y
= p
.y
;
118 if(p
.y
< mMin
.y
) mMin
.y
= p
.y
;
120 if(p
.z
> mMax
.z
) mMax
.z
= p
.z
;
121 if(p
.z
< mMin
.z
) mMin
.z
= p
.z
;
125 //! Get min point of the box
126 inline_
void GetMin(Point
& min
) const { min
= mMin
; }
127 //! Get max point of the box
128 inline_
void GetMax(Point
& max
) const { max
= mMax
; }
130 //! Get component of the box's min point along a given axis
131 inline_
float GetMin(udword axis
) const { return mMin
[axis
]; }
132 //! Get component of the box's max point along a given axis
133 inline_
float GetMax(udword axis
) const { return mMax
[axis
]; }
136 inline_
void GetCenter(Point
& center
) const { center
= (mMax
+ mMin
)*0.5f
; }
138 inline_
void GetExtents(Point
& extents
) const { extents
= (mMax
- mMin
)*0.5f
; }
140 //! Get component of the box's center along a given axis
141 inline_
float GetCenter(udword axis
) const { return (mMax
[axis
] + mMin
[axis
])*0.5f
; }
142 //! Get component of the box's extents along a given axis
143 inline_
float GetExtents(udword axis
) const { return (mMax
[axis
] - mMin
[axis
])*0.5f
; }
146 inline_
void GetDiagonal(Point
& diagonal
) const { diagonal
= mMax
- mMin
; }
147 inline_
float GetWidth() const { return mMax
.x
- mMin
.x
; }
148 inline_
float GetHeight() const { return mMax
.y
- mMin
.y
; }
149 inline_
float GetDepth() const { return mMax
.z
- mMin
.z
; }
152 inline_
float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); }
154 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156 * Computes the intersection between two AABBs.
157 * \param a [in] the other AABB
158 * \return true on intersection
160 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
161 inline_ BOOL
Intersect(const AABB
& a
) const
168 || a
.mMax
.z
< mMin
.z
) return FALSE
;
173 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
175 * Computes the 1D-intersection between two AABBs, on a given axis.
176 * \param a [in] the other AABB
177 * \param axis [in] the axis (0, 1, 2)
178 * \return true on intersection
180 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181 inline_ BOOL
Intersect(const AABB
& a
, udword axis
) const
183 if(mMax
[axis
] < a
.mMin
[axis
] || a
.mMax
[axis
] < mMin
[axis
]) return FALSE
;
187 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
189 * Recomputes the AABB after an arbitrary transform by a 4x4 matrix.
190 * Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it)
191 * \param mtx [in] the transform matrix
192 * \param aabb [out] the transformed AABB [can be *this]
194 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
195 inline_
void Rotate(const Matrix4x4
& mtx
, AABB
& aabb
) const
197 // The three edges transformed: you can efficiently transform an X-only vector
198 // by just getting the "X" column of the matrix
200 mtx
.GetRow(0, vx
); vx
*= (mMax
.x
- mMin
.x
);
201 mtx
.GetRow(1, vy
); vy
*= (mMax
.y
- mMin
.y
);
202 mtx
.GetRow(2, vz
); vz
*= (mMax
.z
- mMin
.z
);
204 // Transform the min point
205 aabb
.mMin
= aabb
.mMax
= mMin
* mtx
;
207 // Take the transformed min & axes and find new extents
208 // Using CPU code in the right place is faster...
209 if(IS_NEGATIVE_FLOAT(vx
.x
)) aabb
.mMin
.x
+= vx
.x
; else aabb
.mMax
.x
+= vx
.x
;
210 if(IS_NEGATIVE_FLOAT(vx
.y
)) aabb
.mMin
.y
+= vx
.y
; else aabb
.mMax
.y
+= vx
.y
;
211 if(IS_NEGATIVE_FLOAT(vx
.z
)) aabb
.mMin
.z
+= vx
.z
; else aabb
.mMax
.z
+= vx
.z
;
212 if(IS_NEGATIVE_FLOAT(vy
.x
)) aabb
.mMin
.x
+= vy
.x
; else aabb
.mMax
.x
+= vy
.x
;
213 if(IS_NEGATIVE_FLOAT(vy
.y
)) aabb
.mMin
.y
+= vy
.y
; else aabb
.mMax
.y
+= vy
.y
;
214 if(IS_NEGATIVE_FLOAT(vy
.z
)) aabb
.mMin
.z
+= vy
.z
; else aabb
.mMax
.z
+= vy
.z
;
215 if(IS_NEGATIVE_FLOAT(vz
.x
)) aabb
.mMin
.x
+= vz
.x
; else aabb
.mMax
.x
+= vz
.x
;
216 if(IS_NEGATIVE_FLOAT(vz
.y
)) aabb
.mMin
.y
+= vz
.y
; else aabb
.mMax
.y
+= vz
.y
;
217 if(IS_NEGATIVE_FLOAT(vz
.z
)) aabb
.mMin
.z
+= vz
.z
; else aabb
.mMax
.z
+= vz
.z
;
220 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
222 * Checks the AABB is valid.
223 * \return true if the box is valid
225 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
226 inline_ BOOL
IsValid() const
228 // Consistency condition for (Min, Max) boxes: min < max
229 if(mMin
.x
> mMax
.x
) return FALSE
;
230 if(mMin
.y
> mMax
.y
) return FALSE
;
231 if(mMin
.z
> mMax
.z
) return FALSE
;
235 //! Operator for AABB *= float. Scales the extents, keeps same center.
236 inline_ AABB
& operator*=(float s
)
238 Point Center
; GetCenter(Center
);
239 Point Extents
; GetExtents(Extents
);
240 SetCenterExtents(Center
, Extents
* s
);
244 //! Operator for AABB /= float. Scales the extents, keeps same center.
245 inline_ AABB
& operator/=(float s
)
247 Point Center
; GetCenter(Center
);
248 Point Extents
; GetExtents(Extents
);
249 SetCenterExtents(Center
, Extents
/ s
);
253 //! Operator for AABB += Point. Translates the box.
254 inline_ AABB
& operator+=(const Point
& trans
)
261 Point mMin
; //!< Min point
262 Point mMax
; //!< Max point
267 class ICEMATHS_API AABB
275 //! Type-independent methods
278 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
280 * Setups an AABB from min & max vectors.
281 * \param min [in] the min point
282 * \param max [in] the max point
284 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
285 void SetMinMax(const Point
& min
, const Point
& max
) { mCenter
= (max
+ min
)*0.5f
; mExtents
= (max
- min
)*0.5f
; }
287 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
289 * Setups an AABB from center & extents vectors.
290 * \param c [in] the center point
291 * \param e [in] the extents vector
293 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
294 void SetCenterExtents(const Point
& c
, const Point
& e
) { mCenter
= c
; mExtents
= e
; }
296 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
298 * Setups an empty AABB.
300 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
301 void SetEmpty() { mCenter
.Zero(); mExtents
.Set(MIN_FLOAT
, MIN_FLOAT
, MIN_FLOAT
);}
303 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
305 * Setups a point AABB.
307 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
308 void SetPoint(const Point
& pt
) { mCenter
= pt
; mExtents
.Zero(); }
310 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
312 * Gets the size of the AABB. The size is defined as the longest extent.
313 * \return the size of the AABB
315 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
316 float GetSize() const { return mExtents
.Max(); }
318 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
321 * \param p [in] the next point
323 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
324 void Extend(const Point
& p
)
326 Point Max
= mCenter
+ mExtents
;
327 Point Min
= mCenter
- mExtents
;
329 if(p
.x
> Max
.x
) Max
.x
= p
.x
;
330 if(p
.x
< Min
.x
) Min
.x
= p
.x
;
332 if(p
.y
> Max
.y
) Max
.y
= p
.y
;
333 if(p
.y
< Min
.y
) Min
.y
= p
.y
;
335 if(p
.z
> Max
.z
) Max
.z
= p
.z
;
336 if(p
.z
< Min
.z
) Min
.z
= p
.z
;
342 //! Get min point of the box
343 inline_
void GetMin(Point
& min
) const { min
= mCenter
- mExtents
; }
344 //! Get max point of the box
345 inline_
void GetMax(Point
& max
) const { max
= mCenter
+ mExtents
; }
347 //! Get component of the box's min point along a given axis
348 inline_
float GetMin(udword axis
) const { return mCenter
[axis
] - mExtents
[axis
]; }
349 //! Get component of the box's max point along a given axis
350 inline_
float GetMax(udword axis
) const { return mCenter
[axis
] + mExtents
[axis
]; }
353 inline_
void GetCenter(Point
& center
) const { center
= mCenter
; }
355 inline_
void GetExtents(Point
& extents
) const { extents
= mExtents
; }
357 //! Get component of the box's center along a given axis
358 inline_
float GetCenter(udword axis
) const { return mCenter
[axis
]; }
359 //! Get component of the box's extents along a given axis
360 inline_
float GetExtents(udword axis
) const { return mExtents
[axis
]; }
363 inline_
void GetDiagonal(Point
& diagonal
) const { diagonal
= mExtents
* 2.0f
; }
364 inline_
float GetWidth() const { return mExtents
.x
* 2.0f
; }
365 inline_
float GetHeight() const { return mExtents
.y
* 2.0f
; }
366 inline_
float GetDepth() const { return mExtents
.z
* 2.0f
; }
369 inline_
float GetVolume() const { return mExtents
.x
* mExtents
.y
* mExtents
.z
* 8.0f
; }
371 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
373 * Computes the intersection between two AABBs.
374 * \param a [in] the other AABB
375 * \return true on intersection
377 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
378 inline_ BOOL
Intersect(const AABB
& a
) const
380 float tx
= mCenter
.x
- a
.mCenter
.x
; float ex
= a
.mExtents
.x
+ mExtents
.x
; if(AIR(tx
) > IR(ex
)) return FALSE
;
381 float ty
= mCenter
.y
- a
.mCenter
.y
; float ey
= a
.mExtents
.y
+ mExtents
.y
; if(AIR(ty
) > IR(ey
)) return FALSE
;
382 float tz
= mCenter
.z
- a
.mCenter
.z
; float ez
= a
.mExtents
.z
+ mExtents
.z
; if(AIR(tz
) > IR(ez
)) return FALSE
;
386 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
388 * The standard intersection method from Gamasutra. Just here to check its speed against the one above.
389 * \param a [in] the other AABB
390 * \return true on intersection
392 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
393 inline_
bool GomezIntersect(const AABB
& a
)
395 Point T
= mCenter
- a
.mCenter
; // Vector from A to B
396 return ((fabsf(T
.x
) <= (a
.mExtents
.x
+ mExtents
.x
))
397 && (fabsf(T
.y
) <= (a
.mExtents
.y
+ mExtents
.y
))
398 && (fabsf(T
.z
) <= (a
.mExtents
.z
+ mExtents
.z
)));
401 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
403 * Computes the 1D-intersection between two AABBs, on a given axis.
404 * \param a [in] the other AABB
405 * \param axis [in] the axis (0, 1, 2)
406 * \return true on intersection
408 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
409 inline_ BOOL
Intersect(const AABB
& a
, udword axis
) const
411 float t
= mCenter
[axis
] - a
.mCenter
[axis
];
412 float e
= a
.mExtents
[axis
] + mExtents
[axis
];
413 if(AIR(t
) > IR(e
)) return FALSE
;
417 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
419 * Recomputes the AABB after an arbitrary transform by a 4x4 matrix.
420 * \param mtx [in] the transform matrix
421 * \param aabb [out] the transformed AABB [can be *this]
423 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
424 inline_
void Rotate(const Matrix4x4
& mtx
, AABB
& aabb
) const
426 // Compute new center
427 aabb
.mCenter
= mCenter
* mtx
;
429 // Compute new extents. FPU code & CPU code have been interleaved for improved performance.
430 Point
Ex(mtx
.m
[0][0] * mExtents
.x
, mtx
.m
[0][1] * mExtents
.x
, mtx
.m
[0][2] * mExtents
.x
);
431 //IR(Ex.x)&=0x7fffffff; IR(Ex.y)&=0x7fffffff; IR(Ex.z)&=0x7fffffff;
432 Ex
.x
= FR( AIR(Ex
.x
) );
433 Ex
.y
= FR( AIR(Ex
.y
) );
434 Ex
.z
= FR( AIR(Ex
.z
) );
436 Point
Ey(mtx
.m
[1][0] * mExtents
.y
, mtx
.m
[1][1] * mExtents
.y
, mtx
.m
[1][2] * mExtents
.y
);
437 //IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff;
438 Ey
.x
= FR( AIR(Ey
.x
) );
439 Ey
.y
= FR( AIR(Ey
.y
) );
440 Ey
.z
= FR( AIR(Ey
.z
) );
442 Point
Ez(mtx
.m
[2][0] * mExtents
.z
, mtx
.m
[2][1] * mExtents
.z
, mtx
.m
[2][2] * mExtents
.z
);
443 //IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff;
444 Ez
.x
= FR( AIR(Ez
.x
) );
445 Ez
.y
= FR( AIR(Ez
.y
) );
446 Ez
.z
= FR( AIR(Ez
.z
) );
448 aabb
.mExtents
.x
= Ex
.x
+ Ey
.x
+ Ez
.x
;
449 aabb
.mExtents
.y
= Ex
.y
+ Ey
.y
+ Ez
.y
;
450 aabb
.mExtents
.z
= Ex
.z
+ Ey
.z
+ Ez
.z
;
453 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
455 * Checks the AABB is valid.
456 * \return true if the box is valid
458 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
459 inline_ BOOL
IsValid() const
461 // Consistency condition for (Center, Extents) boxes: Extents >= 0
462 if(IS_NEGATIVE_FLOAT(mExtents
.x
)) return FALSE
;
463 if(IS_NEGATIVE_FLOAT(mExtents
.y
)) return FALSE
;
464 if(IS_NEGATIVE_FLOAT(mExtents
.z
)) return FALSE
;
468 //! Operator for AABB *= float. Scales the extents, keeps same center.
469 inline_ AABB
& operator*=(float s
) { mExtents
*=s
; return *this; }
471 //! Operator for AABB /= float. Scales the extents, keeps same center.
472 inline_ AABB
& operator/=(float s
) { mExtents
/=s
; return *this; }
474 //! Operator for AABB += Point. Translates the box.
475 inline_ AABB
& operator+=(const Point
& trans
)
481 Point mCenter
; //!< AABB Center
482 Point mExtents
; //!< x, y and z extents
487 inline_
void ComputeMinMax(const Point
& p
, Point
& min
, Point
& max
)
489 if(p
.x
> max
.x
) max
.x
= p
.x
;
490 if(p
.x
< min
.x
) min
.x
= p
.x
;
492 if(p
.y
> max
.y
) max
.y
= p
.y
;
493 if(p
.y
< min
.y
) min
.y
= p
.y
;
495 if(p
.z
> max
.z
) max
.z
= p
.z
;
496 if(p
.z
< min
.z
) min
.z
= p
.z
;
499 inline_
void ComputeAABB(AABB
& aabb
, const Point
* list
, udword nb_pts
)
503 Point
Maxi(MIN_FLOAT
, MIN_FLOAT
, MIN_FLOAT
);
504 Point
Mini(MAX_FLOAT
, MAX_FLOAT
, MAX_FLOAT
);
507 // _prefetch(list+1); // off by one ?
508 ComputeMinMax(*list
++, Mini
, Maxi
);
510 aabb
.SetMinMax(Mini
, Maxi
);
514 #endif // __ICEAABB_H__