Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

cm_trace.c File Reference

#include "cm_local.h"

Include dependency graph for cm_trace.c:

Include dependency graph

Go to the source code of this file.

Defines

#define MAX_POSITION_LEAFS   1024
#define RADIUS_EPSILON   1.0f

Functions

void CM_BoxTrace (trace_t *results, const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, clipHandle_t model, int brushmask, int capsule)
float CM_DistanceFromLineSquared (vec3_t p, vec3_t lp1, vec3_t lp2, vec3_t dir)
void CM_PositionTest (traceWork_t *tw)
void CM_ProjectPointOntoVector (vec3_t point, vec3_t vStart, vec3_t vDir, vec3_t vProj)
void CM_TestBoundingBoxInCapsule (traceWork_t *tw, clipHandle_t model)
void CM_TestBoxInBrush (traceWork_t *tw, cbrush_t *brush)
void CM_TestCapsuleInCapsule (traceWork_t *tw, clipHandle_t model)
void CM_TestInLeaf (traceWork_t *tw, cLeaf_t *leaf)
void CM_Trace (trace_t *results, const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, clipHandle_t model, const vec3_t origin, int brushmask, int capsule, sphere_t *sphere)
void CM_TraceBoundingBoxThroughCapsule (traceWork_t *tw, clipHandle_t model)
void CM_TraceCapsuleThroughCapsule (traceWork_t *tw, clipHandle_t model)
void CM_TraceThroughBrush (traceWork_t *tw, cbrush_t *brush)
void CM_TraceThroughLeaf (traceWork_t *tw, cLeaf_t *leaf)
void CM_TraceThroughPatch (traceWork_t *tw, cPatch_t *patch)
void CM_TraceThroughSphere (traceWork_t *tw, vec3_t origin, float radius, vec3_t start, vec3_t end)
void CM_TraceThroughTree (traceWork_t *tw, int num, float p1f, float p2f, vec3_t p1, vec3_t p2)
void CM_TraceThroughVerticalCylinder (traceWork_t *tw, vec3_t origin, float radius, float halfheight, vec3_t start, vec3_t end)
void CM_TransformedBoxTrace (trace_t *results, const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, clipHandle_t model, int brushmask, const vec3_t origin, const vec3_t angles, int capsule)
float CM_VectorDistanceSquared (vec3_t p1, vec3_t p2)
void CreateRotationMatrix (const vec3_t angles, vec3_t matrix[3])
void RotatePoint (vec3_t point, vec3_t matrix[3])
float SquareRootFloat (float number)
void TransposeMatrix (vec3_t matrix[3], vec3_t transpose[3])


Define Documentation

#define MAX_POSITION_LEAFS   1024
 

Definition at line 410 of file cm_trace.c.

#define RADIUS_EPSILON   1.0f
 

Definition at line 720 of file cm_trace.c.

Referenced by CM_TraceCapsuleThroughCapsule().


Function Documentation

void CM_BoxTrace trace_t results,
const vec3_t  start,
const vec3_t  end,
vec3_t  mins,
vec3_t  maxs,
clipHandle_t  model,
int  brushmask,
int  capsule
 

Definition at line 1367 of file cm_trace.c.

References CM_Trace(), NULL, and vec3_origin.

Referenced by BotImport_Trace(), CL_CgameSystemCalls(), and SV_Trace().

01369                                                                            {
01370     CM_Trace( results, start, end, mins, maxs, model, vec3_origin, brushmask, capsule, NULL );
01371 }

Here is the call graph for this function:

float CM_DistanceFromLineSquared vec3_t  p,
vec3_t  lp1,
vec3_t  lp2,
vec3_t  dir
 

Definition at line 96 of file cm_trace.c.

References CM_ProjectPointOntoVector(), fabs(), j, p, t, vec3_t, VectorLengthSquared(), and VectorSubtract.

Referenced by CM_TraceThroughSphere(), and CM_TraceThroughVerticalCylinder().

00096                                                                                {
00097     vec3_t proj, t;
00098     int j;
00099 
00100     CM_ProjectPointOntoVector(p, lp1, dir, proj);
00101     for (j = 0; j < 3; j++) 
00102         if ((proj[j] > lp1[j] && proj[j] > lp2[j]) ||
00103             (proj[j] < lp1[j] && proj[j] < lp2[j]))
00104             break;
00105     if (j < 3) {
00106         if (fabs(proj[j] - lp1[j]) < fabs(proj[j] - lp2[j]))
00107             VectorSubtract(p, lp1, t);
00108         else
00109             VectorSubtract(p, lp2, t);
00110         return VectorLengthSquared(t);
00111     }
00112     VectorSubtract(p, proj, t);
00113     return VectorLengthSquared(t);
00114 }

