source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.h @ 3070

Revision 3070, 13.2 KB checked in by mattausch, 16 years ago (diff)
Line 
1#ifndef _AxisAlignedBox3_H__
2#define _AxisAlignedBox3_H__
3
4
5#include "Matrix4x4.h"
6#include "Vector3.h"
7#include "common.h"
8
9
10namespace CHCDemoEngine
11{
12
13struct Triangle3;
14class Plane3;
15class Polygon3;
16class Polyhedron;
17
18
19struct SimpleRay
20{
21        SimpleRay() {}
22
23        SimpleRay(const Vector3 &o, const Vector3 &d): mOrigin(o), mDirection(d) {}
24
25        Vector3 mOrigin;
26        Vector3 mDirection;
27
28        Vector3 Extrap(const float t) const
29        {
30                return mOrigin + mDirection * t;
31        }
32};
33
34
35/** Axis alignedd box class.
36    This is a box in 3-space, defined by min and max
37        corner vectors.  Many useful operations are defined.
38*/
39class AxisAlignedBox3
40{
41
42public:
43
44        ///////////
45        //-- Constructors.
46
47        AxisAlignedBox3();
48
49        AxisAlignedBox3(const Vector3 &nMin, const Vector3 &nMax);
50        /** initialization to the non existing bounding box
51        */
52        void Initialize();
53        /** The center of the box
54        */
55        Vector3 Center() const;
56        /** The diagonal of the box
57        */
58        Vector3 Diagonal() const;
59
60        float Center(const int axis) const;
61
62        float Min(const int axis) const;
63
64        float Max(const int axis) const;
65
66        float Size(const int axis) const;
67        /** Returns axis where box has largest extent.
68        */
69        int MajorAxis() const;
70        /** Read-only const access tomMin and max vectors using references
71        */
72        const Vector3& Min() const;
73        const Vector3& Max() const;
74
75        void Enlarge(const Vector3 &v);
76
77        void EnlargeToMinSize();
78
79        void SetMin(const Vector3 &v);
80
81        void SetMax(const Vector3 &v);
82
83        void SetMin(int axis, const float value);
84
85        void SetMax(int axis, const float value);
86        /** Decrease box by given splitting plane
87        */
88        void Reduce(int axis, int right, float value);
89
90        bool Intersects(const Vector3 &lStart, const Vector3 &lEnd) const;
91
92        // the size of the box along all the axes
93        Vector3 Size() const;
94        float Radius() const { return 0.5f * Magnitude(Size()); }
95        float SqrRadius() const { return 0.5f * SqrMagnitude(Size()); }
96        /** Return whether the box is unbounded.  Unbounded boxes appear
97                when unbounded objects such as quadric surfaces are included.
98        */
99        bool Unbounded() const;
100
101        // Expand the axis-aligned box to include the given object.
102        void Include(const Vector3 &newpt);
103        void Include(const AxisAlignedBox3 &bbox);
104        void Include(const Polygon3 &newpoly);
105        void Include(const PolygonContainer &polys);
106       
107        /** Expand the axis-aligned box to include given values in particular axis.
108        */
109        void Include(const int &axis, const float &newBound);
110        /** Includes returns true if a includes b (completely)
111        */
112        bool Includes(const AxisAlignedBox3 &b) const;
113
114        /** Returns true if this point is inside box.
115        */
116        virtual int IsInside(const Vector3 &v) const;
117        /** Test if the box makes sense.
118        */
119        virtual bool IsCorrect();
120        /** To answer true requires the box of real volume of non-zero value.
121        */
122        bool IsSingularOrIncorrect() const;
123        /** When the box is not of non-zero or negative surface area.
124        */
125        bool IsCorrectAndNotPoint() const;
126        /** Returns true when the box degenerates to a point.
127        */
128        bool IsPoint() const;
129        /** Scales the box with the factor.
130        */
131        void Scale(float scale);
132        /** Scale box non-uniformally
133        */
134        void Scale(const Vector3 &scale);
135        /** Translates the box with the factor.
136        */
137        void Translate(const Vector3 &shift);
138        /** Returns the square of the minimal and maximal distance to
139            a point on the box.
140        */
141        void GetSqrDistances(const Vector3 &point,
142                                 float &minDistance,
143                                                 float &maxDistance) const;
144        /** return random point in box.
145        */
146        Vector3 GetRandomPoint() const;
147        /** Returns surface area of the box.
148        */
149        float SurfaceArea() const;
150        /** Returns volume of the box.
151        */
152        float GetVolume() const;
153
154        // Six faces are distuinguished by their name.
155        enum EFaces {ID_Back = 0,
156                                 ID_Left = 1,
157                                 ID_Bottom = 2,
158                                 ID_Front = 3,
159                                 ID_Right = 4,
160                                 ID_Top = 5};
161
162        // Writes a brief description of the object, indenting by the given
163        // number of spaces first.
164        virtual void Describe(std::ostream& app, int ind) const;
165
166        // For edge .. number <0..11> returns two incident vertices
167        void GetEdge(int edge, Vector3 *a, Vector3 *b) const;
168
169        // Compute the coordinates of one vertex of the box for 0/1 in each axis
170        // 0 .. smaller coordinates, 1 .. large coordinates
171        Vector3 GetVertex(int xAxis, int yAxis, int zAxis) const;
172
173        // Compute the vertex for number N=<0..7>, N = 4*x + 2*y + z, where
174        // x,y,z are either 0 or 1; (0 .. lower coordinate, 1 .. large coordinate)
175        // (xmin,ymin, zmin) .. N = 0, (xmax, ymax, zmax) .. N= 7
176        void GetVertex(int N, Vector3 &vertex) const;
177
178        Vector3 GetVertex(int N) const;
179        /** get the extent of face.
180        */
181        float GetExtent(int face) const;
182        /** Returns 1, if the box includes on arbitrary face a given box
183        */
184        int IsPiercedByBox(const AxisAlignedBox3 &box, int &axis) const;
185
186        int GetFaceVisibilityMask(const Vector3 &position) const;
187        /** Returns vertex indices of edge.
188        */
189        void GetEdge(int edge, int  &aIdx, int &bIdx) const;
190        /** Get distance of plane to vertex with specified index.
191        */
192        float GetDistance(int index, const Plane3 &plane) const;
193        /** Returns the distance between the plane given by 'vecNearplaneNormal' and the vertex that
194            is closest to it (this vertex is unequivocally identified by the direction of the vector)
195        */
196        float GetMinDistance(const Plane3 &near) const;
197        /** Returns the distance between the plane given by 'vecNearplaneNormal' and the vertex that
198            is farthest to it (this vertex is unequivocally identified by the direction of the vector)
199        */
200        float GetMaxDistance(const Plane3 &near) const;
201       
202        /** Returns cross section of the plane as a polygon.
203        */
204        Polygon3 *CrossSection(const Plane3 &plane) const;
205        /** Returns the supporting plane of this face.
206        */
207        Plane3 GetPlane(const int face) const;
208        /** Returns
209                0 if box intersects plane
210                1 if box in front of plane
211                -1 if box behind plane
212        */
213        int Side(const Plane3 &plane) const;
214        /**  Calculates the intersection of the polyhedron with the box.
215        */
216        Polyhedron *CalcIntersection(const Polyhedron &polyhedron) const;
217        /** Tests for intersection of the ray with the box.
218        */
219        bool Intersects(const SimpleRay &ray, float &tnear, float &tfar) const;
220        /** Extracts the box sides as polygons.
221        */
222        void ExtractPolygons(PolygonContainer &polys) const;
223        /** Returns triangle representation of this box.
224        */
225        void Triangulate(std::vector<Triangle3> &triangles) const;
226
227
228
229        ////////////
230        //-- friend functions
231
232        /// Overlap returns 1 if the two axis-aligned boxes overlap .. even weakly
233        friend inline bool Overlap(const AxisAlignedBox3 &, const AxisAlignedBox3 &);
234
235        /// Overlap returns 1 if the two axis-aligned boxes overlap .. only strongly
236        friend inline bool OverlapS(const AxisAlignedBox3 &,const AxisAlignedBox3 &);
237
238        /** Overlap returns 1 if the two axis-aligned boxes overlap for a given epsilon.
239        If eps > 0.0, then the boxes has to have the real intersection
240        box, if eps < 0.0, then the boxes need not intersect really, they
241        can be at eps distance in the projection.
242        */
243        friend inline bool Overlap(const AxisAlignedBox3 &,     const AxisAlignedBox3 &, float eps);
244
245
246        // Returns the smallest axis-aligned box that includes all points
247        // inside the two given boxes.
248        friend inline AxisAlignedBox3 Union(const AxisAlignedBox3 &x,
249                                                const AxisAlignedBox3 &y);
250
251        // Returns the intersection of two axis-aligned boxes.
252        friend inline AxisAlignedBox3 Intersect(const AxisAlignedBox3 &x,
253                                                    const AxisAlignedBox3 &y);
254
255        // Given 4x4 matrix, transform the current box to new one.
256        friend inline AxisAlignedBox3 Transform(const AxisAlignedBox3 &box,
257                                                    const Matrix4x4 &tform);
258
259
260        // returns true when two boxes are completely equal
261        friend inline int operator== (const AxisAlignedBox3 &A,
262                                          const AxisAlignedBox3 &B);
263
264        // input and output operator with stream
265        friend std::ostream& operator<<(std::ostream &s, const AxisAlignedBox3 &A);
266        friend std::istream& operator>>(std::istream &s, AxisAlignedBox3 &A);
267
268
269
270        // The vertices that form boundaries of the projected bounding box
271        // for all the regions possible, number of regions is 3^3 = 27,
272        // since two parallel sides of bbox forms three disjoint spaces
273        // the vertices are given in anti-clockwise order .. stopped by -1 elem.
274        static const int bvertices[27][9];
275
276        // The list of all faces visible from a given region (except region 13)
277        // the faces are identified by triple: (axis, min-vertex, max-vertex),
278        // that is maximaly three triples are defined. axis = 0 (x-axis),
279        // axis = 1 (y-axis), axis = 2 (z-axis), -1 .. terminator. Is is always
280        // true that: min-vertex < max-vertex for all coordinates excluding axis
281        static const int bfaces[27][10];
282
283        // The correct corners indexed starting from entry face to exit face
284        // first index determines entry face, second index exit face, and
285        // the two numbers (indx, inc) determines: ind = the index on the exit
286        // face, when starting from the vertex 0 on entry face, 'inc' is
287        // the increment when we go on entry face in order 0,1,2,3 to create
288        // convex shaft with the rectangle on exit face. That is, inc = -1 or 1.
289        static const int pairFaceRects[6][6][2];
290
291        // The vertices that form CLOSEST points with respect to the region
292        // for all the regions possible, number of regions is 3^3 = 27,
293        // since two parallel sides of bbox forms three disjoint spaces.
294        // The vertices are given in anti-clockwise order, stopped by -1 elem,
295        // at most 8 points, at least 1 point.
296        static const int cvertices[27][9];
297        static const int csvertices[27][6];
298
299        // The vertices that form FARTHEST points with respect to the region
300        // for all the regions possible, number of regions is 3^3 = 27,
301        // since two parallel sides of bbox forms three disjoint spaces.
302        // The vertices are given in anti-clockwise order, stopped by -1 elem,
303        // at most 8 points, at least 1 point.
304        static const int fvertices[27][9]; 
305        static const int fsvertices[27][9];
306
307        /** Returns the vertex index nearest from the plane specified by the normal.
308        */
309        static int GetIndexNearestVertex(const Vector3 &vecPlaneNormal);
310        /** Returns the vertwx index farthest from the plane specified by the normal.
311        */
312        static int GetIndexFarthestVertex(const Vector3 &vecPlaneNormal);
313
314
315
316protected:
317
318        Vector3 mMin, mMax;
319};
320
321
322// --------------------------------------------------------------------------
323// Implementation of inline (member) functions
324
325inline bool
326Overlap(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
327{
328        if (x.mMax.x < y.mMin.x ||
329                x.mMin.x > y.mMax.x ||
330                x.mMax.y < y.mMin.y ||
331                x.mMin.y > y.mMax.y ||
332                x.mMax.z < y.mMin.z ||
333                x.mMin.z > y.mMax.z) {
334                        return false;
335        }
336        return true;
337}
338
339inline bool
340OverlapS(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
341{
342        if (x.mMax.x <= y.mMin.x ||
343                x.mMin.x >= y.mMax.x ||
344                x.mMax.y <= y.mMin.y ||
345                x.mMin.y >= y.mMax.y ||
346                x.mMax.z <= y.mMin.z ||
347                x.mMin.z >= y.mMax.z) {
348                        return false;
349        }
350        return true;
351}
352
353inline bool
354Overlap(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y, float eps)
355{
356        if ( (x.mMax.x - eps) < y.mMin.x ||
357                (x.mMin.x + eps) > y.mMax.x ||
358                (x.mMax.y - eps) < y.mMin.y ||
359                (x.mMin.y + eps) > y.mMax.y ||
360                (x.mMax.z - eps) < y.mMin.z ||
361                (x.mMin.z + eps) > y.mMax.z ) {
362                        return false;
363        }
364        return true;
365}
366
367inline AxisAlignedBox3
368Intersect(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
369{
370        if (x.Unbounded())
371                return y;
372        else
373                if (y.Unbounded())
374                        return x;
375        AxisAlignedBox3 ret = x;
376        if (Overlap(ret, y)) {
377                Maximize(ret.mMin, y.mMin);
378                Minimize(ret.mMax, y.mMax);
379                return ret;
380        }
381        else      // Null intersection.
382                return AxisAlignedBox3(Vector3(0), Vector3(0));
383        // return AxisAlignedBox3(Vector3(0), Vector3(-1));
384}
385
386inline AxisAlignedBox3
387Union(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
388{
389        Vector3 min = x.mMin;
390        Vector3 max = x.mMax;
391        Minimize(min, y.mMin);
392        Maximize(max, y.mMax);
393        return AxisAlignedBox3(min, max);
394}
395
396inline AxisAlignedBox3
397Transform(const AxisAlignedBox3 &box, const Matrix4x4 &tform)
398{
399        Vector3 mmin(MAXFLOAT);
400        Vector3 mmax(-MAXFLOAT);
401       
402        AxisAlignedBox3 ret(mmin, mmax);
403       
404        ret.Include(tform * Vector3(box.mMin.x, box.mMin.y, box.mMin.z));
405        ret.Include(tform * Vector3(box.mMin.x, box.mMin.y, box.mMax.z));
406        ret.Include(tform * Vector3(box.mMin.x, box.mMax.y, box.mMin.z));
407        ret.Include(tform * Vector3(box.mMin.x, box.mMax.y, box.mMax.z));
408        ret.Include(tform * Vector3(box.mMax.x, box.mMin.y, box.mMin.z));
409        ret.Include(tform * Vector3(box.mMax.x, box.mMin.y, box.mMax.z));
410        ret.Include(tform * Vector3(box.mMax.x, box.mMax.y, box.mMin.z));
411        ret.Include(tform * Vector3(box.mMax.x, box.mMax.y, box.mMax.z));
412       
413        return ret;
414}
415
416inline float RatioOfOverlap(const AxisAlignedBox3 &box1, const AxisAlignedBox3 &box2)
417{
418        // return ratio of intersection to union
419        const AxisAlignedBox3 bisect = Intersect(box1, box2);
420        const AxisAlignedBox3 bunion = Union(box1, box2);
421
422        return bisect.GetVolume() / bunion.GetVolume();
423}
424
425inline int operator==(const AxisAlignedBox3 &A, const AxisAlignedBox3 &B)
426{
427        return (A.mMin == B.mMin) && (A.mMax == B.mMax);
428}
429
430
431}
432
433
434#endif
Note: See TracBrowser for help on using the repository browser.