Index: binaries/data/config/default.cfg
===================================================================
--- binaries/data/config/default.cfg	(revision 10184)
+++ binaries/data/config/default.cfg	(working copy)
@@ -85,10 +85,16 @@
 view.zoom.min = 96.0
 view.zoom.max = 512.0
 view.zoom.default = 192.0
+view.fov.min = 20
+view.fov.max = 70
+view.fov.speed = 0.5
+view.fov.speed.wheel = 0.1
+view.fov.default = 45
 view.pos.smoothness = 0.1
 view.zoom.smoothness = 0.4
 view.rotate.x.smoothness = 0.5
 view.rotate.y.smoothness = 0.3
+view.fov.smoothness = 0.3
 
 ; HOTKEY MAPPINGS:
 
@@ -120,6 +126,8 @@
 hotkey.camera.rotate.ccw = "Ctrl+RightArrow", "Ctrl+D", E ; Rotate camera anticlockwise around terrain
 hotkey.camera.rotate.wheel.cw = "Shift+WheelUp", MouseX1    ; Rotate camera clockwise around terrain (stepped control)
 hotkey.camera.rotate.wheel.ccw = "Shift+WheelDown", MouseX2 ; Rotate camera anticlockwise around terrain (stepped control)
+hotkey.camera.fov.wheel.increase = "Ctrl+WheelUp"
+hotkey.camera.fov.wheel.decrease = "Ctrl+WheelDown"
 hotkey.camera.pan = MouseMiddle, ForwardSlash             ; Enable scrolling by moving mouse
 hotkey.camera.left = A, LeftArrow                         ; Scroll or rotate left
 hotkey.camera.right = D, RightArrow                       ; Scroll or rotate right
Index: source/graphics/GameView.cpp
===================================================================
--- source/graphics/GameView.cpp	(revision 10184)
+++ source/graphics/GameView.cpp	(working copy)
@@ -59,10 +59,8 @@
 
 extern int g_xres, g_yres;
 
-const float CGameView::defaultFOV = DEGTORAD(20.f);
 const float CGameView::defaultNear = 16.f;
 const float CGameView::defaultFar = 4096.f;
-const float CGameView::defaultCullFOV = CGameView::defaultFOV + DEGTORAD(6.0f);	//add 6 degrees to the default FOV for use with the culling frustum
 
 // Maximum distance outside the edge of the map that the camera's
 // focus point can be moved
@@ -184,6 +182,11 @@
 		ViewZoomMin(0),
 		ViewZoomMax(0),
 		ViewZoomDefault(0),
+		ViewFOVMin(0),
+		ViewFOVMax(0),
+		ViewFOVDefault(0),
+		ViewFOVSpeed(0),
+		ViewFOVSpeedWheel(0),
 		JoystickPanX(-1),
 		JoystickPanY(-1),
 		JoystickRotateX(-1),
@@ -196,7 +199,8 @@
 		PosZ(0, 0, 0.01f),
 		Zoom(0, 0, 0.1f),
 		RotateX(0, 0, 0.001f),
-		RotateY(0, 0, 0.001f)
+		RotateY(0, 0, 0.001f),
+		FOV(DEGTORAD(45.0f), 0, 0.1f)
 	{
 	}
 
@@ -280,6 +284,11 @@
 	float ViewZoomMin;
 	float ViewZoomMax;
 	float ViewZoomDefault;
+	float ViewFOVMin;
+	float ViewFOVMax;
+	float ViewFOVDefault;
+	float ViewFOVSpeed;
+	float ViewFOVSpeedWheel;
 	int JoystickPanX;
 	int JoystickPanY;
 	int JoystickRotateX;
@@ -295,6 +304,7 @@
 	CSmoothedValue Zoom;
 	CSmoothedValue RotateX; // inclination around x axis (relative to camera)
 	CSmoothedValue RotateY; // rotation around y (vertical) axis