Here is the call graph for this function:

void CM_PositionTest traceWork_t tw  ) 
 

Definition at line 411 of file cm_trace.c.

References trace_t::allsolid, leafList_s::bounds, clipMap_t::checkcount, cm, CM_BoxLeafnums_r(), CM_TestInLeaf(), leafList_s::count, i, leafList_s::lastLeaf, leafList_t, clipMap_t::leafs, leafs, leafList_s::list, leafList_s::maxcount, leafList_s::overflowed, traceWork_t::size, traceWork_t::start, leafList_s::storeLeafs, traceWork_t::trace, and VectorAdd.

Referenced by CM_Trace().

00411                                         {
00412     int     leafs[MAX_POSITION_LEAFS];
00413     int     i;
00414     leafList_t  ll;
00415 
00416     // identify the leafs we are touching
00417     VectorAdd( tw->start, tw->size[0], ll.bounds[0] );
00418     VectorAdd( tw->start, tw->size[1], ll.bounds[1] );
00419 
00420     for (i=0 ; i<3 ; i++) {
00421         ll.bounds[0][i] -= 1;
00422         ll.bounds[1][i] += 1;
00423     }
00424 
00425     ll.count = 0;
00426     ll.maxcount = MAX_POSITION_LEAFS;
00427     ll.list = leafs;
00428     ll.storeLeafs = CM_StoreLeafs;
00429     ll.lastLeaf = 0;
00430     ll.overflowed = qfalse;
00431 
00432     cm.checkcount++;
00433 
00434     CM_BoxLeafnums_r( &ll, 0 );
00435 
00436 
00437     cm.checkcount++;
00438 
00439     // test the contents of the leafs
00440     for (i=0 ; i < ll.count ; i++) {
00441         CM_TestInLeaf( tw, &cm.leafs[leafs[i]] );
00442         if ( tw->trace.allsolid ) {
00443             break;
00444         }
00445     }
00446 }

Here is the call graph for this function:

void CM_ProjectPointOntoVector vec3_t  point,
vec3_t  vStart,
vec3_t  vDir,
vec3_t  vProj
 

Definition at line 82 of file cm_trace.c.

References DotProduct, point, vec3_t, VectorMA, and VectorSubtract.

Referenced by CM_DistanceFromLineSquared().

00083 {
00084     vec3_t pVec;
00085 
00086     VectorSubtract( point, vStart, pVec );
00087     // project onto the directional vector for this segment
00088     VectorMA( vStart, DotProduct( pVec, vDir ), vDir, vProj );
00089 }

void CM_TestBoundingBoxInCapsule traceWork_t tw,
clipHandle_t  model
 

Definition at line 374 of file cm_trace.c.

References clipHandle_t, CM_ClipHandleToModel(), CM_ModelBounds(), CM_TempBoxModel(), CM_TestInLeaf(), cmodel_t, traceWork_t::end, h(), sphere_t::halfheight, i, cmodel_s::leaf, sphere_t::offset, offset, qfalse, sphere_t::radius, traceWork_t::size, traceWork_t::sphere, traceWork_t::start, sphere_t::use, vec3_t, and VectorSet.

Referenced by CM_Trace().

00374                                                                         {
00375     vec3_t mins, maxs, offset, size[2];
00376     clipHandle_t h;
00377     cmodel_t *cmod;
00378     int i;
00379 
00380     // mins maxs of the capsule
00381     CM_ModelBounds(model, mins, maxs);
00382 
00383     // offset for capsule center
00384     for ( i = 0 ; i < 3 ; i++ ) {
00385         offset[i] = ( mins[i] + maxs[i] ) * 0.5;
00386         size[0][i] = mins[i] - offset[i];
00387         size[1][i] = maxs[i] - offset[i];
00388         tw->start[i] -= offset[i];
00389         tw->end[i] -= offset[i];
00390     }
00391 
00392     // replace the bounding box with the capsule
00393     tw->sphere.use = qtrue;
00394     tw->sphere.radius = ( size[1][0] > size[1][2] ) ? size[1][2]: size[1][0];
00395     tw->sphere.halfheight = size[1][2];
00396     VectorSet( tw->sphere.offset, 0, 0, size[1][2] - tw->sphere.radius );
00397 
00398     // replace the capsule with the bounding box
00399     h = CM_TempBoxModel(tw->size[0], tw->size[1], qfalse);
00400     // calculate collision
00401     cmod = CM_ClipHandleToModel( h );
00402     CM_TestInLeaf( tw, &cmod->leaf );
00403 }

Here is the call graph for this function:

void CM_TestBoxInBrush traceWork_t tw,
cbrush_t brush
 

Definition at line 162 of file cm_trace.c.

