void CGCam_Update( void ) { int i; qboolean checkFollow = qfalse; qboolean checkTrack = qfalse; // Apply new roff data to the camera as needed if ( client_camera.info_state & CAMERA_ROFFING ) { CGCam_Roff(); } //Check for a zoom if ( client_camera.info_state & CAMERA_ZOOMING ) { float actualFOV_X; if ( client_camera.FOV_time + client_camera.FOV_duration < cg.time ) { actualFOV_X = client_camera.FOV = client_camera.FOV2; client_camera.info_state &= ~CAMERA_ZOOMING; } else { actualFOV_X = client_camera.FOV + (( ( client_camera.FOV2 - client_camera.FOV ) ) / client_camera.FOV_duration ) * ( cg.time - client_camera.FOV_time ); } CG_CalcFOVFromX( actualFOV_X ); } else { CG_CalcFOVFromX( client_camera.FOV ); } //Check for roffing angles if ( (client_camera.info_state & CAMERA_ROFFING) && !(client_camera.info_state & CAMERA_FOLLOWING) ) { for ( i = 0; i < 3; i++ ) { cg.refdefViewAngles[i] = client_camera.angles[i] + ( client_camera.angles2[i] / client_camera.pan_duration ) * ( cg.time - client_camera.pan_time ); } } else if ( client_camera.info_state & CAMERA_PANNING ) { //Note: does not actually change the camera's angles until the pan time is done! if ( client_camera.pan_time + client_camera.pan_duration < cg.time ) {//finished panning for ( i = 0; i < 3; i++ ) { client_camera.angles[i] = AngleNormalize360( ( client_camera.angles[i] + client_camera.angles2[i] ) ); } client_camera.info_state &= ~CAMERA_PANNING; VectorCopy(client_camera.angles, cg.refdefViewAngles ); } else {//still panning for ( i = 0; i < 3; i++ ) { //NOTE: does not store the resultant angle in client_camera.angles until pan is done cg.refdefViewAngles[i] = client_camera.angles[i] + ( client_camera.angles2[i] / client_camera.pan_duration ) * ( cg.time - client_camera.pan_time ); } } } else { checkFollow = qtrue; } AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis ); //Check for movement if ( client_camera.info_state & CAMERA_MOVING ) { //NOTE: does not actually move the camera until the movement time is done! if ( client_camera.move_time + client_camera.move_duration < cg.time ) { VectorCopy( client_camera.origin2, client_camera.origin ); client_camera.info_state &= ~CAMERA_MOVING; VectorCopy( client_camera.origin, cg.refdef.vieworg ); } else { for ( i = 0; i < 3; i++ ) { cg.refdef.vieworg[i] = client_camera.origin[i] + (( ( client_camera.origin2[i] - client_camera.origin[i] ) ) / client_camera.move_duration ) * ( cg.time - client_camera.move_time ); } } } else { checkTrack = qtrue; } if ( checkFollow ) { if ( client_camera.info_state & CAMERA_FOLLOWING ) {//This needs to be done after camera movement CGCam_FollowUpdate(); } VectorCopy(client_camera.angles, cg.refdefViewAngles ); } if ( checkTrack ) { if ( client_camera.info_state & CAMERA_TRACKING ) {//This has to run AFTER Follow if the camera is following a cameraGroup CGCam_TrackUpdate(); } VectorCopy( client_camera.origin, cg.refdef.vieworg ); } //Bar fading if ( client_camera.info_state & CAMERA_BAR_FADING ) { CGCam_UpdateBarFade(); } //Normal fading - separate call because can finish after camera is disabled CGCam_UpdateFade(); //Update shaking if there's any //CGCam_UpdateSmooth( cg.refdef.vieworg, cg.refdefViewAngles ); CGCam_UpdateShake( cg.refdef.vieworg, cg.refdefViewAngles ); }
void CGCam_Update( void ) { int i; qboolean checkFollow = qfalse; qboolean checkTrack = qfalse; // Apply new roff data to the camera as needed if ( client_camera.info_state & CAMERA_ROFFING ) { CGCam_Roff(); } //Check for a zoom if (client_camera.info_state & CAMERA_ACCEL) { // x = x0 + vt + 0.5*a*t*t float actualFOV_X = client_camera.FOV; float sanityMin = 1, sanityMax = 180; float t = (cg.time - client_camera.FOV_time)*0.001; // mult by 0.001 cuz otherwise t is too darned big float fovDuration = client_camera.FOV_duration; #ifndef FINAL_BUILD if (cg_roffval4.integer) { fovDuration = cg_roffval4.integer; } #endif if ( client_camera.FOV_time + fovDuration < cg.time ) { client_camera.info_state &= ~CAMERA_ACCEL; } else { float initialPosVal = client_camera.FOV2; float velVal = client_camera.FOV_vel; float accVal = client_camera.FOV_acc; #ifndef FINAL_BUILD if (cg_roffdebug.integer) { if (fabs(cg_roffval1.value) > 0.001f) { initialPosVal = cg_roffval1.value; } if (fabs(cg_roffval2.value) > 0.001f) { velVal = cg_roffval2.value; } if (fabs(cg_roffval3.value) > 0.001f) { accVal = cg_roffval3.value; } } #endif float initialPos = initialPosVal; float vel = velVal*t; float acc = 0.5*accVal*t*t; actualFOV_X = initialPos + vel + acc; if (cg_roffdebug.integer) { Com_Printf("%d: fovaccel from %2.1f using vel = %2.4f, acc = %2.4f (current fov calc = %5.6f)\n", cg.time, initialPosVal, velVal, accVal, actualFOV_X); } if (actualFOV_X < sanityMin) { actualFOV_X = sanityMin; } else if (actualFOV_X > sanityMax) { actualFOV_X = sanityMax; } client_camera.FOV = actualFOV_X; } CG_CalcFOVFromX( actualFOV_X ); } else if ( client_camera.info_state & CAMERA_ZOOMING ) { float actualFOV_X; if ( client_camera.FOV_time + client_camera.FOV_duration < cg.time ) { actualFOV_X = client_camera.FOV = client_camera.FOV2; client_camera.info_state &= ~CAMERA_ZOOMING; } else { actualFOV_X = client_camera.FOV + (( ( client_camera.FOV2 - client_camera.FOV ) ) / client_camera.FOV_duration ) * ( cg.time - client_camera.FOV_time ); } CG_CalcFOVFromX( actualFOV_X ); } else { CG_CalcFOVFromX( client_camera.FOV ); } //Check for roffing angles if ( (client_camera.info_state & CAMERA_ROFFING) && !(client_camera.info_state & CAMERA_FOLLOWING) ) { if (client_camera.info_state & CAMERA_CUT) { // we're doing a cut, so just go to the new angles. none of this hifalutin lerping business. for ( i = 0; i < 3; i++ ) { cg.refdefViewAngles[i] = AngleNormalize360( ( client_camera.angles[i] + client_camera.angles2[i] ) ); } } else { for ( i = 0; i < 3; i++ ) { cg.refdefViewAngles[i] = client_camera.angles[i] + ( client_camera.angles2[i] / client_camera.pan_duration ) * ( cg.time - client_camera.pan_time ); } } } else if ( client_camera.info_state & CAMERA_PANNING ) { if (client_camera.info_state & CAMERA_CUT) { // we're doing a cut, so just go to the new angles. none of this hifalutin lerping business. for ( i = 0; i < 3; i++ ) { cg.refdefViewAngles[i] = AngleNormalize360( ( client_camera.angles[i] + client_camera.angles2[i] ) ); } } else { //Note: does not actually change the camera's angles until the pan time is done! if ( client_camera.pan_time + client_camera.pan_duration < cg.time ) {//finished panning for ( i = 0; i < 3; i++ ) { client_camera.angles[i] = AngleNormalize360( ( client_camera.angles[i] + client_camera.angles2[i] ) ); } client_camera.info_state &= ~CAMERA_PANNING; VectorCopy(client_camera.angles, cg.refdefViewAngles ); } else {//still panning for ( i = 0; i < 3; i++ ) { //NOTE: does not store the resultant angle in client_camera.angles until pan is done cg.refdefViewAngles[i] = client_camera.angles[i] + ( client_camera.angles2[i] / client_camera.pan_duration ) * ( cg.time - client_camera.pan_time ); } } } } else { checkFollow = qtrue; } //Check for movement if ( client_camera.info_state & CAMERA_MOVING ) { //NOTE: does not actually move the camera until the movement time is done! if ( client_camera.move_time + client_camera.move_duration < cg.time ) { VectorCopy( client_camera.origin2, client_camera.origin ); client_camera.info_state &= ~CAMERA_MOVING; VectorCopy( client_camera.origin, cg.refdef.vieworg ); } else { if (client_camera.info_state & CAMERA_CUT) { // we're doing a cut, so just go to the new origin. none of this fancypants lerping stuff. for ( i = 0; i < 3; i++ ) { cg.refdef.vieworg[i] = client_camera.origin2[i]; } } else { for ( i = 0; i < 3; i++ ) { cg.refdef.vieworg[i] = client_camera.origin[i] + (( ( client_camera.origin2[i] - client_camera.origin[i] ) ) / client_camera.move_duration ) * ( cg.time - client_camera.move_time ); } } } } else { checkTrack = qtrue; } if ( checkFollow ) { if ( client_camera.info_state & CAMERA_FOLLOWING ) {//This needs to be done after camera movement CGCam_FollowUpdate(); } VectorCopy(client_camera.angles, cg.refdefViewAngles ); } if ( checkTrack ) { if ( client_camera.info_state & CAMERA_TRACKING ) {//This has to run AFTER Follow if the camera is following a cameraGroup CGCam_TrackUpdate(); } VectorCopy( client_camera.origin, cg.refdef.vieworg ); } //Bar fading if ( client_camera.info_state & CAMERA_BAR_FADING ) { CGCam_UpdateBarFade(); } //Normal fading - separate call because can finish after camera is disabled CGCam_UpdateFade(); //Update shaking if there's any //CGCam_UpdateSmooth( cg.refdef.vieworg, cg.refdefViewAngles ); CGCam_UpdateShake( cg.refdef.vieworg, cg.refdefViewAngles ); AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis ); }
void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView ) { qboolean inwater = qfalse; cg.time = serverTime; CG_BuildSolidList(); // 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 cgi_S_ClearLoopingSounds(); // clear all the render lists cgi_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_DrawInformation(); return; } // let the client system know what our weapon and zoom settings are cgi_SetUserCmdValue( cg.weaponSelect, cg.refdef.fov_y / 75.0 ); // this counter will be bumped for every valid scene we generate cg.clientFrame++; // update cg.predicted_player_state CG_PredictPlayerState(); // decide on third person view cg.renderingThirdPerson = cg_thirdPerson.integer || (cg.snap->ps.stats[STAT_HEALTH] <= 0); if ( in_camera ) { // The camera takes over the view CGCam_RenderScene(); } else { //Finish any fading that was happening CGCam_UpdateFade(); // build cg.refdef inwater = CG_CalcViewValues(); } //This is done from the vieworg to get origin for non-attenuated sounds cgi_S_UpdateAmbientSet( CG_ConfigString( CS_AMBIENT_SET ), cg.refdef.vieworg ); // first person blend blobs, done after AnglesToAxis if ( !cg.renderingThirdPerson ) { CG_DamageBlendBlob(); } // build the render lists if ( !cg.hyperspace ) { CG_AddPacketEntities(); // adter calcViewValues, so predicted player state is correct CG_AddMarks(); CG_AddLocalEntities(); } // Don't draw the in-view weapon when in camera mode if ( !in_camera && !cg_pano.integer ) CG_AddViewWeapon( &cg.predicted_player_state ); // 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 ) ); // update audio positions cgi_S_Respatialize( cg.snap->ps.clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater ); // warning sounds when powerup is wearing off CG_PowerupTimerSounds(); // make sure the lagometerSample and frame timing isn't done twice when in stereo if ( stereoView != STEREO_RIGHT ) { cg.frametime = cg.time - cg.oldTime; cg.oldTime = cg.time; } //Add all effects if (cg.frametime >= 0) { FX_Add(); } if ( cg_pano.integer ) { // let's grab a panorama! cg.levelShot = qtrue; //hide the 2d VectorClear(cg.refdefViewAngles); cg.refdefViewAngles[YAW] = -360 * cg_pano.integer/cg_panoNumShots.integer; //choose angle AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis ); CG_DrawActive( stereoView ); cg.levelShot = qfalse; } else { // actually issue the rendering calls CG_DrawActive( stereoView ); } }