1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3 * Contains AABB-related code.
5 * \author Pierre Terdiman
6 * \date January, 29, 2000
8 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
14 * \author Pierre Terdiman
17 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
23 using namespace IceMaths
;
25 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
27 * Computes the sum of two AABBs.
28 * \param aabb [in] the other AABB
29 * \return Self-Reference
31 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32 AABB
& AABB::Add(const AABB
& aabb
)
34 // Compute new min & max values
35 Point Min
; GetMin(Min
);
36 Point Tmp
; aabb
.GetMin(Tmp
);
39 Point Max
; GetMax(Max
);
48 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
50 * Makes a cube from the AABB.
51 * \param cube [out] the cube AABB
52 * \return cube edge length
54 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55 float AABB::MakeCube(AABB
& cube
) const
57 Point Ext
; GetExtents(Ext
);
58 float Max
= Ext
.Max();
60 Point Cnt
; GetCenter(Cnt
);
61 cube
.SetCenterExtents(Cnt
, Point(Max
, Max
, Max
));
65 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
67 * Makes a sphere from the AABB.
68 * \param sphere [out] sphere containing the AABB
70 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71 void AABB::MakeSphere(Sphere
& sphere
) const
73 GetExtents(sphere
.mCenter
);
74 sphere
.mRadius
= sphere
.mCenter
.Magnitude() * 1.00001f
; // To make sure sphere::Contains(*this) succeeds
75 GetCenter(sphere
.mCenter
);
78 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
80 * Checks a box is inside another box.
81 * \param box [in] the other AABB
82 * \return true if current box is inside input box
84 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
85 bool AABB::IsInside(const AABB
& box
) const
87 if(box
.GetMin(0)>GetMin(0)) return false;
88 if(box
.GetMin(1)>GetMin(1)) return false;
89 if(box
.GetMin(2)>GetMin(2)) return false;
90 if(box
.GetMax(0)<GetMax(0)) return false;
91 if(box
.GetMax(1)<GetMax(1)) return false;
92 if(box
.GetMax(2)<GetMax(2)) return false;
96 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
98 * Computes the AABB planes.
99 * \param planes [out] 6 planes surrounding the box
100 * \return true if success
102 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
103 bool AABB::ComputePlanes(Plane
* planes
) const
106 if(!planes
) return false;
108 Point Center
, Extents
;
113 planes
[0].n
= Point(1.0f
, 0.0f
, 0.0f
);
114 planes
[1].n
= Point(-1.0f
, 0.0f
, 0.0f
);
115 planes
[2].n
= Point(0.0f
, 1.0f
, 0.0f
);
116 planes
[3].n
= Point(0.0f
, -1.0f
, 0.0f
);
117 planes
[4].n
= Point(0.0f
, 0.0f
, 1.0f
);
118 planes
[5].n
= Point(0.0f
, 0.0f
, -1.0f
);
120 // Compute a point on each plane
121 Point p0
= Point(Center
.x
+Extents
.x
, Center
.y
, Center
.z
);
122 Point p1
= Point(Center
.x
-Extents
.x
, Center
.y
, Center
.z
);
123 Point p2
= Point(Center
.x
, Center
.y
+Extents
.y
, Center
.z
);
124 Point p3
= Point(Center
.x
, Center
.y
-Extents
.y
, Center
.z
);
125 Point p4
= Point(Center
.x
, Center
.y
, Center
.z
+Extents
.z
);
126 Point p5
= Point(Center
.x
, Center
.y
, Center
.z
-Extents
.z
);
129 planes
[0].d
= -(planes
[0].n
|p0
);
130 planes
[1].d
= -(planes
[1].n
|p1
);
131 planes
[2].d
= -(planes
[2].n
|p2
);
132 planes
[3].d
= -(planes
[3].n
|p3
);
133 planes
[4].d
= -(planes
[4].n
|p4
);
134 planes
[5].d
= -(planes
[5].n
|p5
);
139 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
141 * Computes the aabb points.
142 * \param pts [out] 8 box points
143 * \return true if success
145 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
146 bool AABB::ComputePoints(Point
* pts
) const
149 if(!pts
) return false;
152 Point min
; GetMin(min
);
153 Point max
; GetMax(max
);
155 // 7+------+6 0 = ---
158 // / 4+---/--+5 3 = -+-
159 // 3+------+2 / y z 4 = --+
160 // | / | / | / 5 = +-+
162 // 0+------+1 *---x 7 = -++
164 // Generate 8 corners of the bbox
165 pts
[0] = Point(min
.x
, min
.y
, min
.z
);
166 pts
[1] = Point(max
.x
, min
.y
, min
.z
);
167 pts
[2] = Point(max
.x
, max
.y
, min
.z
);
168 pts
[3] = Point(min
.x
, max
.y
, min
.z
);
169 pts
[4] = Point(min
.x
, min
.y
, max
.z
);
170 pts
[5] = Point(max
.x
, min
.y
, max
.z
);
171 pts
[6] = Point(max
.x
, max
.y
, max
.z
);
172 pts
[7] = Point(min
.x
, max
.y
, max
.z
);
177 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
179 * Gets vertex normals.
180 * \param pts [out] 8 box points
181 * \return true if success
183 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
184 const Point
* AABB::GetVertexNormals() const
186 static const float VertexNormals
[] =
188 -INVSQRT3
, -INVSQRT3
, -INVSQRT3
,
189 INVSQRT3
, -INVSQRT3
, -INVSQRT3
,
190 INVSQRT3
, INVSQRT3
, -INVSQRT3
,
191 -INVSQRT3
, INVSQRT3
, -INVSQRT3
,
192 -INVSQRT3
, -INVSQRT3
, INVSQRT3
,
193 INVSQRT3
, -INVSQRT3
, INVSQRT3
,
194 INVSQRT3
, INVSQRT3
, INVSQRT3
,
195 -INVSQRT3
, INVSQRT3
, INVSQRT3
197 return (const Point
*)VertexNormals
;
200 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
203 * \return 24 indices (12 edges) indexing the list returned by ComputePoints()
205 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
206 const udword
* AABB::GetEdges() const
208 static const udword Indices
[] = {
209 0, 1, 1, 2, 2, 3, 3, 0,
210 7, 6, 6, 5, 5, 4, 4, 7,
217 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
219 * Returns edge normals.
220 * \return edge normals in local space
222 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
223 const Point
* AABB::GetEdgeNormals() const
225 static const float EdgeNormals
[] =
227 0, -INVSQRT2
, -INVSQRT2
, // 0-1
228 INVSQRT2
, 0, -INVSQRT2
, // 1-2
229 0, INVSQRT2
, -INVSQRT2
, // 2-3
230 -INVSQRT2
, 0, -INVSQRT2
, // 3-0
232 0, INVSQRT2
, INVSQRT2
, // 7-6
233 INVSQRT2
, 0, INVSQRT2
, // 6-5
234 0, -INVSQRT2
, INVSQRT2
, // 5-4
235 -INVSQRT2
, 0, INVSQRT2
, // 4-7
237 INVSQRT2
, -INVSQRT2
, 0, // 1-5
238 INVSQRT2
, INVSQRT2
, 0, // 6-2
239 -INVSQRT2
, INVSQRT2
, 0, // 3-7
240 -INVSQRT2
, -INVSQRT2
, 0 // 4-0
242 return (const Point
*)EdgeNormals
;
245 // ===========================================================================
246 // (C) 1996-98 Vienna University of Technology
247 // ===========================================================================
250 // PROJECT: Bounding Box Area
251 // CONTENT: Computes area of 2D projection of 3D oriented bounding box
253 // ===========================================================================
254 // AUTHORS: ds Dieter Schmalstieg
256 // ===========================================================================
259 // 19-sep-99 15:23:03 ds last modification
260 // 01-dec-98 15:23:03 ep created
261 // ===========================================================================
263 //----------------------------------------------------------------------------
264 // SAMPLE CODE STARTS HERE
265 //----------------------------------------------------------------------------
267 // NOTE: This sample program requires OPEN INVENTOR!
269 //indexlist: this table stores the 64 possible cases of classification of
270 //the eyepoint with respect to the 6 defining planes of the bbox (2^6=64)
271 //only 26 (3^3-1, where 1 is "inside" cube) of these cases are valid.
272 //the first 6 numbers in each row are the indices of the bbox vertices that
273 //form the outline of which we want to compute the area (counterclockwise
274 //ordering), the 7th entry means the number of vertices in the outline.
275 //there are 6 cases with a single face and and a 4-vertex outline, and
276 //20 cases with 2 or 3 faces and a 6-vertex outline. a value of 0 indicates
280 // Original list was made of 7 items, I added an 8th element:
281 // - to padd on a cache line
282 // - to repeat the first entry to avoid modulos
284 // I also replaced original ints with sbytes.
286 static const sbyte gIndexList
[64][8] =
288 {-1,-1,-1,-1,-1,-1,-1, 0}, // 0 inside
289 { 0, 4, 7, 3, 0,-1,-1, 4}, // 1 left
290 { 1, 2, 6, 5, 1,-1,-1, 4}, // 2 right
291 {-1,-1,-1,-1,-1,-1,-1, 0}, // 3 -
292 { 0, 1, 5, 4, 0,-1,-1, 4}, // 4 bottom
293 { 0, 1, 5, 4, 7, 3, 0, 6}, // 5 bottom, left
294 { 0, 1, 2, 6, 5, 4, 0, 6}, // 6 bottom, right
295 {-1,-1,-1,-1,-1,-1,-1, 0}, // 7 -
296 { 2, 3, 7, 6, 2,-1,-1, 4}, // 8 top
297 { 0, 4, 7, 6, 2, 3, 0, 6}, // 9 top, left
298 { 1, 2, 3, 7, 6, 5, 1, 6}, //10 top, right
299 {-1,-1,-1,-1,-1,-1,-1, 0}, //11 -
300 {-1,-1,-1,-1,-1,-1,-1, 0}, //12 -
301 {-1,-1,-1,-1,-1,-1,-1, 0}, //13 -
302 {-1,-1,-1,-1,-1,-1,-1, 0}, //14 -
303 {-1,-1,-1,-1,-1,-1,-1, 0}, //15 -
304 { 0, 3, 2, 1, 0,-1,-1, 4}, //16 front
305 { 0, 4, 7, 3, 2, 1, 0, 6}, //17 front, left
306 { 0, 3, 2, 6, 5, 1, 0, 6}, //18 front, right
307 {-1,-1,-1,-1,-1,-1,-1, 0}, //19 -
308 { 0, 3, 2, 1, 5, 4, 0, 6}, //20 front, bottom
309 { 1, 5, 4, 7, 3, 2, 1, 6}, //21 front, bottom, left
310 { 0, 3, 2, 6, 5, 4, 0, 6}, //22 front, bottom, right
311 {-1,-1,-1,-1,-1,-1,-1, 0}, //23 -
312 { 0, 3, 7, 6, 2, 1, 0, 6}, //24 front, top
313 { 0, 4, 7, 6, 2, 1, 0, 6}, //25 front, top, left
314 { 0, 3, 7, 6, 5, 1, 0, 6}, //26 front, top, right
315 {-1,-1,-1,-1,-1,-1,-1, 0}, //27 -
316 {-1,-1,-1,-1,-1,-1,-1, 0}, //28 -
317 {-1,-1,-1,-1,-1,-1,-1, 0}, //29 -
318 {-1,-1,-1,-1,-1,-1,-1, 0}, //30 -
319 {-1,-1,-1,-1,-1,-1,-1, 0}, //31 -
320 { 4, 5, 6, 7, 4,-1,-1, 4}, //32 back
321 { 0, 4, 5, 6, 7, 3, 0, 6}, //33 back, left
322 { 1, 2, 6, 7, 4, 5, 1, 6}, //34 back, right
323 {-1,-1,-1,-1,-1,-1,-1, 0}, //35 -
324 { 0, 1, 5, 6, 7, 4, 0, 6}, //36 back, bottom
325 { 0, 1, 5, 6, 7, 3, 0, 6}, //37 back, bottom, left
326 { 0, 1, 2, 6, 7, 4, 0, 6}, //38 back, bottom, right
327 {-1,-1,-1,-1,-1,-1,-1, 0}, //39 -
328 { 2, 3, 7, 4, 5, 6, 2, 6}, //40 back, top
329 { 0, 4, 5, 6, 2, 3, 0, 6}, //41 back, top, left
330 { 1, 2, 3, 7, 4, 5, 1, 6}, //42 back, top, right
331 {-1,-1,-1,-1,-1,-1,-1, 0}, //43 invalid
332 {-1,-1,-1,-1,-1,-1,-1, 0}, //44 invalid
333 {-1,-1,-1,-1,-1,-1,-1, 0}, //45 invalid
334 {-1,-1,-1,-1,-1,-1,-1, 0}, //46 invalid
335 {-1,-1,-1,-1,-1,-1,-1, 0}, //47 invalid
336 {-1,-1,-1,-1,-1,-1,-1, 0}, //48 invalid
337 {-1,-1,-1,-1,-1,-1,-1, 0}, //49 invalid
338 {-1,-1,-1,-1,-1,-1,-1, 0}, //50 invalid
339 {-1,-1,-1,-1,-1,-1,-1, 0}, //51 invalid
340 {-1,-1,-1,-1,-1,-1,-1, 0}, //52 invalid
341 {-1,-1,-1,-1,-1,-1,-1, 0}, //53 invalid
342 {-1,-1,-1,-1,-1,-1,-1, 0}, //54 invalid
343 {-1,-1,-1,-1,-1,-1,-1, 0}, //55 invalid
344 {-1,-1,-1,-1,-1,-1,-1, 0}, //56 invalid
345 {-1,-1,-1,-1,-1,-1,-1, 0}, //57 invalid
346 {-1,-1,-1,-1,-1,-1,-1, 0}, //58 invalid
347 {-1,-1,-1,-1,-1,-1,-1, 0}, //59 invalid
348 {-1,-1,-1,-1,-1,-1,-1, 0}, //60 invalid
349 {-1,-1,-1,-1,-1,-1,-1, 0}, //61 invalid
350 {-1,-1,-1,-1,-1,-1,-1, 0}, //62 invalid
351 {-1,-1,-1,-1,-1,-1,-1, 0} //63 invalid
354 const sbyte
* AABB::ComputeOutline(const Point
& local_eye
, sdword
& num
) const
357 Point min
; GetMin(min
);
358 Point max
; GetMax(max
);
360 // Compute 6-bit code to classify eye with respect to the 6 defining planes of the bbox
361 int pos
= ((local_eye
.x
< min
.x
) ? 1 : 0) // 1 = left
362 + ((local_eye
.x
> max
.x
) ? 2 : 0) // 2 = right
363 + ((local_eye
.y
< min
.y
) ? 4 : 0) // 4 = bottom
364 + ((local_eye
.y
> max
.y
) ? 8 : 0) // 8 = top
365 + ((local_eye
.z
< min
.z
) ? 16 : 0) // 16 = front
366 + ((local_eye
.z
> max
.z
) ? 32 : 0); // 32 = back
368 // Look up number of vertices in outline
369 num
= (sdword
)gIndexList
[pos
][7];
370 // Zero indicates invalid case
371 if(!num
) return null
;
373 return &gIndexList
[pos
][0];
376 // calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box
378 //const Point& eye, //eye point (in bbox object coordinates)
379 //const AABB& box, //3d bbox
380 //const Matrix4x4& mat, //free transformation for bbox
381 //float width, float height, int& num)
382 float AABB::ComputeBoxArea(const Point
& eye
, const Matrix4x4
& mat
, float width
, float height
, sdword
& num
) const
384 const sbyte
* Outline
= ComputeOutline(eye
, num
);
385 if(!Outline
) return -1.0f
;
387 // Compute box vertices
388 Point vertexBox
[8], dst
[8];
389 ComputePoints(vertexBox
);
391 // Transform all outline corners into 2D screen space
392 for(sdword i
=0;i
<num
;i
++)
395 vertexBox
[Outline
[i
]].ProjectToScreen(width
, height
, mat
, Projected
);
399 float Sum
= (dst
[num
-1][0] - dst
[0][0]) * (dst
[num
-1][1] + dst
[0][1]);
401 for(int i
=0; i
<num
-1; i
++)
402 Sum
+= (dst
[i
][0] - dst
[i
+1][0]) * (dst
[i
][1] + dst
[i
+1][1]);
404 return Sum
* 0.5f
; //return computed value corrected by 0.5