References trace_t::allsolid, cbrush_t::bounds, traceWork_t::bounds, cbrush_t::contents, trace_t::contents, cplane_t, cplane_s::dist, DotProduct, trace_t::fraction, i, cplane_s::normal, cbrush_t::numsides, sphere_t::offset, traceWork_t::offsets, cbrushside_t::plane, sphere_t::radius, cbrush_t::sides, cplane_s::signbits, traceWork_t::sphere, traceWork_t::start, trace_t::startsolid, t, traceWork_t::trace, sphere_t::use, vec3_t, VectorAdd, and VectorSubtract.

Referenced by CM_TestInLeaf().

00162                                                            {
00163     int         i;
00164     cplane_t    *plane;
00165     float       dist;
00166     float       d1;
00167     cbrushside_t    *side;
00168     float       t;
00169     vec3_t      startp;
00170 
00171     if (!brush->numsides) {
00172         return;
00173     }
00174 
00175     // special test for axial
00176     if ( tw->bounds[0][0] > brush->bounds[1][0]
00177         || tw->bounds[0][1] > brush->bounds[1][1]
00178         || tw->bounds[0][2] > brush->bounds[1][2]
00179         || tw->bounds[1][0] < brush->bounds[0][0]
00180         || tw->bounds[1][1] < brush->bounds[0][1]
00181         || tw->bounds[1][2] < brush->bounds[0][2]
00182         ) {
00183         return;
00184     }
00185 
00186    if ( tw->sphere.use ) {
00187         // the first six planes are the axial planes, so we only
00188         // need to test the remainder
00189         for ( i = 6 ; i < brush->numsides ; i++ ) {
00190             side = brush->sides + i;
00191             plane = side->plane;
00192 
00193             // adjust the plane distance apropriately for radius
00194             dist = plane->dist + tw->sphere.radius;
00195             // find the closest point on the capsule to the plane
00196             t = DotProduct( plane->normal, tw->sphere.offset );
00197             if ( t > 0 )
00198             {
00199                 VectorSubtract( tw->start, tw->sphere.offset, startp );
00200             }
00201             else
00202             {
00203                 VectorAdd( tw->start, tw->sphere.offset, startp );
00204             }
00205             d1 = DotProduct( startp, plane->normal ) - dist;
00206             // if completely in front of face, no intersection
00207             if ( d1 > 0 ) {
00208                 return;
00209             }
00210         }
00211     } else {
00212         // the first six planes are the axial planes, so we only
00213         // need to test the remainder
00214         for ( i = 6 ; i < brush->numsides ; i++ ) {
00215             side = brush->sides + i;
00216             plane = side->plane;
00217 
00218             // adjust the plane distance apropriately for mins/maxs
00219             dist = plane->dist - DotProduct( tw->offsets[ plane->signbits ], plane->normal );
00220 
00221             d1 = DotProduct( tw->start, plane->normal ) - dist;
00222 
00223             // if completely in front of face, no intersection
00224             if ( d1 > 0 ) {
00225                 return;
00226             }
00227         }
00228     }
00229 
00230     // inside this brush
00231     tw->trace.startsolid = tw->trace.allsolid = qtrue;
00232     tw->trace.fraction = 0;
00233     tw->trace.contents = brush->contents;
00234 }

void CM_TestCapsuleInCapsule traceWork_t tw,
clipHandle_t  model
 

Definition at line 305 of file cm_trace.c.

References trace_t::allsolid, bottom, CM_ModelBounds(), trace_t::fraction, i, offset, sphere_t::offset, p2, r, sphere_t::radius, traceWork_t::sphere, Square, traceWork_t::start, trace_t::startsolid, top, traceWork_t::trace, vec3_t, VectorAdd, VectorCopy, VectorLengthSquared(), and VectorSubtract.

Referenced by CM_Trace().