+	CSmoothedValue FOV;
 
 	static void ScriptingInit();
 };
@@ -333,7 +343,7 @@
 	vp.m_Height=g_yres;
 	m->ViewCamera.SetViewPort(vp);
 
-	m->ViewCamera.SetProjection(defaultNear, defaultFar, defaultFOV);
+	m->ViewCamera.SetProjection(defaultNear, defaultFar, m->FOV.GetValue());
 	SetupCameraMatrixSmooth(m, &m->ViewCamera.m_Orientation);
 	m->ViewCamera.UpdateFrustum();
 
@@ -351,7 +361,7 @@
 void CGameView::SetViewport(const SViewPort& vp)
 {
 	m->ViewCamera.SetViewPort(vp);
-	m->ViewCamera.SetProjection(defaultNear, defaultFar, defaultFOV);
+	m->ViewCamera.SetProjection(defaultNear, defaultFar, m->FOV.GetValue());
 }
 
 CObjectManager& CGameView::GetObjectManager() const
@@ -415,6 +425,11 @@
 	CFG_GET_SYS_VAL("view.zoom.min", Float, m->ViewZoomMin);
 	CFG_GET_SYS_VAL("view.zoom.max", Float, m->ViewZoomMax);
 	CFG_GET_SYS_VAL("view.zoom.default", Float, m->ViewZoomDefault);
+	CFG_GET_SYS_VAL("view.fov.min", Float, m->ViewFOVMin);
+	CFG_GET_SYS_VAL("view.fov.max", Float, m->ViewFOVMax);
+	CFG_GET_SYS_VAL("view.fov.default", Float, m->ViewFOVDefault);
+	CFG_GET_SYS_VAL("view.fov.speed", Float, m->ViewFOVSpeed);
+	CFG_GET_SYS_VAL("view.fov.speed.wheel", Float, m->ViewFOVSpeedWheel);
 
 	CFG_GET_SYS_VAL("joystick.camera.pan.x", Int, m->JoystickPanX);
 	CFG_GET_SYS_VAL("joystick.camera.pan.y", Int, m->JoystickPanY);
@@ -429,9 +444,11 @@
 	CFG_GET_SYS_VAL("view.zoom.smoothness", Float, m->Zoom.m_Smoothness);
 	CFG_GET_SYS_VAL("view.rotate.x.smoothness", Float, m->RotateX.m_Smoothness);
 	CFG_GET_SYS_VAL("view.rotate.y.smoothness", Float, m->RotateY.m_Smoothness);
+	CFG_GET_SYS_VAL("view.fov.smoothness", Float, m->FOV.m_Smoothness);
 
 	m->RotateX.SetValue(DEGTORAD(m->ViewRotateXDefault));
 	m->RotateY.SetValue(DEGTORAD(m->ViewRotateYDefault));
+	m->FOV.SetValue(DEGTORAD(m->ViewFOVDefault));
 
 	return 0;
 }
@@ -463,7 +480,7 @@
 		// from model rendering; as it is now, a shadow map is only rendered if its associated model is to be
 		// rendered.
 		// (See http://trac.wildfiregames.com/ticket/504)
-		m->CullCamera.SetProjection(defaultNear, defaultFar, defaultCullFOV);
+		m->CullCamera.SetProjection(defaultNear, defaultFar, GetCullFOV());
 		m->CullCamera.UpdateFrustum();
 	}
 	g_Renderer.SetSceneCamera(m->ViewCamera, m->CullCamera);
@@ -774,7 +791,10 @@
 	}
 
 	if (m->ConstrainCamera)
+	{
 		m->RotateX.ClampSmoothly(DEGTORAD(m->ViewRotateXMin), DEGTORAD(m->ViewRotateXMax));
+		m->FOV.ClampSmoothly(DEGTORAD(m->ViewFOVMin), DEGTORAD(m->ViewFOVMax));
+	}
 
 	ClampDistance(m, true);
 
