Пример #1
0
/*
** RB_SurfaceRailRinges
*/
static void RB_SurfaceRailRings( void ) {
	refEntity_t *e;
	int			numSegs;
	int			len;
	vec3_t		vec;
	vec3_t		right, up;
	vec3_t		start, end;

	e = &backEnd.currentEntity->e;

	VectorCopy( e->oldorigin, start );
	VectorCopy( e->origin, end );

	// compute variables
	VectorSubtract( end, start, vec );
	len = VectorNormalize( vec );
	MakeNormalVectors( vec, right, up );
	numSegs = ( len ) / r_railSegmentLength->value;
	if ( numSegs <= 0 ) {
		numSegs = 1;
	}

	VectorScale( vec, r_railSegmentLength->value, vec );

	DoRailDiscs( numSegs, start, vec, right, up );
}
Пример #2
0
/*
==============
CG_SurfaceRailRings
==============
*/
void CG_SurfaceRailRings( const refEntity_t *originEnt ) {
	refEntity_t re;
	int			numSegs;
	int			len;
	vec3_t		vec;
	vec3_t		right, up;
	vec3_t		start, end;

	re = *originEnt;

	VectorCopy( re.oldorigin, start );
	VectorCopy( re.origin, end );

	// compute variables
	VectorSubtract( end, start, vec );
	len = VectorNormalize( vec );
	MakeNormalVectors( vec, right, up );
	numSegs = ( len ) / cg_railSegmentLength.value;
	if ( numSegs <= 0 ) {
		numSegs = 1;
	}

	VectorScale( vec, cg_railSegmentLength.value, vec );

	CG_DoRailDiscs( re.customShader, re.shaderRGBA, numSegs, start, vec, right, up );
}
Пример #3
0
/*
===============
CL_ParticleSmokeEffect - like the steam effect, but unaffected by gravity
===============
*/
void CL_ParticleSmokeEffect (vec3_t org, vec3_t dir, int color, int count, int magnitude)
{
    int         i, j;
    cparticle_t *p;
    float       d;
    vec3_t      r, u;

    MakeNormalVectors (dir, r, u);

    for (i=0 ; i<count ; i++)
    {
        p = CL_AllocParticle();
        if (!p)
            return;

        p->time = cl.time;
        p->color = color + (rand()&7);

        for (j=0 ; j<3 ; j++)
        {
            p->org[j] = org[j] + magnitude*0.1*crand();
//          p->vel[j] = dir[j]*magnitude;
        }
        VectorScale (dir, magnitude, p->vel);
        d = crand()*magnitude/3;
        VectorMA (p->vel, d, r, p->vel);
        d = crand()*magnitude/3;
        VectorMA (p->vel, d, u, p->vel);

        p->accel[0] = p->accel[1] = p->accel[2] = 0;
        p->alpha = 1.0;

        p->alphavel = -1.0 / (0.5 + frand()*0.3);
    }
}
Пример #4
0
//	Puffs with velocity along direction, with some randomness thrown in
void CLQ2_ParticleSteamEffect( vec3_t org, vec3_t dir, int color, int count, int magnitude ) {
	vec3_t r, u;
	MakeNormalVectors( dir, r, u );

	for ( int i = 0; i < count; i++ ) {
		cparticle_t* p = CL_AllocParticle();
		if ( !p ) {
			return;
		}
		p->type = pt_q2static;

		p->color = color + ( rand() & 7 );

		for ( int j = 0; j < 3; j++ ) {
			p->org[ j ] = org[ j ] + magnitude * 0.1 * crand();
		}
		VectorScale( dir, magnitude, p->vel );
		float d = crand() * magnitude / 3;
		VectorMA( p->vel, d, r, p->vel );
		d = crand() * magnitude / 3;
		VectorMA( p->vel, d, u, p->vel );

		p->accel[ 0 ] = p->accel[ 1 ] = 0;
		p->accel[ 2 ] = -PARTICLE_GRAVITY / 2;
		p->alpha = 1.0;

		p->alphavel = -1.0 / ( 0.5 + frand() * 0.3 );
	}
}
Пример #5
0
void CLQ2_DebugTrail( vec3_t start, vec3_t end ) {
	vec3_t move;
	VectorCopy( start, move );
	vec3_t vec;
	VectorSubtract( end, start, vec );
	float len = VectorNormalize( vec );

	vec3_t right, up;
	MakeNormalVectors( vec, right, up );

	float dec = 3;
	VectorScale( vec, dec, vec );
	VectorCopy( start, move );

	while ( len > 0 ) {
		len -= dec;

		cparticle_t* p = CL_AllocParticle();
		if ( !p ) {
			return;
		}
		p->type = pt_q2static;

		VectorClear( p->accel );
		VectorClear( p->vel );
		p->alpha = 1.0;
		p->alphavel = -0.1;
		p->color = 0x74 + ( rand() & 7 );
		VectorCopy( move, p->org );
		VectorAdd( move, vec, move );
	}
}
Пример #6
0
void R_RailTrail (vec3_t start, vec3_t end)
{
    vec3_t              move;
    vec3_t              vec;
    float               len;
    int                 j;
    particle_t          *p;
    float               dec;
    vec3_t              right, up;
    int                 i;
    float               d, c, s;
    vec3_t              dir;
    byte                clr = 40;

    VectorCopy (start, move);
    VectorSubtract (end, start, vec);
    len = VectorNormalize (vec);

    MakeNormalVectors (vec, right, up);

    for (i=0 ; i<len ; i++)
    {
        if (!free_particles)
            return;

        p = free_particles;
        free_particles = p->next;
        p->next = active_particles;
        active_particles = p;

        p->die = cl.time + 2.0;
        p->start_time = cl.time; // Manoel Kasimier
        VectorClear (p->vel);

        d = i * 0.1;
        c = cos(d);
        s = sin(d);

        VectorScale (right, c, dir);
        VectorMA (dir, s, up, dir);
        p->type = pt_staticfadeadd;
        p->alpha = 1.0;
        //      p->alphavel = -1.0 / (1+frand()*0.2);
        p->alphavel = -1.0;

        p->color = clr + (rand()&7);
        for (j=0 ; j<3 ; j++)
        {
            p->org[j] = move[j] + dir[j]*3;
            p->vel[j] = dir[j]*6;
        }

        VectorAdd (move, vec, move);
    }

    dec = 0.75;
    VectorScale (vec, dec, vec);
    VectorCopy (start, move);
}
Пример #7
0
/*
======
CL_DebugTrail
======
*/
void CL_DebugTrail (vec3_t start, vec3_t end)
{
	vec3_t		move;
	vec3_t		vec;
	float		len;
//	int			j;
	cparticle_t	*p;
	float		dec;
	vec3_t		right, up;
//	int			i;
//	float		d, c, s;
//	vec3_t		dir;

	VectorCopy (start, move);
	VectorSubtract (end, start, vec);
	len = VectorNormalize (vec);

	MakeNormalVectors (vec, right, up);

//	VectorScale(vec, RT2_SKIP, vec);

//	dec = 1.0;
//	dec = 0.75;
	dec = 3;
	VectorScale (vec, dec, vec);
	VectorCopy (start, move);

	while (len > 0)
	{
		len -= dec;

		if (!free_particles)
			return;
		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
		VectorClear (p->accel);
		VectorClear (p->vel);
		p->alpha = 1.0;
		p->alphavel = -0.1;
//		p->alphavel = 0;
		p->color = 0x74 + (rand()&7);
		VectorCopy (move, p->org);
/*
		for (j=0 ; j<3 ; j++)
		{
			p->org[j] = move[j] + crand()*2;
			p->vel[j] = crand()*3;
			p->accel[j] = 0;
		}
*/
		VectorAdd (move, vec, move);
	}

}
Пример #8
0
void CG_PlayEffect( const char *fxName, vec3_t origin, const vec3_t fwd )
{
	vec3_t	temp, axis[3];

	// Assume angles, we'll do a cross product to finish up
	VectorCopy( fwd, axis[0] );
	MakeNormalVectors( fwd, axis[1], temp );
	CrossProduct( axis[0], axis[1], axis[2] );
	//call FX scheduler directly
	theFxScheduler.PlayEffect( fxName, origin, axis, -1, -1, false );
}
Пример #9
0
/*==============
CG_AuraStart
==============*/
void CG_AuraStart( centity_t *player){
	int				clientNum, tier;
	auraState_t		*state;
	auraConfig_t	*config;

	vec3_t			groundPoint;
	trace_t			trace;

	// Get the aura system corresponding to the player
	clientNum = player->currentState.clientNum;
	if(clientNum < 0 || clientNum >= MAX_CLIENTS){
		CG_Error( "Bad clientNum on player entity");
		return;
	}
	state = &auraStates[ clientNum ];
	tier = cgs.clientinfo[clientNum].tierCurrent;
	config = &(state->configurations[tier]);	
	

	// If the aura is already active, don't continue activating it again.
	if(state->isActive){
		return;
	}

	// Initialize the system
	state->isActive = qtrue;
	state->lightAmt = config->lightMin;

	// create a small camerashake
	CG_AddEarthquake( player->lerpOrigin, 1000, 1, 0, 1, 200);

	// We don't want smoke jets if this is a boost aura instead of a charge aura.
	if(!(player->currentState.powerups &(1 << PW_BOOST))){
		// Check if we're on, or near ground level
		VectorCopy( player->lerpOrigin, groundPoint);
		groundPoint[2] -= 48;
		CG_Trace( &trace, player->lerpOrigin, NULL, NULL, groundPoint, player->currentState.number, CONTENTS_SOLID);
		if(trace.allsolid || trace.startsolid){
			trace.fraction = 1.0f;
		}
		if(trace.fraction < 1.0f){
			vec3_t tempAxis[3];

			// Place the explosion just a bit off the surface
			VectorNormalize2(trace.plane.normal, groundPoint);
			VectorMA( trace.endpos, 5, groundPoint, groundPoint);

			VectorNormalize2( trace.plane.normal, tempAxis[0]);
			MakeNormalVectors( tempAxis[0], tempAxis[1], tempAxis[2]);
			PSys_SpawnCachedSystem( "AuraSmokeBurst", groundPoint, tempAxis, NULL, NULL, qfalse, qfalse);
		}
	}
}
Пример #10
0
// Play an effect at the origin of the specified entity
//----------------------------
void G_PlayEffect( int fxID, int entNum, vec3_t fwd )
{
	gentity_t	*tent;
	vec3_t		temp;

	tent = G_TempEntity( g_entities[entNum].currentOrigin, EV_PLAY_EFFECT );
	tent->s.eventParm = fxID;
	tent->s.otherEntityNum = entNum;
	VectorSet( tent->maxs, FX_ENT_RADIUS, FX_ENT_RADIUS, FX_ENT_RADIUS );
	VectorScale( tent->maxs, -1, tent->mins );
	VectorCopy( fwd, tent->pos3 );

	// Assume angles, we'll do a cross product on the other end to finish up
	MakeNormalVectors( fwd, tent->pos4, temp );
}
Пример #11
0
void CL_ParticleSteamEffect2 (cl_sustain_t *self)
//vec3_t org, vec3_t dir, int color, int count, int magnitude)
{
	int			i, j;
	cparticle_t	*p;
	float		d;
	vec3_t		r, u;
	vec3_t		dir;

//	vectoangles2 (dir, angle_dir);
//	AngleVectors (angle_dir, f, r, u);

	VectorCopy (self->dir, dir);
	MakeNormalVectors (dir, r, u);

	for (i=0 ; i<self->count ; i++)
	{
		if (!free_particles)
			return;
		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
#ifndef QMAX
		p->color = self->color + (rand()&7);
#endif
		for (j=0 ; j<3 ; j++)
		{
			p->org[j] = self->org[j] + self->magnitude*0.1*crand();
//			p->vel[j] = dir[j]*magnitude;
		}
		VectorScale (dir, self->magnitude, p->vel);
		d = crand()*self->magnitude/3;
		VectorMA (p->vel, d, r, p->vel);
		d = crand()*self->magnitude/3;
		VectorMA (p->vel, d, u, p->vel);

		p->accel[0] = p->accel[1] = 0;
		p->accel[2] = -PARTICLE_GRAVITY/2;
		p->alpha = 1.0;

		p->alphavel = -1.0 / (0.5 + frand()*0.3);
	}
	self->nextthink += self->thinkinterval;
}
Пример #12
0
//-----------------------------
void G_PlayEffect( int fxID, const vec3_t origin, const vec3_t fwd )
{
	gentity_t	*tent;
	vec3_t	temp;

	tent = G_TempEntity( origin, EV_PLAY_EFFECT );
	tent->s.eventParm = fxID;

	VectorSet( tent->maxs, FX_ENT_RADIUS, FX_ENT_RADIUS, FX_ENT_RADIUS );
	VectorScale( tent->maxs, -1, tent->mins );

	VectorCopy( fwd, tent->pos3 );

	// Assume angles, we'll do a cross product on the other end to finish up
	MakeNormalVectors( fwd, tent->pos4, temp );
	gi.linkentity( tent );
}
Пример #13
0
// Play an effect at a position on an entity.
// Mostly for G_MissileBounceEffect so we can play an effect on the bouncee.
//-----------------------------
void G_PlayEffect( int fxID, int clientNum, vec3_t origin, vec3_t fwd )
{
	gentity_t	*tent;
	vec3_t	temp;

	tent = G_TempEntity( origin, EV_PLAY_EFFECT );
	tent->s.eventParm = fxID;
	if ( clientNum != -1 )
	{
		tent->s.saberActive = 1;
		tent->s.otherEntityNum = clientNum;
	}
	VectorSet( tent->maxs, FX_ENT_RADIUS, FX_ENT_RADIUS, FX_ENT_RADIUS );
	VectorScale( tent->maxs, -1, tent->mins );
	VectorCopy( fwd, tent->s.angles );

	// Assume angles, we'll do a cross product on the other end to finish up
	MakeNormalVectors( fwd, tent->s.angles2, temp );
}
Пример #14
0
/*
===============
CL_ParticleSteamEffect

Puffs with velocity along direction, with some randomness thrown in
===============
*/
void CL_ParticleSteamEffect (vec3_t org, vec3_t dir, int color, int count, int magnitude)
{
	int			i, j;
	cparticle_t	*p;
	float		d;
	vec3_t		r, u;

//	vectoangles2 (dir, angle_dir);
//	AngleVectors (angle_dir, f, r, u);

	MakeNormalVectors (dir, r, u);

	for (i=0 ; i<count ; i++)
	{
		if (!free_particles)
			return;
		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
		p->color = color + (rand()&7);

		for (j=0 ; j<3 ; j++)
		{
			p->org[j] = org[j] + magnitude*0.1*crand();
//			p->vel[j] = dir[j]*magnitude;
		}
		VectorScale (dir, magnitude, p->vel);
		d = crand()*magnitude/3;
		VectorMA (p->vel, d, r, p->vel);
		d = crand()*magnitude/3;
		VectorMA (p->vel, d, u, p->vel);

		p->accel[0] = p->accel[1] = 0;
		p->accel[2] = -PARTICLE_GRAVITY/2;
		p->alpha = 1.0;

		p->alphavel = -1.0 / (0.5 + frand()*0.3);
	}
}
Пример #15
0
//----------------------------------------------------------
void fx_runner_think( gentity_t *ent )
{
	vec3_t temp;

	EvaluateTrajectory( &ent->s.pos, level.time, ent->currentOrigin );
	EvaluateTrajectory( &ent->s.apos, level.time, ent->currentAngles );

	// call the effect with the desired position and orientation
	G_AddEvent( ent, EV_PLAY_EFFECT, ent->fxID );

	// Assume angles, we'll do a cross product on the other end to finish up
	AngleVectors( ent->currentAngles, ent->pos3, NULL, NULL );
	MakeNormalVectors( ent->pos3, ent->pos4, temp ); // there IS a reason this is done...it's so that it doesn't break every effect in the game...

	ent->nextthink = level.time + ent->delay + random() * ent->random;

	if ( ent->spawnflags & 4 ) // damage
	{
		G_RadiusDamage( ent->currentOrigin, ent, ent->splashDamage, ent->splashRadius, ent, MOD_UNKNOWN );
	}

	if ( ent->target2 )
	{
		// let our target know that we have spawned an effect
		G_UseTargets2( ent, ent, ent->target2 );
	}

	if ( !(ent->spawnflags & 2 ) && !ent->s.loopSound ) // NOT ONESHOT...this is an assy thing to do
	{
		if ( VALIDSTRING( ent->soundSet ) == true )
		{
			ent->s.loopSound = CAS_GetBModelSound( ent->soundSet, BMS_MID );

			if ( ent->s.loopSound < 0 )
			{
				ent->s.loopSound = 0;
			}
		}
	}

}
Пример #16
0
/*
======
CL_DebugTrail
======
*/
void CL_DebugTrail (const vec3_t start, const vec3_t end)
{
	vec3_t		move, vec;
	float		len;
	cparticle_t	*p;
	float		dec = 3;
	vec3_t		right, up;


	VectorCopy (start, move);
	VectorSubtract (end, start, vec);
	len = VectorNormalize (vec);

	MakeNormalVectors (vec, right, up);

	VectorScale (vec, dec, vec);
	VectorCopy (start, move);

	while (len > 0)
	{
		len -= dec;

		if (!free_particles)
			return;
		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
		VectorClear (p->accel);
		VectorClear (p->vel);
		p->alpha = 1.0f;
		p->alphavel = -0.1f;
		p->color = 0x74 + (rand()&7);
		VectorCopy (move, p->org);

		VectorAdd (move, vec, move);
	}

}
Пример #17
0
/*
===============
CL_ParticleSteamEffect

Puffs with velocity along direction, with some randomness thrown in
===============
*/
void CL_ParticleSteamEffect (const vec3_t org, const vec3_t dir, int color, int count, int magnitude)
{
	int			i;
	cparticle_t	*p;
	float		d;
	vec3_t		r, u;

//	VecToAngles(dir, angle_dir);
//	AngleVectors (angle_dir, f, r, u);

	MakeNormalVectors (dir, r, u);

	for (i=0 ; i<count ; i++)
	{
		if (!free_particles)
			return;
		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
		p->color = color + (rand()&7);

		p->org[0] = org[0] + magnitude*0.1f*crand();
		p->org[1] = org[1] + magnitude*0.1f*crand();
		p->org[2] = org[2] + magnitude*0.1f*crand();

		VectorScale (dir, magnitude, p->vel);
		d = crand()*magnitude*0.3333333333f;
		VectorMA (p->vel, d, r, p->vel);
		d = crand()*magnitude*0.3333333333f;
		VectorMA (p->vel, d, u, p->vel);

		p->accel[0] = p->accel[1] = 0;
		p->accel[2] = -PARTICLE_GRAVITY*0.5f;
		p->alpha = 1.0f;

		p->alphavel = -1.0f / (0.5f + frand()*0.3f);
	}
}
Пример #18
0
void CL_ParticleSteamEffect2 (cl_sustain_t *self)
{
	int			i;
	cparticle_t	*p;
	float		d;
	vec3_t		r, u, dir;

	VectorCopy (self->dir, dir);
	MakeNormalVectors (dir, r, u);

	for (i=0 ; i<self->count ; i++)
	{
		if (!free_particles)
			return;
		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
		p->color = self->color + (rand()&7);

		p->org[0] = self->org[0] + self->magnitude*0.1f*crand();
		p->org[1] = self->org[1] + self->magnitude*0.1f*crand();
		p->org[2] = self->org[2] + self->magnitude*0.1f*crand();

		VectorScale (dir, self->magnitude, p->vel);
		d = crand()*self->magnitude*0.3333333333f;
		VectorMA (p->vel, d, r, p->vel);
		d = crand()*self->magnitude*0.3333333333f;
		VectorMA (p->vel, d, u, p->vel);

		p->accel[0] = p->accel[1] = 0;
		p->accel[2] = -PARTICLE_GRAVITY*0.5f;
		p->alpha = 1.0f;

		p->alphavel = -1.0f / (0.5f + frand()*0.3f);
	}
	self->nextthink += self->thinkinterval;
}
Пример #19
0
void FXQuad::Draw( void )
{
	polyVert_t	verts[NUM_QUADVERTS];
	vec3_t		vr, vu;
	vec3_t		axis[3];
	float		scale;
	int			i;

	scale = m_scale * 0.5f;

	MakeNormalVectors( m_normal, vr, vu );
	VectorCopy( m_normal, axis[0] );
	VectorCopy( vr, axis[1] );
	VectorCopy( vu, axis[2] );

	RotateAroundDirection( axis, m_roll );

	//Construct the quad
	for ( i = 0; i < NUM_QUADVERTS; i++ )
	{
		VectorMA( m_origin,		quad_template[i][0] * ( scale ), axis[1], verts[i].xyz );
		VectorMA( verts[i].xyz, quad_template[i][1] * ( scale ), axis[2], verts[i].xyz );
		
		verts[i].modulate[0] = m_RGB[0] * 255;
		verts[i].modulate[1] = m_RGB[1] * 255;
		verts[i].modulate[2] = m_RGB[2] * 255;
		if ( m_flags & FXF_USE_ALPHA_CHAN )
			verts[i].modulate[3] = (byte)(m_alpha * 255);
		else
			verts[i].modulate[3] = 255;
		
		verts[i].st[0] = quad_st_template[i][0];
		verts[i].st[1] = quad_st_template[i][1];
	}

	cgi_R_AddPolyToScene( m_shader, NUM_QUADVERTS, verts );
}
Пример #20
0
/*
==================
CM_Trace
==================
*/
static void CM_Trace(trace_t *results, const vec3_t start, const vec3_t end,
                     const vec3_t mins, const vec3_t maxs,
                     clipHandle_t model, const vec3_t origin, int brushmask, int capsule, sphere_t *sphere)
{
	int         i;
	traceWork_t tw;
	vec3_t      offset;
	cmodel_t    *cmod;
	qboolean    positionTest;

	cmod = CM_ClipHandleToModel(model);

	cm.checkcount++;        // for multi-check avoidance

	c_traces++;             // for statistics, may be zeroed

	// fill in a default trace
	memset(&tw, 0, sizeof(tw));
	tw.trace.fraction = 1.0f;   // assume it goes the entire distance until shown otherwise
	VectorCopy(origin, tw.modelOrigin);

	if (!cm.numNodes)
	{
		*results = tw.trace;

		return; // map not loaded, shouldn't happen
	}

	// allow NULL to be passed in for 0,0,0
	if (!mins)
	{
		mins = vec3_origin;
	}
	if (!maxs)
	{
		maxs = vec3_origin;
	}

	// set basic parms
	tw.contents = brushmask;

	// adjust so that mins and maxs are always symetric, which
	// avoids some complications with plane expanding of rotated
	// bmodels
	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]   = start[i] + offset[i];
		tw.end[i]     = end[i] + offset[i];
	}

	// if a sphere is already specified
	if (sphere)
	{
		tw.sphere = *sphere;
	}
	else
	{
		tw.sphere.use        = 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);
	}

	positionTest = (start[0] == end[0] && start[1] == end[1] && start[2] == end[2]);

	tw.maxOffset = tw.size[1][0] + tw.size[1][1] + tw.size[1][2];

	// tw.offsets[signbits] = vector to apropriate corner from origin
	tw.offsets[0][0] = tw.size[0][0];
	tw.offsets[0][1] = tw.size[0][1];
	tw.offsets[0][2] = tw.size[0][2];

	tw.offsets[1][0] = tw.size[1][0];
	tw.offsets[1][1] = tw.size[0][1];
	tw.offsets[1][2] = tw.size[0][2];

	tw.offsets[2][0] = tw.size[0][0];
	tw.offsets[2][1] = tw.size[1][1];
	tw.offsets[2][2] = tw.size[0][2];

	tw.offsets[3][0] = tw.size[1][0];
	tw.offsets[3][1] = tw.size[1][1];
	tw.offsets[3][2] = tw.size[0][2];

	tw.offsets[4][0] = tw.size[0][0];
	tw.offsets[4][1] = tw.size[0][1];
	tw.offsets[4][2] = tw.size[1][2];

	tw.offsets[5][0] = tw.size[1][0];
	tw.offsets[5][1] = tw.size[0][1];
	tw.offsets[5][2] = tw.size[1][2];

	tw.offsets[6][0] = tw.size[0][0];
	tw.offsets[6][1] = tw.size[1][1];
	tw.offsets[6][2] = tw.size[1][2];

	tw.offsets[7][0] = tw.size[1][0];
	tw.offsets[7][1] = tw.size[1][1];
	tw.offsets[7][2] = tw.size[1][2];

	// check for point special case
	if (tw.size[0][0] == 0.0f && tw.size[0][1] == 0.0f && tw.size[0][2] == 0.0f)
	{
		tw.isPoint = qtrue;
		VectorClear(tw.extents);
	}
	else
	{
		tw.isPoint    = qfalse;
		tw.extents[0] = tw.size[1][0];
		tw.extents[1] = tw.size[1][1];
		tw.extents[2] = tw.size[1][2];
	}

	if (positionTest)
	{
		CM_CalcTraceBounds(&tw, qfalse);
	}
	else
	{
		vec3_t dir;

		VectorSubtract(tw.end, tw.start, dir);
		VectorCopy(dir, tw.dir);
		VectorNormalize(dir);
		MakeNormalVectors(dir, tw.tracePlane1.normal, tw.tracePlane2.normal);
		tw.tracePlane1.dist = DotProduct(tw.tracePlane1.normal, tw.start);
		tw.tracePlane2.dist = DotProduct(tw.tracePlane2.normal, tw.start);
		if (tw.isPoint)
		{
			tw.traceDist1 = tw.traceDist2 = 1.0f;
		}
		else
		{
			float dist;

			tw.traceDist1 = tw.traceDist2 = 0.0f;
			for (i = 0; i < 8; i++)
			{
				dist = Q_fabs(DotProduct(tw.tracePlane1.normal, tw.offsets[i]) - tw.tracePlane1.dist);
				if (dist > tw.traceDist1)
				{
					tw.traceDist1 = dist;
				}
				dist = Q_fabs(DotProduct(tw.tracePlane2.normal, tw.offsets[i]) - tw.tracePlane2.dist);
				if (dist > tw.traceDist2)
				{
					tw.traceDist2 = dist;
				}
			}
			// expand for epsilon
			tw.traceDist1 += 1.0f;
			tw.traceDist2 += 1.0f;
		}

		CM_CalcTraceBounds(&tw, qtrue);
	}

	// check for position test special case
	if (positionTest)
	{
		if (model)
		{
#ifdef ALWAYS_BBOX_VS_BBOX
			if (model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE)
			{
				tw.sphere.use = qfalse;
				CM_TestInLeaf(&tw, &cmod->leaf);
			}
			else
#elif defined(ALWAYS_CAPSULE_VS_CAPSULE)
			if (model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE)
			{
				CM_TestCapsuleInCapsule(&tw, model);
			}
			else
#else // this is dead code when ALWAYS_BBOX_VS_BBOX or ALWAYS_CAPSULE_VS_CAPSULE are active
			if (model == CAPSULE_MODEL_HANDLE)
			{
				if (tw.sphere.use)
				{
					CM_TestCapsuleInCapsule(&tw, model);
				}
				else
				{
					CM_TestBoundingBoxInCapsule(&tw, model);
				}
			}
			else
#endif
			{
				CM_TestInLeaf(&tw, &cmod->leaf);
			}
		}
		else
		{
			CM_PositionTest(&tw);
		}
	}
	else
	{
		// general sweeping through world
		if (model)
		{
#ifdef ALWAYS_BBOX_VS_BBOX
			if (model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE)
			{
				tw.sphere.use = qfalse;
				CM_TraceThroughLeaf(&tw, &cmod->leaf);
			}
			else
#elif defined(ALWAYS_CAPSULE_VS_CAPSULE)
			if (model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE)
			{
				CM_TraceCapsuleThroughCapsule(&tw, model);
			}
			else
#else // this is dead code when ALWAYS_BBOX_VS_BBOX or ALWAYS_CAPSULE_VS_CAPSULE are active
			if (model == CAPSULE_MODEL_HANDLE)
			{
				if (tw.sphere.use)
				{
					CM_TraceCapsuleThroughCapsule(&tw, model);
				}
				else
				{
					CM_TraceBoundingBoxThroughCapsule(&tw, model);
				}
			}
			else
#endif
			{
				CM_TraceThroughLeaf(&tw, &cmod->leaf);
			}
		}
		else
		{
			CM_TraceThroughTree(&tw, 0, 0, 1, tw.start, tw.end);
		}
	}

	// generate endpos from the original, unmodified start/end
	if (tw.trace.fraction == 1)
	{
		VectorCopy(end, tw.trace.endpos);
	}
	else
	{
		for (i = 0 ; i < 3 ; i++)
		{
			tw.trace.endpos[i] = start[i] + tw.trace.fraction * (end[i] - start[i]);
		}
	}

	*results = tw.trace;
}
Пример #21
0
/*
====================
AddEdge
====================
*/
int AddEdge( vec3_t v1, vec3_t v2, qboolean createNonAxial ) {
	int			i;
	edgeLine_t	*e;
	float		d;
	vec3_t		dir;

	VectorSubtract( v2, v1, dir );
	d = VectorNormalize( dir, dir );
	if ( d < 0.1 ) {
		// if we added a 0 length vector, it would make degenerate planes
		c_degenerateEdges++;
		return -1;
	}

	if ( !createNonAxial ) {
		if ( fabs( dir[0] + dir[1] + dir[2] ) != 1.0 ) {
			if ( numOriginalEdges == MAX_ORIGINAL_EDGES ) {
				Error( "MAX_ORIGINAL_EDGES" );
			}
			originalEdges[ numOriginalEdges ].dv[0] = (bspDrawVert_t *)v1;
			originalEdges[ numOriginalEdges ].dv[1] = (bspDrawVert_t *)v2;
			originalEdges[ numOriginalEdges ].length = d;
			numOriginalEdges++;
			return -1;
		}
	}

	for ( i = 0 ; i < numEdgeLines ; i++ ) {
		e = &edgeLines[i];

		d = DotProduct( v1, e->normal1 ) - e->dist1;
		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
			continue;
		}
		d = DotProduct( v1, e->normal2 ) - e->dist2;
		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
			continue;
		}

		d = DotProduct( v2, e->normal1 ) - e->dist1;
		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
			continue;
		}
		d = DotProduct( v2, e->normal2 ) - e->dist2;
		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
			continue;
		}

		// this is the edge
		InsertPointOnEdge( v1, e );
		InsertPointOnEdge( v2, e );
		return i;
	}

	// create a new edge
	if ( numEdgeLines >= MAX_EDGE_LINES ) {
		Error( "MAX_EDGE_LINES" );
	}

	e = &edgeLines[ numEdgeLines ];
	numEdgeLines++;

	e->chain.next = e->chain.prev = &e->chain;

	VectorCopy( v1, e->origin );
	VectorCopy( dir, e->dir );

	MakeNormalVectors( e->dir, e->normal1, e->normal2 );
	e->dist1 = DotProduct( e->origin, e->normal1 );
	e->dist2 = DotProduct( e->origin, e->normal2 );

	InsertPointOnEdge( v1, e );
	InsertPointOnEdge( v2, e );

	return numEdgeLines - 1;
}
Пример #22
0
/*
   ====================
   AddEdge
   ====================
 */
