/*
========================
CG_InterpolatePlayerState

Generates cg.cur_lc->predictedPlayerState by interpolating between
cg.snap->player_state and cg.nextFrame->player_state
========================
*/
static void CG_InterpolatePlayerState( qboolean grabAngles ) {
	float			f;
	int				i;
	playerState_t	*out;
	snapshot_t		*prev, *next;
	playerState_t	*prevPS, *nextPS;

	out = &cg.cur_lc->predictedPlayerState;
	prev = cg.snap;
	next = cg.nextSnap;

	*out = *cg.cur_ps;

	// if we are still allowing local input, short circuit the view angles
	if ( grabAngles ) {
		usercmd_t	cmd;
		int			cmdNum;

		cmdNum = trap_GetCurrentCmdNumber();
		trap_GetUserCmd( cmdNum, &cmd, cg.cur_localPlayerNum );

		PM_UpdateViewAngles( out, &cmd );
	}

	// if the next frame is a teleport, we can't lerp to it
	if ( cg.nextFrameTeleport ) {
		return;
	}

	if ( !next || next->serverTime <= prev->serverTime ) {
		return;
	}

	if (prev->playerNums[cg.cur_localPlayerNum] == -1 ||
		next->playerNums[cg.cur_localPlayerNum] == -1) {
		return;
	}

	prevPS = &prev->pss[cg.cur_localPlayerNum];
	nextPS = &next->pss[cg.cur_localPlayerNum];

	f = (float)( cg.time - prev->serverTime ) / ( next->serverTime - prev->serverTime );

	i = nextPS->bobCycle;
	if ( i < prevPS->bobCycle ) {
		i += 256;		// handle wraparound
	}
	out->bobCycle = prevPS->bobCycle + f * ( i - prevPS->bobCycle );

	for ( i = 0 ; i < 3 ; i++ ) {
		out->origin[i] = prevPS->origin[i] + f * (nextPS->origin[i] - prevPS->origin[i] );
		if ( !grabAngles ) {
			out->viewangles[i] = LerpAngle( 
				prevPS->viewangles[i], nextPS->viewangles[i], f );
		}
		out->velocity[i] = prevPS->velocity[i] + 
			f * (nextPS->velocity[i] - prevPS->velocity[i] );
	}

}
Beispiel #2
0
void GS_TraceCurveLaserBeam( trace_t *trace, vec3_t origin, vec3_t angles, vec3_t blendPoint, int ignore, int timeDelta, void ( *impact )( trace_t *tr, vec3_t dir ) )
{
	float frac, subdivisions = CURVELASERBEAM_SUBDIVISIONS;
	float range = (float)GS_GetWeaponDef( WEAP_LASERGUN )->firedef_weak.timeout;
	vec3_t from, dir, end;
	int passthrough = ignore;

	int i, j;
	vec3_t tmpangles, blendAngles;

	assert( trace );

	VectorCopy( origin, from );
	VectorSubtract( blendPoint, origin, dir );
	VecToAngles( dir, blendAngles );

	for( i = 1; i <= (int)subdivisions; i++ )
	{
		frac = ( ( range/subdivisions )*(float)i ) / (float)range;

		for( j = 0; j < 3; j++ )
			tmpangles[j] = LerpAngle( angles[j], blendAngles[j], frac );

		AngleVectors( tmpangles, dir, NULL, NULL );
		VectorMA( origin, range * frac, dir, end );

		GS_TraceLaserBeam( trace, from, tmpangles, DistanceFast( from, end ), passthrough, timeDelta, impact );
		if( trace->fraction != 1.0f )
			break;

		passthrough = trace->ent;
		VectorCopy( end, from );
	}
}
Beispiel #3
0
/*
=============================
CG_InterpolateEntityPosition
=============================
*/
static void CG_InterpolateEntityPosition( centity_t* cent )
{
	float       f;
	
	// it would be an internal error to find an entity that interpolates without
	// a snapshot ahead of the current one
	if ( cg.nextSnap == NULL )
	{
		CG_Error( "CG_InterpoateEntityPosition: cg.nextSnap == NULL" );
	}
	//CG_Printf("CG_InterpolateEntityPosition: TODO\n");
	f = cg.frameInterpolation;
	
	// this will linearize a sine or parabolic curve, but it is important
	// to not extrapolate player positions if more recent data is available
	//BG_EvaluateTrajectory( &cent->currentState.pos, cg.snap->serverTime, current );
	//BG_EvaluateTrajectory( &cent->nextState.pos, cg.nextSnap->serverTime, next );
	
	const float* current = cent->currentState.origin;
	const float* next = cent->nextState.origin;
	
	cent->lerpOrigin[0] = current[0] + f * ( next[0] - current[0] );
	cent->lerpOrigin[1] = current[1] + f * ( next[1] - current[1] );
	cent->lerpOrigin[2] = current[2] + f * ( next[2] - current[2] );
	
	//BG_EvaluateTrajectory( &cent->currentState.apos, cg.snap->serverTime, current );
	//BG_EvaluateTrajectory( &cent->nextState.apos, cg.nextSnap->serverTime, next );
	
	current = cent->currentState.angles;
	next = cent->nextState.angles;
	
	cent->lerpAngles[0] = LerpAngle( current[0], next[0], f );
	cent->lerpAngles[1] = LerpAngle( current[1], next[1], f );
	cent->lerpAngles[2] = LerpAngle( current[2], next[2], f );
	
	// update render entity and/or render light
	CG_OnEntityOrientationChange( cent );
}
Beispiel #4
0
static c4clipedict_t *GClip_GetClipEdictForDeltaTime( int entNum, int deltaTime )
{
	static int index = 0;
	static c4clipedict_t clipEnts[8];
	static c4clipedict_t *clipent;
	static c4clipedict_t clipentNewer; // for interpolation
	c4frame_t *cframe = NULL;
	unsigned int backTime, cframenum, backframes, i;
	edict_t	*ent = game.edicts + entNum;

	// pick one of the 8 slots to prevent overwritings
	clipent = &clipEnts[index];
	index = ( index + 1 )&7;

	if( !entNum || deltaTime >= 0 || !g_antilag->integer )
	{                                                    // current time entity
		clipent->r = ent->r;
		clipent->s = ent->s;
		return clipent;
	}

	if( !ent->r.inuse || ent->r.solid == SOLID_NOT 
		|| ( ent->r.solid == SOLID_TRIGGER && !(entNum >= 1 && entNum <= gs.maxclients) ) )
	{
		clipent->r = ent->r;
		clipent->s = ent->s;
		return clipent;
	}

	// clamp delta time inside the backed up limits
	backTime = abs( deltaTime );
	if( g_antilag_maxtimedelta->integer )
	{
		if( g_antilag_maxtimedelta->integer < 0 )
			trap_Cvar_SetValue( "g_antilag_maxtimedelta", abs( g_antilag_maxtimedelta->integer ) );
		if( backTime > (unsigned int)g_antilag_maxtimedelta->integer )
			backTime = (unsigned int)g_antilag_maxtimedelta->integer;
	}

	// find the first snap with timestamp < than realtime - backtime
	cframenum = sv_collisionFrameNum;
	for( backframes = 1; backframes < CFRAME_UPDATE_BACKUP && backframes < sv_collisionFrameNum; backframes++ ) // never overpass limits
	{
		cframe = &sv_collisionframes[( cframenum-backframes ) & CFRAME_UPDATE_MASK];
		// if solid has changed, we can't keep moving backwards
		if( ent->r.solid != cframe->clipEdicts[entNum].r.solid || ent->r.inuse != cframe->clipEdicts[entNum].r.inuse )
		{
			backframes--;
			if( backframes == 0 )
			{           // we can't step back from first
				cframe = NULL;
			}
			else
			{
				cframe = &sv_collisionframes[( cframenum-backframes ) & CFRAME_UPDATE_MASK];
			}
			break;
		}

		if( game.serverTime >= cframe->timestamp + backTime )
			break;
	}

	if( !cframe )
	{           // current time entity
		clipent->r = ent->r;
		clipent->s = ent->s;
		return clipent;
	}

	// setup with older for the data that is not interpolated
	*clipent = cframe->clipEdicts[entNum];

	// if we found an older than desired backtime frame, interpolate to find a more precise position.
	if( game.serverTime > cframe->timestamp+backTime )
	{
		float lerpFrac;

		if( backframes == 1 )
		{               // interpolate from 1st backed up to current
			lerpFrac = (float)( ( game.serverTime - backTime ) - cframe->timestamp ) / (float)( game.serverTime - cframe->timestamp );
			clipentNewer.r = ent->r;
			clipentNewer.s = ent->s;
		}
		else
		{ // interpolate between 2 backed up
			c4frame_t *cframeNewer = &sv_collisionframes[( cframenum-( backframes-1 ) ) & CFRAME_UPDATE_MASK];
			lerpFrac = (float)( ( game.serverTime - backTime ) - cframe->timestamp ) / (float)( cframeNewer->timestamp - cframe->timestamp );
			clipentNewer = cframeNewer->clipEdicts[entNum];
		}

		//G_Printf( "backTime:%i cframeBackTime:%i backFrames:%i lerfrac:%f\n", backTime, game.serverTime - cframe->timestamp, backframes, lerpFrac );

		// interpolate
		VectorLerp( clipent->s.origin, lerpFrac, clipentNewer.s.origin, clipent->s.origin );
		VectorLerp( clipent->r.mins, lerpFrac, clipentNewer.r.mins, clipent->r.mins );
		VectorLerp( clipent->r.maxs, lerpFrac, clipentNewer.r.maxs, clipent->r.maxs );
		for( i = 0; i < 3; i++ )
			clipent->s.angles[i] = LerpAngle( clipent->s.angles[i], clipentNewer.s.angles[i], lerpFrac );
	}

	//G_Printf( "backTime:%i cframeBackTime:%i backFrames:%i\n", backTime, game.serverTime - cframe->timestamp, backframes );

	// back time entity
	return clipent;
}
Beispiel #5
0
/*
=================
G_TimeShiftClient

Move a client back to where he was at the specified "time"
=================
*/
void G_TimeShiftClient( gentity_t *ent, int time ) {
	int		j, k;

	if ( time > level.time ) {
		time = level.time;
	}

	// find two entries in the origin trail whose times sandwich "time"
	// assumes no two adjacent trail records have the same timestamp
	j = k = ent->client->trailHead;
	do {
		if ( ent->client->trail[j].time <= time )
			break;

		k = j;
		j--;
		if ( j < 0 ) {
			j = NUM_CLIENT_TRAILS - 1;
		}
	}
	while ( j != ent->client->trailHead );

	// if we got past the first iteration above, we've sandwiched (or wrapped)
	if ( j != k ) {
		// make sure it doesn't get re-saved
		if ( ent->client->saved.leveltime != level.time ) {
			// save the current origin and bounding box
			VectorCopy( &ent->r.mins, &ent->client->saved.mins );
			VectorCopy( &ent->r.maxs, &ent->client->saved.maxs );
			VectorCopy( &ent->r.currentOrigin, &ent->client->saved.currentOrigin );
			VectorCopy( &ent->r.currentAngles, &ent->client->saved.currentAngles );
			ent->client->saved.leveltime = level.time;
		}

		// if we haven't wrapped back to the head, we've sandwiched, so
		// we shift the client's position back to where he was at "time"
		if ( j != ent->client->trailHead )
		{
			float	frac = (float)(ent->client->trail[k].time - time) / (float)(ent->client->trail[k].time - ent->client->trail[j].time);

			// FOR TESTING ONLY
//			Com_Printf( "level time: %d, fire time: %d, j time: %d, k time: %d\n", level.time, time, ent->client->trail[j].time, ent->client->trail[k].time );

			// interpolate between the two origins to give position at time index "time"
			TimeShiftLerp( frac, &ent->client->trail[k].currentOrigin, &ent->client->trail[j].currentOrigin, &ent->r.currentOrigin );
			ent->r.currentAngles.yaw = LerpAngle( ent->client->trail[k].currentAngles.yaw, ent->r.currentAngles.yaw, frac );

			// lerp these too, just for fun (and ducking)
			TimeShiftLerp( frac, &ent->client->trail[k].mins, &ent->client->trail[j].mins, &ent->r.mins );
			TimeShiftLerp( frac, &ent->client->trail[k].maxs, &ent->client->trail[j].maxs, &ent->r.maxs );

			// this will recalculate absmin and absmax
			trap->LinkEntity( (sharedEntity_t *)ent );
		} else {
			// we wrapped, so grab the earliest
			VectorCopy( &ent->client->trail[k].currentAngles, &ent->r.currentAngles );
			VectorCopy( &ent->client->trail[k].currentOrigin, &ent->r.currentOrigin );
			VectorCopy( &ent->client->trail[k].mins, &ent->r.mins );
			VectorCopy( &ent->client->trail[k].maxs, &ent->r.maxs );

			// this will recalculate absmin and absmax
			trap->LinkEntity( (sharedEntity_t *)ent );
		}
	}
}
Beispiel #6
0
/*
* CG_Democam_CalcView
*/
static int CG_Democam_CalcView( void ) {
	int i, viewType;
	float lerpfrac;
	vec3_t v;

	viewType = VIEWDEF_PLAYERVIEW;
	VectorClear( cam_velocity );

	if( currentcam ) {
		if( !nextcam ) {
			lerpfrac = 0;
		} else {
			lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
		}

		switch( currentcam->type ) {
			case DEMOCAM_FIRSTPERSON:
				VectorCopy( cg.view.origin, cam_origin );
				VectorCopy( cg.view.angles, cam_angles );
				VectorCopy( cg.view.velocity, cam_velocity );
				cam_fov = cg.view.fov_y;
				break;

			case DEMOCAM_THIRDPERSON:
				VectorCopy( cg.view.origin, cam_origin );
				VectorCopy( cg.view.angles, cam_angles );
				VectorCopy( cg.view.velocity, cam_velocity );
				cam_fov = cg.view.fov_y;
				cam_3dPerson = true;
				break;

			case DEMOCAM_POSITIONAL:
				viewType = VIEWDEF_DEMOCAM;
				cam_POVent = 0;
				VectorCopy( currentcam->origin, cam_origin );
				if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
					VectorCopy( currentcam->angles, cam_angles );
				}
				cam_fov = currentcam->fov;
				break;

			case DEMOCAM_PATH_LINEAR:
				viewType = VIEWDEF_DEMOCAM;
				cam_POVent = 0;
				VectorCopy( cam_origin, v );

				if( !nextcam || nextcam->type == DEMOCAM_FIRSTPERSON || nextcam->type == DEMOCAM_THIRDPERSON ) {
					CG_Printf( "Warning: CG_DemoCam: path_linear cam without a valid next cam\n" );
					VectorCopy( currentcam->origin, cam_origin );
					if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
						VectorCopy( currentcam->angles, cam_angles );
					}
					cam_fov = currentcam->fov;
				} else {
					VectorLerp( currentcam->origin, lerpfrac, nextcam->origin, cam_origin );
					if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
						for( i = 0; i < 3; i++ ) cam_angles[i] = LerpAngle( currentcam->angles[i], nextcam->angles[i], lerpfrac );
					}
					cam_fov = (float)currentcam->fov + (float)( nextcam->fov - currentcam->fov ) * lerpfrac;
				}

				// set velocity
				VectorSubtract( cam_origin, v, cam_velocity );
				VectorScale( cam_velocity, 1.0f / (float)cg.frameTime, cam_velocity );
				break;

			case DEMOCAM_PATH_SPLINE:
				viewType = VIEWDEF_DEMOCAM;
				cam_POVent = 0;
				clamp( lerpfrac, 0, 1 );
				VectorCopy( cam_origin, v );

				if( !nextcam || nextcam->type == DEMOCAM_FIRSTPERSON || nextcam->type == DEMOCAM_THIRDPERSON ) {
					CG_Printf( "Warning: CG_DemoCam: path_spline cam without a valid next cam\n" );
					VectorCopy( currentcam->origin, cam_origin );
					if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
						VectorCopy( currentcam->angles, cam_angles );
					}
					cam_fov = currentcam->fov;
				} else {  // valid spline path
#define VectorHermiteInterp( a, at, b, bt, c, v )  ( ( v )[0] = ( 2 * pow( c, 3 ) - 3 * pow( c, 2 ) + 1 ) * a[0] + ( pow( c, 3 ) - 2 * pow( c, 2 ) + c ) * 2 * at[0] + ( -2 * pow( c, 3 ) + 3 * pow( c, 2 ) ) * b[0] + ( pow( c, 3 ) - pow( c, 2 ) ) * 2 * bt[0], ( v )[1] = ( 2 * pow( c, 3 ) - 3 * pow( c, 2 ) + 1 ) * a[1] + ( pow( c, 3 ) - 2 * pow( c, 2 ) + c ) * 2 * at[1] + ( -2 * pow( c, 3 ) + 3 * pow( c, 2 ) ) * b[1] + ( pow( c, 3 ) - pow( c, 2 ) ) * 2 * bt[1], ( v )[2] = ( 2 * pow( c, 3 ) - 3 * pow( c, 2 ) + 1 ) * a[2] + ( pow( c, 3 ) - 2 * pow( c, 2 ) + c ) * 2 * at[2] + ( -2 * pow( c, 3 ) + 3 * pow( c, 2 ) ) * b[2] + ( pow( c, 3 ) - pow( c, 2 ) ) * 2 * bt[2] )

					float lerpspline, A, B, C, n1, n2, n3;
					cg_democam_t *previouscam = NULL;
					cg_democam_t *secondnextcam = NULL;

					if( nextcam ) {
						secondnextcam = CG_Democam_FindNext( nextcam->timeStamp );
					}
					if( currentcam->timeStamp > 0 ) {
						previouscam = CG_Democam_FindCurrent( currentcam->timeStamp - 1 );
					}

					if( !previouscam && nextcam && !secondnextcam ) {
						lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
						lerpspline = lerpfrac;
					} else if( !previouscam && nextcam && secondnextcam ) {
						n1 = nextcam->timeStamp - currentcam->timeStamp;
						n2 = secondnextcam->timeStamp - nextcam->timeStamp;
						A = n1 * ( n1 - n2 ) / ( pow( n1, 2 ) + n1 * n2 - n1 - n2 );
						B = ( 2 * n1 * n2 - n1 - n2 ) / ( pow( n1, 2 ) + n1 * n2 - n1 - n2 );
						lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
						lerpspline = A * pow( lerpfrac, 2 ) + B * lerpfrac;
					} else if( previouscam && nextcam && !secondnextcam ) {
						n2 = currentcam->timeStamp - previouscam->timeStamp;
						n3 = nextcam->timeStamp - currentcam->timeStamp;
						A = n3 * ( n2 - n3 ) / ( -n2 - n3 + n2 * n3 + pow( n3, 2 ) );
						B = -1 / ( -n2 - n3 + n2 * n3 + pow( n3, 2 ) ) * ( n2 + n3 - 2 * pow( n3, 2 ) );
						lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
						lerpspline = A * pow( lerpfrac, 2 ) + B * lerpfrac;
					} else if( previouscam && nextcam && secondnextcam ) {
						n1 = currentcam->timeStamp - previouscam->timeStamp;
						n2 = nextcam->timeStamp - currentcam->timeStamp;
						n3 = secondnextcam->timeStamp - nextcam->timeStamp;
						A = -2 * pow( n2, 2 ) * ( -pow( n2, 2 ) + n1 * n3 ) / ( 2 * n2 * n3 + pow( n2, 3 ) * n3 - 3 * pow( n2, 2 ) * n1 + n1 * pow( n2, 3 ) + 2 * n1 * n2 - 3 * pow( n2, 2 ) * n3 - 3 * pow( n2, 3 ) + 2 * pow( n2, 2 ) + pow( n2, 4 ) + n1 * pow( n2, 2 ) * n3 - 3 * n1 * n2 * n3 + 2 * n1 * n3 );
						B = pow( n2, 2 ) * ( -2 * n1 - 3 * pow( n2, 2 ) - n2 * n3 + 2 * n3 + 3 * n1 * n3 + n1 * n2 ) / ( 2 * n2 * n3 + pow( n2, 3 ) * n3 - 3 * pow( n2, 2 ) * n1 + n1 * pow( n2, 3 ) + 2 * n1 * n2 - 3 * pow( n2, 2 ) * n3 - 3 * pow( n2, 3 ) + 2 * pow( n2, 2 ) + pow( n2, 4 ) + n1 * pow( n2, 2 ) * n3 - 3 * n1 * n2 * n3 + 2 * n1 * n3 );
						C = -( pow( n2, 2 ) * n1 - 2 * n1 * n2 + 3 * n1 * n2 * n3 - 2 * n1 * n3 - 2 * pow( n2, 4 ) + 3 * pow( n2, 3 ) - 2 * pow( n2, 3 ) * n3 + 5 * pow( n2, 2 ) * n3 - 2 * pow( n2, 2 ) - 2 * n2 * n3 ) / ( 2 * n2 * n3 + pow( n2, 3 ) * n3 - 3 * pow( n2, 2 ) * n1 + n1 * pow( n2, 3 ) + 2 * n1 * n2 - 3 * pow( n2, 2 ) * n3 - 3 * pow( n2, 3 ) + 2 * pow( n2, 2 ) + pow( n2, 4 ) + n1 * pow( n2, 2 ) * n3 - 3 * n1 * n2 * n3 + 2 * n1 * n3 );
						lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp );
						lerpspline = A * pow( lerpfrac, 3 ) + B * pow( lerpfrac, 2 ) + C * lerpfrac;
					} else {
						lerpfrac = 0;
						lerpspline = 0;
					}


					VectorHermiteInterp( currentcam->origin, currentcam->tangent, nextcam->origin, nextcam->tangent, lerpspline, cam_origin );
					if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) {
						VectorHermiteInterp( currentcam->angles, currentcam->angles_tangent, nextcam->angles, nextcam->angles_tangent, lerpspline, cam_angles );
					}
					cam_fov = (float)currentcam->fov + (float)( nextcam->fov - currentcam->fov ) * lerpfrac;