@@ -889,7 +909,10 @@
 
 	m->RotateY.Wrap(-(float)M_PI, (float)M_PI);
 
+	m->FOV.Update(DeltaTime);
+
 	// Update the camera matrix
+	m->ViewCamera.SetProjection(defaultNear, defaultFar, m->FOV.GetValue());
 	SetupCameraMatrixSmooth(m, &m->ViewCamera.m_Orientation);
 	m->ViewCamera.UpdateFrustum();
 }
@@ -934,6 +957,7 @@
 	m->PosZ.SetValue(target.Z - delta.Z);
 	m->RotateX.SetValue(DEGTORAD(m->ViewRotateXDefault));
 	m->RotateY.SetValue(DEGTORAD(m->ViewRotateYDefault));
+	m->FOV.SetValue(DEGTORAD(m->ViewFOVDefault));
 
 	ClampDistance(m, false);
 
@@ -958,6 +982,7 @@
 	// Reset orientations to default
 	m->RotateX.SetValueSmoothly(DEGTORAD(m->ViewRotateXDefault));
 	m->RotateY.SetValueSmoothly(DEGTORAD(m->ViewRotateYDefault));
+	m->FOV.SetValue(DEGTORAD(m->ViewFOVDefault));
 }
 
 void CGameView::CameraFollow(entity_id_t entity, bool firstPerson)
@@ -971,6 +996,16 @@
 	return m->FollowEntity;
 }
 
+float CGameView::GetFOV() const
+{
+	return m->FOV.GetValue();
+}
+
+float CGameView::GetCullFOV() const
+{
+	return m->FOV.GetValue() + DEGTORAD(6.0f);	//add 6 degrees to the default FOV for use with the culling frustum;
+}
+
 InReaction game_view_handler(const SDL_Event_* ev)
 {
 	// put any events that must be processed even if inactive here
@@ -1032,6 +1067,16 @@
 			m->RotateY.AddSmoothly(-m->ViewRotateYSpeedWheel);
 			return IN_HANDLED;
 		}
+		else if (hotkey == "camera.fov.wheel.increase")
+		{
+			m->FOV.AddSmoothly(m->ViewFOVSpeedWheel);
+			return IN_HANDLED;
+		}
+		else if (hotkey == "camera.fov.wheel.decrease")
+		{
+			m->FOV.AddSmoothly(-m->ViewFOVSpeedWheel);
+			return IN_HANDLED;
+		}
 		else if (hotkey == "camera.reset")
 		{
 			ResetCameraAngleZoom();
Index: source/graphics/GameView.h
===================================================================
--- source/graphics/GameView.h	(revision 10184)
+++ source/graphics/GameView.h	(working copy)
@@ -38,7 +38,7 @@
 {
 	NONCOPYABLE(CGameView);
 public:
-	static const float defaultFOV, defaultCullFOV, defaultNear, defaultFar;
+	static const float defaultNear, defaultFar;
 
 private:
 	CGameViewImpl* m;
@@ -88,6 +88,9 @@
 	void CameraFollow(entity_id_t entity, bool firstPerson);
 	entity_id_t GetFollowedEntity();
 
+	float GetFOV() const;
+	float GetCullFOV() const;
+
 	CCamera *GetCamera();
 	CCinemaManager* GetCinema();
 
Index: source/ps/Util.cpp
===================================================================
--- source/ps/Util.cpp	(revision 10184)
+++ source/ps/Util.cpp	(working copy)
@@ -296,7 +296,7 @@
 		g_Renderer.Resize(tile_w, tile_h);
 		SViewPort vp = { 0, 0, tile_w, tile_h };
 		g_Game->GetView()->GetCamera()->SetViewPort(vp);
-		g_Game->GetView()->GetCamera()->SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV);
+		g_Game->GetView()->GetCamera()->SetProjection(CGameView::defaultNear, CGameView::defaultFar, g_Game->GetView()->GetFOV());
 	}
 
 	// Temporarily move everything onto the front buffer, so the user can