00305                                                                     {
00306     int i;
00307     vec3_t mins, maxs;
00308     vec3_t top, bottom;
00309     vec3_t p1, p2, tmp;
00310     vec3_t offset, symetricSize[2];
00311     float radius, halfwidth, halfheight, offs, r;
00312 
00313     CM_ModelBounds(model, mins, maxs);
00314 
00315     VectorAdd(tw->start, tw->sphere.offset, top);
00316     VectorSubtract(tw->start, tw->sphere.offset, bottom);
00317     for ( i = 0 ; i < 3 ; i++ ) {
00318         offset[i] = ( mins[i] + maxs[i] ) * 0.5;
00319         symetricSize[0][i] = mins[i] - offset[i];
00320         symetricSize[1][i] = maxs[i] - offset[i];
00321     }
00322     halfwidth = symetricSize[ 1 ][ 0 ];
00323     halfheight = symetricSize[ 1 ][ 2 ];
00324     radius = ( halfwidth > halfheight ) ? halfheight : halfwidth;
00325     offs = halfheight - radius;
00326 
00327     r = Square(tw->sphere.radius + radius);
00328     // check if any of the spheres overlap
00329     VectorCopy(offset, p1);
00330     p1[2] += offs;
00331     VectorSubtract(p1, top, tmp);
00332     if ( VectorLengthSquared(tmp) < r ) {
00333         tw->trace.startsolid = tw->trace.allsolid = qtrue;
00334         tw->trace.fraction = 0;
00335     }
00336     VectorSubtract(p1, bottom, tmp);
00337     if ( VectorLengthSquared(tmp) < r ) {
00338         tw->trace.startsolid = tw->trace.allsolid = qtrue;
00339         tw->trace.fraction = 0;
00340     }
00341     VectorCopy(offset, p2);
00342     p2[2] -= offs;
00343     VectorSubtract(p2, top, tmp);
00344     if ( VectorLengthSquared(tmp) < r ) {
00345         tw->trace.startsolid = tw->trace.allsolid = qtrue;
00346         tw->trace.fraction = 0;
00347     }
00348     VectorSubtract(p2, bottom, tmp);
00349     if ( VectorLengthSquared(tmp) < r ) {
00350         tw->trace.startsolid = tw->trace.allsolid = qtrue;
00351         tw->trace.fraction = 0;
00352     }
00353     // if between cylinder up and lower bounds
00354     if ( (top[2] >= p1[2] && top[2] <= p2[2]) ||
00355         (bottom[2] >= p1[2] && bottom[2] <= p2[2]) ) {
00356         // 2d coordinates
00357         top[2] = p1[2] = 0;
00358         // if the cylinders overlap
00359         VectorSubtract(top, p1, tmp);
00360         if ( VectorLengthSquared(tmp) < r ) {
00361             tw->trace.startsolid = tw->trace.allsolid = qtrue;
00362             tw->trace.fraction = 0;
00363         }
00364     }
00365 }

Here is the call graph for this function:

void CM_TestInLeaf traceWork_t tw,
cLeaf_t leaf
 

Definition at line 243 of file cm_trace.c.

References trace_t::allsolid, b, clipMap_t::brushes, cPatch_t::checkcount, clipMap_t::checkcount, cbrush_t::checkcount, cm, cm_noCurves, CM_PositionTestInPatchCollide(), CM_TestBoxInBrush(), trace_t::contents, cPatch_t::contents, traceWork_t::contents, cbrush_t::contents, cLeaf_t::firstLeafBrush, cLeaf_t::firstLeafSurface, trace_t::fraction, cvar_s::integer, k, clipMap_t::leafbrushes, clipMap_t::leafsurfaces, cLeaf_t::numLeafBrushes, cLeaf_t::numLeafSurfaces, cPatch_t::pc, trace_t::startsolid, clipMap_t::surfaces, and traceWork_t::trace.

Referenced by CM_PositionTest(), CM_TestBoundingBoxInCapsule(), and CM_Trace().

