home *** CD-ROM | disk | FTP | other *** search
/ Enter 2005 March / ENTER.ISO / files / fwp-0.0.6-win32-installer.exe / collision.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-12-06  |  7.9 KB  |  344 lines

  1. #include "collision.h"
  2. #include "intersection.h"
  3. //#include "camera.h"
  4. #include "log.h"
  5. //#include "quadtree.h"
  6. #include "Game.h"
  7. #include "Renderer.h"
  8. //#include "mech.h"
  9. #include "random.h"
  10. #include "Network.h"
  11.  
  12. #include "LightEffectsParticleClusters.h"
  13.  
  14. //trace_t lastTrace={0};
  15.  
  16. bool rayIntersectsFace(vec3_t pos, vec3_t dir, Face* face, float* distance, vec3_t hitpoint){
  17.     vec4_t plane;
  18.     vec3_t p1p2, p1p3, p2p3;
  19.     vec3_t p1point, p2point;
  20.     vec3_t c1,c2;
  21.  
  22.     float* p1=&face->vertices[0];
  23.  
  24.     float* p2=&face->vertices[3];
  25.     float* p3=&face->vertices[6];
  26.  
  27.     vectorSub3d(p2, p1, p1p2);
  28.     vectorSub3d(p3, p1, p1p3);
  29.     vectorSub3d(p3, p2, p2p3);
  30.  
  31.     vectorCopy3d(face->normal, plane);
  32.     //vectorNormalize3d(plane, plane);
  33.     plane[3]=vectorDotP3d(p1, plane);
  34.  
  35.     double xd=vectorDotP3d(plane, dir);
  36.  
  37.     if(xd==0.0)
  38.         return false;
  39.  
  40.     *distance=(float)( (plane[3]-vectorDotP3d(plane, pos))/xd );
  41.     if(*distance<0.0)
  42.         return false;
  43.  
  44.     vectorMA3d(pos, *distance, dir, hitpoint);
  45.  
  46.     // check if hitpoint is in triangle
  47.     vectorSub3d(hitpoint, p1, p1point);
  48.     vectorCrossP3d(p1p2, p1p3, c1);
  49.     vectorCrossP3d(p1p2, p1point, c2);
  50.     if(vectorDotP3d(c1,c2) < 0.0)
  51.         return false;
  52.  
  53. //    vectorSub3d(point, p1, p1point);
  54.     vectorCrossP3d(p1p3, p1p2, c1);
  55.     vectorCrossP3d(p1p3, p1point, c2);
  56.     if(vectorDotP3d(c1,c2) < 0.0)
  57.         return false;
  58.  
  59.     vectorScale3d(-1.0f, p1p2, p1p2);
  60.     vectorSub3d(hitpoint, p2, p2point);
  61.     vectorCrossP3d(p2p3, p1p2, c1);
  62.     vectorCrossP3d(p2p3, p2point, c2);
  63.     if(vectorDotP3d(c1,c2) < 0.0)
  64.         return false;
  65.  
  66.     return true;
  67.  
  68. }
  69.  
  70. bool linesegmentIntersectsFace(vec3_t pos1, vec3_t pos2, Face* face, float* distance, vec3_t hitpoint){
  71.     vec4_t plane;
  72.     vec3_t p1p2, p1p3, p2p3;
  73.     vec3_t dir;
  74.     vec3_t p1point, p2point;
  75.     vec3_t c1,c2;
  76.  
  77.     vectorSub3d(pos2, pos1, dir);
  78.  
  79.     float* p1=&face->vertices[0];
  80.     float* p2=&face->vertices[3];
  81.     float* p3=&face->vertices[6];
  82.  
  83.     vectorSub3d(p2, p1, p1p2);
  84.     vectorSub3d(p3, p1, p1p3);
  85.     vectorSub3d(p3, p2, p2p3);
  86.  
  87.     vectorCopy3d(face->normal, plane);
  88.     //vectorNormalize3d(plane, plane);
  89.     plane[3]=vectorDotP3d(p1, plane);
  90.  
  91.     double xd=vectorDotP3d(plane, dir);
  92.  
  93.     if(xd==0.0)
  94.         return false;
  95.  
  96.     *distance=(float)( (plane[3]-vectorDotP3d(plane, pos1))/xd );
  97.     if(*distance<0.0 || *distance>1.0)
  98.         return false;
  99.  
  100.     vectorMA3d(pos1, *distance, dir, hitpoint);
  101.  
  102.     // check if hitpoint is in triangle
  103.     vectorSub3d(hitpoint, p1, p1point);
  104.     vectorCrossP3d(p1p2, p1p3, c1);
  105.     vectorCrossP3d(p1p2, p1point, c2);
  106.     if(vectorDotP3d(c1,c2) < 0.0)
  107.         return false;
  108.  
  109. //    vectorSub3d(point, p1, p1point);
  110.     vectorCrossP3d(p1p3, p1p2, c1);
  111.     vectorCrossP3d(p1p3, p1point, c2);
  112.     if(vectorDotP3d(c1,c2) < 0.0)
  113.         return false;
  114.  
  115.     vectorScale3d(-1.0f, p1p2, p1p2);
  116.     vectorSub3d(hitpoint, p2, p2point);
  117.     vectorCrossP3d(p2p3, p1p2, c1);
  118.     vectorCrossP3d(p2p3, p2point, c2);
  119.     if(vectorDotP3d(c1,c2) < 0.0)
  120.         return false;
  121.  
  122.     return true;
  123.  
  124. }
  125.  
  126.  
  127.  
  128.  
  129.  
  130. void traceRay(vec3_t startPos, vec3_t dir, trace_t* trace){
  131.     vectorCopy3d(startPos, trace->startPos);
  132.     vectorCopy3d(dir, trace->dir);
  133.     trace->traceType=TRACE_TYPE_RAY;
  134.  
  135.     trace->hits.clear();
  136.  
  137.     if( !(trace->ignoreFlags & COLLISION_FLAG_ARENA) ){
  138.         Game::arena->sptree->traceRay(trace);
  139.     }
  140.  
  141.     if( !(trace->ignoreFlags & COLLISION_FLAG_VEHICLES) ){
  142.  
  143.         for(int i=0;i<GAME_MAX_VEHICLES;i++){
  144.             if( Game::vehicles[i] == NULL )
  145.                 continue;
  146.  
  147.             Vehicle* v = Game::vehicles[i];
  148.  
  149.             vec3_t absMin, absMax;
  150.             vectorAdd3d(v->pos, v->hitAABB.min, absMin);
  151.             vectorAdd3d(v->pos, v->hitAABB.max, absMax);
  152.  
  153.             float dist = 0.0f;
  154.             vec3_t hp;
  155.             if( rayIntersectsAABB( startPos, dir, absMin, absMax, &dist, hp ) ){
  156.                 vector<hit_t>::iterator hits_iter;
  157.                 for (hits_iter = trace->hits.begin(); hits_iter != trace->hits.end(); hits_iter++){
  158.                     if( dist < hits_iter->distance ){
  159.                         break;
  160.                     }
  161.  
  162.                 }
  163.  
  164.                 hit_t hit;
  165.  
  166.                 hit.distance = dist;
  167.                 hit.face = NULL;
  168.                 hit.node = NULL;
  169.                 hit.vehicle = v;
  170.                 vectorCopy3d(hp, hit.pos);
  171.  
  172. //                trace->hits.push_back(hit);
  173.                 hits_iter = trace->hits.insert(hits_iter, hit);
  174.             }
  175.         }
  176.     }
  177. }
  178. void traceLinesegment(vec3_t pos1, vec3_t pos2, trace_t* trace){
  179.     vectorCopy3d(pos1, trace->startPos);
  180.     vectorCopy3d(pos2, trace->endPos);
  181.     vectorSub3d(pos2, pos1, trace->dir);
  182.     trace->traceType=TRACE_TYPE_LINE_SEGMENT;
  183.  
  184.     trace->hits.clear();
  185.  
  186.     if( !(trace->ignoreFlags & COLLISION_FLAG_ARENA) ){
  187.         Game::arena->sptree->traceLinesegment(trace);
  188.     }
  189.  
  190.     if( !(trace->ignoreFlags & COLLISION_FLAG_VEHICLES) ){
  191.  
  192.         for(int i=0;i<GAME_MAX_VEHICLES;i++){
  193.             if( Game::vehicles[i] == NULL )
  194.                 continue;
  195.  
  196.             Vehicle* v = Game::vehicles[i];
  197.  
  198.             vec3_t absMin, absMax;
  199.             vectorAdd3d(v->pos, v->hitAABB.min, absMin);
  200.             vectorAdd3d(v->pos, v->hitAABB.max, absMax);
  201.  
  202.             float dist = 0.0f;
  203.             vec3_t hp;
  204.             if( linesegmentIntersectsAABB( pos1, pos2, absMin, absMax, &dist, hp ) ){
  205.                 vector<hit_t>::iterator hits_iter;
  206.                 for (hits_iter = trace->hits.begin(); hits_iter != trace->hits.end(); hits_iter++){
  207.                     if( dist < hits_iter->distance ){
  208.                         break;
  209.                     }
  210.  
  211.                 }
  212.  
  213.                 hit_t hit;
  214.  
  215.                 hit.distance = dist;
  216.                 hit.face = NULL;
  217.                 hit.node = NULL;
  218.                 hit.vehicle = v;
  219.                 vectorCopy3d(hp, hit.pos);
  220.  
  221. //                trace->hits.push_back(hit);
  222.                 hits_iter = trace->hits.insert(hits_iter, hit);
  223.             }
  224.         }
  225.     }
  226. }
  227.  
  228. void traceAABB(vec3_t pos1, vec3_t pos2, AABB_t aabb, trace_t* trace){
  229.     vectorCopy3d(pos1, trace->startPos);
  230.     vectorCopy3d(pos2, trace->endPos);
  231.     vectorSub3d(pos2, pos1, trace->dir);
  232.     vectorCopy3d(aabb.min, trace->min);
  233.     vectorCopy3d(aabb.max, trace->max);
  234.     trace->traceType = TRACE_TYPE_AABB;
  235.  
  236.     trace->hits.clear();
  237.  
  238.     if( !(trace->ignoreFlags & COLLISION_FLAG_ARENA) ){
  239.         Game::arena->sptree->traceAABB(trace );
  240.     }
  241.  
  242.     if( !(trace->ignoreFlags & COLLISION_FLAG_VEHICLES) ){
  243.  
  244.         vec3_t trace_absMin, trace_absMax;
  245.         vectorAdd3d(trace->endPos, aabb.min, trace_absMin);
  246.         vectorAdd3d(trace->endPos, aabb.max, trace_absMax);
  247.  
  248.         for(int i=0;i<GAME_MAX_VEHICLES;i++){
  249.             if( Game::vehicles[i] == NULL )
  250.                 continue;
  251.  
  252.             Vehicle* v = Game::vehicles[i];
  253.  
  254.             vec3_t absMin, absMax;
  255.             vectorAdd3d(v->pos, v->moveAABB.min, absMin);
  256.             vectorAdd3d(v->pos, v->moveAABB.max, absMax);
  257.  
  258.             if( AABBIntersectsAABB(trace_absMin, trace_absMax, absMin, absMax ) ){
  259.                 hit_t hit;
  260.  
  261.                 hit.distance = vectorLength3d(trace->dir);
  262.                 hit.face = NULL;
  263.                 hit.node = NULL;
  264.                 hit.vehicle = v;
  265.                 vectorCopy3d(trace->endPos, hit.pos);
  266.  
  267.                 trace->hits.push_back(hit);
  268.             }
  269.         }
  270.  
  271.     }
  272. }
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281. /*
  282. static SpacePartitioningTreeNode* debug_node = NULL;
  283. static Face* debug_face = NULL;
  284.  
  285. void castRay(){
  286.     trace_t trace;
  287.     trace.ignoreFlags = 0 | COLLISION_FLAG_BACKFACES | COLLISION_FLAG_SHOOT_THROUGH;
  288.  
  289.     debug_node = NULL;
  290.     debug_face = NULL;
  291.  
  292.     //Game::arena->sptree->traceRay(Game::cam.pos, Game::cam.dir, &trace);
  293.     traceRay(Game::cam.pos, Game::cam.dir, &trace);
  294.     if( trace.hits.empty() ){
  295.         log("castRay(): hit nothing\n");
  296.     }else{
  297.         int vehicleHits = 0;
  298.         int faceHits = 0;
  299.         for( unsigned int i=0; i<trace.hits.size(); i++){
  300.             if( trace.hits[i].face != NULL ){
  301.                 faceHits++;
  302.             }
  303.             if( trace.hits[i].vehicle != NULL ){
  304.                 vehicleHits++;
  305.             }
  306.         }
  307.  
  308.         log("castRay(): hit %i faces and %i vehicles\n", faceHits, vehicleHits);
  309.  
  310.         vec3_t col, pos;
  311.         //vectorInit3d(0.1f, 0.6f, 0.2f, col);
  312.         vectorInit3d(frand(1.0f), frand(1.0f), frand(1.0f), col);
  313.         vectorCopy3d(trace.hits[0].pos, pos);
  314.         Renderer::particleSystem.linkParticleCluster(new DynamicLightParticleCluster(pos, col, 5.0f, 10000));
  315.  
  316. //        debug_node = trace.hits[0].node;
  317. //        debug_face = trace.hits[0].face;
  318.     }
  319. }
  320.  
  321. void renderDebugStuff(){
  322.     if( debug_node != NULL )
  323.         debug_node->drawBorders();
  324.  
  325.     if( debug_face != NULL ){
  326.         Renderer::disableLighting();
  327.         glColor3f(0.0f, 1.0f, 0.0f);
  328.         Renderer::debug_renderFace(debug_face);
  329.         Renderer::enableLighting();
  330.     }
  331. }
  332. */
  333. /*
  334. bool castLinesegmentAgainstArena(vec3_t pos1, vec3_t pos2, float* distance, vec3_t hitPoint){
  335.     return false;
  336. }
  337. */
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344.