#undef VectorHermiteInterp
				}

				// set velocity
				VectorSubtract( cam_origin, v, cam_velocity );
				VectorScale( cam_velocity, 1.0f / (float)cg.frameTime, cam_velocity );
				break;

			case DEMOCAM_ORBITAL:
				viewType = VIEWDEF_DEMOCAM;
				cam_POVent = 0;
				cam_fov = currentcam->fov;
				VectorCopy( cam_origin, v );

				if( !currentcam->trackEnt || currentcam->trackEnt >= MAX_EDICTS ) {
					CG_Printf( "Warning: CG_DemoCam: orbital cam needs a track entity set\n" );
					VectorCopy( currentcam->origin, cam_origin );
					VectorClear( cam_angles );
					VectorClear( cam_velocity );
				} else {
					vec3_t center, forward;
					struct cmodel_s *cmodel;
					const float ft = (float)cg.frameTime * 0.001f;

					// find the trackEnt origin
					VectorLerp( cg_entities[currentcam->trackEnt].prev.origin, cg.lerpfrac, cg_entities[currentcam->trackEnt].current.origin, center );

					// if having a bounding box, look to its center
					if( ( cmodel = CG_CModelForEntity( currentcam->trackEnt ) ) != NULL ) {
						vec3_t mins, maxs;
						trap_CM_InlineModelBounds( cmodel, mins, maxs );
						for( i = 0; i < 3; i++ )
							center[i] += ( mins[i] + maxs[i] );
					}

					if( !cam_orbital_radius ) {
						// cam is just started, find distance from cam to trackEnt and keep it as radius
						VectorSubtract( currentcam->origin, center, forward );
						cam_orbital_radius = VectorNormalize( forward );
						VecToAngles( forward, cam_orbital_angles );
					}

					for( i = 0; i < 3; i++ ) {
						cam_orbital_angles[i] += currentcam->angles[i] * ft;
						cam_orbital_angles[i] = AngleNormalize360( cam_orbital_angles[i] );
					}

					AngleVectors( cam_orbital_angles, forward, NULL, NULL );
					VectorMA( center, cam_orbital_radius, forward, cam_origin );

					// lookat
					VectorInverse( forward );
					VecToAngles( forward, cam_angles );
				}

				// set velocity
				VectorSubtract( cam_origin, v, cam_velocity );
				VectorScale( cam_velocity, 1.0f / ( cg.frameTime * 1000.0f ), cam_velocity );
				break;

			default:
				break;
		}

		if( currentcam->type != DEMOCAM_ORBITAL ) {
			VectorClear( cam_orbital_angles );
			cam_orbital_radius = 0;
		}
	}

	return viewType;
}
Beispiel #7
0
/**
 * @brief G_AdjustSingleClientPosition
 * @param[in,out] ent
 * @param[in] time
 */
