/* ================= 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; 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_DrawLoadingScreen( ); 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_DrawLoadingScreen( ); return; } // let the client system know what our weapon and zoom settings are trap_SetUserCmdValue( cg.weaponSelect, cg.zoomSensitivity ); // this counter will be bumped for every valid scene we generate cg.clientFrame++; // update cg.predictedPlayerState CG_PredictPlayerState( ); // decide on third person view cg.renderingThirdPerson = ( cg_thirdPerson.integer || ( cg.snap->ps.stats[ STAT_HEALTH ] <= 0 ) || ( cg.chaseFollow && cg.snap->ps.pm_flags & PMF_FOLLOW) ); // update speedometer CG_AddSpeed( ); // build cg.refdef inwater = CG_CalcViewValues( ); // build the render lists if( !cg.hyperspace ) { CG_AddPacketEntities( ); // after calcViewValues, so predicted player state is correct CG_AddMarks( ); } CG_AddViewWeapon( &cg.predictedPlayerState ); //after CG_AddViewWeapon if( !cg.hyperspace ) { CG_AddParticles( ); CG_AddTrails( ); } // add buffered sounds CG_PlayBufferedSounds( ); // 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 ) ); //remove expired console lines if( cg.consoleLines[ 0 ].time + cg_consoleLatency.integer < cg.time && cg_consoleLatency.integer > 0 ) CG_RemoveNotifyLine( ); // update audio positions trap_S_Respatialize( cg.snap->ps.clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater ); // make sure the lagometerSample and frame timing isn't done twice when in stereo if( stereoView != STEREO_RIGHT ) { 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 ); if( cg_stats.integer ) CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame ); }
/* ================= 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 ); } }