Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

collide.C

Go to the documentation of this file.
00001 #include "collide.H"
00002 
00003 /********************************************************
00004 Given a velocity vector and a position, it will test all
00005 objects found with the sps octree for collisions and 
00006 return and new velocity that doesn't run through objects
00007 ********************************************************/
00008 CWvec 
00009 Collide::_get_move(CWpt& source, CWvec& velocity)
00010    { 
00011    Wpt dest = source + velocity; //destination to travel to
00012    Wtransf xf;
00013 
00014    //adjust camera and destination bounding spheres to match given position
00015    xf = Wtransf::translation(source - _BSphere->get_bb().center());
00016    _BSphere->transform(xf);
00017 
00018    xf = Wtransf::translation(Wpt(source+velocity) - _DestSphere->get_bb().center());
00019    _DestSphere->transform(xf);
00020  
00021    //Using the camera and destination spheres create a 
00022    //bounding box containing all possible faces that can be hit
00023    _polyBox = _BSphere->get_bb() + _DestSphere->get_bb();
00024 
00025    //make sure the list of potential colliders is empty
00026    _hitFaces.clear(); 
00027 
00028    //for all objects in the scene build collision list
00029    for(int i = 0; i < _RootNodes.num(); i++)
00030       buildCollisionList(_RootNodes[i]);
00031 
00032     //if there are no potential collisions return velocity
00033     if (_hitFaces.empty())
00034       return velocity;
00035       
00036 
00037    // Determine the nearest collider from the list potentialColliders
00038    bool   first = true;
00039    double nearDist = -1.0;
00040    Bface* nearCollide = NULL;
00041    Wpt  nearIntersect;
00042    Wpt  nearFaceIntersect;
00043     Wpt polyIntersect;
00044 
00045    //for all potential colliders(faces)
00046    for(int i = 0; i < _hitFaces.num(); i++)
00047       {
00048       Wpt camIntersect;   //the point within the camera bounding sphere that
00049                      //*will* hit the face 
00050       Wpt faceIntersect;
00051 
00052       Wpt fOrigin = _hitFaces[i]->centroid(); //face origin(chosen as the centroid)
00053       Wvec fNorm = _hitFaces[i]->norm(); //face normal
00054 
00055       //get the distance from the current face to camera source
00056       double fDist = intersect(source, -fNorm, fOrigin, fNorm); 
00057    
00058       //radius vector of the bounding sphere in the direction of face's normal
00059                 // XXX - compile error here: can't assign Wpt to Wvec.
00060                 //       not sure what is supposed to be computed, so
00061                 //       doing a quick fix: -- sapo
00062       Wvec dRad = (source - (fNorm * (_size/fNorm.length())))
00063                    - Wpt::Origin(); // quick fix
00064       
00065       double radius = _size; 
00066 
00067       //if the face is within the bounding sphere radius
00068       if(fabs(fDist) <= radius)
00069          {
00070          //calc the face intersection point
00071          Wvec distNorm = fNorm * (fDist/fNorm.length()); 
00072          faceIntersect = source + -distNorm;
00073          }
00074       else
00075          {
00076          camIntersect = source + (fNorm * (radius/fNorm.length()));
00077          double t = intersect(camIntersect, velocity, fOrigin, fNorm);
00078 
00079          // Calculate the face intersection point
00080          Wvec v = velocity *  (t/velocity.length());
00081          faceIntersect = camIntersect + v;
00082          }
00083 
00084 
00085       //set the polygon intersection point to the plane
00086       polyIntersect = faceIntersect;
00087 
00088       //if its not within the face, get the closest point
00089       if(!_hitFaces[i]->contains(faceIntersect))
00090          {
00091          Wvec bc; 
00092          bool inside = false;
00093          polyIntersect = _hitFaces[i]->nearest_pt(faceIntersect,bc,inside);//nearest point on poly's perimeter to plane intersect
00094          }
00095 
00096       
00097        Wvec invVelocity = -velocity; //inverted velocity
00098 
00099       //find the time in which the bounding sphere will interesect with
00100       //the face
00101       double t = intersectSphere(source,dRad,polyIntersect,radius);
00102 
00103       //if there is a reasonable intersection
00104       if(t>=0 && t <= velocity.length())
00105          {
00106          Wvec v = invVelocity * (t/invVelocity.length()); //with length set to t
00107          Wpt sPoint = polyIntersect + v; //point that we hit the sphere
00108          //set closests intersection info
00109           if (first || t < nearDist)
00110             {
00111             nearDist = t;
00112             nearCollide = _hitFaces[i];
00113             nearIntersect = sPoint;
00114             nearFaceIntersect = polyIntersect;
00115             first = false;
00116             }
00117          }
00118       }
00119 
00120    //if never found collision, return unchanged velocity
00121    if(first)
00122       return velocity;
00123 
00124     //create new velocity vector with length set to nearDist;
00125    Wvec v = velocity * (nearDist / velocity.length());
00126 
00127    if (v.length() < .01)
00128       return v;
00129 
00130     // Determine the sliding plane (for sliding against surfaces)
00131     Wpt newSource = source + v; 
00132     Wpt  slidePlaneO = nearFaceIntersect;
00133     Wvec  slidePlaneN = nearFaceIntersect - newSource;//newSource;
00134 
00135     double time = intersect(source+velocity, slidePlaneN, slidePlaneO, slidePlaneN);
00136     //Set length of slidePlaneNormal to time;
00137     //cout << "TIME: " << time << endl;
00138     Wvec destinationProjectionNormal = slidePlaneN  *  (time/slidePlaneN.length());
00139     Wpt  newDestinationPoint = dest + destinationProjectionNormal;
00140 
00141        // Generate the slide vector, which will become our new velocity vector
00142    // for the next iteration
00143     Wvec newVelocityVector = newDestinationPoint - newSource;//Wvec(Wpt::Origin() - nearFaceIntersect);
00144 
00145    return _get_move(source + v, newVelocityVector);
00146 } 
00147 
00148 bool 
00149 Collide::_update_scene()
00150 {
00151      CGELlist objects = VIEW::peek()->active();
00152 
00153       //create a octree and get the potential hit faces from it
00154       for (int i=0; i<objects.num(); i++) 
00155       {
00156         ARRAY<OctreeNode*> nodes;
00157       GEOMptr geom = GEOM::upcast(objects[i]);
00158 
00159       if (geom && BMESH::isa(geom->body())) 
00160          {
00161          Bvert_list list;
00162          Bface_list fs;
00163          ARRAY<Wvec> bcs;
00164          
00165          nodes += sps(BMESH::upcast(geom->body()), _height, _regularity, _min_dist, fs, bcs);
00166          _RootNodes.push(nodes[0]);
00167          _objs += 1;
00168          }
00169        } 
00170 
00171 
00172    return true;
00173 }
00174 
00175 
00176 double 
00177 Collide::intersect(CWpt& pOrigin, CWvec& pNormal, CWpt& rOrigin, CWvec& rVector)
00178    {
00179    double d = -(Wvec(pOrigin) * pNormal);
00180    return -((pNormal * Wvec(rOrigin) + d) / (pNormal * rVector));
00181    }
00182    
00183 
00184 
00185 double 
00186 Collide::intersectSphere(CWpt& rO, CWvec& rV, CWpt& sO, double sR)
00187 {
00188    Wvec Q = sO - rO;
00189    double c = Q.length();
00190    double v = Q * rV;
00191    double d = sR*sR - (c*c - v*v);
00192 
00193    // If there was no intersection, return -1
00194 
00195    if (d < 0.0) return -1.0;
00196 
00197    // Return the distance to the [first] intersecting point
00198 
00199    return v - sqrt(d);
00200 } 
00201 
00202 bool 
00203 Collide::buildCollisionList(OctreeNode* node)
00204    {
00205    //if the bounding box doesn't intersect the node
00206    //then ignore it and its children
00207    if(node->get_leaf() != 1 && node->get_leaf() != 0)
00208       return false;
00209 
00210    //if the node doesn't overlap then no need to add children
00211    if(!node->overlaps(_polyBox))
00212       return false;
00213 
00214 
00215    //if the node has no children(its a leaf), add its triangles
00216 if(node->get_leaf())
00217       _hitFaces = _hitFaces + node->intersects();
00218    else //else, check its children
00219       {
00220       OctreeNode** children =  node->get_children();
00221       for(int i = 0; i<8; i++)
00222          buildCollisionList(children[i]);
00223       }
00224    return true;
00225    }
00226 /*
00227 void Collide::set_size(double s)
00228 {
00229    _size = s;
00230 
00231     _BSphere = new BMESH;
00232     _BSphere->Sphere(_BSphere->new_patch());
00233     _BSphere->transform(Wtransf::scaling(_size,_size,_size));
00234 
00235 
00236    _DestSphere = new BMESH;
00237     _DestSphere->Sphere(_DestSphere->new_patch());
00238     _DestSphere->transform(Wtransf::scaling(_size,_size,_size));
00239 }
00240 */
00241 
00242 ////////////////////////////////
00243 //Gravity
00244 //
00245 ////////////////////////////
00246 
00247 
00248 
00249 /////////////////////
00250 //get_dir()
00251 //given position, find the current gravity for that point
00252 /////////////////////
00253 CWvec 
00254 Gravity::_get_dir(CWpt& p)
00255 {
00256 cout << "GEtting DIrection" << endl;
00257 cout << _world << endl;
00258 
00259 //If Gravity hasn't been set
00260 if(_ground == NULL)
00261    return Wvec(0,0,0);
00262 
00263 if(_currentGrav == WORLD)
00264    return _strength * _world_dir;
00265 
00266 Wpt cent = _ground->bbox().center();
00267 Wpt max  = _ground->bbox().max();
00268 
00269 if(_currentGrav == GLOBE)
00270    return _strength * (cent-p).normalized();
00271 
00272 if(_currentGrav == LANDSCAPE)
00273    return _strength * (Wvec(0,cent[1],0) - Wvec(0,max[1],0)).normalized();
00274 
00275 return Wvec(0,0,0);
00276 
00277 }
00278 
00279 
00280 bool
00281 Gravity::set_grav(GEOMptr g, mlib::CWvec& d, int t)
00282 {
00283    cout << "GRAVITY BEING SET" << endl;
00284    _ground        = g;
00285    _world_dir     = d;
00286    _currentGrav   = t;
00287    return true;
00288 }
00289 
00290 
00291 void 
00292 Gravity::set_globe(GEOMptr g)
00293 {
00294    _ground     = g;
00295    _globe      = true;        
00296    _landscape  = false;
00297    _world      = false;
00298 
00299 }
00300 void 
00301 Gravity::set_landscape(GEOMptr g)
00302 {
00303    _ground     = g;
00304    _globe      = false;       
00305    _landscape  = true;
00306    _world      = false;
00307 }
00308 void Gravity::set_world(Wvec d)
00309 {
00310    _world_dir  = d;
00311    _globe      = false;       
00312    _landscape  = false;
00313    _world      = true;
00314 }
00315 
00316 
00317 
00318 /* end of file collide.C */

Generated on Mon Sep 18 11:39:29 2006 for jot by  doxygen 1.4.4