Index: graphics/Terrain.cpp
===================================================================
--- graphics/Terrain.cpp	(revision 8051)
+++ graphics/Terrain.cpp	(working copy)
@@ -94,7 +94,38 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// GetEdgeNearestPoint: get the nearest edge point close to the passed
+// returns true if the point was outside the map
+bool CTerrain::GetEdgeNearestPoint(float *x, float *z) const
+{
+	debug_assert(x != NULL && z != NULL && "NULL parameters have been passed");
 
+	// do nothing if the point is already on the map
+	if(IsOnMap(*x, *z))
+		return false;
+
+	float min_x = GetMinX();
+	float max_x = GetMaxX() - 1.0f / CELL_SIZE;
+	float min_z = GetMinZ();
+	float max_z = GetMaxZ() - 1.0f / CELL_SIZE;
+
+	// x constraint
+	if(*x < min_x)
+		*x = min_x;
+	else if(*x > max_x)
+		*x = max_x;
+
+	// z constraint
+	if(*z < min_z)
+		*z = min_z;
+	else if(*z > max_z)
+		*z = max_z;
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 CStr8 CTerrain::GetMovementClass(ssize_t i, ssize_t j) const
 {
 	CMiniPatch* tile = GetTile(i, j);
Index: graphics/Camera.h
===================================================================
--- graphics/Camera.h	(revision 8051)
+++ graphics/Camera.h	(working copy)
@@ -82,7 +82,7 @@
 		// Get the point on the plane at height h corresponding to pixel (px,py)
 		CVector3D GetWorldCoordinates(int px, int py, float h) const;
 		// Get the point on the terrain the camera is pointing towards
-		CVector3D GetFocus();
+		CVector3D GetFocus(bool *is_on_map = NULL);
 
 		// Build an orientation matrix from camera position, camera focus point, and up-vector
 		void LookAt(const CVector3D& camera, const CVector3D& orientation, const CVector3D& up);
Index: graphics/GameView.cpp
===================================================================
--- graphics/GameView.cpp	(revision 8051)
+++ graphics/GameView.cpp	(working copy)
@@ -60,6 +60,7 @@
 const float CGameView::defaultNear = 4.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
+const float CGameView::cameraPivotMargin = 20.0f;
 
 /**
  * A value with exponential decay towards the target value.
@@ -739,14 +740,56 @@
 			m->PosY.AddSmoothly(limit - nearPoint.Y);
 	}
 	*/
-
+	
 	m->RotateY.Wrap(-(float)M_PI, (float)M_PI);
 
+	// Ensure the ViewCamera focus is inside the map with the chosen margins
+	// if not so - apply margins to the camera
+	if (m->ConstrainCamera)
+	{
+		CCamera	targetCam = m->ViewCamera;
+		SetupCameraMatrix(m, &targetCam.m_Orientation);
+		CVector3D pivot = targetCam.m_Orientation.GetTranslation() + targetCam.m_Orientation.GetIn() * m->ViewZoomDefault;
+		ApplyCameraPivotMargins(pivot);
+	}
+
 	// Update the camera matrix
 	SetupCameraMatrix(m, &m->ViewCamera.m_Orientation);
 	m->ViewCamera.UpdateFrustum();
 }
 
+// ApplyCameraPivotMargins: constraint camera pivot
+// returns true if margins were applied to the pivot passed
+bool CGameView::ApplyCameraPivotMargins(CVector3D &pivot)
+{
+	bool		margins_applied = false;
+	CTerrain	*pter = m->Game->GetWorld()->GetTerrain();
+	debug_assert(pter != NULL && "NULL terrain pointer");
+	CVector3D	old_pivot(pivot);
+
+	float	min_x = pter->GetMinX() + cameraPivotMargin;
+	float	max_x = pter->GetMaxX() - cameraPivotMargin;
+	float	min_z = pter->GetMinZ() + cameraPivotMargin;
+	float	max_z = pter->GetMaxZ() - cameraPivotMargin;
+
+	     if(pivot.X < min_x) { pivot.X = min_x; margins_applied = true; }
+	else if(pivot.X > max_x) { pivot.X = max_x; margins_applied = true; }
+	     if(pivot.Z < min_z) { pivot.Z = min_z; margins_applied = true; }
+	else if(pivot.Z > max_z) { pivot.Z = max_z; margins_applied = true; }
+
+	if(margins_applied)
+	{
+		m->PosX.Add(pivot.X - old_pivot.X);
+		m->PosZ.Add(pivot.Z - old_pivot.Z);
+
+		// doesn't need because of the fixed Y camera position
+//		pivot.Y = pter->GetExactGroundLevel(pivot.X, pivot.Z);
+//		m->PosY.Add(pivot.Y - old_pivot.Y);
+	}
+
+	return margins_applied;
+}
+
 void CGameView::MoveCameraTarget(const CVector3D& target)
 {
 	// Maintain the same orientation and level of zoom, if we can
Index: graphics/Terrain.h
===================================================================
--- graphics/Terrain.h	(revision 8051)
+++ graphics/Terrain.h	(working copy)
@@ -66,11 +66,20 @@
 	// return number of patches along edge of the terrain
 	ssize_t GetPatchesPerSide() const { return m_MapSizePatches; }
 
+	float GetMinX() const { return 0.0f; }
+	float GetMinZ() const { return 0.0f; }
+	float GetMaxX() const { return (float)((m_MapSize-1) * CELL_SIZE); }
+	float GetMaxZ() const { return (float)((m_MapSize-1) * CELL_SIZE); }
+
 	bool IsOnMap(float x, float z) const
 	{
-		return ((x >= 0.0f) && (x < (float)((m_MapSize-1) * CELL_SIZE))
-		     && (z >= 0.0f) && (z < (float)((m_MapSize-1) * CELL_SIZE)));
+		return ((x >= GetMinX()) && (x < GetMaxX())
+		     && (z >= GetMinZ()) && (z < GetMaxZ()));
 	}
+    
+    // GetEdgeNearestPoint: get the nearest edge point close to the passed
+	// returns true if the point was outside the map
+	bool GetEdgeNearestPoint(float *x, float *z) const;
 
 	CStr8 GetMovementClass(ssize_t i, ssize_t j) const;
 
Index: graphics/GameView.h
===================================================================
--- graphics/GameView.h	(revision 8051)
+++ graphics/GameView.h	(working copy)
@@ -44,6 +44,7 @@
 	static const float defaultFOV, defaultCullFOV, defaultNear, defaultFar;
 
 private:
+	static const float cameraPivotMargin;
 	CGameViewImpl* m;
 
 	// Check whether lighting environment has changed and update vertex data if necessary
@@ -76,6 +77,10 @@
 	// *presentation*
 	void Update(float DeltaTime);
 
+	// ApplyCameraPivotMargins: constraint pivot
+	// returns true if margins were applied to the pivot passed
+	bool ApplyCameraPivotMargins(CVector3D &pivot);
+
 	// Render: Render the World
 	void Render();
 
Index: graphics/Camera.cpp
===================================================================
--- graphics/Camera.cpp	(revision 8051)
+++ graphics/Camera.cpp	(working copy)
@@ -285,7 +285,7 @@
 	return CVector3D(0.f, h, 0.f);
 }
 
-CVector3D CCamera::GetFocus()
+CVector3D CCamera::GetFocus(bool *is_on_map)
 {
 	// Basically the same as GetWorldCoordinates
 
@@ -298,11 +298,15 @@
 	dir = m_Orientation.GetIn();
 
 	if (tracer.RayIntersect(origin, dir, x, z, currentTarget))
+	{
+		if(is_on_map != NULL) *is_on_map = true;
 		return (currentTarget);
+	}
 
 	// Off the edge of the world?
 	// Work out where it /would/ hit, if the map were extended out to infinity with average height.
 
+	if(is_on_map != NULL) *is_on_map = false;
 	return (origin + dir * ((50.0f - origin.Y) / dir.Y));
 }
 
