/* ==================== CM_TraceThroughPatchCollide ==================== */ void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) { int i, j, hit, hitnum; float offset, enterFrac, leaveFrac, t; patchPlane_t *planes; facet_t *facet; float plane[4] = {0, 0, 0, 0}, bestplane[4] = {0, 0, 0, 0}; vec3_t startp, endp; #ifndef BSPC static cvar_t *cv; #endif if ( !CM_BoundsIntersect( tw->bounds[0], tw->bounds[1], pc->bounds[0], pc->bounds[1] ) ) { return; } if ( tw->isPoint ) { CM_TracePointThroughPatchCollide( tw, pc ); return; } #ifndef ADDBEVELS CM_TracePointThroughPatchCollide( tw, pc ); return; #endif // facet = pc->facets; for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) { enterFrac = -1.0; leaveFrac = 1.0; hitnum = -1; // planes = &pc->planes[ facet->surfacePlane ]; VectorCopy( planes->plane, plane ); plane[3] = planes->plane[3]; if ( tw->sphere.use ) { // adjust the plane distance apropriately for radius plane[3] += tw->sphere.radius; // find the closest point on the capsule to the plane t = DotProduct( plane, tw->sphere.offset ); if ( t > 0 ) { VectorSubtract( tw->start, tw->sphere.offset, startp ); VectorSubtract( tw->end, tw->sphere.offset, endp ); } else { VectorAdd( tw->start, tw->sphere.offset, startp ); VectorAdd( tw->end, tw->sphere.offset, endp ); } } else { offset = DotProduct( tw->offsets[ planes->signbits ], plane ); plane[3] -= offset; VectorCopy( tw->start, startp ); VectorCopy( tw->end, endp ); } // if ( !CM_CheckFacetPlane( plane, startp, endp, &enterFrac, &leaveFrac, &hit ) ) { continue; } if ( hit ) { Vector4Copy( plane, bestplane ); } // for ( j = 0 ; j < facet->numBorders ; j++ ) { planes = &pc->planes[ facet->borderPlanes[j] ]; if ( facet->borderInward[j] ) { VectorNegate( planes->plane, plane ); plane[3] = -planes->plane[3]; } else { VectorCopy( planes->plane, plane ); plane[3] = planes->plane[3]; } if ( tw->sphere.use ) { // adjust the plane distance apropriately for radius plane[3] += tw->sphere.radius; // find the closest point on the capsule to the plane t = DotProduct( plane, tw->sphere.offset ); if ( t > 0 ) { VectorSubtract( tw->start, tw->sphere.offset, startp ); VectorSubtract( tw->end, tw->sphere.offset, endp ); } else { VectorAdd( tw->start, tw->sphere.offset, startp ); VectorAdd( tw->end, tw->sphere.offset, endp ); } } else { // NOTE: this works even though the plane might be flipped because the bbox is centered offset = DotProduct( tw->offsets[ planes->signbits ], plane ); plane[3] += fabs( offset ); VectorCopy( tw->start, startp ); VectorCopy( tw->end, endp ); } // if ( !CM_CheckFacetPlane( plane, startp, endp, &enterFrac, &leaveFrac, &hit ) ) { break; } if ( hit ) { hitnum = j; Vector4Copy( plane, bestplane ); } } if ( j < facet->numBorders ) { continue; } //never clip against the back side if ( hitnum == facet->numBorders - 1 ) { continue; } // if ( enterFrac < leaveFrac && enterFrac >= 0 ) { if ( enterFrac < tw->trace.fraction ) { if ( enterFrac < 0 ) { enterFrac = 0; } #ifndef BSPC if ( !cv ) { cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 ); } if ( cv && cv->integer ) { debugPatchCollide = pc; debugFacet = facet; } #endif tw->trace.fraction = enterFrac; VectorCopy( bestplane, tw->trace.plane.normal ); tw->trace.plane.dist = bestplane[3]; } } } }
/* ==================== CM_TraceThroughPatchCollide ==================== */ void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ) { int i, j, hit, hitnum; bfixed offset, t; gfixed enterFrac, leaveFrac; patchPlane_t *planes; facet_t *facet; planeDef_t plane, bestplane; bvec3_t startp, endp; #ifndef BSPC static cvar_t *cv; #endif //BSPC if (tw->isPoint) { CM_TracePointThroughPatchCollide( tw, pc ); return; } facet = pc->facets; for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) { enterFrac = -GFIXED_1; leaveFrac = GFIXED_1; hitnum = -1; // planes = &pc->planes[ facet->surfacePlane ]; VectorCopy(planes->pd.normal, plane.normal); plane.dist = planes->pd.dist; if ( tw->sphere.use ) { // adjust the plane distance apropriately for radius plane.dist += tw->sphere.radius; // find the closest point on the capsule to the plane t = FIXED_VEC3DOT_R( plane.normal, tw->sphere.offset ); if ( t > BFIXED_0 ) { VectorSubtract( tw->start, tw->sphere.offset, startp ); VectorSubtract( tw->end, tw->sphere.offset, endp ); } else { VectorAdd( tw->start, tw->sphere.offset, startp ); VectorAdd( tw->end, tw->sphere.offset, endp ); } } else { offset = FIXED_VEC3DOT( tw->offsets[ planes->signbits ], plane.normal); plane.dist -= offset; VectorCopy( tw->start, startp ); VectorCopy( tw->end, endp ); } if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) { continue; } if (hit) { VectorCopy(plane.normal, bestplane.normal); bestplane.dist=plane.dist; } for ( j = 0; j < facet->numBorders; j++ ) { planes = &pc->planes[ facet->borderPlanes[j] ]; if (facet->borderInward[j]) { VectorNegate(planes->pd.normal, plane.normal); plane.dist = -planes->pd.dist; } else { VectorCopy(planes->pd.normal, plane.normal); plane.dist = planes->pd.dist; } if ( tw->sphere.use ) { // adjust the plane distance apropriately for radius plane.dist += tw->sphere.radius; // find the closest point on the capsule to the plane t = FIXED_VEC3DOT_R( plane.normal, tw->sphere.offset ); if ( t > BFIXED_0 ) { VectorSubtract( tw->start, tw->sphere.offset, startp ); VectorSubtract( tw->end, tw->sphere.offset, endp ); } else { VectorAdd( tw->start, tw->sphere.offset, startp ); VectorAdd( tw->end, tw->sphere.offset, endp ); } } else { // NOTE: this works even though the plane might be flipped because the bbox is centered offset = FIXED_VEC3DOT( tw->offsets[ planes->signbits ], plane.normal); plane.dist += FIXED_ABS(offset); VectorCopy( tw->start, startp ); VectorCopy( tw->end, endp ); } if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit)) { break; } if (hit) { hitnum = j; VectorCopy(plane.normal, bestplane.normal); bestplane.dist=plane.dist; } } if (j < facet->numBorders) continue; //never clip against the back side if (hitnum == facet->numBorders - 1) continue; if (enterFrac < leaveFrac && enterFrac >= GFIXED_0) { if (enterFrac < tw->trace.fraction) { if (enterFrac < GFIXED_0) { enterFrac = GFIXED_0; } #ifndef BSPC if (!cv) { cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 ); } if (cv && cv->integer) { debugPatchCollide = pc; debugFacet = facet; } #endif //BSPC tw->trace.fraction = enterFrac; VectorCopy( bestplane.normal, tw->trace.plane.normal ); tw->trace.plane.dist = bestplane.dist; } } } }