aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/include/G3D/AABox.h
diff options
context:
space:
mode:
Diffstat (limited to 'dep/g3dlite/include/G3D/AABox.h')
-rw-r--r--dep/g3dlite/include/G3D/AABox.h193
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 {