source: GTP/trunk/App/Demos/Vis/CHC_revisited/AxisAlignedBox3.h @ 2747

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