source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.cpp @ 3318

Revision 3318, 39.6 KB checked in by mattausch, 15 years ago (diff)

played around with reprojection, cleaned up code

Line 
1#include "AxisAlignedBox3.h"
2#include "Plane3.h"
3#include "Polygon3.h"
4#include "Polyhedron.h"
5#include "Triangle3.h"
6
7#include <cassert>
8#include <iostream>
9
10#ifdef _CRT_SET
11        #define _CRTDBG_MAP_ALLOC
12        #include <stdlib.h>
13        #include <crtdbg.h>
14
15        // redefine new operator
16        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
17        #define new DEBUG_NEW
18#endif
19
20
21using namespace std;
22
23
24namespace CHCDemoEngine
25{
26
27// Overload << operator for C++-style output
28ostream& operator<< (ostream &s, const AxisAlignedBox3 &A)
29{
30        return s << '[' << A.mMin.x << ", " << A.mMin.y << ", " << A.mMin.z << "]["
31                     << A.mMax.x << ", " << A.mMax.y << ", " << A.mMax.z << ']';
32}
33
34
35// Overload >> operator for C++-style input
36istream& operator>> (istream &s, AxisAlignedBox3 &A)
37{
38        char a;
39        // read "[min.x, min.y, min.z][mMax.x, mMax.y, mMax.z]"
40        return s >> a >> A.mMin.x >> a >> A.mMin.y >> a >> A.mMin.z >> a >> a
41                     >> A.mMax.x >> a >> A.mMax.y >> a >> A.mMax.z >> a;
42}
43
44
45AxisAlignedBox3::AxisAlignedBox3()
46{}
47
48
49AxisAlignedBox3::AxisAlignedBox3(const Vector3 &nMin,
50                                                                 const Vector3 &nMax)
51: mMin(nMin), mMax(nMax)
52{}
53
54
55
56bool AxisAlignedBox3::Unbounded() const
57{
58        return (mMin == Vector3(-MAXFLOAT)) ||
59                   (mMax == Vector3(-MAXFLOAT));
60}
61
62
63void AxisAlignedBox3::Include(const Vector3 &newpt)
64{
65        Minimize(mMin, newpt);
66        Maximize(mMax, newpt);
67}
68
69
70void AxisAlignedBox3::Include(const Polygon3 &newpoly)
71{
72        VertexArray::const_iterator it, it_end = newpoly.mVertices.end();
73
74        for (it = newpoly.mVertices.begin(); it != it_end; ++ it)
75        {
76                Include(*it);
77        }
78}
79
80
81void AxisAlignedBox3::Include(const PolygonContainer &polys)
82{
83        PolygonContainer::const_iterator it, it_end = polys.end();
84
85        for (it = polys.begin(); it != it_end; ++ it)
86        {
87                Include(*(*it));
88        }
89}
90
91
92void AxisAlignedBox3::Include(const AxisAlignedBox3 &bbox)
93{
94        Minimize(mMin, bbox.mMin);
95        Maximize(mMax, bbox.mMax);
96}
97
98
99bool AxisAlignedBox3::IsCorrect()
100{
101        if ((mMin.x > mMax.x) ||
102                (mMin.y > mMax.y) ||
103                (mMin.z > mMax.z) )
104        {
105                return false; // box is not formed
106        }
107
108        return true;
109}
110
111
112void AxisAlignedBox3::GetEdge(int edge,
113                                                          Vector3 *a,
114                                                          Vector3 *b) const
115{
116        switch(edge)
117        {
118        case 0:
119                a->SetValue(mMin.x, mMin.y, mMin.z);
120                b->SetValue(mMin.x, mMin.y, mMax.z);
121                break;
122        case 1:
123                a->SetValue(mMin.x, mMin.y, mMin.z);
124                b->SetValue(mMin.x, mMax.y, mMin.z);
125                break;
126        case 2:
127                a->SetValue(mMin.x, mMin.y, mMin.z);
128                b->SetValue(mMax.x, mMin.y, mMin.z);
129                break;
130        case 3:
131                a->SetValue(mMax.x, mMax.y, mMax.z);
132                b->SetValue(mMax.x, mMax.y, mMin.z);
133                break;
134        case 4:
135                a->SetValue(mMax.x, mMax.y, mMax.z);
136                b->SetValue(mMax.x, mMin.y, mMax.z);
137                break;
138        case 5:
139                a->SetValue(mMax.x, mMax.y, mMax.z);
140                b->SetValue(mMin.x, mMax.y, mMax.z);
141                break;
142
143        case 6:
144                a->SetValue(mMin.x, mMin.y, mMax.z);
145                b->SetValue(mMin.x, mMax.y, mMax.z);
146                break;
147        case 7:
148                a->SetValue(mMin.x, mMin.y, mMax.z);
149                b->SetValue(mMax.x, mMin.y, mMax.z);
150                break;
151        case 8:
152                a->SetValue(mMin.x, mMax.y, mMin.z);
153                b->SetValue(mMin.x, mMax.y, mMax.z);
154                break;
155        case 9:
156                a->SetValue(mMin.x, mMax.y, mMin.z);
157                b->SetValue(mMax.x, mMax.y, mMin.z);
158                break;
159        case 10:
160                a->SetValue(mMax.x, mMin.y, mMin.z);
161                b->SetValue(mMax.x, mMax.y, mMin.z);
162                break;
163        case 11:
164                a->SetValue(mMax.x, mMin.y, mMin.z);
165                b->SetValue(mMax.x, mMin.y, mMax.z);
166                break;
167        }
168}
169
170// returns the vertex indices in the range <0..7>, v = 4.x + 2.y + z, where
171// x,y,z are either 0 or 1; (0 .. min coordinate, 1 .. max coordinate)
172void AxisAlignedBox3::GetEdge(int edge, int  &aIdx, int &bIdx) const
173{
174        switch(edge)
175        {
176        case 0: aIdx = 0; bIdx = 1; break;
177        case 1: aIdx = 0; bIdx = 2; break;
178        case 2: aIdx = 0; bIdx = 4; break;
179        case 3: aIdx = 7; bIdx = 6; break;
180        case 4: aIdx = 7; bIdx = 5; break;
181        case 5: aIdx = 7; bIdx = 3; break;
182        case 6: aIdx = 1; bIdx = 3; break;
183        case 7: aIdx = 1; bIdx = 5; break;
184        case 8: aIdx = 2; bIdx = 3; break;
185        case 9: aIdx = 2; bIdx = 6; break;
186        case 10: aIdx = 4; bIdx = 6; break;
187        case 11: aIdx = 4; bIdx = 5; break;
188        }
189}
190
191
192void AxisAlignedBox3::Include(int axis, float newBound)
193{
194        switch (axis)
195        {
196        case 0:
197                { // x-axis
198                        if (mMin.x > newBound) mMin.x = newBound;
199                        if (mMax.x < newBound) mMax.x = newBound;
200                        break;
201                }
202        case 1:
203                { // y-axis
204                        if (mMin.y > newBound) mMin.y = newBound;
205                        if (mMax.y < newBound) mMax.y = newBound;
206                        break;
207                }
208        case 2:
209                { // z-axis
210                        if (mMin.z > newBound) mMin.z = newBound;
211                        if (mMax.z < newBound) mMax.z = newBound;
212                        break;
213                }
214        }
215}
216
217
218void AxisAlignedBox3::Describe(ostream &app, int ind) const
219{
220        indent(app, ind);
221        app << "AxisAlignedBox3: min at(" << mMin << "), max at(" << mMax << ")\n";
222}
223
224
225int AxisAlignedBox3::IsInside(const Vector3 &v) const
226{
227        return !((v.x < mMin.x) ||
228                     (v.x > mMax.x) ||
229                         (v.y < mMin.y) ||
230                         (v.y > mMax.y) ||
231                         (v.z < mMin.z) ||
232                         (v.z > mMax.z));
233}
234
235
236bool AxisAlignedBox3::Includes(const AxisAlignedBox3 &b) const
237{
238        return (b.mMin.x >= mMin.x &&
239                b.mMin.y >= mMin.y &&
240                        b.mMin.z >= mMin.z &&
241                        b.mMax.x <= mMax.x &&
242                        b.mMax.y <= mMax.y &&
243                        b.mMax.z <= mMax.z);
244}
245
246
247// compute the coordinates of one vertex of the box
248Vector3 AxisAlignedBox3::GetVertex(int xAxis,
249                                                                   int yAxis,
250                                                                   int zAxis) const
251{
252        Vector3 p;
253
254        p.x = xAxis ? mMax.x : mMin.x;
255        p.y = yAxis ? mMax.y : mMin.y;
256        p.z = zAxis ? mMax.z : mMin.z;
257
258        return p;
259}
260
261
262// compute the vertex for number N = <0..7>, N = 4.x + 2.y + z, where
263// x,y,z are either 0 or 1; (0 .. min coordinate, 1 .. max coordinate)
264void AxisAlignedBox3::GetVertex2(int N, Vector3 &vertex) const
265{
266        switch (N)
267        {
268        case 0: vertex.SetValue(mMin.x, mMin.y, mMin.z); break;
269        case 1: vertex.SetValue(mMax.x, mMin.y, mMin.z); break;
270        case 2: vertex.SetValue(mMax.x, mMax.y, mMin.z); break;
271        case 3: vertex.SetValue(mMin.x, mMax.y, mMin.z); break;
272        case 4: vertex.SetValue(mMin.x, mMax.y, mMax.z); break;
273        case 5: vertex.SetValue(mMax.x, mMax.y, mMax.z); break;
274        case 6: vertex.SetValue(mMax.x, mMin.y, mMax.z); break;
275        case 7: vertex.SetValue(mMin.x, mMin.y, mMax.z); break;
276        default:
277                {
278                        cerr << "ERROR in AxisAlignedBox3::GetVertex N=" << N <<  "\n";
279                }
280        }
281}
282
283// compute the vertex for number N = <0..7>, N = 4.x + 2.y + z, where
284// x,y,z are either 0 or 1; (0 .. min coordinate, 1 .. max coordinate)
285void AxisAlignedBox3::GetVertex(int N, Vector3 &vertex) const
286{
287        switch (N)
288        {
289        case 0: vertex = mMin; break;
290        case 1: vertex.SetValue(mMin.x, mMin.y, mMax.z); break;
291        case 2: vertex.SetValue(mMin.x, mMax.y, mMin.z); break;
292        case 3: vertex.SetValue(mMin.x, mMax.y, mMax.z); break;
293        case 4: vertex.SetValue(mMax.x, mMin.y, mMin.z); break;
294        case 5: vertex.SetValue(mMax.x, mMin.y, mMax.z); break;
295        case 6: vertex.SetValue(mMax.x, mMax.y, mMin.z); break;
296        case 7: vertex = mMax; break;
297        default:
298                {
299                        cerr << "ERROR in AxisAlignedBox3::GetVertex N=" << N <<  "\n";
300                }
301        }
302}
303
304
305float AxisAlignedBox3::SurfaceArea() const
306{
307        Vector3 ext = mMax - mMin;
308        return 2.0f * (ext.x * ext.y + ext.x * ext.z + ext.y * ext.z);
309}
310
311
312float AxisAlignedBox3::GetVolume() const
313{
314        return (mMax.x - mMin.x) * (mMax.y - mMin.y) * (mMax.z - mMin.z);
315}
316
317
318const int AxisAlignedBox3::bvertices[27][9] =
319{                                // region number .. position
320        {5,1,3,2,6,4,-1,-1,-1},      // 0 .. x=0 y=0 z=0
321        {4,5,1,3,2,0,-1,-1,-1},      // 1 .. x=0 y=0 z=1
322        {4,5,7,3,2,0,-1,-1,-1},      // 2 .. x=0 y=0 z=2
323
324        {0,1,3,2,6,4,-1,-1,-1},      // 3 .. x=0 y=1 z=0
325        {0,1,3,2,-1,-1,-1,-1,-1},    // 4 .. x=0 y=1 z=1
326        {1,5,7,3,2,0,-1,-1,-1},      // 5 .. x=0 y=1 z=2
327
328        {0,1,3,7,6,4,-1,-1,-1},      // 6 .. x=0 y=2 z=0
329        {0,1,3,7,6,2,-1,-1,-1},      // 7 .. x=0 y=2 z=1
330        {1,5,7,6,2,0,-1,-1,-1},      // 8 .. x=0 y=2 z=2
331
332        // the regions number <9,17>
333        {5,1,0,2,6,4,-1,-1,-1},      // 9  .. x=1 y=0 z=0
334        {5,1,0,4,-1,-1,-1,-1,-1},    // 10 .. x=1 y=0 z=1
335        {7,3,1,0,4,5,-1,-1,-1},      // 11 .. x=1 y=0 z=2
336
337        {4,0,2,6,-1,-1,-1,-1,-1},    // 12 .. x=1 y=1 z=0
338        {0,2,3,1,5,4,6,7,-1},        // 13 .. x=1 y=1 z=1 .. inside the box
339        {1,5,7,3,-1,-1,-1,-1,-1},    // 14 .. x=1 y=1 z=2
340
341        {4,0,2,3,7,6,-1,-1,-1},      // 15 .. x=1 y=2 z=0
342        {6,2,3,7,-1,-1,-1,-1,-1},    // 16 .. x=1 y=2 z=1
343        {1,5,7,6,2,3,-1,-1,-1},      // 17 .. x=1 y=2 z=2
344
345        // the regions number <18,26>
346        {1,0,2,6,7,5,-1,-1,-1},      // 18 .. x=2 y=0 z=0
347        {1,0,4,6,7,5,-1,-1,-1},      // 19 .. x=2 y=0 z=1
348        {0,4,6,7,3,1,-1,-1,-1},      // 20 .. x=2 y=0 z=2
349
350        {4,0,2,6,7,5,-1,-1,-1},      // 21 .. x=2 y=1 z=0
351        {5,4,6,7,-1,-1,-1,-1,-1},    // 22 .. x=2 y=1 z=1
352        {5,4,6,7,3,1,-1,-1,-1},      // 23 .. x=2 y=1 z=2
353
354        {4,0,2,3,7,5,-1,-1,-1},      // 24 .. x=2 y=2 z=0
355        {5,4,6,2,3,7,-1,-1,-1},      // 25 .. x=2 y=2 z=1
356        {5,4,6,2,3,1,-1,-1,-1},      // 26 .. x=2 y=2 z=2
357};
358
359// the visibility of boundary faces from a given region
360// one to three triples: (axis, min_vertex, max_vertex), axis==-1(terminator)
361const int AxisAlignedBox3::bfaces[27][10] =
362{                                // region number .. position
363        {0,0,3,1,0,5,2,0,6,-1},      // 0 .. x=0 y=0 z=0
364        {0,0,3,1,0,5,-1,-1,-1,-1},   // 1 .. x=0 y=0 z=1
365        {0,0,3,1,0,5,2,1,7,-1},      // 2 .. x=0 y=0 z=2
366
367        {0,0,3,2,0,6,-1,-1,-1,-1},   // 3 .. x=0 y=1 z=0
368        {0,0,3,-1,-1,-1,-1,-1,-1,-1},// 4 .. x=0 y=1 z=1
369        {0,0,3,2,1,7,-1,-1,-1,-1},   // 5 .. x=0 y=1 z=2
370
371        {0,0,3,1,2,7,2,0,6,-1},      // 6 .. x=0 y=2 z=0
372        {0,0,3,1,2,7,-1,-1,-1,-1},   // 7 .. x=0 y=2 z=1
373        {0,0,3,1,2,7,2,1,7,-1},      // 8 .. x=0 y=2 z=2
374
375        // the regions number <9,17>
376        {1,0,5,2,0,6,-1,-1,-1,-1},   // 9  .. x=1 y=0 z=0
377        {1,0,5,-1,-1,-1,-1,-1,-1,-1},// 10 .. x=1 y=0 z=1
378        {1,0,5,2,1,7,-1,-1,-1,-1},   // 11 .. x=1 y=0 z=2
379
380        {2,0,6,-1,-1,-1,-1,-1,-1,-1},// 12 .. x=1 y=1 z=0
381        {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},// 13 .. x=1 y=1 z=1 .. inside the box
382        {2,1,7,-1,-1,-1,-1,-1,-1,-1},// 14 .. x=1 y=1 z=2
383
384        {1,2,7,2,0,6,-1,-1,-1,-1},   // 15 .. x=1 y=2 z=0
385        {1,2,7,-1,-1,-1,-1,-1,-1,-1},// 16 .. x=1 y=2 z=1
386        {1,2,7,2,1,7,-1,-1,-1,-1},   // 17 .. x=1 y=2 z=2
387
388        // the region number <18,26>
389        {0,4,7,1,0,5,2,0,6,-1},      // 18 .. x=2 y=0 z=0
390        {0,4,7,1,0,5,-1,-1,-1,-1},   // 19 .. x=2 y=0 z=1
391        {0,4,7,1,0,5,2,1,7,-1},      // 20 .. x=2 y=0 z=2
392
393        {0,4,7,2,0,6,-1,-1,-1,-1},   // 21 .. x=2 y=1 z=0
394        {0,4,7,-1,-1,-1,-1,-1,-1,-1},// 22 .. x=2 y=1 z=1
395        {0,4,7,2,1,7,-1,-1,-1,-1},   // 23 .. x=2 y=1 z=2
396
397        {0,4,7,1,2,7,2,0,6,-1},      // 24 .. x=2 y=2 z=0
398        {0,4,7,1,2,7,-1,-1,-1,-1},   // 25 .. x=2 y=2 z=1
399        {0,4,7,1,2,7,2,1,7,-1},      // 26 .. x=2 y=2 z=2
400};
401
402// the correct corners indexing from entry face to exit face
403// first index determines entry face, second index exit face, and
404// the two numbers (indx, inc) determines: ind = the index on the exit
405// face, when starting from the vertex 0 on entry face, 'inc' is
406// the increment when we go on entry face in order 0,1,2,3 to create
407// convex shaft with the rectangle on exit face. That is, inc = -1 or 1.
408const int AxisAlignedBox3::pairFaceRects[6][6][2] = {
409        { // entry face = 0
410                {-1,0}, // exit face 0 .. no meaning
411                {0,-1}, // 1
412                {0,-1}, // 2
413                {0,1}, // 3 .. opposite face
414                {3,1}, // 4
415                {1,1} // 5
416        },
417        { // entry face = 1
418                {0,-1}, // exit face 0
419                {-1,0}, // 1 .. no meaning
420                {0,-1}, // 2
421                {1,1}, // 3
422                {0,1}, // 4 .. opposite face
423                {3,1} // 5
424        },
425        { // entry face = 2
426                {0,-1}, // 0
427                {0,-1}, // 1
428                {-1,0}, // 2 .. no meaning
429                {3,1}, // 3
430                {1,1}, // 4
431                {0,1} // 5 .. opposite face
432        },
433        { // entry face = 3
434                {0,1}, // 0 .. opposite face
435                {3,-1}, // 1
436                {1,1}, // 2
437                {-1,0}, // 3  .. no meaning
438                {0,-1}, // 4
439                {0,-1} // 5
440        },
441        { // entry face = 4
442                {1,1}, // 0
443                {0,1}, // 1 .. opposite face
444                {3,1}, // 2
445                {0,-1}, // 3
446                {-1,0}, // 4 .. no meaning
447                {0,-1} // 5
448        },
449        { // entry face = 5
450                {3,-1}, // 0
451                {1,1}, // 1
452                {0,1}, // 2  .. opposite face
453                {0,-1}, // 3
454                {0,-1}, // 4
455                {-1,0} // 5 .. no meaning
456        }
457};
458
459
460// ------------------------------------------------------------
461// The vertices that form CLOSEST points with respect to the region
462// for all the regions possible, number of regions is 3^3 = 27,
463// since two parallel sides of bbox forms three disjoint spaces.
464// The vertices are given in anti-clockwise order, stopped by value 15,
465// at most 8 points, at least 1 point.
466// The table includes the closest 1/2/4/8 points, followed possibly
467// by the set of coordinates that should be used for testing for
468// the proximity queries. The coordinates to be tested are described by
469// the pair (a,b), when a=0, we want to test min vector of the box,
470//                 when a=1, we want to test max vector of the box
471//                 b=0,1,2 corresponds to the axis (0=x,1=y,2=z)
472// The sequence is ended by 15, number -1 is used as the separator
473// between the vertices and coordinates.
474const int AxisAlignedBox3::cvertices[27][9] =
475{                                // region number.. position
476        {0,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D one vertex
477        {0,1,-1,0,0,0,1,15,15},      // 1 .. x=0 y=0 z=1 D two vertices foll. by 2
478        {1,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D one vertex
479
480        {0,2,-1,0,0,0,2,15,15},      // 3 .. x=0 y=1 z=0 D
481        {0,1,3,2,-1,0,0,15,15},      // 4 .. x=0 y=1 z=1 D
482        {1,3,-1,0,0,1,2,15,15},      // 5 .. x=0 y=1 z=2 D
483
484        {2,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D
485        {2,3,-1,0,0,1,1,15,15},      // 7 .. x=0 y=2 z=1 D
486        {3,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D
487
488        // the regions number <9,17>
489        {0,4,-1,0,1,0,2,15,15},      // 9  .. x=1 y=0 z=0 D
490        {5,1,0,4,-1,0,1,15,15},      // 10 .. x=1 y=0 z=1 D
491        {1,5,-1,0,1,1,2,15,15},      // 11 .. x=1 y=0 z=2 D
492
493        {4,0,2,6,-1,0,2,15,15},      // 12 .. x=1 y=1 z=0 D
494        {0,2,3,1,5,4,6,7,15},        // 13 .. x=1 y=1 z=1 .. inside the box
495        {1,5,7,3,-1,1,2,15,15},      // 14 .. x=1 y=1 z=2 D
496
497        {6,2,-1,0,2,1,1,15,15},      // 15 .. x=1 y=2 z=0 D
498        {6,2,3,7,-1,1,1,15,15},      // 16 .. x=1 y=2 z=1 D
499        {3,7,-1,1,1,1,2,15,15},      // 17 .. x=1 y=2 z=2 D
500
501        // the regions number <18,26>
502        {4,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D
503        {4,5,-1,0,1,1,0,15,15},      // 19 .. x=2 y=0 z=1 D
504        {5,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D
505
506        {4,6,-1,0,2,1,0,15,15},      // 21 .. x=2 y=1 z=0 D
507        {5,4,6,7,-1,1,0,15,15},      // 22 .. x=2 y=1 z=1 D
508        {7,5,-1,1,0,1,2,15,15},      // 23 .. x=2 y=1 z=2 D
509
510        {6,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D
511        {6,7,-1,1,0,1,1,15,15},      // 25 .. x=2 y=2 z=1 D
512        {7,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D
513};
514
515// Table for Sphere-AABB intersection based on the region knowledge
516// Similar array to previous cvertices, but we omit the surfaces
517// which are not necessary for testing. First are vertices,
518// they are finished with -1. Second, there are indexes in
519// the pair (a,b), when a=0, we want to test min vector of the box,
520//                 when a=1, we want to test max vector of the box
521//                 b=0,1,2 corresponds to the axis (0=x,1=y,2=z)
522//
523// So either we check the vertices or only the distance in specified
524// dimensions. There are at all four possible cases:
525//
526//   1) we check one vertex - then sequence start with non-negative index
527//      and is finished with 15
528//   2) we check two coordinates of min/max vector describe by the pair
529//         (a,b) .. a=min/max(0/1) b=x/y/z (0/1/2), sequence starts with 8
530//      and finishes with 15
531//   3) we check only one coordinate of min/max, as for 2), sequence start
532//      with 9 and ends with 15
533//   4) Position 13 - sphere is inside the box, intersection always exist
534//        the sequence start with 15 .. no further testing is necessary
535//        in this case
536const int AxisAlignedBox3::csvertices[27][6] =
537{                        // region number.. position
538        {0,15,15,15,15,15},  // 0 .. x=0 y=0 z=0 D vertex only
539        {8,0,0,0,1,15},      // 1 .. x=0 y=0 z=1 D two coords.
540        {1,15,15,15,15,15},  // 2 .. x=0 y=0 z=2 D vertex only
541
542        {8,0,0,0,2,15},      // 3 .. x=0 y=1 z=0 D two coords
543        {9,0,0,15,15,15},    // 4 .. x=0 y=1 z=1 D one coord
544        {8,0,0,1,2,15},      // 5 .. x=0 y=1 z=2 D two coords.
545
546        {2,15,15,15,15,15},  // 6 .. x=0 y=2 z=0 D one vertex
547        {8,0,0,1,1,15},      // 7 .. x=0 y=2 z=1 D two coords
548        {3,15,15,15,15,15},  // 8 .. x=0 y=2 z=2 D one vertex
549
550        // the regions number <9,17>
551        {8,0,1,0,2,15},      // 9  .. x=1 y=0 z=0 D two coords
552        {9,0,1,15,15,15},    // 10 .. x=1 y=0 z=1 D one coord
553        {8,0,1,1,2,15},      // 11 .. x=1 y=0 z=2 D two coords
554
555        {9,0,2,15,15,15},    // 12 .. x=1 y=1 z=0 D one coord
556        {15,15,15,15,15,15}, // 13 .. x=1 y=1 z=1 inside the box, special case/value
557        {9,1,2,15,15,15},    // 14 .. x=1 y=1 z=2 D one corrd
558
559        {8,0,2,1,1,15},      // 15 .. x=1 y=2 z=0 D two coords
560        {9,1,1,15,15},       // 16 .. x=1 y=2 z=1 D one coord
561        {8,1,1,1,2,15},      // 17 .. x=1 y=2 z=2 D two coords
562
563        // the regions number <18,26>
564        {4,15,15,15,15,15},  // 18 .. x=2 y=0 z=0 D one vertex
565        {8,0,1,1,0,15},      // 19 .. x=2 y=0 z=1 D two coords
566        {5,15,15,15,15,15},  // 20 .. x=2 y=0 z=2 D one vertex
567
568        {8,0,2,1,0,15},      // 21 .. x=2 y=1 z=0 D two coords
569        {9,1,0,15,15,15},    // 22 .. x=2 y=1 z=1 D one coord
570        {8,1,0,1,2,15},      // 23 .. x=2 y=1 z=2 D two coords
571
572        {6,15,15,15,15,15},  // 24 .. x=2 y=2 z=0 D one vertex
573        {8,1,0,1,1,15},      // 25 .. x=2 y=2 z=1 D two coords
574        {7,15,15,15,15,15},  // 26 .. x=2 y=2 z=2 D one vertex
575};
576
577
578// The vertices that form all FARTHEST points with respect to the region
579// for all the regions possible, number of regions is 3^3 = 27,
580// since two parallel sides of bbox forms three disjoint spaces.
581// The vertices are given in anti-clockwise order, stopped by value 15,
582// at most 8 points, at least 1 point.
583// For testing, if the AABB is whole in the sphere, it is enough
584// to test only vertices, either 1,2,4, or 8.
585const int AxisAlignedBox3::fvertices[27][9] =
586{                                // region number.. position
587        {7,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D
588        {6,7,15,15,15,15,15,15,15},  // 1 .. x=0 y=0 z=1 D
589        {6,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D
590
591        {5,7,15,15,15,15,15,15,15},  // 3 .. x=0 y=1 z=0 D
592        {4,5,7,6,15,15,15,15,15},    // 4 .. x=0 y=1 z=1 D
593        {4,6,15,15,15,15,15,15,15},  // 5 .. x=0 y=1 z=2 D
594
595        {5,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D
596        {4,5,15,15,15,15,15,15,15},  // 7 .. x=0 y=2 z=1 D
597        {4,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D
598
599        // the regions number <9,17>
600        {3,7,15,15,15,15,15,15,15},  // 9  .. x=1 y=0 z=0 D
601        {7,3,2,6,15,15,15,15,15},    // 10 .. x=1 y=0 z=1 D
602        {2,6,15,15,15,15,15,15,15},  // 11 .. x=1 y=0 z=2 D
603
604        {5,1,3,7,15,15,15,15,15},    // 12 .. x=1 y=1 z=0 D
605        {0,7,1,6,3,4,5,2,15},        // 13 .. x=1 y=1 z=1 .. inside the box
606        {0,4,6,2,15,15,15,15,15},    // 14 .. x=1 y=1 z=2 D
607
608        {5,1,15,15,15,15,15,15,15},  // 15 .. x=1 y=2 z=0 D
609        {4,0,1,5,15,15,15,15,15},    // 16 .. x=1 y=2 z=1 D
610        {4,0,15,15,15,15,15,15,15},  // 17 .. x=1 y=2 z=2 D
611
612        // the regions number <18,26>
613        {3,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D
614        {2,3,15,15,15,15,15,15,15},  // 19 .. x=2 y=0 z=1 D
615        {2,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D
616
617        {1,3,15,15,15,15,15,15,15},  // 21 .. x=2 y=1 z=0 D
618        {1,0,2,3,15,15,15,15,15},    // 22 .. x=2 y=1 z=1 D
619        {2,0,15,15,15,15,15,15,15},  // 23 .. x=2 y=1 z=2 D
620
621        {1,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D
622        {0,1,15,15,15,15,15,15,15},  // 25 .. x=2 y=2 z=1 D
623        {0,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D
624};
625
626// Similar table as above, farthest points, but only the ones
627// necessary for testing the intersection problem. If we do
628// not consider the case 13, center of the sphere is inside the
629// box, then we can always test at most 2 box vertices to say whether
630// the whole box is inside the sphere.
631// The number of vertices is minimized using some assumptions
632// about the ortogonality of vertices and sphere properties.
633const int AxisAlignedBox3::fsvertices[27][9] =
634{                                // region number.. position
635        {7,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D 1 vertex
636        {6,7,15,15,15,15,15,15,15},  // 1 .. x=0 y=0 z=1 D 2 vertices
637        {6,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D 1 vertex
638
639        {5,7,15,15,15,15,15,15,15},  // 3 .. x=0 y=1 z=0 D 2 vertices
640        {4,7,15,5,6,15,15,15,15},    // 4 .. x=0 y=1 z=1 D 4/2 vertices
641        {4,6,15,15,15,15,15,15,15},  // 5 .. x=0 y=1 z=2 D 2 vertices
642
643        {5,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D 1 vertex
644        {4,5,15,15,15,15,15,15,15},  // 7 .. x=0 y=2 z=1 D 2 vertices
645        {4,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D 1 vertex
646
647        // the regions number <9,17>
648        {3,7,15,15,15,15,15,15,15},  // 9  .. x=1 y=0 z=0 D 2 vertices
649        {7,2,15,3,6,15,15,15,15},    // 10 .. x=1 y=0 z=1 D 4/2 vertices
650        {2,6,15,15,15,15,15,15,15},  // 11 .. x=1 y=0 z=2 D 2 vertices
651
652        {5,3,15,1,7,15,15,15,15},    // 12 .. x=1 y=1 z=0 D 4/2 vertices
653        {0,7,1,6,3,4,5,2,15},        // 13 .. x=1 y=1 z=1 .. inside the box
654        {0,6,15,4,2,15,15,15,15},    // 14 .. x=1 y=1 z=2 D 4/2 vertices
655
656        {5,1,15,15,15,15,15,15,15},  // 15 .. x=1 y=2 z=0 D 2 vertices
657        {4,1,15,0,5,15,15,15,15},    // 16 .. x=1 y=2 z=1 D 4/2 vertices
658        {4,0,15,15,15,15,15,15,15},  // 17 .. x=1 y=2 z=2 D 2 vertices
659
660        // the regions number <18,26>
661        {3,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D 1 vertex
662        {2,3,15,15,15,15,15,15,15},  // 19 .. x=2 y=0 z=1 D 2 vertices
663        {2,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D 1 vertex
664
665        {1,3,15,15,15,15,15,15,15},  // 21 .. x=2 y=1 z=0 D 2 vertices
666        {1,2,15,0,3,15,15,15,15},    // 22 .. x=2 y=1 z=1 D 4/2 vertices
667        {2,0,15,15,15,15,15,15,15},  // 23 .. x=2 y=1 z=2 D 2 vertices
668
669        {1,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D 1 vertex
670        {0,1,15,15,15,15,15,15,15},  // 25 .. x=2 y=2 z=1 D 2 vertices
671        {0,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D 1 vertex
672};
673
674
675// The fast computation of arctangent .. the maximal error is less
676// than 4.1 degrees, according to Graphics GEMSII, 1991, pages 389--391
677// Ron Capelli: "Fast approximation to the arctangent"
678float atan22(const float& y)
679{
680        const float x = 1.0;
681        const float c = (float)(M_PI * 0.25);
682
683        if (y < 0.0)
684        {
685                if (y < -1.0)
686                        return c * (-2.0f + x / y); // for angle in <-PI/2, -PI/4)
687                else
688                        return c * (y / x); // for angle in <-PI/4 , 0>
689        }
690        else
691        {
692                if (y > 1.0)
693                        return c * (2.0f - x / y); // for angle in <PI/4, PI/2>
694                else
695                        return c * (y / x); // for angle in <0, PI/2>
696        }
697}
698
699
700// This definition allows to be a point when answering true
701bool AxisAlignedBox3::IsCorrectAndNotPoint() const
702{
703        if ((mMin.x > mMax.x) ||
704                (mMin.y > mMax.y) ||
705                (mMin.z > mMax.z))
706        {
707                return false; // box is not formed
708        }
709
710        if ((mMin.x == mMax.x) &&
711                (mMin.y == mMax.y) &&
712                (mMin.z == mMax.z))
713        {
714                return false; // degenerates to a point
715        }
716
717        return true;
718}
719
720// This definition allows to be a point when answering true
721bool AxisAlignedBox3::IsPoint() const
722{
723        if ((mMin.x == mMax.x) &&
724                (mMin.y == mMax.y) &&
725                (mMin.z == mMax.z))
726        {
727                return true; // degenerates to a point
728        }
729
730        return false;
731}
732
733// This definition requires shape of non-zero volume
734bool AxisAlignedBox3::IsSingularOrIncorrect() const
735{
736        if ((mMin.x >= mMax.x) ||
737                (mMin.y >= mMax.y) ||
738                (mMin.z >= mMax.z))
739        {
740                return true; // box is not formed
741        }
742
743        return false; // has non-zero volume
744}
745
746
747void AxisAlignedBox3::GetSqrDistances(const Vector3 &point,
748                                                                          float &minDistance,
749                                                                          float &maxDistance) const
750{
751        // some overlap is possible, check the distance of vertices
752        float sumMin = 0;
753        float sumMax = 0;
754
755        // Try to minimize the function of a distance
756        // from the sphere center
757
758        const float *minp = &(mMin.x);
759        const float *maxp = &(mMax.x);
760        const float *pcenter = &(point.x);
761
762        // for x-axis
763        for (int i = 0; i < 3; i ++, minp ++, maxp ++, pcenter ++)
764        {
765                float minsqr = sqr(*minp - *pcenter);
766                float maxsqr = sqr(*maxp - *pcenter);
767
768                if (*pcenter < *minp)
769                {               
770                        sumMin += minsqr;
771                }
772                else
773                {
774                        if (*pcenter > *maxp) sumMin += maxsqr;
775                }
776
777                sumMax += (minsqr > maxsqr) ? minsqr : maxsqr;
778        }
779
780        minDistance = sumMin;
781        maxDistance = sumMax;
782}
783
784
785void AxisAlignedBox3::Scale(float scale)
786{
787        Vector3 newSize = Size() * (scale * 0.5f);
788        Vector3 center = Center();
789
790        mMin = center - newSize;
791        mMax = center + newSize;
792}
793
794
795void AxisAlignedBox3::Scale(const Vector3 &scale)
796{
797        Vector3 newSize = Size() * (scale * 0.5f);
798        Vector3 center = Center();
799
800        mMin = center - newSize;
801        mMax = center + newSize;
802}
803
804
805void AxisAlignedBox3::Translate(const Vector3 &shift)
806{
807        mMin += shift;
808        mMax += shift;
809}
810
811
812void AxisAlignedBox3::Initialize()
813{
814        mMin = Vector3(MAXFLOAT);
815        mMax = Vector3(-MAXFLOAT);
816}
817
818
819Vector3 AxisAlignedBox3::Center() const
820{
821        return 0.5 * (mMin + mMax);
822}
823
824
825Vector3 AxisAlignedBox3::Diagonal() const
826{
827        return (mMax - mMin);
828}
829
830
831float AxisAlignedBox3::Center(int axis) const
832{
833        return  0.5f * (mMin[axis] + mMax[axis]);
834}
835
836
837float AxisAlignedBox3::Min(int axis) const
838{
839        return mMin[axis];
840}
841
842
843float AxisAlignedBox3::Max(int axis) const
844{
845        return  mMax[axis];
846}
847
848
849float AxisAlignedBox3::Size(int axis) const
850{
851        return  Max(axis) - Min(axis);
852}
853
854// Read-only const access tomMin and max vectors using references
855const Vector3& AxisAlignedBox3::Min() const
856{
857        return mMin;
858}
859
860
861const Vector3& AxisAlignedBox3::Max() const
862{
863        return mMax;
864}
865
866
867void AxisAlignedBox3::Enlarge (const Vector3 &v)
868{
869        mMax += v;
870        mMin -= v;
871}
872
873
874void AxisAlignedBox3::EnlargeToMinSize()
875{
876        const float epsMin = 1e-7f;
877        const float epsAdd = 1e-6f;
878        const float epsMul = 1.000005f;
879       
880        float dir = mMax.x - mMin.x;
881
882        assert(dir >= 0.f);
883
884        if (dir < epsMin)
885        {
886                if (mMax.x > 0)
887                {
888                        mMax.x *= epsMul;
889                        mMax.x += epsAdd;
890                }
891                else
892                {
893                        mMin.x *= epsMul;
894                        mMin.x -= epsAdd;
895                }
896               
897                assert(mMin.x < mMax.x);
898        }
899
900        dir = mMax.y - mMin.y;
901        assert(dir >= 0.f);
902       
903        if (dir < epsMin)
904        {
905                if (mMax.y > 0)
906                {
907                        mMax.y *= epsMul;
908                        mMax.y += epsAdd;
909                }
910                else
911                {
912                        mMin.y *= epsMul;
913                        mMin.y -= epsAdd;
914                }
915                assert(mMin.y < mMax.y);
916        }
917       
918        dir = mMax.z - mMin.z;
919        assert(dir >= 0.f);
920       
921        if (dir < epsMin)
922        {
923                if (mMax.z > 0)
924                {
925                        mMax.z *= epsMul;
926                        mMax.z += epsAdd;
927                }
928                else
929                {
930                        mMin.z *= epsMul;
931                        mMin.z -= epsAdd;
932                }
933               
934                assert(mMin.z < mMax.z);
935        }
936}
937
938
939void AxisAlignedBox3::SetMin(const Vector3 &v)
940{
941        mMin = v;
942}
943
944
945void AxisAlignedBox3::SetMax(const Vector3 &v)
946{
947        mMax = v;
948}
949
950
951void AxisAlignedBox3::SetMin(int axis, float value)
952{
953        mMin[axis] = value;
954}
955
956
957void AxisAlignedBox3::SetMax(int axis, float value)
958{
959        mMax[axis] = value;
960}
961
962
963// Decrease box by given splitting plane
964void AxisAlignedBox3::Reduce(int axis, int right, float value)
965{
966        if ((value >= mMin[axis]) && (value <= mMax[axis]))
967        {
968                if (right)
969                        mMin[axis] = value;
970                else
971                        mMax[axis] = value;
972        }
973}
974
975
976Vector3 AxisAlignedBox3::Size() const
977{
978        return mMax - mMin;
979}
980
981
982Vector3 AxisAlignedBox3::GetRandomPoint() const
983{
984        Vector3 size = Size();
985
986        return mMin + Vector3(RandomValue(0.0f, 1.0f),
987                                  RandomValue(0.0f, 1.0f),
988                                                  RandomValue(0.0f, 1.0f)) * Size();
989}
990
991
992bool AxisAlignedBox3::Intersects(const Vector3 &lStart,
993                                                                 const Vector3 &lEnd) const
994{
995        float st, et, fst = 0, fet = 1;
996        float const *bmin = &mMin.x;
997        float const *bmax = &mMax.x;
998        float const *si = &lStart.x;
999        float const *ei = &lEnd.x;
1000
1001        for (int i = 0; i < 3; ++ i)
1002        {
1003                if (*si < *ei)
1004                {
1005                        if (*si > *bmax || *ei < *bmin) return false;
1006
1007                        const float di = *ei - *si;
1008
1009                        st = (*si < *bmin)? (*bmin - *si) / di : 0;
1010                        et = (*ei > *bmax)? (*bmax - *si) / di : 1;
1011                }
1012                else
1013                {
1014                        if (*ei > *bmax || *si < *bmin) return false;
1015
1016                        const float di = *ei - *si;
1017
1018                        st = (*si > *bmax)? (*bmax - *si) / di : 0;
1019                        et = (*ei < *bmin)? (*bmin - *si) / di : 1;
1020                }
1021
1022                if (st > fst) fst = st;
1023                if (et < fet) fet = et;
1024                if (fet < fst) return false;
1025
1026                ++ bmin; ++ bmax;
1027                ++ si; ++ ei;
1028        }
1029
1030        return true;
1031}
1032
1033
1034Vector3 AxisAlignedBox3::GetVertex(const int N) const
1035{
1036        Vector3 v;
1037        GetVertex(N, v);
1038
1039        return v;
1040}
1041
1042
1043float AxisAlignedBox3::GetExtent(int face) const
1044{
1045        if (face < 3)
1046                return mMin[face];
1047        else
1048                return mMax[face - 3];
1049}
1050
1051
1052int AxisAlignedBox3::GetIndexNearestVertex(const Vector3 &vecPlaneNormal)
1053{
1054        int x, y, z;
1055
1056        x = (vecPlaneNormal.x > 0.0f) ? 0 : 1;
1057        y = (vecPlaneNormal.y > 0.0f) ? 0 : 1;
1058        z = (vecPlaneNormal.z > 0.0f) ? 0 : 1;
1059       
1060        return 4 * x + 2 * y + z;
1061}
1062
1063
1064int AxisAlignedBox3::GetIndexFarthestVertex(const Vector3 &vecPlaneNormal)
1065{
1066        int x, y, z;
1067
1068        x = (vecPlaneNormal.x <= 0.0f) ? 0 : 1;
1069        y = (vecPlaneNormal.y <= 0.0f) ? 0 : 1;
1070        z = (vecPlaneNormal.z <= 0.0f) ? 0 : 1;
1071       
1072        return 4 * x + 2 * y + z;
1073}
1074
1075
1076float AxisAlignedBox3::GetDistance(int index, const Plane3 &plane) const
1077{
1078        return plane.Distance(GetVertex(index));
1079}
1080
1081
1082float AxisAlignedBox3::GetMinDistance(const Plane3 &near) const
1083{
1084        return  near.mNormal.x * ((near.mNormal.x > 0.0f) ? mMin.x : mMax.x) +
1085                        near.mNormal.y * ((near.mNormal.y > 0.0f) ? mMin.y : mMax.y) +
1086                        near.mNormal.z * ((near.mNormal.z > 0.0f) ? mMin.z : mMax.z) +
1087                        near.mD;
1088}
1089
1090
1091float AxisAlignedBox3::GetMaxDistance(const Plane3 &near) const
1092{
1093        return  near.mNormal.x * ((near.mNormal.x <= 0.0f) ? mMin.x : mMax.x) +
1094                        near.mNormal.y * ((near.mNormal.y <= 0.0f) ? mMin.y : mMax.y) +
1095                        near.mNormal.z * ((near.mNormal.z <= 0.0f) ? mMin.z : mMax.z) +
1096                        near.mD;
1097}
1098
1099
1100struct VertexData
1101{
1102        Vector3 mVertex;
1103        float mAngle;
1104       
1105        VertexData(Vector3 vtx, float angle): mVertex(vtx), mAngle(angle)
1106        {}
1107
1108        bool operator<(const VertexData &b) const
1109        {
1110                return mAngle > b.mAngle;
1111        }
1112};
1113
1114// TODO: use a table to avoid normal and distance computations
1115Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) const
1116{
1117        Polygon3 *planePoly = new Polygon3();
1118       
1119        int side[8];
1120        bool onFrontSide = false, onBackSide = false;
1121       
1122        Vector3 vtx;
1123       
1124        //////////////
1125        //-- compute classification of vertices
1126
1127        for (int i = 0; i < 8; ++ i)
1128        {
1129                GetVertex(i, vtx);
1130                side[i] = plane.Side(vtx);
1131
1132                if (side[i] > 0)
1133                        onFrontSide = true;
1134                else if (side[i] < 0)
1135                        onBackSide = true;
1136                else // vertex coincident => push_back
1137                        planePoly->mVertices.push_back(vtx);
1138        }
1139
1140        ///////////
1141        //-- find intersections
1142
1143        if (onFrontSide && onBackSide)
1144        {
1145                Vector3 ptA, ptB;
1146
1147                for (int i = 0; i < 12; ++ i)
1148                {
1149                        int aIdx, bIdx;
1150                        GetEdge(i, aIdx, bIdx);
1151
1152                        ptA = GetVertex(aIdx);
1153                        ptB = GetVertex(bIdx);
1154
1155                        int sideA = side[aIdx];
1156                        int sideB = side[bIdx];
1157
1158                        if (((sideA > 0) && (sideB < 0)) || (sideA < 0) && (sideB > 0))
1159                                planePoly->mVertices.push_back(plane.FindIntersection(ptA, ptB));       
1160                }
1161        }
1162
1163        // order intersections 
1164        if (planePoly->mVertices.size() > 3)
1165        {
1166                Vector3 centerOfMass(0);
1167
1168                int i;
1169                // compute center of mass
1170                for (i = 0; i < (int)planePoly->mVertices.size(); ++ i)
1171                {
1172                        centerOfMass += planePoly->mVertices[i];
1173                }
1174
1175                centerOfMass /= (float)planePoly->mVertices.size();
1176
1177                vector<VertexData> vertexData;
1178                Vector3 refVec = Normalize(centerOfMass - planePoly->mVertices[0]);
1179
1180                // compute angle to reference point
1181                for (i = 1; i < (int)planePoly->mVertices.size(); ++ i)
1182                {
1183                    float angle =
1184                                Angle(refVec, centerOfMass - planePoly->mVertices[i], plane.mNormal);
1185                   
1186                    vertexData.push_back(VertexData(planePoly->mVertices[i], angle));
1187                }
1188               
1189                std::stable_sort(vertexData.begin(), vertexData.end());
1190
1191                // update vertices
1192                for (i = 1; i < (int)planePoly->mVertices.size(); ++ i)
1193                {
1194                        planePoly->mVertices[i] = vertexData[i - 1].mVertex;
1195                }
1196        }
1197        else if (planePoly->mVertices.size() == 3)
1198        {
1199                // fix orientation if needed
1200                if (DotProd(planePoly->GetNormal(), plane.mNormal) < 0)
1201                {
1202                        Vector3 v = planePoly->mVertices[1];
1203                        planePoly->mVertices[1] = planePoly->mVertices[2];
1204                        planePoly->mVertices[2] = v;
1205                }
1206        }
1207       
1208        return planePoly;
1209}
1210
1211
1212Plane3 AxisAlignedBox3::GetPlane(int face) const
1213{
1214        switch (face)
1215        {
1216        case 0:
1217                return Plane3(Vector3(0, -1, 0), mMin);
1218        case 1:
1219                return Plane3(Vector3(0, 1, 0), mMax);
1220        case 2:
1221                return Plane3(Vector3(-1, 0, 0), mMin);
1222        case 3:
1223                return Plane3(Vector3(1, 0, 0), mMax);
1224        case 4:
1225                return Plane3(Vector3(0, 0, -1), mMin);
1226        case 5:
1227                return Plane3(Vector3(0, 0, 1), mMax);
1228        }
1229
1230        // should not come here
1231        return Plane3();
1232}
1233
1234
1235int AxisAlignedBox3::Side(const Plane3 &plane) const
1236{
1237        int s = 0;
1238        // if exactly one of the vertices lies on the plane
1239        // and the others are on the same side, the plane is tangent
1240        // to the box on either side and not intersecting
1241        for (int i = 0; i < 8; ++ i)
1242        {
1243                Vector3 pt;
1244                GetVertex(i, pt);
1245
1246                int side = plane.Side(pt);
1247
1248                if (side != 0)
1249                {
1250                        if (side == -s)
1251                                return 0; // sign changed => intersects
1252
1253                        s = side;
1254                }
1255        }
1256
1257        return s;
1258}
1259
1260
1261Polyhedron *AxisAlignedBox3::CalcIntersection(const Polyhedron &polyhedron) const
1262{
1263        Polyhedron *oldPolyhedron = new Polyhedron(polyhedron);
1264        Polyhedron *newPolyhedron = NULL;
1265
1266        for (int i = 0; i < 6; ++ i)
1267        {
1268                newPolyhedron = oldPolyhedron->CalcIntersection(GetPlane(i));
1269
1270                if (!newPolyhedron || !newPolyhedron->Valid())
1271                {
1272                        DEL_PTR(newPolyhedron);
1273                        //cerr << "polyhedron not valid or NULL!" << endl;
1274                        return NULL;   
1275                }
1276
1277                DEL_PTR(oldPolyhedron);
1278                oldPolyhedron = newPolyhedron;
1279        }
1280
1281        return newPolyhedron;
1282}
1283
1284
1285bool AxisAlignedBox3::Intersects(const SimpleRay &ray,
1286                                                                 float &tnear,
1287                                                                 float &tfar) const
1288{
1289        tnear = -1e20f;
1290        tfar = 1e20f;
1291
1292        const Vector3 origin = ray.mOrigin;
1293        const Vector3 dir = ray.mDirection;
1294
1295        float t1, t2;
1296
1297        // ray is parallel to the planes
1298        if (dir.x == 0)
1299        {
1300                if ((origin.x < mMin.x) || (origin.x > mMax.x))
1301                {
1302                        return false; // origin not between planes
1303                }
1304        }
1305        else
1306        {
1307                // time at which ray intersects minimum X plane
1308                t1 = (mMin.x - origin.x) / dir.x;
1309                // time at which ray intersects maximum X plane
1310                t2 = (mMax.x - origin.x) / dir.x;
1311               
1312                if (t1 > t2) swap(t1, t2);
1313                if (t1 > tnear) tnear = t1;
1314                if (t2 < tfar) tfar = t2;
1315                if (tnear > tfar) return false;
1316                if (tfar < 0) return false;
1317        }
1318
1319        if (dir.y == 0) // ray is parallel to the planes
1320        {
1321                if ((origin.y < mMin.y) || (origin.y > mMax.y))
1322                {
1323                        return false; // origin not between planes)
1324                }
1325        }
1326        else
1327        {
1328                t1 = (mMin.y - origin.y) / dir.y;
1329                t2 = (mMax.y - origin.y) / dir.y;
1330               
1331                if (t1 > t2) swap(t1, t2);
1332                if (t1 > tnear) tnear = t1;
1333                if (t2 < tfar) tfar = t2;
1334                if (tnear > tfar) return false;
1335                if (tfar < 0) return false;
1336        }
1337
1338        if (dir.z == 0) // ray is parallel to the planes
1339        {
1340                if ((origin.z < mMin.z) || (origin.z > mMax.z))
1341                {
1342                        return false; // origin not between planes)
1343                }
1344        }
1345        else
1346        {
1347                t1 = (mMin.z - origin.z) / dir.z;
1348                t2 = (mMax.z - origin.z) / dir.z;
1349               
1350                if (t1 > t2) swap(t1, t2);
1351                if (t1 > tnear) tnear = t1;
1352                if (t2 < tfar) tfar = t2;
1353                if (tnear > tfar) return false;
1354                if (tfar < 0) return false;
1355        }
1356
1357        return true;
1358}
1359
1360
1361void AxisAlignedBox3::ExtractPolygons(PolygonContainer &polys) const
1362{
1363        Polygon3 *face1 = new Polygon3();
1364        polys.push_back(face1);   
1365
1366    face1->mVertices.push_back(Vector3(mMin.x, mMin.y, mMax.z));
1367        face1->mVertices.push_back(Vector3(mMin.x, mMax.y, mMax.z));
1368        face1->mVertices.push_back(Vector3(mMin.x, mMax.y ,mMin.z));
1369        face1->mVertices.push_back(Vector3(mMin.x, mMin.y, mMin.z));
1370
1371        Polygon3 *face2 = new Polygon3(); 
1372        polys.push_back(face2);
1373   
1374    face2->mVertices.push_back(Vector3(mMax.x, mMin.y, mMin.z));
1375    face2->mVertices.push_back(Vector3(mMax.x, mMax.y, mMin.z));
1376    face2->mVertices.push_back(Vector3(mMax.x, mMax.y, mMax.z));
1377    face2->mVertices.push_back(Vector3(mMax.x, mMin.y, mMax.z));
1378 
1379        Polygon3 *face3 = new Polygon3(); 
1380        polys.push_back(face3);
1381
1382    face3->mVertices.push_back(Vector3(mMax.x, mMin.y ,mMin.z));
1383        face3->mVertices.push_back(Vector3(mMax.x, mMin.y, mMax.z));
1384        face3->mVertices.push_back(Vector3(mMin.x, mMin.y, mMax.z));
1385        face3->mVertices.push_back(Vector3(mMin.x, mMin.y, mMin.z));
1386
1387        Polygon3 *face4 = new Polygon3(); 
1388        polys.push_back(face4);
1389
1390        face4->mVertices.push_back(Vector3(mMin.x, mMax.y, mMin.z));
1391        face4->mVertices.push_back(Vector3(mMin.x, mMax.y, mMax.z));
1392        face4->mVertices.push_back(Vector3(mMax.x, mMax.y, mMax.z));
1393        face4->mVertices.push_back(Vector3(mMax.x, mMax.y, mMin.z));
1394   
1395        Polygon3 *face5 = new Polygon3(); 
1396        polys.push_back(face5);
1397
1398        face5->mVertices.push_back(Vector3(mMin.x, mMax.y, mMin.z));
1399    face5->mVertices.push_back(Vector3(mMax.x, mMax.y, mMin.z));
1400    face5->mVertices.push_back(Vector3(mMax.x, mMin.y, mMin.z));
1401        face5->mVertices.push_back(Vector3(mMin.x, mMin.y, mMin.z));
1402
1403        Polygon3 *face6 = new Polygon3(); 
1404        polys.push_back(face6); 
1405 
1406    face6->mVertices.push_back(Vector3(mMin.x, mMin.y, mMax.z));
1407    face6->mVertices.push_back(Vector3(mMax.x, mMin.y, mMax.z));
1408    face6->mVertices.push_back(Vector3(mMax.x, mMax.y, mMax.z));
1409    face6->mVertices.push_back(Vector3(mMin.x, mMax.y, mMax.z));
1410}
1411
1412
1413void AxisAlignedBox3::Triangulate(std::vector<Triangle3> &triangles) const
1414{
1415        Triangle3 tri;
1416
1417        tri.mVertices[0] = Vector3(mMin.x, mMax.y ,mMin.z);
1418        tri.mVertices[1] = Vector3(mMin.x, mMax.y, mMax.z);
1419        tri.mVertices[2] = Vector3(mMin.x, mMin.y, mMax.z);
1420
1421        triangles.push_back(tri);
1422
1423    tri.mVertices[0] = Vector3(mMin.x, mMin.y, mMax.z);
1424        tri.mVertices[1] = Vector3(mMin.x, mMin.y, mMin.z);
1425        tri.mVertices[2] = Vector3(mMin.x, mMax.y ,mMin.z);
1426
1427        triangles.push_back(tri);
1428
1429        //////////////////////////////////////
1430
1431    tri.mVertices[0] = Vector3(mMax.x, mMax.y, mMax.z);
1432    tri.mVertices[1] = Vector3(mMax.x, mMax.y, mMin.z);
1433        tri.mVertices[2] = Vector3(mMax.x, mMin.y, mMin.z);
1434
1435        triangles.push_back(tri);
1436
1437        tri.mVertices[0] = Vector3(mMax.x, mMin.y, mMin.z);
1438        tri.mVertices[1] = Vector3(mMax.x, mMin.y, mMax.z);
1439    tri.mVertices[2] = Vector3(mMax.x, mMax.y, mMax.z);
1440
1441        triangles.push_back(tri);
1442
1443
1444        //////////////////////////////////////
1445
1446        tri.mVertices[0] = Vector3(mMin.x, mMin.y, mMax.z);
1447        tri.mVertices[1] = Vector3(mMax.x, mMin.y, mMax.z);
1448    tri.mVertices[2] = Vector3(mMax.x, mMin.y ,mMin.z);
1449
1450        triangles.push_back(tri);
1451
1452    tri.mVertices[0] = Vector3(mMax.x, mMin.y ,mMin.z);
1453        tri.mVertices[1] = Vector3(mMin.x, mMin.y, mMin.z);
1454        tri.mVertices[2] = Vector3(mMin.x, mMin.y, mMax.z);     
1455
1456        triangles.push_back(tri);
1457
1458
1459        //////////////////////////////////////
1460
1461        tri.mVertices[0] = Vector3(mMax.x, mMax.y, mMax.z);
1462        tri.mVertices[1] = Vector3(mMin.x, mMax.y, mMax.z);
1463        tri.mVertices[2] = Vector3(mMin.x, mMax.y, mMin.z);
1464
1465        triangles.push_back(tri);
1466
1467        tri.mVertices[0] = Vector3(mMin.x, mMax.y, mMin.z);
1468        tri.mVertices[1] = Vector3(mMax.x, mMax.y, mMin.z);
1469        tri.mVertices[2] = Vector3(mMax.x, mMax.y, mMax.z);
1470   
1471        triangles.push_back(tri);
1472
1473
1474        //////////////////////////////////////
1475
1476    tri.mVertices[0] = Vector3(mMax.x, mMin.y, mMin.z);
1477        tri.mVertices[1] = Vector3(mMax.x, mMax.y, mMin.z);
1478        tri.mVertices[2] = Vector3(mMin.x, mMax.y, mMin.z);
1479           
1480        triangles.push_back(tri);
1481
1482        tri.mVertices[0] = Vector3(mMin.x, mMax.y, mMin.z);
1483        tri.mVertices[1] = Vector3(mMin.x, mMin.y, mMin.z);
1484    tri.mVertices[2] = Vector3(mMax.x, mMin.y, mMin.z);
1485           
1486        triangles.push_back(tri);
1487
1488
1489        //////////////////////////////////////
1490
1491    tri.mVertices[0] = Vector3(mMax.x, mMax.y, mMax.z);
1492        tri.mVertices[1] = Vector3(mMax.x, mMin.y, mMax.z);
1493    tri.mVertices[2] = Vector3(mMin.x, mMin.y, mMax.z);
1494
1495        triangles.push_back(tri);
1496
1497    tri.mVertices[0] = Vector3(mMin.x, mMin.y, mMax.z);
1498    tri.mVertices[1] = Vector3(mMin.x, mMax.y, mMax.z);
1499    tri.mVertices[2] = Vector3(mMax.x, mMax.y, mMax.z);
1500           
1501        triangles.push_back(tri);
1502}
1503
1504
1505int AxisAlignedBox3::MajorAxis() const
1506{
1507        const Vector3 sizeVec = mMax - mMin;
1508
1509        int axis;
1510
1511        if (sizeVec.x > sizeVec.y) axis = (sizeVec.x > sizeVec.z) ? 0 : 2;
1512        else axis = (sizeVec.y > sizeVec.z) ? 1 : 2;
1513
1514        return axis;
1515}
1516
1517
1518}
1519
Note: See TracBrowser for help on using the repository browser.