Exemple #1
0
void SV_ClearWorld( void ) {
	clipHandle_t	h;
	vector3			mins, maxs;

	memset( sv_worldSectors, 0, sizeof(sv_worldSectors) );
	sv_numworldSectors = 0;

	// get world map bounds
	h = CM_InlineModel( 0 );
	CM_ModelBounds( h, &mins, &maxs );
	SV_CreateworldSector( 0, &mins, &maxs );
}
Exemple #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);
}
Exemple #3
0
/*
 * SV_ClearWorld
 *
 */
void
SV_ClearWorld(void)
{
	Cliphandle h;
	Vec3 mins, maxs;

	Q_Memset(sv_worldSectors, 0, sizeof(sv_worldSectors));
	sv_numworldSectors = 0;

	/* get world map bounds */
	h = CM_InlineModel(0);
	CM_ModelBounds(h, mins, maxs);
	SV_CreateworldSector(0, mins, maxs);
}
Exemple #4
0
/*
==================
CM_TestBoundingBoxInCapsule

bounding box inside capsule check
==================
*/
void CM_TestBoundingBoxInCapsule( traceWork_t *tw, clipHandle_t model ) {
	vec3_t mins, maxs, offset, bboxSize[2];
	clipHandle_t h;
	cmodel_t *cmod;
	int i;

	// save size of the bounding box
	VectorCopy(tw->size[0], bboxSize[0]);
	VectorCopy(tw->size[1], bboxSize[1]);

	// mins maxs of the capsule
	CM_ModelBounds(model, mins, maxs);

	// offset for capsule center
	for ( i = 0 ; i < 3 ; i++ ) {
		offset[i] = ( mins[i] + maxs[i] ) * 0.5;
		tw->size[0][i] = mins[i] - offset[i];
		tw->size[1][i] = maxs[i] - offset[i];
		tw->start[i] -= offset[i];
		tw->end[i] -= offset[i];

		if ( tw->start[i] < tw->end[i] ) {
			tw->bounds[0][i] = tw->start[i] + tw->size[0][i];
			tw->bounds[1][i] = tw->end[i] + tw->size[1][i];
		} else {
			tw->bounds[0][i] = tw->end[i] + tw->size[0][i];
			tw->bounds[1][i] = tw->start[i] + tw->size[1][i];
		}
	}

	// replace the bounding box with the capsule
	tw->type = TT_CAPSULE;
	tw->sphere.radius = ( tw->size[1][0] > tw->size[1][2] ) ? tw->size[1][2]: tw->size[1][0];
	tw->sphere.halfheight = tw->size[1][2];
	VectorSet( tw->sphere.offset, 0, 0, tw->size[1][2] - tw->sphere.radius );

	// replace the capsule with the bounding box
	h = CM_TempBoxModel(bboxSize[0], bboxSize[1], qfalse, capsule_contents);
	// calculate collision
	cmod = CM_ClipHandleToModel( h );
	CM_TestInLeaf( tw, &cmod->leaf );
}
Exemple #5
0
/*
==================
BotImport_BSPModelMinsMaxsOrigin
==================
*/
static void BotImport_BSPModelMinsMaxsOrigin(int modelnum, vec3_t angles, vec3_t outmins, vec3_t outmaxs, vec3_t origin) {
	clipHandle_t h;
	vec3_t mins, maxs;
	float max;
	int	i;

	h = CM_InlineModel(modelnum);
	CM_ModelBounds(h, mins, maxs);
	//if the model is rotated
	if ((angles[0] || angles[1] || angles[2])) {
		// expand for rotation

		max = RadiusFromBounds(mins, maxs);
		for (i = 0; i < 3; i++) {
			mins[i] = -max;
			maxs[i] = max;
		}
	}
	if (outmins) VectorCopy(mins, outmins);
	if (outmaxs) VectorCopy(maxs, outmaxs);
	if (origin) VectorClear(origin);
}
Exemple #6
0
static void BotImport_BSPModelMinsMaxsOrigin(int modelnum, vector3 *angles, vector3 *outmins, vector3 *outmaxs, vector3 *origin) {
	clipHandle_t h;
	vector3 mins, maxs;
	float max;
	int	i;

	h = CM_InlineModel(modelnum);
	CM_ModelBounds(h, &mins, &maxs);
	//if the model is rotated
	if ((angles->pitch || angles->yaw || angles->roll)) {
		// expand for rotation

		max = RadiusFromBounds(&mins, &maxs);
		for (i = 0; i < 3; i++) {
			mins.data[i] = -max;
			maxs.data[i] =  max;
		}
	}
	if (outmins) VectorCopy(&mins, outmins);
	if (outmaxs) VectorCopy(&maxs, outmaxs);
	if (origin) VectorClear(origin);
}
Exemple #7
0
/*
=================
SV_SetBrushModel

sets mins and maxs for inline bmodels
=================
*/
void SV_SetBrushModel(sharedEntity_t * ent, const char *name) {
	clipHandle_t    h;
	vec3_t          mins, maxs;

	if(!name) {
		Com_Error(ERR_DROP, "SV_SetBrushModel: NULL");
	}

	if(name[0] != '*') {
		Com_Error(ERR_DROP, "SV_SetBrushModel: %s isn't a brush model", name);
	}

	ent->s.modelindex = atoi(name + 1);

	h = CM_InlineModel(ent->s.modelindex);
	CM_ModelBounds(h, mins, maxs);
	VectorCopy(mins, ent->r.mins);
	VectorCopy(maxs, ent->r.maxs);
	ent->r.bmodel = true;

	ent->r.contents = -1;		// we don't know exactly what is in the brushes

	SV_LinkEntity(ent);			// FIXME: remove
}
Exemple #8
0
/*
==================
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;
		}
	}
}
Exemple #9
0
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;
		}
	}
}
Exemple #10
0
/*
================
CM_TraceCapsuleThroughCapsule

capsule vs. capsule collision (not rotated)
================
*/
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, h;

	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
		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, capsule_contents);
			if ( tw->trace.allsolid ) {
				return;
			}
		}
	}

	// test for collision between the spheres
	CM_TraceThroughSphere(tw, top, radius, startbottom, endbottom, capsule_contents);
	if ( tw->trace.allsolid ) {
		return;
	}

	CM_TraceThroughSphere(tw, bottom, radius, starttop, endtop, capsule_contents);
}
Exemple #11
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;
		}
	}
}