/* =============== 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; }
/* =============== CG_OffsetShoulderView =============== */ void CG_OffsetShoulderView( void ) { int i; int cmdNum; usercmd_t cmd, oldCmd; vec3_t rotationAngles; vec3_t axis[ 3 ], rotaxis[ 3 ]; float deltaMousePitch; static float mousePitch; vec3_t forward, right, up; classConfig_t* classConfig; // Ignore following pitch; it's too jerky otherwise. if( !cg_thirdPersonPitchFollow.integer ) cg.refdefViewAngles[ PITCH ] = 0.0f; AngleVectors( cg.refdefViewAngles, forward, right, up ); classConfig = BG_ClassConfig( cg.snap->ps.stats[ STAT_CLASS ] ); VectorMA( cg.refdef.vieworg, classConfig->shoulderOffsets[ 0 ], forward, cg.refdef.vieworg ); VectorMA( cg.refdef.vieworg, classConfig->shoulderOffsets[ 1 ], right, cg.refdef.vieworg ); VectorMA( cg.refdef.vieworg, classConfig->shoulderOffsets[ 2 ], up, cg.refdef.vieworg ); // If someone is playing like this, the rest is already taken care of // so just get the firstperson effects and leave. if( !cg.demoPlayback && !( cg.snap->ps.pm_flags & PMF_FOLLOW ) ) { CG_OffsetFirstPersonView(); return; } // Get mouse input for camera rotation. cmdNum = trap_GetCurrentCmdNumber(); trap_GetUserCmd( cmdNum, &cmd ); trap_GetUserCmd( cmdNum - 1, &oldCmd ); // Prevent pitch from wrapping and clamp it within a [30, -50] range. // Cgame has no access to ps.delta_angles[] here, so we need to reproduce // it ourselves here. deltaMousePitch = SHORT2ANGLE( cmd.angles[ PITCH ] - oldCmd.angles[ PITCH ] ); if( fabs(deltaMousePitch) < 200.0f ) mousePitch += deltaMousePitch; // Handle pitch. rotationAngles[ PITCH ] = mousePitch; rotationAngles[ PITCH ] = AngleNormalize180( rotationAngles[ PITCH ] + AngleNormalize180( cg.refdefViewAngles[ PITCH ] ) ); if( rotationAngles [ PITCH ] < -90.0f ) rotationAngles [ PITCH ] = -90.0f; if( rotationAngles [ PITCH ] > 90.0f ) rotationAngles [ PITCH ] = 90.0f; // Yaw and Roll are much easier. rotationAngles[ YAW ] = SHORT2ANGLE( cmd.angles[ YAW ] ) + cg.refdefViewAngles[ YAW ]; rotationAngles[ ROLL ] = 0.0f; // Perform the rotations. AnglesToAxis( rotationAngles, axis ); if( !( cg.snap->ps.stats[ STAT_STATE ] & SS_WALLCLIMBING ) || !BG_RotateAxis( cg.snap->ps.grapplePoint, axis, rotaxis, qfalse, cg.snap->ps.eFlags & EF_WALLCLIMBCEILING ) ) AxisCopy( axis, rotaxis ); AxisToAngles( rotaxis, rotationAngles ); // Actually set the viewangles. for( i = 0; i < 3; i++ ) cg.refdefViewAngles[ i ] = rotationAngles[ i ]; // Now run the first person stuff so we get various effects added. CG_OffsetFirstPersonView( ); }
/* =============== 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(); }
/* =============== 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(); }
/* =============== 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(); }
/* =============== 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(); }
/* =============== 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(); }