void CGCam_Enable( void )
{
	if (!cg.refdef.height) {
		CG_CalcVrect();
	}
	client_camera.bar_alpha = 0.0f;
	client_camera.bar_time = cg.time;

	client_camera.bar_alpha_source = 0.0f;
	client_camera.bar_alpha_dest = 1.0f;
	
	client_camera.bar_height_source = 0.0f;
	client_camera.bar_height_dest = cg.refdef.height/10;
	client_camera.bar_height = 0.0f;

	client_camera.info_state |= CAMERA_BAR_FADING;

	client_camera.FOV	= CAMERA_DEFAULT_FOV;
	client_camera.FOV2	= CAMERA_DEFAULT_FOV;

	in_camera = true;

	client_camera.next_roff_time = 0;

	if ( &g_entities[0] && g_entities[0].client )
	{
		//Player zero not allowed to do anything
		VectorClear( g_entities[0].client->ps.velocity );
		g_entities[0].contents = 0;
	}
}
Exemple #2
0
/*
===============
CG_CalcViewValues

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

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

    ps = &cg.predictedPlayerState;

    cg.refdefViewOrigin = ps->origin;
    cg.refdefViewAngles = ps->viewangles;

    // add first person / third person view offset
    if ( cg_thirdPerson.integer )
    {
        // back away from character
        CG_OffsetThirdPersonView();
    }
    else
    {
        // offset for local bobbing and kicks
        CG_OffsetFirstPersonView();
    }
    cg.refdefViewAxis.fromAngles( cg.refdefViewAngles );

    if ( cg_printCurCamPos.getInt() )
    {
        CG_Printf( "CG_CalcViewValues: camera eye is at %f %f %f\n", cg.refdefViewOrigin[0], cg.refdefViewOrigin[1], cg.refdefViewOrigin[2] );
    }
    if ( cg_printCurFarPlane.getInt() )
    {
        CG_Printf( "CG_CalcViewValues: cg.farPlane is %f\n", cg.farPlane );
    }

    projDef_s projDef;
    projDef.setDefaults();
    if ( cg.farPlane >= 8.f )
    {
        projDef.zFar = cg.farPlane;
    }
    rf->setupProjection3D( &projDef );
    rf->setup3DView( cg.refdefViewOrigin, cg.refdefViewAngles, cg_thirdPerson.integer );

    return 0;
}
Exemple #3
0
/*
===============
CG_CalcViewValues

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

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

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

  ps = &cg.predictedPlayerState;

  // intermission view
  if( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_FREEZE ||
      ps->pm_type == PM_SPECTATOR )
  {
    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 ] );

  // the bob velocity should't get too fast to avoid jerking
  if( cg.xyspeed > 300.0f )
    cg.xyspeed = 300.0f;

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

  if( BG_ClassHasAbility( ps->stats[ STAT_CLASS ], SCA_WALLCLIMBER ) )
    CG_smoothWWTransitions( ps, ps->viewangles, cg.refdefViewAngles );
  else if( BG_ClassHasAbility( ps->stats[ STAT_CLASS ], SCA_WALLJUMPER ) )
    CG_smoothWJTransitions( ps, ps->viewangles, cg.refdefViewAngles );
  else
    VectorCopy( ps->viewangles, cg.refdefViewAngles );

  //clumsy logic, but it needs to be this way round because the CS propogation
  //delay screws things up otherwise
  if( !BG_ClassHasAbility( ps->stats[ STAT_CLASS ], SCA_WALLJUMPER ) )
  {
    if( !( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) )
      VectorSet( cg.lastNormal, 0.0f, 0.0f, 1.0f );
  }

  // 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;
  }

  //shut off the poison cloud effect if it's still on the go
  if( cg.snap->ps.stats[ STAT_HEALTH ] <= 0 )
  {
    if( CG_IsParticleSystemValid( &cg.poisonCloudPS ) )
      CG_DestroyParticleSystem( &cg.poisonCloudPS );
  }
  else
    cg.wasDeadLastFrame = qfalse;

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

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

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

  //draw the surface normal looking at
  if( cg_drawSurfNormal.integer )
    CG_DrawSurfNormal( );

  // field of view
  return CG_CalcFov( );
}
/*
===============
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;
		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.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();
	}

	// 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();
}
/*
===============
CG_CalcViewValues

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

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

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

	ps = &cg.predictedPlayerState;

	CG_CalcColorGradingForPoint( ps->origin );
	CG_AddColorGradingEffects( ps );

	CG_AddReverbEffects( ps->origin );

	// intermission view
	if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_FREEZE ||
	     ps->pm_type == PM_SPECTATOR )
	{
		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 ] );

	// to avoid jerking, the bob velocity shouldn't be too high
	if ( cg.xyspeed > 300.0f )
	{
		cg.xyspeed = 300.0f;
	}

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

	if ( BG_ClassHasAbility( ps->stats[ STAT_CLASS ], SCA_WALLCLIMBER ) )
	{
		CG_smoothWWTransitions( ps, ps->viewangles, cg.refdefViewAngles );
	}
	else if ( BG_ClassHasAbility( ps->stats[ STAT_CLASS ], SCA_WALLJUMPER ) )
	{
		CG_smoothWJTransitions( ps, ps->viewangles, cg.refdefViewAngles );
	}
	else
	{
		VectorCopy( ps->viewangles, cg.refdefViewAngles );
	}

	//clumsy logic, but it needs to be this way around because the CS propagation
	//delay screws things up otherwise
	if ( !BG_ClassHasAbility( ps->stats[ STAT_CLASS ], SCA_WALLJUMPER ) )
	{
		if ( !( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) )
		{
			VectorSet( cg.lastNormal, 0.0f, 0.0f, 1.0f );
		}
	}

	// 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;
		}
	}

	//shut off the poison cloud effect if it's still on the go
	if ( cg.snap->ps.stats[ STAT_HEALTH ] > 0 )
	{
		cg.wasDeadLastFrame = qfalse;
	}

	if ( cg.renderingThirdPerson )
	{
		// back away from character
		CG_OffsetThirdPersonView();
	}
	else
	{
		float speed;

		// offset for local bobbing and kicks
		CG_OffsetFirstPersonView();

		// Compute motion blur vector
		speed = VectorNormalize2( cg.snap->ps.velocity, cg.refdef.blurVec );

		speed = (speed - cg_motionblurMinSpeed.value);
		if( speed < 0.0f ) speed = 0.0f;

		VectorScale( cg.refdef.blurVec, speed * cg_motionblur.value,
			     cg.refdef.blurVec );

	}

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

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

	//draw the surface normal looking at
	if ( cg_drawSurfNormal.integer )
	{
		CG_DrawSurfNormal();
	}

	// field of view
	return CG_CalcFov();
}
Exemple #6
0
/*
===============
CG_CalcViewValues

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

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

	// 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;                 // camera off in cgame
			trap_Cvar_Set( "cg_letterbox", "0" );
			trap_SendClientCommand( "stopCamera" );    // camera off in game
			trap_stopCamera( CAM_PRIMARY );           // camera off in client

			CG_Fade( 0, 0, 0, 255, 0, 0 );                // go black
			CG_Fade( 0, 0, 0, 0, cg.time + 200, 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 );
	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
		*/
		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 == 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;
		}
		// 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();
}
Exemple #7
0
/*
-------------------------
CGCam_RenderScene
-------------------------
*/
void CGCam_RenderScene( void )
{
	CGCam_Update();
	CG_CalcVrect();
}
Exemple #8
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();
}
Exemple #9
0
/*
=================
CG_DrawActiveFrame

Generates and draws a game scene and status information at the given time.
=================
*/
void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ) {
	int		inwater;
	qboolean renderClientViewport[MAX_SPLITVIEW];
	int		i;

	cg.time = serverTime;
	cg.demoPlayback = demoPlayback;

	// update cvars
	CG_UpdateCvars();

	// if we are only updating the screen as a loading
	// pacifier, don't even try to read snapshots
	if ( cg.infoScreenText[0] != 0 ) {
		CG_DrawInformation();
		return;
	}

	// any looped sounds will be respecified as entities
	// are added to the render list
	trap_S_ClearLoopingSounds(qfalse);

	// clear all the render lists
	trap_R_ClearScene();

	// set up cg.snap and possibly cg.nextSnap
	CG_ProcessSnapshots();

	// if we haven't received any snapshots yet, all
	// we can draw is the information screen
	if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) {
		CG_DrawInformation();
		return;
	}

	// this counter will be bumped for every valid scene we generate
	cg.clientFrame++;

	// Use single camera/viewport at intermission
	for (i = 0; i < CG_MaxSplitView(); i++) {
		if (cg.snap->lcIndex[i] != -1 && cg.snap->pss[i].pm_type != PM_INTERMISSION) {
			// client present and not at intermission, keep viewports separate.
			break;
		}
	}
	cg.singleCamera = (cg.snap->numPSs > 1) && (i == CG_MaxSplitView());

	cg.numViewports = 0;
	for (i = 0; i < CG_MaxSplitView(); i++) {
		if (cg.snap->lcIndex[i] == -1) {
			renderClientViewport[i] = qfalse;
			continue;
		}
		cg.cur_localClientNum = i;
		cg.cur_lc = &cg.localClients[i];
		cg.cur_ps = &cg.snap->pss[cg.snap->lcIndex[i]];

		// Check if viewport should be drawn.
		if ( cg.singleCamera && cg.numViewports >= 1 ) {
			renderClientViewport[i] = qfalse;
		} else {
			cg.numViewports++;
			renderClientViewport[i] = qtrue;
		}

		// let the client system know what our weapon and zoom settings are
		trap_SetUserCmdValue( cg.cur_lc->weaponSelect, cg.cur_lc->zoomSensitivity, cg.cur_localClientNum );

		// update cg.predictedPlayerState
		CG_PredictPlayerState();

		// Remove expired console lines
		if( cg.cur_lc->consoleLines[ 0 ].time + cg_consoleLatency.integer < cg.time && cg_consoleLatency.integer > 0 ) {
			CG_RemoveNotifyLine( cg.cur_lc );
		}
	}

	// If all local clients dropped out from playing still draw main local client.
	if (cg.numViewports == 0) {
		cg.numViewports = 1;
		renderClientViewport[0] = qtrue;
	}

	// play lead change annoucement and time/frag limit warnings
	CG_CheckGameSounds();

	// add buffered sounds
	CG_PlayBufferedSounds();

