00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef __SGL_SPHERE_BOUND_HPP
00026 #define __SGL_SPHERE_BOUND_HPP
00027
00028 #include <sgl.h>
00029 #include <sglVector.hpp>
00030 #include <sglPlane.hpp>
00031 #include <sglPolytope.hpp>
00032
00033 #include <sglSegment.hpp>
00034 #include <sglBound.hpp>
00035 #include <sglBoxBound.hpp>
00036
00037
00038
00039
00040
00041 template <class T>
00042 class sglSphereBound : public sglBound
00043 {
00044 public:
00045 sglSphereBound() : m_radius(0), m_center(0,0,0) {};
00046
00047 template <class S>
00048 sglSphereBound(const sglSphereBound<S> &rhs)
00049 : m_radius((T)rhs.getRadius()),m_center(rhs.getCenter()) {}
00050
00051
00052 ~sglSphereBound() {};
00053
00054 #ifndef WIN32
00055 sglSphereBound &operator=(const sglSphereBound<T> &rhs)
00056 {
00057 if (this != &rhs)
00058 {
00059 m_radius = rhs.m_radius;
00060 m_center = rhs.m_center;
00061 }
00062 return *this;
00063 }
00064 #endif
00065
00066 template <class S>
00067 sglSphereBound &operator=(const sglSphereBound<S> &rhs)
00068 {
00069 if (this != (sglSphereBound<T>*)&rhs)
00070 {
00071 m_radius = rhs.getRadius();
00072 m_center = rhs.getCenter();
00073 }
00074 return *this;
00075 }
00076
00077 template <class S>
00078 bool operator==(const sglSphereBound<S> &rhs) const
00079 {
00080 return ((m_radius == rhs.getRadius()) &&
00081 (m_center == rhs.getCenter()));
00082 }
00083
00084 void makeEmpty() { m_radius = 0.0; }
00085 bool isEmpty() const { return (m_radius == 0.0); }
00086 bool isInfinite() const { return (m_radius < 0.0); }
00087
00088
00089
00090 void setCenter(T x, T y, T z) {m_center.set(x,y,z);}
00091 template <class S> void setCenter(const sglVec3<S> &v) { m_center = v; }
00092 const sglVec3<T> &getCenter() const { return m_center; }
00093
00094 void setRadius(T radius) { m_radius = radius; }
00095 T getRadius() const { return m_radius; }
00096
00097
00098
00099 template <class S>
00100 void mul(const sglMat4<S>& mat)
00101 {
00102 sglVec3<T> center;
00103 center[0] = (T)(m_center[0]*mat[0][0] + m_center[1]*mat[1][0] +
00104 m_center[2]*mat[2][0] + mat[3][0]);
00105 center[1] = (T)(m_center[0]*mat[0][1] + m_center[1]*mat[1][1] +
00106 m_center[2]*mat[2][1] + mat[3][1]);
00107 center[2] = (T)(m_center[0]*mat[0][2] + m_center[1]*mat[1][2] +
00108 m_center[2]*mat[2][2] + mat[3][2]);
00109 m_center = center;
00110
00111
00112 }
00113
00114
00115
00116 void computeFromBox(const sglBoxBound &box);
00117
00118 void expandToInclude(const sglSphereBound<T> &sphere);
00119
00120
00121
00122 template <class S>
00123 IntersectResultEnum intersect(sglSegment<S> &ray) const
00124 {
00125
00126 if (isEmpty()) return eOUTSIDE;
00127 if (isInfinite()) return eINSIDE;
00128
00129
00130 sglVec3<S> eo = m_center - ray.getPos();
00131
00132 double d_sqr = eo.dot(eo);
00133 double r_sqr = m_radius*m_radius;
00134 if (d_sqr < r_sqr)
00135 {
00136 return eINSIDE;
00137 }
00138
00139
00140 double v = eo.dot(ray.getDir());
00141
00142 if ((v < 0) || (v > (m_radius + ray.getLen())))
00143 {
00144 return eOUTSIDE;
00145 }
00146
00147 double disc = r_sqr - d_sqr + v*v;
00148
00149
00150 if (disc < 0)
00151 {
00152 return eOUTSIDE;
00153 }
00154 else
00155 {
00156 double new_len = v - sqrt(disc);
00157 if (ray.getLen() < new_len)
00158 {
00159 return eOUTSIDE;
00160 }
00161 else
00162 {
00163 ray.setLen(new_len);
00164 return eINTERSECT;
00165 }
00166 }
00167 }
00168
00169 template <class S>
00170 IntersectResultEnum intersect(const sglPlane<S> &plane) const
00171 {
00172
00173
00174
00175 if (m_radius < 0.0) return eINTERSECT;
00176
00177
00178 if (m_radius == 0.0) return eOUTSIDE;
00179
00180
00181 T p = (T)plane.signedDistance(m_center);
00182
00183 if (p - m_radius > 0.0) return eINSIDE;
00184 else if (p + m_radius < 0.0) return eOUTSIDE;
00185 else return eINTERSECT;
00186 }
00187
00188 template <class S>
00189 IntersectResultEnum intersect(const sglPolytope<S> &ptope) const
00190 {
00191
00192
00193 if (isInfinite())
00194 {
00195 return eINTERSECT;
00196 }
00197
00198 bool intersect_flag = false;
00199
00200 for (unsigned int i=0; i<ptope.getNumPlanes(); i++)
00201 {
00202 IntersectResultEnum result = intersect(ptope.getPlane(i));
00203 if (result == eOUTSIDE)
00204 {
00205 return eOUTSIDE;
00206 }
00207 else if (result == eINTERSECT)
00208 {
00209 intersect_flag = true;
00210 }
00211 }
00212
00213 if (!intersect_flag)
00214 {
00215 return eINSIDE;
00216 }
00217
00218
00219
00220 return eINTERSECT;
00221 }
00222
00223 template <class S>
00224 IntersectResultEnum intersect(const sglPolytope<S> &ptope,
00225 unsigned int &cull_flags) const
00226 {
00227
00228
00229 if (isInfinite())
00230 {
00231 for (unsigned int i=0; i<ptope.getNumPlanes(); i++)
00232 {
00233 cull_flags |= (1<<i);
00234 }
00235 return eINTERSECT;
00236 }
00237
00238 unsigned int new_flags = 0;
00239
00240 for (unsigned int i=0; i<ptope.getNumPlanes(); i++)
00241 {
00242
00243
00244 if (cull_flags & (1<<i))
00245 {
00246 IntersectResultEnum result = intersect(ptope.getPlane(i));
00247 if (result == eOUTSIDE)
00248 {
00249 cull_flags=0;
00250 return eOUTSIDE;
00251 }
00252 else if (result == eINTERSECT)
00253 {
00254 new_flags |= (1<<i);
00255 }
00256 }
00257 }
00258
00259 if (new_flags == 0)
00260 {
00261 cull_flags=0;
00262 return eINSIDE;
00263 }
00264
00265
00266
00267 cull_flags = new_flags;
00268 return eINTERSECT;
00269 }
00270
00271
00272
00273
00274
00275
00276 void drawImmediate() const;
00277
00278 friend ostream &operator<<(ostream &ostrm, const sglSphereBound<T> &sphere)
00279 {
00280 if (sphere.isEmpty())
00281 return (ostrm << "bsphere: [empty]");
00282 if (sphere.isInfinite())
00283 return (ostrm << "bsphere: [infinite]");
00284
00285 return (ostrm << "bsphere: [" << setprecision(12)
00286 << sphere.m_radius << setprecision(6) << ", "
00287 << sphere.m_center << "]");
00288 }
00289
00290 protected:
00291 T m_radius;
00292 sglVec3<T> m_center;
00293 };
00294
00295
00296
00297
00298
00299
00301 typedef sglSphereBound<float> sglSphereBoundf;
00303 typedef sglSphereBound<double> sglSphereBoundd;
00304
00305 #endif