00001 #ifndef BOX_H
00002 #define BOX_H
00003
00004
00005 #include "Vec3f.h"
00006 #include "Ray.h"
00007 #include "Axis.h"
00008 #include "SplitPlane.h"
00009
00010
00016 class Box
00017 {
00018 public:
00021 Box()
00022 {
00023 clear();
00024 }
00025
00031 Box(const Vec3f & minVertex, const Vec3f & maxVertex)
00032 : mMin(minVertex),
00033 mMax(maxVertex)
00034 {
00035 }
00036
00041 void extend(const Vec3f & a)
00042 {
00043 mMin = min(a - Vec3f(EPSILON), mMin);
00044 mMax = max(a + Vec3f(EPSILON), mMax);
00045 }
00046
00051 void extend(const Box & box)
00052 {
00053 extend(box.mMin - Vec3f(EPSILON));
00054 extend(box.mMax + Vec3f(EPSILON));
00055 }
00056
00059 void clear()
00060 {
00061 mMin = Vec3f(INFINITY, INFINITY, INFINITY);
00062 mMax = Vec3f(-INFINITY, -INFINITY, -INFINITY);
00063 }
00064
00070 std::pair<float, float> intersect(const Ray & ray) const
00071 {
00072 float d0 = -INFINITY;
00073 float d1 = INFINITY;
00074
00075 if (fabs(ray.dir().x()) > EPSILON)
00076 {
00077 d0 = (mMin.x() - ray.org().x()) / ray.dir().x();
00078 d1 = (mMax.x() - ray.org().x()) / ray.dir().x();
00079 if (d1 < d0)
00080 std::swap(d0, d1);
00081 }
00082
00083 if (fabs(ray.dir().y()) > EPSILON)
00084 {
00085 float t0, t1;
00086 t0 = (mMin.y() - ray.org().y()) / ray.dir().y();
00087 t1 = (mMax.y() - ray.org().y()) / ray.dir().y();
00088 if (t1 < t0)
00089 std::swap(t0, t1);
00090 d0 = std::max(d0, t0);
00091 d1 = std::min(d1, t1);
00092 }
00093
00094 if (fabs(ray.dir().z()) > EPSILON)
00095 {
00096 float t0, t1;
00097 t0 = (mMin.z() - ray.org().z()) / ray.dir().z();
00098 t1 = (mMax.z() - ray.org().z()) / ray.dir().z();
00099 if (t1 < t0)
00100 std::swap(t0, t1);
00101 d0 = std::max(d0, t0);
00102 d1 = std::min(d1, t1);
00103 }
00104
00105 if (d1 < d0 || d0 <= -INFINITY)
00106 return std::make_pair(INFINITY, -INFINITY);
00107 else
00108 return std::make_pair(d0 - EPSILON, d1 + EPSILON);
00109 }
00110
00113 inline const Vec3f & minVertex() const
00114 {
00115 return mMin;
00116 }
00117
00120 inline const Vec3f & maxVertex() const
00121 {
00122 return mMax;
00123 }
00124
00131 float area(const SplitPlane & plane) const
00132 {
00133 assert(plane.direction() != NO_AXIS);
00134
00135
00136 Vec3f diff = mMax - mMin;
00137 return (plane.position() - mMin[plane.direction()]) / diff[plane.direction()];
00138 }
00139
00145 std::pair<Box, Box> split(const SplitPlane & plane) const
00146 {
00147 assert(plane.direction() != NO_AXIS);
00148
00149
00150
00151 switch (plane.direction())
00152 {
00153 case X_AXIS: return std::make_pair(Box(mMin, Vec3f(plane.position() - EPSILON, mMax.y(), mMax.z())),
00154 Box(Vec3f(plane.position() + EPSILON, mMin.y(), mMin.z()), mMax));
00155 case Y_AXIS: return std::make_pair(Box(mMin, Vec3f(mMax.x(), plane.position() - EPSILON, mMax.z())),
00156 Box(Vec3f(mMin.x(), plane.position() + EPSILON, mMin.z()), mMax));
00157 case Z_AXIS: return std::make_pair(Box(mMin, Vec3f(mMax.x(), mMax.y(), plane.position() - EPSILON)),
00158 Box(Vec3f(mMin.x(), mMin.y(), plane.position() + EPSILON), mMax));
00159 default: return std::make_pair(Box(), Box());
00160 }
00161 }
00162
00167 Box clip(const Box & other) const
00168 {
00169 return Box(max(mMin, other.mMin), min(mMax, other.mMax));
00170 }
00171
00172 private:
00174 Vec3f mMin;
00175
00177 Vec3f mMax;
00178 };
00179
00180 #endif
00181