@@ -350,7 +350,7 @@
 		g_Renderer.Resize(g_xres, g_yres);
 		SViewPort vp = { 0, 0, g_xres, g_yres };
 		g_Game->GetView()->GetCamera()->SetViewPort(vp);
-		g_Game->GetView()->GetCamera()->SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV);
+		g_Game->GetView()->GetCamera()->SetProjection(CGameView::defaultNear, CGameView::defaultFar, g_Game->GetView()->GetFOV());
 
 		g_Game->GetView()->GetCamera()->SetProjectionTile(1, 0, 0);
 	}
Index: source/renderer/Renderer.cpp
===================================================================
--- source/renderer/Renderer.cpp	(revision 10184)
+++ source/renderer/Renderer.cpp	(working copy)
@@ -1220,7 +1220,7 @@
 	vp.m_X = 0;
 	vp.m_Y = 0;
 	m_ViewCamera.SetViewPort(vp);
-	m_ViewCamera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV*1.05f); // Slightly higher than view FOV
+	m_ViewCamera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, g_Game->GetView()->GetFOV()*1.05f); // Slightly higher than view FOV
 	CMatrix3D scaleMat;
 	scaleMat.SetScaling(m_Height/float(std::max(1, m_Width)), 1.0f, 1.0f);
 	m_ViewCamera.m_ProjMat = scaleMat * m_ViewCamera.m_ProjMat;
@@ -1304,7 +1304,7 @@
 	vp.m_X = 0;
 	vp.m_Y = 0;
 	m_ViewCamera.SetViewPort(vp);
-	m_ViewCamera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV*1.05f); // Slightly higher than view FOV
+	m_ViewCamera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, g_Game->GetView()->GetFOV()*1.05f); // Slightly higher than view FOV
 	CMatrix3D scaleMat;
 	scaleMat.SetScaling(m_Height/float(std::max(1, m_Width)), 1.0f, 1.0f);
 	m_ViewCamera.m_ProjMat = scaleMat * m_ViewCamera.m_ProjMat;
Index: source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp
===================================================================
--- source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp	(revision 10184)
+++ source/tools/atlas/GameInterface/Handlers/MiscHandlers.cpp	(working copy)
@@ -60,7 +60,7 @@
 		g_Renderer.Resize(w, h);
 		SViewPort vp = { 0, 0, w, h };
 		g_Game->GetView()->GetCamera()->SetViewPort(vp);
-		g_Game->GetView()->GetCamera()->SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV);
+		g_Game->GetView()->GetCamera()->SetProjection(CGameView::defaultNear, CGameView::defaultFar, g_Game->GetView()->GetFOV());
 	}
 
 	unsigned char* img = new unsigned char [w*h*3];
@@ -113,7 +113,7 @@
 		g_Renderer.Resize(g_xres, g_yres);
 		SViewPort vp = { 0, 0, g_xres, g_yres };
 		g_Game->GetView()->GetCamera()->SetViewPort(vp);
-		g_Game->GetView()->GetCamera()->SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV);
+		g_Game->GetView()->GetCamera()->SetProjection(CGameView::defaultNear, CGameView::defaultFar, g_Game->GetView()->GetFOV());
 	}
 
 }
Index: source/tools/atlas/GameInterface/View.cpp
===================================================================
--- source/tools/atlas/GameInterface/View.cpp	(revision 10184)
+++ source/tools/atlas/GameInterface/View.cpp	(working copy)
@@ -220,7 +220,7 @@
 	SViewPort vp = { 0, 0, g_xres, g_yres };
 	CCamera& camera = GetCamera();
 	camera.SetViewPort(vp);
-	camera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV);
+	camera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, g_Game->GetView()->GetFOV());
 	camera.UpdateFrustum();
 
 	// Update the pathfinder display if necessary
