示例#1
0
/*
=================
R_SetupEntityLightingGrid

=================
*/
static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
	vec3_t			lightOrigin;
	int				pos[3];
	int				i, j;
	float			frac[3];
	int				gridStep[3];
	vec3_t			direction;
	float			totalFactor;
	unsigned short	*startGridPos;

	
	if (r_fullbright->integer || tr.refdef.doFullbright )
	{
		ent->ambientLight[0] = ent->ambientLight[1] = ent->ambientLight[2] = 255.0;
		ent->directedLight[0] = ent->directedLight[1] = ent->directedLight[2] = 255.0;
		VectorCopy( tr.sunDirection, ent->lightDir );
		return;
	}

	if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
		// seperate lightOrigins are needed so an object that is
		// sinking into the ground can still be lit, and so
		// multi-part models can be lit identically
		VectorCopy( ent->e.lightingOrigin, lightOrigin );
	} else {
		VectorCopy( ent->e.origin, lightOrigin );
	}
#define ACCURATE_LIGHTGRID_SAMPLING 1
#if ACCURATE_LIGHTGRID_SAMPLING
	vec3_t	startLightOrigin;
	VectorCopy( lightOrigin, startLightOrigin );
#endif

	VectorSubtract( lightOrigin, tr.world->lightGridOrigin, lightOrigin );
	for ( i = 0 ; i < 3 ; i++ ) {
		float	v;

		v = lightOrigin[i]*tr.world->lightGridInverseSize[i];
		pos[i] = floor( v );
		frac[i] = v - pos[i];
		if ( pos[i] < 0 ) {
			pos[i] = 0;
		} else if ( pos[i] >= tr.world->lightGridBounds[i] - 1 ) {
			pos[i] = tr.world->lightGridBounds[i] - 1;
		}
	}

	VectorClear( ent->ambientLight );
	VectorClear( ent->directedLight );
	VectorClear( direction );

	// trilerp the light value
	gridStep[0] = 1;
	gridStep[1] = tr.world->lightGridBounds[0];
	gridStep[2] = tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1];
	startGridPos = tr.world->lightGridArray	+ pos[0] * gridStep[0] 
					+ pos[1] * gridStep[1] 	+ pos[2] * gridStep[2];
#if ACCURATE_LIGHTGRID_SAMPLING
	vec3_t	startGridOrg;
	VectorCopy( tr.world->lightGridOrigin, startGridOrg );
	startGridOrg[0] += pos[0] * tr.world->lightGridSize[0];
	startGridOrg[1] += pos[1] * tr.world->lightGridSize[1];
	startGridOrg[2] += pos[2] * tr.world->lightGridSize[2];
#endif
	totalFactor = 0;
	for ( i = 0 ; i < 8 ; i++ ) {
		float			factor;
		mgrid_t			*data;
		unsigned short	*gridPos;
		int				lat, lng;
		vec3_t			normal;
#if ACCURATE_LIGHTGRID_SAMPLING
		vec3_t			gridOrg;
		VectorCopy( startGridOrg, gridOrg );
#endif

		factor = 1.0;
		gridPos = startGridPos;
		for ( j = 0 ; j < 3 ; j++ ) {
			if ( i & (1<<j) ) {
				factor *= frac[j];
				gridPos += gridStep[j];
#if ACCURATE_LIGHTGRID_SAMPLING
				gridOrg[j] += tr.world->lightGridSize[j];
#endif
			} else {
				factor *= (1.0 - frac[j]);
			}
		}

		if (gridPos >= tr.world->lightGridArray + tr.world->numGridArrayElements)
		{//we've gone off the array somehow
			continue;
		}
		data = tr.world->lightGridData + *gridPos;
		if ( data->styles[0] == LS_NONE ) 
		{
			continue;	// ignore samples in walls
		}

#if 0
		if ( !SV_inPVS( startLightOrigin, gridOrg ) )
		{
			continue;
		}
#endif

		totalFactor += factor;

		for(j=0;j<MAXLIGHTMAPS;j++)
		{
			if (data->styles[j] != LS_NONE)
			{
				const byte	style= data->styles[j];

				ent->ambientLight[0] += factor * data->ambientLight[j][0] * styleColors[style][0] / 255.0f;
				ent->ambientLight[1] += factor * data->ambientLight[j][1] * styleColors[style][1] / 255.0f;
				ent->ambientLight[2] += factor * data->ambientLight[j][2] * styleColors[style][2] / 255.0f;

				ent->directedLight[0] += factor * data->directLight[j][0] * styleColors[style][0] / 255.0f;
				ent->directedLight[1] += factor * data->directLight[j][1] * styleColors[style][1] / 255.0f;
				ent->directedLight[2] += factor * data->directLight[j][2] * styleColors[style][2] / 255.0f;
			}
			else
			{
				break;
			}
		}


		lat = data->latLong[1];
		lng = data->latLong[0];
		lat *= (FUNCTABLE_SIZE/256);
		lng *= (FUNCTABLE_SIZE/256);

		// decode X as cos( lat ) * sin( long )
		// decode Y as sin( lat ) * sin( long )
		// decode Z as cos( long )

		normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
		normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
		normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];

		VectorMA( direction, factor, normal, direction );

#if ACCURATE_LIGHTGRID_SAMPLING
		if ( r_debugLight->integer && ent->e.hModel == -1 )
		{
			//draw 	
			refEntity_t refEnt;
			refEnt.hModel = 0;
			refEnt.ghoul2 = NULL;
			refEnt.renderfx = 0;
			VectorCopy( gridOrg, refEnt.origin );
			vectoangles( normal, refEnt.angles );
			AnglesToAxis( refEnt.angles, refEnt.axis );
			refEnt.reType = RT_MODEL;
			RE_AddRefEntityToScene( &refEnt );

			refEnt.renderfx = RF_DEPTHHACK;
			refEnt.reType = RT_SPRITE;
			refEnt.customShader = RE_RegisterShader( "gfx/misc/debugAmbient" );
			refEnt.shaderRGBA[0] = data->ambientLight[0][0];
			refEnt.shaderRGBA[1] = data->ambientLight[0][1];
			refEnt.shaderRGBA[2] = data->ambientLight[0][2];
			refEnt.shaderRGBA[3] = 255;
			refEnt.radius = factor*50+2.0f; // maybe always give it a minimum size?
			refEnt.rotation = 0;			// don't let the sprite wobble around
			RE_AddRefEntityToScene( &refEnt );

			refEnt.reType = RT_LINE;
			refEnt.customShader = RE_RegisterShader( "gfx/misc/debugArrow" );
			refEnt.shaderRGBA[0] = data->directLight[0][0];
			refEnt.shaderRGBA[1] = data->directLight[0][1];
			refEnt.shaderRGBA[2] = data->directLight[0][2];
			refEnt.shaderRGBA[3] = 255;
			VectorCopy( refEnt.origin, refEnt.oldorigin );
			VectorMA( gridOrg, (factor*-255) - 2.0f, normal, refEnt.origin ); // maybe always give it a minimum length
			refEnt.radius = 1.5f;
			RE_AddRefEntityToScene( &refEnt );
		}