int AddEdge( vec3_t v1, vec3_t v2, qboolean createNonAxial ) {
	int i;
	edgeLine_t  *e;
	float d;
	vec3_t dir;

	VectorSubtract( v2, v1, dir );
	d = VectorNormalize( dir, dir );
	if ( d < 0.1 ) {
		// if we added a 0 length vector, it would make degenerate planes
		c_degenerateEdges++;
		return -1;
	}

	if ( !createNonAxial ) {
		if ( fabs( dir[0] + dir[1] + dir[2] ) != 1.0 ) {
			AUTOEXPAND_BY_REALLOC( originalEdges, numOriginalEdges, allocatedOriginalEdges, 1024 );
			originalEdges[ numOriginalEdges ].dv[0] = (bspDrawVert_t *)v1;
			originalEdges[ numOriginalEdges ].dv[1] = (bspDrawVert_t *)v2;
			originalEdges[ numOriginalEdges ].length = d;
			numOriginalEdges++;
			return -1;
		}
	}

	for ( i = 0 ; i < numEdgeLines ; i++ ) {
		e = &edgeLines[i];

		d = DotProduct( v1, e->normal1 ) - e->dist1;
		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
			continue;
		}
		d = DotProduct( v1, e->normal2 ) - e->dist2;
		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
			continue;
		}

		d = DotProduct( v2, e->normal1 ) - e->dist1;
		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
			continue;
		}
		d = DotProduct( v2, e->normal2 ) - e->dist2;
		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
			continue;
		}

		// this is the edge
		InsertPointOnEdge( v1, e );
		InsertPointOnEdge( v2, e );
		return i;
	}

	// create a new edge
	AUTOEXPAND_BY_REALLOC( edgeLines, numEdgeLines, allocatedEdgeLines, 1024 );

	e = &edgeLines[ numEdgeLines ];
	numEdgeLines++;

	e->chain = safe_malloc( sizeof( edgePoint_t ) );
	e->chain->next = e->chain->prev = e->chain;

	VectorCopy( v1, e->origin );
	VectorCopy( dir, e->dir );

	MakeNormalVectors( e->dir, e->normal1, e->normal2 );
	e->dist1 = DotProduct( e->origin, e->normal1 );
	e->dist2 = DotProduct( e->origin, e->normal2 );

	InsertPointOnEdge( v1, e );
	InsertPointOnEdge( v2, e );

	return numEdgeLines - 1;
}
Пример #23
0
void QClipMap46::Trace( q3trace_t* results, const vec3_t start, const vec3_t end,
	const vec3_t mins, const vec3_t maxs, clipHandle_t model, const vec3_t origin,
	int brushmask, int capsule, sphere_t* sphere ) {
	int i;
	traceWork_t tw;
	vec3_t offset;
	cmodel_t* cmod;

	cmod = ClipHandleToModel( model );

	checkcount++;		// for multi-check avoidance

	c_traces++;				// for statistics, may be zeroed

	// fill in a default trace
	Com_Memset( &tw, 0, sizeof ( tw ) );
	tw.trace.fraction = 1;	// assume it goes the entire distance until shown otherwise
	VectorCopy( origin, tw.modelOrigin );

	if ( !numNodes ) {
		*results = tw.trace;

		return;	// map not loaded, shouldn't happen
	}

	// allow NULL to be passed in for 0,0,0
	if ( !mins ) {
		mins = oldvec3_origin;
	}
	if ( !maxs ) {
		maxs = oldvec3_origin;
	}

	// set basic parms
	tw.contents = brushmask;

	// adjust so that mins and maxs are always symetric, which
	// avoids some complications with plane expanding of rotated
	// bmodels
	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 ] = start[ i ] + offset[ i ];
		tw.end[ i ] = end[ i ] + offset[ i ];
	}

	// if a sphere is already specified
	if ( sphere ) {
		tw.sphere = *sphere;
	} else {
		tw.sphere.use = 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 );
	}

	bool positionTest = start[ 0 ] == end[ 0 ] && start[ 1 ] == end[ 1 ] && start[ 2 ] == end[ 2 ];

	tw.maxOffset = tw.size[ 1 ][ 0 ] + tw.size[ 1 ][ 1 ] + tw.size[ 1 ][ 2 ];

	// tw.offsets[signbits] = vector to apropriate corner from origin
	tw.offsets[ 0 ][ 0 ] = tw.size[ 0 ][ 0 ];
	tw.offsets[ 0 ][ 1 ] = tw.size[ 0 ][ 1 ];
	tw.offsets[ 0 ][ 2 ] = tw.size[ 0 ][ 2 ];

	tw.offsets[ 1 ][ 0 ] = tw.size[ 1 ][ 0 ];
	tw.offsets[ 1 ][ 1 ] = tw.size[ 0 ][ 1 ];
	tw.offsets[ 1 ][ 2 ] = tw.size[ 0 ][ 2 ];

	tw.offsets[ 2 ][ 0 ] = tw.size[ 0 ][ 0 ];
	tw.offsets[ 2 ][ 1 ] = tw.size[ 1 ][ 1 ];
	tw.offsets[ 2 ][ 2 ] = tw.size[ 0 ][ 2 ];

	tw.offsets[ 3 ][ 0 ] = tw.size[ 1 ][ 0 ];
	tw.offsets[ 3 ][ 1 ] = tw.size[ 1 ][ 1 ];
	tw.offsets[ 3 ][ 2 ] = tw.size[ 0 ][ 2 ];

	tw.offsets[ 4 ][ 0 ] = tw.size[ 0 ][ 0 ];
	tw.offsets[ 4 ][ 1 ] = tw.size[ 0 ][ 1 ];
	tw.offsets[ 4 ][ 2 ] = tw.size[ 1 ][ 2 ];

	tw.offsets[ 5 ][ 0 ] = tw.size[ 1 ][ 0 ];
	tw.offsets[ 5 ][ 1 ] = tw.size[ 0 ][ 1 ];
	tw.offsets[ 5 ][ 2 ] = tw.size[ 1 ][ 2 ];

	tw.offsets[ 6 ][ 0 ] = tw.size[ 0 ][ 0 ];
	tw.offsets[ 6 ][ 1 ] = tw.size[ 1 ][ 1 ];
	tw.offsets[ 6 ][ 2 ] = tw.size[ 1 ][ 2 ];

	tw.offsets[ 7 ][ 0 ] = tw.size[ 1 ][ 0 ];
	tw.offsets[ 7 ][ 1 ] = tw.size[ 1 ][ 1 ];
	tw.offsets[ 7 ][ 2 ] = tw.size[ 1 ][ 2 ];

	//
	// check for point special case
	//
	if ( tw.size[ 0 ][ 0 ] == 0 && tw.size[ 0 ][ 1 ] == 0 && tw.size[ 0 ][ 2 ] == 0 ) {
		tw.isPoint = true;
		VectorClear( tw.extents );
	} else {
		tw.isPoint = false;
		tw.extents[ 0 ] = tw.size[ 1 ][ 0 ];
		tw.extents[ 1 ] = tw.size[ 1 ][ 1 ];
		tw.extents[ 2 ] = tw.size[ 1 ][ 2 ];
	}

	if ( GGameType & GAME_ET ) {
		if ( positionTest ) {
			CalcTraceBounds( &tw, false );
		} else {
			vec3_t dir;
			VectorSubtract( tw.end, tw.start, dir );
			VectorCopy( dir, tw.dir );
			VectorNormalize( dir );
			MakeNormalVectors( dir, tw.tracePlane1.normal, tw.tracePlane2.normal );
			tw.tracePlane1.dist = DotProduct( tw.tracePlane1.normal, tw.start );
			tw.tracePlane2.dist = DotProduct( tw.tracePlane2.normal, tw.start );
			if ( tw.isPoint ) {
				tw.traceDist1 = tw.traceDist2 = 1.0f;
			} else {
				tw.traceDist1 = tw.traceDist2 = 0.0f;
				for ( i = 0; i < 8; i++ ) {
					float dist = idMath::Fabs( DotProduct( tw.tracePlane1.normal, tw.offsets[ i ] ) - tw.tracePlane1.dist );
					if ( dist > tw.traceDist1 ) {
						tw.traceDist1 = dist;
					}
					dist = idMath::Fabs( DotProduct( tw.tracePlane2.normal, tw.offsets[ i ] ) - tw.tracePlane2.dist );
					if ( dist > tw.traceDist2 ) {
						tw.traceDist2 = dist;
					}
				}
				// expand for epsilon
				tw.traceDist1 += 1.0f;
				tw.traceDist2 += 1.0f;
			}

			CalcTraceBounds( &tw, true );
		}
	} else {
		//
		// calculate bounds
		//
		if ( tw.sphere.use ) {
			for ( i = 0; i < 3; i++ ) {
				if ( tw.start[ i ] < tw.end[ i ] ) {
					tw.bounds[ 0 ][ i ] = tw.start[ i ] - idMath::Fabs( tw.sphere.offset[ i ] ) - tw.sphere.radius;
					tw.bounds[ 1 ][ i ] = tw.end[ i ] + idMath::Fabs( tw.sphere.offset[ i ] ) + tw.sphere.radius;
				} else {
					tw.bounds[ 0 ][ i ] = tw.end[ i ] - idMath::Fabs( tw.sphere.offset[ i ] ) - tw.sphere.radius;
					tw.bounds[ 1 ][ i ] = tw.start[ i ] + idMath::Fabs( tw.sphere.offset[ i ] ) + tw.sphere.radius;
				}
			}
		} else {
			for ( i = 0; i < 3; 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 ];
				}
			}
		}
	}

	//
	// check for position test special case
	//
	if ( positionTest ) {
		if ( model ) {
			if ( GGameType & ( GAME_WolfSP | GAME_ET ) ) {
				//	Always box vs. box.
				if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE ) {
					tw.sphere.use = false;
				}
				TestInLeaf( &tw, &cmod->leaf );
			} else {
#ifdef ALWAYS_BBOX_VS_BBOX	// bk010201 - FIXME - compile time flag?
				if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE ) {
					tw.sphere.use = false;
					TestInLeaf( &tw, &cmod->leaf );
				} else
#elif defined( ALWAYS_CAPSULE_VS_CAPSULE )
				if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE ) {
					TestCapsuleInCapsule( &tw, model );
				} else
