Пример #1
0
/*
====================
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];
			}
		}
	}
}
Пример #2
0
/*
====================
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;
			}
		}
	}
}