#endif
	}

	if ( totalFactor > 0 && totalFactor < 0.99 ) 
	{
		totalFactor = 1.0 / totalFactor;
		VectorScale( ent->ambientLight, totalFactor, ent->ambientLight );
		VectorScale( ent->directedLight, totalFactor, ent->directedLight );
	}

	VectorScale( ent->ambientLight, r_ambientScale->value, ent->ambientLight );
	VectorScale( ent->directedLight, r_directedScale->value, ent->directedLight );

	VectorNormalize2( direction, ent->lightDir );
}
示例#2
0
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;

	if (le->forceAlpha)
	{
		le->refEntity.renderfx |= RF_FORCE_ENT_ALPHA;
		le->refEntity.shaderRGBA[3] = le->forceAlpha;
	}

	if ( le->pos.trType == TR_STATIONARY ) {
		// sink into the ground if near the removal time
		int		t;
		float	t_e;

		t = le->endTime - cg.time;
		if ( t < (SINK_TIME*2) ) {
			le->refEntity.renderfx |= RF_FORCE_ENT_ALPHA;
			t_e = (float)((float)(le->endTime - cg.time)/(SINK_TIME*2));
			t_e = (int)((t_e)*255);

			if (t_e > 255)
			{
				t_e = 255;
			}
			if (t_e < 1)
			{
				t_e = 1;
			}

			if (le->refEntity.shaderRGBA[3] && t_e > le->refEntity.shaderRGBA[3])
			{
				t_e = le->refEntity.shaderRGBA[3];
			}

			le->refEntity.shaderRGBA[3] = t_e;

			trap_R_AddRefEntityToScene( &le->refEntity );
		} else {
			trap_R_AddRefEntityToScene( &le->refEntity );
		}

		return;
	}

	// calculate new position
	BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );

	// trace a line from previous position to new position
	CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
	if ( trace.fraction == 1.0 ) {
		// still in free fall
		VectorCopy( newOrigin, le->refEntity.origin );

		if ( le->leFlags & LEF_TUMBLE ) {
			vec3_t angles;

			BG_EvaluateTrajectory( &le->angles, cg.time, angles );
			AnglesToAxis( angles, le->refEntity.axis );
		}

		trap_R_AddRefEntityToScene( &le->refEntity );

		// add a blood trail
		if ( le->leBounceSoundType == LEBS_BLOOD ) {
			CG_BloodTrail( le );
		}

		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
		CG_FreeLocalEntity( le );
		return;
	}

	if (!trace.startsolid)
	{
		// leave a mark
		CG_FragmentBounceMark( le, &trace );

		// do a bouncy sound
		CG_FragmentBounceSound( le, &trace );

		if (le->bounceSound)
		{ //specified bounce sound (debris)
			trap_S_StartSound(le->pos.trBase, ENTITYNUM_WORLD, CHAN_AUTO, le->bounceSound);
		}

		// reflect the velocity on the trace plane
		CG_ReflectVelocity( le, &trace );

		trap_R_AddRefEntityToScene( &le->refEntity );
	}
}
示例#3
0
/*
====================
CG_AddKamikaze
====================
*/
void CG_AddKamikaze( localEntity_t *le ) {
	refEntity_t	*re;
	refEntity_t shockwave;
	float		c;
	vec3_t		test, axis[3];
	int			t;

	re = &le->refEntity;

	t = cg.time - le->startTime;
	VectorClear( test );
	AnglesToAxis( test, axis );

	if (t > KAMI_SHOCKWAVE_STARTTIME && t < KAMI_SHOCKWAVE_ENDTIME) {

		if (!(le->leFlags & LEF_SOUND1)) {
//			trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeExplodeSound );
			trap_S_StartLocalSound(cgs.media.kamikazeExplodeSound, CHAN_AUTO);
			le->leFlags |= LEF_SOUND1;
		}
		// 1st kamikaze shockwave
		memset(&shockwave, 0, sizeof(shockwave));
		shockwave.hModel = cgs.media.kamikazeShockWave;
		shockwave.reType = RT_MODEL;
		shockwave.shaderTime = re->shaderTime;
		VectorCopy(re->origin, shockwave.origin);

		c = (float)(t - KAMI_SHOCKWAVE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVE_STARTTIME);
		VectorScale( axis[0], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] );
		VectorScale( axis[1], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] );
		VectorScale( axis[2], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] );
		shockwave.nonNormalizedAxes = qtrue;

		if (t > KAMI_SHOCKWAVEFADE_STARTTIME) {
			c = (float)(t - KAMI_SHOCKWAVEFADE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVEFADE_STARTTIME);
		}
		else {
			c = 0;
		}
		c *= 0xff;
		shockwave.shaderRGBA[0] = 0xff - c;
		shockwave.shaderRGBA[1] = 0xff - c;
		shockwave.shaderRGBA[2] = 0xff - c;
		shockwave.shaderRGBA[3] = 0xff - c;

		trap_R_AddRefEntityToScene( &shockwave );
	}

	if (t > KAMI_EXPLODE_STARTTIME && t < KAMI_IMPLODE_ENDTIME) {
		// explosion and implosion
		c = ( le->endTime - cg.time ) * le->lifeRate;
		c *= 0xff;
		re->shaderRGBA[0] = le->color[0] * c;
		re->shaderRGBA[1] = le->color[1] * c;
		re->shaderRGBA[2] = le->color[2] * c;
		re->shaderRGBA[3] = le->color[3] * c;

		if( t < KAMI_IMPLODE_STARTTIME ) {
			c = (float)(t - KAMI_EXPLODE_STARTTIME) / (float)(KAMI_IMPLODE_STARTTIME - KAMI_EXPLODE_STARTTIME);
		}
		else {
			if (!(le->leFlags & LEF_SOUND2)) {
//				trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeImplodeSound );
				trap_S_StartLocalSound(cgs.media.kamikazeImplodeSound, CHAN_AUTO);
				le->leFlags |= LEF_SOUND2;
			}
			c = (float)(KAMI_IMPLODE_ENDTIME - t) / (float) (KAMI_IMPLODE_ENDTIME - KAMI_IMPLODE_STARTTIME);
		}
		VectorScale( axis[0], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[0] );
		VectorScale( axis[1], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[1] );
		VectorScale( axis[2], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[2] );
		re->nonNormalizedAxes = qtrue;

		trap_R_AddRefEntityToScene( re );
		// add the dlight
		trap_R_AddLightToScene( re->origin, c * 1000.0, 1.0, 1.0, c );
	}

	if (t > KAMI_SHOCKWAVE2_STARTTIME && t < KAMI_SHOCKWAVE2_ENDTIME) {
		// 2nd kamikaze shockwave
		if (le->angles.trBase[0] == 0 &&
			le->angles.trBase[1] == 0 &&
			le->angles.trBase[2] == 0) {
			le->angles.trBase[0] = random() * 360;
			le->angles.trBase[1] = random() * 360;
			le->angles.trBase[2] = random() * 360;
		}
		else {
			c = 0;
		}
		memset(&shockwave, 0, sizeof(shockwave));
		shockwave.hModel = cgs.media.kamikazeShockWave;
		shockwave.reType = RT_MODEL;
		shockwave.shaderTime = re->shaderTime;
		VectorCopy(re->origin, shockwave.origin);

		test[0] = le->angles.trBase[0];
		test[1] = le->angles.trBase[1];
		test[2] = le->angles.trBase[2];
		AnglesToAxis( test, axis );

		c = (float)(t - KAMI_SHOCKWAVE2_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2_STARTTIME);
		VectorScale( axis[0], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] );
		VectorScale( axis[1], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] );
		VectorScale( axis[2], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] );
		shockwave.nonNormalizedAxes = qtrue;

		if (t > KAMI_SHOCKWAVE2FADE_STARTTIME) {
			c = (float)(t - KAMI_SHOCKWAVE2FADE_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2FADE_STARTTIME);
		}
		else {
			c = 0;
		}
		c *= 0xff;
		shockwave.shaderRGBA[0] = 0xff - c;
		shockwave.shaderRGBA[1] = 0xff - c;
		shockwave.shaderRGBA[2] = 0xff - c;
		shockwave.shaderRGBA[3] = 0xff - c;

		trap_R_AddRefEntityToScene( &shockwave );
	}
}
示例#4
0
/*
===============
CG_LightningBolt

Origin will be the exact tag point, which is slightly
different than the muzzle point used for determining hits.
The cent should be the non-predicted cent if it is from the player,
so the endpoint will reflect the simulated strike (lagging the predicted
angle)
===============
*/
static void CG_LightningBolt( centity_t *cent, vec3_t origin, int viewHeight ) {
	trace_t  trace;
	refEntity_t  beam;
	vec3_t   forward;
	vec3_t   muzzlePoint, endPoint;
	fxParent_t fxParent;

	if (cent->currentState.weapon != WP_LIGHTNING) {
		return;
	}

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

	// CPMA  "true" lightning
	if (cg.playerCent && (cent->currentState.number == cg.playerCent->currentState.number) && (cg_trueLightning.value != 0)) {
		vec3_t angle;
		int i;

		for (i = 0; i < 3; i++) {
			float a = cent->lerpAngles[i] - cg.refdefViewAngles[i];
			if (a > 180) {
				a -= 360;
			}
			if (a < -180) {
				a += 360;
			}

			angle[i] = cg.refdefViewAngles[i] + a * (1.0 - cg_trueLightning.value);
			if (angle[i] < 0) {
				angle[i] += 360;
			}
			if (angle[i] > 360) {
				angle[i] -= 360;
			}
		}
		AngleVectors(angle, forward, NULL, NULL );
		VectorCopy(cent->lerpOrigin, muzzlePoint );
//		VectorCopy(cg.refdef.vieworg, muzzlePoint );
	} else {
		// !CPMA
		AngleVectors( cent->lerpAngles, forward, NULL, NULL );
		VectorCopy(cent->lerpOrigin, muzzlePoint );
	}

	// FIXME: crouch
	//Cana viewheight fix
//	muzzlePoint[2] += DEFAULT_VIEWHEIGHT;
	muzzlePoint[2] += viewHeight;

	VectorMA( muzzlePoint, 14, forward, muzzlePoint );

	// project forward by the lightning range
	VectorMA( muzzlePoint, LIGHTNING_RANGE, forward, endPoint );

	// see if it hit a wall
	CG_Trace( &trace, muzzlePoint, vec3_origin, vec3_origin, endPoint, 
		cent->currentState.number, MASK_SHOT );
#if 1 
	VectorCopy( origin, fxParent.origin );
	VectorSubtract( trace.endpos, origin, fxParent.dir );
	fxParent.flags = FXP_ORIGIN | FXP_DIR;
	trap_FX_Run( cgs.fx.lightning.trail, &fxParent, cent );
#else
	// this is the endpoint
	VectorCopy( trace.endpos, beam.oldorigin );

	// use the provided origin, even though it may be slightly
	// different than the muzzle origin
	VectorCopy( origin, beam.origin );
	beam.reType = RT_LIGHTNING;
	beam.customShader = cgs.media.lightningShader;
	trap_R_AddRefEntityToScene( &beam );

	// add the impact flare if it hit something
	if ( trace.fraction < 1.0 ) {
		vec3_t	angles;
		vec3_t	dir;

		VectorSubtract( beam.oldorigin, beam.origin, dir );
		VectorNormalize( dir );

		memset( &beam, 0, sizeof( beam ) );
		beam.hModel = cgs.media.lightningExplosionModel;

		VectorMA( trace.endpos, -16, dir, beam.origin );

		// make a random orientation
		angles[0] = rand() % 360;
		angles[1] = rand() % 360;
		angles[2] = rand() % 360;
		AnglesToAxis( angles, beam.axis );
		trap_R_AddRefEntityToScene( &beam );
	}
#endif
}
示例#5
0
/*
* CG_SkeletalPoseGetAttachment
* Get the tag from the interpolated and transformed pose
*/
qboolean CG_SkeletalPoseGetAttachment( orientation_t *orient, cgs_skeleton_t *skel, bonepose_t *boneposes, char *bonename )
{
	int i;
	quat_t quat;
	cgs_bone_t *bone;
	bonepose_t *bonepose;
	cg_tagmask_t *tagmask;

	if( !boneposes || !skel )
	{
		CG_Printf( "CG_SkeletalPoseLerpAttachment: Wrong model or boneposes %s\n", bonename );
		return qfalse;
	}

	tagmask = CG_TagMask( bonename, skel );
	// find the appropriate attachment bone
	if( tagmask )
	{
		bone = skel->bones;
		for( i = 0; i < skel->numBones; i++, bone++ )
		{
			if( !Q_stricmp( bone->name, tagmask->bonename ) )
				break;
		}
	}
	else
	{
		bone = skel->bones;
		for( i = 0; i < skel->numBones; i++, bone++ )
		{
			if( !Q_stricmp( bone->name, bonename ) )
				break;
		}
	}

	if( i == skel->numBones )
	{
		CG_Printf( "CG_SkeletalPoseLerpAttachment: no such bone %s\n", bonename );
		return qfalse;
	}

	// get the desired bone
	bonepose = boneposes + i;

	// copy the inverted bone into the tag
	Quat_Inverse( &bonepose->dualquat[0], quat ); // inverse the tag direction
	Quat_Matrix( quat, orient->axis );
	DualQuat_GetVector( bonepose->dualquat, orient->origin );

	// normalize each axis
	for( i = 0; i < 3; i++ )
		VectorNormalizeFast( orient->axis[i] );

	// do the offseting if having a tagmask
	if( tagmask )
	{
		// we want to place a rotated model over this tag, not to rotate the tag, 
		// because all rotations would move. So we create a new orientation for the
		// model and we position the new orientation in tag space
		if( tagmask->rotate[YAW] || tagmask->rotate[PITCH] || tagmask->rotate[ROLL] )
		{
			orientation_t modOrient, newOrient;

			VectorCopy( tagmask->offset, modOrient.origin );
			AnglesToAxis( tagmask->rotate, modOrient.axis );

			VectorCopy( vec3_origin, newOrient.origin );
			Matrix_Identity( newOrient.axis );

			CG_MoveToTag( newOrient.origin, newOrient.axis,
				orient->origin, orient->axis,
				modOrient.origin, modOrient.axis
				 );

			Matrix_Copy( newOrient.axis, orient->axis );
			VectorCopy( newOrient.origin, orient->origin );
		}
		else
		{
			// offset
			for( i = 0; i < 3; i++ )
			{
				if( tagmask->offset[i] )
					VectorMA( orient->origin, tagmask->offset[i], orient->axis[i], orient->origin );
			}
		}
	}

	return qtrue;
}
示例#6
0
/*
===============
Main_MenuDraw
===============
*/
static void Main_MenuDraw( void ) {
	refdef_t		refdef;
	refEntity_t		ent;
	vec3_t			origin;
	vec3_t			angles;
	float			adjust;
	float			x, y, w, h;
	vec4_t			color = {0.5, 0, 0, 1};

	// setup the refdef

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

	refdef.rdflags = RDF_NOWORLDMODEL;

	AxisClear( refdef.viewaxis );

	x = 0;
	y = 0;
	w = 640;
	h = 120;
	UI_AdjustFrom640( &x, &y, &w, &h );
	refdef.x = x;
	refdef.y = y;
	refdef.width = w;
	refdef.height = h;

	
	adjust = 0; // JDC: Kenneth asked me to stop this  1.0 * sin( (float)uis.realtime / 1000 );
	refdef.fov_x = 70 + adjust;
	refdef.fov_y = 19.6875 + adjust;

	refdef.time = uis.realtime;

	origin[0] = 300;
	origin[1] = 0;
	origin[2] = -32;

	trap_R_ClearScene();

	// add the model

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

	adjust = 20.0 * sin( (float)uis.realtime / 3000 );
	VectorSet( angles, 0, 180 + adjust, 0 );
	AnglesToAxis( angles, ent.axis );
	ent.hModel = s_main.bannerModel;
	VectorCopy( origin, ent.origin );
	VectorCopy( origin, ent.lightingOrigin );
	ent.renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW;
	VectorCopy( ent.origin, ent.oldorigin );

	trap_R_AddRefEntityToScene( &ent );

	// standard menu drawing
	Menu_Draw( &s_main.menu );

	trap_R_RenderScene( &refdef );

/*	if (uis.demoversion) {
		UI_DrawProportionalString( 320, 372, "DEMO      FOR MATURE AUDIENCES      DEMO", UI_CENTER|UI_SMALLFONT, color );
		UI_DrawString( 320, 400, "Quake III Arena(c) 1999-2000, Id Software, Inc.  All Rights Reserved", UI_CENTER|UI_SMALLFONT, color );
	} else {
		UI_DrawString( 320, 450, "Quake III Arena(c) 1999-2000, Id Software, Inc.  All Rights Reserved", UI_CENTER|UI_SMALLFONT, color );
	}*/
}
示例#7
0
static void CG_PlasmaTrail( centity_t *cent, const weaponInfo_t *wi ) {
	localEntity_t	*le;
	refEntity_t		*re;
	entityState_t	*es;
	vec3_t			velocity, xvelocity, origin;
	vec3_t			offset, xoffset;
	vec3_t			v[3];
	int				t, startTime, step;

	float	waterScale = 1.0f;

	if ( cg_noProjectileTrail.integer || cg_oldPlasma.integer ) {
		return;
	}

	step = 50;

	es = &cent->currentState;
	startTime = cent->trailTime;
	t = step * ( (startTime + step) / step );

	BG_EvaluateTrajectory( &es->pos, cg.time, origin );

	le = CG_AllocLocalEntity();
	re = &le->refEntity;

	velocity[0] = 60 - 120 * crandom();
	velocity[1] = 40 - 80 * crandom();
	velocity[2] = 100 - 200 * crandom();

	le->leType = LE_MOVE_SCALE_FADE;
	le->leFlags = LEF_TUMBLE;
	le->leBounceSoundType = LEBS_NONE;
	le->leMarkType = LEMT_NONE;

	le->startTime = cg.time;
	le->endTime = le->startTime + 600;

	le->pos.trType = TR_GRAVITY;
	le->pos.trTime = cg.time;

	AnglesToAxis( cent->lerpAngles, v );

	offset[0] = 2;
	offset[1] = 2;
	offset[2] = 2;

	xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0];
	xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1];
	xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2];

	VectorAdd( origin, xoffset, re->origin );
	VectorCopy( re->origin, le->pos.trBase );

	if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) {
		waterScale = 0.10f;
	}

	xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0];
	xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1];
	xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2];
	VectorScale( xvelocity, waterScale, le->pos.trDelta );

	AxisCopy( axisDefault, re->axis );
    re->shaderTime = cg.time / 1000.0f;
    re->reType = RT_SPRITE;
    re->radius = 0.25f;
	re->customShader = cgs.media.railRingsShader;
	le->bounceFactor = 0.3f;

    re->shaderRGBA[0] = wi->flashDlightColor[0] * 63;
    re->shaderRGBA[1] = wi->flashDlightColor[1] * 63;
    re->shaderRGBA[2] = wi->flashDlightColor[2] * 63;
    re->shaderRGBA[3] = 63;

    le->color[0] = wi->flashDlightColor[0] * 0.2;
    le->color[1] = wi->flashDlightColor[1] * 0.2;
    le->color[2] = wi->flashDlightColor[2] * 0.2;
    le->color[3] = 0.25f;

	le->angles.trType = TR_LINEAR;
	le->angles.trTime = cg.time;
	le->angles.trBase[0] = rand()&31;
	le->angles.trBase[1] = rand()&31;
	le->angles.trBase[2] = rand()&31;
	le->angles.trDelta[0] = 1;
	le->angles.trDelta[1] = 0.5;
	le->angles.trDelta[2] = 0;

}
示例#8
0
/*
=================
R_LoadMDC
=================
*/
qboolean R_LoadMDC(model_t * mod, int lod, void *buffer, int bufferSize, const char *modName)
{
	int             i, j, k, l;

	mdcHeader_t    *mdcModel;
	md3Frame_t     *mdcFrame;
	mdcSurface_t   *mdcSurf;
	md3Shader_t    *mdcShader;
	md3Triangle_t  *mdcTri;
	md3St_t        *mdcst;
	md3XyzNormal_t *mdcxyz;
	mdcXyzCompressed_t *mdcxyzComp;
	mdcTag_t       *mdcTag;
	mdcTagName_t   *mdcTagName;

	mdvModel_t     *mdvModel;
	mdvFrame_t     *frame;
	mdvSurface_t   *surf, *surface;
	srfTriangle_t  *tri;
	mdvVertex_t    *v;
	mdvSt_t        *st;
	mdvTag_t       *tag;
	mdvTagName_t   *tagName;
	short          *ps;

	int             version;
	int             size;

	mdcModel = (mdcHeader_t *) buffer;

	version = LittleLong(mdcModel->version);
	if(version != MDC_VERSION)
	{
		ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", modName, version, MDC_VERSION);
		return qfalse;
	}

	mod->type = MOD_MESH;
	size = LittleLong(mdcModel->ofsEnd);
	mod->dataSize += size;
	mdvModel = mod->mdv[lod] = ri.Hunk_Alloc(sizeof(mdvModel_t), h_low);


	LL(mdcModel->ident);
	LL(mdcModel->version);
	LL(mdcModel->numFrames);
	LL(mdcModel->numTags);
	LL(mdcModel->numSurfaces);
	LL(mdcModel->ofsFrames);
	LL(mdcModel->ofsTags);
	LL(mdcModel->ofsSurfaces);
	LL(mdcModel->ofsEnd);
	LL(mdcModel->ofsEnd);
	LL(mdcModel->flags);
	LL(mdcModel->numSkins);

	if(mdcModel->numFrames < 1)
	{
		ri.Printf(PRINT_WARNING, "R_LoadMDC: '%s' has no frames\n", modName);
		return qfalse;
	}

	// swap all the frames
	mdvModel->numFrames = mdcModel->numFrames;
	mdvModel->frames = frame = ri.Hunk_Alloc(sizeof(*frame) * mdcModel->numFrames, h_low);

	mdcFrame = (md3Frame_t *) ((byte *) mdcModel + mdcModel->ofsFrames);
	for(i = 0; i < mdcModel->numFrames; i++, frame++, mdcFrame++)
	{
		
#if 1
		// RB: ET HACK
		if(strstr(mod->name, "sherman") || strstr(mod->name, "mg42"))
		{
			frame->radius = 256;
			for(j = 0; j < 3; j++)
			{
				frame->bounds[0][j] = 128;
				frame->bounds[1][j] = -128;
				frame->localOrigin[j] = LittleFloat(mdcFrame->localOrigin[j]);
			}
		}
		else
#endif
		{
			frame->radius = LittleFloat(mdcFrame->radius);
			for(j = 0; j < 3; j++)
			{
				frame->bounds[0][j] = LittleFloat(mdcFrame->bounds[0][j]);
				frame->bounds[1][j] = LittleFloat(mdcFrame->bounds[1][j]);
				frame->localOrigin[j] = LittleFloat(mdcFrame->localOrigin[j]);
			}
		}
	}

	// swap all the tags
	mdvModel->numTags = mdcModel->numTags;
	mdvModel->tags = tag = ri.Hunk_Alloc(sizeof(*tag) * (mdcModel->numTags * mdcModel->numFrames), h_low);

	mdcTag = (mdcTag_t *) ((byte *) mdcModel + mdcModel->ofsTags);
	for(i = 0; i < mdcModel->numTags * mdcModel->numFrames; i++, tag++, mdcTag++)
	{
		vec3_t		angles;
		for(j = 0; j < 3; j++)
		{
			tag->origin[j] = (float)LittleShort(mdcTag->xyz[j]) * MD3_XYZ_SCALE;
			angles[j] = (float)LittleShort(mdcTag->angles[j]) * MDC_TAG_ANGLE_SCALE;
		}

		AnglesToAxis(angles, tag->axis);
	}

	mdvModel->tagNames = tagName = ri.Hunk_Alloc(sizeof(*tagName) * (mdcModel->numTags), h_low);

	mdcTagName = (mdcTagName_t *) ((byte *) mdcModel + mdcModel->ofsTagNames);
	for(i = 0; i < mdcModel->numTags; i++, tagName++, mdcTagName++)
	{
		Q_strncpyz(tagName->name, mdcTagName->name, sizeof(tagName->name));
	}

	// swap all the surfaces
	mdvModel->numSurfaces = mdcModel->numSurfaces;
	mdvModel->surfaces = surf = ri.Hunk_Alloc(sizeof(*surf) * mdcModel->numSurfaces, h_low);

	mdcSurf = (mdcSurface_t *) ((byte *) mdcModel + mdcModel->ofsSurfaces);
	for(i = 0; i < mdcModel->numSurfaces; i++)
	{
		LL(mdcSurf->ident);
		LL(mdcSurf->flags);
		LL(mdcSurf->numBaseFrames);
		LL(mdcSurf->numCompFrames);
		LL(mdcSurf->numShaders);
		LL(mdcSurf->numTriangles);
		LL(mdcSurf->ofsTriangles);
		LL(mdcSurf->numVerts);
		LL(mdcSurf->ofsShaders);
		LL(mdcSurf->ofsSt);
		LL(mdcSurf->ofsXyzNormals);
		LL(mdcSurf->ofsXyzNormals);
		LL(mdcSurf->ofsXyzCompressed);
		LL(mdcSurf->ofsFrameBaseFrames);
		LL(mdcSurf->ofsFrameCompFrames);
		LL(mdcSurf->ofsEnd);


		if(mdcSurf->numVerts > SHADER_MAX_VERTEXES)
		{
			ri.Error(ERR_DROP, "R_LoadMDC: %s has more than %i verts on a surface (%i)",
					 modName, SHADER_MAX_VERTEXES, mdcSurf->numVerts);
		}
		if(mdcSurf->numTriangles > SHADER_MAX_TRIANGLES)
		{
			ri.Error(ERR_DROP, "R_LoadMDC: %s has more than %i triangles on a surface (%i)",
					 modName, SHADER_MAX_TRIANGLES, mdcSurf->numTriangles);
		}

		// change to surface identifier
		surf->surfaceType = SF_MDV;

		// give pointer to model for Tess_SurfaceMDX
		surf->model = mdvModel;

		// copy surface name
		Q_strncpyz(surf->name, mdcSurf->name, sizeof(surf->name));

		// lowercase the surface name so skin compares are faster
		Q_strlwr(surf->name);

		// strip off a trailing _1 or _2
		// this is a crutch for q3data being a mess
		j = strlen(surf->name);
		if(j > 2 && surf->name[j - 2] == '_')
		{
			surf->name[j - 2] = 0;
		}

		// register the shaders
		/*
		   surf->numShaders = md3Surf->numShaders;
		   surf->shaders = shader = ri.Hunk_Alloc(sizeof(*shader) * md3Surf->numShaders, h_low);

		   md3Shader = (md3Shader_t *) ((byte *) md3Surf + md3Surf->ofsShaders);
		   for(j = 0; j < md3Surf->numShaders; j++, shader++, md3Shader++)
		   {
		   shader_t       *sh;

		   sh = R_FindShader(md3Shader->name, SHADER_3D_DYNAMIC, qtrue);
		   if(sh->defaultShader)
		   {
		   shader->shaderIndex = 0;
		   }
		   else
		   {
		   shader->shaderIndex = sh->index;
		   }
		   }
		 */

		// only consider the first shader
		mdcShader = (md3Shader_t *) ((byte *) mdcSurf + mdcSurf->ofsShaders);
		surf->shader = R_FindShader(mdcShader->name, SHADER_3D_DYNAMIC, qtrue);

		// swap all the triangles
		surf->numTriangles = mdcSurf->numTriangles;
		surf->triangles = tri = ri.Hunk_Alloc(sizeof(*tri) * mdcSurf->numTriangles, h_low);

		mdcTri = (md3Triangle_t *) ((byte *) mdcSurf + mdcSurf->ofsTriangles);
		for(j = 0; j < mdcSurf->numTriangles; j++, tri++, mdcTri++)
		{
			tri->indexes[0] = LittleLong(mdcTri->indexes[0]);
			tri->indexes[1] = LittleLong(mdcTri->indexes[1]);
			tri->indexes[2] = LittleLong(mdcTri->indexes[2]);
		}

		R_CalcSurfaceTriangleNeighbors(surf->numTriangles, surf->triangles);

		// swap all the XyzNormals
		mdcxyz = (md3XyzNormal_t *) ((byte *) mdcSurf + mdcSurf->ofsXyzNormals);
		for(j = 0; j < mdcSurf->numVerts * mdcSurf->numBaseFrames; j++, mdcxyz++)
		{
			mdcxyz->xyz[0] = LittleShort(mdcxyz->xyz[0]);
			mdcxyz->xyz[1] = LittleShort(mdcxyz->xyz[1]);
			mdcxyz->xyz[2] = LittleShort(mdcxyz->xyz[2]);

			mdcxyz->normal = LittleShort(mdcxyz->normal);
		}

		// swap all the XyzCompressed
		mdcxyzComp = (mdcXyzCompressed_t *) ((byte *) mdcSurf + mdcSurf->ofsXyzCompressed);
		for(j = 0; j < mdcSurf->numVerts * mdcSurf->numCompFrames; j++, mdcxyzComp++)
		{
			LL(mdcxyzComp->ofsVec);
		}

		// swap the frameBaseFrames
		ps = (short *)((byte *) mdcSurf + mdcSurf->ofsFrameBaseFrames);
		for(j = 0; j < mdcModel->numFrames; j++, ps++)
		{
			*ps = LittleShort(*ps);
		}

		// swap the frameCompFrames
		ps = (short *)((byte *) mdcSurf + mdcSurf->ofsFrameCompFrames);
		for(j = 0; j < mdcModel->numFrames; j++, ps++)
		{
			*ps = LittleShort(*ps);
		}

		surf->numVerts = mdcSurf->numVerts;
		surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (mdcSurf->numVerts * mdcModel->numFrames), h_low);
		
		for(j = 0; j < mdcModel->numFrames; j++)
		{
			int             baseFrame;
			int				compFrame;

			baseFrame = (int) *((short *)((byte *) mdcSurf + mdcSurf->ofsFrameBaseFrames) + j);

			mdcxyz = (md3XyzNormal_t *)((byte *) mdcSurf + mdcSurf->ofsXyzNormals + baseFrame * mdcSurf->numVerts * sizeof(md3XyzNormal_t));

			if(mdcSurf->numCompFrames > 0)
			{
				compFrame = (int) *((short *)((byte *) mdcSurf + mdcSurf->ofsFrameCompFrames) + j);
				if(compFrame >= 0)
				{
					mdcxyzComp = (mdcXyzCompressed_t *) ((byte *) mdcSurf + mdcSurf->ofsXyzCompressed + compFrame * mdcSurf->numVerts * sizeof(mdcXyzCompressed_t));
				}
			}

			for(k = 0; k < mdcSurf->numVerts; k++, v++, mdcxyz++)
			{
				v->xyz[0] = LittleShort(mdcxyz->xyz[0]) * MD3_XYZ_SCALE;
				v->xyz[1] = LittleShort(mdcxyz->xyz[1]) * MD3_XYZ_SCALE;
				v->xyz[2] = LittleShort(mdcxyz->xyz[2]) * MD3_XYZ_SCALE;

				if(mdcSurf->numCompFrames > 0 && compFrame >= 0)
				{
					vec3_t      ofsVec;
					vec3_t		normal;

					R_MDC_DecodeXyzCompressed(LittleShort(mdcxyzComp->ofsVec), ofsVec, normal);
					VectorAdd(v->xyz, ofsVec, v->xyz);

					mdcxyzComp++;
				}
			}
		}

		// swap all the ST
		surf->st = st = ri.Hunk_Alloc(sizeof(*st) * mdcSurf->numVerts, h_low);

		mdcst = (md3St_t *) ((byte *) mdcSurf + mdcSurf->ofsSt);
		for(j = 0; j < mdcSurf->numVerts; j++, mdcst++, st++)
		{
			st->st[0] = LittleFloat(mdcst->st[0]);
			st->st[1] = LittleFloat(mdcst->st[1]);
		}

		// find the next surface
		mdcSurf = (mdcSurface_t *) ((byte *) mdcSurf + mdcSurf->ofsEnd);
		surf++;
	}