#ifdef MISSIONPACK
	// play buffered voice chats
	CG_PlayBufferedVoiceChats();
#endif

	for (i = 0, cg.viewport = -1; i < CG_MaxSplitView(); i++) {
		if (!renderClientViewport[i]) {
			continue;
		}
		cg.viewport++;
		cg.cur_localClientNum = i;
		cg.cur_lc = &cg.localClients[i];
		cg.cur_ps = &cg.snap->pss[cg.snap->lcIndex[i]];

		// decide on third person view
		cg.cur_lc->renderingThirdPerson = cg_thirdPerson[cg.cur_localClientNum].integer || (cg.cur_ps->stats[STAT_HEALTH] <= 0);

		CG_PB_ClearPolyBuffers();

		// build cg.refdef
		inwater = CG_CalcViewValues();
		CG_SetupFrustum();

		// first person blend blobs, done after AnglesToAxis
		if ( !cg.cur_lc->renderingThirdPerson ) {
			CG_DamageBlendBlob();
		}

		// build the render lists
		if ( !cg.cur_lc->hyperspace ) {
			CG_AddPacketEntities();			// adter calcViewValues, so predicted player state is correct
			CG_AddMarks();
			CG_AddParticles ();
			CG_AddLocalEntities();
			CG_AddAtmosphericEffects();
		}
		CG_AddViewWeapon( &cg.cur_lc->predictedPlayerState );

		// finish up the rest of the refdef
		if ( cg.testModelEntity.hModel ) {
			CG_AddTestModel();
		}
		cg.refdef.time = cg.time;
		memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) );

		// warning sounds when powerup is wearing off
		CG_PowerupTimerSounds();

		// update audio positions
		trap_S_Respatialize( cg.cur_ps->clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater, !cg.cur_lc->renderingThirdPerson );

		// make sure the lagometerSample and frame timing isn't done twice when in stereo
		if ( stereoView != STEREO_RIGHT && cg.viewport == 0 ) {
			cg.frametime = cg.time - cg.oldTime;
			if ( cg.frametime < 0 ) {
				cg.frametime = 0;
			}
			cg.oldTime = cg.time;
			CG_AddLagometerFrameInfo();
		}
		if (cg_timescale.value != cg_timescaleFadeEnd.value) {
			if (cg_timescale.value < cg_timescaleFadeEnd.value) {
				cg_timescale.value += cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000;
				if (cg_timescale.value > cg_timescaleFadeEnd.value)
					cg_timescale.value = cg_timescaleFadeEnd.value;
			}
			else {
				cg_timescale.value -= cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000;
				if (cg_timescale.value < cg_timescaleFadeEnd.value)
					cg_timescale.value = cg_timescaleFadeEnd.value;
			}
			if (cg_timescaleFadeSpeed.value) {
				trap_Cvar_Set("timescale", va("%f", cg_timescale.value));
			}
		}

		// actually issue the rendering calls
		CG_DrawActive( stereoView );
	}

	// load any models that have been deferred if a scoreboard is shown
	if ( !CG_AnyScoreboardShowing() ) {
		cg.deferredPlayerLoading = 0;
	} else if ( ++cg.deferredPlayerLoading > 10 ) {
		CG_LoadDeferredPlayers();
	}

	if (cg.numViewports != 1) {
		// Setup single viewport
		cg.numViewports = 1;
		cg.viewport = 0;

		// calculate size of viewport
		CG_CalcVrect();
	}

	// Not drawing single client view.
	cg.cur_lc = NULL;
	cg.cur_ps = NULL;
	cg.cur_localClientNum = -1;

	// Draw over all viewports
	CG_DrawScreen2D( stereoView );

	if ( cg_stats.integer ) {
		CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame );
	}


}
Exemple #10
0
/*
-------------------------
CGCam_RenderScene
-------------------------
*/
void CGCam_RenderScene( void )
{
	memset( &cg.refdef, 0, sizeof( cg.refdef ) );
	CGCam_Update();
	CG_CalcVrect();
}
Exemple #11
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;
    		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 );

    //link to view to head of ppm if dying - edited, only do this if the player killed himself
    //or specting someone else
    if ((((ps->pm_flags & PMF_SUICIDE) || !cgs.deathcam || cgs.gametype == GT_DUEL)
            && (ps->pm_type == PM_DEAD) && (!cg.renderingThirdPerson))
            || ((cg.snap->ps.pm_flags & PMF_FOLLOW) && (cg.snap->ps.pm_type != PM_CHASECAM)
                && (ps->stats[STAT_HEALTH] <= 0))) {
        VectorCopy(cg.anim_viewangles, cg.refdefViewAngles);
        VectorCopy(cg.anim_vieworigin, cg.refdef.vieworg);
    }

    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;
        }
    }

    // this is a special camera movement around the players
    if(cg.introend - DU_INTRO_DRAW >= cg.time && cgs.gametype == GT_DUEL &&
            cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_FREE &&
            !(cg.snap->ps.pm_flags & PMF_FOLLOW)) {

        CG_OffsetFirstPersonView();
        CG_DuelIntroView();

    } else if ((cg.renderingThirdPerson ||(cg.snap->ps.pm_flags & PMF_FOLLOW &&
                                           cg.snap->ps.pm_type == PM_CHASECAM)) && !cg.introstart) {
        // back away from character
        CG_OffsetThirdPersonView();
        cg.introstart = 0;
    } else {
        // offset for local bobbing and kicks
        CG_OffsetFirstPersonView();
        cg.introstart = 0;
    }

    // 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();
}
Exemple #12
0
/*
===============
Wolfcam_OffsetFirstPersonView

Sets cg.refdef view values if following other players
===============
*/
int Wolfcam_OffsetFirstPersonView (void)
{
    int clientNum;
    const clientInfo_t *ci;
    centity_t *cent;
    const entityState_t *es;
    wclient_t *wc;
    float ratio;
    float v_dmg_pitch;
    //qboolean wasBinocZooming;
    int timeDelta;
    //qboolean notDrawing;
    float bob;
    float speed;
    float delta;
    qboolean                useLastValidBob = qfalse;
    int anim;
	int t;

	memset(&cg.refdef, 0, sizeof(cg.refdef));
	CG_CalcVrect();
	if (cg.hyperspace) {
		cg.refdef.rdflags |= RDF_NOWORLDMODEL | RDF_HYPERSPACE;
	}

    clientNum = wcg.clientNum;

	if (wcg.followMode == WOLFCAM_FOLLOW_KILLER) {
		const centity_t *c;

		c = &cg_entities[cg.wcKillerClientNum];
		t = wcg.nextKillerServerTime - cg.snap->serverTime;
		if (t < 0  &&  t > -wolfcam_hoverTime.integer) {

			if (!c->currentValid) {
				// handled at end of function
			} else {
				clientNum = cg.wcKillerClientNum;
			}
		}
	}

    ci = &cgs.clientinfo[clientNum];
    cent = &cg_entities[clientNum];
    es = &cent->currentState;
    wc = &wclients[wcg.clientNum];

    anim = cent->currentState.legsAnim & ~ANIM_TOGGLEBIT;

    if (wcg.clientNum == cg.snap->ps.clientNum) {
        //cg.renderingThirdPerson = 0;
        //trap_Cvar_Set ("cg_thirdPerson", "0");
    } else {
        //cg.renderingThirdPerson = 1;
        //trap_Cvar_Set ("cg_thirdPerson", "1");
    }

    //notDrawing = cent->currentState.eFlags & EF_NODRAW;
    cent->currentState.eFlags |= EF_NODRAW;
    cent->nextState.eFlags |= EF_NODRAW;


    VectorCopy (cent->lerpOrigin, cg.refdef.vieworg);
    VectorCopy (cent->lerpAngles, cg.refdefViewAngles);

    // CG_TransitionPlayerState for wcg.clientNum
    //FIXME wolfcam don't know
#if 0
    if (cent->currentState.eFlags & EF_DEAD) {
        trap_SendConsoleCommand ("-zoom\n");
    }
#endif

#if 0
    wasBinocZooming = qfalse;
    if (wolfcam_esPrev.eFlags & EF_ZOOMING  &&  wolfcam_esPrev.weapon == WP_BINOCULARS) {
        wasBinocZooming = qtrue;
    }

    if (wasBinocZooming == qfalse  &&  cent->currentState.weapon == WP_BINOCULARS  &&  cent->currentState.eFlags & EF_ZOOMING) {
        wolfcam_binocZoomTime = cg.time;
        Com_Printf ("ent zooming with binocs\n");
    }
#endif

#if 1
    // add view height
    //if (es->eFlags & EF_CROUCHING) {
    if (anim == LEGS_WALKCR || anim == LEGS_IDLECR) {
        cg.refdef.vieworg[2] += CROUCH_VIEWHEIGHT;
        //cg.refdef.vieworg[2] += CROUCH_VIEWHEIGHT;
        //Com_Printf ("test.....\n");
    }
    else {
        cg.refdef.vieworg[2] += DEFAULT_VIEWHEIGHT;
        //cg.refdef.vieworg[2] += DEFAULT_VIEWHEIGHT;
        //Com_Printf ("test.....\n");
    }
#endif

    timeDelta = cg.time - wc->duckTime;  //FIXME cg.ioverf
    {
        if (timeDelta < 0)
            wc->duckTime = cg.time - DUCK_TIME;
        if (timeDelta < DUCK_TIME) {
            cg.refdef.vieworg[2] -= wc->duckChange * (DUCK_TIME - timeDelta) / DUCK_TIME;
        }
    }

#if 0
    //if (es->eFlags & EF_DEAD  &&  ci->infoValid  &&  !notDrawing) {
    if (!cent->currentValid  ||  es->eFlags & EF_DEAD) {
        return qfalse;
    }
#endif

    //FIXME  fall, stepOffset?

    // add angles based on bob

    //    if (cent->currentValid) {
    if (wclients[wcg.clientNum].currentValid) {
    // make sure the bob is visible even at low speeds
    speed = wc->xyspeed > 200 ? wc->xyspeed : 200;


    /////////////////////
    if( !wc->bobfracsin  &&  wc->lastvalidBobfracsin > 0 ) {
        // 200 msec to get back to center from 1
        // that's 1/200 per msec = 0.005 per msec
        wc->lastvalidBobfracsin -= 0.005 * cg.frametime;
        useLastValidBob = qtrue;
    }

    //    delta = useLastValidBob ? wolfcam_lastvalidBobfracsin * cg_bobpitch.value * speed : cg.bobfracsin * cg_bobpitch.value * speed;
    delta = useLastValidBob ? wc->lastvalidBobfracsin * cg_bobpitch.value * speed : wc->bobfracsin * cg_bobpitch.value * speed;

    //if (es->eFlags & EF_CROUCHING)
    if ( anim == LEGS_WALKCR || anim == LEGS_IDLECR )
        delta *= 3;             // crouching
    cg.refdefViewAngles[PITCH] += delta;
    delta = useLastValidBob ? wc->lastvalidBobfracsin * cg_bobroll.value * speed : wc->bobfracsin * cg_bobroll.value * speed;

    //    if (es->eFlags & EF_CROUCHING)
    if ( anim == LEGS_WALKCR || anim == LEGS_IDLECR )
        delta *= 3;             // crouching accentuates roll
    if( useLastValidBob ) {
        if( wc->lastvalidBobcycle & 1 )
            delta = -delta;
    } else if (wc->bobcycle & 1)
        delta = -delta;
    cg.refdefViewAngles[ROLL] += delta;  //FIXME wolfcam ok for weapons, sucks for regular walking


    //FIXME wolfcam using v_dmg_pitch == kick == -5
    v_dmg_pitch = -5;
    ratio = cg.time - wc->bulletDamageTime;
    if (ratio < DAMAGE_TIME  &&  !(es->eFlags & EF_DEAD)  &&  ci->infoValid) {
        if (ratio < DAMAGE_DEFLECT_TIME) {
            ratio /= DAMAGE_DEFLECT_TIME;
            cg.refdefViewAngles[PITCH] += ratio * v_dmg_pitch;
            //FIXME wolfcam ROLL
        } else {
            ratio = 1.0 - (ratio - DAMAGE_DEFLECT_TIME) / DAMAGE_RETURN_TIME;
            if (ratio > 0) {
                cg.refdefViewAngles[PITCH] += ratio * v_dmg_pitch;
                //FIXME wolfcam ROLL
            }
        }
    }

    bob = wc->bobfracsin * wc->xyspeed * cg_bobup.value;
    if (bob > 6) {
        bob = 6;
    }
    cg.refdef.vieworg[2] += bob;  //FIXME wolfcam ok for weapons, not player movement
    }

#if 0
    // ZoomSway
    if (wc->zoomval)
    {
        float spreadfrac, phase;

        if (es->eFlags & EF_MG42_ACTIVE) {  //  ||  es->eFlags & EF_AAGUN_ACTIVE) {
        } else {
            //spreadfrac = (float)cg.snap->ps.aimSpreadScale / 255.0;
            spreadfrac = 0.25;  //FIXME wolfcam
            phase = cg.time / 1000.0 * ZOOM_PITCH_FREQUENCY * M_PI * 2;
            cg.refdefViewAngles[PITCH] += ZOOM_PITCH_AMPLITUDE * sin( phase ) * (spreadfrac+ZOOM_PITCH_MIN_AMPLITUDE);
            phase = cg.time / 1000.0 * ZOOM_YAW_FREQUENCY * M_PI * 2;
            cg.refdefViewAngles[YAW] += ZOOM_YAW_AMPLITUDE * sin( phase ) * (spreadfrac+ZOOM_YAW_MIN_AMPLITUDE);
        }
    }
#endif

	if (wcg.followMode == WOLFCAM_FOLLOW_VICTIM) {
		t = wcg.nextVictimServerTime - cg.snap->serverTime;
		if (t < 0  &&  t > -wolfcam_hoverTime.integer) {
			VectorCopy(cg.victimOrigin, cg.refdef.vieworg);
			VectorCopy(cg.victimAngles, cg.refdefViewAngles);
		}
	} else if (wcg.followMode == WOLFCAM_FOLLOW_KILLER) {
		const centity_t *c;

		c = &cg_entities[cg.wcKillerClientNum];
		t = wcg.nextKillerServerTime - cg.snap->serverTime;
		if (t < 0  &&  t > -wolfcam_hoverTime.integer) {

			if (!c->currentValid) {
				VectorCopy(cg.wcKillerOrigin, cg.refdef.vieworg);
				VectorCopy(cg.wcKillerAngles, cg.refdefViewAngles);
			}
		}
	}

    AnglesToAxis (cg.refdefViewAngles, cg.refdef.viewaxis );

    //VectorCopy (cg.refdef.vieworg, cg.refdef_current->vieworg);
    //AnglesToAxis (cg.refdefViewAngles, cg.refdef_current->viewaxis);

    return 0;
}
/*
===============
CG_CalcViewValues

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

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

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

	ps = &cg.predicted_player_state;

	// 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 );

	// 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
		if ( cg_thirdPerson.integer == CG_CAM_ABOVE)
		{			
			CG_OffsetThirdPersonOverheadView();
		}
		else
		{
			CG_OffsetThirdPersonView();
		}
	} else {
		// offset for local bobbing and kicks
		CG_OffsetFirstPersonView();
	}

	// shake the camera if necessary
	CGCam_UpdateShake( cg.refdef.vieworg, cg.refdefViewAngles );

	// Doing this when the camera is directly above will look bad
	if ( cg_thirdPerson.integer != CG_CAM_ABOVE )
	{
		// 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();
}
Exemple #14
0
void CG_RenderView( float frameTime, float realFrameTime, int realTime, unsigned int serverTime, float stereo_separation, unsigned int extrapolationTime, bool flipped )
{
	refdef_t *rd = &cg.view.refdef;

	// update time
	cg.realTime = realTime;
	cg.frameTime = frameTime;
	cg.realFrameTime = realFrameTime;
	cg.frameCount++;
	cg.time = serverTime;

	if( !cgs.precacheDone || !cg.frame.valid )
	{
		CG_Precache();
		CG_DrawLoading();
		return;
	}

	{
		float snapTime = ( cg.frame.serverTime - cg.oldFrame.serverTime );

		if( !snapTime )
			snapTime = cgs.snapFrameTime;

		// moved this from CG_Init here
		cgs.extrapolationTime = extrapolationTime;

		if( cg.oldFrame.serverTime == cg.frame.serverTime )
			cg.lerpfrac = 1.0f;
		else
			cg.lerpfrac = ( (double)( cg.time - cgs.extrapolationTime ) - (double)cg.oldFrame.serverTime ) / (double)snapTime;

		if( cgs.extrapolationTime )
		{
			cg.xerpTime = 0.001f * ( (double)cg.time - (double)cg.frame.serverTime );
			cg.oldXerpTime = 0.001f * ( (double)cg.time - (double)cg.oldFrame.serverTime );

			if( cg.time >= cg.frame.serverTime )
			{
				cg.xerpSmoothFrac = (double)( cg.time - cg.frame.serverTime ) / (double)( cgs.extrapolationTime );
				clamp( cg.xerpSmoothFrac, 0.0f, 1.0f );
			}
			else
			{
				cg.xerpSmoothFrac = (double)( cg.frame.serverTime - cg.time ) / (double)( cgs.extrapolationTime );
				clamp( cg.xerpSmoothFrac, -1.0f, 0.0f );
				cg.xerpSmoothFrac = 1.0f - cg.xerpSmoothFrac;
			}

			clamp_low( cg.xerpTime, -( cgs.extrapolationTime * 0.001f ) );
			//clamp( cg.xerpTime, -( cgs.extrapolationTime * 0.001f ), ( cgs.extrapolationTime * 0.001f ) );
			//clamp( cg.oldXerpTime, 0, ( ( snapTime + cgs.extrapolationTime ) * 0.001f ) );
		}
		else
		{
			cg.xerpTime = 0.0f;
			cg.xerpSmoothFrac = 0.0f;
		}
	}

	if( cg_showClamp->integer )
	{
		if( cg.lerpfrac > 1.0f )
			CG_Printf( "high clamp %f\n", cg.lerpfrac );
		else if( cg.lerpfrac < 0.0f )
			CG_Printf( "low clamp  %f\n", cg.lerpfrac );
	}

	clamp( cg.lerpfrac, 0.0f, 1.0f );

	if( !cgs.configStrings[CS_WORLDMODEL][0] )
	{
		CG_AddLocalSounds();

		trap_R_DrawStretchPic( 0, 0, cgs.vidWidth, cgs.vidHeight, 0, 0, 1, 1, colorBlack, cgs.shaderWhite );

		trap_S_Update( vec3_origin, vec3_origin, axis_identity, cgs.clientInfo[cgs.playerNum].name );

		return;
	}

	// bring up the game menu after reconnecting
	if( !cgs.tv && !cgs.demoPlaying ) {
		if( ISREALSPECTATOR() && !cg.firstFrame ) {
			if( !cgs.gameMenuRequested ) {
				trap_Cmd_ExecuteText( EXEC_NOW, "gamemenu\n" );
			}
			cgs.gameMenuRequested = true;
		}
	}

	if( !cg.viewFrameCount )
		cg.firstViewRealTime = cg.realTime;

	CG_FlashGameWindow(); // notify player of important game events

	CG_CalcVrect(); // find sizes of the 3d drawing screen
	CG_TileClear(); // clear any dirty part of the background

	CG_ChaseCamButtons();

	CG_RunLightStyles();

	CG_ClearFragmentedDecals();

	trap_R_ClearScene();

	if( CG_DemoCam_Update() )
		CG_SetupViewDef( &cg.view, CG_DemoCam_GetViewType(), flipped );
	else
		CG_SetupViewDef( &cg.view, VIEWDEF_PLAYERVIEW, flipped );

	CG_LerpEntities();  // interpolate packet entities positions

	CG_CalcViewWeapon( &cg.weapon );

	CG_FireEvents( false );

	CG_AddEntities();
	CG_AddViewWeapon( &cg.weapon );
	CG_AddLocalEntities();
	CG_AddParticles();
	CG_AddDlights();
	CG_AddShadeBoxes();
	CG_AddDecals();
	CG_AddPolys();
	CG_AddLightStyles();

#ifndef PUBLIC_BUILD
	CG_AddTest();
#endif

	// offset vieworg appropriately if we're doing stereo separation
	VectorMA( cg.view.origin, stereo_separation, &cg.view.axis[AXIS_RIGHT], rd->vieworg );

	// never let it sit exactly on a node line, because a water plane can
	// disappear when viewed with the eye exactly on it.
	// the server protocol only specifies to 1/16 pixel, so add 1/16 in each axis
	rd->vieworg[0] += 1.0/PM_VECTOR_SNAP;
	rd->vieworg[1] += 1.0/PM_VECTOR_SNAP;
	rd->vieworg[2] += 1.0/PM_VECTOR_SNAP;

	AnglesToAxis( cg.view.angles, rd->viewaxis );

	rd->rdflags = CG_RenderFlags();

	// warp if underwater
	if( rd->rdflags & RDF_UNDERWATER )
	{
		float phase = rd->time * 0.001 * WAVE_FREQUENCY * M_TWOPI;
		float v = WAVE_AMPLITUDE * ( sin( phase ) - 1.0 ) + 1;
		rd->fov_x *= v;
		rd->fov_y *= v;
	}

	CG_AddLocalSounds();
	CG_SetSceneTeamColors(); // update the team colors in the renderer

	trap_R_RenderScene( &cg.view.refdef );

	cg.oldAreabits = true;

	trap_S_Update( cg.view.origin, cg.view.velocity, cg.view.axis, cgs.clientInfo[cgs.playerNum].name );

	CG_Draw2D();

	CG_ResetTemporaryBoneposesCache(); // clear for next frame

	cg.viewFrameCount++;
}