root/trunk/dep/src/g3dlite/AABox.cpp @ 2

Revision 2, 7.4 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/**
2  @file AABox.cpp
3
4  @maintainer Morgan McGuire, matrix@graphics3d.com
5
6  @created 2004-01-10
7  @edited  2006-01-11
8*/
9
10#include "G3D/platform.h"
11#   if defined(_MSC_VER) && (_MSC_VER <= 1200)
12        // VC6 std:: has signed/unsigned problems
13#       pragma warning (disable : 4018)
14#   endif
15
16#include <assert.h>
17#include "G3D/AABox.h"
18#include "G3D/Box.h"
19#include "G3D/Plane.h"
20#include "G3D/Sphere.h"
21
22
23namespace G3D {
24
25Box AABox::toBox() const {
26    return Box(lo, hi);
27}
28
29
30
31void AABox::split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const {
32    // Low, medium, and high along the chosen axis
33    float L = G3D::min(location, lo[axis]);
34    float M = G3D::min(G3D::max(location, lo[axis]), hi[axis]);
35    float H = G3D::max(location, hi[axis]);
36
37    // Copy over this box.
38    high = low = *this;
39
40    // Now move the split points along the special axis
41    low.lo[axis] = L;
42    low.hi[axis] = M;
43    high.lo[axis] = M;
44    high.hi[axis] = H;
45}
46
47#if 0
48Vector3 AABox::randomSurfacePoint() const {
49    Vector3 extent = hi - lo;
50    float aXY = extent.x * extent.y;
51    float aYZ = extent.y * extent.z;
52    float aZX = extent.z * extent.x;
53
54    float r = (float)random(0, aXY + aYZ + aZX);
55
56    // Choose evenly between positive and negative face planes
57    float d = ((float)random(0, 1) < 0.5f) ? 0.0f : 1.0f;
58
59    // The probability of choosing a given face is proportional to
60    // its area.
61    if (r < aXY) {
62        return
63            lo +
64            Vector3(
65                (float)random(0, extent.x),
66                (float)random(0, extent.y),
67                d * extent.z);
68    } else if (r < aYZ) {
69        return
70            lo +
71            Vector3(
72                d * extent.x,
73                (float)random(0, extent.y),
74                (float)random(0, extent.z));
75    } else {
76        return
77            lo +
78            Vector3(
79                (float)random(0, extent.x),
80                d * extent.y,
81                (float)random(0, extent.z));
82    }
83}
84
85
86Vector3 AABox::randomInteriorPoint() const {
87    return Vector3(
88        (float)random(lo.x, hi.x),
89        (float)random(lo.y, hi.y),
90        (float)random(lo.z, hi.z));
91}
92#endif
93
94
95bool AABox::intersects(const AABox& other) const {
96    // Must be overlap along all three axes.
97    // Try to find a separating axis.
98
99    for (int a = 0; a < 3; ++a) {
100
101        //     |--------|
102        // |------|
103
104        if ((lo[a] > other.hi[a]) ||
105            (hi[a] < other.lo[a])) {
106            return false;
107        }
108    }
109
110    return true;
111}
112
113
114bool AABox::culledBy(
115    const Array<Plane>&         plane,
116        int&                                cullingPlaneIndex,
117        const uint32                    inMask,
118        uint32&                                 outMask) const {
119
120        return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask, outMask);
121}
122
123
124bool AABox::culledBy(
125    const Array<Plane>&         plane,
126        int&                                cullingPlaneIndex,
127        const uint32                    inMask) const {
128
129        return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask);
130}
131
132
133int AABox::dummy = 0;
134
135
136bool AABox::culledBy(
137    const class Plane*  plane,
138    int                 numPlanes,
139        int&                            cullingPlane,
140        const uint32            _inMask,
141    uint32&             childMask) const {
142
143        uint32 inMask = _inMask;
144        assert(numPlanes < 31);
145
146    childMask = 0;
147
148    const bool finite = 
149        (abs(lo.x) < G3D::inf()) &&
150        (abs(hi.x) < G3D::inf()) &&
151        (abs(lo.y) < G3D::inf()) &&
152        (abs(hi.y) < G3D::inf()) &&
153        (abs(lo.z) < G3D::inf()) &&
154        (abs(hi.z) < G3D::inf());
155
156    // See if there is one plane for which all of the
157        // vertices are in the negative half space.
158    for (int p = 0; p < numPlanes; p++) {
159
160                // Only test planes that are not masked
161                if ((inMask & 1) != 0) {
162               
163                        Vector3 corner;
164
165            int numContained = 0;
166            int v = 0;
167
168            // We can early-out only if we have found one point on each
169            // side of the plane (i.e. if we are straddling).  That
170            // occurs when (numContained < v) && (numContained > 0)
171                        for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
172                // Unrolling these 3 if's into a switch decreases performance
173                // by about 2x
174                                corner.x = (v & 1) ? hi.x : lo.x;
175                                corner.y = (v & 2) ? hi.y : lo.y;
176                                corner.z = (v & 4) ? hi.z : lo.z;
177       
178                if (finite) { // this branch is highly predictable
179                    if (plane[p].halfSpaceContainsFinite(corner)) {
180                        ++numContained;
181                    }
182                } else {
183                    if (plane[p].halfSpaceContains(corner)) {
184                        ++numContained;
185                    }
186                }
187                        }
188
189                        if (numContained == 0) {
190                                // Plane p culled the box
191                                cullingPlane = p;
192
193                // The caller should not recurse into the children,
194                // since the parent is culled.  If they do recurse,
195                // make them only test against this one plane, which
196                // will immediately cull the volume.
197                childMask = 1 << p;
198                                return true;
199
200            } else if (numContained < v) {
201                // The bounding volume straddled the plane; we have
202                // to keep testing against this plane
203                childMask |= (1 << p);
204            }
205                }
206
207        // Move on to the next bit.
208                inMask = inMask >> 1;
209    }
210
211    // None of the planes could cull this box
212        cullingPlane = -1;
213    return false;
214}
215
216
217bool AABox::culledBy(
218    const class Plane*  plane,
219    int                 numPlanes,
220        int&                            cullingPlane,
221        const uint32            _inMask) const {
222
223        uint32 inMask = _inMask;
224        assert(numPlanes < 31);
225   
226    const bool finite = 
227        (abs(lo.x) < G3D::inf()) &&
228        (abs(hi.x) < G3D::inf()) &&
229        (abs(lo.y) < G3D::inf()) &&
230        (abs(hi.y) < G3D::inf()) &&
231        (abs(lo.z) < G3D::inf()) &&
232        (abs(hi.z) < G3D::inf());
233
234    // See if there is one plane for which all of the
235        // vertices are in the negative half space.
236    for (int p = 0; p < numPlanes; p++) {
237
238                // Only test planes that are not masked
239                if ((inMask & 1) != 0) {
240               
241                        bool culled = true;
242                        Vector3 corner;
243
244            int v;
245
246                        // Assume this plane culls all points.  See if there is a point
247                        // not culled by the plane... early out when at least one point
248            // is in the positive half space.
249                        for (v = 0; (v < 8) && culled; ++v) {
250
251                // Unrolling these 3 if's into a switch decreases performance
252                // by about 2x
253                                corner.x = (v & 1) ? hi.x : lo.x;
254                                corner.y = (v & 2) ? hi.y : lo.y;
255                                corner.z = (v & 4) ? hi.z : lo.z;
256       
257                if (finite) { // this branch is highly predictable
258                    culled = ! plane[p].halfSpaceContainsFinite(corner);
259                } else {
260                    culled = ! plane[p].halfSpaceContains(corner);
261                }
262                        }
263
264                        if (culled) {
265                                // Plane p culled the box
266                                cullingPlane = p;
267
268                                return true;
269            }
270                }
271
272        // Move on to the next bit.
273                inMask = inMask >> 1;
274    }
275
276    // None of the planes could cull this box
277        cullingPlane = -1;
278    return false;
279}
280
281
282bool AABox::intersects(const class Sphere& sphere) const {
283    double d = 0; 
284
285    //find the square of the distance
286    //from the sphere to the box
287    for (int i = 0; i < 3; ++i) {
288        if (sphere.center[i] < lo[i]) {
289            d += square(sphere.center[i] - lo[i]);
290        } else if (sphere.center[i] > hi[i]) {
291            d += square(sphere.center[i] - hi[i]);
292        }
293    }
294
295    return d <= square(sphere.radius);
296}
297
298
299} // namespace
Note: See TracBrowser for help on using the browser.