diff options
Diffstat (limited to 'dep/g3dlite/include/G3D/AABox.h')
-rw-r--r-- | dep/g3dlite/include/G3D/AABox.h | 193 |
1 files changed, 132 insertions, 61 deletions
diff --git a/dep/g3dlite/include/G3D/AABox.h b/dep/g3dlite/include/G3D/AABox.h index d57320d73eb..7a47ea63aa2 100644 --- a/dep/g3dlite/include/G3D/AABox.h +++ b/dep/g3dlite/include/G3D/AABox.h @@ -1,29 +1,31 @@ /** - @file AABox.h + \file G3D/AABox.h Axis-aligned box class - @maintainer Morgan McGuire, http://graphics.cs.williams.edu + \maintainer Morgan McGuire, http://graphics.cs.williams.edu - @created 2004-01-10 - @edited 2009-02-10 + \created 2004-01-10 + \edited 2013-04-13 - Copyright 2000-2009, Morgan McGuire. + Copyright 2000-2013, Morgan McGuire. All rights reserved. */ -#ifndef G3D_AABOX_H -#define G3D_AABOX_H +#ifndef G3D_AABox_h +#define G3D_AABox_h #include "G3D/platform.h" -#include "G3D/Vector3.h" #include "G3D/debug.h" #include "G3D/Array.h" #include "G3D/Plane.h" #include "G3D/Sphere.h" +#include "G3D/Vector3.h" namespace G3D { +class Any; + /** An axis-aligned box. */ @@ -34,66 +36,109 @@ private: /** Optional argument placeholder */ static int dummy; - Vector3 lo; - Vector3 hi; + /** NaN if empty */ + Point3 lo; + + /** NaN if empty */ + Point3 hi; public: - /** Does not initialize the fields */ - inline AABox() {} + /** Creates the empty bounds, i.e., an empty set of points. */ + AABox() : lo(fnan(), fnan(), fnan()), hi(fnan(), fnan(), fnan()) {} /** - Constructs a zero-area AABox at v. + Constructs a zero-volume AABox at v. */ - inline explicit AABox(const Vector3& v) { + explicit AABox(const Point3& v) { lo = hi = v; } + /** Format is one of: + - AABox(lowpoint, highpoint) + - AABox(point) + - AABox::empty() + - AABox::inf() + */ + explicit AABox(const class Any& a); + + Any toAny() const; + + bool isEmpty() const { + return lo.isNaN(); + } + /** Assumes that low is less than or equal to high along each dimension. To have this automatically enforced, use <code>AABox(low.min(high), low.max(high));</code> */ - inline AABox(const Vector3& low, const Vector3& high) { + AABox(const Point3& low, const Point3& high) { set(low, high); } + AABox operator*(float f) const { + if (f < 0) { + return AABox(hi * f, lo * f); + } else { + return AABox(lo * f, hi * f); + } + } + + AABox operator/(float f) const { + return *this * (1.0f / f); + } + /** Assumes that low is less than or equal to high along each dimension. */ - inline void set(const Vector3& low, const Vector3& high) { + inline void set(const Point3& low, const Point3& high) { debugAssert( (low.x <= high.x) && (low.y <= high.y) && (low.z <= high.z)); + debugAssert(! low.isNaN() && ! high.isNaN()); lo = low; hi = high; } /** - Grows to include the bounds of a + Grows to include the bounds of \a a */ inline void merge(const AABox& a) { - lo = lo.min(a.lo); - hi = hi.max(a.hi); + if (isEmpty()) { + lo = a.lo; + hi = a.hi; + } else if (! a.isEmpty()) { + lo = lo.min(a.lo); + hi = hi.max(a.hi); + } } - inline void merge(const Vector3& a) { - lo = lo.min(a); - hi = hi.max(a); + inline void merge(const Point3& a) { + if (isEmpty()) { + lo = hi = a; + } else { + lo = lo.min(a); + hi = hi.max(a); + } } + void merge(const class Box& b); + void serialize(class BinaryOutput& b) const; void deserialize(class BinaryInput& b); inline bool isFinite() const { - return lo.isFinite() && hi.isFinite(); + return isEmpty() || (lo.isFinite() && hi.isFinite()); } - inline const Vector3& low() const { + /** Returns not-a-number if empty */ + inline const Point3& low() const { return lo; } - inline const Vector3& high() const { + /** Returns not-a-number if empty */ + inline const Point3& high() const { return hi; } @@ -110,25 +155,33 @@ public: static const AABox& zero(); + static const AABox& empty(); + /** - Returns the centroid of the box. + Returns the centroid of the box (NaN if empty) */ - inline Vector3 center() const { + inline Point3 center() const { return (lo + hi) * 0.5; } - Vector3 corner(int index) const; + Point3 corner(int index) const; /** Distance from corner(0) to the next corner along axis a. */ inline float extent(int a) const { + if (isEmpty()) { + return 0.0f; + } debugAssert(a < 3); return hi[a] - lo[a]; } inline Vector3 extent() const { + if (isEmpty()) { + return Vector3::zero(); + } return hi - lo; } @@ -140,46 +193,46 @@ public: */ void split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const; - /** - Conservative culling test for up to 32 planes. - Returns true if there exists a <CODE>plane[p]</CODE> for + /** + Conservative culling test for up to 32 planes. + Returns true if there exists a <CODE>plane[p]</CODE> for which the entire object is in the negative half space (opposite the plane normal). - <CODE>testMask</CODE> and <CODE>childMask</CODE> - are used for optimizing bounding volume hierarchies. + <CODE>testMask</CODE> and <CODE>childMask</CODE> + are used for optimizing bounding volume hierarchies. The version of this method that produces childMask is slower than the version without; it should only be used for parent nodes. - @param cullingPlaneIndex The index of the first plane for which - the entire object is in the negative half-space. The function - exits early when one plane is found. -1 when the function - returns false (i.e. when no plane culls the whole object). + @param cullingPlaneIndex The index of the first plane for which + the entire object is in the negative half-space. The function + exits early when one plane is found. -1 when the function + returns false (i.e. when no plane culls the whole object). - @param testMask If bit <I>p</I> is 0, the - bounding volume automatically passes the culling test for - <CODE>plane[p]</CODE> (i.e. it is known that the volume - is entirely within the positive half space). The function + @param testMask If bit <I>p</I> is 0, the + bounding volume automatically passes the culling test for + <CODE>plane[p]</CODE> (i.e. it is known that the volume + is entirely within the positive half space). The function must return false if testMask is 0 and test all planes when testMask is -1 (0xFFFFFFFF). @param childMask Test mask for the children of this volume. - */ - bool culledBy( - const Array<Plane>& plane, - int32& cullingPlaneIndex, - const uint32 testMask, - uint32& childMask) const; + */ + bool culledBy + (const Array<Plane>& plane, + int32& cullingPlaneIndex, + const uint32 testMask, + uint32& childMask) const; /** Conservative culling test that does not produce a mask for children. */ - bool culledBy( - const Array<Plane>& plane, - int32& cullingPlaneIndex = dummy, - const uint32 testMask = 0xFFFFFFFF) const; + bool culledBy + (const Array<Plane>& plane, + int32& cullingPlaneIndex = dummy, + const uint32 testMask = 0xFFFFFFFF) const; /** less than or equal to containment */ inline bool contains(const AABox& other) const { @@ -192,8 +245,7 @@ public: (other.lo.z >= lo.z); } - inline bool contains( - const Vector3& point) const { + inline bool contains(const Point3& point) const { return (point.x >= lo.x) && (point.y >= lo.y) && @@ -204,31 +256,42 @@ public: } inline float area() const { + if (isEmpty()) { return 0; } Vector3 diag = hi - lo; return 2.0f * (diag.x * diag.y + diag.y * diag.z + diag.x * diag.z); } inline float volume() const { + if (isEmpty()) { return 0; } Vector3 diag = hi - lo; return diag.x * diag.y * diag.z; } - Vector3 randomInteriorPoint() const; + Point3 randomInteriorPoint() const; - Vector3 randomSurfacePoint() const; + Point3 randomSurfacePoint() const; /** Returns true if there is any overlap */ bool intersects(const AABox& other) const; /** Returns true if there is any overlap. @cite Jim Arvo's algorithm from Graphics Gems II*/ - bool intersects(const class Sphere& other) const; + bool intersects(const Sphere& other) const; /** Return the intersection of the two boxes */ AABox intersect(const AABox& other) const { - Vector3 H = hi.min(other.hi); - Vector3 L = lo.max(other.lo).min(H); - return AABox(L, H); + if (isEmpty() || other.isEmpty()) { + return empty(); + } + + const Point3& H = hi.min(other.hi); + const Point3& L = lo.max(other.lo).min(H); + + if (H.x < L.x && H.y < L.y && H.z < L.z) { + return empty(); + } else { + return AABox(L, H); + } } inline size_t hashCode() const { @@ -236,11 +299,19 @@ public: } inline bool operator==(const AABox& b) const { - return (lo == b.lo) && (hi == b.hi); + if (isEmpty() && b.isEmpty()) { + return true; + } else { + return (lo == b.lo) && (hi == b.hi); + } } inline bool operator!=(const AABox& b) const { - return !((lo == b.lo) && (hi == b.hi)); + if (isEmpty()) { + return b.isEmpty(); + } else { + return !((lo == b.lo) && (hi == b.hi)); + } } inline AABox operator+(const Vector3& v) const { |