#if 1
	// create VBO surfaces from md3 surfaces
	{
		growList_t      vboSurfaces;
		srfVBOMDVMesh_t *vboSurf;

		byte           *data;
		int             dataSize;
		int             dataOfs;

		vec4_t          tmp;

		GLuint          ofsTexCoords;
		GLuint          ofsTangents;
		GLuint          ofsBinormals;
		GLuint          ofsNormals;

		GLuint			sizeXYZ;
		GLuint			sizeTangents;
		GLuint			sizeBinormals;
		GLuint			sizeNormals;

		int				vertexesNum;
		int				f;

		Com_InitGrowList(&vboSurfaces, 10);

		for(i = 0, surf = mdvModel->surfaces; i < mdvModel->numSurfaces; i++, surf++)
		{
			// calc tangent spaces
			{
				const float    *v0, *v1, *v2;
				const float    *t0, *t1, *t2;
				vec3_t          tangent;
				vec3_t          binormal;
				vec3_t          normal;

				for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
				{
					VectorClear(v->tangent);
					VectorClear(v->binormal);
					VectorClear(v->normal);
				}

				for(f = 0; f < mdvModel->numFrames; f++)
				{
					for(j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++)
					{
						v0 = surf->verts[surf->numVerts * f + tri->indexes[0]].xyz;
						v1 = surf->verts[surf->numVerts * f + tri->indexes[1]].xyz;
						v2 = surf->verts[surf->numVerts * f + tri->indexes[2]].xyz;

						t0 = surf->st[tri->indexes[0]].st;
						t1 = surf->st[tri->indexes[1]].st;
						t2 = surf->st[tri->indexes[2]].st;

						#if 1
						R_CalcTangentSpace(tangent, binormal, normal, v0, v1, v2, t0, t1, t2);
						#else
						R_CalcNormalForTriangle(normal, v0, v1, v2);
						R_CalcTangentsForTriangle(tangent, binormal, v0, v1, v2, t0, t1, t2);
						#endif

						for(k = 0; k < 3; k++)
						{
							float          *v;

							v = surf->verts[surf->numVerts * f + tri->indexes[k]].tangent;
							VectorAdd(v, tangent, v);

							v = surf->verts[surf->numVerts * f + tri->indexes[k]].binormal;
							VectorAdd(v, binormal, v);

							v = surf->verts[surf->numVerts * f + tri->indexes[k]].normal;
							VectorAdd(v, normal, v);
						}
					}
				}

				for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
				{
					VectorNormalize(v->tangent);
					VectorNormalize(v->binormal);
					VectorNormalize(v->normal);
				}
			}

			//ri.Printf(PRINT_ALL, "...calculating MDC mesh VBOs ( '%s', %i verts %i tris )\n", surf->name, surf->numVerts, surf->numTriangles);

			// create surface
			vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
			Com_AddToGrowList(&vboSurfaces, vboSurf);

			vboSurf->surfaceType = SF_VBO_MDVMESH;
			vboSurf->mdvModel = mdvModel;
			vboSurf->mdvSurface = surf;
			vboSurf->numIndexes = surf->numTriangles * 3;
			vboSurf->numVerts = surf->numVerts;

			/*
			vboSurf->vbo = R_CreateVBO2(va("staticWorldMesh_vertices %i", vboSurfaces.currentElements), numVerts, optimizedVerts,
									   ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL | ATTR_NORMAL
									   | ATTR_COLOR);
									   */

			vboSurf->ibo = R_CreateIBO2(va("staticMDCMesh_IBO %s", surf->name), surf->numTriangles, surf->triangles, VBO_USAGE_STATIC);


			// create VBO
			vertexesNum = surf->numVerts;

			dataSize =	(surf->numVerts * mdvModel->numFrames * sizeof(vec4_t) * 4) + // xyz, tangent, binormal, normal
						(surf->numVerts * sizeof(vec4_t)); // texcoords
			data = ri.Malloc(dataSize);
			dataOfs = 0;

			// feed vertex XYZ
			for(f = 0; f < mdvModel->numFrames; f++)
			{
				for(j = 0; j < vertexesNum; j++)
				{
					for(k = 0; k < 3; k++)
					{
						tmp[k] = surf->verts[f * vertexesNum + j].xyz[k];
					}
					tmp[3] = 1;
					Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t));
					dataOfs += sizeof(vec4_t);
				}

				if(f == 0)
				{
					sizeXYZ = dataOfs;
				}
			}

			// feed vertex texcoords
			ofsTexCoords = dataOfs;
			for(j = 0; j < vertexesNum; j++)
			{
				for(k = 0; k < 2; k++)
				{
					tmp[k] = surf->st[j].st[k];
				}
				tmp[2] = 0;
				tmp[3] = 1;
				Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t));
				dataOfs += sizeof(vec4_t);
			}

			// feed vertex tangents
			ofsTangents = dataOfs;
			for(f = 0; f < mdvModel->numFrames; f++)
			{
				for(j = 0; j < vertexesNum; j++)
				{
					for(k = 0; k < 3; k++)
					{
						tmp[k] = surf->verts[f * vertexesNum + j].tangent[k];
					}
					tmp[3] = 1;
					Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t));
					dataOfs += sizeof(vec4_t);
				}

				if(f == 0)
				{
					sizeTangents = dataOfs - ofsTangents;
				}
			}

			// feed vertex binormals
			ofsBinormals = dataOfs;
			for(f = 0; f < mdvModel->numFrames; f++)
			{
				for(j = 0; j < vertexesNum; j++)
				{
					for(k = 0; k < 3; k++)
					{
						tmp[k] = surf->verts[f * vertexesNum + j].binormal[k];
					}
					tmp[3] = 1;
					Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t));
					dataOfs += sizeof(vec4_t);
				}

				if(f == 0)
				{
					sizeBinormals = dataOfs - ofsBinormals;
				}
			}

			// feed vertex normals
			ofsNormals = dataOfs;
			for(f = 0; f < mdvModel->numFrames; f++)
			{
				for(j = 0; j < vertexesNum; j++)
				{
					for(k = 0; k < 3; k++)
					{
						tmp[k] = surf->verts[f * vertexesNum + j].normal[k];
					}
					tmp[3] = 1;
					Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t));
					dataOfs += sizeof(vec4_t);
				}

				if(f == 0)
				{
					sizeNormals = dataOfs - ofsNormals;
				}
			}

			vboSurf->vbo = R_CreateVBO(va("staticMDCMesh_VBO '%s'", surf->name), data, dataSize, VBO_USAGE_STATIC);
			vboSurf->vbo->ofsXYZ = 0;
			vboSurf->vbo->ofsTexCoords = ofsTexCoords;
			vboSurf->vbo->ofsLightCoords = ofsTexCoords;
			vboSurf->vbo->ofsTangents = ofsTangents;
			vboSurf->vbo->ofsBinormals = ofsBinormals;
			vboSurf->vbo->ofsNormals = ofsNormals;

			vboSurf->vbo->sizeXYZ = sizeXYZ;
			vboSurf->vbo->sizeTangents = sizeTangents;
			vboSurf->vbo->sizeBinormals = sizeBinormals;
			vboSurf->vbo->sizeNormals = sizeNormals;

			ri.Free(data);
		}

		// move VBO surfaces list to hunk
		mdvModel->numVBOSurfaces = vboSurfaces.currentElements;
		mdvModel->vboSurfaces = ri.Hunk_Alloc(mdvModel->numVBOSurfaces * sizeof(*mdvModel->vboSurfaces), h_low);

		for(i = 0; i < mdvModel->numVBOSurfaces; i++)
		{
			mdvModel->vboSurfaces[i] = (srfVBOMDVMesh_t *) Com_GrowListElement(&vboSurfaces, i);
		}

		Com_DestroyGrowList(&vboSurfaces);
	}
#endif

	return qtrue;
}
示例#9
0
void CGCam_Update( void )
{
	int	i;
	qboolean	checkFollow = qfalse;
	qboolean	checkTrack = qfalse;

	// Apply new roff data to the camera as needed
	if ( client_camera.info_state & CAMERA_ROFFING )
	{
		CGCam_Roff();
	}

	//Check for a zoom
	if (client_camera.info_state & CAMERA_ACCEL)
	{
		// x = x0 + vt + 0.5*a*t*t
		float	actualFOV_X = client_camera.FOV;
		float	sanityMin = 1, sanityMax = 180;
		float	t = (cg.time - client_camera.FOV_time)*0.001; // mult by 0.001 cuz otherwise t is too darned big
		float	fovDuration = client_camera.FOV_duration;

#ifndef FINAL_BUILD
		if (cg_roffval4.integer)
		{
			fovDuration = cg_roffval4.integer;
		}
#endif
		if ( client_camera.FOV_time + fovDuration < cg.time )
		{
			client_camera.info_state &= ~CAMERA_ACCEL;
		}
		else
		{
			float	initialPosVal = client_camera.FOV2;
			float	velVal = client_camera.FOV_vel;
			float	accVal = client_camera.FOV_acc;

#ifndef FINAL_BUILD
			if (cg_roffdebug.integer)
			{
				if (fabs(cg_roffval1.value) > 0.001f)
				{
					initialPosVal = cg_roffval1.value;
				}
				if (fabs(cg_roffval2.value) > 0.001f)
				{
					velVal = cg_roffval2.value;
				}
				if (fabs(cg_roffval3.value) > 0.001f)
				{
					accVal = cg_roffval3.value;
				}
			}
#endif
			float	initialPos = initialPosVal;
			float	vel = velVal*t;
			float	acc = 0.5*accVal*t*t;

			actualFOV_X = initialPos + vel + acc;
			if (cg_roffdebug.integer)
			{
				Com_Printf("%d: fovaccel from %2.1f using vel = %2.4f, acc = %2.4f (current fov calc = %5.6f)\n",
					cg.time, initialPosVal, velVal, accVal, actualFOV_X);
			}

			if (actualFOV_X < sanityMin)
			{
				actualFOV_X = sanityMin;
			}
			else if (actualFOV_X > sanityMax)
			{
				actualFOV_X = sanityMax;
			}
			client_camera.FOV = actualFOV_X;
		}
		CG_CalcFOVFromX( actualFOV_X );
	}
	else if ( client_camera.info_state & CAMERA_ZOOMING )
	{
		float	actualFOV_X;

		if ( client_camera.FOV_time + client_camera.FOV_duration < cg.time )
		{
			actualFOV_X = client_camera.FOV = client_camera.FOV2;
			client_camera.info_state &= ~CAMERA_ZOOMING;
		}
		else
		{
			actualFOV_X = client_camera.FOV + (( ( client_camera.FOV2 - client_camera.FOV ) ) / client_camera.FOV_duration ) * ( cg.time - client_camera.FOV_time );
		}
		CG_CalcFOVFromX( actualFOV_X );
	}
	else
	{
		CG_CalcFOVFromX( client_camera.FOV );
	}

	//Check for roffing angles
	if ( (client_camera.info_state & CAMERA_ROFFING) && !(client_camera.info_state & CAMERA_FOLLOWING) )
	{
		if (client_camera.info_state & CAMERA_CUT)
		{
			// we're doing a cut, so just go to the new angles. none of this hifalutin lerping business.
			for ( i = 0; i < 3; i++ )
			{
				cg.refdefViewAngles[i] = AngleNormalize360( ( client_camera.angles[i] + client_camera.angles2[i] ) );
			}
		}
		else
		{
			for ( i = 0; i < 3; i++ )
			{
				cg.refdefViewAngles[i] =  client_camera.angles[i] + ( client_camera.angles2[i] / client_camera.pan_duration ) * ( cg.time - client_camera.pan_time );
			}
		}
	}
	else if ( client_camera.info_state & CAMERA_PANNING )
	{
		if (client_camera.info_state & CAMERA_CUT)
		{
			// we're doing a cut, so just go to the new angles. none of this hifalutin lerping business.
			for ( i = 0; i < 3; i++ )
			{
				cg.refdefViewAngles[i] = AngleNormalize360( ( client_camera.angles[i] + client_camera.angles2[i] ) );
			}
		}
		else
		{
			//Note: does not actually change the camera's angles until the pan time is done!
			if ( client_camera.pan_time + client_camera.pan_duration < cg.time )
			{//finished panning
				for ( i = 0; i < 3; i++ )
				{
					client_camera.angles[i] = AngleNormalize360( ( client_camera.angles[i] + client_camera.angles2[i] ) );
				}

				client_camera.info_state &= ~CAMERA_PANNING;
				VectorCopy(client_camera.angles, cg.refdefViewAngles );
			}
			else
			{//still panning
				for ( i = 0; i < 3; i++ )
				{
					//NOTE: does not store the resultant angle in client_camera.angles until pan is done
					cg.refdefViewAngles[i] = client_camera.angles[i] + ( client_camera.angles2[i] / client_camera.pan_duration ) * ( cg.time - client_camera.pan_time );
				}
			}
		}
	}
	else 
	{
		checkFollow = qtrue;
	}

	//Check for movement
	if ( client_camera.info_state & CAMERA_MOVING )
	{
		//NOTE: does not actually move the camera until the movement time is done!
		if ( client_camera.move_time + client_camera.move_duration < cg.time )
		{
			VectorCopy( client_camera.origin2, client_camera.origin );
			client_camera.info_state &= ~CAMERA_MOVING;
			VectorCopy( client_camera.origin, cg.refdef.vieworg );
		}
		else
		{
			if (client_camera.info_state & CAMERA_CUT)
			{
				// we're doing a cut, so just go to the new origin. none of this fancypants lerping stuff.
				for ( i = 0; i < 3; i++ )
				{
					cg.refdef.vieworg[i] = client_camera.origin2[i];
				}
			}
			else
			{
				for ( i = 0; i < 3; i++ )
				{
					cg.refdef.vieworg[i] = client_camera.origin[i] + (( ( client_camera.origin2[i] - client_camera.origin[i] ) ) / client_camera.move_duration ) * ( cg.time - client_camera.move_time );
				}
			}
		}
	}
	else
	{
		checkTrack = qtrue;
	}

	if ( checkFollow )
	{
		if ( client_camera.info_state & CAMERA_FOLLOWING )
		{//This needs to be done after camera movement
			CGCam_FollowUpdate();
		}
		VectorCopy(client_camera.angles, cg.refdefViewAngles );
	}

	if ( checkTrack )
	{
		if ( client_camera.info_state & CAMERA_TRACKING )
		{//This has to run AFTER Follow if the camera is following a cameraGroup
			CGCam_TrackUpdate();
		}

		VectorCopy( client_camera.origin, cg.refdef.vieworg );
	}

	//Bar fading
	if ( client_camera.info_state & CAMERA_BAR_FADING )
	{
		CGCam_UpdateBarFade();
	}

	//Normal fading - separate call because can finish after camera is disabled
	CGCam_UpdateFade();

	//Update shaking if there's any
	//CGCam_UpdateSmooth( cg.refdef.vieworg, cg.refdefViewAngles );
	CGCam_UpdateShake( cg.refdef.vieworg, cg.refdefViewAngles );
	AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
}
示例#10
0
void Wolfcam_AddViewWeapon (void)
{
    vec3_t origin;
    centity_t *cent;
    const entityState_t *es;
    refEntity_t hand;
    const clientInfo_t *ci;
    float fovOffset;
    vec3_t angles;
    const weaponInfo_t *weapon;
    float gunX;
    int fov;

    if (!wolfcam_following) {
        return;
    }

    cent = &cg_entities[wcg.clientNum];
    es = &cent->currentState;

    if (!cg_drawGun.integer) {
        if (es->eFlags & EF_FIRING  &&  es->weapon == WP_LIGHTNING) {
            // special hack for lightning gun...
            VectorCopy( cg.refdef.vieworg, origin );
            VectorMA( origin, -8, cg.refdef.viewaxis[2], origin );
            CG_LightningBolt( &cg_entities[es->number], origin );

            //FIXME is this adding the sound twice?
            CG_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, cg_weapons[es->weapon].firingSound );
        }

        return;
    }

    // don't draw if testing a gun model
    if (cg.testGun) {
        return;
    }

    gunX = cg_gun_x.value;
    if (es->weapon == WP_GRAPPLING_HOOK) {
        gunX += 8.9;
    }

    fov = cg_fov.integer;

    //FIXME option
    // drop gun lower at higher fov
    if (fov > 90) {
        fovOffset = -0.2 * (fov - 90);
    } else {
        fovOffset = 0;
    }

    CG_RegisterWeapon(es->weapon);
    weapon = &cg_weapons[es->weapon];

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

    // set up gun position
    Wolfcam_CalculateWeaponPosition(hand.origin, angles);

    VectorMA( hand.origin, gunX, cg.refdef.viewaxis[0], hand.origin );
	VectorMA( hand.origin, cg_gun_y.value, cg.refdef.viewaxis[1], hand.origin );
	VectorMA( hand.origin, (cg_gun_z.value+fovOffset), cg.refdef.viewaxis[2], hand.origin );

	AnglesToAxis( angles, hand.axis );

	// map torso animations to weapon animations
	//cg_gun_frame.integer = 1;
	if ( cg_gun_frame.integer ) {
		// development tool
		hand.frame = hand.oldframe = cg_gun_frame.integer;
		hand.backlerp = 0;
	} else {  //if (0) {
		// these are just for calling CG_PlayerAnimation()
		int legsOld;
		int legs;
		float legsBackLerp;
		int torsoOld;
		int torso;
		float torsoBackLerp;

		// get clientinfo for animation map
		ci = &cgs.clientinfo[ cent->currentState.clientNum ];

		// animations weren't run for /follow'ed player
		CG_PlayerAnimation(cent, &legsOld, &legs, &legsBackLerp, &torsoOld, &torso, &torsoBackLerp);

		hand.frame = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.frame );
		hand.oldframe = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.oldFrame );
		hand.backlerp = cent->pe.torso.backlerp;
	}

	hand.hModel = weapon->handsModel;
	hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT;

	// add everything onto the hand
	Wolfcam_AddPlayerWeapon(&hand, cent, cgs.clientinfo[cent->currentState.clientNum].team);
}
示例#11
0
//----------------------------
void CEmitter::UpdateAngles()
{
	VectorMA( mAngles, theFxHelper.mFrameTime * 0.01f, mAngleDelta, mAngles ); // was 0.001f, but then you really have to jack up the delta to even notice anything
	AnglesToAxis( mAngles, mRefEnt.axis );
}
示例#12
0
void Wolfcam_AddPlayerWeapon (const refEntity_t *parent, centity_t *cent, int team)
{
	refEntity_t	gun;
	refEntity_t	barrel;
	refEntity_t	flash;
	vec3_t		angles;
	weapon_t	weaponNum;
	const weaponInfo_t	*weapon;
	centity_t	*nonPredictedCent;
//	int	col
	clientInfo_t	*ci;
	float flashSize;
	float dlight[3];
	float f;
	qboolean revertColors = qfalse;
	vec3_t origColor1;
	vec3_t origColor2;

	if (!cent->inCurrentSnapshot) {
		// this can happen with /follow which can stay in victim position
		// (frag hover)
		return;
	}

	ci = &cgs.clientinfo[ cent->currentState.clientNum ];
	weaponNum = cent->currentState.weapon;

	if (weaponNum <= WP_NONE  ||  weaponNum >= WP_NUM_WEAPONS) {
		return;
	}

	CG_RegisterWeapon( weaponNum );
	weapon = &cg_weapons[weaponNum];

	// add the weapon
	memset( &gun, 0, sizeof( gun ) );
	VectorCopy( parent->lightingOrigin, gun.lightingOrigin );
	gun.shadowPlane = parent->shadowPlane;
	gun.renderfx = parent->renderfx;

	// set custom shading for railgun refire rate
	if (0) {  //( ps ) {
	} else {
		if (weaponNum == WP_RAILGUN) {
			qboolean teamRail;
			qboolean enemyRail;

			if (cg_railUseOwnColors.integer  &&  CG_IsUs(ci)) {
				VectorCopy(ci->color1, origColor1);
				VectorCopy(ci->color2, origColor2);
				VectorCopy(cg.color1, ci->color1);
				VectorCopy(cg.color2, ci->color2);
				revertColors = qtrue;
			}

			teamRail = CG_IsTeammate(ci);
			enemyRail = CG_IsEnemy(ci);
			if (cgs.gametype < GT_TEAM) {
				if (!CG_IsUs(ci)) {
					if (*cg_enemyRailItemColor.string) {
						SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_enemyRailItemColor);
						gun.shaderRGBA[3] = 255;
					} else {
						gun.shaderRGBA[0] = 255 * ci->color1[0];
						gun.shaderRGBA[1] = 255 * ci->color1[1];
						gun.shaderRGBA[2] = 255 * ci->color1[2];
						gun.shaderRGBA[3] = 255;
					}
				} else {
					gun.shaderRGBA[0] = 255 * ci->color1[0];
					gun.shaderRGBA[1] = 255 * ci->color1[1];
					gun.shaderRGBA[2] = 255 * ci->color1[2];
					gun.shaderRGBA[3] = 255;
				}
			} else {  // team game
				if (!CG_IsUs(ci)  &&  teamRail) {
					if (cg_teamRailItemColorTeam.integer) {
						if (ci->team == TEAM_RED) {
							SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_weaponRedTeamColor);
						} else {
							SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_weaponBlueTeamColor);
						}
						gun.shaderRGBA[3] = 255;
					} else if (*cg_teamRailItemColor.string) {
						SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_teamRailItemColor);
						gun.shaderRGBA[3] = 255;
					} else {
						gun.shaderRGBA[0] = 255 * ci->color1[0];
						gun.shaderRGBA[1] = 255 * ci->color1[1];
						gun.shaderRGBA[2] = 255 * ci->color1[2];
						gun.shaderRGBA[3] = 255;
					}
				} else if (!CG_IsUs(ci)  &&  enemyRail) {
					if (cg_enemyRailItemColorTeam.integer) {
						if (ci->team == TEAM_RED) {
							SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_weaponRedTeamColor);
						} else {
							SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_weaponBlueTeamColor);
						}
						gun.shaderRGBA[3] = 255;
					} else if (*cg_enemyRailItemColor.string) {
						SC_ByteVec3ColorFromCvar(gun.shaderRGBA, &cg_enemyRailItemColor);
						gun.shaderRGBA[3] = 255;
					} else {
						gun.shaderRGBA[0] = 255 * ci->color1[0];
						gun.shaderRGBA[1] = 255 * ci->color1[1];
						gun.shaderRGBA[2] = 255 * ci->color1[2];
						gun.shaderRGBA[3] = 255;
					}
				} else {  // us
					gun.shaderRGBA[0] = 255 * ci->color1[0];
					gun.shaderRGBA[1] = 255 * ci->color1[1];
					gun.shaderRGBA[2] = 255 * ci->color1[2];
					gun.shaderRGBA[3] = 255;
				}
			}

			// end weapon == WP_RAILGUN
			//cent->pe.muzzleFlashTime
			//Com_Printf("yes....\n");
			//f = cg.time - (cent->pe.muzzleFlashTime + 1500);
			f = cg.time - (cent->pe.muzzleFlashTime + 1460);  // hack
			//Com_Printf("f %f\n", f);
			if (f < 0) {
				f = 1.0 - (f / -1500);
				gun.shaderRGBA[0] *= 0.314 * f;
				gun.shaderRGBA[1] *= 0.314 * f;
				gun.shaderRGBA[2] *= 0.314 * f;
			}
		}
	}

	gun.hModel = weapon->weaponModel;
	if (!gun.hModel) {
		//Com_Printf("no gun model '%s'\n", weapNamesCasual[weaponNum]);
		//FIXME grapple returns here
		//FIXME fx
		//CG_PositionEntityOnTag(&gun, parent, parent->hModel, "tag_weapon");
		//CG_CheckFxWeaponFlash(cent, weaponNum, gun.origin);
		//return;
	}

	CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon");

    CG_ScaleModel(&gun, cg_gunSize.value);

	// custom weapon shaders
	{
		vmCvar_t *firstPersonShaders[MAX_WEAPONS] = { NULL, &cg_firstPersonShaderWeaponGauntlet, &cg_firstPersonShaderWeaponMachineGun, &cg_firstPersonShaderWeaponShotgun, &cg_firstPersonShaderWeaponGrenadeLauncher, &cg_firstPersonShaderWeaponRocketLauncher, &cg_firstPersonShaderWeaponLightningGun, &cg_firstPersonShaderWeaponRailGun, &cg_firstPersonShaderWeaponPlasmaGun, &cg_firstPersonShaderWeaponBFG, &cg_firstPersonShaderWeaponGrapplingHook, &cg_firstPersonShaderWeaponNailGun, &cg_firstPersonShaderWeaponProximityLauncher, &cg_firstPersonShaderWeaponChainGun, &cg_firstPersonShaderWeaponHeavyMachineGun };

		if (firstPersonShaders[weaponNum]  &&  *(firstPersonShaders[weaponNum]->string)) {
			gun.customShader = trap_R_RegisterShader(firstPersonShaders[weaponNum]->string);
		}
	}

	if (gun.hModel) {
		if (cg_drawGun.integer > 2) {
			gun.customShader = cgs.media.ghostWeaponShader;
			gun.shaderRGBA[0] = 255;
			gun.shaderRGBA[1] = 255;
			gun.shaderRGBA[2] = 255;
			gun.shaderRGBA[3] = 255;
		}

		CG_AddWeaponWithPowerups( &gun, cent->currentState.powerups );
	}

	// add the spinning barrel
	if ( weapon->barrelModel ) {
		memset( &barrel, 0, sizeof( barrel ) );
		VectorCopy( parent->lightingOrigin, barrel.lightingOrigin );
		barrel.shadowPlane = parent->shadowPlane;
		barrel.renderfx = parent->renderfx;

		barrel.hModel = weapon->barrelModel;
		angles[YAW] = 0;
		angles[PITCH] = 0;
		angles[ROLL] = CG_MachinegunSpinAngle( cent );
		AnglesToAxis( angles, barrel.axis );

		CG_PositionRotatedEntityOnTag( &barrel, &gun, weapon->weaponModel, "tag_barrel" );

        CG_ScaleModel(&barrel, cg_gunSize.value);

		if (cg_drawGun.integer > 2) {
			barrel.customShader = cgs.media.ghostWeaponShader;
			barrel.shaderRGBA[0] = 255;
			barrel.shaderRGBA[1] = 255;
			barrel.shaderRGBA[2] = 255;
			barrel.shaderRGBA[3] = 255;
		}

		CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
	}

	// make sure we aren't looking at cg.predictedPlayerEntity for LG
	nonPredictedCent = &cg_entities[cent->currentState.clientNum];

