예제 #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 );
}
예제 #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;
}
예제 #3
0
int BSphereBSphereIntersect(BSphere *bsa, BSphere *bsb ) {

	float lx, ly, lz;
	float ls, rs;

	lx = bsa->sphereX - bsb->sphereX;
	ly = bsa->sphereY - bsb->sphereY;
	lz = bsa->sphereZ - bsb->sphereZ;

	ls = DOT_PRODUCT(lx, ly, lz, lx, ly, lz);
	rs = bsa->radius + bsb->radius;
	if (ls > (rs * rs)) return IREJECT; // Disjoint
	return IINTERSECT; // Intersect
}
예제 #4
0
void
PickShell (vector *v, real radius)
{
    real temp_r;
    real r_scale;

    do {
        v->x = XRand(-1.0, 1.0);
        v->y = XRand(-1.0, 1.0);
        temp_r = DOT_PRODUCT((*v), (*v));
    }
    while (temp_r >1.0);
    r_scale = radius / (real) sqrt(temp_r);
    VECTOR_MUL((*v), (*v), r_scale);
}
예제 #5
0
파일: vpArit.cpp 프로젝트: ricsp/visp
/*
 * La procedure "norm_vector" normalise le vecteur.
 * Si la norme est nulle la normalisation n'est pas effectuee.
 * Entree :
 * vp		Le vecteur a norme.
 * Sortie :
 * 		La norme du vecteur.
 */
float
norm_vector (Vector *vp)
{
	float	norm;	/* norme du vecteur 	*/

	if ((norm = (float) sqrt ((double) DOT_PRODUCT(*vp,*vp))) > M_EPSILON) {
		vp->x /= norm;
		vp->y /= norm;
		vp->z /= norm;
	}
  else {
    static	char	proc_name[] = "norm_vector";
    fprintf (stderr, "%s: nul vector\n", proc_name);
  }
	return (norm);
}
예제 #6
0
파일: vpArit.cpp 프로젝트: ricsp/visp
/*
 * La procedure "rotate_vector" transforme le vecteur
 * par la rotation de sens trigonometrique d'angle et d'axe donnes.
 * Entree :
 * vp		Vecteur a transformer.
 * a		Angle de rotation en degres.
 * axis		Vecteur directeur de l'axe de rotation.
 */
