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;
}
Beispiel #2
0
void ToggleThirdPerson( bool bValue )
{
	if ( bValue == true )
	{
		CAM_ToThirdPerson();
	}
	else
	{
		CAM_ToFirstPerson();
	}
}
Beispiel #3
0
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);
}
Beispiel #5
0
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
}
Beispiel #6
0
/*
==================
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;
}