00243                                                      {
00244     int         k;
00245     int         brushnum;
00246     cbrush_t    *b;
00247     cPatch_t    *patch;
00248 
00249     // test box position against all brushes in the leaf
00250     for (k=0 ; k<leaf->numLeafBrushes ; k++) {
00251         brushnum = cm.leafbrushes[leaf->firstLeafBrush+k];
00252         b = &cm.brushes[brushnum];
00253         if (b->checkcount == cm.checkcount) {
00254             continue;   // already checked this brush in another leaf
00255         }
00256         b->checkcount = cm.checkcount;
00257 
00258         if ( !(b->contents & tw->contents)) {
00259             continue;
00260         }
00261         
00262         CM_TestBoxInBrush( tw, b );
00263         if ( tw->trace.allsolid ) {
00264             return;
00265         }
00266     }
00267 
00268     // test against all patches
00269 #ifdef BSPC
00270     if (1) {
00271 #else
00272     if ( !cm_noCurves->integer ) {
00273 #endif //BSPC
00274         for ( k = 0 ; k < leaf->numLeafSurfaces ; k++ ) {
00275             patch = cm.surfaces[ cm.leafsurfaces[ leaf->firstLeafSurface + k ] ];
00276             if ( !patch ) {
00277                 continue;
00278             }
00279             if ( patch->checkcount == cm.checkcount ) {
00280                 continue;   // already checked this brush in another leaf
00281             }
00282             patch->checkcount = cm.checkcount;
00283 
00284             if ( !(patch->contents & tw->contents)) {
00285                 continue;
00286             }
00287             
00288             if ( CM_PositionTestInPatchCollide( tw, patch->pc ) ) {
00289                 tw->trace.startsolid = tw->trace.allsolid = qtrue;
00290                 tw->trace.fraction = 0;
00291                 tw->trace.contents = patch->contents;
00292                 return;
00293             }
00294         }
00295     }
00296 }

Here is the call graph for this function:

void CM_Trace trace_t results,
const vec3_t  start,
const vec3_t  end,
vec3_t  mins,
vec3_t  maxs,
clipHandle_t  model,
const vec3_t  origin,
int  brushmask,
int  capsule,
sphere_t sphere
 

Definition at line 1149 of file cm_trace.c.

References assert, BOX_MODEL_HANDLE, c_traces, clipMap_t::checkcount, cm, CM_ClipHandleToModel(), CM_PositionTest(), CM_TestBoundingBoxInCapsule(), CM_TestCapsuleInCapsule(), CM_TestInLeaf(), CM_TraceBoundingBoxThroughCapsule(), CM_TraceCapsuleThroughCapsule(), CM_TraceThroughLeaf(), CM_TraceThroughTree(), cmodel_t, Com_Memset(), trace_t::contents, fabs(), sphere_t::halfheight, i, cmodel_s::leaf, clipMap_t::numNodes, offset, sphere_t::radius, sphere_t::use, vec3_t, VectorClear, VectorCopy, VectorLengthSquared(), and VectorSet.

Referenced by CM_BoxTrace(), and CM_TransformedBoxTrace().

01150                                                                                                                   {
01151     int         i;
01152     traceWork_t tw;
01153     vec3_t      offset;
01154     cmodel_t    *cmod;
01155 
01156     cmod = CM_ClipHandleToModel( model );
01157 
01158     cm.checkcount++;        // for multi-check avoidance
01159 
01160     c_traces++;             // for statistics, may be zeroed
01161 
01162     // fill in a default trace
01163     Com_Memset( &tw, 0, sizeof(tw) );
01164     tw.trace.fraction = 1;  // assume it goes the entire distance until shown otherwise
01165     VectorCopy(origin, tw.modelOrigin);
01166 
01167     if (!cm.numNodes) {
01168         *results = tw.trace;
01169 
01170         return; // map not loaded, shouldn't happen
01171     }
01172 
01173     // allow NULL to be passed in for 0,0,0
01174     if ( !mins ) {
01175         mins = vec3_origin;
01176     }
01177     if ( !maxs ) {
01178         maxs = vec3_origin;
01179     }
01180 
01181     // set basic parms
01182     tw.contents = brushmask;
01183 
01184     // adjust so that mins and maxs are always symetric, which
01185     // avoids some complications with plane expanding of rotated
01186     // bmodels
01187     for ( i = 0 ; i < 3 ; i++ ) {
01188         offset[i] = ( mins[i] + maxs[i] ) * 0.5;
01189         tw.size[0][i] = mins[i] - offset[i];
01190         tw.size[1][i] = maxs[i] - offset[i];
01191         tw.start[i] = start[i] + offset[i];
01192         tw.end[i] = end[i] + offset[i];
01193     }
01194 
01195     // if a sphere is already specified
01196     if ( sphere ) {
01197         tw.sphere = *sphere;
01198     }
01199     else {
01200         tw.sphere.use = capsule;
01201         tw.sphere.radius = ( tw.size[1][0] > tw.size[1][2] ) ? tw.size[1][2]: tw.size[1][0];
01202         tw.sphere.halfheight = tw.size[1][2];
01203         VectorSet( tw.sphere.offset, 0, 0, tw.size[1][2] - tw.sphere.radius );
01204     }
01205 
01206     tw.maxOffset = tw.size[1][0] + tw.size[1][1] + tw.size[1][2];
01207 
01208     // tw.offsets[signbits] = vector to apropriate corner from origin
01209     tw.offsets[0][0] = tw.size[0][0];
01210     tw.offsets[0][1] = tw.size[0][1];
01211     tw.offsets[0][2] = tw.size[0][2];
01212 
01213     tw.offsets[1][0] = tw.size[1][0];
01214     tw.offsets[1][1] = tw.size[0][1];
01215     tw.offsets[1][2] = tw.size[0][2];
01216 
01217     tw.offsets[2][0] = tw.size[0][0];
01218     tw.offsets[2][1] = tw.size[1][1];
01219     tw.offsets[2][2] = tw.size[0][2];
01220 
01221     tw.offsets[3][0] = tw.size[1][0];
01222     tw.offsets[3][1] = tw.size[1][1];
01223     tw.offsets[3][2] = tw.size[0][2];
01224 
01225     tw.offsets[4][0] = tw.size[0][0];
01226     tw.offsets[4][1] = tw.size[0][1];
01227     tw.offsets[4][2] = tw.size[1][2];
01228 
01229     tw.offsets[5][0] = tw.size[1][0];
01230     tw.offsets[5][1] = tw.size[0][1];
01231     tw.offsets[5][2] = tw.size[1][2];
01232 
01233     tw.offsets[6][0] = tw.size[0][0];
01234     tw.offsets[6][1] = tw.size[1][1];
01235     tw.offsets[6][2] = tw.size[1][2];
01236 
01237     tw.offsets[7][0] = tw.size[1][0];
01238     tw.offsets[7][1] = tw.size[1][1];
01239     tw.offsets[7][2] = tw.size[1][2];
01240 
01241     //
01242     // calculate bounds
01243     //
01244     if ( tw.sphere.use ) {
01245         for ( i = 0 ; i < 3 ; i++ ) {
01246             if ( tw.start[i] < tw.end[i] ) {
01247                 tw.bounds[0][i] = tw.start[i] - fabs(tw.sphere.offset[i]) - tw.sphere.radius;
01248                 tw.bounds[1][i] = tw.end[i] + fabs(tw.sphere.offset[i]) + tw.sphere.radius;
01249             } else {
01250                 tw.bounds[0][i] = tw.end[i] - fabs(tw.sphere.offset[i]) - tw.sphere.radius;
01251                 tw.bounds[1][i] = tw.start[i] + fabs(tw.sphere.offset[i]) + tw.sphere.radius;
01252             }
01253         }
01254     }
01255     else {
01256         for ( i = 0 ; i < 3 ; i++ ) {
01257             if ( tw.start[i] < tw.end[i] ) {
01258                 tw.bounds[0][i] = tw.start[i] + tw.size[0][i];
01259                 tw.bounds[1][i] = tw.end[i] + tw.size[1][i];
01260             } else {
01261                 tw.bounds[0][i] = tw.end[i] + tw.size[0][i];
01262                 tw.bounds[1][i] = tw.start[i] + tw.size[1][i];
01263             }
01264         }
01265     }
01266 
01267     //
01268     // check for position test special case
01269     //
01270     if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2]) {
01271         if ( model ) {
01272 #ifdef ALWAYS_BBOX_VS_BBOX // bk010201 - FIXME - compile time flag?
01273             if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE) {
01274                 tw.sphere.use = qfalse;
01275                 CM_TestInLeaf( &tw, &cmod->leaf );
01276             }
01277             else
01278 #elif defined(ALWAYS_CAPSULE_VS_CAPSULE)
01279             if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE) {
01280                 CM_TestCapsuleInCapsule( &tw, model );
01281             }
01282             else
01283 #endif
01284             if ( model == CAPSULE_MODEL_HANDLE ) {
01285                 if ( tw.sphere.use ) {
01286                     CM_TestCapsuleInCapsule( &tw, model );
01287                 }
01288                 else {
01289                     CM_TestBoundingBoxInCapsule( &tw, model );
01290                 }
01291             }
01292             else {
01293                 CM_TestInLeaf( &tw, &cmod->leaf );
01294             }
01295         } else {
01296             CM_PositionTest( &tw );
01297         }
01298     } else {
01299         //
01300         // check for point special case
01301         //
01302         if ( tw.size[0][0] == 0 && tw.size[0][1] == 0 && tw.size[0][2] == 0 ) {
01303             tw.isPoint = qtrue;
01304             VectorClear( tw.extents );
01305         } else {
01306             tw.isPoint = qfalse;
01307             tw.extents[0] = tw.size[1][0];
01308             tw.extents[1] = tw.size[1][1];
01309             tw.extents[2] = tw.size[1][2];
01310         }
01311 
01312         //
01313         // general sweeping through world
01314         //
01315         if ( model ) {
01316 #ifdef ALWAYS_BBOX_VS_BBOX
01317             if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE) {
01318                 tw.sphere.use = qfalse;
01319                 CM_TraceThroughLeaf( &tw, &cmod->leaf );
01320             }
01321             else
01322 #elif defined(ALWAYS_CAPSULE_VS_CAPSULE)
01323             if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE) {
01324                 CM_TraceCapsuleThroughCapsule( &tw, model );
01325             }
01326             else
01327 #endif
01328             if ( model == CAPSULE_MODEL_HANDLE ) {
01329                 if ( tw.sphere.use ) {
01330                     CM_TraceCapsuleThroughCapsule( &tw, model );
01331                 }
01332                 else {
01333                     CM_TraceBoundingBoxThroughCapsule( &tw, model );
01334                 }
01335             }
01336             else {
01337                 CM_TraceThroughLeaf( &tw, &cmod->leaf );
01338             }
01339         } else {
01340             CM_TraceThroughTree( &tw, 0, 0, 1, tw.start, tw.end );
01341         }
01342     }
01343 
01344     // generate endpos from the original, unmodified start/end
01345     if ( tw.trace.fraction == 1 ) {
01346         VectorCopy (end, tw.trace.endpos);
01347     } else {
01348         for ( i=0 ; i<3 ; i++ ) {
01349             tw.trace.endpos[i] = start[i] + tw.trace.fraction * (end[i] - start[i]);
01350         }
01351     }
01352 
01353         // If allsolid is set (was entirely inside something solid), the plane is not valid.
01354         // If fraction == 1.0, we never hit anything, and thus the plane is not valid.
01355         // Otherwise, the normal on the plane should have unit length
01356         assert(tw.trace.allsolid ||
01357                tw.trace.fraction == 1.0 ||
01358                VectorLengthSquared(tw.trace.plane.normal) > 0.9999);
01359     *results = tw.trace;
01360 }

