void CASWInput::CAM_Think( void ) { Assert( engine->IsLocalPlayerResolvable() ); UpdateOrderArrow(); // update the arrow direction if we're in the middle of ordering a marine (see in_main.cpp) switch( GetPerUser().m_nCamCommand ) { case CAM_COMMAND_TOTHIRDPERSON: CAM_ToThirdPerson(); break; case CAM_COMMAND_TOFIRSTPERSON: CAM_ToFirstPerson(); break; case CAM_COMMAND_NONE: default: break; } if( !GetPerUser().m_fCameraInThirdPerson ) return; GetPerUser().m_vecCameraOffset[ PITCH ] = ASW_GetCameraPitch(); GetPerUser().m_vecCameraOffset[ YAW ] = ASW_GetCameraYaw(); GetPerUser().m_vecCameraOffset[ DIST ] = 0; }
void ToggleThirdPerson( bool bValue ) { if ( bValue == true ) { CAM_ToThirdPerson(); } else { CAM_ToFirstPerson(); } }
void CAM_Toggle( void ) { #ifdef DEBUG if(cam_thirdperson) { CAM_ToFirstPerson(); } else { CAM_ToThirdPerson(); } #endif }
/* ============================== CAM_Think ============================== */ void CInput::CAM_Think( void ) { VPROF("CAM_Think"); // if ( m_pCameraThirdData ) { return CAM_CameraThirdThink(); } Vector idealAngles; Vector camOffset; float flSensitivity; QAngle viewangles; switch( cam_command.GetInt() ) { case CAM_COMMAND_TOTHIRDPERSON: CAM_ToThirdPerson(); break; case CAM_COMMAND_TOFIRSTPERSON: CAM_ToFirstPerson(); break; case CAM_COMMAND_NONE: default: break; } //All this code after this comment has to do with thirdperson g_ThirdPersonManager.Update(); if( !m_fCameraInThirdPerson ) return; // In Maya-mode if ( Is_CAM_ThirdPerson_MayaMode() ) { // Unless explicitly moving the camera, don't move it m_fCameraInterceptingMouse = m_fCameraMovingWithMouse = vgui::input()->IsKeyDown( KEY_LALT ) || vgui::input()->IsKeyDown( KEY_RALT ); if ( !m_fCameraMovingWithMouse ) return; // Zero-out camera-control kbutton_t structures memset( &cam_pitchup, 0, sizeof( cam_pitchup ) ); memset( &cam_pitchdown, 0, sizeof( cam_pitchdown ) ); memset( &cam_yawleft, 0, sizeof( cam_yawleft ) ); memset( &cam_yawright, 0, sizeof( cam_yawright ) ); memset( &cam_in, 0, sizeof( cam_in ) ); memset( &cam_out, 0, sizeof( cam_out ) ); // Unless left or right mouse button is down, don't do anything #ifndef _XBOX if ( /* Left+Middle Button Down */ vgui::input()->IsMouseDown( MOUSE_LEFT ) && vgui::input()->IsMouseDown( MOUSE_MIDDLE ) ) { // Do only zoom in/out camera adjustment m_fCameraDistanceMove = true; } else if ( /* Left Button Down */ vgui::input()->IsMouseDown( MOUSE_LEFT ) ) { // Do only rotational camera movement m_fCameraDistanceMove = false; } else if ( /* Right Button Down */ vgui::input()->IsMouseDown( MOUSE_RIGHT ) ) { // Do only zoom in/out camera adjustment m_fCameraDistanceMove = true; } else { // Neither left or right buttons down, don't do anything ResetMouse(); return; } #endif } idealAngles[ PITCH ] = cam_idealpitch.GetFloat(); idealAngles[ YAW ] = cam_idealyaw.GetFloat(); idealAngles[ DIST ] = cam_idealdist.GetFloat(); // //movement of the camera with the mouse // if ( m_fCameraMovingWithMouse ) { int cpx, cpy; #ifndef _XBOX //get windows cursor position GetMousePos (cpx, cpy); #else //xboxfixme cpx = cpy = 0; #endif m_nCameraX = cpx; m_nCameraY = cpy; //check for X delta values and adjust accordingly //eventually adjust YAW based on amount of movement //don't do any movement of the cam using YAW/PITCH if we are zooming in/out the camera if (!m_fCameraDistanceMove) { int x, y; GetWindowCenter( x, y ); //keep the camera within certain limits around the player (ie avoid certain bad viewing angles) if (m_nCameraX>x) { //if ((idealAngles[YAW]>=225.0)||(idealAngles[YAW]<135.0)) if (idealAngles[YAW]<c_maxyaw.GetFloat()) { idealAngles[ YAW ] += (CAM_ANGLE_MOVE)*((m_nCameraX-x)/2); } if (idealAngles[YAW]>c_maxyaw.GetFloat()) { idealAngles[YAW]=c_maxyaw.GetFloat(); } } else if (m_nCameraX<x) { //if ((idealAngles[YAW]<=135.0)||(idealAngles[YAW]>225.0)) if (idealAngles[YAW]>c_minyaw.GetFloat()) { idealAngles[ YAW ] -= (CAM_ANGLE_MOVE)* ((x-m_nCameraX)/2); } if (idealAngles[YAW]<c_minyaw.GetFloat()) { idealAngles[YAW]=c_minyaw.GetFloat(); } } //check for y delta values and adjust accordingly //eventually adjust PITCH based on amount of movement //also make sure camera is within bounds if (m_nCameraY > y) { if(idealAngles[PITCH]<c_maxpitch.GetFloat()) { idealAngles[PITCH] +=(CAM_ANGLE_MOVE)* ((m_nCameraY-y)/2); } if (idealAngles[PITCH]>c_maxpitch.GetFloat()) { idealAngles[PITCH]=c_maxpitch.GetFloat(); } } else if (m_nCameraY<y) { if (idealAngles[PITCH]>c_minpitch.GetFloat()) { idealAngles[PITCH] -= (CAM_ANGLE_MOVE)*((y-m_nCameraY)/2); } if (idealAngles[PITCH]<c_minpitch.GetFloat()) { idealAngles[PITCH]=c_minpitch.GetFloat(); } } //set old mouse coordinates to current mouse coordinates //since we are done with the mouse if ( ( flSensitivity = gHUD.GetSensitivity() ) != 0 ) { m_nCameraOldX=m_nCameraX*flSensitivity; m_nCameraOldY=m_nCameraY*flSensitivity; } else { m_nCameraOldX=m_nCameraX; m_nCameraOldY=m_nCameraY; } #ifndef _XBOX ResetMouse(); #endif } } //Nathan code here if( input->KeyState( &cam_pitchup ) ) idealAngles[ PITCH ] += cam_idealdelta.GetFloat(); else if( input->KeyState( &cam_pitchdown ) ) idealAngles[ PITCH ] -= cam_idealdelta.GetFloat(); if( input->KeyState( &cam_yawleft ) ) idealAngles[ YAW ] -= cam_idealdelta.GetFloat(); else if( input->KeyState( &cam_yawright ) ) idealAngles[ YAW ] += cam_idealdelta.GetFloat(); if( input->KeyState( &cam_in ) ) { idealAngles[ DIST ] -= 2*cam_idealdelta.GetFloat(); if( idealAngles[ DIST ] < CAM_MIN_DIST ) { // If we go back into first person, reset the angle idealAngles[ PITCH ] = 0; idealAngles[ YAW ] = 0; idealAngles[ DIST ] = CAM_MIN_DIST; } } else if( input->KeyState( &cam_out ) ) idealAngles[ DIST ] += 2*cam_idealdelta.GetFloat(); if (m_fCameraDistanceMove) { int x, y; GetWindowCenter( x, y ); if (m_nCameraY>y) { if(idealAngles[ DIST ]<c_maxdistance.GetFloat()) { idealAngles[ DIST ] +=cam_idealdelta.GetFloat() * ((m_nCameraY-y)/2); } if (idealAngles[ DIST ]>c_maxdistance.GetFloat()) { idealAngles[ DIST ]=c_maxdistance.GetFloat(); } } else if (m_nCameraY<y) { if (idealAngles[ DIST ]>c_mindistance.GetFloat()) { idealAngles[ DIST ] -= (cam_idealdelta.GetFloat())*((y-m_nCameraY)/2); } if (idealAngles[ DIST ]<c_mindistance.GetFloat()) { idealAngles[ DIST ]=c_mindistance.GetFloat(); } } //set old mouse coordinates to current mouse coordinates //since we are done with the mouse m_nCameraOldX=m_nCameraX*gHUD.GetSensitivity(); m_nCameraOldY=m_nCameraY*gHUD.GetSensitivity(); #ifndef _XBOX ResetMouse(); #endif } // Obtain engine view angles and if they popped while the camera was static, // fix the camera angles as well engine->GetViewAngles( viewangles ); static QAngle s_oldAngles = viewangles; if ( Is_CAM_ThirdPerson_MayaMode() && ( s_oldAngles != viewangles ) ) { idealAngles[ PITCH ] += s_oldAngles[ PITCH ] - viewangles[ PITCH ]; idealAngles[ YAW ] += s_oldAngles[ YAW ] - viewangles[ YAW ]; s_oldAngles = viewangles; } // bring the pitch values back into a range that MoveToward can handle if ( idealAngles[ PITCH ] > 180 ) idealAngles[ PITCH ] -= 360; else if ( idealAngles[ PITCH ] < -180 ) idealAngles[ PITCH ] += 360; // bring the yaw values back into a range that MoveToward can handle // -- // Vitaliy: going with >= 180 and <= -180. // This introduces a potential discontinuity when looking directly at model face // as camera yaw will be jumping from +180 to -180 and back, but when working with // the camera allows smooth rotational transitions from left to right and back. // Otherwise one of the transitions that has ">"-comparison will be locked. // -- if ( idealAngles[ YAW ] >= 180 ) idealAngles[ YAW ] -= 360; else if ( idealAngles[ YAW ] <= -180 ) idealAngles[ YAW ] += 360; // clamp pitch, yaw and dist... idealAngles[ PITCH ] = clamp( idealAngles[ PITCH ], c_minpitch.GetFloat(), c_maxpitch.GetFloat() ); idealAngles[ YAW ] = clamp( idealAngles[ YAW ], c_minyaw.GetFloat(), c_maxyaw.GetFloat() ); idealAngles[ DIST ] = clamp( idealAngles[ DIST ], c_mindistance.GetFloat(), c_maxdistance.GetFloat() ); // update ideal angles cam_idealpitch.SetValue( idealAngles[ PITCH ] ); cam_idealyaw.SetValue( idealAngles[ YAW ] ); cam_idealdist.SetValue( idealAngles[ DIST ] ); // Move the CameraOffset "towards" the idealAngles // Note: CameraOffset = viewangle + idealAngle VectorCopy( g_ThirdPersonManager.GetCameraOffsetAngles(), camOffset ); if( cam_snapto.GetInt() ) { camOffset[ YAW ] = cam_idealyaw.GetFloat() + viewangles[ YAW ]; camOffset[ PITCH ] = cam_idealpitch.GetFloat() + viewangles[ PITCH ]; camOffset[ DIST ] = cam_idealdist.GetFloat(); } else { float lag = MAX( 1, 1 + cam_ideallag.GetFloat() ); if( camOffset[ YAW ] - viewangles[ YAW ] != cam_idealyaw.GetFloat() ) camOffset[ YAW ] = MoveToward( camOffset[ YAW ], cam_idealyaw.GetFloat() + viewangles[ YAW ], lag ); if( camOffset[ PITCH ] - viewangles[ PITCH ] != cam_idealpitch.GetFloat() ) camOffset[ PITCH ] = MoveToward( camOffset[ PITCH ], cam_idealpitch.GetFloat() + viewangles[ PITCH ], lag ); if( abs( camOffset[ DIST ] - cam_idealdist.GetFloat() ) < 2.0 ) camOffset[ DIST ] = cam_idealdist.GetFloat(); else camOffset[ DIST ] += ( cam_idealdist.GetFloat() - camOffset[ DIST ] ) / lag; } // move the camera closer to the player if it hit something if ( cam_collision.GetInt() ) { QAngle desiredCamAngles = QAngle( camOffset[ PITCH ], camOffset[ YAW ], camOffset[ DIST ] ); if ( g_ThirdPersonManager.IsOverridingThirdPerson() == false ) { desiredCamAngles = viewangles; } g_ThirdPersonManager.PositionCamera( C_BasePlayer::GetLocalPlayer(), desiredCamAngles ); } if ( cam_showangles.GetInt() ) { engine->Con_NPrintf( 4, "Pitch: %6.1f Yaw: %6.1f %38s", viewangles[ PITCH ], viewangles[ YAW ], "view angles" ); engine->Con_NPrintf( 6, "Pitch: %6.1f Yaw: %6.1f Dist: %6.1f %19s", cam_idealpitch.GetFloat(), cam_idealyaw.GetFloat(), cam_idealdist.GetFloat(), "ideal angles" ); engine->Con_NPrintf( 8, "Pitch: %6.1f Yaw: %6.1f Dist: %6.1f %16s", g_ThirdPersonManager.GetCameraOffsetAngles()[ PITCH ], g_ThirdPersonManager.GetCameraOffsetAngles()[ YAW ], g_ThirdPersonManager.GetCameraOffsetAngles()[ DIST ], "camera offset" ); } //g_ThirdPersonManager.SetCameraOffsetAngles( camOffset ); g_ThirdPersonManager.SetCameraOffsetAngles(camOffset); }
void CHud :: MsgFunc_ViewMode( const char *pszName, int iSize, void *pbuf ) { CAM_ToFirstPerson(); }
void CL_DLLEXPORT CAM_Think( void ) { RecClCamThink(); #ifdef HL_CAMERA vec3_t origin; vec3_t ext, pnt, camForward, camRight, camUp; moveclip_t clip; float dist; vec3_t camAngles; float flSensitivity; #ifdef LATER int i; #endif vec3_t viewangles; switch( (int) cam_command->value ) { case CAM_COMMAND_TOTHIRDPERSON: CAM_ToThirdPerson(); break; case CAM_COMMAND_TOFIRSTPERSON: CAM_ToFirstPerson(); break; case CAM_COMMAND_NONE: default: break; } if( !cam_thirdperson ) return; #ifdef LATER if ( cam_contain->value ) { gEngfuncs.GetClientOrigin( origin ); ext[0] = ext[1] = ext[2] = 0.0; } #endif camAngles[ PITCH ] = cam_idealpitch->value; camAngles[ YAW ] = cam_idealyaw->value; dist = cam_idealdist->value; // //movement of the camera with the mouse // if (cam_mousemove) { //get windows cursor position GetCursorPos (&cam_mouse); //check for X delta values and adjust accordingly //eventually adjust YAW based on amount of movement //don't do any movement of the cam using YAW/PITCH if we are zooming in/out the camera if (!cam_distancemove) { //keep the camera within certain limits around the player (ie avoid certain bad viewing angles) if (cam_mouse.x>gEngfuncs.GetWindowCenterX()) { //if ((camAngles[YAW]>=225.0)||(camAngles[YAW]<135.0)) if (camAngles[YAW]<c_maxyaw->value) { camAngles[ YAW ] += (CAM_ANGLE_MOVE)*((cam_mouse.x-gEngfuncs.GetWindowCenterX())/2); } if (camAngles[YAW]>c_maxyaw->value) { camAngles[YAW]=c_maxyaw->value; } } else if (cam_mouse.x<gEngfuncs.GetWindowCenterX()) { //if ((camAngles[YAW]<=135.0)||(camAngles[YAW]>225.0)) if (camAngles[YAW]>c_minyaw->value) { camAngles[ YAW ] -= (CAM_ANGLE_MOVE)* ((gEngfuncs.GetWindowCenterX()-cam_mouse.x)/2); } if (camAngles[YAW]<c_minyaw->value) { camAngles[YAW]=c_minyaw->value; } } //check for y delta values and adjust accordingly //eventually adjust PITCH based on amount of movement //also make sure camera is within bounds if (cam_mouse.y>gEngfuncs.GetWindowCenterY()) { if(camAngles[PITCH]<c_maxpitch->value) { camAngles[PITCH] +=(CAM_ANGLE_MOVE)* ((cam_mouse.y-gEngfuncs.GetWindowCenterY())/2); } if (camAngles[PITCH]>c_maxpitch->value) { camAngles[PITCH]=c_maxpitch->value; } } else if (cam_mouse.y<gEngfuncs.GetWindowCenterY()) { if (camAngles[PITCH]>c_minpitch->value) { camAngles[PITCH] -= (CAM_ANGLE_MOVE)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2); } if (camAngles[PITCH]<c_minpitch->value) { camAngles[PITCH]=c_minpitch->value; } } //set old mouse coordinates to current mouse coordinates //since we are done with the mouse if ( ( flSensitivity = gHUD.GetSensitivity() ) != 0 ) { cam_old_mouse_x=cam_mouse.x*flSensitivity; cam_old_mouse_y=cam_mouse.y*flSensitivity; } else { cam_old_mouse_x=cam_mouse.x; cam_old_mouse_y=cam_mouse.y; } SetCursorPos (gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY()); } } //Nathan code here if( CL_KeyState( &cam_pitchup ) ) camAngles[ PITCH ] += CAM_ANGLE_DELTA; else if( CL_KeyState( &cam_pitchdown ) ) camAngles[ PITCH ] -= CAM_ANGLE_DELTA; if( CL_KeyState( &cam_yawleft ) ) camAngles[ YAW ] -= CAM_ANGLE_DELTA; else if( CL_KeyState( &cam_yawright ) ) camAngles[ YAW ] += CAM_ANGLE_DELTA; if( CL_KeyState( &cam_in ) ) { dist -= CAM_DIST_DELTA; if( dist < CAM_MIN_DIST ) { // If we go back into first person, reset the angle camAngles[ PITCH ] = 0; camAngles[ YAW ] = 0; dist = CAM_MIN_DIST; } } else if( CL_KeyState( &cam_out ) ) dist += CAM_DIST_DELTA; if (cam_distancemove) { if (cam_mouse.y>gEngfuncs.GetWindowCenterY()) { if(dist<c_maxdistance->value) { dist +=CAM_DIST_DELTA * ((cam_mouse.y-gEngfuncs.GetWindowCenterY())/2); } if (dist>c_maxdistance->value) { dist=c_maxdistance->value; } } else if (cam_mouse.y<gEngfuncs.GetWindowCenterY()) { if (dist>c_mindistance->value) { dist -= (CAM_DIST_DELTA)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2); } if (dist<c_mindistance->value) { dist=c_mindistance->value; } } //set old mouse coordinates to current mouse coordinates //since we are done with the mouse cam_old_mouse_x=cam_mouse.x*gHUD.GetSensitivity(); cam_old_mouse_y=cam_mouse.y*gHUD.GetSensitivity(); SetCursorPos (gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY()); } #ifdef LATER if( cam_contain->value ) { // check new ideal VectorCopy( origin, pnt ); AngleVectors( camAngles, camForward, camRight, camUp ); for (i=0 ; i<3 ; i++) pnt[i] += -dist*camForward[i]; // check line from r_refdef.vieworg to pnt memset ( &clip, 0, sizeof ( moveclip_t ) ); clip.trace = SV_ClipMoveToEntity( sv.edicts, r_refdef.vieworg, ext, ext, pnt ); if( clip.trace.fraction == 1.0 ) { // update ideal cam_idealpitch->value = camAngles[ PITCH ]; cam_idealyaw->value = camAngles[ YAW ]; cam_idealdist->value = dist; } } else #endif { // update ideal cam_idealpitch->value = camAngles[ PITCH ]; cam_idealyaw->value = camAngles[ YAW ]; cam_idealdist->value = dist; } // Move towards ideal VectorCopy( cam_ofs, camAngles ); gEngfuncs.GetViewAngles( (float *)viewangles ); if( cam_snapto->value ) { camAngles[ YAW ] = cam_idealyaw->value + viewangles[ YAW ]; camAngles[ PITCH ] = cam_idealpitch->value + viewangles[ PITCH ]; camAngles[ 2 ] = cam_idealdist->value; } else { if( camAngles[ YAW ] - viewangles[ YAW ] != cam_idealyaw->value ) camAngles[ YAW ] = MoveToward( camAngles[ YAW ], cam_idealyaw->value + viewangles[ YAW ], CAM_ANGLE_SPEED ); if( camAngles[ PITCH ] - viewangles[ PITCH ] != cam_idealpitch->value ) camAngles[ PITCH ] = MoveToward( camAngles[ PITCH ], cam_idealpitch->value + viewangles[ PITCH ], CAM_ANGLE_SPEED ); if( abs( camAngles[ 2 ] - cam_idealdist->value ) < 2.0 ) camAngles[ 2 ] = cam_idealdist->value; else camAngles[ 2 ] += ( cam_idealdist->value - camAngles[ 2 ] ) / 4.0; } #ifdef LATER if( cam_contain->value ) { // Test new position dist = camAngles[ ROLL ]; camAngles[ ROLL ] = 0; VectorCopy( origin, pnt ); AngleVectors( camAngles, camForward, camRight, camUp ); for (i=0 ; i<3 ; i++) pnt[i] += -dist*camForward[i]; // check line from r_refdef.vieworg to pnt memset ( &clip, 0, sizeof ( moveclip_t ) ); ext[0] = ext[1] = ext[2] = 0.0; clip.trace = SV_ClipMoveToEntity( sv.edicts, r_refdef.vieworg, ext, ext, pnt ); if( clip.trace.fraction != 1.0 ) return; } #endif cam_ofs[ 0 ] = camAngles[ 0 ]; cam_ofs[ 1 ] = camAngles[ 1 ]; cam_ofs[ 2 ] = dist; // HL_CAMERA #endif }
/* ================== V_CalcRefdef ================== */ void V_CalcNormalRefdef(struct ref_params_s *pparams) { cl_entity_t * ent, *view; int i; vec3_t angles; float bob, waterOffset; static viewinterp_t ViewInterp; static float oldz = 0; static float lasttime; static float lastang[3]; vec3_t angdelta; vec3_t camAngles, camForward, camRight, camUp; cl_entity_t *pwater; // don't allow cheats in multiplayer if(pparams->maxclients > 1) { scr_ofsx->value = 0.0; scr_ofsy->value = 0.0; scr_ofsz->value = 0.0; } V_DriftPitch(pparams); // ent is the player model ( visible when out of body ) ent = gEngfuncs.GetLocalPlayer(); // view is the weapon model (only visible from inside body ) view = gEngfuncs.GetViewModel(); // transform the view offset by the model's matrix to get the offset from // model origin for the view bob = V_CalcBob(pparams); // Observer angle capturing and smoothing if(iHasNewViewOrigin) { // Get the angles from the physics code VectorCopy(vecNewViewOrigin, pparams->vieworg); VectorCopy(vecNewViewOrigin, pparams->simorg); } // refresh position VectorCopy(pparams->simorg, pparams->vieworg); pparams->vieworg[2] += (bob); VectorAdd(pparams->vieworg, pparams->viewheight, pparams->vieworg); // Observer angle capturing and smoothing if(iHasNewViewAngles) { // Get the angles from the physics code VectorCopy(vecNewViewAngles, pparams->cl_viewangles); } else if(pparams->health == -5) { CAM_ToThirdPerson(); // Lock mouse movement iMouseInUse = 1; pparams->cl_viewangles[0] = 89; // Spin the view float flTimeDelta = (pparams->time - g_flStartScaleTime); if(flTimeDelta > 0) { float flROFSpin = 1.0 + (flTimeDelta * 2.0); float flSpin = flTimeDelta * 45; pparams->cl_viewangles[1] = flSpin * flROFSpin; } } else { CAM_ToFirstPerson(); // Unlock mouse movement iMouseInUse = 0; } VectorSubtract(pparams->cl_viewangles, lastang, angdelta); if(Length(angdelta) != 0.0) { VectorCopy(pparams->cl_viewangles, ViewInterp.Angles[ViewInterp.CurrentAngle & ORIGIN_MASK]); ViewInterp.AngleTime[ViewInterp.CurrentAngle & ORIGIN_MASK] = pparams->time; ViewInterp.CurrentAngle++; VectorCopy(pparams->cl_viewangles, lastang); } if(cl_vsmoothing && cl_vsmoothing->value && (iIsSpectator & SPEC_SMOOTH_ANGLES)) { int foundidx; int i; float t; if(cl_vsmoothing->value < 0.0) { gEngfuncs.Cvar_SetValue("cl_vsmoothing", 0.0); } t = pparams->time - cl_vsmoothing->value; for(i = 1; i < ORIGIN_MASK; i++) { foundidx = ViewInterp.CurrentAngle - 1 - i; if(ViewInterp.AngleTime[foundidx & ORIGIN_MASK] <= t) break; } if(i < ORIGIN_MASK && ViewInterp.AngleTime[foundidx & ORIGIN_MASK] != 0.0) { // Interpolate double dt; dt = ViewInterp.AngleTime[(foundidx + 1) & ORIGIN_MASK] - ViewInterp.AngleTime[foundidx & ORIGIN_MASK]; if(dt > 0.0) { double frac; frac = (t - ViewInterp.AngleTime[foundidx & ORIGIN_MASK]) / dt; frac = min(1.0, frac); // interpolate angles V_InterpolateAngles(ViewInterp.Angles[foundidx & ORIGIN_MASK], ViewInterp.Angles[(foundidx + 1) & ORIGIN_MASK], pparams->cl_viewangles, frac); VectorCopy(pparams->cl_viewangles, vecNewViewAngles); } } } VectorCopy(pparams->cl_viewangles, pparams->viewangles); gEngfuncs.V_CalcShake(); gEngfuncs.V_ApplyShake(pparams->vieworg, pparams->viewangles, 1.0); // never let view origin sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // FIXME, we send origin at 1/128 now, change this? // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis pparams->vieworg[0] += 1.0 / 32; pparams->vieworg[1] += 1.0 / 32; pparams->vieworg[2] += 1.0 / 32; // Check for problems around water, move the viewer artificially if necessary // -- this prevents drawing errors in GL due to waves waterOffset = 0; if(pparams->waterlevel >= 2) { int i, contents, waterDist, waterEntity; vec3_t point; waterDist = cl_waterdist->value; if(pparams->hardware) { waterEntity = gEngfuncs.PM_WaterEntity(pparams->simorg); if(waterEntity >= 0 && waterEntity < pparams->max_entities) { pwater = gEngfuncs.GetEntityByIndex(waterEntity); if(pwater && (pwater->model != NULL)) { waterDist += (pwater->curstate.scale * 16); // Add in wave height } } } else { waterEntity = 0; // Don't need this in software } VectorCopy(pparams->vieworg, point); // Eyes are above water, make sure we're above the waves if(pparams->waterlevel == 2) { point[2] -= waterDist; for(i = 0; i < waterDist; i++) { contents = gEngfuncs.PM_PointContents(point, NULL); if(contents > CONTENTS_WATER) break; point[2] += 1; } waterOffset = (point[2] + waterDist) - pparams->vieworg[2]; } else { // eyes are under water. Make sure we're far enough under point[2] += waterDist; for(i = 0; i < waterDist; i++) { contents = gEngfuncs.PM_PointContents(point, NULL); if(contents <= CONTENTS_WATER) break; point[2] -= 1; } waterOffset = (point[2] - waterDist) - pparams->vieworg[2]; } } pparams->vieworg[2] += waterOffset; V_CalcViewRoll(pparams); V_AddIdle(pparams); // offsets VectorCopy(pparams->cl_viewangles, angles); AngleVectors(angles, pparams->forward, pparams->right, pparams->up); for(i = 0; i < 3; i++) { pparams->vieworg[i] += scr_ofsx->value * pparams->forward[i] + scr_ofsy->value * pparams->right[i] + scr_ofsz->value * pparams->up[i]; } // Treating cam_ofs[2] as the distance if(CL_IsThirdPerson()) { vec3_t ofs; ofs[0] = ofs[1] = ofs[2] = 0.0; CL_CameraOffset((float *)&ofs); VectorCopy(ofs, camAngles); camAngles[ROLL] = 0; AngleVectors(camAngles, camForward, camRight, camUp); // Is the player in a falling anim? If so, raise camera above and look down if(pparams->health == -5) { pparams->vieworg[2] += 92; } else { for(i = 0; i < 3; i++) { pparams->vieworg[i] += -ofs[2] * camForward[i]; } pparams->vieworg[2] += 20; } } // Give gun our viewangles VectorCopy(pparams->cl_viewangles, view->angles); // set up gun position V_CalcGunAngle(pparams); // Use predicted origin as view origin. VectorCopy(pparams->simorg, view->origin); view->origin[2] += (waterOffset); VectorAdd(view->origin, pparams->viewheight, view->origin); // Let the viewmodel shake at about 10% of the amplitude gEngfuncs.V_ApplyShake(view->origin, view->angles, 0.9); for(i = 0; i < 3; i++) { view->origin[i] += bob * 0.4 * pparams->forward[i]; } view->origin[2] += bob; // throw in a little tilt. view->angles[YAW] -= bob * 0.5; view->angles[ROLL] -= bob * 1; view->angles[PITCH] -= bob * 0.3; // pushing the view origin down off of the same X/Z plane as the ent's origin will give the // gun a very nice 'shifting' effect when the player looks up/down. If there is a problem // with view model distortion, this may be a cause. (SJB). view->origin[2] -= 1; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if(pparams->viewsize == 110) { view->origin[2] += 1; } else if(pparams->viewsize == 100) { view->origin[2] += 2; } else if(pparams->viewsize == 90) { view->origin[2] += 1; } else if(pparams->viewsize == 80) { view->origin[2] += 0.5; } // Add in the punchangle, if any VectorAdd(pparams->viewangles, pparams->punchangle, pparams->viewangles); // Include client side punch, too VectorAdd(pparams->viewangles, (float *)&ev_punchangle, pparams->viewangles); V_DropPunchAngle(pparams->frametime, (float *)&ev_punchangle); // smooth out stair step ups #if 1 if(!pparams->smoothing && pparams->onground && pparams->simorg[2] - oldz > 0) { float steptime; steptime = pparams->time - lasttime; if(steptime < 0) //FIXME I_Error ("steptime < 0"); steptime = 0; oldz += steptime * 150; if(oldz > pparams->simorg[2]) oldz = pparams->simorg[2]; if(pparams->simorg[2] - oldz > 18) oldz = pparams->simorg[2] - 18; pparams->vieworg[2] += oldz - pparams->simorg[2]; view->origin[2] += oldz - pparams->simorg[2]; } else { oldz = pparams->simorg[2]; } #endif { static float lastorg[3]; vec3_t delta; VectorSubtract(pparams->simorg, lastorg, delta); if(Length(delta) != 0.0) { VectorCopy(pparams->simorg, ViewInterp.Origins[ViewInterp.CurrentOrigin & ORIGIN_MASK]); ViewInterp.OriginTime[ViewInterp.CurrentOrigin & ORIGIN_MASK] = pparams->time; ViewInterp.CurrentOrigin++; VectorCopy(pparams->simorg, lastorg); } } // Smooth out whole view in multiplayer when on trains, lifts if(cl_vsmoothing && cl_vsmoothing->value && ((iIsSpectator & SPEC_SMOOTH_ORIGIN) || (pparams->smoothing && (pparams->maxclients > 1)))) { int foundidx; int i; float t; if(cl_vsmoothing->value < 0.0) { gEngfuncs.Cvar_SetValue("cl_vsmoothing", 0.0); } t = pparams->time - cl_vsmoothing->value; for(i = 1; i < ORIGIN_MASK; i++) { foundidx = ViewInterp.CurrentOrigin - 1 - i; if(ViewInterp.OriginTime[foundidx & ORIGIN_MASK] <= t) break; } if(i < ORIGIN_MASK && ViewInterp.OriginTime[foundidx & ORIGIN_MASK] != 0.0) { // Interpolate vec3_t delta; double frac; double dt; vec3_t neworg; dt = ViewInterp.OriginTime[(foundidx + 1) & ORIGIN_MASK] - ViewInterp.OriginTime[foundidx & ORIGIN_MASK]; if(dt > 0.0) { frac = (t - ViewInterp.OriginTime[foundidx & ORIGIN_MASK]) / dt; frac = min(1.0, frac); VectorSubtract(ViewInterp.Origins[(foundidx + 1) & ORIGIN_MASK], ViewInterp.Origins[foundidx & ORIGIN_MASK], delta); VectorMA(ViewInterp.Origins[foundidx & ORIGIN_MASK], frac, delta, neworg); // Dont interpolate large changes if(Length(delta) < 64) { VectorSubtract(neworg, pparams->simorg, delta); VectorAdd(pparams->simorg, delta, pparams->simorg); VectorAdd(pparams->vieworg, delta, pparams->vieworg); VectorAdd(view->origin, delta, view->origin); VectorCopy(pparams->simorg, vecNewViewOrigin); } } } } // Store off v_angles before munging for third person v_angles = pparams->viewangles; if(CL_IsThirdPerson()) { VectorCopy(camAngles, pparams->viewangles); } // override all previous settings if the viewent isn't the client if(pparams->viewentity > pparams->maxclients) { cl_entity_t *viewentity; viewentity = gEngfuncs.GetEntityByIndex(pparams->viewentity); if(viewentity) { VectorCopy(viewentity->origin, pparams->vieworg); VectorCopy(viewentity->angles, pparams->viewangles); // Store off overridden viewangles v_angles = pparams->viewangles; } } lasttime = pparams->time; v_origin = pparams->vieworg; }