static void G_AdjustSingleClientPosition(gentity_t *ent, int time)
{
	int i, j;

	if (time > level.time)
	{
		time = level.time;
	} // no lerping forward....

	if (!G_AntilagSafe(ent))
	{
		return;
	}

	// find a pair of markers which bound the requested time
	i = j = ent->client->topMarker;
	do
	{
		if (ent->client->clientMarkers[i].time <= time)
		{
			break;
		}

		j = i;
		i--;
		if (i < 0)
		{
			i = MAX_CLIENT_MARKERS - 1;
		}
	}
	while (i != ent->client->topMarker);

	if (i == j)     // oops, no valid stored markers
	{
		return;
	}

	// save current position to backup
	if (ent->client->backupMarker.time != level.time)
	{
		VectorCopy(ent->r.currentOrigin, ent->client->backupMarker.origin);
		VectorCopy(ent->r.mins, ent->client->backupMarker.mins);
		VectorCopy(ent->r.maxs, ent->client->backupMarker.maxs);
		// Head, Legs
		VectorCopy(ent->client->ps.viewangles, ent->client->backupMarker.viewangles);
		ent->client->backupMarker.eFlags     = ent->client->ps.eFlags;
		ent->client->backupMarker.pm_flags   = ent->client->ps.pm_flags;
		ent->client->backupMarker.viewheight = ent->client->ps.viewheight;

		ent->client->backupMarker.time = level.time;

		// Torso Markers
		ent->client->backupMarker.torsoOldFrameModel = ent->torsoFrame.oldFrameModel;
		ent->client->backupMarker.torsoFrameModel    = ent->torsoFrame.frameModel;
		ent->client->backupMarker.torsoOldFrame      = ent->torsoFrame.oldFrame;
		ent->client->backupMarker.torsoFrame         = ent->torsoFrame.frame;
		ent->client->backupMarker.torsoOldFrameTime  = ent->torsoFrame.oldFrameTime;
		ent->client->backupMarker.torsoFrameTime     = ent->torsoFrame.frameTime;
		ent->client->backupMarker.torsoYawAngle      = ent->torsoFrame.yawAngle;
		ent->client->backupMarker.torsoPitchAngle    = ent->torsoFrame.pitchAngle;
		ent->client->backupMarker.torsoYawing        = ent->torsoFrame.yawing;
		ent->client->backupMarker.torsoPitching      = ent->torsoFrame.pitching;

		// Legs Markers
		ent->client->backupMarker.legsOldFrameModel = ent->legsFrame.oldFrameModel;
		ent->client->backupMarker.legsFrameModel    = ent->legsFrame.frameModel;
		ent->client->backupMarker.legsOldFrame      = ent->legsFrame.oldFrame;
		ent->client->backupMarker.legsFrame         = ent->legsFrame.frame;
		ent->client->backupMarker.legsOldFrameTime  = ent->legsFrame.oldFrameTime;
		ent->client->backupMarker.legsFrameTime     = ent->legsFrame.frameTime;
		ent->client->backupMarker.legsYawAngle      = ent->legsFrame.yawAngle;
		ent->client->backupMarker.legsPitchAngle    = ent->legsFrame.pitchAngle;
		ent->client->backupMarker.legsYawing        = ent->legsFrame.yawing;
		ent->client->backupMarker.legsPitching      = ent->legsFrame.pitching;
	}

	if (i != ent->client->topMarker)
	{
		float frac = (float)(time - ent->client->clientMarkers[i].time) /
		             (float)(ent->client->clientMarkers[j].time - ent->client->clientMarkers[i].time);

		//LerpPosition(ent->client->clientMarkers[i].origin, ent->client->clientMarkers[j].origin, frac, ent->r.currentOrigin);
		//LerpPosition(ent->client->clientMarkers[i].mins, ent->client->clientMarkers[j].mins, frac, ent->r.mins);
		//LerpPosition(ent->client->clientMarkers[i].maxs, ent->client->clientMarkers[j].maxs, frac, ent->r.maxs);

		// Using TimeShiftLerp since it follows the client exactly meaning less roundoff error
		TimeShiftLerp(
		    ent->client->clientMarkers[i].origin,
		    ent->client->clientMarkers[j].origin,
		    frac,
		    ent->r.currentOrigin);
		TimeShiftLerp(
		    ent->client->clientMarkers[i].mins,
		    ent->client->clientMarkers[j].mins,
		    frac,
		    ent->r.mins);
		TimeShiftLerp(
		    ent->client->clientMarkers[i].maxs,
		    ent->client->clientMarkers[j].maxs,
		    frac,
		    ent->r.maxs);

		// These are for Head / Legs
		ent->client->ps.viewangles[0] = LerpAngle(
		    ent->client->clientMarkers[i].viewangles[0],
		    ent->client->clientMarkers[j].viewangles[0],
		    frac);
		ent->client->ps.viewangles[1] = LerpAngle(
		    ent->client->clientMarkers[i].viewangles[1],
		    ent->client->clientMarkers[j].viewangles[1],
		    frac);
		ent->client->ps.viewangles[2] = LerpAngle(
		    ent->client->clientMarkers[i].viewangles[2],
		    ent->client->clientMarkers[j].viewangles[2],
		    frac);
		// Set the ints to the closest ones in time since you can't lerp them.
		if ((ent->client->clientMarkers[j].time - time) < (time - ent->client->clientMarkers[i].time))
		{
			ent->client->ps.eFlags     = ent->client->clientMarkers[j].eFlags;
			ent->client->ps.pm_flags   = ent->client->clientMarkers[j].pm_flags;
			ent->client->ps.viewheight = ent->client->clientMarkers[j].viewheight;

			// Torso Markers
			ent->torsoFrame.oldFrameModel = ent->client->clientMarkers[j].torsoOldFrameModel;
			ent->torsoFrame.frameModel    = ent->client->clientMarkers[j].torsoFrameModel;
			ent->torsoFrame.oldFrame      = ent->client->clientMarkers[j].torsoOldFrame;
			ent->torsoFrame.frame         = ent->client->clientMarkers[j].torsoFrame;
			ent->torsoFrame.oldFrameTime  = ent->client->clientMarkers[j].torsoOldFrameTime;
			ent->torsoFrame.frameTime     = ent->client->clientMarkers[j].torsoFrameTime;
			ent->torsoFrame.yawAngle      = ent->client->clientMarkers[j].torsoYawAngle;
			ent->torsoFrame.pitchAngle    = ent->client->clientMarkers[j].torsoPitchAngle;
			ent->torsoFrame.yawing        = ent->client->clientMarkers[j].torsoYawing;
			ent->torsoFrame.pitching      = ent->client->clientMarkers[j].torsoPitching;

			// Legs Markers
			ent->legsFrame.oldFrameModel = ent->client->clientMarkers[j].legsOldFrameModel;
			ent->legsFrame.frameModel    = ent->client->clientMarkers[j].legsFrameModel;
			ent->legsFrame.oldFrame      = ent->client->clientMarkers[j].legsOldFrame;
			ent->legsFrame.frame         = ent->client->clientMarkers[j].legsFrame;
			ent->legsFrame.oldFrameTime  = ent->client->clientMarkers[j].legsOldFrameTime;
			ent->legsFrame.frameTime     = ent->client->clientMarkers[j].legsFrameTime;
			ent->legsFrame.yawAngle      = ent->client->clientMarkers[j].legsYawAngle;
			ent->legsFrame.pitchAngle    = ent->client->clientMarkers[j].legsPitchAngle;
			ent->legsFrame.yawing        = ent->client->clientMarkers[j].legsYawing;
			ent->legsFrame.pitching      = ent->client->clientMarkers[j].legsPitching;

			// time stamp for BuildHead/Leg
			ent->timeShiftTime = ent->client->clientMarkers[j].time;

		}
		else
		{
			ent->client->ps.eFlags     = ent->client->clientMarkers[i].eFlags;
			ent->client->ps.pm_flags   = ent->client->clientMarkers[i].pm_flags;
			ent->client->ps.viewheight = ent->client->clientMarkers[i].viewheight;

			// Torso Markers
			ent->torsoFrame.oldFrameModel = ent->client->clientMarkers[i].torsoOldFrameModel;
			ent->torsoFrame.frameModel    = ent->client->clientMarkers[i].torsoFrameModel;
			ent->torsoFrame.oldFrame      = ent->client->clientMarkers[i].torsoOldFrame;
			ent->torsoFrame.frame         = ent->client->clientMarkers[i].torsoFrame;
			ent->torsoFrame.oldFrameTime  = ent->client->clientMarkers[i].torsoOldFrameTime;
			ent->torsoFrame.frameTime     = ent->client->clientMarkers[i].torsoFrameTime;
			ent->torsoFrame.yawAngle      = ent->client->clientMarkers[i].torsoYawAngle;
			ent->torsoFrame.pitchAngle    = ent->client->clientMarkers[i].torsoPitchAngle;
			ent->torsoFrame.yawing        = ent->client->clientMarkers[i].torsoYawing;
			ent->torsoFrame.pitching      = ent->client->clientMarkers[i].torsoPitching;

			// Legs Markers
			ent->legsFrame.oldFrameModel = ent->client->clientMarkers[i].legsOldFrameModel;
			ent->legsFrame.frameModel    = ent->client->clientMarkers[i].legsFrameModel;
			ent->legsFrame.oldFrame      = ent->client->clientMarkers[i].legsOldFrame;
			ent->legsFrame.frame         = ent->client->clientMarkers[i].legsFrame;
			ent->legsFrame.oldFrameTime  = ent->client->clientMarkers[i].legsOldFrameTime;
			ent->legsFrame.frameTime     = ent->client->clientMarkers[i].legsFrameTime;
			ent->legsFrame.yawAngle      = ent->client->clientMarkers[i].legsYawAngle;
			ent->legsFrame.pitchAngle    = ent->client->clientMarkers[i].legsPitchAngle;
			ent->legsFrame.yawing        = ent->client->clientMarkers[i].legsYawing;
			ent->legsFrame.pitching      = ent->client->clientMarkers[i].legsPitching;

			// time stamp for BuildHead/Leg
			ent->timeShiftTime = ent->client->clientMarkers[i].time;
		}

		/* FIXME
		if ( debugger && debugger->client) {
		    // print some debugging stuff exactly like what the client does
		    // it starts with "Rec:" to let you know it backward-reconciled
		    char msg[2048];
		    Com_sprintf( msg, sizeof(msg),
		        "print \"^1Rec: time: %d, j: %d, k: %d, origin: %0.2f %0.2f %0.2f\n"
		        "^2frac: %0.4f, origin1: %0.2f %0.2f %0.2f, origin2: %0.2f %0.2f %0.2f\n"
		        "^7level.time: %d, est time: %d, level.time delta: %d, est real ping: %d\n\"",
		        time, ent->client->clientMarkers[i].time, ent->client->clientMarkers[j].time,
		        ent->r.currentOrigin[0], ent->r.currentOrigin[1], ent->r.currentOrigin[2],
		        frac,
		        ent->client->clientMarkers[i].origin[0],
		        ent->client->clientMarkers[i].origin[1],
		        ent->client->clientMarkers[i].origin[2],
		        ent->client->clientMarkers[j].origin[0],
		        ent->client->clientMarkers[j].origin[1],
		        ent->client->clientMarkers[j].origin[2],
		        level.time, level.time + debugger->client->frameOffset,
		        level.time - time, level.time + debugger->client->frameOffset - time);

		    trap_SendServerCommand( debugger - g_entities, msg );
		}
		*/
	}
	else
	{
		VectorCopy(ent->client->clientMarkers[j].origin, ent->r.currentOrigin);
		VectorCopy(ent->client->clientMarkers[j].mins, ent->r.mins);
		VectorCopy(ent->client->clientMarkers[j].maxs, ent->r.maxs);

		// BuildHead/Legs uses these
		VectorCopy(ent->client->clientMarkers[j].viewangles, ent->client->ps.viewangles);
		ent->client->ps.eFlags     = ent->client->clientMarkers[j].eFlags;
		ent->client->ps.pm_flags   = ent->client->clientMarkers[j].pm_flags;
		ent->client->ps.viewheight = ent->client->clientMarkers[j].viewheight;

		// Torso Markers
		ent->torsoFrame.oldFrameModel = ent->client->clientMarkers[j].torsoOldFrameModel;
		ent->torsoFrame.frameModel    = ent->client->clientMarkers[j].torsoFrameModel;
		ent->torsoFrame.oldFrame      = ent->client->clientMarkers[j].torsoOldFrame;
		ent->torsoFrame.frame         = ent->client->clientMarkers[j].torsoFrame;
		ent->torsoFrame.oldFrameTime  = ent->client->clientMarkers[j].torsoOldFrameTime;
		ent->torsoFrame.frameTime     = ent->client->clientMarkers[j].torsoFrameTime;
		ent->torsoFrame.yawAngle      = ent->client->clientMarkers[j].torsoYawAngle;
		ent->torsoFrame.pitchAngle    = ent->client->clientMarkers[j].torsoPitchAngle;
		ent->torsoFrame.yawing        = ent->client->clientMarkers[j].torsoYawing;
		ent->torsoFrame.pitching      = ent->client->clientMarkers[j].torsoPitching;

		// Legs Markers
		ent->legsFrame.oldFrameModel = ent->client->clientMarkers[j].legsOldFrameModel;
		ent->legsFrame.frameModel    = ent->client->clientMarkers[j].legsFrameModel;
		ent->legsFrame.oldFrame      = ent->client->clientMarkers[j].legsOldFrame;
		ent->legsFrame.frame         = ent->client->clientMarkers[j].legsFrame;
		ent->legsFrame.oldFrameTime  = ent->client->clientMarkers[j].legsOldFrameTime;
		ent->legsFrame.frameTime     = ent->client->clientMarkers[j].legsFrameTime;
		ent->legsFrame.yawAngle      = ent->client->clientMarkers[j].legsYawAngle;
		ent->legsFrame.pitchAngle    = ent->client->clientMarkers[j].legsPitchAngle;
		ent->legsFrame.yawing        = ent->client->clientMarkers[j].legsYawing;
		ent->legsFrame.pitching      = ent->client->clientMarkers[j].legsPitching;

		// time stamp for BuildHead/Leg
		ent->timeShiftTime = ent->client->clientMarkers[j].time;
	}

	trap_LinkEntity(ent);
}
Beispiel #8
0
void G_AdjustSingleClientPosition( gentity_t* ent, int time, gentity_t* debugger) {
	int	i, j;
	// unlagged analogies: antilag i = unlagged j, antilag j = unlagged k

	if( time > level.time ) {
		time = level.time;
	} // no lerping forward.... You mean extrapolating, not lerping (inter)

	if(!G_AntilagSafe(ent)) return;

	// find a pair of markers which bound the requested time
	i = j = ent->client->topMarker;
	do {
		if( ent->client->clientMarkers[i].time <= time ) {
			break;
		}

		j = i;
		i--;
		if( i < 0 ) {
			i = MAX_CLIENT_MARKERS - 1;
		}
	} while( i != ent->client->topMarker );

	if( i == j ) { // oops, no valid stored markers
		return;
	}

	// josh: from unlagged make sure it doesn't get backed-up twice
	if ( ent->client->backupMarker.time != level.time ) {
		VectorCopy(ent->r.currentOrigin,	ent->client->backupMarker.origin);
		VectorCopy(ent->r.mins,				ent->client->backupMarker.mins);
		VectorCopy(ent->r.maxs,				ent->client->backupMarker.maxs);
		//josh: for Head, Legs
		VectorCopy(ent->client->ps.viewangles,
			ent->client->backupMarker.viewangles);
		ent->client->backupMarker.eFlags = ent->client->ps.eFlags;
		ent->client->backupMarker.pm_flags = ent->client->ps.pm_flags;
		ent->client->backupMarker.viewheight = ent->client->ps.viewheight;
		// josh: This was missing, but needed or else no readjustment
		ent->client->backupMarker.time = level.time;

		// forty - realistic hitboxes - Torso Markers
		ent->client->backupMarker.torsoOldFrameModel	= ent->torsoFrame.oldFrameModel;
		ent->client->backupMarker.torsoFrameModel 	= ent->torsoFrame.frameModel;
		ent->client->backupMarker.torsoOldFrame		= ent->torsoFrame.oldFrame;
		ent->client->backupMarker.torsoFrame		= ent->torsoFrame.frame;
		ent->client->backupMarker.torsoOldFrameTime	= ent->torsoFrame.oldFrameTime;
		ent->client->backupMarker.torsoFrameTime	= ent->torsoFrame.frameTime;
		ent->client->backupMarker.torsoYawAngle		= ent->torsoFrame.yawAngle; 
		ent->client->backupMarker.torsoPitchAngle	= ent->torsoFrame.pitchAngle;
		ent->client->backupMarker.torsoYawing		= ent->torsoFrame.yawing;
		ent->client->backupMarker.torsoPitching		= ent->torsoFrame.pitching;

 		// forty - realistic hitboxes - Legs Markers
		ent->client->backupMarker.legsOldFrameModel	= ent->legsFrame.oldFrameModel;
		ent->client->backupMarker.legsFrameModel 	= ent->legsFrame.frameModel;
		ent->client->backupMarker.legsOldFrame		= ent->legsFrame.oldFrame;
		ent->client->backupMarker.legsFrame		= ent->legsFrame.frame;
		ent->client->backupMarker.legsOldFrameTime	= ent->legsFrame.oldFrameTime;
		ent->client->backupMarker.legsFrameTime		= ent->legsFrame.frameTime;
		ent->client->backupMarker.legsYawAngle		= ent->legsFrame.yawAngle; 
		ent->client->backupMarker.legsPitchAngle	= ent->legsFrame.pitchAngle;
		ent->client->backupMarker.legsYawing		= ent->legsFrame.yawing;
		ent->client->backupMarker.legsPitching		= ent->legsFrame.pitching;
	}

	if(i != ent->client->topMarker) {
		//float frac = ((float)(ent->client->clientMarkers[j].time - time)) / (ent->client->clientMarkers[j].time - ent->client->clientMarkers[i].time);
		//josh: reversing the order to better match the client and prevent 
		//roundoff error
		float	frac = (float)(time - ent->client->clientMarkers[i].time) /
				(float)(ent->client->clientMarkers[j].time - ent->client->clientMarkers[i].time);

		//LerpPosition(ent->client->clientMarkers[i].origin,		ent->client->clientMarkers[j].origin,	frac,	ent->r.currentOrigin);
		//LerpPosition(ent->client->clientMarkers[i].mins,		ent->client->clientMarkers[j].mins,		frac,	ent->r.mins);
		//LerpPosition(ent->client->clientMarkers[i].maxs,		ent->client->clientMarkers[j].maxs,		frac,	ent->r.maxs);
		//josh: Using TimeShiftLerp since it follows the client exactly
		//meaning less roundoff error
		TimeShiftLerp(
				ent->client->clientMarkers[i].origin,		
				ent->client->clientMarkers[j].origin,	
				frac,	
				ent->r.currentOrigin);
		TimeShiftLerp(
				ent->client->clientMarkers[i].mins,
				ent->client->clientMarkers[j].mins,
				frac,
				ent->r.mins);
		TimeShiftLerp(
				ent->client->clientMarkers[i].maxs,
				ent->client->clientMarkers[j].maxs,
				frac,
				ent->r.maxs);

		// These are for Head / Legs
		ent->client->ps.viewangles[0] = LerpAngle(
				ent->client->clientMarkers[i].viewangles[0],
				ent->client->clientMarkers[j].viewangles[0],
				frac);
		ent->client->ps.viewangles[1] = LerpAngle(
				ent->client->clientMarkers[i].viewangles[1],
				ent->client->clientMarkers[j].viewangles[1],
				frac);
		ent->client->ps.viewangles[2] = LerpAngle(
				ent->client->clientMarkers[i].viewangles[2],
				ent->client->clientMarkers[j].viewangles[2],
				frac);
		// josh: Set the ints to the closest ones in time since you can't
		//       lerp them.
		if((ent->client->clientMarkers[j].time - time)
			< (time - ent->client->clientMarkers[i].time)) {

			ent->client->ps.eFlags =
				ent->client->clientMarkers[j].eFlags;
			ent->client->ps.pm_flags =
				ent->client->clientMarkers[j].pm_flags;
			ent->client->ps.viewheight =
				ent->client->clientMarkers[j].viewheight;

			// forty - realistic hitboxes - Torso Markers
			ent->torsoFrame.oldFrameModel	= ent->client->clientMarkers[j].torsoOldFrameModel;
			ent->torsoFrame.frameModel	= ent->client->clientMarkers[j].torsoFrameModel;
			ent->torsoFrame.oldFrame	= ent->client->clientMarkers[j].torsoOldFrame;
			ent->torsoFrame.frame		= ent->client->clientMarkers[j].torsoFrame;
			ent->torsoFrame.oldFrameTime	= ent->client->clientMarkers[j].torsoOldFrameTime;
			ent->torsoFrame.frameTime	= ent->client->clientMarkers[j].torsoFrameTime;
			ent->torsoFrame.yawAngle	= ent->client->clientMarkers[j].torsoYawAngle; 
			ent->torsoFrame.pitchAngle	= ent->client->clientMarkers[j].torsoPitchAngle;
			ent->torsoFrame.yawing		= ent->client->clientMarkers[j].torsoYawing;
			ent->torsoFrame.pitching	= ent->client->clientMarkers[j].torsoPitching;
	
			// forty - realistic hitboxes - Legs Markers
			ent->legsFrame.oldFrameModel	= ent->client->clientMarkers[j].legsOldFrameModel;
			ent->legsFrame.frameModel	= ent->client->clientMarkers[j].legsFrameModel;
			ent->legsFrame.oldFrame		= ent->client->clientMarkers[j].legsOldFrame;
			ent->legsFrame.frame		= ent->client->clientMarkers[j].legsFrame;
			ent->legsFrame.oldFrameTime	= ent->client->clientMarkers[j].legsOldFrameTime;
			ent->legsFrame.frameTime	= ent->client->clientMarkers[j].legsFrameTime;
			ent->legsFrame.yawAngle		= ent->client->clientMarkers[j].legsYawAngle; 
			ent->legsFrame.pitchAngle	= ent->client->clientMarkers[j].legsPitchAngle;
			ent->legsFrame.yawing		= ent->client->clientMarkers[j].legsYawing;
			ent->legsFrame.pitching		= ent->client->clientMarkers[j].legsPitching;

			// forty - realistic hitboxes - time stamp for BuildHead/Leg
			ent->timeShiftTime = ent->client->clientMarkers[j].time;

		} else {
			ent->client->ps.eFlags =
				ent->client->clientMarkers[i].eFlags;
			ent->client->ps.pm_flags =
				ent->client->clientMarkers[i].pm_flags;
			ent->client->ps.viewheight =
				ent->client->clientMarkers[i].viewheight;

			// forty - realistic hitboxes - Torso Markers
			ent->torsoFrame.oldFrameModel	= ent->client->clientMarkers[i].torsoOldFrameModel;
			ent->torsoFrame.frameModel	= ent->client->clientMarkers[i].torsoFrameModel;
			ent->torsoFrame.oldFrame	= ent->client->clientMarkers[i].torsoOldFrame;
			ent->torsoFrame.frame		= ent->client->clientMarkers[i].torsoFrame;
			ent->torsoFrame.oldFrameTime	= ent->client->clientMarkers[i].torsoOldFrameTime;
			ent->torsoFrame.frameTime	= ent->client->clientMarkers[i].torsoFrameTime;
			ent->torsoFrame.yawAngle	= ent->client->clientMarkers[i].torsoYawAngle; 
			ent->torsoFrame.pitchAngle	= ent->client->clientMarkers[i].torsoPitchAngle;
			ent->torsoFrame.yawing		= ent->client->clientMarkers[i].torsoYawing;
			ent->torsoFrame.pitching	= ent->client->clientMarkers[i].torsoPitching;
	
			// forty - realistic hitboxes - Legs Markers
			ent->legsFrame.oldFrameModel	= ent->client->clientMarkers[i].legsOldFrameModel;
			ent->legsFrame.frameModel	= ent->client->clientMarkers[i].legsFrameModel;
			ent->legsFrame.oldFrame		= ent->client->clientMarkers[i].legsOldFrame;
			ent->legsFrame.frame		= ent->client->clientMarkers[i].legsFrame;
			ent->legsFrame.oldFrameTime	= ent->client->clientMarkers[i].legsOldFrameTime;
			ent->legsFrame.frameTime	= ent->client->clientMarkers[i].legsFrameTime;
			ent->legsFrame.yawAngle		= ent->client->clientMarkers[i].legsYawAngle; 
			ent->legsFrame.pitchAngle	= ent->client->clientMarkers[i].legsPitchAngle;
			ent->legsFrame.yawing		= ent->client->clientMarkers[i].legsYawing;
			ent->legsFrame.pitching		= ent->client->clientMarkers[i].legsPitching;
		
			// forty - realistic hitboxes - time stamp for BuildHead/Leg
			ent->timeShiftTime = ent->client->clientMarkers[i].time;

		}
		if ( debugger && debugger->client) {
			// print some debugging stuff exactly like what the client does
			// it starts with "Rec:" to let you know it backward-reconciled
			char msg[2048];
			Com_sprintf( msg, sizeof(msg),
				"print \"^1Rec: time: %d, j: %d, k: %d, origin: %0.2f %0.2f %0.2f\n"
				"^2frac: %0.4f, origin1: %0.2f %0.2f %0.2f, origin2: %0.2f %0.2f %0.2f\n"
				"^7level.time: %d, est time: %d, level.time delta: %d, est real ping: %d\n\"",
				time, ent->client->clientMarkers[i].time, ent->client->clientMarkers[j].time,
				ent->r.currentOrigin[0], ent->r.currentOrigin[1], ent->r.currentOrigin[2],
				frac,
				ent->client->clientMarkers[i].origin[0],
				ent->client->clientMarkers[i].origin[1],
				ent->client->clientMarkers[i].origin[2], 
				ent->client->clientMarkers[j].origin[0],
				ent->client->clientMarkers[j].origin[1],
				ent->client->clientMarkers[j].origin[2],
				level.time, level.time + debugger->client->frameOffset,
				level.time - time, level.time + debugger->client->frameOffset - time);

			trap_SendServerCommand( debugger - g_entities, msg );
		}
	} else {
		VectorCopy( ent->client->clientMarkers[j].origin, ent->r.currentOrigin );
		VectorCopy( ent->client->clientMarkers[j].mins,	ent->r.mins );
		VectorCopy( ent->client->clientMarkers[j].maxs,	ent->r.maxs );
		//// josh: BuildHead/Legs uses these
		VectorCopy(ent->client->clientMarkers[j].viewangles,
			ent->client->ps.viewangles);
		ent->client->ps.eFlags =
			ent->client->clientMarkers[j].eFlags;
		ent->client->ps.pm_flags =
			ent->client->clientMarkers[j].pm_flags;
		ent->client->ps.viewheight =
			ent->client->clientMarkers[j].viewheight;

		// forty - realistic hitboxes - Torso Markers
		ent->torsoFrame.oldFrameModel	= ent->client->clientMarkers[j].torsoOldFrameModel;
		ent->torsoFrame.frameModel	= ent->client->clientMarkers[j].torsoFrameModel;
		ent->torsoFrame.oldFrame	= ent->client->clientMarkers[j].torsoOldFrame;
		ent->torsoFrame.frame		= ent->client->clientMarkers[j].torsoFrame;
		ent->torsoFrame.oldFrameTime	= ent->client->clientMarkers[j].torsoOldFrameTime;
		ent->torsoFrame.frameTime	= ent->client->clientMarkers[j].torsoFrameTime;
		ent->torsoFrame.yawAngle	= ent->client->clientMarkers[j].torsoYawAngle; 
		ent->torsoFrame.pitchAngle	= ent->client->clientMarkers[j].torsoPitchAngle;
		ent->torsoFrame.yawing		= ent->client->clientMarkers[j].torsoYawing;
		ent->torsoFrame.pitching	= ent->client->clientMarkers[j].torsoPitching;

		// forty - realistic hitboxes - Legs Markers
		ent->legsFrame.oldFrameModel	= ent->client->clientMarkers[j].legsOldFrameModel;
		ent->legsFrame.frameModel	= ent->client->clientMarkers[j].legsFrameModel;
		ent->legsFrame.oldFrame		= ent->client->clientMarkers[j].legsOldFrame;
		ent->legsFrame.frame		= ent->client->clientMarkers[j].legsFrame;
		ent->legsFrame.oldFrameTime	= ent->client->clientMarkers[j].legsOldFrameTime;
		ent->legsFrame.frameTime	= ent->client->clientMarkers[j].legsFrameTime;
		ent->legsFrame.yawAngle		= ent->client->clientMarkers[j].legsYawAngle; 
		ent->legsFrame.pitchAngle	= ent->client->clientMarkers[j].legsPitchAngle;
		ent->legsFrame.yawing		= ent->client->clientMarkers[j].legsYawing;
		ent->legsFrame.pitching		= ent->client->clientMarkers[j].legsPitching;

		// forty - realistic hitboxes - time stamp for BuildHead/Leg
		ent->timeShiftTime = ent->client->clientMarkers[j].time;

	}

	trap_LinkEntity( ent );
}
Beispiel #9
0
void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const entity_state_t *prev )
{
	float	m_fLerp;

	if( state->ed_type == ED_CLIENT && state->ed_flags & ESF_NO_PREDICTION )
		m_fLerp = 1.0f;
	else m_fLerp = GetLerpFrac();

	if( state->flags & FL_PROJECTILE && state->ed_flags & ( ESF_NO_PREDICTION|ESF_NODELTA ))
	{
		// cut rocket trail, dont pass it from teleport
		// FIXME: don't work
		g_pViewRenderBeams->KillDeadBeams( ent );		
	}

	// copy state to progs
	ent->v.modelindex = state->modelindex;
	ent->v.weaponmodel = state->weaponmodel;
	ent->v.sequence = state->sequence;
	ent->v.gaitsequence = state->gaitsequence;
	ent->v.body = state->body;
	ent->v.skin = state->skin;
	ent->v.effects = state->effects;
	ent->v.velocity = state->velocity;
	ent->v.basevelocity = state->basevelocity;
	ent->v.oldorigin = ent->v.origin;		// previous origin holds
	ent->v.mins = state->mins;
	ent->v.maxs = state->maxs;
	ent->v.framerate = state->framerate;
	ent->v.colormap = state->colormap; 
	ent->v.rendermode = state->rendermode; 
	ent->v.renderfx = state->renderfx; 
	ent->v.fov = state->fov; 
	ent->v.scale = state->scale; 
	ent->v.weapons = state->weapons;
	ent->v.gravity = state->gravity;
	ent->v.health = state->health;
	ent->v.solid = state->solid;
	ent->v.movetype = state->movetype;
	ent->v.flags = state->flags;
	ent->v.ideal_pitch = state->idealpitch;
	ent->v.animtime = state->animtime;
	ent->v.ltime = state->localtime;

	if( state->groundent != -1 )
		ent->v.groundentity = GetEntityByIndex( state->groundent );
	else ent->v.groundentity = NULL;

	if( state->aiment != -1 )
		ent->v.aiment = GetEntityByIndex( state->aiment );
	else ent->v.aiment = NULL;

	switch( ent->v.movetype )
	{
	case MOVETYPE_NONE:
	case MOVETYPE_STEP:
		// monster's steps will be interpolated on render-side
		ent->v.origin = state->origin;
		ent->v.angles = state->angles;
		ent->v.oldorigin = prev->origin;	// used for lerp 'monster view'
		ent->v.oldangles = prev->angles;	// used for lerp 'monster view'
		break;
	default:
		ent->v.angles = LerpAngle( prev->angles, state->angles, m_fLerp );
		ent->v.origin = LerpPoint( prev->origin, state->origin, m_fLerp );
		ent->v.basevelocity = LerpPoint( prev->basevelocity, state->basevelocity, m_fLerp );
		break;
	}

	// interpolate scale, renderamount etc
	ent->v.scale = LerpPoint( prev->scale, state->scale, m_fLerp );
	ent->v.rendercolor = LerpPoint( prev->rendercolor, state->rendercolor, m_fLerp );
	ent->v.renderamt = LerpPoint( prev->renderamt, state->renderamt, m_fLerp );

	if( ent->v.animtime )
	{
		// use normal studio lerping
		ent->v.frame = state->frame;
	}
	else
	{
		// round sprite and brushmodel frames
		ent->v.frame = Q_rint( state->frame );
	}

	switch( state->ed_type )
	{
	case ED_CLIENT:
		ent->v.punchangle = LerpAngle( prev->punch_angles, state->punch_angles, m_fLerp );
		ent->v.viewangles = LerpAngle( prev->viewangles, state->viewangles, m_fLerp );
		ent->v.view_ofs = LerpPoint( prev->viewoffset, state->viewoffset, m_fLerp );

		if( prev->fov != 90.0f && state->fov == 90.0f )
			ent->v.fov = state->fov; // fov is reset, so don't lerping
		else ent->v.fov = LerpPoint( prev->fov, state->fov, m_fLerp ); 
		ent->v.maxspeed = state->maxspeed;

		ent->v.iStepLeft = state->iStepLeft;
		ent->v.flFallVelocity = state->flFallVelocity;
		
		if( ent == GetLocalPlayer())
		{
			edict_t	*viewent = GetViewModel();

			// if viewmodel has changed update sequence here
			if( viewent->v.modelindex != state->viewmodel )
			{
//				ALERT( at_console, "Viewmodel changed\n" );
				SendWeaponAnim( viewent->v.sequence, viewent->v.body, viewent->v.framerate );
                              }
			// setup player viewmodel (only for local player!)
			viewent->v.modelindex = state->viewmodel;
			gHUD.m_flFOV = ent->v.fov; // keep client fov an actual
		}
		break;
	case ED_PORTAL:
	case ED_MOVER:
	case ED_BSPBRUSH:
		ent->v.movedir = BitsToDir( state->body );
		ent->v.oldorigin = state->oldorigin;
		break;
	case ED_SKYPORTAL:
		{
			skyportal_t *sky = &gpViewParams->skyportal;

			// setup sky portal
			sky->vieworg = ent->v.origin; 
			sky->viewanglesOffset.x = sky->viewanglesOffset.z = 0.0f;
			sky->viewanglesOffset.y = gHUD.m_flTime * ent->v.angles[1];
			sky->scale = (ent->v.scale ? 1.0f / ent->v.scale : 0.0f );	// critical stuff
			sky->fov = ent->v.fov;
		}
		break;
	case ED_BEAM:
		ent->v.oldorigin = state->oldorigin;	// beam endpoint
		ent->v.frags = state->gaitsequence;
		if( state->owner != -1 )
			ent->v.owner = GetEntityByIndex( state->owner );
		else ent->v.owner = NULL;

		// add server beam now
		g_pViewRenderBeams->AddServerBeam( ent );
		break;
	default:
		ent->v.movedir = Vector( 0, 0, 0 );
		break;
	}

	int	i;

	// copy blendings
	for( i = 0; i < MAXSTUDIOBLENDS; i++ )
		ent->v.blending[i] = state->blending[i];

	// copy controllers
	for( i = 0; i < MAXSTUDIOCONTROLLERS; i++ )
		ent->v.controller[i] = state->controller[i];

	// g-cont. moved here because we may needs apply null scale to skyportal
	if( ent->v.scale == 0.0f && ent->v.skin >= 0 ) ent->v.scale = 1.0f;	
	ent->v.pContainingEntity = ent;
}
Beispiel #10
0
void CG_LaserBeamEffect( centity_t *cent )
{
	struct sfx_s *sound = NULL;
	float range;
	trace_t trace;
	orientation_t projectsource;
	vec4_t color;
	vec3_t laserOrigin, laserAngles, laserPoint;
	int i, j;

	if( cent->localEffects[LOCALEFFECT_LASERBEAM] <= cg.time )
		return;

	laserOwner = cent;

	if( cg_teamColoredBeams->integer && ( cent->current.team == TEAM_ALPHA || cent->current.team == TEAM_BETA ) )
		CG_TeamColor( cent->current.team, color );
	else
		Vector4Set( color, 1, 1, 1, 1 );

	// interpolate the positions

	if( ISVIEWERENTITY( cent->current.number ) && !cg.view.thirdperson )
	{
		VectorCopy( cg.predictedPlayerState.pmove.origin, laserOrigin );
		laserOrigin[2] += cg.predictedPlayerState.viewheight;
		VectorCopy( cg.predictedPlayerState.viewangles, laserAngles );

		VectorLerp( cent->laserPointOld, cg.lerpfrac, cent->laserPoint, laserPoint );
	}
	else
	{
		VectorLerp( cent->laserOriginOld, cg.lerpfrac, cent->laserOrigin, laserOrigin );
		VectorLerp( cent->laserPointOld, cg.lerpfrac, cent->laserPoint, laserPoint );
		if( !cent->laserCurved )
		{
			vec3_t dir;

			// make up the angles from the start and end points (s->angles is not so precise)
			VectorSubtract( laserPoint, laserOrigin, dir );
			VecToAngles( dir, laserAngles );
		}
		else // use player entity angles
		{
			for( i = 0; i < 3; i++ )
				laserAngles[i] = LerpAngle( cent->prev.angles[i], cent->current.angles[i], cg.lerpfrac );
		}
	}

	if( !cent->laserCurved )
	{
		range = GS_GetWeaponDef( WEAP_LASERGUN )->firedef.timeout;

		if( cent->current.effects & EF_QUAD )
			sound = CG_MediaSfx( cgs.media.sfxLasergunStrongQuadHum );
		else
			sound = CG_MediaSfx( cgs.media.sfxLasergunStrongHum );

		// trace the beam: for tracing we use the real beam origin
		GS_TraceLaserBeam( &trace, laserOrigin, laserAngles, range, cent->current.number, 0, _LaserImpact );
		
		// draw the beam: for drawing we use the weapon projection source (already handles the case of viewer entity)
		if( !CG_PModel_GetProjectionSource( cent->current.number, &projectsource ) )
			VectorCopy( laserOrigin, projectsource.origin );

		CG_KillPolyBeamsByTag( cent->current.number );
		CG_LaserGunPolyBeam( projectsource.origin, trace.endpos, color, cent->current.number );
	}
	else
	{
		float frac, subdivisions = cg_laserBeamSubdivisions->integer;
		vec3_t from, dir, end, blendPoint;
		int passthrough = cent->current.number;
		vec3_t tmpangles, blendAngles;

		range = GS_GetWeaponDef( WEAP_LASERGUN )->firedef_weak.timeout;

		if( cent->current.effects & EF_QUAD )
			sound = CG_MediaSfx( cgs.media.sfxLasergunWeakQuadHum );
		else
			sound = CG_MediaSfx( cgs.media.sfxLasergunWeakHum );

		// trace the beam: for tracing we use the real beam origin
		GS_TraceCurveLaserBeam( &trace, laserOrigin, laserAngles, laserPoint, cent->current.number, 0, _LaserImpact );

		// draw the beam: for drawing we use the weapon projection source (already handles the case of viewer entity)
		if( !CG_PModel_GetProjectionSource( cent->current.number, &projectsource ) )
			VectorCopy( laserOrigin, projectsource.origin );

		if( subdivisions < CURVELASERBEAM_SUBDIVISIONS )
			subdivisions = CURVELASERBEAM_SUBDIVISIONS;

		CG_KillPolyBeamsByTag( cent->current.number );

		// we redraw the full beam again, and trace each segment for stop dead impact
		VectorCopy( laserPoint, blendPoint );
		VectorCopy( projectsource.origin, from );
		VectorSubtract( blendPoint, projectsource.origin, dir );
		VecToAngles( dir, blendAngles );

		for( i = 1; i <= (int)subdivisions; i++ )
		{
			frac = ( ( range/subdivisions )*(float)i ) / (float)range;

			for( j = 0; j < 3; j++ )
				tmpangles[j] = LerpAngle( laserAngles[j], blendAngles[j], frac );

			AngleVectors( tmpangles, dir, NULL, NULL );
			VectorMA( projectsource.origin, range * frac, dir, end );

			GS_TraceLaserBeam( &trace, from, tmpangles, DistanceFast( from, end ), passthrough, 0, NULL );
			CG_LaserGunPolyBeam( from, trace.endpos, color, cent->current.number );
			if( trace.fraction != 1.0f )
				break;

			passthrough = trace.ent;
			VectorCopy( trace.endpos, from );
		}
	}

	// enable continuous flash on the weapon owner
	if( cg_weaponFlashes->integer )
		cg_entPModels[cent->current.number].flash_time = cg.time + CG_GetWeaponInfo( WEAP_LASERGUN )->flashTime;

	if( sound )
	{
		if( ISVIEWERENTITY( cent->current.number ) )
			trap_S_AddLoopSound( sound, cent->current.number, 1.0, ATTN_NONE );
		else
			trap_S_AddLoopSound( sound, cent->current.number, 1.0, ATTN_STATIC );
	}

	laserOwner = NULL;
}
Beispiel #11
0
void Wolfcam_CheckNoMove (void)
{
	int clientNum;
	int i;
	const centity_t *cent;
	const entityState_t *es;
	entityState_t *nes;
	const entityState_t *nnes;
	qboolean inNextNextSnapshot;
	qboolean nextNextReset;

	cg.noMove = qfalse;
	cg.numNoMoveClients = 0;

	//if (cg.time < cgs.timeoutEndTime) {
	if (cg.snap->serverTime < cgs.timeoutEndTime) {
		return;
	}

	//FIXME other snaps as well?
	if (cg.snap->ps.pm_type == PM_INTERMISSION) {
		return;
	}

#if 1
	if (!cg.nextNextSnapValid) {
		//Com_Printf("FIXME Wolfcam_CheckNoMove() !cg.nextNextSnapValid\n");
		//CG_Abort();
		return;
	}
#endif

	if ((cg.snap->snapFlags ^ cg.nextSnap->snapFlags) & SNAPFLAG_SERVERCOUNT) {
		return;
	}

	if ((cg.nextSnap->snapFlags ^ cg.nextNextSnap->snapFlags) & SNAPFLAG_SERVERCOUNT) {
		nextNextReset = qtrue;
	} else {
		nextNextReset = qfalse;
	}

	for (clientNum = 0;  clientNum < MAX_CLIENTS;  clientNum++) {
		cent = &cg_entities[clientNum];

		if (!cent->inCurrentSnapshot) {
			continue;
		}

		// view switching
		if ((cg.snap->ps.clientNum != cg.nextSnap->ps.clientNum)  &&  (clientNum == cg.snap->ps.clientNum  ||  clientNum == cg.nextSnap->ps.clientNum)) {
            continue;
        }

		if (clientNum != cg.snap->ps.clientNum  &&  !cent->inNextSnapshot) {
			continue;
		}

#if 0
		if (clientNum == cg.nextSnap->ps.clientNum  &&  cg.snap->ps.clientNum != cg.nextSnap->ps.clientNum) {
			continue;
		}
#endif

		if (clientNum == cg.snap->ps.clientNum) {
			if ((cg.snap->ps.eFlags ^ cg.nextSnap->ps.eFlags) & EF_TELEPORT_BIT) {
				continue;
			}
			if (Distance(cg.snap->ps.origin, cg.nextSnap->ps.origin) == 0.0f  &&  VectorLength(cg.snap->ps.velocity) > 0.0  &&  VectorLength(cg.nextSnap->ps.velocity) > 0.0) {
				CG_LagometerMarkNoMove();
				cg.noMove = qtrue;
				wclients[clientNum].noMoveCount++;

				if (cg.snap->ps.clientNum != cg.nextNextSnap->ps.clientNum) {
					continue;
				}
				if ((cg.nextSnap->ps.eFlags ^ cg.nextNextSnap->ps.eFlags) & EF_TELEPORT_BIT) {
					continue;
				}
				if (nextNextReset) {
					continue;
				}
				if (cg_demoSmoothing.integer == 1) {
					cg.nextSnap->ps.origin[0] = cg.snap->ps.origin[0] + (cg.nextNextSnap->ps.origin[0] - cg.snap->ps.origin[0]) / 2;
					cg.nextSnap->ps.origin[1] = cg.snap->ps.origin[1] + (cg.nextNextSnap->ps.origin[1] - cg.snap->ps.origin[1]) / 2;
					cg.nextSnap->ps.origin[2] = cg.snap->ps.origin[2] + (cg.nextNextSnap->ps.origin[2] - cg.snap->ps.origin[2]) / 2;


					cg.nextSnap->ps.viewangles[0] = LerpAngle(cg.snap->ps.viewangles[0], cg.nextNextSnap->ps.viewangles[0], 0.5);
					cg.nextSnap->ps.viewangles[1] = LerpAngle(cg.snap->ps.viewangles[1], cg.nextNextSnap->ps.viewangles[1], 0.5);
					cg.nextSnap->ps.viewangles[2] = LerpAngle(cg.snap->ps.viewangles[2], cg.nextNextSnap->ps.viewangles[2], 0.5);
				}
			}
		} else {
			qboolean inSnapshot;
			qboolean inNextSnapshot;

			inSnapshot = qfalse;
			for (i = 0;  i < cg.snap->numEntities;  i++) {
				es = &cg.snap->entities[i];
				if (es->number == clientNum) {
					inSnapshot = qtrue;
					break;
				}
			}
			if (!inSnapshot) {
				CG_Printf("^1Wolfcam_CheckNoMove() not in snap %d\n", clientNum);
				//es = NULL;
				continue;  // shouldn't get here
			}

			inNextSnapshot = qfalse;
			for (i = 0;  i < cg.nextSnap->numEntities;  i++) {
				nes = &cg.nextSnap->entities[i];
				if (nes->number == clientNum) {
					inNextSnapshot = qtrue;
					break;
				}
			}
			if (!inNextSnapshot) {
				CG_Printf("^1Wolfcam_CheckNoMove() not in next snap %d : %d\n", clientNum, cent->inNextSnapshot);
				//nes = NULL;
				continue;  // shouldn't get here
			}

#if 0
			if (!nes) {
				Com_Printf("^3wtf:  clientNum %d  cg.nextSnap->numEntities %d\n", clientNum, cg.nextSnap->numEntities);
				continue;
			}
#endif

			inNextNextSnapshot = qfalse;
			for (i = 0;  i < cg.nextNextSnap->numEntities;  i++) {
				nnes = &cg.nextNextSnap->entities[i];
				if (nnes->number == clientNum) {
					inNextNextSnapshot = qtrue;
					break;
				}
			}
			if (!inNextNextSnapshot) {
				nnes = NULL;
			}

			if ((es->eFlags ^ nes->eFlags) & EF_TELEPORT_BIT) {
				continue;
			}

			if (Distance(es->pos.trBase, nes->pos.trBase) == 0.0f  &&  VectorLength(es->pos.trDelta) > 0.0  &&  VectorLength(nes->pos.trDelta) > 0.0) {

				wclients[clientNum].noMoveCount++;

				if (!inNextNextSnapshot) {
					continue;
				}
				if ((nes->eFlags ^ nnes->eFlags) & EF_TELEPORT_BIT) {
					continue;
				}
				if (nextNextReset) {
					continue;
				}
				if (cg_demoSmoothing.integer == 1) {
					nes->pos.trBase[0] = es->pos.trBase[0] + (nnes->pos.trBase[0] - es->pos.trBase[0]) / 2;
					nes->pos.trBase[1] = es->pos.trBase[1] + (nnes->pos.trBase[1] - es->pos.trBase[1]) / 2;
					nes->pos.trBase[2] = es->pos.trBase[2] + (nnes->pos.trBase[2] - es->pos.trBase[2]) / 2;

					nes->apos.trBase[0] = LerpAngle(es->apos.trBase[0], nnes->apos.trBase[0], 0.5f);
					nes->apos.trBase[1] = LerpAngle(es->apos.trBase[1], nnes->apos.trBase[1], 0.5f);
					nes->apos.trBase[2] = LerpAngle(es->apos.trBase[2], nnes->apos.trBase[2], 0.5f);
				}
			}
		}
	}
}
void CGCam_FollowUpdate ( void )
{
	vec3_t		center, dir, cameraAngles, vec, focus[MAX_CAMERA_GROUP_SUBJECTS];//No more than 16 subjects in a cameraGroup
	gentity_t	*from = NULL;
	centity_t	*fromCent = NULL;
	int			num_subjects = 0, i;
	
	if ( client_camera.cameraGroup && client_camera.cameraGroup[0] )
	{
		//Stay centered in my cameraGroup, if I have one
		while( NULL != (from = G_Find(from, FOFS(cameraGroup), client_camera.cameraGroup)))
		{
			/*
			if ( from->s.number == client_camera.aimEntNum )
			{//This is the misc_camera_focus, we'll be removing this ent altogether eventually
				continue;
			}
			*/

			if ( num_subjects >= MAX_CAMERA_GROUP_SUBJECTS )
			{
				gi.Printf(S_COLOR_RED"ERROR: Too many subjects in shot composition %s", client_camera.cameraGroup);
				break;
			}

			fromCent = &cg_entities[from->s.number];
			if ( !fromCent )
			{
				continue;
			}

			if ( from->s.pos.trType == TR_INTERPOLATE )
			{//use interpolated origin?
				VectorCopy(fromCent->lerpOrigin, focus[num_subjects]);
			}
			else
			{
				VectorCopy(from->currentOrigin, focus[num_subjects]);
			}
			//FIXME: make a list here of their s.numbers instead so we can do other stuff with the list below
			if ( from->client )
			{//Track to their eyes - FIXME: maybe go off a tag?
				//FIXME: 
				//Based on FOV and distance to subject from camera, pick the point that
				//keeps eyes 3/4 up from bottom of screen... what about bars?
				focus[num_subjects][2] += from->client->ps.viewheight;
			}
			num_subjects++;
		}

		if ( !num_subjects )	// Bad cameragroup 
		{
			gi.Printf(S_COLOR_RED"ERROR: Camera Focus unable to locate cameragroup: %s\n", client_camera.cameraGroup);
			return;
		}

		//Now average all points
		VectorCopy( focus[0], center );
		for( i = 1; i < num_subjects; i++ )
		{
			VectorAdd( focus[i], center, center );
		}
		VectorScale( center, 1.0f/((float)num_subjects), center );
	}
	else
	{
		return;
	}

	//Need to set a speed to keep a distance from
	//the subject- fixme: only do this if have a distance
	//set
	VectorSubtract( client_camera.subjectPos, center, vec );
	client_camera.subjectSpeed = VectorLengthSquared( vec ) * 100.0f / cg.frametime;

	VectorCopy( center, client_camera.subjectPos );

	VectorSubtract( center, cg.refdef.vieworg, dir );//can't use client_camera.origin because it's not updated until the end of the move.

	//Get desired angle
	vectoangles(dir, cameraAngles);
	
	if ( client_camera.followInitLerp )
	{//Lerping
		for( i = 0; i < 3; i++ )
		{
			cameraAngles[i] = LerpAngle( client_camera.angles[i], cameraAngles[i], cg.frametime/100.0f * client_camera.followSpeed/100.f );
		}
	}
	else
	{//Snapping, should do this first time if follow_lerp_to_start_duration is zero
		//will lerp from this point on
		client_camera.followInitLerp = qtrue;
		//So tracker doesn't move right away thinking the first angle change
		//is the subject moving... FIXME: shouldn't set this until lerp done OR snapped?
		client_camera.subjectSpeed = 0;
	}

	//Point camera to lerp angles
	VectorCopy( cameraAngles, client_camera.angles );
}
Beispiel #13
0
/*
* CG_InterpolatePlayerState
*/
static void CG_InterpolatePlayerState( player_state_t *playerState )
{
	int i;
	player_state_t *ps, *ops;
	bool teleported;

	ps = &cg.frame.playerState;
	ops = &cg.oldFrame.playerState;

	*playerState = *ps;

	teleported = ( ps->pmove.pm_flags & PMF_TIME_TELEPORT ) ? true : false;

	if( abs( (int)(ops->pmove.origin[0] - ps->pmove.origin[0]) ) > 256
		|| abs( (int)(ops->pmove.origin[1] - ps->pmove.origin[1]) ) > 256
		|| abs( (int)(ops->pmove.origin[2] - ps->pmove.origin[2]) ) > 256 )
		teleported = true;

#ifdef EXTRAPOLATE_PLAYERSTATE // isn't smooth enough for the 1st person view
	if( cgs.extrapolationTime )
	{
		vec3_t newPosition, oldPosition;

		// if the player entity was teleported this frame use the final position
		if( !teleported )
		{
			for( i = 0; i < 3; i++ )
			{
				playerState->pmove.velocity[i] = ops->pmove.velocity[i] + cg.lerpfrac * ( ps->pmove.velocity[i] - ops->pmove.velocity[i] );
				playerState->viewangles[i] = LerpAngle( ops->viewangles[i], ps->viewangles[i], cg.lerpfrac );
			}
		}

		VectorMA( ps->pmove.origin, cg.xerpTime, ps->pmove.velocity, newPosition );

		if( cg.xerpTime < 0.0f ) // smooth with the ending of oldsnap-newsnap interpolation
		{
			if( teleported )
				VectorCopy( ps->pmove.origin, oldPosition );
			else
				VectorMA( ops->pmove.origin, cg.oldXerpTime, ops->pmove.velocity, oldPosition );
		}

		VectorLerp( oldPosition, cg.xerpSmoothFrac, newPosition, playerState->pmove.origin );
	}
	else
	{
#endif
		// if the player entity was teleported this frame use the final position
		if( !teleported )
		{
			for( i = 0; i < 3; i++ )
			{
				playerState->pmove.origin[i] = ops->pmove.origin[i] + cg.lerpfrac * ( ps->pmove.origin[i] - ops->pmove.origin[i] );
				playerState->pmove.velocity[i] = ops->pmove.velocity[i] + cg.lerpfrac * ( ps->pmove.velocity[i] - ops->pmove.velocity[i] );
				playerState->viewangles[i] = LerpAngle( ops->viewangles[i], ps->viewangles[i], cg.lerpfrac );
			}
		}
#ifdef EXTRAPOLATE_PLAYERSTATE
	}
#endif

	// interpolate fov and viewheight
	if( !teleported )
	{
		playerState->fov = ops->fov + cg.lerpfrac * ( ps->fov - ops->fov );
		playerState->viewheight = ops->viewheight + cg.lerpfrac * ( ps->viewheight - ops->viewheight );
	}
}