Here is the call graph for this function:

void CM_TraceBoundingBoxThroughCapsule traceWork_t tw,
clipHandle_t  model
 

Definition at line 982 of file cm_trace.c.

References clipHandle_t, CM_ClipHandleToModel(), CM_ModelBounds(), CM_TempBoxModel(), CM_TraceThroughLeaf(), cmodel_t, traceWork_t::end, h(), sphere_t::halfheight, i, cmodel_s::leaf, sphere_t::offset, offset, qfalse, sphere_t::radius, traceWork_t::size, traceWork_t::sphere, traceWork_t::start, sphere_t::use, vec3_t, and VectorSet.

Referenced by CM_Trace().

00982                                                                               {
00983     vec3_t mins, maxs, offset, size[2];
00984     clipHandle_t h;
00985     cmodel_t *cmod;
00986     int i;
00987 
00988     // mins maxs of the capsule
00989     CM_ModelBounds(model, mins, maxs);
00990 
00991     // offset for capsule center
00992     for ( i = 0 ; i < 3 ; i++ ) {
00993         offset[i] = ( mins[i] + maxs[i] ) * 0.5;
00994         size[0][i] = mins[i] - offset[i];
00995         size[1][i] = maxs[i] - offset[i];
00996         tw->start[i] -= offset[i];
00997         tw->end[i] -= offset[i];
00998     }
00999 
01000     // replace the bounding box with the capsule
01001     tw->sphere.use = qtrue;
01002     tw->sphere.radius = ( size[1][0] > size[1][2] ) ? size[1][2]: size[1][0];
01003     tw->sphere.halfheight = size[1][2];
01004     VectorSet( tw->sphere.offset, 0, 0, size[1][2] - tw->sphere.radius );
01005 
01006     // replace the capsule with the bounding box
01007     h = CM_TempBoxModel(tw->size[0], tw->size[1], qfalse);
01008     // calculate collision
01009     cmod = CM_ClipHandleToModel( h );
01010     CM_TraceThroughLeaf( tw, &cmod->leaf );
01011 }