#endif
				if ( model == CAPSULE_MODEL_HANDLE ) {
					if ( tw.sphere.use ) {
						TestCapsuleInCapsule( &tw, model );
					} else {
						TestBoundingBoxInCapsule( &tw, model );
					}
				} else {
					TestInLeaf( &tw, &cmod->leaf );
				}
			}
		} else {
			PositionTest( &tw );
		}
	} else {
		//
		// general sweeping through world
		//
		if ( model ) {
			if ( GGameType & ( GAME_WolfSP | GAME_ET ) ) {
				//	Always box vs. box.
				if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE ) {
					tw.sphere.use = false;
				}
				TraceThroughLeaf( &tw, &cmod->leaf );
			} else {
#ifdef ALWAYS_BBOX_VS_BBOX
				if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE ) {
					tw.sphere.use = false;
					TraceThroughLeaf( &tw, &cmod->leaf );
				} else
#elif defined( ALWAYS_CAPSULE_VS_CAPSULE )
				if ( model == BOX_MODEL_HANDLE || model == CAPSULE_MODEL_HANDLE ) {
					TraceCapsuleThroughCapsule( &tw, model );
				} else
#endif
				if ( model == CAPSULE_MODEL_HANDLE ) {
					if ( tw.sphere.use ) {
						TraceCapsuleThroughCapsule( &tw, model );
					} else {
						TraceBoundingBoxThroughCapsule( &tw, model );
					}
				} else {
					TraceThroughLeaf( &tw, &cmod->leaf );
				}
			}
		} else {
			TraceThroughTree( &tw, 0, 0, 1, tw.start, tw.end );
		}
	}

	// generate endpos from the original, unmodified start/end
	if ( tw.trace.fraction == 1 ) {
		VectorCopy( end, tw.trace.endpos );
	} else {
		for ( i = 0; i < 3; i++ ) {
			tw.trace.endpos[ i ] = start[ i ] + tw.trace.fraction * ( end[ i ] - start[ i ] );
		}
	}

	// If allsolid is set (was entirely inside something solid), the plane is not valid.
	// If fraction == 1.0, we never hit anything, and thus the plane is not valid.
	// Otherwise, the normal on the plane should have unit length
	assert( tw.trace.allsolid ||
		tw.trace.fraction == 1.0 ||
		VectorLengthSquared( tw.trace.plane.normal ) > 0.9999 );
	*results = tw.trace;
}
Пример #24
0
/*
===============
CL_RailTrail

===============
*/
void CL_RailTrail (const vec3_t start, const vec3_t end)
{
	vec3_t		move, vec, right, up, dir;
	float		len, dec, c, s;
	cparticle_t	*p;
	int			i;
	byte		clr = 0x74;
	cdlight_t *dl;

	VectorCopy (start, move);
	VectorSubtract (end, start, vec);
	len = VectorNormalize (vec);

	// add a light at the dest
	dl = CL_AllocDlight(0);
	VectorCopy(end, dl->origin);
	dl->radius = 100;
	dl->die = cl.time + 200;
	VectorSet(dl->color, 0.3, 0.5, 1.0);

	MakeNormalVectors (vec, right, up);

	for (i=0 ; i<len ; i++)
	{

		if(i % 3 == 0){
			VectorAdd(move, vec, move);
			continue;
		}

		if (!free_particles)
			return;

		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;
		
		p->time = cl.time;
		VectorClear (p->accel);

		Q_sincos(i * 0.1f, &s, &c);

		VectorScale (right, c, dir);
		VectorMA (dir, s, up, dir);

		p->alpha = 1.0f;
		p->alphavel = -1.0f / (1.0f+frand()*0.2f);
		p->color = clr + (rand()&7);

		p->org[0] = move[0] + dir[0]*3;
		p->org[1] = move[1] + dir[1]*3;
		p->org[2] = move[2] + dir[2]*3;
		p->vel[0] = dir[0]*6;
		p->vel[1] = dir[1]*6;
		p->vel[2] = dir[2]*6;

		VectorAdd (move, vec, move);
	}

	dec = 2.0f;
	VectorScale (vec, dec, vec);
	VectorCopy (start, move);

	while (len > 0)
	{
		len -= dec;

		if (!free_particles)
			return;
		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
		VectorClear (p->accel);

		p->alpha = 1.0f;
		p->alphavel = -1.0f / (0.6f+frand()*0.2f);
		p->color = 0x0 + (rand()&15);

		p->org[0] = move[0] + crand()*3;
		p->org[1] = move[1] + crand()*3;
		p->org[2] = move[2] + crand()*3;
		p->vel[0] = crand()*3;
		p->vel[1] = crand()*3;
		p->vel[2] = crand()*3;

		VectorAdd (move, vec, move);
	}
}
Пример #25
0
//---------------------------------------------------------
void FireWeapon( gentity_t *ent, qboolean alt_fire ) 
//---------------------------------------------------------
{
	float alert = 256;
	Vehicle_t *pVeh = NULL;

	// track shots taken for accuracy tracking. 
	ent->client->ps.persistant[PERS_ACCURACY_SHOTS]++;

	// If this is a vehicle, fire it's weapon and we're done.
	if ( ent && ent->client && ent->client->NPC_class == CLASS_VEHICLE )
	{
		FireVehicleWeapon( ent, alt_fire );
		return;
	}

	// set aiming directions
	if ( ent->s.weapon == WP_DISRUPTOR && alt_fire )
	{
		if ( ent->NPC )
		{
			//snipers must use the angles they actually did their shot trace with
			AngleVectors( ent->lastAngles, forwardVec, vrightVec, up );
		}
	}
	else if ( ent->s.weapon == WP_ATST_SIDE || ent->s.weapon == WP_ATST_MAIN ) 
	{
		vec3_t	delta1, enemy_org1, muzzle1;
		vec3_t	angleToEnemy1;

		VectorCopy( ent->client->renderInfo.muzzlePoint, muzzle1 );

		if ( !ent->s.number )
		{//player driving an AT-ST
			//SIGH... because we can't anticipate alt-fire, must calc muzzle here and now
			mdxaBone_t		boltMatrix;
			int				bolt;

			if ( ent->client->ps.weapon == WP_ATST_MAIN )
			{//FIXME: alt_fire should fire both barrels, but slower?
				if ( ent->alt_fire )
				{
					bolt = ent->handRBolt;
				}
				else
				{
					bolt = ent->handLBolt;
				}
			}
			else
			{// ATST SIDE weapons
				if ( ent->alt_fire )
				{
					if ( gi.G2API_GetSurfaceRenderStatus( &ent->ghoul2[ent->playerModel], "head_light_blaster_cann" ) )
					{//don't have it!
						return;
					}
					bolt = ent->genericBolt2;
				}
				else
				{
					if ( gi.G2API_GetSurfaceRenderStatus( &ent->ghoul2[ent->playerModel], "head_concussion_charger" ) )
					{//don't have it!
						return;
					}
					bolt = ent->genericBolt1;
				}
			}

			vec3_t yawOnlyAngles = {0, ent->currentAngles[YAW], 0};
			if ( ent->currentAngles[YAW] != ent->client->ps.legsYaw )
			{
				yawOnlyAngles[YAW] = ent->client->ps.legsYaw;
			}
			gi.G2API_GetBoltMatrix( ent->ghoul2, ent->playerModel, bolt, &boltMatrix, yawOnlyAngles, ent->currentOrigin, (cg.time?cg.time:level.time), NULL, ent->s.modelScale );

			// work the matrix axis stuff into the original axis and origins used.
			gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, ent->client->renderInfo.muzzlePoint );
			gi.G2API_GiveMeVectorFromMatrix( boltMatrix, NEGATIVE_Y, ent->client->renderInfo.muzzleDir );
			ent->client->renderInfo.mPCalcTime = level.time;

			AngleVectors( ent->client->ps.viewangles, forwardVec, vrightVec, up );
			//CalcMuzzlePoint( ent, forwardVec, vrightVec, up, muzzle, 0 );
		}
		else if ( !ent->enemy )
		{//an NPC with no enemy to auto-aim at
			VectorCopy( ent->client->renderInfo.muzzleDir, forwardVec );
		}
		else
		{//NPC, auto-aim at enemy
			CalcEntitySpot( ent->enemy, SPOT_HEAD, enemy_org1 );
			
			VectorSubtract (enemy_org1, muzzle1, delta1);

			vectoangles ( delta1, angleToEnemy1 );
			AngleVectors (angleToEnemy1, forwardVec, vrightVec, up);
		}
	} 
	else if ( ent->s.weapon == WP_BOT_LASER && ent->enemy ) 
	{
		vec3_t	delta1, enemy_org1, muzzle1;
		vec3_t	angleToEnemy1;

		CalcEntitySpot( ent->enemy, SPOT_HEAD, enemy_org1 );
		CalcEntitySpot( ent, SPOT_WEAPON, muzzle1 );
		
		VectorSubtract (enemy_org1, muzzle1, delta1);

		vectoangles ( delta1, angleToEnemy1 );
		AngleVectors (angleToEnemy1, forwardVec, vrightVec, up);
	}
	else 
	{
  		if ( (pVeh = G_IsRidingVehicle( ent )) != NULL) //riding a vehicle
		{//use our muzzleDir, can't use viewangles or vehicle m_vOrientation because we may be animated to shoot left or right...
			if ((ent->s.eFlags&EF_NODRAW))//we're inside it
			{
				vec3_t	aimAngles;
				VectorCopy( ent->client->renderInfo.muzzleDir, forwardVec );
				vectoangles( forwardVec, aimAngles );
				//we're only keeping the yaw
				aimAngles[PITCH] = ent->client->ps.viewangles[PITCH];
				aimAngles[ROLL] = 0;
				AngleVectors( aimAngles, forwardVec, vrightVec, up );
			}
			else
			{
				vec3_t	actorRight;
				vec3_t	actorFwd;

				VectorCopy( ent->client->renderInfo.muzzlePoint, muzzle );
				AngleVectors(ent->currentAngles, actorFwd, actorRight, 0);
 
				// Aiming Left
				//-------------
				if (ent->client->ps.torsoAnim==BOTH_VT_ATL_G || ent->client->ps.torsoAnim==BOTH_VS_ATL_G)
				{
 					VectorScale(actorRight, -1.0f, forwardVec);
				}

				// Aiming Right
				//--------------
				else if (ent->client->ps.torsoAnim==BOTH_VT_ATR_G || ent->client->ps.torsoAnim==BOTH_VS_ATR_G)
				{
 					VectorCopy(actorRight, forwardVec);
				}

				// Aiming Forward
				//----------------
				else
				{
	 				VectorCopy(actorFwd, forwardVec);
				}

				// If We Have An Enemy, Fudge The Aim To Hit The Enemy
				if (ent->enemy)
				{
					vec3_t	toEnemy;
					VectorSubtract(ent->enemy->currentOrigin, ent->currentOrigin, toEnemy);
					VectorNormalize(toEnemy);
					if (DotProduct(toEnemy, forwardVec)>0.75f && 
						((ent->s.number==0 && !Q_irand(0,2)) ||		// the player has a 1 in 3 chance
						 (ent->s.number!=0 && !Q_irand(0,5))))		// other guys have a 1 in 6 chance
					{
						VectorCopy(toEnemy, forwardVec);
					}
					else
					{
						forwardVec[0] += Q_flrand(-0.1f, 0.1f);
						forwardVec[1] += Q_flrand(-0.1f, 0.1f);
						forwardVec[2] += Q_flrand(-0.1f, 0.1f);
					}
				}
			}
		}
		else
		{
			AngleVectors( ent->client->ps.viewangles, forwardVec, vrightVec, up );
		}
	}

	ent->alt_fire = alt_fire;
	if (!pVeh)
	{
		if (ent->NPC && (ent->NPC->scriptFlags&SCF_FIRE_WEAPON_NO_ANIM))
		{
		 	VectorCopy( ent->client->renderInfo.muzzlePoint, muzzle );
			VectorCopy( ent->client->renderInfo.muzzleDir, forwardVec );
			MakeNormalVectors(forwardVec, vrightVec, up);
		}
		else
		{
			CalcMuzzlePoint ( ent, forwardVec, vrightVec, up, muzzle , 0);
		}
	}

	// fire the specific weapon
	switch( ent->s.weapon ) 
	{
	// Player weapons
	//-----------------
	case WP_SABER:
		return;
		break;

	case WP_BRYAR_PISTOL:
	case WP_BLASTER_PISTOL:
		WP_FireBryarPistol( ent, alt_fire );
		break;

	case WP_BLASTER:
		WP_FireBlaster( ent, alt_fire );
		break;

	case WP_TUSKEN_RIFLE:
		if ( alt_fire )
		{
			WP_FireTuskenRifle( ent );
		}
		else
		{
			WP_Melee( ent );
		}
		break;

	case WP_DISRUPTOR:
		alert = 50; // if you want it to alert enemies, remove this
		WP_FireDisruptor( ent, alt_fire );
		break;

	case WP_BOWCASTER:
		WP_FireBowcaster( ent, alt_fire );
		break;

	case WP_REPEATER:
		WP_FireRepeater( ent, alt_fire );
		break;

	case WP_DEMP2:
		WP_FireDEMP2( ent, alt_fire );
		break;

	case WP_FLECHETTE:
		WP_FireFlechette( ent, alt_fire );
		break;

	case WP_ROCKET_LAUNCHER:
		WP_FireRocket( ent, alt_fire );
		break;

	case WP_CONCUSSION:
		WP_Concussion( ent, alt_fire );
		break;

	case WP_THERMAL:
		WP_FireThermalDetonator( ent, alt_fire );
		break;

	case WP_TRIP_MINE:
		alert = 0; // if you want it to alert enemies, remove this
		WP_PlaceLaserTrap( ent, alt_fire );
		break;

	case WP_DET_PACK:
		alert = 0; // if you want it to alert enemies, remove this
		WP_FireDetPack( ent, alt_fire );
		break;

	case WP_BOT_LASER:
		WP_BotLaser( ent );
		break;

	case WP_EMPLACED_GUN:
		// doesn't care about whether it's alt-fire or not.  We can do an alt-fire if needed
		WP_EmplacedFire( ent );
		break;

	case WP_MELEE:
		alert = 0; // if you want it to alert enemies, remove this
		if ( !alt_fire || !g_debugMelee->integer )
		{
			WP_Melee( ent );
		}
		break;

	case WP_ATST_MAIN:
		WP_ATSTMainFire( ent );
		break;

	case WP_ATST_SIDE:

		// TEMP
		if ( alt_fire )
		{
//			WP_FireRocket( ent, qfalse );
			WP_ATSTSideAltFire(ent);
		}
		else
		{
			// FIXME!
		/*	if ( ent->s.number == 0 
				&& ent->client->NPC_class == CLASS_VEHICLE
				&& vehicleData[((CVehicleNPC *)ent->NPC)->m_iVehicleTypeID].type == VH_FIGHTER )
			{
				WP_ATSTMainFire( ent );
			}
			else*/
			{
				WP_ATSTSideFire(ent);
			}
		}
		break;

	case WP_TIE_FIGHTER:
		// TEMP
		WP_EmplacedFire( ent );
		break;

	case WP_RAPID_FIRE_CONC:
		// TEMP
		if ( alt_fire )
		{
			WP_FireRepeater( ent, alt_fire );	
		}
		else
		{
			WP_EmplacedFire( ent );
		}
		break;

	case WP_STUN_BATON:
		WP_FireStunBaton( ent, alt_fire );
		break;

//	case WP_BLASTER_PISTOL:
	case WP_JAWA:
		WP_FireBryarPistol( ent, qfalse ); // never an alt-fire?
		break;

	case WP_SCEPTER:
		WP_FireScepter( ent, alt_fire );
		break;

	case WP_NOGHRI_STICK:
		if ( !alt_fire )
		{
			WP_FireNoghriStick( ent );
		}
		//else does melee attack/damage/func
		break;

	case WP_TUSKEN_STAFF:
	default:
		return;
		break;
	}

	if ( !ent->s.number )
	{
		if ( ent->s.weapon == WP_FLECHETTE || (ent->s.weapon == WP_BOWCASTER && !alt_fire) )
		{//these can fire multiple shots, count them individually within the firing functions
		}
		else if ( W_AccuracyLoggableWeapon( ent->s.weapon, alt_fire, MOD_UNKNOWN ) )
		{
			ent->client->sess.missionStats.shotsFired++;
		}
	}
	// We should probably just use this as a default behavior, in special cases, just set alert to false.
	if ( ent->s.number == 0 && alert > 0 )
	{
		if ( ent->client->ps.groundEntityNum == ENTITYNUM_WORLD//FIXME: check for sand contents type?
			&& ent->s.weapon != WP_STUN_BATON
			&& ent->s.weapon != WP_MELEE
			&& ent->s.weapon != WP_TUSKEN_STAFF
			&& ent->s.weapon != WP_THERMAL
			&& ent->s.weapon != WP_TRIP_MINE
			&& ent->s.weapon != WP_DET_PACK )
		{//the vibration of the shot carries through your feet into the ground
			AddSoundEvent( ent, muzzle, alert, AEL_DISCOVERED, qfalse, qtrue );
		}
		else
		{//an in-air alert
			AddSoundEvent( ent, muzzle, alert, AEL_DISCOVERED );
		}
		AddSightEvent( ent, muzzle, alert*2, AEL_DISCOVERED, 20 );
	}
}
Пример #26
0
static void objectVec3_MakeNormalVectors( asvec3_t *r, asvec3_t *u, asvec3_t *self )
{
	MakeNormalVectors( self->v, r->v, u->v );
}
Пример #27
0
void FXCylinder::Draw( void )
{
	polyVert_t	lower_points[NUM_CYLINDER_SEGMENTS], upper_points[NUM_CYLINDER_SEGMENTS], verts[4];
	vec3_t		vr, vu, vu2, midpoint, origin2;
	float		detail, length;
	int			i;
	int			segments;

	// allow for overriding the LOD mechanism, not recommended, but hey, flexibility is often cool...
	if ( m_flags & FXF_NO_LOD )
	{
		segments = NUM_CYLINDER_SEGMENTS;
	}
	else
	{
		//Work out the detail level of this cylinder
		VectorMA( m_origin, m_height * 0.5, m_normal, midpoint );
		VectorSubtract( midpoint, cg.refdef.vieworg, midpoint );
		length = VectorLengthSquared( midpoint );

		detail = 1 - (length / (1024.0*1024.0) );

		// FIXME: the bias doesn't really work all that great
		//Cylinder bias is simply implemented as a multiplier
		segments = NUM_CYLINDER_SEGMENTS * detail * m_bias;

		// 3 is the absolute minimum, but the pop between 3, 4 and 5 is too noticeable
		if ( segments < 7 )
		{
			segments = 7;
		}

		if ( segments > NUM_CYLINDER_SEGMENTS )
		{
			segments = NUM_CYLINDER_SEGMENTS;
		}
	}

	//Get the direction vector
	MakeNormalVectors( m_normal, vr, vu );

	VectorScale( vu, m_scale2 * 0.5, vu2 );
	VectorScale( vu, m_scale * 0.5, vu );

	VectorMA( m_origin, m_height, m_normal, origin2 );

	// Calculate the step around the cylinder
	detail = 360.0 / (float)segments;

	for ( i = 0; i < segments ; i++ )
	{
		//Upper ring
		RotatePointAroundVector( upper_points[i].xyz, m_normal, vu, detail * i );
		VectorAdd( upper_points[i].xyz, m_origin, upper_points[i].xyz );
		
		//Lower ring
		RotatePointAroundVector( lower_points[i].xyz, m_normal, vu2, detail * i );
		VectorAdd( lower_points[i].xyz, origin2, lower_points[i].xyz );
	}
	
	// Calculate the texture coords so the texture can wrap around the whole cylinder
	if ( m_flags & FXF_WRAP )
	{
		if ( m_flags & FXF_STRETCH )
			detail = 1.0f / (float)segments;
		else
			detail = m_stScale / (float)segments;
	}

	for ( i = 0; i < segments ; i++ )
	{
		int nextSegment = ( i + 1 == segments ) ? 0 : i + 1;

		if ( m_flags & FXF_WRAP )
		{
			verts[0].st[0] = detail * i;
			verts[1].st[0] = detail * i;
			verts[2].st[0] = detail * ( i + 1 );
			verts[3].st[0] = detail * ( i + 1 );
		}
		else
		{
			verts[0].st[0] = 0.0f;
			verts[1].st[0] = 0.0f;
			verts[2].st[0] = m_stScale;
			verts[3].st[0] = m_stScale;
		}

		if( m_flags & FXF_STRETCH )
		{
			verts[0].st[1] = m_stScale;
			verts[1].st[1] = 0.0f;
			verts[2].st[1] = 0.0f;
			verts[3].st[1] = m_stScale;
		}
		else
		{
			verts[0].st[1] = 1.0f;
			verts[1].st[1] = 0.0f;
			verts[2].st[1] = 0.0f;
			verts[3].st[1] = 1.0f;
		}
			
 		VectorCopy( upper_points[i].xyz, verts[0].xyz );
		
		verts[0].modulate[0] = m_RGB[0] * 255;
		verts[0].modulate[1] = m_RGB[1] * 255;
		verts[0].modulate[2] = m_RGB[2] * 255;

		VectorCopy( lower_points[i].xyz, verts[1].xyz );
		
		verts[1].modulate[0] = m_RGB[0] * 255;
		verts[1].modulate[1] = m_RGB[1] * 255;
		verts[1].modulate[2] = m_RGB[2] * 255;

		VectorCopy( lower_points[nextSegment].xyz, verts[2].xyz );
		
		verts[2].modulate[0] = m_RGB[0] * 255;
		verts[2].modulate[1] = m_RGB[1] * 255;
		verts[2].modulate[2] = m_RGB[2] * 255;

		VectorCopy( upper_points[nextSegment].xyz, verts[3].xyz );
		
		verts[3].modulate[0] = m_RGB[0] * 255;
		verts[3].modulate[1] = m_RGB[1] * 255;
		verts[3].modulate[2] = m_RGB[2] * 255;

		if ( m_flags & FXF_USE_ALPHA_CHAN )
		{
			verts[0].modulate[3] =
			verts[1].modulate[3] =
			verts[2].modulate[3] =
			verts[3].modulate[3] = (byte)(m_alpha * 255);
		}
		else
		{
			verts[0].modulate[3] =
			verts[1].modulate[3] =
			verts[2].modulate[3] =
			verts[3].modulate[3] = 255;
		}

		cgi_R_AddPolyToScene( m_shader, 4, verts );
	}
}
Пример #28
0
/*
===============
CL_RailTrail
===============
*/
void CL_RailTrail (vec3_t start, vec3_t end)
{
	vec3_t		move;
	vec3_t		vec;
	float		len;
	int			j;
	cparticle_t	*p;
	float		dec;
	vec3_t		right, up;
	int			i;
	float		d, c, s;
	vec3_t		dir;
	byte		clr = 0x74;

	VectorCopy (start, move);
	VectorSubtract (end, start, vec);
	len = VectorNormalize (vec);

	MakeNormalVectors (vec, right, up);

	for (i = 0; i < len; i++)
	{
		if (!free_particles)
			return;

		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
		VectorClear (p->accel);

		d = i * 0.1;

		Q_sincos (d, &s, &c);

		VectorScale (right, c, dir);
		VectorMA (dir, s, up, dir);

		p->alpha = 1.0;
		p->alphavel = -1.0 / (1 + frand () * 0.2);
		p->color = clr + (rand () & 7);

		for (j = 0; j < 3; j++)
		{
			p->org[j] = move[j] + dir[j] * 3;
			p->vel[j] = dir[j] * 6;
		}

		VectorAdd (move, vec, move);

		p->bounceFactor = 0.1f;
		p->ignoreGrav = true;
	}

	dec = 0.75;
	VectorScale (vec, dec, vec);
	VectorCopy (start, move);

	while (len > 0)
	{
		len -= dec;

		if (!free_particles)
			return;

		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
		VectorClear (p->accel);

		p->alpha = 1.0;
		p->alphavel = -1.0 / (0.6 + frand () * 0.2);
		p->color = 0x0 + rand () & 15;

		for (j = 0; j < 3; j++)
		{
			p->org[j] = move[j] + crand () * 3;
			p->vel[j] = crand () * 3;
			p->accel[j] = 0;
		}

		VectorAdd (move, vec, move);

		p->bounceFactor = 0.1f;
		p->ignoreGrav = true;
	}
}
Пример #29
0
void CLQ2_RailTrail( vec3_t start, vec3_t end ) {
	byte clr = 0x74;

	vec3_t move;
	VectorCopy( start, move );
	vec3_t vec;
	VectorSubtract( end, start, vec );
	float len = VectorNormalize( vec );

	vec3_t right, up;
	MakeNormalVectors( vec, right, up );

	for ( int i = 0; i < len; i++ ) {
		cparticle_t* p = CL_AllocParticle();
		if ( !p ) {
			return;
		}

		p->type = pt_q2static;

		VectorClear( p->accel );

		float d = i * 0.1;
		float c = cos( d );
		float s = sin( d );

		vec3_t dir;
		VectorScale( right, c, dir );
		VectorMA( dir, s, up, dir );

		p->alpha = 1.0;
		p->alphavel = -1.0 / ( 1 + frand() * 0.2 );
		p->color = clr + ( rand() & 7 );
		for ( int j = 0; j < 3; j++ ) {
			p->org[ j ] = move[ j ] + dir[ j ] * 3;
			p->vel[ j ] = dir[ j ] * 6;
		}

		VectorAdd( move, vec, move );
	}

	float dec = 0.75;
	VectorScale( vec, dec, vec );
	VectorCopy( start, move );

	while ( len > 0 ) {
		len -= dec;

		cparticle_t* p = CL_AllocParticle();
		if ( !p ) {
			return;
		}
		p->type = pt_q2static;

		VectorClear( p->accel );

		p->alpha = 1.0;
		p->alphavel = -1.0 / ( 0.6 + frand() * 0.2 );
		p->color = rand() & 15;

		for ( int j = 0; j < 3; j++ ) {
			p->org[ j ] = move[ j ] + crand() * 3;
			p->vel[ j ] = crand() * 3;
			p->accel[ j ] = 0;
		}

		VectorAdd( move, vec, move );
	}
}
Пример #30
0
/*
======
CL_DebugTrail
======
*/
void CL_DebugTrail (vec3_t start, vec3_t end)
{
	vec3_t		move;
	vec3_t		vec;
	float		len;
#ifndef QMAX
	cparticle_t	*p;
#endif
	float		dec;
	vec3_t		right, up;

	VectorCopy (start, move);
	VectorSubtract (end, start, vec);
	len = VectorNormalize (vec);

	MakeNormalVectors (vec, right, up);

//	VectorScale(vec, RT2_SKIP, vec);

//	dec = 1.0;
//	dec = 0.75;
	dec = 3;
	VectorScale (vec, dec, vec);
	VectorCopy (start, move);

	while (len > 0)
	{
		len -= dec;
#ifdef QMAX
		setupParticle (
			0,	0,	0,
			move[0],	move[1],	move[2],
			0,	0,	0,
			0,		0,		0,
			50,	50,	255,
			0,	0,	0,
			1,		-0.75,
			7.5,			0,			
			particle_generic,
			0,
			NULL,0);
#else
		if (!free_particles)
			return;
		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cl.time;
		VectorClear (p->accel);
		VectorClear (p->vel);
		p->alpha = 1.0;
		p->alphavel = -0.1;
//		p->alphavel = 0;
		p->color = 0x74 + (rand()&7);
		VectorCopy (move, p->org);
		/*
		for (j=0 ; j<3 ; j++)
		{
			p->org[j] = move[j] + crand()*2;
			p->vel[j] = crand()*3;
			p->accel[j] = 0;
		}
		*/
#endif
		VectorAdd (move, vec, move);
	}

}