/* ================ CL_MouseMove ================ */ static void CL_MouseMove( void ) { static int old_dx, old_dy; int dx, dy; float mx, my; float speed; if( !input.initialized ) { return; } if( cls.key_dest & (KEY_MENU|KEY_CONSOLE) ) { return; } if( !input.api.GetMotion( &dx, &dy ) ) { return; } if( m_filter->integer ) { mx = ( dx + old_dx ) * 0.5f; my = ( dy + old_dy ) * 0.5f; } else { mx = dx; my = dy; } old_dx = dx; old_dy = dy; if( !mx && !my ) { return; } Cvar_ClampValue( m_accel, 0, 1 ); speed = sqrt( mx * mx + my * my ); speed = sensitivity->value + speed * m_accel->value; mx *= speed; my *= speed; if( m_autosens->integer ) { mx *= cl.fov_x / 90.0f; my *= V_CalcFov( cl.fov_x, 4, 3 ) / 73.739795291688f; } // add mouse X/Y movement if( ( in_strafe.state & 1 ) || ( lookstrafe->integer && !in_mlooking ) ) { cl.mousemove[1] += m_side->value * mx; } else { cl.viewangles[YAW] -= m_yaw->value * mx; } if( ( in_mlooking || freelook->integer ) && !( in_strafe.state & 1 ) ) { cl.viewangles[PITCH] += m_pitch->value * my; } else { cl.mousemove[0] -= m_forward->value * my; } }
/* =============== V_SetupRefDef update refdef values each frame =============== */ void V_SetupRefDef( void ) { cl_entity_t *clent; clent = CL_GetLocalPlayer (); clgame.entities->curstate.scale = clgame.movevars.waveHeight; VectorCopy( cl.frame.local.client.punchangle, cl.refdef.punchangle ); clgame.viewent.curstate.modelindex = cl.frame.local.client.viewmodel; clgame.viewent.model = Mod_Handle( clgame.viewent.curstate.modelindex ); clgame.viewent.curstate.entityType = ET_NORMAL; clgame.viewent.index = cl.playernum + 1; cl.refdef.movevars = &clgame.movevars; cl.refdef.onground = ( cl.frame.local.client.flags & FL_ONGROUND ) ? 1 : 0; cl.refdef.health = cl.frame.local.client.health; cl.refdef.playernum = cl.playernum; cl.refdef.max_entities = clgame.maxEntities; cl.refdef.maxclients = cl.maxclients; cl.refdef.time = cl.time; cl.refdef.frametime = cl.time - cl.oldtime; cl.refdef.demoplayback = cls.demoplayback; cl.refdef.smoothing = cl_smooth->integer; cl.refdef.waterlevel = cl.frame.local.client.waterlevel; cl.refdef.onlyClientDraw = 0; // reset clientdraw cl.refdef.viewsize = scr_viewsize->integer; cl.refdef.hardware = true; // always true cl.refdef.spectator = cl.spectator; cl.refdef.nextView = 0; // setup default viewport cl.refdef.viewport[0] = cl.refdef.viewport[1] = 0; cl.refdef.viewport[2] = scr_width->integer; cl.refdef.viewport[3] = scr_height->integer; // calc FOV cl.refdef.fov_x = cl.data.fov; // this is a final fov value cl.refdef.fov_y = V_CalcFov( &cl.refdef.fov_x, cl.refdef.viewport[2], cl.refdef.viewport[3] ); if( CL_IsPredicted( ) && !cl.refdef.demoplayback ) { VectorCopy( cl.predicted_origin, cl.refdef.simorg ); VectorCopy( cl.predicted_velocity, cl.refdef.simvel ); VectorCopy( cl.predicted_viewofs, cl.refdef.viewheight ); } else { VectorCopy( cl.frame.local.client.origin, cl.refdef.simorg ); VectorCopy( cl.frame.local.client.view_ofs, cl.refdef.viewheight ); VectorCopy( cl.frame.local.client.velocity, cl.refdef.simvel ); } }
/* ==================== V_AdjustFov ==================== */ void V_AdjustFov( float *fov_x, float *fov_y, float width, float height, qboolean lock_x ) { float x, y; if( width * 3 == 4 * height || width * 4 == height * 5 ) { // 4:3 or 5:4 ratio return; } if( lock_x ) { *fov_y = 2 * atan((width * 3) / (height * 4) * tan( *fov_y * M_PI / 360.0 * 0.5 )) * 360 / M_PI; return; } y = V_CalcFov( fov_x, 640, 480 ); x = *fov_x; *fov_x = V_CalcFov( &y, height, width ); if( *fov_x < x ) *fov_x = x; else *fov_y = y; }
/* =============== V_SetupRefDef update refdef values each frame =============== */ void V_SetupRefDef( void ) { cl_entity_t *clent; int size; int sb_lines; clent = CL_GetLocalPlayer (); clgame.entities->curstate.scale = clgame.movevars.waveHeight; VectorCopy( cl.frame.local.client.punchangle, cl.refdef.punchangle ); clgame.viewent.curstate.modelindex = cl.frame.local.client.viewmodel; clgame.viewent.model = Mod_Handle( clgame.viewent.curstate.modelindex ); clgame.viewent.curstate.number = cl.playernum + 1; clgame.viewent.curstate.entityType = ET_NORMAL; clgame.viewent.index = cl.playernum + 1; cl.refdef.movevars = &clgame.movevars; cl.refdef.onground = ( cl.frame.local.client.flags & FL_ONGROUND ) ? 1 : 0; cl.refdef.health = cl.frame.local.client.health; cl.refdef.playernum = cl.playernum; cl.refdef.max_entities = clgame.maxEntities; cl.refdef.maxclients = cl.maxclients; cl.refdef.time = cl.time; cl.refdef.frametime = cl.time - cl.oldtime; cl.refdef.demoplayback = cls.demoplayback; cl.refdef.smoothing = cl_smooth->integer; cl.refdef.viewsize = scr_viewsize->integer; cl.refdef.waterlevel = cl.frame.local.client.waterlevel; cl.refdef.onlyClientDraw = 0; // reset clientdraw cl.refdef.hardware = true; // always true cl.refdef.spectator = (clent->curstate.spectator != 0); cl.refdef.nextView = 0; SCR_AddDirtyPoint( 0, 0 ); SCR_AddDirtyPoint( scr_width->integer - 1, scr_height->integer - 1 ); if( cl.refdef.viewsize >= 120 ) sb_lines = 0; // no status bar at all else if( cl.refdef.viewsize >= 110 ) sb_lines = 24; // no inventory else sb_lines = 48; size = min( scr_viewsize->integer, 100 ); cl.refdef.viewport[2] = scr_width->integer * size / 100; cl.refdef.viewport[3] = scr_height->integer * size / 100; if( cl.refdef.viewport[3] > scr_height->integer - sb_lines ) cl.refdef.viewport[3] = scr_height->integer - sb_lines; if( cl.refdef.viewport[3] > scr_height->integer ) cl.refdef.viewport[3] = scr_height->integer; cl.refdef.viewport[0] = (scr_width->integer - cl.refdef.viewport[2]) / 2; cl.refdef.viewport[1] = (scr_height->integer - sb_lines - cl.refdef.viewport[3]) / 2; // calc FOV cl.refdef.fov_x = cl.data.fov; // this is a final fov value cl.refdef.fov_y = V_CalcFov( &cl.refdef.fov_x, cl.refdef.viewport[2], cl.refdef.viewport[3] ); // adjust FOV for widescreen if( glState.wideScreen && r_adjust_fov->integer ) V_AdjustFov( &cl.refdef.fov_x, &cl.refdef.fov_y, cl.refdef.viewport[2], cl.refdef.viewport[3], false ); if( CL_IsPredicted( ) && !cl.refdef.demoplayback ) { VectorCopy( cl.predicted_origin, cl.refdef.simorg ); VectorCopy( cl.predicted_velocity, cl.refdef.simvel ); VectorCopy( cl.predicted_viewofs, cl.refdef.viewheight ); } else { VectorCopy( cl.frame.local.client.origin, cl.refdef.simorg ); VectorCopy( cl.frame.local.client.view_ofs, cl.refdef.viewheight ); VectorCopy( cl.frame.local.client.velocity, cl.refdef.simvel ); } }
//========================== // V_CalcCameraRefdef //========================== void V_CalcCameraRefdef( struct ref_params_s *pparams ) { static float lasttime, oldz = 0; // get viewentity and monster eyeposition cl_entity_t *view = GET_ENTITY( pparams->viewentity ); if( view ) { pparams->vieworg = view->origin; pparams->viewangles = view->angles; // interpolate position for monsters if( view->curstate.movetype == MOVETYPE_STEP ) { float f; // don't do it if the goalstarttime hasn't updated in a while. // NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit // was increased to 1.0 s., which is 2x the max lag we are accounting for. if(( GET_CLIENT_TIME() < view->curstate.animtime + 1.0f ) && ( view->curstate.animtime != view->latched.prevanimtime )) { f = (GET_CLIENT_TIME() - view->curstate.animtime) / (view->curstate.animtime - view->latched.prevanimtime); } if( !( view->curstate.effects & EF_NOINTERP )) { // ugly hack to interpolate angle, position. // current is reached 0.1 seconds after being set f = f - 1.0f; } else { f = 0.0f; } InterpolateOrigin( view->latched.prevorigin, view->origin, pparams->vieworg, f, true ); InterpolateAngles( view->latched.prevangles, view->angles, pparams->viewangles, f, true ); } studiohdr_t *viewmonster = (studiohdr_t *)IEngineStudio.Mod_Extradata( view->model ); if( viewmonster && view->curstate.eflags & EFLAG_SLERP ) { Vector forward; AngleVectors( pparams->viewangles, forward, NULL, NULL ); Vector viewpos = viewmonster->eyeposition; if( viewpos == g_vecZero ) viewpos = Vector( 0, 0, 8 ); // monster_cockroach pparams->vieworg += viewpos + forward * 8; // best value for humans pparams->fov_x = 100; // adjust fov for monster view pparams->fov_y = V_CalcFov( pparams->fov_x, pparams->viewport[2], pparams->viewport[3] ); } // this is smooth stair climbing in thirdperson mode but not affected for client model :( if( !pparams->smoothing && pparams->onground && view->origin[2] - oldz > 0.0f ) { float steptime; steptime = pparams->time - lasttime; if( steptime < 0 ) steptime = 0; oldz += steptime * 150.0f; if( oldz > view->origin[2] ) oldz = view->origin[2]; if( view->origin[2] - oldz > pparams->movevars->stepsize ) oldz = view->origin[2] - pparams->movevars->stepsize; pparams->vieworg[2] += oldz - view->origin[2]; } else { oldz = view->origin[2]; } lasttime = pparams->time; if( view->curstate.effects & EF_NUKE_ROCKET ) pparams->viewangles.x = -pparams->viewangles.x; // stupid quake bug! // g-cont. apply shake to camera gEngfuncs.V_CalcShake(); gEngfuncs.V_ApplyShake( pparams->vieworg, pparams->viewangles, 1.0f ); } }