/* ================ CM_TestInLeaf ================ */ void CM_TestInLeaf(traceWork_t *tw, cLeaf_t *leaf) { int k; int brushnum; cbrush_t *b; // test box position against all brushes in the leaf for (k = 0 ; k < leaf->numLeafBrushes ; k++) { brushnum = cm.leafbrushes[leaf->firstLeafBrush + k]; b = &cm.brushes[brushnum]; if (b->checkcount == cm.checkcount) { continue; // already checked this brush in another leaf } b->checkcount = cm.checkcount; if (!(b->contents & tw->contents)) { continue; } CM_TestBoxInBrush(tw, b); if (tw->trace.allsolid) { return; } } // test against all patches if (!cm_noCurves->integer) { cPatch_t *patch; for (k = 0 ; k < leaf->numLeafSurfaces ; k++) { patch = cm.surfaces[cm.leafsurfaces[leaf->firstLeafSurface + k]]; if (!patch) { continue; } if (patch->checkcount == cm.checkcount) { continue; // already checked this brush in another leaf } patch->checkcount = cm.checkcount; if (!(patch->contents & tw->contents)) { continue; } if (CM_PositionTestInPatchCollide(tw, patch->pc)) { tw->trace.startsolid = tw->trace.allsolid = qtrue; tw->trace.fraction = 0; return; } } } }
/* ================ CM_TestInLeaf ================ */ void CM_TestInLeaf( traceWork_t *tw, cLeaf_t *leaf, clipMap_t *local ) { int k; int brushnum; cbrush_t *b; cPatch_t *patch; // test box position against all brushes in the leaf for (k=0 ; k<leaf->numLeafBrushes ; k++) { brushnum = local->leafbrushes[leaf->firstLeafBrush+k]; b = &local->brushes[brushnum]; if (b->checkcount == local->checkcount) { continue; // already checked this brush in another leaf } b->checkcount = local->checkcount; if ( !(b->contents & tw->contents)) { continue; } #ifndef BSPC #ifndef _XBOX // Removing terrain from Xbox if (com_terrainPhysics->integer && cmg.landScape && (b->contents & CONTENTS_TERRAIN) ) { // Invalidate the checkcount for terrain as the terrain brush has to be processed // many times. b->checkcount--; CM_TraceThroughTerrain( tw, tw->trace, b ); // If inside a terrain brush don't bother with regular brush collision continue; } #endif #endif CM_TestBoxInBrush( tw, b ); if ( tw->trace.allsolid ) { return; } } // test against all patches #ifdef BSPC if (1) { #else if ( !cm_noCurves->integer ) { #endif //BSPC for ( k = 0 ; k < leaf->numLeafSurfaces ; k++ ) { #ifdef _XBOX int index = CM_GetSurfaceIndex(leaf->firstLeafSurface + k); patch = cmg.surfaces[ index ]; #else patch = local->surfaces[ local->leafsurfaces[ leaf->firstLeafSurface + k ] ]; #endif if ( !patch ) { continue; } if ( patch->checkcount == local->checkcount ) { continue; // already checked this brush in another leaf } patch->checkcount = local->checkcount; if ( !(patch->contents & tw->contents)) { continue; } if ( CM_PositionTestInPatchCollide( tw, patch->pc ) ) { tw->trace.startsolid = tw->trace.allsolid = qtrue; tw->trace.fraction = 0; tw->trace.contents = patch->contents; return; } } } } /* ================== CM_PositionTest ================== */ #define MAX_POSITION_LEAFS 1024 void CM_PositionTest( traceWork_t *tw ) { int leafs[MAX_POSITION_LEAFS]; int i; leafList_t ll; // identify the leafs we are touching VectorAdd( tw->start, tw->size[0], ll.bounds[0] ); VectorAdd( tw->start, tw->size[1], ll.bounds[1] ); for (i=0 ; i<3 ; i++) { ll.bounds[0][i] -= 1; ll.bounds[1][i] += 1; } ll.count = 0; ll.maxcount = MAX_POSITION_LEAFS; ll.list = leafs; ll.storeLeafs = CM_StoreLeafs; ll.lastLeaf = 0; ll.overflowed = qfalse; cmg.checkcount++; CM_BoxLeafnums_r( &ll, 0 ); cmg.checkcount++; // test the contents of the leafs for (i=0 ; i < ll.count ; i++) { CM_TestInLeaf( tw, &cmg.leafs[leafs[i]], &cmg ); if ( tw->trace.allsolid ) { break; } } }
static void CM_TestInLeaf( traceWork_t* tw, const cLeaf_t* leaf ) { int k; int brushnum; cbrush_t *b; cPatch_t *patch; // test box position against all brushes in the leaf for (k=0 ; k<leaf->numLeafBrushes ; k++) { brushnum = cm.leafbrushes[leaf->firstLeafBrush+k]; b = &cm.brushes[brushnum]; if (b->checkcount == cm.checkcount) { continue; // already checked this brush in another leaf } b->checkcount = cm.checkcount; if ( !(b->contents & tw->contents)) { continue; } CM_TestBoxInBrush( tw, b ); if ( tw->trace.allsolid ) { return; } } // test against all patches #ifdef BSPC if (1) { #else if ( !cm_noCurves->integer ) { #endif //BSPC for ( k = 0 ; k < leaf->numLeafSurfaces ; k++ ) { patch = cm.surfaces[ cm.leafsurfaces[ leaf->firstLeafSurface + k ] ]; if ( !patch ) { continue; } if ( patch->checkcount == cm.checkcount ) { continue; // already checked this brush in another leaf } patch->checkcount = cm.checkcount; if ( !(patch->contents & tw->contents)) { continue; } if ( CM_PositionTestInPatchCollide( tw, patch->pc ) ) { tw->trace.startsolid = tw->trace.allsolid = qtrue; tw->trace.fraction = 0; tw->trace.contents = patch->contents; return; } } } } /* ================== CM_TestCapsuleInCapsule capsule inside capsule check ================== */ void CM_TestCapsuleInCapsule( traceWork_t *tw, clipHandle_t model ) { int i; vec3_t mins, maxs; vec3_t top, bottom; vec3_t p1, p2, tmp; vec3_t offset, symetricSize[2]; float radius, halfwidth, halfheight, offs, r; CM_ModelBounds(model, mins, maxs); VectorAdd(tw->start, tw->sphere.offset, top); VectorSubtract(tw->start, tw->sphere.offset, bottom); for ( i = 0 ; i < 3 ; i++ ) { offset[i] = ( mins[i] + maxs[i] ) * 0.5; symetricSize[0][i] = mins[i] - offset[i]; symetricSize[1][i] = maxs[i] - offset[i]; } halfwidth = symetricSize[ 1 ][ 0 ]; halfheight = symetricSize[ 1 ][ 2 ]; radius = ( halfwidth > halfheight ) ? halfheight : halfwidth; offs = halfheight - radius; r = Square(tw->sphere.radius + radius); // check if any of the spheres overlap VectorCopy(offset, p1); p1[2] += offs; VectorSubtract(p1, top, tmp); if ( VectorLengthSquared(tmp) < r ) { tw->trace.startsolid = tw->trace.allsolid = qtrue; tw->trace.fraction = 0; } VectorSubtract(p1, bottom, tmp); if ( VectorLengthSquared(tmp) < r ) { tw->trace.startsolid = tw->trace.allsolid = qtrue; tw->trace.fraction = 0; } VectorCopy(offset, p2); p2[2] -= offs; VectorSubtract(p2, top, tmp); if ( VectorLengthSquared(tmp) < r ) { tw->trace.startsolid = tw->trace.allsolid = qtrue; tw->trace.fraction = 0; } VectorSubtract(p2, bottom, tmp); if ( VectorLengthSquared(tmp) < r ) { tw->trace.startsolid = tw->trace.allsolid = qtrue; tw->trace.fraction = 0; } // if between cylinder up and lower bounds if ( (top[2] >= p1[2] && top[2] <= p2[2]) || (bottom[2] >= p1[2] && bottom[2] <= p2[2]) ) { // 2d coordinates top[2] = p1[2] = 0; // if the cylinders overlap VectorSubtract(top, p1, tmp); if ( VectorLengthSquared(tmp) < r ) { tw->trace.startsolid = tw->trace.allsolid = qtrue; tw->trace.fraction = 0; } } }
/* ================ CM_TestInLeaf ================ */ void CM_TestInLeaf( traceWork_t *tw, trace_t &trace, cLeaf_t *leaf, clipMap_t *local ) { int k; int brushnum; cbrush_t *b; cPatch_t *patch; // test box position against all brushes in the leaf for (k=0 ; k<leaf->numLeafBrushes ; k++) { brushnum = local->leafbrushes[leaf->firstLeafBrush+k]; b = &local->brushes[brushnum]; if (b->checkcount == local->checkcount) { continue; // already checked this brush in another leaf } b->checkcount = local->checkcount; if ( !(b->contents & tw->contents)) { continue; } #ifndef BSPC if (com_terrainPhysics->integer && cmg.landScape && (b->contents & CONTENTS_TERRAIN) ) { // Invalidate the checkcount for terrain as the terrain brush has to be processed // many times. b->checkcount--; CM_TraceThroughTerrain( tw, trace, b ); // If inside a terrain brush don't bother with regular brush collision continue; } #endif CM_TestBoxInBrush( tw, trace, b ); if ( trace.allsolid ) { return; } } // test against all patches #ifdef BSPC if (1) { #else if ( !cm_noCurves->integer ) { #endif //BSPC for ( k = 0 ; k < leaf->numLeafSurfaces ; k++ ) { patch = local->surfaces[ local->leafsurfaces[ leaf->firstLeafSurface + k ] ]; if ( !patch ) { continue; } if ( patch->checkcount == local->checkcount ) { continue; // already checked this brush in another leaf } patch->checkcount = local->checkcount; if ( !(patch->contents & tw->contents)) { continue; } if ( CM_PositionTestInPatchCollide( tw, patch->pc ) ) { trace.startsolid = trace.allsolid = qtrue; trace.fraction = 0; trace.contents = patch->contents; return; } } } } /* ================== CM_TestCapsuleInCapsule capsule inside capsule check ================== */ void CM_TestCapsuleInCapsule( traceWork_t *tw, trace_t &trace, clipHandle_t model ) { int i; vec3_t mins, maxs; vec3_t top, bottom; vec3_t p1, p2, tmp; vec3_t offset, symetricSize[2]; float radius, halfwidth, halfheight, offs, r; CM_ModelBounds(model, mins, maxs); VectorAdd(tw->start, tw->sphere.offset, top); VectorSubtract(tw->start, tw->sphere.offset, bottom); for ( i = 0 ; i < 3 ; i++ ) { offset[i] = ( mins[i] + maxs[i] ) * 0.5; symetricSize[0][i] = mins[i] - offset[i]; symetricSize[1][i] = maxs[i] - offset[i]; } halfwidth = symetricSize[ 1 ][ 0 ]; halfheight = symetricSize[ 1 ][ 2 ]; radius = ( halfwidth > halfheight ) ? halfheight : halfwidth; offs = halfheight - radius; r = Square(tw->sphere.radius + radius); // check if any of the spheres overlap VectorCopy(offset, p1); p1[2] += offs; VectorSubtract(p1, top, tmp); if ( VectorLengthSquared(tmp) < r ) { trace.startsolid = trace.allsolid = qtrue; trace.fraction = 0; } VectorSubtract(p1, bottom, tmp); if ( VectorLengthSquared(tmp) < r ) { trace.startsolid = trace.allsolid = qtrue; trace.fraction = 0; } VectorCopy(offset, p2); p2[2] -= offs; VectorSubtract(p2, top, tmp); if ( VectorLengthSquared(tmp) < r ) { trace.startsolid = trace.allsolid = qtrue; trace.fraction = 0; } VectorSubtract(p2, bottom, tmp); if ( VectorLengthSquared(tmp) < r ) { trace.startsolid = trace.allsolid = qtrue; trace.fraction = 0; } // if between cylinder up and lower bounds if ( (top[2] >= p1[2] && top[2] <= p2[2]) || (bottom[2] >= p1[2] && bottom[2] <= p2[2]) ) { // 2d coordinates top[2] = p1[2] = 0; // if the cylinders overlap VectorSubtract(top, p1, tmp); if ( VectorLengthSquared(tmp) < r ) { trace.startsolid = trace.allsolid = qtrue; trace.fraction = 0; } } }