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

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