#if 0
	// if the index of the nonPredictedCent is not the same as the clientNum
	// then this is a fake player (like on teh single player podiums), so
	// go ahead and use the cent
	if( ( nonPredictedCent - cg_entities ) != cent->currentState.clientNum ) {
		nonPredictedCent = cent;
		//Com_Printf("fake player %d  ->  %d\n", nonPredictedCent - cg_entities, cent->currentState.clientNum);
	}
#endif


	// add the flash
	//if ( ( weaponNum == WP_LIGHTNING || weaponNum == WP_GAUNTLET || weaponNum == WP_GRAPPLING_HOOK )  &&  (cent->currentState.eFlags & EF_FIRING)) {
	if ( ( weaponNum == WP_LIGHTNING || weaponNum == WP_GAUNTLET || weaponNum == WP_GRAPPLING_HOOK )  &&  (nonPredictedCent->currentState.eFlags & EF_FIRING)) {
		// && ( nonPredictedCent->currentState.eFlags & EF_FIRING ) ) {
		// continuous flash
	} else {
		//int ftime;

		if (weaponNum == WP_LIGHTNING  &&  cent->currentState.eFlags & EF_FIRING) {
			//Com_Printf("%f wtf ps %p\n", cg.ftime, ps);
		}
		// impulse flash
		//if ( cg.time - cent->pe.muzzleFlashTime > MUZZLE_FLASH_TIME && !cent->pe.railgunFlash ) {
		if ( cg.time - nonPredictedCent->pe.muzzleFlashTime > MUZZLE_FLASH_TIME && !nonPredictedCent->pe.railgunFlash ) {
			//Com_Printf("returning for %d (%d)\n", cent - cg_entities, cent->currentState.number);
			//goto bolt;
			// not called, in case code changes
			if (revertColors) {
				VectorCopy(origColor1, ci->color1);
				VectorCopy(origColor2, ci->color2);
			}
			return;
		}
	}

	memset( &flash, 0, sizeof( flash ) );
	VectorCopy( parent->lightingOrigin, flash.lightingOrigin );
	flash.shadowPlane = parent->shadowPlane;
	flash.renderfx = parent->renderfx;

	flash.hModel = weapon->flashModel;
	/*
	if (weaponNum == WP_HEAVY_MACHINEGUN) {
		flash.hModel = cg_weapons[WP_MACHINEGUN].flashModel;
	}
	*/

	if (!flash.hModel) {
		//Com_Printf("no flash model '%s'\n", weapNamesCasual[weaponNum]);
		//FIXME fx
		//return;
	}
	angles[YAW] = 0;
	angles[PITCH] = 0;
	angles[ROLL] = crandom() * 10;
	AnglesToAxis( angles, flash.axis );

	// colorize the railgun blast
	if ( weaponNum == WP_RAILGUN ) {
		//clientInfo_t	*ci;

		//ci = &cgs.clientinfo[ cent->currentState.clientNum ];
		if (cg_railUseOwnColors.integer  &&  CG_IsUs(ci)) {
			flash.shaderRGBA[0] = 255 * cg.color1[0];
			flash.shaderRGBA[1] = 255 * cg.color1[1];
			flash.shaderRGBA[2] = 255 * cg.color1[2];
		} else {
			flash.shaderRGBA[0] = 255 * ci->color1[0];
			flash.shaderRGBA[1] = 255 * ci->color1[1];
			flash.shaderRGBA[2] = 255 * ci->color1[2];
		}
	}

	if (0) {  //(weapon->hasFlashScript) {
		//CG_RunQ3mmeFlashScript(weapon, dlight, flash.shaderRGBA, &flashSize);
		//VectorCopy(flash.origin, ScriptVars.origin);
		//CG_RunQ3mmeScript((char *)weapon->flashScript);
		//return;
	} else {
		dlight[0] = weapon->flashDlightColor[0];
		dlight[1] = weapon->flashDlightColor[1];
		dlight[2] = weapon->flashDlightColor[2];


		/*
		flash.shaderRGBA[0] = 255;
		flash.shaderRGBA[1] = 255;
		flash.shaderRGBA[2] = 255;
		flash.shaderRGBA[3] = 0;
		*/

		flashSize = 300 + (rand()&31);
	}

	CG_PositionRotatedEntityOnTag( &flash, &gun, weapon->weaponModel, "tag_flash");
	//Com_Printf("ps:%d  %p\n", ps != NULL, cent);

	if (0) {  //(cent == &cg.predictedPlayerEntity  &&  !cg.renderingThirdPerson  &&  !ps) {
		// don't run flash script twice for first person view
	} else if (EffectScripts.weapons[weaponNum].hasFlashScript) {
		//CG_RunQ3mmeFlashScript(weapon, dlight, flash.shaderRGBA, &flashSize);
		//memset(&ScriptVars, 0, sizeof(ScriptVars));
		//CG_Printf("addplayerweapon()  flash script cent %d\n", cent - cg_entities);
		CG_ResetScriptVars();
		CG_CopyPlayerDataToScriptData(cent);
		VectorCopy(flash.origin, ScriptVars.origin);
		VectorCopy(flash.origin, ScriptVars.parentOrigin);

		VectorCopy(cent->lastFlashIntervalPosition, ScriptVars.lastIntervalPosition);
		ScriptVars.lastIntervalTime = cent->lastFlashIntervalTime;
		VectorCopy(cent->lastFlashDistancePosition, ScriptVars.lastDistancePosition);
		ScriptVars.lastDistanceTime = cent->lastFlashDistanceTime;

		CG_RunQ3mmeScript((char *)EffectScripts.weapons[weaponNum].flashScript, NULL);

		VectorCopy(ScriptVars.lastIntervalPosition, cent->lastFlashIntervalPosition);
		cent->lastFlashIntervalTime = ScriptVars.lastIntervalTime;
		VectorCopy(ScriptVars.lastDistancePosition, cent->lastFlashDistancePosition);
		cent->lastFlashDistanceTime = ScriptVars.lastDistanceTime;
		//return;
	}

	if (!cg_muzzleFlash.integer) {
		// pass
	} else {
		if (flash.hModel) {
			CG_AddRefEntity(&flash);
		}
	}

	// bolt:
	if (1) {
		// add lightning bolt
		if (1) {
			CG_LightningBolt( nonPredictedCent, flash.origin );

			//Com_Printf("adding bolt\n");
			// add rail trail
			CG_SpawnRailTrail( cent, flash.origin );

			//if ((dlight[0]  ||  dlight[1]  ||  dlight[2])  &&  !weapon->hasFlashScript) {
			if ((dlight[0]  ||  dlight[1]  ||  dlight[2])  &&  !EffectScripts.weapons[weaponNum].hasFlashScript) {
				trap_R_AddLightToScene(flash.origin, flashSize, dlight[0], dlight[1], dlight[2]);
			}
		}
	} else {
		//Com_Printf("%f no...\n", cg.ftime);
	}

	if (revertColors) {
		VectorCopy(origColor1, ci->color1);
		VectorCopy(origColor2, ci->color2);
	}
}
示例#13
0
/*
==================
CG_Buildable
==================
*/
void CG_Buildable( centity_t *cent )
{
  refEntity_t     ent;
  entityState_t   *es = &cent->currentState;
  vec3_t          angles;
  vec3_t          surfNormal, xNormal, mins, maxs;
  vec3_t          refNormal = { 0.0f, 0.0f, 1.0f };
  float           rotAngle;
  buildableTeam_t team = (buildableTeam_t)BG_FindTeamForBuildable( es->modelindex );
  float           scale;
  int             health;
  float           healthScale;

  //must be before EF_NODRAW check
  if( team == BIT_ALIENS )
    CG_Creep( cent );

  // if set to invisible, skip
  if( es->eFlags & EF_NODRAW )
  {
    if( CG_IsParticleSystemValid( &cent->buildablePS ) )
      CG_DestroyParticleSystem( &cent->buildablePS );

    return;
  }

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

  VectorCopy( cent->lerpOrigin, ent.origin );
  VectorCopy( cent->lerpOrigin, ent.oldorigin );
  VectorCopy( cent->lerpOrigin, ent.lightingOrigin );

  VectorCopy( es->origin2, surfNormal );

  VectorCopy( es->angles, angles );
  BG_FindBBoxForBuildable( es->modelindex, mins, maxs );

  if( es->pos.trType == TR_STATIONARY )
    CG_PositionAndOrientateBuildable( angles, ent.origin, surfNormal, es->number,
                                      mins, maxs, ent.axis, ent.origin );

  //offset on the Z axis if required
  VectorMA( ent.origin, BG_FindZOffsetForBuildable( es->modelindex ), surfNormal, ent.origin );

  VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all
  VectorCopy( ent.origin, ent.lightingOrigin );

  ent.hModel = cg_buildables[ es->modelindex ].models[ 0 ];

  if( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) )
  {
    sfxHandle_t prebuildSound = cgs.media.humanBuildablePrebuild;

    if( team == BIT_HUMANS )
    {
      ent.customShader = cgs.media.humanSpawningShader;
      prebuildSound = cgs.media.humanBuildablePrebuild;
    }
    else if( team == BIT_ALIENS )
      prebuildSound = cgs.media.alienBuildablePrebuild;

    //trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, prebuildSound, 0 );
  }

  CG_BuildableAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp );

  //rescale the model
  scale = BG_FindModelScaleForBuildable( es->modelindex );

  if( scale != 1.0f )
  {
    VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] );
    VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] );
    VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] );

    ent.nonNormalizedAxes = qtrue;
  }
  else
    ent.nonNormalizedAxes = qfalse;


  //add to refresh list
  trap_R_AddRefEntityToScene( &ent );

  CrossProduct( surfNormal, refNormal, xNormal );
  VectorNormalize( xNormal );
  rotAngle = RAD2DEG( acos( DotProduct( surfNormal, refNormal ) ) );

  //turret barrel bit
  if( cg_buildables[ es->modelindex ].models[ 1 ] )
  {
    refEntity_t turretBarrel;
    vec3_t      flatAxis[ 3 ];

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

    turretBarrel.hModel = cg_buildables[ es->modelindex ].models[ 1 ];

    CG_PositionEntityOnTag( &turretBarrel, &ent, ent.hModel, "tag_turret" );
    VectorCopy( cent->lerpOrigin, turretBarrel.lightingOrigin );
    AnglesToAxis( es->angles2, flatAxis );

    RotatePointAroundVector( turretBarrel.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle );
    RotatePointAroundVector( turretBarrel.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle );
    RotatePointAroundVector( turretBarrel.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle );

    turretBarrel.oldframe = ent.oldframe;
    turretBarrel.frame    = ent.frame;
    turretBarrel.backlerp = ent.backlerp;

    turretBarrel.customShader = ent.customShader;

    if( scale != 1.0f )
    {
      VectorScale( turretBarrel.axis[ 0 ], scale, turretBarrel.axis[ 0 ] );
      VectorScale( turretBarrel.axis[ 1 ], scale, turretBarrel.axis[ 1 ] );
      VectorScale( turretBarrel.axis[ 2 ], scale, turretBarrel.axis[ 2 ] );

      turretBarrel.nonNormalizedAxes = qtrue;
    }
    else
      turretBarrel.nonNormalizedAxes = qfalse;

    trap_R_AddRefEntityToScene( &turretBarrel );
  }

  //turret barrel bit
  if( cg_buildables[ es->modelindex ].models[ 2 ] )
  {
    refEntity_t turretTop;
    vec3_t      flatAxis[ 3 ];
    vec3_t      swivelAngles;

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

    VectorCopy( es->angles2, swivelAngles );
    swivelAngles[ PITCH ] = 0.0f;

    turretTop.hModel = cg_buildables[ es->modelindex ].models[ 2 ];

    CG_PositionRotatedEntityOnTag( &turretTop, &ent, ent.hModel, "tag_turret" );
    VectorCopy( cent->lerpOrigin, turretTop.lightingOrigin );
    AnglesToAxis( swivelAngles, flatAxis );

    RotatePointAroundVector( turretTop.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle );
    RotatePointAroundVector( turretTop.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle );
    RotatePointAroundVector( turretTop.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle );

    turretTop.oldframe = ent.oldframe;
    turretTop.frame    = ent.frame;
    turretTop.backlerp = ent.backlerp;

    turretTop.customShader = ent.customShader;

    if( scale != 1.0f )
    {
      VectorScale( turretTop.axis[ 0 ], scale, turretTop.axis[ 0 ] );
      VectorScale( turretTop.axis[ 1 ], scale, turretTop.axis[ 1 ] );
      VectorScale( turretTop.axis[ 2 ], scale, turretTop.axis[ 2 ] );

      turretTop.nonNormalizedAxes = qtrue;
    }
    else
      turretTop.nonNormalizedAxes = qfalse;

    trap_R_AddRefEntityToScene( &turretTop );
  }

  switch( cg.predictedPlayerState.weapon )
  {
    case WP_ABUILD:
    case WP_ABUILD2:
    case WP_HBUILD:
    case WP_HBUILD2:
      if( BG_FindTeamForBuildable( es->modelindex ) ==
          BG_FindTeamForWeapon( cg.predictedPlayerState.weapon ) )
        CG_BuildableHealthBar( cent );
      break;

    default:
      break;
  }

  //weapon effects for turrets
  if( es->eFlags & EF_FIRING )
  {
    weaponInfo_t  *weapon = &cg_weapons[ es->weapon ];

    if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME ||
        BG_FindProjTypeForBuildable( es->modelindex ) == WP_TESLAGEN )
    {
      if( weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ] ||
          weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ] ||
          weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] )
      {
		trap_R_AddLightToScene( cent->lerpOrigin, 320, 1.25 + (rand() & 31) / 128, 
            weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ],
            weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ],
            weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ], 
			0, 
			0 );
      }
    }

    if( weapon->wim[ WPM_PRIMARY ].firingSound )
    {
      /*trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin,
          weapon->wim[ WPM_PRIMARY ].firingSound, 0 );*/
    }
    else if( weapon->readySound ) {
      //trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound, 0 );
	}
  }

  health = es->generic1 & ~( B_POWERED_TOGGLEBIT | B_DCCED_TOGGLEBIT | B_SPAWNED_TOGGLEBIT );
  healthScale = (float)health / B_HEALTH_SCALE;

  if( healthScale < cent->lastBuildableHealthScale && ( es->generic1 & B_SPAWNED_TOGGLEBIT ) )
  {
    if( cent->lastBuildableDamageSoundTime + BUILDABLE_SOUND_PERIOD < cg.time )
    {
      if( team == BIT_HUMANS )
      {
        int i = rand( ) % 4;
        trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.humanBuildableDamage[ i ] );
      }
      else if( team == BIT_ALIENS )
        trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienBuildableDamage );

      cent->lastBuildableDamageSoundTime = cg.time;
    }
  }

  cent->lastBuildableHealthScale = healthScale;

  //smoke etc for damaged buildables
  CG_BuildableParticleEffects( cent );
}
示例#14
0
/*
==================
CG_Buildable
==================
*/
void CG_Buildable( centity_t *cent )
{
  refEntity_t     ent;
  entityState_t   *es = &cent->currentState;
  vec3_t          angles;
  vec3_t          surfNormal, xNormal, mins, maxs;
  vec3_t          refNormal = { 0.0f, 0.0f, 1.0f };
  float           rotAngle;
  team_t          team = BG_Buildable( es->modelindex )->team;
  float           scale;
  int             health;

  //must be before EF_NODRAW check
  if( team == TEAM_ALIENS )
    CG_Creep( cent );

  // if set to invisible, skip
  if( es->eFlags & EF_NODRAW )
  {
    if( CG_IsParticleSystemValid( &cent->buildablePS ) )
      CG_DestroyParticleSystem( &cent->buildablePS );

    return;
  }

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

  VectorCopy( cent->lerpOrigin, ent.origin );
  VectorCopy( cent->lerpOrigin, ent.oldorigin );
  VectorCopy( cent->lerpOrigin, ent.lightingOrigin );

  VectorCopy( es->origin2, surfNormal );

  VectorCopy( es->angles, angles );
  BG_BuildableBoundingBox( es->modelindex, mins, maxs );

  if( es->pos.trType == TR_STATIONARY )
  {
    // Positioning a buildable involves potentially up to two traces, and
    // seeing as buildables rarely move, we cache the results and recalculate
    // only if the buildable moves or changes orientation
    if( VectorCompare( cent->buildableCache.cachedOrigin, cent->lerpOrigin ) &&
        VectorCompare( cent->buildableCache.cachedNormal, surfNormal ) )
    {
      VectorCopy( cent->buildableCache.axis[ 0 ], ent.axis[ 0 ] );
      VectorCopy( cent->buildableCache.axis[ 1 ], ent.axis[ 1 ] );
      VectorCopy( cent->buildableCache.axis[ 2 ], ent.axis[ 2 ] );
      VectorCopy( cent->buildableCache.origin, ent.origin );
    }
    else
    {
      CG_PositionAndOrientateBuildable( angles, ent.origin, surfNormal,
                                        es->number, mins, maxs, ent.axis,
                                        ent.origin );
      VectorCopy( ent.axis[ 0 ], cent->buildableCache.axis[ 0 ] );
      VectorCopy( ent.axis[ 1 ], cent->buildableCache.axis[ 1 ] );
      VectorCopy( ent.axis[ 2 ], cent->buildableCache.axis[ 2 ] );
      VectorCopy( ent.origin, cent->buildableCache.origin );
      VectorCopy( cent->lerpOrigin, cent->buildableCache.cachedOrigin );
      VectorCopy( surfNormal, cent->buildableCache.cachedNormal );
    }
  }

  //offset on the Z axis if required
  VectorMA( ent.origin, BG_BuildableConfig( es->modelindex )->zOffset, surfNormal, ent.origin );

  VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all
  VectorCopy( ent.origin, ent.lightingOrigin );

  ent.hModel = cg_buildables[ es->modelindex ].models[ 0 ];

  if( !( es->eFlags & EF_B_SPAWNED ) )
  {
    sfxHandle_t prebuildSound = cgs.media.humanBuildablePrebuild;

    if( team == TEAM_HUMANS )
    {
      ent.customShader = cgs.media.humanSpawningShader;
      prebuildSound = cgs.media.humanBuildablePrebuild;
    }
    else if( team == TEAM_ALIENS )
      prebuildSound = cgs.media.alienBuildablePrebuild;

    trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, prebuildSound );
  }

  CG_BuildableAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp );

  //rescale the model
  scale = BG_BuildableConfig( es->modelindex )->modelScale;

  if( scale != 1.0f )
  {
    VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] );
    VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] );
    VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] );

    ent.nonNormalizedAxes = qtrue;
  }
  else
    ent.nonNormalizedAxes = qfalse;

  if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) )
    ent.customShader = cgs.media.redBuildShader;

  //add to refresh list
  trap_R_AddRefEntityToScene( &ent );

  CrossProduct( surfNormal, refNormal, xNormal );
  VectorNormalize( xNormal );
  rotAngle = RAD2DEG( acos( DotProduct( surfNormal, refNormal ) ) );

  //turret barrel bit
  if( cg_buildables[ es->modelindex ].models[ 1 ] )
  {
    refEntity_t turretBarrel;
    vec3_t      flatAxis[ 3 ];

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

    turretBarrel.hModel = cg_buildables[ es->modelindex ].models[ 1 ];

    CG_PositionEntityOnTag( &turretBarrel, &ent, ent.hModel, "tag_turret" );
    VectorCopy( cent->lerpOrigin, turretBarrel.lightingOrigin );
    AnglesToAxis( es->angles2, flatAxis );

    RotatePointAroundVector( turretBarrel.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle );
    RotatePointAroundVector( turretBarrel.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle );
    RotatePointAroundVector( turretBarrel.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle );

    turretBarrel.oldframe = ent.oldframe;
    turretBarrel.frame    = ent.frame;
    turretBarrel.backlerp = ent.backlerp;

    turretBarrel.customShader = ent.customShader;

    if( scale != 1.0f )
    {
      VectorScale( turretBarrel.axis[ 0 ], scale, turretBarrel.axis[ 0 ] );
      VectorScale( turretBarrel.axis[ 1 ], scale, turretBarrel.axis[ 1 ] );
      VectorScale( turretBarrel.axis[ 2 ], scale, turretBarrel.axis[ 2 ] );

      turretBarrel.nonNormalizedAxes = qtrue;
    }
    else
      turretBarrel.nonNormalizedAxes = qfalse;

    if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) )
      turretBarrel.customShader = cgs.media.redBuildShader;

    trap_R_AddRefEntityToScene( &turretBarrel );
  }

  //turret barrel bit
  if( cg_buildables[ es->modelindex ].models[ 2 ] )
  {
    refEntity_t turretTop;
    vec3_t      flatAxis[ 3 ];
    vec3_t      swivelAngles;

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

    VectorCopy( es->angles2, swivelAngles );
    swivelAngles[ PITCH ] = 0.0f;

    turretTop.hModel = cg_buildables[ es->modelindex ].models[ 2 ];

    CG_PositionRotatedEntityOnTag( &turretTop, &ent, ent.hModel, "tag_turret" );
    VectorCopy( cent->lerpOrigin, turretTop.lightingOrigin );
    AnglesToAxis( swivelAngles, flatAxis );

    RotatePointAroundVector( turretTop.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle );
    RotatePointAroundVector( turretTop.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle );
    RotatePointAroundVector( turretTop.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle );

    turretTop.oldframe = ent.oldframe;
    turretTop.frame    = ent.frame;
    turretTop.backlerp = ent.backlerp;

    turretTop.customShader = ent.customShader;

    if( scale != 1.0f )
    {
      VectorScale( turretTop.axis[ 0 ], scale, turretTop.axis[ 0 ] );
      VectorScale( turretTop.axis[ 1 ], scale, turretTop.axis[ 1 ] );
      VectorScale( turretTop.axis[ 2 ], scale, turretTop.axis[ 2 ] );

      turretTop.nonNormalizedAxes = qtrue;
    }
    else
      turretTop.nonNormalizedAxes = qfalse;

    if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) )
      turretTop.customShader = cgs.media.redBuildShader;

    trap_R_AddRefEntityToScene( &turretTop );
  }

  //weapon effects for turrets
  if( es->eFlags & EF_FIRING )
  {
    weaponInfo_t  *weapon = &cg_weapons[ es->weapon ];

    if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME ||
        BG_Buildable( es->modelindex )->turretProjType == WP_TESLAGEN )
    {
      if( weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ] ||
          weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ] ||
          weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] )
      {
        trap_R_AddLightToScene( cent->lerpOrigin, 300 + ( rand( ) & 31 ),
            weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ],
            weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ],
            weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] );
      }
    }

    if( weapon->wim[ WPM_PRIMARY ].firingSound )
    {
      trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin,
          weapon->wim[ WPM_PRIMARY ].firingSound );
    }
    else if( weapon->readySound )
      trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound );
  }

  health = es->generic1;

  if( health < cent->lastBuildableHealth &&
      ( es->eFlags & EF_B_SPAWNED ) )
  {
    if( cent->lastBuildableDamageSoundTime + BUILDABLE_SOUND_PERIOD < cg.time )
    {
      if( team == TEAM_HUMANS )
      {
        int i = rand( ) % 4;
        trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.humanBuildableDamage[ i ] );
      }
      else if( team == TEAM_ALIENS )
        trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienBuildableDamage );

      cent->lastBuildableDamageSoundTime = cg.time;
    }
  }

  cent->lastBuildableHealth = health;

  //smoke etc for damaged buildables
  CG_BuildableParticleEffects( cent );
}
示例#15
0
void CG_Spotlight( centity_t *cent, float *color, vec3_t realstart, vec3_t lightDir, int segs, float range, int startWidth, float coneAngle, int flags ) {
	int i, j;
	vec3_t start, traceEnd, proj;
	vec3_t right, up;
	vec3_t v1, v2;
	vec3_t startvec, endvec;        // the vectors to rotate around lightDir to create the circles
	vec3_t conevec;
	vec3_t start_points[MAX_SPOT_SEGS], end_points[MAX_SPOT_SEGS];
	vec3_t coreright;
	polyVert_t verts[MAX_SPOT_SEGS * 4]; // x4 for 4 verts per poly
	polyVert_t plugVerts[MAX_SPOT_SEGS];
	vec3_t endCenter;
	polyVert_t coreverts[4];
	trace_t tr;
	float alpha;
	float radius = 0.0; // TTimo might be used uninitialized
	float coreEndRadius;
	qboolean capStart = qtrue;
	float hitDist;          // the actual distance of the trace impact	(0 is no hit)
	float beamLen;          // actual distance of the drawn beam
	float endAlpha    = 0.0;
	vec4_t colorNorm;       // normalized color vector
	refEntity_t ent;
	vec3_t angles;

	VectorCopy( realstart, start );

	// normalize color
	colorNorm[3] = 0;   // store normalize multiplier in alpha index
	for ( i = 0; i < 3; i++ ) {
		if ( color[i] > colorNorm[3] ) {
			colorNorm[3] = color[i];    // find largest color value in RGB
		}
	}

	if ( colorNorm[3] != 1 ) {     // it needs to be boosted
		VectorMA( color, 1.0 / colorNorm[3], color, colorNorm );    // FIXME: div by 0
	} else {
		VectorCopy( color, colorNorm );
	}
	colorNorm[3] = color[3];


	if ( flags & SL_NOSTARTCAP ) {
		capStart = qfalse;
	}

	if ( startWidth == 0 ) {   // cone, not cylinder
		capStart = qfalse;
	}

	if ( flags & SL_LOCKTRACETORANGE ) {
		VectorMA( start, range, lightDir, traceEnd );           // trace out to 'range'
	} else {
		VectorMA( start, MAX_SPOT_RANGE, lightDir, traceEnd );  // trace all the way out to max dist
	}

	// first trace to see if anything is hit
	if ( flags & SL_NOTRACE ) {
		tr.fraction = 1.0;  // force no hit
	} else {
		if ( flags & SL_TRACEWORLDONLY ) {
			CG_Trace( &tr, start, NULL, NULL, traceEnd, -1, CONTENTS_SOLID );
		} else {
			CG_Trace( &tr, start, NULL, NULL, traceEnd, -1, MASK_SHOT );
		}
//		CG_Trace( &tr, start, NULL, NULL, traceEnd, -1, MASK_ALL &~(CONTENTS_MONSTERCLIP|CONTENTS_AREAPORTAL|CONTENTS_CLUSTERPORTAL));
	}


	if ( tr.fraction < 1.0 ) {
		hitDist = beamLen = MAX_SPOT_RANGE * tr.fraction;
		if ( beamLen > range ) {
			beamLen = range;
		}
	} else {
		hitDist = 0;
		beamLen = range;
	}


	if ( flags & SL_LOCKUV ) {
		if ( beamLen < range ) {
			endAlpha = 255.0f * ( color[3] - ( color[3] * beamLen / range ) );
		}
	}


	if ( segs >= MAX_SPOT_SEGS ) {
		segs = MAX_SPOT_SEGS - 1;
	}

	// TODO: adjust segs based on r_lodbias
	// TODO: move much of this to renderer


// model at base
	if ( cent->currentState.modelindex ) {
		memset( &ent, 0, sizeof( ent ) );
		ent.frame = 0;
		ent.oldframe = 0;
		ent.backlerp = 0;
		VectorCopy( cent->lerpOrigin, ent.origin );
		VectorCopy( cent->lerpOrigin, ent.oldorigin );
		ent.hModel = cgs.gameModels[cent->currentState.modelindex];
		//	AnglesToAxis( cent->lerpAngles, ent.axis );
		vectoangles( lightDir, angles );
		AnglesToAxis( angles, ent.axis );
		trap_R_AddRefEntityToScene( &ent );
		memcpy( &cent->refEnt, &ent, sizeof( refEntity_t ) );

		// push start out a bit so the beam fits to the front of the base model
		VectorMA( start, 14, lightDir, start );
	}

//// BEAM

	PerpendicularVector( up, lightDir );
	CrossProduct( lightDir, up, right );

	// find first vert of the start
	VectorScale( right, startWidth, startvec );
	// find the first vert of the end
	RotatePointAroundVector( conevec, up, lightDir, -coneAngle );
	VectorMA( startvec, beamLen, conevec, endvec );   // this applies the offset of the start diameter before finding the end points

	VectorScale( lightDir, beamLen, endCenter );
	VectorSubtract( endCenter, endvec, coreverts[3].xyz );    // get a vector of the radius out at the end for the core to use
	coreEndRadius = VectorLength( coreverts[3].xyz );
#define CORESCALE 0.6f

//
//	generate the flat beam 'core'
//
	if ( !( flags & SL_NOCORE ) ) {
		VectorSubtract( start, cg.refdef.vieworg, v1 );
		VectorNormalize( v1 );
		VectorSubtract( traceEnd, cg.refdef.vieworg, v2 );
		VectorNormalize( v2 );
		CrossProduct( v1, v2, coreright );
		VectorNormalize( coreright );

		memset( &coreverts[0], 0, 4 * sizeof( polyVert_t ) );
		VectorMA( start, startWidth * 0.5f, coreright, coreverts[0].xyz );
		VectorMA( start, -startWidth * 0.5f, coreright, coreverts[1].xyz );
		VectorMA( endCenter, -coreEndRadius * CORESCALE, coreright, coreverts[2].xyz );
		VectorAdd( start, coreverts[2].xyz, coreverts[2].xyz );
		VectorMA( endCenter, coreEndRadius * CORESCALE, coreright, coreverts[3].xyz );
		VectorAdd( start, coreverts[3].xyz, coreverts[3].xyz );

		for ( i = 0; i < 4; i++ ) {
			coreverts[i].modulate[0] = color[0] * 200.0f;
			coreverts[i].modulate[1] = color[1] * 200.0f;
			coreverts[i].modulate[2] = color[2] * 200.0f;
			coreverts[i].modulate[3] = color[3] * 200.0f;
			if ( i > 1 ) {
				coreverts[i].modulate[3] = 0;
			}
		}

		trap_R_AddPolyToScene( cgs.media.spotLightBeamShader, 4, &coreverts[0] );
	}


//
// generate the beam cylinder
//



	for ( i = 0; i <= segs; i++ ) {
		RotatePointAroundVector( start_points[i], lightDir, startvec, ( 360.0f / (float)segs ) * i );
		VectorAdd( start_points[i], start, start_points[i] );

		RotatePointAroundVector( end_points[i], lightDir, endvec, ( 360.0f / (float)segs ) * i );
		VectorAdd( end_points[i], start, end_points[i] );
	}

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

		j = ( i * 4 );

		VectorCopy( start_points[i], verts[( i * 4 )].xyz );
		verts[j].st[0]  = 0;
		verts[j].st[1]  = 1;
		verts[j].modulate[0] = color[0] * 255.0f;
		verts[j].modulate[1] = color[1] * 255.0f;
		verts[j].modulate[2] = color[2] * 255.0f;
		verts[j].modulate[3] = color[3] * 255.0f;
		j++;

		VectorCopy( end_points[i], verts[j].xyz );
		verts[j].st[0]  = 0;
		verts[j].st[1]  = 0;
		verts[j].modulate[0] = color[0] * 255.0f;
		verts[j].modulate[1] = color[1] * 255.0f;
		verts[j].modulate[2] = color[2] * 255.0f;
		verts[j].modulate[3] = endAlpha;
		j++;

		VectorCopy( end_points[i + 1], verts[j].xyz );
		verts[j].st[0]  = 1;
		verts[j].st[1]  = 0;
		verts[j].modulate[0] = color[0] * 255.0f;
		verts[j].modulate[1] = color[1] * 255.0f;
		verts[j].modulate[2] = color[2] * 255.0f;
		verts[j].modulate[3] = endAlpha;
		j++;

		VectorCopy( start_points[i + 1], verts[j].xyz );
		verts[j].st[0]  = 1;
		verts[j].st[1]  = 1;
		verts[j].modulate[0] = color[0] * 255.0f;
		verts[j].modulate[1] = color[1] * 255.0f;
		verts[j].modulate[2] = color[2] * 255.0f;
		verts[j].modulate[3] = color[3] * 255.0f;

		if ( capStart ) {
			VectorCopy( start_points[i], plugVerts[i].xyz );
			plugVerts[i].st[0]  = 0;
			plugVerts[i].st[1]  = 0;
			plugVerts[i].modulate[0] = color[0] * 255.0f;
			plugVerts[i].modulate[1] = color[1] * 255.0f;
			plugVerts[i].modulate[2] = color[2] * 255.0f;
			plugVerts[i].modulate[3] = color[3] * 255.0f;
		}
	}

	trap_R_AddPolysToScene( cgs.media.spotLightBeamShader, 4, &verts[0], segs );


	// plug up the start circle
	if ( capStart ) {
		trap_R_AddPolyToScene( cgs.media.spotLightBeamShader, segs, &plugVerts[0] );
	}


	// show the endpoint

	if ( !( flags & SL_NOIMPACT ) ) {
		if ( hitDist ) {
			VectorMA( startvec, hitDist, conevec, endvec );

			alpha = 0.3f;
			radius = coreEndRadius * ( hitDist / beamLen );

			VectorNegate( lightDir, proj );
			CG_ImpactMark( cgs.media.spotLightShader, tr.endpos, proj, 0, colorNorm[0], colorNorm[1], colorNorm[2], alpha, qfalse, radius, qtrue, -1 );
		}
	}



	// add d light at end
	if ( !( flags & SL_NODLIGHT ) ) {
		vec3_t dlightLoc;
//		VectorMA(tr.endpos, -60, lightDir, dlightLoc);	// back away from the hit
//		trap_R_AddLightToScene(dlightLoc, 200, colorNorm[0], colorNorm[1], colorNorm[2], 0);	// ,REF_JUNIOR_DLIGHT);
		VectorMA( tr.endpos, 0, lightDir, dlightLoc );    // back away from the hit
//		trap_R_AddLightToScene(dlightLoc, radius*2, colorNorm[0], colorNorm[1], colorNorm[2], 0);	// ,REF_JUNIOR_DLIGHT);
		trap_R_AddLightToScene( dlightLoc, radius * 2, 0.3, 0.3, 0.3, 0 );  // ,REF_JUNIOR_DLIGHT);
	}



	// draw flare at source
	if ( !( flags & SL_NOFLARE ) ) {
		qboolean lightInEyes = qfalse;
		vec3_t camloc, dirtolight;
		float dot, deg, dist;
		float flarescale = 0.0;       // TTimo: might be used uninitialized

		// get camera position and direction to lightsource
		VectorCopy( cg.snap->ps.origin, camloc );
		camloc[2] += cg.snap->ps.viewheight;
		VectorSubtract( start, camloc, dirtolight );
		dist = VectorNormalize( dirtolight );

		// first use dot to determine if it's facing the camera
		dot = DotProduct( lightDir, dirtolight );

		// it's facing the camera, find out how closely and trace to see if the source can be seen

		deg = RAD2DEG( M_PI - acos( dot ) );
		if ( deg <= 35 ) { // start flare a bit before the camera gets inside the cylinder
			lightInEyes = qtrue;
			flarescale = 1 - ( deg / 35 );
		}

		if ( lightInEyes ) {   // the dot check succeeded, now do a trace
			CG_Trace( &tr, start, NULL, NULL, camloc, -1, MASK_ALL & ~( CONTENTS_MONSTERCLIP | CONTENTS_AREAPORTAL | CONTENTS_CLUSTERPORTAL ) );
			if ( tr.fraction != 1 ) {
				lightInEyes = qfalse;
			}

		}

		if ( lightInEyes ) {
			float coronasize = flarescale;
			if ( dist < 512 ) { // make even bigger if you're close enough
				coronasize *= ( 512.0f / dist );
			}

			trap_R_AddCoronaToScene( start, colorNorm[0], colorNorm[1], colorNorm[2], coronasize, cent->currentState.number, qtrue );
		} else {
			// even though it's off, still need to add it, but turned off so it can fade in/out properly
			trap_R_AddCoronaToScene( start, colorNorm[0], colorNorm[1], colorNorm[2], 0, cent->currentState.number, qfalse );
		}
	}

}
示例#16
0
/*
===============
CG_GroundVehicle
===============
*/
void CG_LQM( centity_t *cent, clientInfo_t *ci ) 
{
	vec3_t			velocity;	
	vec3_t		    right, up, temp, start;
	DrawInfo_LQM_t drawInfo;
	int				ONOFF = cent->currentState.ONOFF;


	memset( &drawInfo, 0, sizeof(drawInfo) );
	drawInfo.basicInfo.vehicleIndex = ci->vehicle;
	drawInfo.basicInfo.ONOFF = ONOFF;

	// Copy Weapon Index
	drawInfo.weaponIndex = cent->currentState.weaponIndex;

	// Copy animation state
	drawInfo.anim = cent->currentState.vehicleAnim;

	// Copy animation frames
	drawInfo.lastTorsoAngle = cent->bayAnim;
	drawInfo.lastLegsAngle = cent->gearAnim;
	drawInfo.torsoFrame = cent->bayAnimFrame;
	drawInfo.legsFrame = cent->gearAnimFrame;
	drawInfo.torsoTime = cent->bayAnimStartTime;
	drawInfo.legsTime = cent->gearAnimStartTime;

	// get speed
	VectorCopy( cent->currentState.pos.trDelta, velocity );
	drawInfo.basicInfo.speed = VectorLength( velocity );
	
	// entitynum
	drawInfo.basicInfo.entityNum = cent->currentState.number;

    // get the rotation information
    VectorCopy( cent->currentState.angles, cent->lerpAngles );
    AnglesToAxis( cent->lerpAngles, drawInfo.basicInfo.axis );

	// position and orientation
	VectorCopy( cent->lerpOrigin, drawInfo.basicInfo.origin );
	VectorCopy( cent->lerpAngles, drawInfo.basicInfo.angles );

	// throttle
	drawInfo.basicInfo.throttle = cent->currentState.frame;

	// loadout
	drawInfo.basicInfo.usedLoadout = 0;//&cg_loadouts[cent->currentState.number];

	// muzzleflash
	if( cg.time - cent->muzzleFlashTime <= MUZZLE_FLASH_TIME ) {
		drawInfo.basicInfo.drawMuzzleFlash = true;
		drawInfo.basicInfo.flashWeaponIndex = cent->muzzleFlashWeapon;
	}

	// draw lqm
	CG_DrawLQM(&drawInfo);

	// return frames
	cent->bayAnim = drawInfo.lastTorsoAngle;
	cent->gearAnim = drawInfo.lastLegsAngle;
	cent->bayAnimFrame = drawInfo.torsoFrame;
	cent->bayAnimStartTime = drawInfo.torsoTime;
	cent->gearAnimFrame = drawInfo.legsFrame;
	cent->gearAnimStartTime = drawInfo.legsTime;
	

	// flags
	CG_LQMFlags( cent );


	// reticles
	if( cent == &cg.predictedPlayerEntity )
	{
		refEntity_t		reticle;
		vec3_t	forward, ang, end;
		trace_t	tr;
//		playerState_t * ps = &cg.snap->ps;
		float len;
		float mindist = cg_thirdPersonRange.integer + availableVehicles[ci->vehicle].cam_dist[ CAMERA_V_DEFAULT ] + availableVehicles[ci->vehicle].maxs[0] + 20;

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

		CG_ResetReticles();

		reticle.customShader = availableWeapons[availableVehicles[ci->vehicle].weapons[cent->currentState.weaponNum]].crosshair;
		reticle.hModel = cgs.media.reticle[availableWeapons[availableVehicles[ci->vehicle].weapons[cent->currentState.weaponNum]].crosshair];

		AngleVectors( cent->currentState.angles, forward, right, up );
		RotatePointAroundVector( temp, up, forward, cent->currentState.angles2[ROLL] );
		CrossProduct( up, temp, right );
		RotatePointAroundVector( forward, right, temp, cent->currentState.angles2[PITCH] );
		VectorMA( cent->lerpOrigin, availableVehicles[ci->vehicle].gunoffset[0], forward, start );
		VectorMA( start, availableVehicles[ci->vehicle].gunoffset[1], right, start );
		VectorMA( start, availableVehicles[ci->vehicle].gunoffset[2], up, start );
		VectorMA( start, 2000, forward, end );
		vectoangles( forward, ang );
		ang[2] = 0;
		AnglesToAxis( ang, reticle.axis );
		CG_Trace( &tr, start, 0, 0, end, cg.snap->ps.clientNum, MASK_SOLID ); 

		if( tr.entityNum < MAX_CLIENTS )
		{
			cg.crosshairClientNum = tr.entityNum;
			cg.crosshairClientTime = cg.time;
		}

		VectorCopy( tr.endpos, end );
		CG_Trace( &tr, cg.refdef.vieworg, 0, 0, end, cg.snap->ps.clientNum, MASK_SOLID ); 
		VectorSubtract( tr.endpos, cg.refdef.vieworg, forward );
		len = VectorNormalize(forward);
		
		if( len > mindist )
		{
			VectorMA( cg.refdef.vieworg, mindist, forward, reticle.origin );
		}
		else
		{
			VectorMA( cg.refdef.vieworg, len - 5, forward, reticle.origin );
		}

		VectorCopy( reticle.origin, reticle.lightingOrigin );
		reticle.renderfx = RF_LIGHTING_ORIGIN|RF_SHADOW_PLANE;
		
		CG_AddReticleEntityToScene( &reticle, NULL );
	}
}
示例#17
0
/*
==================
CG_LaunchGib
==================
*/
void CG_LaunchGib( centity_t *cent, vec3_t origin, vec3_t angles, vec3_t velocity, qhandle_t hModel, float sizeScale, int breakCount ) {
	localEntity_t   *le;
	refEntity_t     *re;
	int i;

	if ( !cg_blood.integer ) {
		return;
	}

	le = CG_AllocLocalEntity();
	re = &le->refEntity;

	le->leType = LE_FRAGMENT;
	le->startTime = cg.time;
	// le->endTime = le->startTime + 60000 + random() * 60000;
	le->endTime = le->startTime + 20000 + ( crandom() * 5000 );
	le->breakCount = breakCount;
	le->sizeScale = sizeScale;

	VectorCopy( angles, le->angles.trBase );
	VectorCopy( origin, re->origin );
	AnglesToAxis( angles, re->axis );
	if ( sizeScale != 1.0 ) {
		for ( i = 0; i < 3; i++ ) VectorScale( re->axis[i], sizeScale, re->axis[i] );
	}
	re->hModel = hModel;

	// re->fadeStartTime		= le->endTime - 3000;
	re->fadeStartTime       = le->endTime - 1000;
	re->fadeEndTime         = le->endTime;

	switch ( cent->currentState.aiChar ) {
	case AICHAR_ZOMBIE:
		le->pos.trType = TR_GRAVITY_LOW;
		le->angles.trDelta[0] = 400 * crandom();
		le->angles.trDelta[1] = 400 * crandom();
		le->angles.trDelta[2] = 400 * crandom();

		le->leBounceSoundType = LEBS_BONE;

		le->bounceFactor = 0.5;
		break;
	default:
		le->leBounceSoundType = LEBS_BLOOD;
		le->leMarkType = LEMT_BLOOD;
		le->pos.trType = TR_GRAVITY;

		le->angles.trDelta[0] = ( 10 + ( rand() & 50 ) ) - 30;
		//	le->angles.trDelta[0] = (100 + (rand()&500)) - 300;	// pitch
		le->angles.trDelta[1] = ( 100 + ( rand() & 500 ) ) - 300; // (SA) this is the safe one right now (yaw)  turn the others up when I have tumbling things landing properly
		le->angles.trDelta[2] = ( 10 + ( rand() & 50 ) ) - 30;
		//	le->angles.trDelta[2] = (100 + (rand()&500)) - 300;	// roll

		le->bounceFactor = 0.3;
		break;
	}
	VectorCopy( origin, le->pos.trBase );
	VectorCopy( velocity, le->pos.trDelta );
	le->pos.trTime = cg.time;


	le->angles.trType = TR_LINEAR;

	le->angles.trTime = cg.time;

	le->ownerNum = cent->currentState.number;

	// Ridah, if the player is on fire, then spawn some flaming gibs
	if ( cent && CG_EntOnFire( cent ) ) {
		le->onFireStart = cent->currentState.onFireStart;
		le->onFireEnd = re->fadeEndTime + 1000;
	} else if ( ( cent->currentState.aiChar == AICHAR_ZOMBIE ) && IS_FLAMING_ZOMBIE( cent->currentState ) ) {
		le->onFireStart = cg.time - 1000;
		le->onFireEnd = re->fadeEndTime + 1000;
	}
}
示例#18
0
/*
==============
R_CalcBone
==============
*/
void R_CalcBone(mdsHeader_t *header, const refEntity_t *refent, int boneNum)
{
	thisBoneInfo = &boneInfo[boneNum];
	if (thisBoneInfo->torsoWeight)
	{
		cTBonePtr = &cBoneListTorso[boneNum];
		isTorso   = qtrue;
		if (thisBoneInfo->torsoWeight == 1.0f)
		{
			fullTorso = qtrue;
		}
	}
	else
	{
		isTorso   = qfalse;
		fullTorso = qfalse;
	}
	cBonePtr = &cBoneList[boneNum];

	bonePtr = &bones[boneNum];

	// we can assume the parent has already been uncompressed for this frame + lerp
	if (thisBoneInfo->parent >= 0)
	{
		parentBone     = &bones[thisBoneInfo->parent];
		parentBoneInfo = &boneInfo[thisBoneInfo->parent];
	}
	else
	{
		parentBone     = NULL;
		parentBoneInfo = NULL;
	}

#ifdef HIGH_PRECISION_BONES
	// rotation
	if (fullTorso)
	{
		VectorCopy(cTBonePtr->angles, angles);
	}
	else
	{
		VectorCopy(cBonePtr->angles, angles);
		if (isTorso)
		{
			VectorCopy(cTBonePtr->angles, tangles);
			// blend the angles together
			for (j = 0; j < 3; j++)
			{
				diff = tangles[j] - angles[j];
				if (Q_fabs(diff) > 180)
				{
					diff = AngleNormalize180(diff);
				}
				angles[j] = angles[j] + thisBoneInfo->torsoWeight * diff;
			}
		}
	}
#else
	// rotation
	if (fullTorso)
	{
		sh = (short *)cTBonePtr->angles;
		pf = angles;
		ANGLES_SHORT_TO_FLOAT(pf, sh);
	}
	else
	{
		sh = (short *)cBonePtr->angles;
		pf = angles;
		ANGLES_SHORT_TO_FLOAT(pf, sh);
		if (isTorso)
		{
			int j;

			sh = (short *)cTBonePtr->angles;
			pf = tangles;
			ANGLES_SHORT_TO_FLOAT(pf, sh);
			// blend the angles together
			for (j = 0; j < 3; j++)
			{
				diff = tangles[j] - angles[j];
				if (Q_fabs(diff) > 180)
				{
					diff = AngleNormalize180(diff);
				}
				angles[j] = angles[j] + thisBoneInfo->torsoWeight * diff;
			}
		}
	}
#endif
	AnglesToAxis(angles, bonePtr->matrix);

	// translation
	if (parentBone)
	{

#ifdef HIGH_PRECISION_BONES
		if (fullTorso)
		{
			angles[0] = cTBonePtr->ofsAngles[0];
			angles[1] = cTBonePtr->ofsAngles[1];
			angles[2] = 0;
			LocalAngleVector(angles, vec);
			LocalVectorMA(parentBone->translation, thisBoneInfo->parentDist, vec, bonePtr->translation);
		}
		else
		{
			angles[0] = cBonePtr->ofsAngles[0];
			angles[1] = cBonePtr->ofsAngles[1];
			angles[2] = 0;
			LocalAngleVector(angles, vec);

			if (isTorso)
			{
				tangles[0] = cTBonePtr->ofsAngles[0];
				tangles[1] = cTBonePtr->ofsAngles[1];
				tangles[2] = 0;
				LocalAngleVector(tangles, v2);

				// blend the angles together
				SLerp_Normal(vec, v2, thisBoneInfo->torsoWeight, vec);
				LocalVectorMA(parentBone->translation, thisBoneInfo->parentDist, vec, bonePtr->translation);

			}
			else        // legs bone
			{
				LocalVectorMA(parentBone->translation, thisBoneInfo->parentDist, vec, bonePtr->translation);
			}
		}
#else
		if (fullTorso)
		{
			sh      = (short *)cTBonePtr->ofsAngles; pf = angles;
			*(pf++) = SHORT2ANGLE(*(sh++)); *(pf++) = SHORT2ANGLE(*(sh++)); *(pf++) = 0;
			LocalAngleVector(angles, vec);
			LocalVectorMA(parentBone->translation, thisBoneInfo->parentDist, vec, bonePtr->translation);
		}
		else
		{
			sh      = (short *)cBonePtr->ofsAngles; pf = angles;
			*(pf++) = SHORT2ANGLE(*(sh++)); *(pf++) = SHORT2ANGLE(*(sh++)); *(pf++) = 0;
			LocalAngleVector(angles, vec);

			if (isTorso)
			{
				sh      = (short *)cTBonePtr->ofsAngles;
				pf      = tangles;
				*(pf++) = SHORT2ANGLE(*(sh++)); *(pf++) = SHORT2ANGLE(*(sh++)); *(pf++) = 0;
				LocalAngleVector(tangles, v2);

				// blend the angles together
				SLerp_Normal(vec, v2, thisBoneInfo->torsoWeight, vec);
				LocalVectorMA(parentBone->translation, thisBoneInfo->parentDist, vec, bonePtr->translation);

			}
			else        // legs bone
			{
				LocalVectorMA(parentBone->translation, thisBoneInfo->parentDist, vec, bonePtr->translation);
			}
		}
#endif
	}
	else        // just use the frame position
	{
		bonePtr->translation[0] = frame->parentOffset[0];
		bonePtr->translation[1] = frame->parentOffset[1];
		bonePtr->translation[2] = frame->parentOffset[2];
	}

	if (boneNum == header->torsoParent)     // this is the torsoParent
	{
		VectorCopy(bonePtr->translation, torsoParentOffset);
	}

	validBones[boneNum] = 1;

	rawBones[boneNum] = *bonePtr;
	newBones[boneNum] = 1;

}
示例#19
0
文件: g_phys.cpp 项目: Picmip/qfusion
/*
* SV_Push
*
* Objects need to be moved back on a failed push,
* otherwise riders would continue to slide.
*/
static bool SV_Push( edict_t *pusher, vec3_t move, vec3_t amove ) {
	int i, e;
	edict_t *check, *block;
	vec3_t mins, maxs;
	pushed_t *p;
	mat3_t axis;
	vec3_t org, org2, move2;

	// find the bounding box
	for( i = 0; i < 3; i++ ) {
		mins[i] = pusher->r.absmin[i] + move[i];
		maxs[i] = pusher->r.absmax[i] + move[i];
	}

	// we need this for pushing things later
	VectorNegate( amove, org );
	AnglesToAxis( org, axis );

	// save the pusher's original position
	pushed_p->ent = pusher;
	VectorCopy( pusher->s.origin, pushed_p->origin );
	VectorCopy( pusher->s.angles, pushed_p->angles );
	if( pusher->r.client ) {
		VectorCopy( pusher->r.client->ps.pmove.velocity, pushed_p->pmove_origin );
		pushed_p->yaw = pusher->r.client->ps.viewangles[YAW];
	}
	pushed_p++;

	// move the pusher to its final position
	VectorAdd( pusher->s.origin, move, pusher->s.origin );
	VectorAdd( pusher->s.angles, amove, pusher->s.angles );
	GClip_LinkEntity( pusher );

	// see if any solid entities are inside the final position
	check = game.edicts + 1;
	for( e = 1; e < game.numentities; e++, check++ ) {
		if( !check->r.inuse ) {
			continue;
		}
		if( check->movetype == MOVETYPE_PUSH
			|| check->movetype == MOVETYPE_STOP
			|| check->movetype == MOVETYPE_NONE
			|| check->movetype == MOVETYPE_NOCLIP ) {
			continue;
		}

		if( !check->areagrid[0].prev ) {
			continue; // not linked in anywhere

		}

		// if the entity is standing on the pusher, it will definitely be moved
		if( check->groundentity != pusher ) {
			// see if the ent needs to be tested
			if( check->r.absmin[0] >= maxs[0]
				|| check->r.absmin[1] >= maxs[1]
				|| check->r.absmin[2] >= maxs[2]
				|| check->r.absmax[0] <= mins[0]
				|| check->r.absmax[1] <= mins[1]
				|| check->r.absmax[2] <= mins[2] ) {
				continue;
			}

			// see if the ent's bbox is inside the pusher's final position
			if( !SV_TestEntityPosition( check ) ) {
				continue;
			}
		}

		if( ( pusher->movetype == MOVETYPE_PUSH ) || ( check->groundentity == pusher ) ) {
			// move this entity
			pushed_p->ent = check;
			VectorCopy( check->s.origin, pushed_p->origin );
			VectorCopy( check->s.angles, pushed_p->angles );
			pushed_p++;

			// try moving the contacted entity
			VectorAdd( check->s.origin, move, check->s.origin );
			if( check->r.client ) {
				// FIXME: doesn't rotate monsters?
				VectorAdd( check->r.client->ps.pmove.origin, move, check->r.client->ps.pmove.origin );
				check->r.client->ps.viewangles[YAW] += amove[YAW];
			}

			// figure movement due to the pusher's amove
			VectorSubtract( check->s.origin, pusher->s.origin, org );
			Matrix3_TransformVector( axis, org, org2 );
			VectorSubtract( org2, org, move2 );
			VectorAdd( check->s.origin, move2, check->s.origin );

			if( check->movetype != MOVETYPE_BOUNCEGRENADE ) {
				// may have pushed them off an edge
				if( check->groundentity != pusher ) {
					check->groundentity = NULL;
				}
			}

			block = SV_TestEntityPosition( check );
			if( !block ) {
				// pushed ok
				GClip_LinkEntity( check );

				// impact?
				continue;
			} else {
				// try to fix block
				// if it is ok to leave in the old position, do it
				// this is only relevant for riding entities, not pushed
				VectorSubtract( check->s.origin, move, check->s.origin );
				VectorSubtract( check->s.origin, move2, check->s.origin );
				block = SV_TestEntityPosition( check );
				if( !block ) {
					pushed_p--;
					continue;
				}
			}
		}

		// save off the obstacle so we can call the block function
		obstacle = check;

		// move back any entities we already moved
		// go backwards, so if the same entity was pushed
		// twice, it goes back to the original position
		for( p = pushed_p - 1; p >= pushed; p-- ) {
			VectorCopy( p->origin, p->ent->s.origin );
			VectorCopy( p->angles, p->ent->s.angles );
			if( p->ent->r.client ) {
				VectorCopy( p->pmove_origin, p->ent->r.client->ps.pmove.origin );
				p->ent->r.client->ps.viewangles[YAW] = p->yaw;
			}
			GClip_LinkEntity( p->ent );
		}
		return false;
	}

	//FIXME: is there a better way to handle this?
	// see if anything we moved has touched a trigger
	for( p = pushed_p - 1; p >= pushed; p-- )
		GClip_TouchTriggers( p->ent );

	return true;
}
示例#20
0
/*
==============
R_CalcBoneLerp
==============
*/
void R_CalcBoneLerp(mdsHeader_t *header, const refEntity_t *refent, int boneNum)
{
	if (!refent || !header || boneNum < 0 || boneNum >= MDS_MAX_BONES)
	{
		return;
	}

	thisBoneInfo = &boneInfo[boneNum];

	if (!thisBoneInfo)
	{
		return;
	}

	if (thisBoneInfo->parent >= 0)
	{
		parentBone     = &bones[thisBoneInfo->parent];
		parentBoneInfo = &boneInfo[thisBoneInfo->parent];
	}
	else
	{
		parentBone     = NULL;
		parentBoneInfo = NULL;
	}

	if (thisBoneInfo->torsoWeight)
	{
		cTBonePtr    = &cBoneListTorso[boneNum];
		cOldTBonePtr = &cOldBoneListTorso[boneNum];
		isTorso      = qtrue;
		if (thisBoneInfo->torsoWeight == 1.0f)
		{
			fullTorso = qtrue;
		}
	}
	else
	{
		isTorso   = qfalse;
		fullTorso = qfalse;
	}
	cBonePtr    = &cBoneList[boneNum];
	cOldBonePtr = &cOldBoneList[boneNum];

	bonePtr = &bones[boneNum];

	newBones[boneNum] = 1;

	// rotation (take into account 170 to -170 lerps, which need to take the shortest route)
	if (fullTorso)
	{
		sh  = (short *)cTBonePtr->angles;
		sh2 = (short *)cOldTBonePtr->angles;
		pf  = angles;

		a1      = SHORT2ANGLE(*(sh++)); a2 = SHORT2ANGLE(*(sh2++)); diff = AngleNormalize180(a1 - a2);
		*(pf++) = a1 - torsoBacklerp * diff;
		a1      = SHORT2ANGLE(*(sh++)); a2 = SHORT2ANGLE(*(sh2++)); diff = AngleNormalize180(a1 - a2);
		*(pf++) = a1 - torsoBacklerp * diff;
		a1      = SHORT2ANGLE(*(sh++)); a2 = SHORT2ANGLE(*(sh2++)); diff = AngleNormalize180(a1 - a2);
		*(pf++) = a1 - torsoBacklerp * diff;

	}
	else
	{
		sh  = (short *)cBonePtr->angles;
		sh2 = (short *)cOldBonePtr->angles;
		pf  = angles;

		a1      = SHORT2ANGLE(*(sh++)); a2 = SHORT2ANGLE(*(sh2++)); diff = AngleNormalize180(a1 - a2);
		*(pf++) = a1 - backlerp * diff;
		a1      = SHORT2ANGLE(*(sh++)); a2 = SHORT2ANGLE(*(sh2++)); diff = AngleNormalize180(a1 - a2);
		*(pf++) = a1 - backlerp * diff;
		a1      = SHORT2ANGLE(*(sh++)); a2 = SHORT2ANGLE(*(sh2++)); diff = AngleNormalize180(a1 - a2);
		*(pf++) = a1 - backlerp * diff;

		if (isTorso)
		{
			int j;

			sh  = (short *)cTBonePtr->angles;
			sh2 = (short *)cOldTBonePtr->angles;
			pf  = tangles;

			a1      = SHORT2ANGLE(*(sh++)); a2 = SHORT2ANGLE(*(sh2++)); diff = AngleNormalize180(a1 - a2);
			*(pf++) = a1 - torsoBacklerp * diff;
			a1      = SHORT2ANGLE(*(sh++)); a2 = SHORT2ANGLE(*(sh2++)); diff = AngleNormalize180(a1 - a2);
			*(pf++) = a1 - torsoBacklerp * diff;
			a1      = SHORT2ANGLE(*(sh++)); a2 = SHORT2ANGLE(*(sh2++)); diff = AngleNormalize180(a1 - a2);
			*(pf++) = a1 - torsoBacklerp * diff;

			// blend the angles together
			for (j = 0; j < 3; j++)
			{
				diff = tangles[j] - angles[j];
				if (Q_fabs(diff) > 180)
				{
					diff = AngleNormalize180(diff);
				}
				angles[j] = angles[j] + thisBoneInfo->torsoWeight * diff;
			}

		}

	}
	AnglesToAxis(angles, bonePtr->matrix);

	if (parentBone)
	{
		if (fullTorso)
		{
			sh  = (short *)cTBonePtr->ofsAngles;
			sh2 = (short *)cOldTBonePtr->ofsAngles;
		}
		else
		{
			sh  = (short *)cBonePtr->ofsAngles;
			sh2 = (short *)cOldBonePtr->ofsAngles;
		}

		pf      = angles;
		*(pf++) = SHORT2ANGLE(*(sh++));
		*(pf++) = SHORT2ANGLE(*(sh++));
		*(pf++) = 0;
		LocalAngleVector(angles, v2);       // new

		pf      = angles;
		*(pf++) = SHORT2ANGLE(*(sh2++));
		*(pf++) = SHORT2ANGLE(*(sh2++));
		*(pf++) = 0;
		LocalAngleVector(angles, vec);      // old

		// blend the angles together
		if (fullTorso)
		{
			SLerp_Normal(vec, v2, torsoFrontlerp, dir);
		}
		else
		{
			SLerp_Normal(vec, v2, frontlerp, dir);
		}

		// translation
		if (!fullTorso && isTorso)        // partial legs/torso, need to lerp according to torsoWeight
		{   // calc the torso frame
			sh  = (short *)cTBonePtr->ofsAngles;
			sh2 = (short *)cOldTBonePtr->ofsAngles;

			pf      = angles;
			*(pf++) = SHORT2ANGLE(*(sh++));
			*(pf++) = SHORT2ANGLE(*(sh++));
			*(pf++) = 0;
			LocalAngleVector(angles, v2);       // new

			pf      = angles;
			*(pf++) = SHORT2ANGLE(*(sh2++));
			*(pf++) = SHORT2ANGLE(*(sh2++));
			*(pf++) = 0;
			LocalAngleVector(angles, vec);      // old

			// blend the angles together
			SLerp_Normal(vec, v2, torsoFrontlerp, v2);

			// blend the torso/legs together
			SLerp_Normal(dir, v2, thisBoneInfo->torsoWeight, dir);

		}

		LocalVectorMA(parentBone->translation, thisBoneInfo->parentDist, dir, bonePtr->translation);
	}
	else        // just interpolate the frame positions
	{
		bonePtr->translation[0] = frontlerp * frame->parentOffset[0] + backlerp * oldFrame->parentOffset[0];
		bonePtr->translation[1] = frontlerp * frame->parentOffset[1] + backlerp * oldFrame->parentOffset[1];
		bonePtr->translation[2] = frontlerp * frame->parentOffset[2] + backlerp * oldFrame->parentOffset[2];
	}

	if (boneNum == header->torsoParent)     // this is the torsoParent
	{
		VectorCopy(bonePtr->translation, torsoParentOffset);
	}
	validBones[boneNum] = 1;

	rawBones[boneNum] = *bonePtr;
	newBones[boneNum] = 1;
}
示例#21
0
/*
==========================
CG_MachineGunEjectBrass
==========================
*/
static void CG_MachineGunEjectBrass( centity_t *cent ) {
	localEntity_t	*le;
	refEntity_t		*re;
	vec3_t			velocity, xvelocity;
	vec3_t			offset, xoffset;
	float			waterScale = 1.0f;
	vec3_t			v[3];

	if ( cg_brassTime.integer <= 0 ) {
		return;
	}

	le = CG_AllocLocalEntity();
	re = &le->refEntity;

	velocity[0] = 0;
	velocity[1] = -50 + 40 * crandom();
	velocity[2] = 100 + 50 * crandom();

	le->leType = LE_FRAGMENT;
	le->startTime = cg.time;
	le->endTime = le->startTime + cg_brassTime.integer + ( cg_brassTime.integer / 4 ) * random();

	le->pos.trType = TR_GRAVITY;
	le->pos.trTime = cg.time - (rand()&15);

	AnglesToAxis( cent->lerpAngles, v );

	offset[0] = 8;
	offset[1] = -4;
	offset[2] = 24;

	xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0];
	xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1];
	xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2];
	VectorAdd( cent->lerpOrigin, xoffset, re->origin );

	VectorCopy( re->origin, le->pos.trBase );

	if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) {
		waterScale = 0.10f;
	}

	xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0];
	xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1];
	xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2];
	VectorScale( xvelocity, waterScale, le->pos.trDelta );

	AxisCopy( axisDefault, re->axis );
	re->hModel = cgs.media.machinegunBrassModel;

	le->bounceFactor = 0.4 * waterScale;

	le->angles.trType = TR_LINEAR;
	le->angles.trTime = cg.time;
	le->angles.trBase[0] = rand()&31;
	le->angles.trBase[1] = rand()&31;
	le->angles.trBase[2] = rand()&31;
	le->angles.trDelta[0] = 2;
	le->angles.trDelta[1] = 1;
	le->angles.trDelta[2] = 0;

	le->leFlags = LEF_TUMBLE;
	le->leBounceSoundType = LEBS_BRASS;
	le->leMarkType = LEMT_NONE;
}
示例#22
0
/*
===============
CG_CalcViewValues

Sets cg.refdef view values
===============
*/
static int CG_CalcViewValues( void ) {
	playerState_t	*ps;

	memset( &cg.refdef, 0, sizeof( cg.refdef ) );

	// strings for in game rendering
	// Q_strncpyz( cg.refdef.text[0], "Park Ranger", sizeof(cg.refdef.text[0]) );
	// Q_strncpyz( cg.refdef.text[1], "19", sizeof(cg.refdef.text[1]) );

	// calculate size of 3D view
	CG_CalcVrect();

	ps = &cg.cur_lc->predictedPlayerState;
/*
	if (cg.cameraMode) {
		vec3_t origin, angles;
		if (trap_getCameraInfo(cg.time, &origin, &angles)) {
			VectorCopy(origin, cg.refdef.vieworg);
			angles[ROLL] = 0;
			VectorCopy(angles, cg.refdefViewAngles);
			AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
			return CG_CalcFov();
		} else {
			cg.cameraMode = qfalse;
		}
	}
*/
	// intermission view
	if ( ps->pm_type == PM_INTERMISSION ) {
		VectorCopy( ps->origin, cg.refdef.vieworg );
		VectorCopy( ps->viewangles, cg.refdefViewAngles );
		AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
		return CG_CalcFov();
	}

	cg.bobcycle = ( ps->bobCycle & 128 ) >> 7;
	cg.bobfracsin = fabs( sin( ( ps->bobCycle & 127 ) / 127.0 * M_PI ) );
	cg.xyspeed = sqrt( ps->velocity[0] * ps->velocity[0] +
		ps->velocity[1] * ps->velocity[1] );


	VectorCopy( ps->origin, cg.refdef.vieworg );
	VectorCopy( ps->viewangles, cg.refdefViewAngles );

	if (cg_cameraOrbit.integer) {
		if (cg.time > cg.nextOrbitTime) {
			cg.nextOrbitTime = cg.time + cg_cameraOrbitDelay.integer;
			cg_thirdPersonAngle[cg.cur_localClientNum].value += cg_cameraOrbit.value;
		}
	}
	// add error decay
	if ( cg_errorDecay.value > 0 ) {
		int		t;
		float	f;

		t = cg.time - cg.cur_lc->predictedErrorTime;
		f = ( cg_errorDecay.value - t ) / cg_errorDecay.value;
		if ( f > 0 && f < 1 ) {
			VectorMA( cg.refdef.vieworg, f, cg.cur_lc->predictedError, cg.refdef.vieworg );
		} else {
			cg.cur_lc->predictedErrorTime = 0;
		}
	}

	if ( cg.cur_lc->renderingThirdPerson ) {
		// back away from character
		CG_OffsetThirdPersonView();
	} else {
		// offset for local bobbing and kicks
		CG_OffsetFirstPersonView();
	}

	// position eye relative to origin
	AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );

	if ( cg.cur_lc->hyperspace ) {
		cg.refdef.rdflags |= RDF_NOWORLDMODEL | RDF_HYPERSPACE;
	}

	// field of view
	return CG_CalcFov();
}
示例#23
0
/*
===============
CG_CalcViewValues

Sets cg.refdef view values
===============
*/
static int CG_CalcViewValues( void ) {
	playerState_t	*ps;

	memset( &cg.refdef, 0, sizeof( cg.refdef ) );

	// strings for in game rendering
	// Q_strncpyz( cg.refdef.text[0], "Park Ranger", sizeof(cg.refdef.text[0]) );
	// Q_strncpyz( cg.refdef.text[1], "19", sizeof(cg.refdef.text[1]) );

	// calculate size of 3D view
	CG_CalcVrect();

	ps = &cg.predictedPlayerState;

	// intermission view
	if ( ps->pm_type == PM_INTERMISSION ) {
		VectorCopy( ps->origin, cg.refdef.vieworg );
		VectorCopy( ps->viewangles, cg.refdefViewAngles );
		AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
		return CG_CalcFov();
	}

	cg.bobcycle = ( ps->bobCycle & 128 ) >> 7;
	cg.bobfracsin = fabs( sin( ( ps->bobCycle & 127 ) / 127.0 * M_PI ) );

	cg.bobfraccos = fabs( cos( ( ps->bobCycle & 127 ) / 127.0 * M_PI ) );
	cg.bobfracsin2 = fabs( sin( ( ps->bobCycle & 127) / 127.0 * (M_PI) ));

	cg.xyspeed = sqrt( ps->velocity[0] * ps->velocity[0] +
		ps->velocity[1] * ps->velocity[1] );


	VectorCopy( ps->origin, cg.refdef.vieworg );
	VectorCopy( ps->viewangles, cg.refdefViewAngles );

	if (cg_cameraOrbit.integer) {
		if (cg.time > cg.nextOrbitTime) {
			cg.nextOrbitTime = cg.time + cg_cameraOrbitDelay.integer;
			cg_thirdPersonAngle.value += cg_cameraOrbit.value;
		}
	}
	// add error decay
	if ( cg_errorDecay.value > 0 ) {
		int		t;
		float	f;

		t = cg.time - cg.predictedErrorTime;
		f = ( cg_errorDecay.value - t ) / cg_errorDecay.value;
		if ( f > 0 && f < 1 ) {
			VectorMA( cg.refdef.vieworg, f, cg.predictedError, cg.refdef.vieworg );
		} else {
			cg.predictedErrorTime = 0;
		}
	}

	if ( cg.renderingThirdPerson ) {
		// back away from character
		CG_OffsetThirdPersonView();

	} else {
		// offset for local bobbing and kicks
		CG_OffsetFirstPersonView();
	}

	// leilei - View-from-the-model-eyes feature, aka "fullbody awareness" lol
	if (cg_cameraEyes.integer && !cg.renderingThirdPerson){
		vec3_t		forward, right, up;	
		cg.refdefViewAngles[ROLL] = headang[ROLL];
		cg.refdefViewAngles[PITCH] = headang[PITCH];
		cg.refdefViewAngles[YAW] = headang[YAW];

		AngleVectors( headang, forward, NULL, up );
		if (cg_cameraEyes.integer == 2){
			VectorMA( headpos, 0, forward, headpos );
			VectorMA( headpos, 4, up, headpos );
		}
		else
		{
			VectorMA( headpos, cg_cameraEyes_Fwd.value, forward, headpos );
			VectorMA( headpos, cg_cameraEyes_Up.value, up, headpos );
		}

		cg.refdef.vieworg[0] = ps->origin[0] + headpos[0];
		cg.refdef.vieworg[1] = ps->origin[1] + headpos[1];
		cg.refdef.vieworg[2] = ps->origin[2] + headpos[2];
		
	}

	// position eye reletive to origin
	AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );

	if ( cg.hyperspace ) {
		cg.refdef.rdflags |= RDF_NOWORLDMODEL | RDF_HYPERSPACE;
	}

	// field of view
	return CG_CalcFov();
}
示例#24
0
// Used for both the view weapon (ps is valid) and the world modelother character models (ps is NULL)
// The main player will have this called for BOTH cases, so effects like light and sound should only be done on the
//	world model case.
void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, int team, vector3 *newAngles, qboolean thirdPerson ) {
	refEntity_t gun, barrel, flash;
	vector3 angles;
	weapon_t weaponNum;
	weaponInfo_t *weapon;
	centity_t *nonPredictedCent;

	if ( !thirdPerson && cg_fakeGun.integer ) {
		weaponNum = (weapon_t)cg_fakeGun.integer;
	}
	else {
		weaponNum = (weapon_t)cent->currentState.weapon;
	}

	if ( weaponNum == WP_EMPLACED_GUN )
		return;

	// spectator mode, don't draw it...
	if ( cg.predictedPlayerState.pm_type == PM_SPECTATOR
		&& cent->currentState.number == cg.predictedPlayerState.clientNum )
	{
		return;
	}

	CG_RegisterWeapon( weaponNum );
	weapon = &cg_weapons[weaponNum];

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

	// only do this if we are in first person, since world weapons are now handled on the server by Ghoul2
	if ( !thirdPerson ) {
		// add the weapon
		VectorCopy( &parent->lightingOrigin, &gun.lightingOrigin );
		gun.shadowPlane = parent->shadowPlane;
		gun.renderfx = parent->renderfx;

		// this player, in first person view
		if ( ps )
			gun.hModel = weapon->viewModel;
		else
			gun.hModel = weapon->weaponModel;
		if ( !gun.hModel )
			return;

		if ( !ps ) {
			// add weapon ready sound
			if ( (cent->currentState.eFlags & EF_FIRING) && weapon->firingSound ) {
				trap->S_AddLoopingSound( cent->currentState.number, &cent->lerpOrigin, &vec3_origin,
					weapon->firingSound
				);
			}
			else if ( weapon->readySound ) {
				trap->S_AddLoopingSound( cent->currentState.number, &cent->lerpOrigin, &vec3_origin,
					weapon->readySound
				);
			}
		}

		CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon" );

		if ( !CG_IsMindTricked( cent->currentState.trickedEntIndex, cg.snap->ps.clientNum ) ) {
			// don't draw the weapon if the player is invisible
			CG_AddWeaponWithPowerups( &gun, cent->currentState.powerups );
		}

		if ( weaponNum == WP_STUN_BATON ) {
			int i;

			for ( i = 0; i < 3; i++ ) {
				memset( &barrel, 0, sizeof(barrel) );
				VectorCopy( &parent->lightingOrigin, &barrel.lightingOrigin );
				barrel.shadowPlane = parent->shadowPlane;
				barrel.renderfx = parent->renderfx;

				if ( i == 0 ) {
					barrel.hModel = trap->R_RegisterModel( "models/weapons2/stun_baton/baton_barrel.md3" );
				}
				else if ( i == 1 ) {
					barrel.hModel = trap->R_RegisterModel( "models/weapons2/stun_baton/baton_barrel2.md3" );
				}
				else {
					barrel.hModel = trap->R_RegisterModel( "models/weapons2/stun_baton/baton_barrel3.md3" );
				}
				angles.yaw = 0;
				angles.pitch = 0;
				angles.roll = 0;

				AnglesToAxis( &angles, barrel.axis );

				if ( i == 0 ) {
					CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel" );
				}
				else if ( i == 1 ) {
					CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel2" );
				}
				else {
					CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel3" );
				}
				CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
			}
		}
		else {
			// add the spinning barrel
			if ( weapon->barrelModel ) {
				memset( &barrel, 0, sizeof(barrel) );
				VectorCopy( &parent->lightingOrigin, &barrel.lightingOrigin );
				barrel.shadowPlane = parent->shadowPlane;
				barrel.renderfx = parent->renderfx;

				barrel.hModel = weapon->barrelModel;
				angles.yaw = 0;
				angles.pitch = 0;
				angles.roll = 0;

				AnglesToAxis( &angles, barrel.axis );

				CG_PositionRotatedEntityOnTag( &barrel, parent, weapon->handsModel, "tag_barrel" );

				CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
			}
		}
	}

	memset( &flash, 0, sizeof(flash) );
	CG_PositionEntityOnTag( &flash, &gun, gun.hModel, "tag_flash" );

	VectorCopy( &flash.origin, &cg.lastFPFlashPoint );

	// Do special charge bits
	// Make the guns do their charging visual in True View.
	if ( (ps || cg.renderingThirdPerson || cg.predictedPlayerState.clientNum != cent->currentState.number || cg_trueGuns.integer) &&
		((cent->currentState.modelindex2 == WEAPON_CHARGING_ALT && weaponNum == WP_BRYAR_PISTOL) ||
		(cent->currentState.modelindex2 == WEAPON_CHARGING_ALT && weaponNum == WP_BRYAR_OLD) ||
		(weaponNum == WP_BOWCASTER && cent->currentState.modelindex2 == WEAPON_CHARGING) ||
		(weaponNum == WP_DEMP2 && cent->currentState.modelindex2 == WEAPON_CHARGING_ALT)) ) {
		int shader = 0;
		float val = 0.0f;
		float scale = 1.0f;
		addspriteArgStruct_t fxSArgs;
		vector3 flashorigin, flashdir;

		if ( !thirdPerson ) {
			VectorCopy( &flash.origin, &flashorigin );
			VectorCopy( &flash.axis[0], &flashdir );
		}
		else {
			mdxaBone_t boltMatrix;

			// it's quite possible that we may have have no weapon model and be in a valid state, so return here if this is the case
			if ( !trap->G2API_HasGhoul2ModelOnIndex( &(cent->ghoul2), 1 ) )
				return;

			// Couldn't find bolt point.
			if ( !trap->G2API_GetBoltMatrix( cent->ghoul2, 1, 0, &boltMatrix, newAngles, &cent->lerpOrigin, cg.time,
				cgs.gameModels, &cent->modelScale ) ) {
				return;
			}

			BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, &flashorigin );
			BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_X, &flashdir );
		}

		if ( weaponNum == WP_BRYAR_PISTOL || weaponNum == WP_BRYAR_OLD ) {
			// Hardcoded max charge time of 1 second
			val = (cg.time - cent->currentState.constantLight) * 0.001f;
			shader = media.gfx.world.bryarFrontFlash;
		}
		else if ( weaponNum == WP_BOWCASTER ) {
			// Hardcoded max charge time of 1 second
			val = (cg.time - cent->currentState.constantLight) * 0.001f;
			shader = media.gfx.world.greenFrontFlash;
		}
		else if ( weaponNum == WP_DEMP2 ) {
			val = (cg.time - cent->currentState.constantLight) * 0.001f;
			shader = media.gfx.world.lightningFlash;
			scale = 1.75f;
		}

		if ( val < 0.0f )
			val = 0.0f;
		else if ( val > 1.0f ) {
			val = 1.0f;
			if ( ps && cent->currentState.number == ps->clientNum )
				CGCam_Shake( 0.2f, 100 );
		}
		else if ( ps && cent->currentState.number == ps->clientNum )
			CGCam_Shake( val * val * 0.6f, 100 );

		val += random() * 0.5f;

		VectorCopy( &flashorigin, &fxSArgs.origin );
		VectorClear( &fxSArgs.vel );
		VectorClear( &fxSArgs.accel );
		fxSArgs.scale = 3.0f*val*scale;
		fxSArgs.dscale = 0.0f;
		fxSArgs.sAlpha = 0.7f;
		fxSArgs.eAlpha = 0.7f;
		fxSArgs.rotation = random() * 360;
		fxSArgs.bounce = 0.0f;
		fxSArgs.life = 1.0f;
		fxSArgs.shader = shader;
		fxSArgs.flags = 0x08000000;

		trap->FX_AddSprite( &fxSArgs );
	}

	// make sure we aren't looking at cg.predictedPlayerEntity for LG
	nonPredictedCent = &cg_entities[cent->currentState.clientNum];

	// if the index of the nonPredictedCent is not the same as the clientNum then this is a fake player (like on the
	//	single player podiums), so go ahead and use the cent
	if ( nonPredictedCent - cg_entities != cent->currentState.clientNum )
		nonPredictedCent = cent;

	// add the flash
	if ( weaponNum != WP_DEMP2 || (nonPredictedCent->currentState.eFlags & EF_FIRING) ) {
		// impulse flash
		if ( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME )
			return;
	}

	if ( ps || cg.renderingThirdPerson || cg_trueGuns.integer
		|| cent->currentState.number != cg.predictedPlayerState.clientNum ) {
		// Make sure we don't do the thirdperson model effects for the local player if we're in first person
		vector3 flashorigin, flashdir;
		refEntity_t	tpflash;

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

		if ( !thirdPerson ) {
			CG_PositionEntityOnTag( &tpflash, &gun, gun.hModel, "tag_flash" );
			VectorCopy( &tpflash.origin, &flashorigin );
			VectorCopy( &tpflash.axis[0], &flashdir );
		}
		else {
			mdxaBone_t boltMatrix;

			// it's quite possible that we may have have no weapon model and be in a valid state, so return here if this is the case
			if ( !trap->G2API_HasGhoul2ModelOnIndex( &(cent->ghoul2), 1 ) )
				return;

			// Couldn't find bolt point.
			if ( !trap->G2API_GetBoltMatrix( cent->ghoul2, 1, 0, &boltMatrix, newAngles, &cent->lerpOrigin, cg.time, cgs.gameModels, &cent->modelScale ) )
				return;

			BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, &flashorigin );
			BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_X, &flashdir );
		}

		if ( cg.time - cent->muzzleFlashTime <= MUZZLE_FLASH_TIME + 10 ) {
			// Handle muzzle flashes
			if ( cent->currentState.eFlags & EF_ALT_FIRING ) {
				// Check the alt firing first.
				if ( weapon->altMuzzleEffect ) {
					if ( !thirdPerson )
						trap->FX_PlayEntityEffectID( weapon->altMuzzleEffect, &flashorigin, tpflash.axis, -1, -1, -1, -1 );
					else
						trap->FX_PlayEffectID( weapon->altMuzzleEffect, &flashorigin, &flashdir, -1, -1, qfalse );
				}
			}
			else {
				// Regular firing
				if ( weapon->muzzleEffect ) {
					if ( !thirdPerson )
						trap->FX_PlayEntityEffectID( weapon->muzzleEffect, &flashorigin, tpflash.axis, -1, -1, -1, -1 );
					else
						trap->FX_PlayEffectID( weapon->muzzleEffect, &flashorigin, &flashdir, -1, -1, qfalse );
				}
			}
		}

		if ( weapon->flashDlightColor.r || weapon->flashDlightColor.g || weapon->flashDlightColor.b ) {
			trap->R_AddLightToScene( &flashorigin, 300 + (rand() & 31), weapon->flashDlightColor.r, weapon->flashDlightColor.g,
				weapon->flashDlightColor.b );
		}
	}
}
示例#25
0
/*
===============
UI_DrawPlayer
===============
*/
void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) {
	refdef_t		refdef;
	refEntity_t		legs;
	refEntity_t		torso;
	refEntity_t		head;
	refEntity_t		gun;
	refEntity_t		barrel;
	refEntity_t		flash;
	vec3_t			origin;
	int				renderfx;
	vec3_t			mins = {-16, -16, -24};
	vec3_t			maxs = {16, 16, 32};
	float			len;
	float			xx;

	if ( !pi->legsModel || !pi->torsoModel || !pi->headModel || !pi->animations[0].numFrames ) {
		return;
	}

	// this allows the ui to cache the player model on the main menu
	if (w == 0 || h == 0) {
		return;
	}

	dp_realtime = time;

	if ( pi->pendingWeapon != WP_NUM_WEAPONS && dp_realtime > pi->weaponTimer ) {
		pi->weapon = pi->pendingWeapon;
		pi->lastWeapon = pi->pendingWeapon;
		pi->pendingWeapon = WP_NUM_WEAPONS;
		pi->weaponTimer = 0;
		if( pi->currentWeapon != pi->weapon ) {
			trap_S_StartLocalSound( weaponChangeSound, CHAN_LOCAL );
		}
	}

	UI_AdjustFrom640( &x, &y, &w, &h );

	y -= jumpHeight;

	memset( &refdef, 0, sizeof( refdef ) );
	memset( &legs, 0, sizeof(legs) );
	memset( &torso, 0, sizeof(torso) );
	memset( &head, 0, sizeof(head) );

	refdef.rdflags = RDF_NOWORLDMODEL;

	AxisClear( refdef.viewaxis );

	refdef.x = x;
	refdef.y = y;
	refdef.width = w;
	refdef.height = h;

	refdef.fov_x = (int)((float)refdef.width / uiInfo.uiDC.xscale / 640.0f * 90.0f);
	xx = refdef.width / uiInfo.uiDC.xscale / tan( refdef.fov_x / 360 * M_PI );
	refdef.fov_y = atan2( refdef.height / uiInfo.uiDC.yscale, xx );
	refdef.fov_y *= ( 360 / (float)M_PI );

	// calculate distance so the player nearly fills the box
	len = 0.7 * ( maxs[2] - mins[2] );
	origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 );
	origin[1] = 0.5 * ( mins[1] + maxs[1] );
	origin[2] = -0.5 * ( mins[2] + maxs[2] );

	refdef.time = dp_realtime;

	trap_R_ClearScene();

	// get the rotation information
	UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis );
	
	// get the animation state (after rotation, to allow feet shuffle)
	UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp,
		 &torso.oldframe, &torso.frame, &torso.backlerp );

	renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW;

	//
	// add the legs
	//
	legs.hModel = pi->legsModel;
	legs.customSkin = pi->legsSkin;

	VectorCopy( origin, legs.origin );

	VectorCopy( origin, legs.lightingOrigin );
	legs.renderfx = renderfx;
	VectorCopy (legs.origin, legs.oldorigin);

	trap_R_AddRefEntityToScene( &legs );

	if (!legs.hModel) {
		return;
	}

	//
	// add the torso
	//
	torso.hModel = pi->torsoModel;
	if (!torso.hModel) {
		return;
	}

	torso.customSkin = pi->torsoSkin;

	VectorCopy( origin, torso.lightingOrigin );

	UI_PositionRotatedEntityOnTag( &torso, &legs, pi->legsModel, "tag_torso");

	torso.renderfx = renderfx;

	trap_R_AddRefEntityToScene( &torso );

	//
	// add the head
	//
	head.hModel = pi->headModel;
	if (!head.hModel) {
		return;
	}
	head.customSkin = pi->headSkin;

	VectorCopy( origin, head.lightingOrigin );

	UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head");

	head.renderfx = renderfx;

	trap_R_AddRefEntityToScene( &head );

	//
	// add the gun
	//
	if ( pi->currentWeapon != WP_NONE ) {
		memset( &gun, 0, sizeof(gun) );
		gun.hModel = pi->weaponModel;
		VectorCopy( origin, gun.lightingOrigin );
		UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon");
		gun.renderfx = renderfx;
		trap_R_AddRefEntityToScene( &gun );
	}

	//
	// add the spinning barrel
	//
	if ( pi->realWeapon == WP_MACHINEGUN || pi->realWeapon == WP_GAUNTLET || pi->realWeapon == WP_BFG ) {
		vec3_t	angles;

		memset( &barrel, 0, sizeof(barrel) );
		VectorCopy( origin, barrel.lightingOrigin );
		barrel.renderfx = renderfx;

		barrel.hModel = pi->barrelModel;
		angles[YAW] = 0;
		angles[PITCH] = 0;
		angles[ROLL] = UI_MachinegunSpinAngle( pi );
		if( pi->realWeapon == WP_GAUNTLET || pi->realWeapon == WP_BFG ) {
			angles[PITCH] = angles[ROLL];
			angles[ROLL] = 0;
		}
		AnglesToAxis( angles, barrel.axis );

		UI_PositionRotatedEntityOnTag( &barrel, &gun, pi->weaponModel, "tag_barrel");

		trap_R_AddRefEntityToScene( &barrel );
	}

	//
	// add muzzle flash
	//
	if ( dp_realtime <= pi->muzzleFlashTime ) {
		if ( pi->flashModel ) {
			memset( &flash, 0, sizeof(flash) );
			flash.hModel = pi->flashModel;
			VectorCopy( origin, flash.lightingOrigin );
			UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, "tag_flash");
			flash.renderfx = renderfx;
			trap_R_AddRefEntityToScene( &flash );
		}

		// make a dlight for the flash
		if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) {
			trap_R_AddLightToScene( flash.origin, 200 + (rand()&31), pi->flashDlightColor[0],
				pi->flashDlightColor[1], pi->flashDlightColor[2] );
		}
	}

	//
	// add the chat icon
	//
	if ( pi->chat ) {
		UI_PlayerFloatSprite( pi, origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) );
	}

	//
	// add an accent light
	//
	origin[0] -= 100;	// + = behind, - = in front
	origin[1] += 100;	// + = left, - = right
	origin[2] += 100;	// + = above, - = below
	trap_R_AddLightToScene( origin, 500, 1.0, 1.0, 1.0 );

	origin[0] -= 100;
	origin[1] -= 100;
	origin[2] -= 100;
	trap_R_AddLightToScene( origin, 500, 1.0, 0.0, 0.0 );

	trap_R_RenderScene( &refdef );
}
示例#26
0
// Add the weapon, and flash for the player's view
void CG_AddViewWeapon( playerState_t *ps ) {
	// no gun if in third person view or a camera is active
	if ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR || ps->pm_type == PM_INTERMISSION || cg.renderingThirdPerson ) {
		return;
	}

	const int weap = cg_fakeGun.integer ? cg_fakeGun.integer : ps->weapon;
	float desiredFov = 0.0f;
	if ( !cg.renderingThirdPerson
		&& (cg_trueGuns.integer || weap == WP_SABER || weap == WP_MELEE)
		&& cg_trueFOV.value
		&& cg.predictedPlayerState.pm_type != PM_SPECTATOR
		&& cg.predictedPlayerState.pm_type != PM_INTERMISSION )
	{
		desiredFov = cg_fovViewmodel.integer ? cg_fovViewmodel.value : cg_trueFOV.value;
	}
	else {
		desiredFov = cg_fovViewmodel.integer ? cg_fovViewmodel.value : cg_fov.value;
	}

	desiredFov = Q_clampi( 1, desiredFov, 180 );

	// allow the gun to be completely removed
	if ( !cg_fakeGun.integer && (!cg_drawGun.integer || cg.predictedPlayerState.zoomMode || cg_trueGuns.integer
		|| weap == WP_SABER || weap == WP_MELEE) ) {
		return;
	}

	// don't draw if testing a gun model
	if ( cg.testGun ) {
		return;
	}

	centity_t *cent = &cg_entities[cg.predictedPlayerState.clientNum];
	CG_RegisterWeapon( weap );

	refEntity_t hand;
	memset( &hand, 0, sizeof(hand) );

	// set up gun position
	vector3 angles;
	CG_CalculateWeaponPosition( &hand.origin, &angles );

	refdef_t *refdef = CG_GetRefdef();
	VectorMA( &hand.origin, cg.gunAlign.x, &refdef->viewaxis[0], &hand.origin );
	VectorMA( &hand.origin, cg.gunAlign.y, &refdef->viewaxis[1], &hand.origin );
	VectorMA( &hand.origin, cg.gunAlign.z, &refdef->viewaxis[2], &hand.origin );

	AnglesToAxis( &angles, hand.axis );

	if ( cg_fovViewmodel.integer ) {
		float fracDistFOV, fracWeapFOV;
		float fov = desiredFov;
		if ( cg_fovAspectAdjust.integer ) {
			// Based on LordHavoc's code for Darkplaces
			// http://www.quakeworld.nu/forum/topic/53/what-does-your-qw-look-like/page/30
			const float baseAspect = 0.75f; // 3/4
			const float aspect = (float)cgs.glconfig.vidWidth / (float)cgs.glconfig.vidHeight;

			fov = atanf( tanf( desiredFov*M_PI / 360.0f ) * baseAspect*aspect )*360.0f / M_PI;
		}
		fracDistFOV = tanf( refdef->fov_x * M_PI / 360.0f );
		fracWeapFOV = (1.0f / fracDistFOV) * tanf( fov * M_PI / 360.0f );
		VectorScale( &hand.axis[0], fracWeapFOV, &hand.axis[0] );
	}

	// map torso animations to weapon animations
	if ( cg_debugGunFrame.integer ) {
		// development tool
		hand.frame = hand.oldframe = cg_debugGunFrame.integer;
		hand.backlerp = 0;
	}
	else {
		float currentFrame;

		// get clientinfo for animation map
		clientInfo_t *ci = nullptr;
		if ( cent->currentState.eType == ET_NPC ) {
			if ( !cent->npcClient ) {
				return;
			}
			ci = cent->npcClient;
		}
		else {
			ci = &cgs.clientinfo[cent->currentState.clientNum];
		}

		// smoother first-person anims by eezstreet http://jkhub.org/topic/1499-/
		//		actually ported from SP
#if 1
		// Sil's fix
		trap->G2API_GetBoneFrame( cent->ghoul2, "lower_lumbar", cg.time, &currentFrame, cgs.gameModels, 0 );
		hand.frame = CG_MapTorsoToWeaponFrame( ci, ceilf( currentFrame ), cent->currentState.torsoAnim );
		hand.oldframe = CG_MapTorsoToWeaponFrame( ci, floorf( currentFrame ), cent->currentState.torsoAnim );
		hand.backlerp = 1.0f - (currentFrame - floorf( currentFrame ));
#else
		// basejka style
		hand.frame = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.frame, cent->currentState.torsoAnim );
		hand.oldframe = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.oldFrame, cent->currentState.torsoAnim );
		hand.backlerp = cent->pe.torso.backlerp;
