1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2 | /** |
---|
3 | * Contains AABB-related code. (axis-aligned bounding box) |
---|
4 | * \file IceAABB.h |
---|
5 | * \author Pierre Terdiman |
---|
6 | * \date January, 13, 2000 |
---|
7 | */ |
---|
8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
9 | |
---|
10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
11 | // Include Guard |
---|
12 | #ifndef __ICEAABB_H__ |
---|
13 | #define __ICEAABB_H__ |
---|
14 | |
---|
15 | // Forward declarations |
---|
16 | class Sphere; |
---|
17 | |
---|
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 \ |
---|
32 | { \ |
---|
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; \ |
---|
36 | return TRUE; \ |
---|
37 | } |
---|
38 | |
---|
39 | enum AABBType |
---|
40 | { |
---|
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. |
---|
43 | |
---|
44 | AABB_FORCE_DWORD = 0x7fffffff, |
---|
45 | }; |
---|
46 | |
---|
47 | #ifdef USE_MINMAX |
---|
48 | |
---|
49 | struct ICEMATHS_API ShadowAABB |
---|
50 | { |
---|
51 | Point mMin; |
---|
52 | Point mMax; |
---|
53 | }; |
---|
54 | |
---|
55 | class ICEMATHS_API AABB |
---|
56 | { |
---|
57 | public: |
---|
58 | //! Constructor |
---|
59 | inline_ AABB() {} |
---|
60 | //! Destructor |
---|
61 | inline_ ~AABB() {} |
---|
62 | |
---|
63 | //! Type-independent methods |
---|
64 | AABB_COMMON_METHODS; |
---|
65 | |
---|
66 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
67 | /** |
---|
68 | * Setups an AABB from min & max vectors. |
---|
69 | * \param min [in] the min point |
---|
70 | * \param max [in] the max point |
---|
71 | */ |
---|
72 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
73 | void SetMinMax(const Point& min, const Point& max) { mMin = min; mMax = max; } |
---|
74 | |
---|
75 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
76 | /** |
---|
77 | * Setups an AABB from center & extents vectors. |
---|
78 | * \param c [in] the center point |
---|
79 | * \param e [in] the extents vector |
---|
80 | */ |
---|
81 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
82 | void SetCenterExtents(const Point& c, const Point& e) { mMin = c - e; mMax = c + e; } |
---|
83 | |
---|
84 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
85 | /** |
---|
86 | * Setups an empty AABB. |
---|
87 | */ |
---|
88 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
89 | void SetEmpty() { Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mMin = -p; mMax = p;} |
---|
90 | |
---|
91 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
92 | /** |
---|
93 | * Setups a point AABB. |
---|
94 | */ |
---|
95 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
96 | void SetPoint(const Point& pt) { mMin = mMax = pt; } |
---|
97 | |
---|
98 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
99 | /** |
---|
100 | * Gets the size of the AABB. The size is defined as the longest extent. |
---|
101 | * \return the size of the AABB |
---|
102 | */ |
---|
103 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
104 | float GetSize() const { Point e; GetExtents(e); return e.Max(); } |
---|
105 | |
---|
106 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
107 | /** |
---|
108 | * Extends the AABB. |
---|
109 | * \param p [in] the next point |
---|
110 | */ |
---|
111 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
112 | void Extend(const Point& p) |
---|
113 | { |
---|
114 | if(p.x > mMax.x) mMax.x = p.x; |
---|
115 | if(p.x < mMin.x) mMin.x = p.x; |
---|
116 | |
---|
117 | if(p.y > mMax.y) mMax.y = p.y; |
---|
118 | if(p.y < mMin.y) mMin.y = p.y; |
---|
119 | |
---|
120 | if(p.z > mMax.z) mMax.z = p.z; |
---|
121 | if(p.z < mMin.z) mMin.z = p.z; |
---|
122 | } |
---|
123 | // Data access |
---|
124 | |
---|
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; } |
---|
129 | |
---|
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]; } |
---|
134 | |
---|
135 | //! Get box center |
---|
136 | inline_ void GetCenter(Point& center) const { center = (mMax + mMin)*0.5f; } |
---|
137 | //! Get box extents |
---|
138 | inline_ void GetExtents(Point& extents) const { extents = (mMax - mMin)*0.5f; } |
---|
139 | |
---|
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; } |
---|
144 | |
---|
145 | //! Get box diagonal |
---|
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; } |
---|
150 | |
---|
151 | //! Volume |
---|
152 | inline_ float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); } |
---|
153 | |
---|
154 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
155 | /** |
---|
156 | * Computes the intersection between two AABBs. |
---|
157 | * \param a [in] the other AABB |
---|
158 | * \return true on intersection |
---|
159 | */ |
---|
160 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
161 | inline_ BOOL Intersect(const AABB& a) const |
---|
162 | { |
---|
163 | if(mMax.x < a.mMin.x |
---|
164 | || a.mMax.x < mMin.x |
---|
165 | || mMax.y < a.mMin.y |
---|
166 | || a.mMax.y < mMin.y |
---|
167 | || mMax.z < a.mMin.z |
---|
168 | || a.mMax.z < mMin.z) return FALSE; |
---|
169 | |
---|
170 | return TRUE; |
---|
171 | } |
---|
172 | |
---|
173 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
174 | /** |
---|
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 |
---|
179 | */ |
---|
180 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
181 | inline_ BOOL Intersect(const AABB& a, udword axis) const |
---|
182 | { |
---|
183 | if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis]) return FALSE; |
---|
184 | return TRUE; |
---|
185 | } |
---|
186 | |
---|
187 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
188 | /** |
---|
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] |
---|
193 | */ |
---|
194 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
195 | inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const |
---|
196 | { |
---|
197 | // The three edges transformed: you can efficiently transform an X-only vector |
---|
198 | // by just getting the "X" column of the matrix |
---|
199 | Point vx,vy,vz; |
---|
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); |
---|
203 | |
---|
204 | // Transform the min point |
---|
205 | aabb.mMin = aabb.mMax = mMin * mtx; |
---|
206 | |
---|
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; |
---|
218 | } |
---|
219 | |
---|
220 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
221 | /** |
---|
222 | * Checks the AABB is valid. |
---|
223 | * \return true if the box is valid |
---|
224 | */ |
---|
225 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
226 | inline_ BOOL IsValid() const |
---|
227 | { |
---|
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; |
---|
232 | return TRUE; |
---|
233 | } |
---|
234 | |
---|
235 | //! Operator for AABB *= float. Scales the extents, keeps same center. |
---|
236 | inline_ AABB& operator*=(float s) |
---|
237 | { |
---|
238 | Point Center; GetCenter(Center); |
---|
239 | Point Extents; GetExtents(Extents); |
---|
240 | SetCenterExtents(Center, Extents * s); |
---|
241 | return *this; |
---|
242 | } |
---|
243 | |
---|
244 | //! Operator for AABB /= float. Scales the extents, keeps same center. |
---|
245 | inline_ AABB& operator/=(float s) |
---|
246 | { |
---|
247 | Point Center; GetCenter(Center); |
---|
248 | Point Extents; GetExtents(Extents); |
---|
249 | SetCenterExtents(Center, Extents / s); |
---|
250 | return *this; |
---|
251 | } |
---|
252 | |
---|
253 | //! Operator for AABB += Point. Translates the box. |
---|
254 | inline_ AABB& operator+=(const Point& trans) |
---|
255 | { |
---|
256 | mMin+=trans; |
---|
257 | mMax+=trans; |
---|
258 | return *this; |
---|
259 | } |
---|
260 | private: |
---|
261 | Point mMin; //!< Min point |
---|
262 | Point mMax; //!< Max point |
---|
263 | }; |
---|
264 | |
---|
265 | #else |
---|
266 | |
---|
267 | class ICEMATHS_API AABB |
---|
268 | { |
---|
269 | public: |
---|
270 | //! Constructor |
---|
271 | inline_ AABB() {} |
---|
272 | //! Destructor |
---|
273 | inline_ ~AABB() {} |
---|
274 | |
---|
275 | //! Type-independent methods |
---|
276 | AABB_COMMON_METHODS; |
---|
277 | |
---|
278 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
279 | /** |
---|
280 | * Setups an AABB from min & max vectors. |
---|
281 | * \param min [in] the min point |
---|
282 | * \param max [in] the max point |
---|
283 | */ |
---|
284 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
285 | void SetMinMax(const Point& min, const Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } |
---|
286 | |
---|
287 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
288 | /** |
---|
289 | * Setups an AABB from center & extents vectors. |
---|
290 | * \param c [in] the center point |
---|
291 | * \param e [in] the extents vector |
---|
292 | */ |
---|
293 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
294 | void SetCenterExtents(const Point& c, const Point& e) { mCenter = c; mExtents = e; } |
---|
295 | |
---|
296 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
297 | /** |
---|
298 | * Setups an empty AABB. |
---|
299 | */ |
---|
300 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
301 | void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);} |
---|
302 | |
---|
303 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
304 | /** |
---|
305 | * Setups a point AABB. |
---|
306 | */ |
---|
307 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
308 | void SetPoint(const Point& pt) { mCenter = pt; mExtents.Zero(); } |
---|
309 | |
---|
310 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
311 | /** |
---|
312 | * Gets the size of the AABB. The size is defined as the longest extent. |
---|
313 | * \return the size of the AABB |
---|
314 | */ |
---|
315 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
316 | float GetSize() const { return mExtents.Max(); } |
---|
317 | |
---|
318 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
319 | /** |
---|
320 | * Extends the AABB. |
---|
321 | * \param p [in] the next point |
---|
322 | */ |
---|
323 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
324 | void Extend(const Point& p) |
---|
325 | { |
---|
326 | Point Max = mCenter + mExtents; |
---|
327 | Point Min = mCenter - mExtents; |
---|
328 | |
---|
329 | if(p.x > Max.x) Max.x = p.x; |
---|
330 | if(p.x < Min.x) Min.x = p.x; |
---|
331 | |
---|
332 | if(p.y > Max.y) Max.y = p.y; |
---|
333 | if(p.y < Min.y) Min.y = p.y; |
---|
334 | |
---|
335 | if(p.z > Max.z) Max.z = p.z; |
---|
336 | if(p.z < Min.z) Min.z = p.z; |
---|
337 | |
---|
338 | SetMinMax(Min, Max); |
---|
339 | } |
---|
340 | // Data access |
---|
341 | |
---|
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; } |
---|
346 | |
---|
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]; } |
---|
351 | |
---|
352 | //! Get box center |
---|
353 | inline_ void GetCenter(Point& center) const { center = mCenter; } |
---|
354 | //! Get box extents |
---|
355 | inline_ void GetExtents(Point& extents) const { extents = mExtents; } |
---|
356 | |
---|
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]; } |
---|
361 | |
---|
362 | //! Get box diagonal |
---|
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; } |
---|
367 | |
---|
368 | //! Volume |
---|
369 | inline_ float GetVolume() const { return mExtents.x * mExtents.y * mExtents.z * 8.0f; } |
---|
370 | |
---|
371 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
372 | /** |
---|
373 | * Computes the intersection between two AABBs. |
---|
374 | * \param a [in] the other AABB |
---|
375 | * \return true on intersection |
---|
376 | */ |
---|
377 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
378 | inline_ BOOL Intersect(const AABB& a) const |
---|
379 | { |
---|
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; |
---|
383 | return TRUE; |
---|
384 | } |
---|
385 | |
---|
386 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
387 | /** |
---|
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 |
---|
391 | */ |
---|
392 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
393 | inline_ bool GomezIntersect(const AABB& a) |
---|
394 | { |
---|
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))); |
---|
399 | } |
---|
400 | |
---|
401 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
402 | /** |
---|
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 |
---|
407 | */ |
---|
408 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
409 | inline_ BOOL Intersect(const AABB& a, udword axis) const |
---|
410 | { |
---|
411 | float t = mCenter[axis] - a.mCenter[axis]; |
---|
412 | float e = a.mExtents[axis] + mExtents[axis]; |
---|
413 | if(AIR(t) > IR(e)) return FALSE; |
---|
414 | return TRUE; |
---|
415 | } |
---|
416 | |
---|
417 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
418 | /** |
---|
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] |
---|
422 | */ |
---|
423 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
424 | inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const |
---|
425 | { |
---|
426 | // Compute new center |
---|
427 | aabb.mCenter = mCenter * mtx; |
---|
428 | |
---|
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 | |
---|
433 | Point Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y); |
---|
434 | IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff; |
---|
435 | |
---|
436 | Point Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z); |
---|
437 | IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff; |
---|
438 | |
---|
439 | aabb.mExtents.x = Ex.x + Ey.x + Ez.x; |
---|
440 | aabb.mExtents.y = Ex.y + Ey.y + Ez.y; |
---|
441 | aabb.mExtents.z = Ex.z + Ey.z + Ez.z; |
---|
442 | } |
---|
443 | |
---|
444 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
445 | /** |
---|
446 | * Checks the AABB is valid. |
---|
447 | * \return true if the box is valid |
---|
448 | */ |
---|
449 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
450 | inline_ BOOL IsValid() const |
---|
451 | { |
---|
452 | // Consistency condition for (Center, Extents) boxes: Extents >= 0 |
---|
453 | if(IS_NEGATIVE_FLOAT(mExtents.x)) return FALSE; |
---|
454 | if(IS_NEGATIVE_FLOAT(mExtents.y)) return FALSE; |
---|
455 | if(IS_NEGATIVE_FLOAT(mExtents.z)) return FALSE; |
---|
456 | return TRUE; |
---|
457 | } |
---|
458 | |
---|
459 | //! Operator for AABB *= float. Scales the extents, keeps same center. |
---|
460 | inline_ AABB& operator*=(float s) { mExtents*=s; return *this; } |
---|
461 | |
---|
462 | //! Operator for AABB /= float. Scales the extents, keeps same center. |
---|
463 | inline_ AABB& operator/=(float s) { mExtents/=s; return *this; } |
---|
464 | |
---|
465 | //! Operator for AABB += Point. Translates the box. |
---|
466 | inline_ AABB& operator+=(const Point& trans) |
---|
467 | { |
---|
468 | mCenter+=trans; |
---|
469 | return *this; |
---|
470 | } |
---|
471 | private: |
---|
472 | Point mCenter; //!< AABB Center |
---|
473 | Point mExtents; //!< x, y and z extents |
---|
474 | }; |
---|
475 | |
---|
476 | #endif |
---|
477 | |
---|
478 | inline_ void ComputeMinMax(const Point& p, Point& min, Point& max) |
---|
479 | { |
---|
480 | if(p.x > max.x) max.x = p.x; |
---|
481 | if(p.x < min.x) min.x = p.x; |
---|
482 | |
---|
483 | if(p.y > max.y) max.y = p.y; |
---|
484 | if(p.y < min.y) min.y = p.y; |
---|
485 | |
---|
486 | if(p.z > max.z) max.z = p.z; |
---|
487 | if(p.z < min.z) min.z = p.z; |
---|
488 | } |
---|
489 | |
---|
490 | inline_ void ComputeAABB(AABB& aabb, const Point* list, udword nb_pts) |
---|
491 | { |
---|
492 | if(list) |
---|
493 | { |
---|
494 | Point Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); |
---|
495 | Point Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT); |
---|
496 | while(nb_pts--) |
---|
497 | { |
---|
498 | // _prefetch(list+1); // off by one ? |
---|
499 | ComputeMinMax(*list++, Mini, Maxi); |
---|
500 | } |
---|
501 | aabb.SetMinMax(Mini, Maxi); |
---|
502 | } |
---|
503 | } |
---|
504 | |
---|
505 | #endif // __ICEAABB_H__ |
---|