AI_Sphere.h

Go to the documentation of this file.
00001 #ifndef AI_SPHERE_H
00002 #define AI_SPHERE_H
00003 //-------------------------------------------------------------------
00012 #include "AI_Vector.h"
00013 #include "AI_BBox.h"
00014 
00015 class AI_Sphere {
00016 public:
00017     AI_Vector3 p;      // position
00018     float   r;      // radius
00019 
00020     //--- constructors ----------------------------------------------
00021     AI_Sphere() : r(1.0f) {};
00022     AI_Sphere(const AI_Vector3& _p, float _r) : p(_p), r(_r) {};
00023     AI_Sphere(const AI_Sphere& s) : p(s.p), r(s.r) {};
00024     AI_Sphere(float _x, float _y, float _z, float _r) 
00025         : r(_r)
00026     {
00027         p.set(_x,_y,_z);
00028     };
00029 
00030     //--- set position and radius ---
00031     void set(const AI_Vector3& _p, float _r)
00032     {
00033         p = _p;
00034         r = _r;
00035     };
00036     void set(float _x, float _y, float _z, float _r)
00037     {
00038         p.set(_x, _y, _z);
00039         r = _r;
00040     };
00041 
00042     //--- check if 2 spheres overlap, without contact point ---------
00043     bool intersects(const AI_Sphere& s) const 
00044     {
00045         AI_Vector3 d(s.p-p);
00046         float rsum = s.r+r;
00047         if (d.lensquared() <= (rsum*rsum)) return true;
00048         else                               return false;
00049     };
00050 
00056     bool intersects(const AI_BBox& box) const
00057     {
00058         float s, d = 0;
00059 
00060         // find the square of the distance
00061         // from the AI_Sphere to the box,
00062         if (p.x < box.vmin.x)
00063         {
00064             s = p.x - box.vmin.x;
00065             d += s*s;
00066         }
00067         else if (p.x > box.vmax.x)
00068         {
00069             s = p.x - box.vmax.x;
00070             d += s*s;
00071         }
00072 
00073         if (p.y < box.vmin.y)
00074         {
00075             s = p.y - box.vmin.y;
00076             d += s*s;
00077         }
00078         else if (p.y > box.vmax.y)
00079         {
00080             s = p.y - box.vmax.y;
00081             d += s*s;
00082         }
00083 
00084         if (p.z < box.vmin.z)
00085         {
00086             s = p.z - box.vmin.z;
00087             d += s*s;
00088         }
00089         else if (p.z > box.vmax.z)
00090         {
00091             s = p.z - box.vmax.z;
00092             d += s*s;
00093         }
00094 
00095         return d <= r*r;
00096     }
00097 
00098     //--- check if 2 moving spheres have contact --------------------
00099     //--- taken from "Simple Intersection Tests For Games" ----------
00100     //--- article in Gamasutra, Oct 18 1999 -------------------------
00101     bool intersect_sweep(const AI_Vector3& va,     // in: distance travelled by 'this'
00102                          const AI_Sphere&  sb,     // in: the other AI_Sphere
00103                          const AI_Vector3& vb,     // in: distance travelled by 'sb'
00104                          float& u0,             // out: normalized intro contact u0
00105                          float& u1)             // out: normalized outro contact u1
00106     {
00107         AI_Vector3 vab(vb - va);
00108         AI_Vector3 ab(sb.p - p);
00109         float rab = r + sb.r;
00110 
00111         // check if spheres are currently overlapping...
00112         if ((ab % ab) <= (rab*rab)) {
00113             u0 = 0.0f;
00114             u1 = 0.0f;
00115             return true;
00116         } else {
00117             // check if they hit each other
00118             float a = vab % vab;
00119             if ((a<-AI_TINY) || (a>+AI_TINY)) {
00120                 // if a is '0' then the objects don't move relative to each other
00121                 float b = (vab % ab) * 2.0f;
00122                 float c = (ab % ab) - (rab * rab);
00123                 float q = b*b - 4*a*c;
00124                 if (q >= 0.0f) {
00125                     // 1 or 2 contacts
00126                     float sq = (float) sqrt(q);
00127                     float d  = 1.0f / (2.0f*a);
00128                     float r1 = (-b + sq) * d;
00129                     float r2 = (-b - sq) * d;
00130                     if (r1 < r2) {
00131                         u0 = r1;
00132                         u1 = r2;
00133                     } else {
00134                         u0 = r2;
00135                         u1 = r1;
00136                     }
00137                     return true;
00138                 } else return false;
00139             } else return false;
00140         }
00141     };
00142 };
00143 
00144 //-------------------------------------------------------------------
00145 #endif