#endif

		// Handle the fringe situation where oldframe is invalid
		if ( hand.frame == -1 ) {
			hand.frame = 0;
			hand.oldframe = 0;
			hand.backlerp = 0;
		}
		else if ( hand.oldframe == -1 ) {
			hand.oldframe = hand.frame;
			hand.backlerp = 0;
		}
	}

	weaponInfo_t *wi = &cg_weapons[weap];
	hand.hModel = wi->handsModel;
	hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON;

	// add everything onto the hand
	CG_AddPlayerWeapon( &hand, ps, &cg_entities[cg.predictedPlayerState.clientNum], ps->persistant[PERS_TEAM], &angles, qfalse );
}
示例#27
0
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;

	if ( le->pos.trType == TR_STATIONARY ) {
		// sink into the ground if near the removal time
		int		t;
		float	oldZ;
		
		t = le->endTime - cg.time;
		if ( t < SINK_TIME ) {
			// we must use an explicit lighting origin, otherwise the
			// lighting would be lost as soon as the origin went
			// into the ground
			VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
			le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
			oldZ = le->refEntity.origin[2];
			le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
			trap_R_AddRefEntityToScene( &le->refEntity );
			le->refEntity.origin[2] = oldZ;
		} else {
			trap_R_AddRefEntityToScene( &le->refEntity );
		}

		return;
	}

	// calculate new position
	BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );

	// trace a line from previous position to new position
	CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
	if ( trace.fraction == 1.0 ) {
		// still in free fall
		VectorCopy( newOrigin, le->refEntity.origin );

		if ( le->leFlags & LEF_TUMBLE ) {
			vec3_t angles;

			BG_EvaluateTrajectory( &le->angles, cg.time, angles );
			AnglesToAxis( angles, le->refEntity.axis );
		}

		trap_R_AddRefEntityToScene( &le->refEntity );

		// add a blood trail
		if ( le->leBounceSoundType == LEBS_BLOOD ) {
			CG_BloodTrail( le );
		}

		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
		CG_FreeLocalEntity( le );
		return;
	}

	// leave a mark
	CG_FragmentBounceMark( le, &trace );

	// do a bouncy sound
	CG_FragmentBounceSound( le, &trace );

	// reflect the velocity on the trace plane
	CG_ReflectVelocity( le, &trace );

	trap_R_AddRefEntityToScene( &le->refEntity );
}
示例#28
0
/*
===============
CG_CalcViewValues

Sets cg.refdef view values
===============
*/
static int CG_CalcViewValues( void ) {
	playerState_t   *ps;

	memset( &cg.refdef, 0, sizeof( cg.refdef ) );

	// strings for in game rendering
	// Q_strncpyz( cg.refdef.text[0], "Park Ranger", sizeof(cg.refdef.text[0]) );
	// Q_strncpyz( cg.refdef.text[1], "19", sizeof(cg.refdef.text[1]) );

	// calculate size of 3D view
	CG_CalcVrect();

	ps = &cg.predictedPlayerState;

	if ( cg.cameraMode ) {
		vec3_t origin, angles;
		float fov = 90;
		float x;

		if ( trap_getCameraInfo( CAM_PRIMARY, cg.time, &origin, &angles, &fov ) ) {
			VectorCopy( origin, cg.refdef.vieworg );
			angles[ROLL] = 0;
			angles[PITCH] = -angles[PITCH];     // (SA) compensate for reversed pitch (this makes the game match the editor, however I'm guessing the real fix is to be done there)
			VectorCopy( angles, cg.refdefViewAngles );
			AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );

			x = cg.refdef.width / tan( fov / 360 * M_PI );
			cg.refdef.fov_y = atan2( cg.refdef.height, x );
			cg.refdef.fov_y = cg.refdef.fov_y * 360 / M_PI;
			cg.refdef.fov_x = fov;

			trap_SendClientCommand( va( "setCameraOrigin %f %f %f", origin[0], origin[1], origin[2] ) );
			return 0;

		} else {
			cg.cameraMode = qfalse;
			trap_Cvar_Set( "cg_letterbox", "0" );
			trap_SendClientCommand( "stopCamera" );
			CG_Fade( 0, 0, 0, 255, 0 );   // go black
			CG_Fade( 0, 0, 0, 0, 1500 );  // then fadeup
		}
	}

	// intermission view
	if ( ps->pm_type == PM_INTERMISSION ) {
		VectorCopy( ps->origin, cg.refdef.vieworg );
		VectorCopy( ps->viewangles, cg.refdefViewAngles );
		AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
		return CG_CalcFov();
	}

	cg.bobcycle = ( ps->bobCycle & 128 ) >> 7;
	cg.bobfracsin = fabs( sin( ( ps->bobCycle & 127 ) / 127.0 * M_PI ) );
	cg.xyspeed = sqrt( ps->velocity[0] * ps->velocity[0] +
					   ps->velocity[1] * ps->velocity[1] );


