/* ================ 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); }
// 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); }