void
rotate_vector (Vector *vp, float a, Vector *axis)
{
	Vector		n, u, v, cross;
	float	f;

	a *= (float)M_PI / (float)180.0;	/* passage en radians		*/

	n = *axis;		/* norme le vecteur directeur	*/
	norm_vector (&n);

	/* 
	 * Avant rotation, vp vaut :
	 *   u + v
	 * Apres rotation, vp vaut :
	 *   u + cos(a) * v + sin(a) * (n^vp)
	 * = u + cos(a) * v + sin(a) * (n^v)
	 * avec u = (vp.n) * n, v = vp-u;
	 * ou "u" est la projection de "vp" sur l'axe "axis",
	 * et "v" est la composante de "vp" perpendiculaire a "axis".
	 */
	f = DOT_PRODUCT(*vp, n);
	u = n;
	MUL_COORD3(u,f,f,f);		/* (vp.n) * n		*/

	DIF_COORD3(v,*vp,u);		/* calcule "v"		*/

	f = (float) cos ((double) a);
	MUL_COORD3(v,f,f,f);		/* v * cos(a)		*/

	CROSS_PRODUCT(cross,n,*vp);
	f = (float) sin ((double) a);
	MUL_COORD3(cross,f,f,f);	/* (n^v) * sin(a)	*/

	SET_COORD3(*vp,
		u.x + v.x + cross.x,
		u.y + v.y + cross.y,
		u.z + v.z + cross.z);
}
예제 #7
0
int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, const Vector& origin)
{
	Vector	vecs[2];
	int		sv, tv;
	vec_t	ang, sinv, cosv;
	vec_t	ns, nt;
	texinfo_t	tx;
	int		i, j;

	if (!bt->name[0])
		return 0;

	memset (&tx, 0, sizeof(tx));

	// HLTOOLS - add support for texture vectors stored in the map file
	if (g_nMapFileVersion < 220)
	{
		TextureAxisFromPlane(plane, vecs[0], vecs[1]);
	}

	if (!bt->textureWorldUnitsPerTexel[0])
		bt->textureWorldUnitsPerTexel[0] = 1;
	if (!bt->textureWorldUnitsPerTexel[1])
		bt->textureWorldUnitsPerTexel[1] = 1;


	float shiftScaleU = 1.0f / 16.0f;
	float shiftScaleV = 1.0f / 16.0f;

	if (g_nMapFileVersion < 220)
	{
	// rotate axis
		if (bt->rotate == 0)
			{ sinv = 0 ; cosv = 1; }
		else if (bt->rotate == 90)
			{ sinv = 1 ; cosv = 0; }
		else if (bt->rotate == 180)
			{ sinv = 0 ; cosv = -1; }
		else if (bt->rotate == 270)
			{ sinv = -1 ; cosv = 0; }
		else
		{	
			ang = bt->rotate / 180 * M_PI;
			sinv = sin(ang);
			cosv = cos(ang);
		}

		if (vecs[0][0])
			sv = 0;
		else if (vecs[0][1])
			sv = 1;
		else
			sv = 2;
					
		if (vecs[1][0])
			tv = 0;
		else if (vecs[1][1])
			tv = 1;
		else
			tv = 2;
						
		for (i=0 ; i<2 ; i++)
		{
			ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
			nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
			vecs[i][sv] = ns;
			vecs[i][tv] = nt;
		}

		for (i=0 ; i<2 ; i++)
		{
			for (j=0 ; j<3 ; j++)
			{
				tx.textureVecsTexelsPerWorldUnits[i][j] = vecs[i][j] / bt->textureWorldUnitsPerTexel[i];
				tx.lightmapVecsLuxelsPerWorldUnits[i][j] = tx.textureVecsTexelsPerWorldUnits[i][j] / 16.0f;
			}
		}
	}
	else
	{
		tx.textureVecsTexelsPerWorldUnits[0][0] = bt->UAxis[0] / bt->textureWorldUnitsPerTexel[0];
		tx.textureVecsTexelsPerWorldUnits[0][1] = bt->UAxis[1] / bt->textureWorldUnitsPerTexel[0];
		tx.textureVecsTexelsPerWorldUnits[0][2] = bt->UAxis[2] / bt->textureWorldUnitsPerTexel[0];

		tx.textureVecsTexelsPerWorldUnits[1][0] = bt->VAxis[0] / bt->textureWorldUnitsPerTexel[1];
		tx.textureVecsTexelsPerWorldUnits[1][1] = bt->VAxis[1] / bt->textureWorldUnitsPerTexel[1];
		tx.textureVecsTexelsPerWorldUnits[1][2] = bt->VAxis[2] / bt->textureWorldUnitsPerTexel[1];

		tx.lightmapVecsLuxelsPerWorldUnits[0][0] = bt->UAxis[0] / bt->lightmapWorldUnitsPerLuxel;
		tx.lightmapVecsLuxelsPerWorldUnits[0][1] = bt->UAxis[1] / bt->lightmapWorldUnitsPerLuxel;
		tx.lightmapVecsLuxelsPerWorldUnits[0][2] = bt->UAxis[2] / bt->lightmapWorldUnitsPerLuxel;
		
		tx.lightmapVecsLuxelsPerWorldUnits[1][0] = bt->VAxis[0] / bt->lightmapWorldUnitsPerLuxel;
		tx.lightmapVecsLuxelsPerWorldUnits[1][1] = bt->VAxis[1] / bt->lightmapWorldUnitsPerLuxel;
		tx.lightmapVecsLuxelsPerWorldUnits[1][2] = bt->VAxis[2] / bt->lightmapWorldUnitsPerLuxel;

		shiftScaleU = bt->textureWorldUnitsPerTexel[0] / bt->lightmapWorldUnitsPerLuxel;
		shiftScaleV = bt->textureWorldUnitsPerTexel[1] / bt->lightmapWorldUnitsPerLuxel;
	}

	tx.textureVecsTexelsPerWorldUnits[0][3] = bt->shift[0] + 
		DOT_PRODUCT( origin, tx.textureVecsTexelsPerWorldUnits[0] );
	tx.textureVecsTexelsPerWorldUnits[1][3] = bt->shift[1] + 
		DOT_PRODUCT( origin, tx.textureVecsTexelsPerWorldUnits[1] );
	
	tx.lightmapVecsLuxelsPerWorldUnits[0][3] = shiftScaleU * bt->shift[0] +
		DOT_PRODUCT( origin, tx.lightmapVecsLuxelsPerWorldUnits[0] );
	tx.lightmapVecsLuxelsPerWorldUnits[1][3] = shiftScaleV * bt->shift[1] +
		DOT_PRODUCT( origin, tx.lightmapVecsLuxelsPerWorldUnits[1] );
	
	tx.flags = bt->flags;
	tx.texdata = FindOrCreateTexData( bt->name );

	// find the texinfo
	return FindOrCreateTexInfo( tx );
}
예제 #8
0
int IntersectTriangleRay(float P0x, float P0y, float P0z,
						 float P1x, float P1y, float P1z,
						 float P2x, float P2y, float P2z,
						 line *l,
						 float *u, float *v, float *t) {
	float e1[3];
	float e2[3];
	float p[3];
	float s[3];
	float q[3];
	float a, f;
	float lu, lv, lt;

	*u=0;
	*v=0;
	*t=0;

	// e1 = P1 - P0
	e1[0] = P1x - P0x;
	e1[1] = P1y - P0x;
	e1[2] = P1z - P0z;

	// e2 = P2 - P0
	e2[0] = P2x - P0x;
	e2[1] = P2y - P0y;
	e2[2] = P2z - P0z;

	crossVV(&p[0], &p[1], &p[2],
			l->dx, l->dy, l->dz,
			e2[0], e2[1], e2[2]);

	a = DOT_PRODUCT(e1[0], e1[1], e1[2],
					p[0], p[1], p[2]);

	if (a > -DISTANCE_EPSILON && a < DISTANCE_EPSILON) return IREJECT;

	f = 1.0 / a;

	// s = l->o - P0
	s[0] = l->ox - P0x;
	s[1] = l->oy - P0y;
	s[2] = l->oz - P0z;

	lu = f * DOT_PRODUCT(s[0], s[1], s[2],
						 p[0], p[1], p[2]);

	if (lu < 0.0 || lu > 1.0) return IREJECT;

	crossVV(&q[0], &q[1], &q[2],
			s[0], s[1], s[2],
			e1[0], e1[1], e1[2]);

	lv = f * DOT_PRODUCT(l->dx, l->dy, l->dz,
						 q[0], q[1], q[2]);

	if (lv < 0.0 || lv > 1.0) return IREJECT;

	lt = f * DOT_PRODUCT(e2[0], e2[1], e2[2],
						 q[0], q[1], q[2]);

	*u = lu;
	*v = lv;
	*t = lt;
	return IINTERSECT;
}
예제 #9
0
void
CreateDistribution (cluster_type cluster, model_type model)
{
    particle *particle_array;
    int global_num_particles;
    particle *new_particle;
    char particle_state[RANDOM_SIZE];
    real charge;
    real r_scale;
    real v_scale;
    vector r_sum;
    vector v_sum;
    int end_limit;
    int i;
    int j;
    real temp_r;
    real radius;
    real x_vel;
    real y_vel;
    real vel;
    real offset;
    particle *twin_particle;

    particle_array = (particle *) G_MALLOC(Total_Particles * sizeof(particle));

    Particle_List = (particle **) G_MALLOC(Total_Particles * sizeof(particle *));
    for (i = 0; i < Total_Particles; i++)
        Particle_List[i] = &particle_array[i];

    r_scale = 3 * M_PI / 16;
    v_scale = (real) sqrt(1.0 / (double) r_scale);
    r_sum.x = (real) 0.0;
    r_sum.y = (real) 0.0;
    v_sum.x = (real) 0.0;
    v_sum.y = (real) 0.0;
    initstate(0, particle_state, RANDOM_SIZE);

    switch (cluster) {
    case ONE_CLUSTER:
        end_limit = Total_Particles;
        switch (model) {
        case UNIFORM:
            printf("Creating a one cluster, uniform distribution for %d ",
                   Total_Particles);
            printf("particles\n");
            break;
        case PLUMMER:
            printf("Creating a one cluster, non uniform distribution for %d ",
                   Total_Particles);
            printf("particles\n");
            break;
        }
        break;
    case TWO_CLUSTER:
        end_limit = (Total_Particles / 2) + (Total_Particles & 0x1);
        switch (model) {
        case UNIFORM:
            printf("Creating a two cluster, uniform distribution for %d ",
                   Total_Particles);
            printf("particles\n");
            break;
        case PLUMMER:
            printf("Creating a two cluster, non uniform distribution for %d ",
                   Total_Particles);
            printf("particles\n");
            break;
        }
        break;
    }
    setstate(particle_state);
    global_num_particles = 0;
    charge = 1.0 / Total_Particles;
    charge /= Total_Particles;
    for (i = 0; i < end_limit; i++) {
        new_particle = InitParticle(charge, charge);
        switch (model) {
        case UNIFORM:
            do {
                new_particle->pos.x = XRand(-1.0, 1.0);
                new_particle->pos.y = XRand(-1.0, 1.0);
                temp_r = DOT_PRODUCT((new_particle->pos), (new_particle->pos));
            }
            while (temp_r > (real) 1.0);
            radius = sqrt(temp_r);
            break;
        case PLUMMER:
            do
                radius = (real) 1.0 / (real) sqrt(pow(XRand(0.0, MAX_FRAC),
                                                      -2.0/3.0) - 1);
            while (radius > 9.0);
            PickShell(&(new_particle->pos), r_scale * radius);
            break;
        }
        VECTOR_ADD(r_sum, r_sum, (new_particle->pos));

        do {
            x_vel = XRand(0.0, 1.0);
            y_vel = XRand(0.0, 0.1);
        }
        while (y_vel > x_vel * x_vel * (real) pow(1.0 - (x_vel * x_vel), 3.5));
        vel = (real) sqrt(2.0) * x_vel / pow(1.0 + (radius * radius), 0.25);
        PickShell(&(new_particle->vel), v_scale * vel);
        VECTOR_ADD(v_sum, v_sum, (new_particle->vel));
    }

    if (cluster == TWO_CLUSTER) {
        switch (model) {
        case UNIFORM:
            offset = 1.5;
            break;
        case PLUMMER:
            offset = 2.0;
            break;
        }
        for (i = end_limit; i < Total_Particles; i++) {
            new_particle = InitParticle(charge, charge);
            twin_particle = Particle_List[i - end_limit];
            new_particle->pos.x = twin_particle->pos.x + offset;
            new_particle->pos.y = twin_particle->pos.y + offset;
            VECTOR_ADD(r_sum, r_sum, (new_particle->pos));
            new_particle->vel.x = twin_particle->vel.x;
            new_particle->vel.y = twin_particle->vel.y;
            VECTOR_ADD(v_sum, v_sum, (new_particle->vel));
        }
    }

    VECTOR_DIV(r_sum, r_sum, (real) Total_Particles);
    VECTOR_DIV(v_sum, v_sum, (real) Total_Particles);
    for (i = 0; i < Total_Particles; i++) {
        new_particle = Particle_List[i];
        VECTOR_SUB((new_particle->pos), (new_particle->pos), r_sum);
        VECTOR_SUB((new_particle->vel), (new_particle->vel), v_sum);
    }
}
예제 #10
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;
}
예제 #11
0
// ----------------------------------------------------------------------------
//
void UTL_LocomotionController::ControlOjbect( object_control_s* pObjctl, Vector3* pDesiredVelocity, fixed_t _DesiredSpeed )
{
	ASSERT( pObjctl != NULL );
	ASSERT( pDesiredVelocity != NULL );

	Vector3 xDir, yDir, zDir;
	FetchXVector( pObjctl->pShip->ObjPosition, &xDir );
	FetchYVector( pObjctl->pShip->ObjPosition, &yDir );
	FetchZVector( pObjctl->pShip->ObjPosition, &zDir );

	geomv_t len = VctLenX( pDesiredVelocity );

	// stop control if desired velocity is zero 
	if ( len <= GEOMV_VANISHING ) {
		pObjctl->rot_x = 0;
		pObjctl->rot_y = 0;
		pObjctl->accel = -0.82;

#ifdef BOT_LOGFILES
		BOT_MsgOut( "ControlOjbect() got dimishing desired velocity" );
#endif // BOT_LOGFILES

		return;
	} else {
		Vector3 DesVelNorm;
		DesVelNorm.X = FLOAT_TO_GEOMV( pDesiredVelocity->X / len );
		DesVelNorm.Y = FLOAT_TO_GEOMV( pDesiredVelocity->Y / len );
		DesVelNorm.Z = FLOAT_TO_GEOMV( pDesiredVelocity->Z / len );
		
		geomv_t yaw_dot		= DOT_PRODUCT( &DesVelNorm, &xDir );
		geomv_t pitch_dot	= DOT_PRODUCT( &DesVelNorm, &yDir );
		geomv_t heading_dot = DOT_PRODUCT( &DesVelNorm, &zDir );

		float fDesiredSpeed = FIXED_TO_FLOAT( _DesiredSpeed );
		float fCurSpeed	  = FIXED_TO_FLOAT( pObjctl->pShip->CurSpeed );

		float pitch = 0;
		float yaw   = 0;

		// target is behind us
		sincosval_s fullturn;
		GetSinCos( DEG_TO_BAMS( 2 * m_nRelaxedHeadingAngle ), &fullturn );
		//if ( heading_dot < 0.0f ) {
		if ( heading_dot < -fullturn.cosval ) {

			// we must initiate a turn, if not already in a turn
			if ( !pObjctl->IsYaw() || !pObjctl->IsPitch() ) {

				// default to random
				yaw   = (float)( RAND() % 3 ) - 1;
				pitch = (float)( RAND() % 3 ) - 1;

				// steer towards goal
				if ( yaw_dot < -GEOMV_VANISHING ) {
					yaw = OCT_YAW_LEFT;
				} else if ( yaw_dot > GEOMV_VANISHING ) {
					yaw = OCT_YAW_RIGHT;
				}
				if ( pitch_dot < -GEOMV_VANISHING ) {
					pitch = OCT_PITCH_UP;
				} else if ( pitch_dot > GEOMV_VANISHING ) {
					pitch = OCT_PITCH_DOWN;
				}

			} else {
				// reuse prev. turn information
				pitch = pObjctl->rot_x;
				yaw   = pObjctl->rot_y;
			}

			// slow down, until in direction of target
		       // pObjctl->accel = heading_dot;
			//pObjctl->accel = OCT_DECELERATE;

			// also maintain min. speed during turns
			if ( fCurSpeed > m_fMinSpeedTurn ) {
				pObjctl->accel = -0.42;
			}

		} else {

			// determine accel
			if ( fDesiredSpeed > fCurSpeed ) {
				// accelerate towards target
				pObjctl->accel = OCT_ACCELERATE;
			} else if ( fDesiredSpeed < fCurSpeed ) {
				// decelerate towards target
				pObjctl->accel = OCT_DECELERATE;
			} else {
				// no accel
				pObjctl->accel = 0;
			}

			// heading must be inside of 5 degrees cone angle
			sincosval_s sincosv;
			GetSinCos( DEG_TO_BAMS( m_nRelaxedHeadingAngle ), &sincosv );
			if ( yaw_dot < -sincosv.sinval ) {
				yaw = OCT_YAW_LEFT;
			} else if ( yaw_dot > sincosv.sinval ) {
				yaw = OCT_YAW_RIGHT;
			}
			if ( pitch_dot < -sincosv.sinval ) {
				pitch = OCT_PITCH_UP;
			} else if ( pitch_dot > sincosv.sinval ) {
				pitch = OCT_PITCH_DOWN;
			}

			// if heading outside of 30 degrees cone angle, we decelerate
			GetSinCos( DEG_TO_BAMS( m_nFullSpeedHeading ), &sincosv );
			bool_t bYawOutsideHeading	= ( ( yaw_dot   < -sincosv.sinval ) || ( yaw_dot   > sincosv.sinval ) );
			bool_t bPitchOutsideHeading = ( ( pitch_dot < -sincosv.sinval ) || ( pitch_dot > sincosv.sinval ) );
			if ( bYawOutsideHeading || bPitchOutsideHeading ) {

				// also maintain min. speed during turns
				if ( fCurSpeed > min( m_fMinSpeedTurn, fDesiredSpeed ) ) {
					// decelerate towards target
					pObjctl->accel = OCT_DECELERATE;
				}
			}
		}

#ifdef BOT_LOGFILES
		BOT_MsgOut( "heading_dot: %f, yaw_dot: %f, pitch_dot: %f", heading_dot, yaw_dot, pitch_dot );
#endif // BOT_LOGFILES

		//FIXME: oct must also handle slide horiz./vert.

		pObjctl->rot_x = pitch;
		pObjctl->rot_y = yaw;
	}
}
예제 #12
0
int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, const Vector& origin)
{
	Vector	vecs[2];
	int		sv, tv;
	vec_t	ang, sinv, cosv;
	vec_t	ns, nt;
	texinfo_t	tx, *tc;
	int		i, j, k;

	if (!bt->name[0])
		return 0;

	memset (&tx, 0, sizeof(tx));

	// HLTOOLS - add support for texture vectors stored in the map file
	if (g_nMapFileVersion < 220)
	{
		TextureAxisFromPlane(plane, vecs[0], vecs[1]);
	}

	if (!bt->textureWorldUnitsPerTexel[0])
		bt->textureWorldUnitsPerTexel[0] = 1;
	if (!bt->textureWorldUnitsPerTexel[1])
		bt->textureWorldUnitsPerTexel[1] = 1;


	if (g_nMapFileVersion < 220)
	{
	// rotate axis
		if (bt->rotate == 0)
			{ sinv = 0 ; cosv = 1; }
		else if (bt->rotate == 90)
			{ sinv = 1 ; cosv = 0; }
		else if (bt->rotate == 180)
			{ sinv = 0 ; cosv = -1; }
		else if (bt->rotate == 270)
			{ sinv = -1 ; cosv = 0; }
		else
		{	
			ang = bt->rotate / 180 * M_PI;
			sinv = sin(ang);
			cosv = cos(ang);
		}

		if (vecs[0][0])
			sv = 0;
		else if (vecs[0][1])
			sv = 1;
		else
			sv = 2;
					
		if (vecs[1][0])
			tv = 0;
		else if (vecs[1][1])
			tv = 1;
		else
			tv = 2;
						
		for (i=0 ; i<2 ; i++)
		{
			ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
			nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
			vecs[i][sv] = ns;
			vecs[i][tv] = nt;
		}

		for (i=0 ; i<2 ; i++)
		{
			for (j=0 ; j<3 ; j++)
			{
				tx.textureVecsTexelsPerWorldUnits[i][j] = vecs[i][j] / bt->textureWorldUnitsPerTexel[i];
				tx.lightmapVecsLuxelsPerWorldUnits[i][j] = tx.textureVecsTexelsPerWorldUnits[i][j] / 16.0f;
			}
		}
	}
	else
	{
		tx.textureVecsTexelsPerWorldUnits[0][0] = bt->UAxis[0] / bt->textureWorldUnitsPerTexel[0];
		tx.textureVecsTexelsPerWorldUnits[0][1] = bt->UAxis[1] / bt->textureWorldUnitsPerTexel[0];
		tx.textureVecsTexelsPerWorldUnits[0][2] = bt->UAxis[2] / bt->textureWorldUnitsPerTexel[0];

		tx.textureVecsTexelsPerWorldUnits[1][0] = bt->VAxis[0] / bt->textureWorldUnitsPerTexel[1];
		tx.textureVecsTexelsPerWorldUnits[1][1] = bt->VAxis[1] / bt->textureWorldUnitsPerTexel[1];
		tx.textureVecsTexelsPerWorldUnits[1][2] = bt->VAxis[2] / bt->textureWorldUnitsPerTexel[1];

		tx.lightmapVecsLuxelsPerWorldUnits[0][0] = bt->UAxis[0] / bt->lightmapWorldUnitsPerLuxel;
		tx.lightmapVecsLuxelsPerWorldUnits[0][1] = bt->UAxis[1] / bt->lightmapWorldUnitsPerLuxel;
		tx.lightmapVecsLuxelsPerWorldUnits[0][2] = bt->UAxis[2] / bt->lightmapWorldUnitsPerLuxel;
		
		tx.lightmapVecsLuxelsPerWorldUnits[1][0] = bt->VAxis[0] / bt->lightmapWorldUnitsPerLuxel;
		tx.lightmapVecsLuxelsPerWorldUnits[1][1] = bt->VAxis[1] / bt->lightmapWorldUnitsPerLuxel;
		tx.lightmapVecsLuxelsPerWorldUnits[1][2] = bt->VAxis[2] / bt->lightmapWorldUnitsPerLuxel;
	}

	tx.textureVecsTexelsPerWorldUnits[0][3] = bt->shift[0] + 
		DOT_PRODUCT( origin, tx.textureVecsTexelsPerWorldUnits[0] );
	tx.textureVecsTexelsPerWorldUnits[1][3] = bt->shift[1] + 
		DOT_PRODUCT( origin, tx.textureVecsTexelsPerWorldUnits[1] );
	
	tx.lightmapVecsLuxelsPerWorldUnits[0][3] = bt->shift[0] +
		DOT_PRODUCT( origin, tx.lightmapVecsLuxelsPerWorldUnits[0] );
	tx.lightmapVecsLuxelsPerWorldUnits[1][3] = bt->shift[1] +
		DOT_PRODUCT( origin, tx.lightmapVecsLuxelsPerWorldUnits[1] );
	
	tx.flags = bt->flags;

	//
	// find the texinfo
	//
	if ( numtexinfo >= MAX_MAP_TEXINFO )
	{
		Error( "Map has too many texinfos, MAX_MAP_TEXINFO == %i\n", MAX_MAP_TEXINFO );
	}

	tc = texinfo;
	tx.texdata = FindTexData( bt->name );
	for (i=0 ; i<numtexinfo ; i++, tc++)
	{
		if (tc->flags != tx.flags)
			continue;
		bool skip = false;
		for (j=0 ; j<2 && !skip; j++)
		{
			if ( tc->texdata != tx.texdata )
			{
				skip = true;
				break;
			}
			for (k=0 ; k<4 && !skip; k++)
			{
				if (tc->textureVecsTexelsPerWorldUnits[j][k] != tx.textureVecsTexelsPerWorldUnits[j][k])
				{
					skip = true;
					break;
				}
				if( tc->lightmapVecsLuxelsPerWorldUnits[j][k] != tx.lightmapVecsLuxelsPerWorldUnits[j][k] )
				{
					skip = true;
					break;
				}
			}
		}

		if ( skip )
		{
			continue;
		}

		return i;
	}

	*tc = tx;

	if ( onlyents )
	{
		Error( "FindOrCreateTexInfo:  Tried to create new texinfo during -onlyents compile!\n" );
	}

	numtexinfo++;

	return i;
}
void Collision_Response(void)
{
// this function does all the "real" physics to determine if there has
// been a collision between any ball and any other ball, if there is a collision
// the function uses the mass of each ball along with the intial velocities to 
// compute the resulting velocities

// from the book we know that in general 
// va2 = (e+1)*mb*vb1+va1(ma - e*mb)/(ma+mb)
// vb2 = (e+1)*ma*va1+vb1(ma - e*mb)/(ma+mb)

// and the objects will have direction vectors co-linear to the normal
// of the point of collision, but since we are using spheres here as the objects
// we know that the normal to the point of collision is just the vector from the 
// center's of each object, thus the resulting velocity vector of each ball will
// be along this normal vector direction

// step 1: test each object against each other object and test for a collision
// there are better ways to do this other than a double nested loop, but since
// there are a small number of objects this is fine, also we want to somewhat model
// if two or more balls hit simulataneously

for (int ball_a = 0; ball_a < NUM_BALLS; ball_a++)
     {
     for (int ball_b = ball_a+1; ball_b < NUM_BALLS; ball_b++)
         {
         if (ball_a == ball_b) 
            continue;

         // compute the normal vector from a->b
         float nabx = (balls[ball_b].varsF[INDEX_X] - balls[ball_a].varsF[INDEX_X] );
         float naby = (balls[ball_b].varsF[INDEX_Y] - balls[ball_a].varsF[INDEX_Y] );
         float length = sqrt(nabx*nabx + naby*naby);

         // is there a collision?
         if (length <= 2.0*(BALL_RADIUS*.75))
            {
            // the balls have made contact, compute response

            // compute the response coordinate system axes
            // normalize normal vector
            nabx/=length;
            naby/=length;

            // compute the tangential vector perpendicular to normal, simply rotate vector 90
            float tabx =  -naby;
            float taby =  nabx;

            // draw collision
            DDraw_Lock_Primary_Surface();

            // blue is normal
            Draw_Clip_Line16(balls[ball_a].varsF[INDEX_X]+0.5, 
               balls[ball_a].varsF[INDEX_Y]+0.5,
               balls[ball_a].varsF[INDEX_X]+20*nabx+0.5,
               balls[ball_a].varsF[INDEX_Y]+20*naby+0.5,
               RGB16Bit(0,0,255), primary_buffer, primary_lpitch); 

            // yellow is tangential
            Draw_Clip_Line16(balls[ball_a].varsF[INDEX_X]+0.5, 
               balls[ball_a].varsF[INDEX_Y]+0.5,
               balls[ball_a].varsF[INDEX_X]+20*tabx+0.5,
               balls[ball_a].varsF[INDEX_Y]+20*taby+0.5,
               RGB16Bit(0,255,255), primary_buffer, primary_lpitch); 

             DDraw_Unlock_Primary_Surface();

            // tangential is also normalized since it's just a rotated normal vector
        
            // step 2: compute all the initial velocities
            // notation ball: (a,b) initial: i, final: f, n: normal direction, t: tangential direction

            float vait = DOT_PRODUCT(balls[ball_a].varsF[INDEX_XV], 
                                     balls[ball_a].varsF[INDEX_YV], 
                                     tabx, taby);

            float vain = DOT_PRODUCT(balls[ball_a].varsF[INDEX_XV], 
                                     balls[ball_a].varsF[INDEX_YV], 
                                     nabx, naby);

            float vbit = DOT_PRODUCT(balls[ball_b].varsF[INDEX_XV], 
                                     balls[ball_b].varsF[INDEX_YV], 
                                     tabx, taby);

            float vbin = DOT_PRODUCT(balls[ball_b].varsF[INDEX_XV], 
                                     balls[ball_b].varsF[INDEX_YV], 
                                     nabx, naby);


            // now we have all the initial velocities in terms of the n and t axes
            // step 3: compute final velocities after collision, from book we have
            // note: all this code can be optimized, but I want you to see what's happening :)

            float ma = balls[ball_a].varsF[INDEX_MASS];
            float mb = balls[ball_b].varsF[INDEX_MASS];
 
            float vafn = (mb*vbin*(cof_E+1) + vain*(ma - cof_E*mb)) / (ma + mb);
            float vbfn = (ma*vain*(cof_E+1) - vbin*(ma - cof_E*mb)) / (ma + mb);

            // now luckily the tangential components are the same before and after, so
            float vaft = vait;
            float vbft = vbit;

            // and that's that baby!
            // the velocity vectors are:
            // object a (vafn, vaft)
            // object b (vbfn, vbft)    
 
            // the only problem is that we are in the wrong coordinate system! we need to 
            // translate back to the original x,y coordinate system, basically we need to 
            // compute the sum of the x components relative to the n,t axes and the sum of
            // the y components relative to the n,t axis, since n,t may both have x,y
            // components in the original x,y coordinate system
            
            float xfa = vafn*nabx + vaft*tabx;
            float yfa = vafn*naby + vaft*taby;

            float xfb = vbfn*nabx + vbft*tabx;
            float yfb = vbfn*naby + vbft*taby;

            // store results
            balls[ball_a].varsF[INDEX_XV] = xfa;
            balls[ball_a].varsF[INDEX_YV] = yfa;

            balls[ball_b].varsF[INDEX_XV] = xfb;
            balls[ball_b].varsF[INDEX_YV] = yfb;

            // update position
            balls[ball_a].varsF[INDEX_X]+=balls[ball_a].varsF[INDEX_XV];
            balls[ball_a].varsF[INDEX_Y]+=balls[ball_a].varsF[INDEX_YV];

            balls[ball_b].varsF[INDEX_X]+=balls[ball_b].varsF[INDEX_XV];
            balls[ball_b].varsF[INDEX_Y]+=balls[ball_b].varsF[INDEX_YV];

            } // end if

         } // end for ball2

     } // end for ball1

} // end Collision_Response
예제 #14
0
// perform animation for homing missiles -------------------------------------
//
PRIVATE
void AnimateHomingMissile( MissileObject *missilepo )
{
	ASSERT( missilepo != NULL );

	Vector3 tempspeed;
	tempspeed.X = missilepo->DirectionVec.X * CurScreenRefFrames;
	tempspeed.Y = missilepo->DirectionVec.Y * CurScreenRefFrames;
	tempspeed.Z = missilepo->DirectionVec.Z * CurScreenRefFrames;

	missilepo->PrevPosition.X = missilepo->ObjPosition[ 0 ][ 3 ];
	missilepo->PrevPosition.Y = missilepo->ObjPosition[ 1 ][ 3 ];
	missilepo->PrevPosition.Z = missilepo->ObjPosition[ 2 ][ 3 ];

	missilepo->ObjPosition[ 0 ][ 3 ] += tempspeed.X;
	missilepo->ObjPosition[ 1 ][ 3 ] += tempspeed.Y;
	missilepo->ObjPosition[ 2 ][ 3 ] += tempspeed.Z;

	TargetMissileObject	*tmissilepo	= (TargetMissileObject *) missilepo;
	GenObject			*targetpo	= NULL;

	if ( tmissilepo->TargetObjNumber == TARGETID_NO_TARGET ) {

		// no target (already lost)
		targetpo = NULL;

	} else if ( tmissilepo->TargetObjNumber == ShipHostObjId( LocalPlayerId ) ) {

		// local player is target
		targetpo = MyShip;

		// announce incoming missile
		#define INCOMING_SHOWTIME	600
		IncomingMissile = INCOMING_SHOWTIME;

		// start incoming sample looping
		AUD_IncomingMissile( INCOMING_SHOWTIME );

	} else {

		// search for target in shiplist
		targetpo = FetchFirstShip();
		while ( ( targetpo != NULL ) &&
				( targetpo->HostObjNumber != tmissilepo->TargetObjNumber ) ) {
			targetpo = targetpo->NextObj;
		}
		if ( targetpo == NULL ) {
			// missile loses target once object not found
			tmissilepo->TargetObjNumber = TARGETID_NO_TARGET;
		}
	}

	if ( ( targetpo != NULL ) ) {

		Vector3 dirvec;
		dirvec.X = targetpo->ObjPosition[ 0 ][ 3 ] - missilepo->ObjPosition[ 0 ][ 3 ];
		dirvec.Y = targetpo->ObjPosition[ 1 ][ 3 ] - missilepo->ObjPosition[ 1 ][ 3 ];
		dirvec.Z = targetpo->ObjPosition[ 2 ][ 3 ] - missilepo->ObjPosition[ 2 ][ 3 ];

		Vector3 normvec;
		normvec.X = missilepo->ObjPosition[ 0 ][ 2 ];
		normvec.Y = missilepo->ObjPosition[ 1 ][ 2 ];
		normvec.Z = missilepo->ObjPosition[ 2 ][ 2 ];

		if ( DOT_PRODUCT( &dirvec, &normvec ) < 0 ) {

			// lock lost due to position
			tmissilepo->TargetObjNumber = TARGETID_NO_TARGET;

		} else {

			normvec.X = missilepo->ObjPosition[ 0 ][ 1 ];
			normvec.Y = missilepo->ObjPosition[ 1 ][ 1 ];
			normvec.Z = missilepo->ObjPosition[ 2 ][ 1 ];
			if ( DOT_PRODUCT( &dirvec, &normvec ) <= 0 ) {
				ObjRotX( missilepo->ObjPosition, tmissilepo->MaxRotation );
			} else {
				ObjRotX( missilepo->ObjPosition, -tmissilepo->MaxRotation );
			}

			normvec.X = missilepo->ObjPosition[ 0 ][ 0 ];
			normvec.Y = missilepo->ObjPosition[ 1 ][ 0 ];
			normvec.Z = missilepo->ObjPosition[ 2 ][ 0 ];
			if ( DOT_PRODUCT( &dirvec, &normvec ) <= 0 ) {
				ObjRotY( missilepo->ObjPosition, -tmissilepo->MaxRotation );
			} else {
				ObjRotY( missilepo->ObjPosition, tmissilepo->MaxRotation );
			}
		}

		DirVctMUL( missilepo->ObjPosition, FIXED_TO_GEOMV( missilepo->Speed ), &missilepo->DirectionVec );
	}
}