//	VectorCopy( ps->origin, cg.refdef.vieworg );
	// Arnout: see if we're attached to a gun
	if ( cg.renderingThirdPerson && ps->eFlags & EF_MG42_ACTIVE ) {
		centity_t *mg42 = &cg_entities[ps->viewlocked_entNum];
		vec3_t forward, right, up;

		AngleVectors( ps->viewangles, forward, right, up );
		VectorMA( mg42->currentState.pos.trBase, -36, forward, cg.refdef.vieworg );
		cg.refdef.vieworg[2] = ps->origin[2];
	} else {
		VectorCopy( ps->origin, cg.refdef.vieworg );
	}
	VectorCopy( ps->viewangles, cg.refdefViewAngles );

	// add error decay
	if ( cg_errorDecay.value > 0 ) {
		int t;
		float f;

		t = cg.time - cg.predictedErrorTime;
		f = ( cg_errorDecay.value - t ) / cg_errorDecay.value;
		if ( f > 0 && f < 1 ) {
			VectorMA( cg.refdef.vieworg, f, cg.predictedError, cg.refdef.vieworg );
		} else {
			cg.predictedErrorTime = 0;
		}
	}

	// Ridah, lock the viewangles if the game has told us to
	if ( ps->viewlocked ) {

		/*
		if (ps->viewlocked == 4)
		{
			centity_t *tent;
			tent = &cg_entities[ps->viewlocked_entNum];
			VectorCopy (tent->currentState.apos.trBase, cg.refdefViewAngles);
		}
		else
		*/
		// DHM - Nerve :: don't bother evaluating if set to 7 (look at medic)
		if ( ps->viewlocked != 7 && ps->viewlocked != 3 && ps->viewlocked != 2 ) {
			BG_EvaluateTrajectory( &cg_entities[ps->viewlocked_entNum].currentState.apos, cg.time, cg.refdefViewAngles );
		}

		if ( ps->viewlocked == 2 ) {
			cg.refdefViewAngles[0] += crandom();
			cg.refdefViewAngles[1] += crandom();
		}
	}
	// done.

	if ( cg.renderingThirdPerson ) {
		// back away from character
		CG_OffsetThirdPersonView();
	} else {
		// offset for local bobbing and kicks
		CG_OffsetFirstPersonView();

		// Ridah, lock the viewangles if the game has told us to
		if ( ps->viewlocked == 7 ) {
			centity_t   *tent;
			vec3_t vec;

			tent = &cg_entities[ps->viewlocked_entNum];
			VectorCopy( tent->lerpOrigin, vec );
			VectorSubtract( vec, cg.refdef.vieworg, vec );
			vectoangles( vec, cg.refdefViewAngles );
		} else if ( ps->viewlocked == 4 )     {
			vec3_t fwd;
			AngleVectors( cg.refdefViewAngles, fwd, NULL, NULL );
			VectorMA( cg_entities[ps->viewlocked_entNum].currentState.pos.trBase, 16, fwd, cg.refdef.vieworg );
		} else if ( ps->viewlocked )     {
			vec3_t fwd;
			float oldZ;
			// set our position to be behind it
			oldZ = cg.refdef.vieworg[2];
			AngleVectors( cg.refdefViewAngles, fwd, NULL, NULL );
			VectorMA( cg_entities[ps->viewlocked_entNum].currentState.pos.trBase, -34, fwd, cg.refdef.vieworg );
			cg.refdef.vieworg[2] = oldZ;

//			CG_Printf( "ps->origin[2]: %f\n", ps->origin[2] );
//			CG_Printf( "fwd: %f %f %f\n", fwd[0], fwd[1], fwd[2] );
//			CG_Printf( "base: %f %f %f\n", cg_entities[ps->viewlocked_entNum].currentState.pos.trBase[0], cg_entities[ps->viewlocked_entNum].currentState.pos.trBase[1], cg_entities[ps->viewlocked_entNum].currentState.pos.trBase[2] );
		}
		// done.
	}

	// position eye relative to origin
	AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );

	if ( cg.hyperspace ) {
		cg.refdef.rdflags |= RDF_NOWORLDMODEL | RDF_HYPERSPACE;
	}

	// field of view
	return CG_CalcFov();
}
示例#29
0
static void CG_DistortionOrb( centity_t *cent )
{
	refEntity_t ent;
	vec3_t ang;
	float scale = 0.5f;
	float vLen;

	if (!cg_renderToTextureFX.integer)
	{
		return;
	}
	memset( &ent, 0, sizeof( ent ) );

	VectorCopy( cent->lerpOrigin, ent.origin );

	VectorSubtract(ent.origin, cg.refdef.vieworg, ent.axis[0]);
	vLen = VectorLength(ent.axis[0]);
	if (VectorNormalize(ent.axis[0]) <= 0.1f)
	{	// Entity is right on vieworg.  quit.
		return;
	}

//	VectorCopy(cg.refdef.viewaxis[2], ent.axis[2]);
//	CrossProduct(ent.axis[0], ent.axis[2], ent.axis[1]);
	vectoangles(ent.axis[0], ang);
	ang[ROLL] = cent->trickAlpha;
	cent->trickAlpha += 16; //spin the half-sphere to give a "screwdriver" effect
	AnglesToAxis(ang, ent.axis);

	//radius must be a power of 2, and is the actual captured texture size
	if (vLen < 128)
	{
		ent.radius = 256;
	}
	else if (vLen < 256)
	{
		ent.radius = 128;
	}
	else if (vLen < 512)
	{
		ent.radius = 64;
	}
	else
	{
		ent.radius = 32;
	}

	VectorScale(ent.axis[0], scale, ent.axis[0]);
	VectorScale(ent.axis[1], scale, ent.axis[1]);
	VectorScale(ent.axis[2], -scale, ent.axis[2]);

	ent.hModel = cgs.media.halfShieldModel;
	ent.customShader = 0;//cgs.media.halfShieldShader;	

#if 1
	ent.renderfx = (RF_DISTORTION|RF_RGB_TINT);

	//tint the whole thing a shade of blue
	ent.shaderRGBA[0] = 200.0f;
	ent.shaderRGBA[1] = 200.0f;
	ent.shaderRGBA[2] = 255.0f;
#else //no tint
	ent.renderfx = RF_DISTORTION;
#endif

	trap->R_AddRefEntityToScene( &ent );
}
示例#30
0
void SP_misc_gamemodel(void)
{
    char   *model;
    vec_t  angle;
    vec3_t angles;

    vec_t  scale;
    vec3_t vScale;

    vec3_t org;

    cg_gamemodel_t *gamemodel;

    int i;

    if (CG_SpawnString("targetname", "", &model) || CG_SpawnString("scriptname", "", &model) || CG_SpawnString("spawnflags", "", &model))
    {
        // Gordon: this model may not be static, so let the server handle it
        return;
    }

    if (cg.numMiscGameModels >= MAX_STATIC_GAMEMODELS)
    {
        CG_Error("^1MAX_STATIC_GAMEMODELS(%i) hit", MAX_STATIC_GAMEMODELS);
    }

    CG_SpawnString("model", "", &model);

    CG_SpawnVector("origin", "0 0 0", org);

    if (!CG_SpawnVector("angles", "0 0 0", angles))
    {
        if (CG_SpawnFloat("angle", "0", &angle))
        {
            angles[YAW] = angle;
        }
    }

    if (!CG_SpawnVector("modelscale_vec", "1 1 1", vScale))
    {
        if (CG_SpawnFloat("modelscale", "1", &scale))
        {
            VectorSet(vScale, scale, scale, scale);
        }
    }

    gamemodel        = &cgs.miscGameModels[cg.numMiscGameModels++];
    gamemodel->model = trap_R_RegisterModel(model);
    AnglesToAxis(angles, gamemodel->axes);
    for (i = 0; i < 3; i++)
    {
        VectorScale(gamemodel->axes[i], vScale[i], gamemodel->axes[i]);
    }
    VectorCopy(org, gamemodel->org);

    if (gamemodel->model)
    {
        vec3_t mins, maxs;

        trap_R_ModelBounds(gamemodel->model, mins, maxs);

        for (i = 0; i < 3; i++)
        {
            mins[i] *= vScale[i];
            maxs[i] *= vScale[i];
        }

        gamemodel->radius = RadiusFromBounds(mins, maxs);
    }
    else
    {
        gamemodel->radius = 0;
    }
}