Example #1
0
// check whether a ship is in range of a stargate -----------------------------
//
PRIVATE
int ShipInStargateRange( Stargate *stargate, ShipObject *ship, geomv_t range )
{
	ASSERT( stargate != NULL );
	ASSERT( ship != NULL );

	//NOTE:
	// the ship is treated as a sphere for activation
	// range detection.

	Vector3 gatenormal;
	FetchZVector( stargate->ObjPosition, &gatenormal );

	Vertex3 gatepos;
	FetchTVector( stargate->ObjPosition, &gatepos );

	Vertex3 shippos;
	FetchTVector( ship->ObjPosition, &shippos );

	geomv_t shipdot  = -DOT_PRODUCT( &gatenormal, &shippos );
	geomv_t gatedot  = -DOT_PRODUCT( &gatenormal, &gatepos );
	geomv_t distance = shipdot - gatedot;

	// bounding sphere touching in negative halfspace is still ok
	distance += ship->BoundingSphere;

	// not in range if ship in wrong halfspace
	if ( GEOMV_NEGATIVE( distance ) ) {
		return FALSE;
	}

	// in range if ship bounding sphere intersects gate range hemisphere
	range += ship->BoundingSphere * 2;
	return ( distance < range );
}
Example #2
0
// check whether a ship is in jump range of a stargate ------------------------
//
PRIVATE
int ShipInStargateJumpRange( Stargate *stargate, ShipObject *ship, geomv_t range )
{
	ASSERT( stargate != NULL );
	ASSERT( ship != NULL );

	//NOTE:
	// the ship is treated as a point for jump
	// range detection.

	Vector3 gatenormal;
	FetchZVector( stargate->ObjPosition, &gatenormal );

	Vertex3 gatepos;
	FetchTVector( stargate->ObjPosition, &gatepos );

	Vertex3 shippos;
	FetchTVector( ship->ObjPosition, &shippos );

	geomv_t shipdot  = -DOT_PRODUCT( &gatenormal, &shippos );
	geomv_t gatedot  = -DOT_PRODUCT( &gatenormal, &gatepos );
	geomv_t distance = shipdot - gatedot;

	// not in range if ship in wrong halfspace
	if ( GEOMV_NEGATIVE( distance ) ) {
		return FALSE;
	}

	// check whether inside of boundingsphere around stargate
	Vector3 stargate_ship;
	VECSUB( &stargate_ship, &shippos, &gatepos );

	geomv_t stargate_ship_len = VctLenX( &stargate_ship );
	if ( stargate_ship_len > stargate->BoundingSphere ) {
		return FALSE;
	}

	// inside the activation distance/range ?
	if ( distance < range ) {

		Vector3 shipnormal;
		FetchZVector( ship->ObjPosition, &shipnormal );

		// ship must be flying approximately head-on into the gate
		//FIXME: cone_angle like for teleporter
		geomv_t dirdot = DOT_PRODUCT( &gatenormal, &shipnormal );
		return ( dirdot > FLOAT_TO_GEOMV( 0.7f ) );
	}

	return FALSE;
}
Example #3
0
// collision detection helper function ----------------------------------------
//
int G_CollDet::_CheckShipProjectileDisjoint()
{
	// extend sphere for point sampling
	geomv_t hugesphere = bd_sphere * CONSERVATIVE_POINTSAMPLE_EXPANSION;

	// vector to center
	Vector3 vectest;
	vectest.X = obj_pos.X - test_pos.X;
	vectest.Y = obj_pos.Y - test_pos.Y;
	vectest.Z = obj_pos.Z - test_pos.Z;

	// check enlarged vicinity for early-out
	if ( vectest.X >= hugesphere )
		return TRUE;
	if ( vectest.Y >= hugesphere )
		return TRUE;
	if ( vectest.Z >= hugesphere )
		return TRUE;

	hugesphere = -hugesphere;
	if ( vectest.X <= hugesphere )
		return TRUE;
	if ( vectest.Y <= hugesphere )
		return TRUE;
	if ( vectest.Z <= hugesphere )
		return TRUE;

	// test shield (bounding sphere)
	if ( test_shield ) {

		// squared distance to current position
		geomv_t vectestl2 = DOT_PRODUCT( &vectest, &vectest );

		// trivial intersect
		if ( vectestl2 < bd_sphere2 )
			return FALSE;

		// squared distance to previous position
		Vector3 vecprev;
		vecprev.X = obj_pos.X - prev_pos.X;
		vecprev.Y = obj_pos.Y - prev_pos.Y;
		vecprev.Z = obj_pos.Z - prev_pos.Z;

		geomv_t vecprevl2 = DOT_PRODUCT( &vecprev, &vecprev );

		// trivial intersect
		if ( vecprevl2 < bd_sphere2 )
			return FALSE;

		// calc nearest point on line to center
		Vector3 vecline;
		vecline.X = test_pos.X - prev_pos.X;
		vecline.Y = test_pos.Y - prev_pos.Y;
		vecline.Z = test_pos.Z - prev_pos.Z;

		geomv_t scaledt = DOT_PRODUCT( &vecline, &vecprev );

		// ray pointing away from sphere?
		if ( GEOMV_NEGATIVE( scaledt ) )
			return TRUE;

		// ray not yet at the sphere?
		geomv_t veclinel2 =	DOT_PRODUCT( &vecline, &vecline );
		if ( scaledt >= veclinel2 )
			return TRUE;
		ASSERT( veclinel2 > GEOMV_VANISHING );

		// calc squared distance of nearest point
		geomv_t dot2  = GEOMV_MUL( scaledt, scaledt );
		geomv_t tlen2 = GEOMV_DIV( dot2, veclinel2 );

		//NOTE:
		// the actual point of impact could now be
		// easily calculated without a sqrt().

		// collision if nearest point inside
		return ( ( vecprevl2 - tlen2 ) >= bd_sphere2 );

	} else {

		ASSERT( FALSE );
/*
		// shield is down: test actual object

#ifdef CHECK_BOX_BEFORE_BSP_COLLISION

		// clip lineseg into box

		geomv_t isect;
		geomv_t seglen;
		geomv_t vtx0t = GEOMV_0;
		geomv_t vtx1t = GEOMV_1;

		int collside = -1;

		static geomv_t vanish = FLOAT_TO_GEOMV( 0.00001 );

		// cull/clip against +Z
		geomv_t curax = obj_pos.Z + bd_sphere;
		geomv_t dist0 = prev_pos.Z - curax;
		geomv_t dist1 = test_pos.Z - curax;
		dword outcode = ( ( DW32( dist0 ) & 0x80000000 ) >> 1 ) |
						  ( DW32( dist1 ) & 0x80000000 );
		// both outside?
		if ( outcode == 0x00000000 )
			return TRUE;
		// at least one outside?
		if ( outcode != 0xc0000000 ) {
			if ( outcode == 0x40000000 ) {
				// v0 inside, v1 outside
				ABS_GEOMV( dist0 );
				seglen = dist0 + dist1;
				if ( seglen <= vanish )
					return TRUE;
				vtx1t = GEOMV_DIV( dist0, seglen );
			} else {
				// v0 outside, v1 inside
				ABS_GEOMV( dist1 );
				seglen = dist0 + dist1;
				if ( seglen <= vanish )
					return TRUE;
				vtx0t = GEOMV_DIV( dist0, seglen );
				collside = 0;
			}
		}

#define AXIAL_CLIP_T(s)	{ \
\
	outcode = ( ( DW32( dist0 ) & 0x80000000 ) >> 1 ) | \
				( DW32( dist1 ) & 0x80000000 ); \
	if ( outcode == 0x00000000 ) \
		return TRUE; \
	if ( outcode != 0xc0000000 ) { \
		if ( outcode == 0x40000000 ) { \
			ABS_GEOMV( dist0 ); \
			seglen = dist0 + dist1; \
			if ( seglen <= vanish ) \
				return TRUE; \
			isect = GEOMV_DIV( dist0, seglen ); \
			if ( isect <= vtx0t ) \
				return TRUE; \
			if ( isect < vtx1t ) \
				vtx1t = isect; \
		} else { \
			ABS_GEOMV( dist1 ); \
			seglen = dist0 + dist1; \
			if ( seglen <= vanish ) \
				return TRUE; \
			isect = GEOMV_DIV( dist0, seglen ); \
			if ( isect >= vtx1t ) \
				return TRUE; \
			if ( isect > vtx0t ) { \
				vtx0t = isect; \
				collside = (s); \
			} \
		} \
	} \
}
		// cull/clip against -Z
		curax = obj_pos.Z - bd_sphere;
		dist0 = curax - prev_pos.Z;
		dist1 = curax - test_pos.Z;
		AXIAL_CLIP_T( 1 );

		// cull/clip against +X
		curax = obj_pos.X + bd_sphere;
		dist0 = prev_pos.X - curax;
		dist1 = test_pos.X - curax;
		AXIAL_CLIP_T( 2 );

		// cull/clip against -X
		curax = obj_pos.X - bd_sphere;
		dist0 = curax - prev_pos.X;
		dist1 = curax - test_pos.X;
		AXIAL_CLIP_T( 3 );

		// cull/clip against +Y
		curax = obj_pos.Y + bd_sphere;
		dist0 = prev_pos.Y - curax;
		dist1 = test_pos.Y - curax;
		AXIAL_CLIP_T( 4 );

		// cull/clip against -Y
		curax = obj_pos.Y - bd_sphere;
		dist0 = curax - prev_pos.Y;
		dist1 = curax - test_pos.Y;
		AXIAL_CLIP_T( 5 );

		//NOTE:
		// collside now contains the code of the collider side
		// (-1 means the lineseg starts in the bounding box)

		//TODO:
		// use already clipped segment in BSP test?

#endif // CHECK_BOX_BEFORE_BSP_COLLISION

		// test actual object (polygon accurate)

		// transform line vertices into object-space
		CalcOrthoInverse( cur_ship->ObjPosition, DestXmatrx );
		Vertex3 v0;
		MtxVctMUL( DestXmatrx, &prev_pos, &v0 );
		Vertex3 v1;
		MtxVctMUL( DestXmatrx, &test_pos, &v1 );

		// assume collision if no bsp tree
		CullBSPNode *node = cur_ship->AuxBSPTree;
		if ( node == NULL )
			return FALSE;

		dword	nodeid = 0;
		geomv_t	impact_t;
		int collided = BSP_FindColliderLine( node, &v0, &v1, &nodeid, &impact_t );

		// no collision?
		if ( !collided )
			return TRUE;

		// react only if not started in solid leaf
		if ( nodeid > 0 ) {

			// fetch collider
			node = &cur_ship->AuxBSPTree[ nodeid ];

			// calc collision position (object-space)
			v1.X -= v0.X;
			v1.Y -= v0.Y;
			v1.Z -= v0.Z;
			v1.X  = v0.X + GEOMV_MUL( v1.X, impact_t );
			v1.Y  = v0.Y + GEOMV_MUL( v1.Y, impact_t );
			v1.Z  = v0.Z + GEOMV_MUL( v1.Z, impact_t );

			// create hull impact particles
			SFX_HullImpact( cur_ship, &v1, &node->plane );
		}

		// disable shield
		test_shield = FALSE;
*/
	}

	return FALSE;
}