Here is the call graph for this function:

void CM_TraceCapsuleThroughCapsule traceWork_t tw,
clipHandle_t  model
 

Definition at line 920 of file cm_trace.c.

References bottom, traceWork_t::bounds, CM_ModelBounds(), CM_TraceThroughSphere(), CM_TraceThroughVerticalCylinder(), traceWork_t::end, h(), sphere_t::halfheight, i, offset, sphere_t::offset, sphere_t::radius, RADIUS_EPSILON, traceWork_t::sphere, traceWork_t::start, top, vec3_t, VectorAdd, VectorCopy, and VectorSubtract.

Referenced by CM_Trace().

00920                                                                           {
00921     int i;
00922     vec3_t mins, maxs;
00923     vec3_t top, bottom, starttop, startbottom, endtop, endbottom;
00924     vec3_t offset, symetricSize[2];
00925     float radius, halfwidth, halfheight, offs, h;
00926 
00927     CM_ModelBounds(model, mins, maxs);
00928     // test trace bounds vs. capsule bounds
00929     if ( tw->bounds[0][0] > maxs[0] + RADIUS_EPSILON
00930         || tw->bounds[0][1] > maxs[1] + RADIUS_EPSILON
00931         || tw->bounds[0][2] > maxs[2] + RADIUS_EPSILON
00932         || tw->bounds[1][0] < mins[0] - RADIUS_EPSILON
00933         || tw->bounds[1][1] < mins[1] - RADIUS_EPSILON
00934         || tw->bounds[1][2] < mins[2] - RADIUS_EPSILON
00935         ) {
00936         return;
00937     }
00938     // top origin and bottom origin of each sphere at start and end of trace
00939     VectorAdd(tw->start, tw->sphere.offset, starttop);
00940     VectorSubtract(tw->start, tw->sphere.offset, startbottom);
00941     VectorAdd(tw->end, tw->sphere.offset, endtop);
00942     VectorSubtract(tw->end, tw->sphere.offset, endbottom);
00943 
00944     // calculate top and bottom of the capsule spheres to collide with
00945     for ( i = 0 ; i < 3 ; i++ ) {
00946         offset[i] = ( mins[i] + maxs[i] ) * 0.5;
00947         symetricSize[0][i] = mins[i] - offset[i];
00948         symetricSize[1][i] = maxs[i] - offset[i];
00949     }
00950     halfwidth = symetricSize[ 1 ][ 0 ];
00951     halfheight = symetricSize[ 1 ][ 2 ];
00952     radius = ( halfwidth > halfheight ) ? halfheight : halfwidth;
00953     offs = halfheight - radius;
00954     VectorCopy(offset, top);
00955     top[2] += offs;
00956     VectorCopy(offset, bottom);
00957     bottom[2] -= offs;
00958     // expand radius of spheres
00959     radius += tw->sphere.radius;
00960     // if there is horizontal movement
00961     if ( tw->start[0] != tw->end[0] || tw->start[1] != tw->end[1] ) {
00962         // height of the expanded cylinder is the height of both cylinders minus the radius of both spheres
00963         h = halfheight + tw->sphere.halfheight - radius;
00964         // if the cylinder has a height
00965         if ( h > 0 ) {
00966             // test for collisions between the cylinders
00967             CM_TraceThroughVerticalCylinder(tw, offset, radius, h, tw->start, tw->end);
00968         }
00969     }
00970     // test for collision between the spheres
00971     CM_TraceThroughSphere(tw, top, radius, startbottom, endbottom);
00972     CM_TraceThroughSphere(tw, bottom, radius, starttop, endtop);
00973 }

