00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef VEE_BOUNDING_BOX_H
00021 #define VEE_BOUNDING_BOX_H
00022
00023 #include <vee_vector3.h>
00024 #include <vee_matrix4.h>
00025
00026 class VEE_BoundingBox
00027 {
00028 public:
00029 VEE_BoundingBox() {}
00030 VEE_BoundingBox(const VEE_Vector3 * lowHigh)
00031 : m_low(*lowHigh), m_high(*lowHigh) {}
00032 VEE_BoundingBox(const VEE_Vector3 & low, const VEE_Vector3 & high)
00033 : m_low(low), m_high(high) {}
00034 ~VEE_BoundingBox() {}
00035
00036 void scale(float v) { m_low = m_low * v; m_high = m_high * v; }
00037 inline void scale(const VEE_Vector3 &v);
00038 void move(const VEE_Vector3 &v) { m_low += v; m_high += v; }
00039
00040 void clear() { m_low = m_high = VEE_Vector3ZERO; }
00041 void clear(const VEE_Vector3 &v) { m_low = m_high = v; }
00042
00043 inline void expand(const VEE_Vector3 &v);
00044 inline void expand(const VEE_Vector3 &v, float radius);
00045 inline void expand(const VEE_BoundingBox &b);
00046
00047 VEE_Vector3 & low() { return m_low; }
00048 const VEE_Vector3 & low() const { return m_low; }
00049 VEE_Vector3 & high() { return m_high; }
00050 const VEE_Vector3 & high() const { return m_high; }
00051
00052 void set(float lx, float ly, float lz, float hx, float hy, float hz)
00053 { m_low.make(lx, ly, lz); m_high.make(hx, hy, hz); }
00054
00055 void set(const VEE_Vector3 &low, const VEE_Vector3 &high)
00056 { m_low = low; m_high = high; }
00057
00058 void set(const VEE_Vector3 * begin, const VEE_Vector3 *end)
00059 { set(*begin); while(begin != end) expand(*begin++); }
00060
00061 void set(const VEE_Vector3 &point)
00062 { m_low = m_high = point; }
00063
00064 void set(const VEE_Vector3 &point, float radius)
00065 { m_low = point - radius; m_high = point + radius; }
00066
00067 inline VEE_Vector3 center() const { return (m_low + m_high) * 0.5f; }
00068 inline float centerX() const { return (m_low.x + m_high.x) * 0.5f; }
00069 inline float centerY() const { return (m_low.y + m_high.y) * 0.5f; }
00070 inline float centerZ() const { return (m_low.z + m_high.z) * 0.5f; }
00071 inline VEE_Vector3 span() const { return m_high - m_low; }
00072 inline VEE_Vector3 topCenter() const;
00073
00074 inline bool intersects(const VEE_BoundingBox &) const;
00075 inline bool contains(const VEE_Vector3 &) const;
00076 inline bool contains(const VEE_BoundingBox &b) const;
00077
00078 inline VEE_Vector3 clamp(const VEE_Vector3 &) const;
00079 inline float axisDistance(const VEE_Vector3 &) const;
00080
00081 protected:
00082 VEE_Vector3 m_low, m_high;
00083 };
00084
00085 inline void VEE_BoundingBox::expand(const VEE_Vector3 &v)
00086 {
00087 if(v[0] < m_low[0]) m_low[0] = v[0];
00088 if(v[1] < m_low[1]) m_low[1] = v[1];
00089 if(v[2] < m_low[2]) m_low[2] = v[2];
00090
00091 if(v[0] > m_high[0]) m_high[0] = v[0];
00092 if(v[1] > m_high[1]) m_high[1] = v[1];
00093 if(v[2] > m_high[2]) m_high[2] = v[2];
00094 }
00095
00096 inline void VEE_BoundingBox::expand(const VEE_Vector3 &v, float radius)
00097 {
00098 expand(v - VEE_Vector3(radius));
00099 expand(v + VEE_Vector3(radius));
00100 }
00101
00102 inline void VEE_BoundingBox::expand(const VEE_BoundingBox &b)
00103 {
00104 if(b.m_low[0] < m_low[0]) m_low[0] = b.m_low[0];
00105 if(b.m_low[1] < m_low[1]) m_low[1] = b.m_low[1];
00106 if(b.m_low[2] < m_low[2]) m_low[2] = b.m_low[2];
00107
00108 if(b.m_high[0] > m_high[0]) m_high[0] = b.m_high[0];
00109 if(b.m_high[1] > m_high[1]) m_high[1] = b.m_high[1];
00110 if(b.m_high[2] > m_high[2]) m_high[2] = b.m_high[2];
00111 }
00112
00113 void VEE_BoundingBox::scale(const VEE_Vector3 &v)
00114 {
00115 m_low[0] *= v[0];
00116 m_low[1] *= v[1];
00117 m_low[2] *= v[2];
00118
00119 m_high[0] *= v[0];
00120 m_high[1] *= v[1];
00121 m_high[2] *= v[2];
00122 }
00123
00124 VEE_Vector3 VEE_BoundingBox::topCenter() const
00125 {
00126 return VEE_Vector3((m_low.x + m_high.x) * 0.5,
00127 m_high.y,
00128 (m_low.z + m_high.z) * 0.5);
00129 }
00130
00131 bool VEE_BoundingBox::intersects(const VEE_BoundingBox &b) const
00132 {
00133 for(int i=0; i < 3; i++) {
00134 if(b.m_high[i] < m_low[i] || b.m_low[i] > m_high[i])
00135 return false;
00136 }
00137
00138 return true;
00139 }
00140
00141 inline bool VEE_BoundingBox::contains(const VEE_Vector3 &v) const
00142 {
00143 return ((v[0] >= m_low[0]) && (v[0] <= m_high[0]) &&
00144 (v[1] >= m_low[1]) && (v[1] <= m_high[1]) &&
00145 (v[2] >= m_low[2]) && (v[2] <= m_high[2]));
00146 }
00147
00148 inline bool VEE_BoundingBox::contains(const VEE_BoundingBox &b) const
00149 {
00150 return ((b.m_low[0] >= m_low[0]) && (b.m_high[0] <= m_high[0]) &&
00151 (b.m_low[1] >= m_low[1]) && (b.m_high[1] <= m_high[1]) &&
00152 (b.m_low[2] >= m_low[2]) && (b.m_high[2] <= m_high[2]));
00153 }
00154
00155 inline VEE_Vector3 VEE_BoundingBox::clamp(const VEE_Vector3 &v) const
00156 {
00157 int i;
00158 VEE_Vector3 r(v);
00159
00160 for(i=0; i < 3; i++)
00161 if(r[i] < m_low[i]) r[i] = m_low[i];
00162
00163 for(i=0; i < 3; i++)
00164 if(r[i] > m_high[i]) r[i] = m_high[i];
00165
00166 return r;
00167 }
00168
00169 inline float VEE_BoundingBox::axisDistance(const VEE_Vector3 &l) const
00170 {
00171 VEE_Vector3 d;
00172
00173 for(int i = 0; i < 3; i++) {
00174 if(l[i] > m_high[i])
00175 d[i] = l[i] - m_high[i];
00176 else if(l[i] < m_low[i])
00177 d[i] = m_low[i] - l[i];
00178 else
00179 d[i] = 0.0f;
00180 }
00181
00182 return d.maximum();
00183 }
00184
00185
00188 template <class M>
00189 inline VEE_BoundingBox operator * (const M &m, const VEE_BoundingBox &b)
00190 {
00191 VEE_Vector3 tmp, low = b.low(), high = b.high();
00192
00193 VEE_BoundingBox box;
00194 box.set(m * low);
00195
00196 for(uint x = 0; x < 2; x++) {
00197 for(uint y = 0; y < 2; y++) {
00198 for(uint z = 0; z < 2; z++) {
00199 tmp.x = x ? low.x : high.x;
00200 tmp.y = y ? low.y : high.y;
00201 tmp.z = z ? low.z : high.z;
00202
00203 box.expand(m * tmp);
00204
00205 }
00206 }
00207 }
00208
00209 return box;
00210 }
00211
00212 #endif
00213