예제 #1
0
/*
================
CM_TraceCapsuleThroughCapsule

capsule vs. capsule collision (not rotated)
================
*/
static void CM_TraceCapsuleThroughCapsule(traceWork_t *tw, clipHandle_t model)
{
	int    i;
	vec3_t mins, maxs;
	vec3_t top, bottom, starttop, startbottom, endtop, endbottom;
	vec3_t offset, symetricSize[2];
	float  radius, halfwidth, halfheight, offs;

	CM_ModelBounds(model, mins, maxs);
	// test trace bounds vs. capsule bounds
	if (tw->bounds[0][0] > maxs[0] + RADIUS_EPSILON
	    || tw->bounds[0][1] > maxs[1] + RADIUS_EPSILON
	    || tw->bounds[0][2] > maxs[2] + RADIUS_EPSILON
	    || tw->bounds[1][0] < mins[0] - RADIUS_EPSILON
	    || tw->bounds[1][1] < mins[1] - RADIUS_EPSILON
	    || tw->bounds[1][2] < mins[2] - RADIUS_EPSILON
	    )
	{
		return;
	}
	// top origin and bottom origin of each sphere at start and end of trace
	VectorAdd(tw->start, tw->sphere.offset, starttop);
	VectorSubtract(tw->start, tw->sphere.offset, startbottom);
	VectorAdd(tw->end, tw->sphere.offset, endtop);
	VectorSubtract(tw->end, tw->sphere.offset, endbottom);

	// calculate top and bottom of the capsule spheres to collide with
	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;
	VectorCopy(offset, top);
	top[2] += offs;
	VectorCopy(offset, bottom);
	bottom[2] -= offs;
	// expand radius of spheres
	radius += tw->sphere.radius;
	// if there is horizontal movement
	if (tw->start[0] != tw->end[0] || tw->start[1] != tw->end[1])
	{
		// height of the expanded cylinder is the height of both cylinders minus the radius of both spheres
		float h = halfheight + tw->sphere.halfheight - radius;

		// if the cylinder has a height
		if (h > 0)
		{
			// test for collisions between the cylinders
			CM_TraceThroughVerticalCylinder(tw, offset, radius, h, tw->start, tw->end);
		}
	}
	// test for collision between the spheres
	CM_TraceThroughSphere(tw, top, radius, startbottom, endbottom);
	CM_TraceThroughSphere(tw, bottom, radius, starttop, endtop);
}
예제 #2
0
// capsule vs. capsule collision (not rotated)
void CM_TraceCapsuleThroughCapsule( traceWork_t *tw, clipHandle_t model ) {
	int i;
	vector3 mins, maxs;
	vector3 top, bottom, starttop, startbottom, endtop, endbottom;
	vector3 offset, symetricSize[2];
	float radius, halfwidth, halfheight, offs, h;

	CM_ModelBounds(model, &mins, &maxs);
	// test trace bounds vs. capsule bounds
	if ( tw->bounds[0].x > maxs.x + RADIUS_EPSILON ||
		 tw->bounds[0].y > maxs.y + RADIUS_EPSILON ||
		 tw->bounds[0].z > maxs.z + RADIUS_EPSILON ||
		 tw->bounds[1].x < mins.x - RADIUS_EPSILON ||
		 tw->bounds[1].y < mins.y - RADIUS_EPSILON ||
		 tw->bounds[1].z < mins.z - RADIUS_EPSILON) {
		return;
	}
	// top origin and bottom origin of each sphere at start and end of trace
	VectorAdd(&tw->start, &tw->sphere.offset, &starttop);
	VectorSubtract(&tw->start, &tw->sphere.offset, &startbottom);
	VectorAdd(&tw->end, &tw->sphere.offset, &endtop);
	VectorSubtract(&tw->end, &tw->sphere.offset, &endbottom);

	// calculate top and bottom of the capsule spheres to collide with
	for ( i = 0 ; i < 3 ; i++ ) {
		offset.data[i] = ( mins.data[i] + maxs.data[i] ) * 0.5f;
		symetricSize[0].data[i] = mins.data[i] - offset.data[i];
		symetricSize[1].data[i] = maxs.data[i] - offset.data[i];
	}
	halfwidth = symetricSize[1].x;
	halfheight = symetricSize[1].z;
	radius = ( halfwidth > halfheight ) ? halfheight : halfwidth;
	offs = halfheight - radius;
	VectorCopy(&offset, &top);
	top.z += offs;
	VectorCopy(&offset, &bottom);
	bottom.z -= offs;
	// expand radius of spheres
	radius += tw->sphere.radius;
	// if there is horizontal movement
	if ( tw->start.x != tw->end.x || tw->start.y != tw->end.y ) {
		// height of the expanded cylinder is the height of both cylinders minus the radius of both spheres
		h = halfheight + tw->sphere.halfheight - radius;
		// if the cylinder has a height
		if ( h > 0 ) {
			// test for collisions between the cylinders
			CM_TraceThroughVerticalCylinder(tw, &offset, radius, h, &tw->start, &tw->end);
		}
	}
	// test for collision between the spheres
	CM_TraceThroughSphere(tw, &top, radius, &startbottom, &endbottom);
	CM_TraceThroughSphere(tw, &bottom, radius, &starttop, &endtop);
}