Here is the call graph for this function:

void CM_TraceThroughBrush traceWork_t tw,
cbrush_t brush
 

Definition at line 483 of file cm_trace.c.

References trace_t::allsolid, c_brush_traces, cbrush_t::contents, trace_t::contents, cplane_t, cplane_s::dist, DotProduct, traceWork_t::end, f, trace_t::fraction, i, cplane_s::normal, cbrush_t::numsides, sphere_t::offset, traceWork_t::offsets, trace_t::plane, cbrushside_t::plane, qboolean, sphere_t::radius, cbrush_t::sides, cplane_s::signbits, traceWork_t::sphere, traceWork_t::start, trace_t::startsolid, SURFACE_CLIP_EPSILON, cbrushside_t::surfaceFlags, trace_t::surfaceFlags, t, traceWork_t::trace, sphere_t::use, vec3_t, VectorAdd, and VectorSubtract.

Referenced by CM_TraceThroughLeaf().

00483                                                               {
00484     int         i;
00485     cplane_t    *plane, *clipplane;
00486     float       dist;
00487     float       enterFrac, leaveFrac;
00488     float       d1, d2;
00489     qboolean    getout, startout;
00490     float       f;
00491     cbrushside_t    *side, *leadside;
00492     float       t;
00493     vec3_t      startp;
00494     vec3_t      endp;
00495 
00496     enterFrac = -1.0;
00497     leaveFrac = 1.0;
00498     clipplane = NULL;
00499 
00500     if ( !brush->numsides ) {
00501         return;
00502     }
00503 
00504     c_brush_traces++;
00505 
00506     getout = qfalse;
00507     startout = qfalse;
00508 
00509     leadside = NULL;
00510 
00511     if ( tw->sphere.use ) {
00512         //
00513         // compare the trace against all planes of the brush
00514         // find the latest time the trace crosses a plane towards the interior
00515         // and the earliest time the trace crosses a plane towards the exterior
00516         //
00517         for (i = 0; i < brush->numsides; i++) {
00518             side = brush->sides + i;
00519             plane = side->plane;
00520 
00521             // adjust the plane distance apropriately for radius
00522             dist = plane->dist + tw->sphere.radius;
00523 
00524             // find the closest point on the capsule to the plane
00525             t = DotProduct( plane->normal, tw->sphere.offset );
00526             if ( t > 0 )
00527             {
00528                 VectorSubtract( tw->start, tw->sphere.offset, startp );
00529                 VectorSubtract( tw->end, tw->sphere.offset, endp );
00530             }
00531             else
00532             {
00533                 VectorAdd( tw->start, tw->sphere.offset, startp );
00534                 VectorAdd( tw->end, tw->sphere.offset, endp );
00535             }
00536 
00537             d1 = DotProduct( startp, plane->normal ) - dist;
00538             d2 = DotProduct( endp, plane->normal ) - dist;
00539 
00540             if (d2 > 0) {
00541                 getout = q