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

Revision 2951, 38.7 KB checked in by mattausch, 16 years ago (diff)

strted to implement animation

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