diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index e5fba7f28f964529d118312327b529b350cff9cd..67b117657f0bb5a6c945e6078c7a082f43240b2d 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -184,6 +184,9 @@ LLAgentCamera::LLAgentCamera() :
 	clearGeneralKeys();
 	clearOrbitKeys();
 	clearPanKeys();
+
+	resetPanDiff();
+	resetOrbitDiff();
 }
 
 // Requires gSavedSettings to be initialized.
@@ -343,7 +346,8 @@ void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera)
 
 		mCameraFOVZoomFactor = 0.f;
 	}
-
+	resetPanDiff();
+	resetOrbitDiff();
 	mHUDTargetZoom = 1.f;
 }
 
@@ -822,6 +826,7 @@ void LLAgentCamera::cameraOrbitAround(const F32 radians)
 	}
 	else
 	{
+		mOrbitAroundRadians += radians;
 		mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f);
 		
 		cameraZoomIn(1.f);
@@ -853,12 +858,34 @@ void LLAgentCamera::cameraOrbitOver(const F32 angle)
 		LLVector3d left_axis;
 		left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis());
 		F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD);
+		mOrbitOverAngle += angle_from_up - new_angle;
 		mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis);
 
 		cameraZoomIn(1.f);
 	}
 }
 
+void LLAgentCamera::resetCameraOrbit()
+{
+	LLVector3 camera_offset_unit(mCameraFocusOffsetTarget);
+	camera_offset_unit.normalize();
+
+	LLVector3d left_axis;
+	left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis());
+	mCameraFocusOffsetTarget.rotVec(-mOrbitOverAngle, left_axis);
+	
+	mCameraFocusOffsetTarget.rotVec(-mOrbitAroundRadians, 0.f, 0.f, 1.f);
+
+	cameraZoomIn(1.f);
+	resetOrbitDiff();
+}
+
+void LLAgentCamera::resetOrbitDiff()
+{
+	mOrbitAroundRadians = 0;
+	mOrbitOverAngle = 0;
+}
+
 //-----------------------------------------------------------------------------
 // cameraZoomIn()
 //-----------------------------------------------------------------------------
@@ -997,6 +1024,8 @@ void LLAgentCamera::cameraPanIn(F32 meters)
 	LLVector3d at_axis;
 	at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis());
 
+	mPanFocusDiff += meters * at_axis;
+
 	mFocusTargetGlobal += meters * at_axis;
 	mFocusGlobal = mFocusTargetGlobal;
 	// don't enforce zoom constraints as this is the only way for users to get past them easily
@@ -1013,6 +1042,8 @@ void LLAgentCamera::cameraPanLeft(F32 meters)
 	LLVector3d left_axis;
 	left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis());
 
+	mPanFocusDiff += meters * left_axis;
+
 	mFocusTargetGlobal += meters * left_axis;
 	mFocusGlobal = mFocusTargetGlobal;
 
@@ -1033,6 +1064,8 @@ void LLAgentCamera::cameraPanUp(F32 meters)
 	LLVector3d up_axis;
 	up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis());
 
+	mPanFocusDiff += meters * up_axis;
+
 	mFocusTargetGlobal += meters * up_axis;
 	mFocusGlobal = mFocusTargetGlobal;
 
@@ -1045,6 +1078,26 @@ void LLAgentCamera::cameraPanUp(F32 meters)
 	mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();
 }
 
+void LLAgentCamera::resetCameraPan()
+{
+	mFocusTargetGlobal -= mPanFocusDiff;
+
+	mFocusGlobal = mFocusTargetGlobal;
+	mCameraSmoothingStop = true;
+
+	cameraZoomIn(1.f);
+	updateFocusOffset();
+
+	mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();
+
+	resetPanDiff();
+}
+
+void LLAgentCamera::resetPanDiff()
+{
+	mPanFocusDiff.clear();
+}
+
 //-----------------------------------------------------------------------------
 // updateLookAt()
 //-----------------------------------------------------------------------------
@@ -2330,6 +2383,9 @@ void LLAgentCamera::switchCameraPreset(ECameraPreset preset)
 
 	mCameraPreset = preset;
 
+	resetPanDiff();
+	resetOrbitDiff();
+
 	gSavedSettings.setU32("CameraPreset", mCameraPreset);
 }
 
diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h
index 8a922bf67860940e5359cb321a7128b34c066a46..0608507d1ad18bb909165b0689ae97176cf70cc5 100644
--- a/indra/newview/llagentcamera.h
+++ b/indra/newview/llagentcamera.h
@@ -262,7 +262,8 @@ class LLAgentCamera
 	void			cameraOrbitAround(const F32 radians);	// Rotate camera CCW radians about build focus point
 	void			cameraOrbitOver(const F32 radians);		// Rotate camera forward radians over build focus point
 	void			cameraOrbitIn(const F32 meters);		// Move camera in toward build focus point
-
+	void			resetCameraOrbit();
+	void			resetOrbitDiff();
 	//--------------------------------------------------------------------
 	// Zoom
 	//--------------------------------------------------------------------
@@ -279,8 +280,9 @@ class LLAgentCamera
 public:
 	void			cameraPanIn(const F32 meters);
 	void			cameraPanLeft(const F32 meters);
-	void			cameraPanUp(const F32 meters);
-	
+	void			cameraPanUp(const F32 meters);	
+	void			resetCameraPan();
+	void			resetPanDiff();
 	//--------------------------------------------------------------------
 	// View
 	//--------------------------------------------------------------------
@@ -367,6 +369,9 @@ class LLAgentCamera
 	F32				mOrbitInKey;
 	F32				mOrbitOutKey;
 
+	F32				mOrbitAroundRadians;
+	F32				mOrbitOverAngle;
+
 	//--------------------------------------------------------------------
 	// Pan
 	//--------------------------------------------------------------------
@@ -394,6 +399,8 @@ class LLAgentCamera
 	F32				mPanInKey;
 	F32				mPanOutKey;
 
+	LLVector3d		mPanFocusDiff;
+
 /**                    Keys
  **                                                                            **
  *******************************************************************************/
diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp
index 59e14e6cc01c902d2e256f0e324bd6d96afedd7a..eb4e4f4100ded3b65f6597d619da66a0fb0b758d 100644
--- a/indra/newview/lljoystickbutton.cpp
+++ b/indra/newview/lljoystickbutton.cpp
@@ -37,6 +37,7 @@
 #include "llui.h"
 #include "llagent.h"
 #include "llagentcamera.h"
+#include "llviewercamera.h"
 #include "llviewertexture.h"
 #include "llviewertexturelist.h"
 #include "llviewerwindow.h"
@@ -54,6 +55,8 @@ static LLDefaultChildRegistry::Register<LLJoystickCameraTrack> r5("joystick_trac
 const F32 NUDGE_TIME = 0.25f;		// in seconds
 const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
 
+const S32 CENTER_DOT_RADIUS = 7;
+
 //
 // Public Methods
 //
@@ -138,9 +141,25 @@ bool LLJoystick::pointInCircle(S32 x, S32 y) const
 	//center is x and y coordinates of center of joystick circle, and also its radius
 	int center = this->getLocalRect().getHeight()/2;
 	bool in_circle = (x - center) * (x - center) + (y - center) * (y - center) <= center * center;
+	
 	return in_circle;
 }
 
+bool LLJoystick::pointInCenterDot(S32 x, S32 y, S32 radius) const
+{
+	if (this->getLocalRect().getHeight() != this->getLocalRect().getWidth())
+	{
+		LL_WARNS() << "Joystick shape is not square" << LL_ENDL;
+		return true;
+	}
+
+	S32 center = this->getLocalRect().getHeight() / 2;
+
+	bool in_center_circle = (x - center) * (x - center) + (y - center) * (y - center) <= radius * radius;
+
+	return in_center_circle;
+}
+
 BOOL LLJoystick::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	//LL_INFOS() << "joystick mouse down " << x << ", " << y << LL_ENDL;
@@ -403,8 +422,11 @@ LLJoystickCameraRotate::LLJoystickCameraRotate(const LLJoystickCameraRotate::Par
 	mInLeft( FALSE ),
 	mInTop( FALSE ),
 	mInRight( FALSE ),
-	mInBottom( FALSE )
-{ }
+	mInBottom( FALSE ),
+	mInCenter( FALSE )
+{ 
+	mCenterImageName = "Cam_Rotate_Center";
+}
 
 
 void LLJoystickCameraRotate::updateSlop()
@@ -434,7 +456,16 @@ BOOL LLJoystickCameraRotate::handleMouseDown(S32 x, S32 y, MASK mask)
 	S32 dx = x - horiz_center;
 	S32 dy = y - vert_center;
 
-	if (dy > dx && dy > -dx)
+	if (pointInCenterDot(x, y, CENTER_DOT_RADIUS))
+	{
+		mInitialOffset.mX = 0;
+		mInitialOffset.mY = 0;
+		mInitialQuadrant = JQ_ORIGIN;
+		mInCenter = TRUE;
+
+		resetJoystickCamera();
+	}
+	else if (dy > dx && dy > -dx)
 	{
 		// top
 		mInitialOffset.mX = 0;
@@ -469,9 +500,20 @@ BOOL LLJoystickCameraRotate::handleMouseDown(S32 x, S32 y, MASK mask)
 BOOL LLJoystickCameraRotate::handleMouseUp(S32 x, S32 y, MASK mask)
 {
 	gAgent.setMovementLocked(FALSE);
+	mInCenter = FALSE;
 	return LLJoystick::handleMouseUp(x, y, mask);
 }
 
+BOOL LLJoystickCameraRotate::handleHover(S32 x, S32 y, MASK mask)
+{
+	if (!pointInCenterDot(x, y, CENTER_DOT_RADIUS))
+	{
+		mInCenter = FALSE;
+	}
+
+	return LLJoystick::handleHover(x, y, mask);
+}
+
 void LLJoystickCameraRotate::onHeldDown()
 {
 	updateSlop();
@@ -504,6 +546,11 @@ void LLJoystickCameraRotate::onHeldDown()
 	}
 }
 
+void LLJoystickCameraRotate::resetJoystickCamera()
+{
+	gAgentCamera.resetCameraOrbit();
+}
+
 F32 LLJoystickCameraRotate::getOrbitRate()
 {
 	F32 time = getElapsedHeldDownTime();
@@ -536,24 +583,31 @@ void LLJoystickCameraRotate::draw()
 	getImageUnselected()->draw( 0, 0 );
 	LLPointer<LLUIImage> image = getImageSelected();
 
-	if( mInTop )
+	if (mInCenter)
 	{
-		drawRotatedImage( getImageSelected(), 0 );
+		drawRotatedImage(LLUI::getUIImage(mCenterImageName), 0);
 	}
-
-	if( mInRight )
+	else
 	{
-		drawRotatedImage( getImageSelected(), 1 );
-	}
+		if (mInTop)
+		{
+			drawRotatedImage(getImageSelected(), 0);
+		}
 
-	if( mInBottom )
-	{
-		drawRotatedImage( getImageSelected(), 2 );
-	}
+		if (mInRight)
+		{
+			drawRotatedImage(getImageSelected(), 1);
+		}
 
-	if( mInLeft )
-	{
-		drawRotatedImage( getImageSelected(), 3 );
+		if (mInBottom)
+		{
+			drawRotatedImage(getImageSelected(), 2);
+		}
+
+		if (mInLeft)
+		{
+			drawRotatedImage(getImageSelected(), 3);
+		}
 	}
 }
 
@@ -613,7 +667,9 @@ LLJoystickCameraTrack::Params::Params()
 
 LLJoystickCameraTrack::LLJoystickCameraTrack(const LLJoystickCameraTrack::Params& p)
 :	LLJoystickCameraRotate(p)
-{}
+{
+	mCenterImageName = "Cam_Tracking_Center";
+}
 
 
 void LLJoystickCameraTrack::onHeldDown()
@@ -646,3 +702,8 @@ void LLJoystickCameraTrack::onHeldDown()
 		gAgentCamera.setPanDownKey(getOrbitRate());
 	}
 }
+
+void LLJoystickCameraTrack::resetJoystickCamera()
+{
+	gAgentCamera.resetCameraPan();
+}
diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h
index 4e6c774cadfa3c062709a7b318041ea4e6658961..3e29215f61b8b9de6952578574b5204d64f2cb2f 100644
--- a/indra/newview/lljoystickbutton.h
+++ b/indra/newview/lljoystickbutton.h
@@ -79,7 +79,8 @@ class LLJoystick
 	 * Image containing circle is square and this square has adherent points with joystick
 	 * circle. Make sure to change method according to shape other than square. 
 	 */
-	bool			pointInCircle(S32 x, S32 y) const;
+	bool	pointInCircle(S32 x, S32 y) const;
+	bool	pointInCenterDot(S32 x, S32 y, S32 radius) const;
 	
 	static std::string nameFromQuadrant(const EJoystickQuadrant quadrant);
 	static EJoystickQuadrant quadrantFromName(const std::string& name);
@@ -147,7 +148,9 @@ class LLJoystickCameraRotate
 
 	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
+	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);
 	virtual void	onHeldDown();
+	virtual void	resetJoystickCamera();
 	virtual void	draw();
 
 protected:
@@ -160,6 +163,9 @@ class LLJoystickCameraRotate
 	BOOL			mInTop;
 	BOOL			mInRight;
 	BOOL			mInBottom;
+	BOOL			mInCenter;
+
+	std::string		mCenterImageName;
 };
 
 
@@ -176,6 +182,7 @@ class LLJoystickCameraTrack
 
 	LLJoystickCameraTrack(const LLJoystickCameraTrack::Params&);
 	virtual void	onHeldDown();
+	virtual void	resetJoystickCamera();
 };
 
 #endif  // LL_LLJOYSTICKBUTTON_H
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png
new file mode 100644
index 0000000000000000000000000000000000000000..ffc3c85ea2a96cb82eeb487625eac03bb1c90aa2
Binary files /dev/null and b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png
new file mode 100644
index 0000000000000000000000000000000000000000..2812d614e6abc12f8f3ec1bcbad8f2f445e6f3e2
Binary files /dev/null and b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index b086f7dfa87c18fe8319f01178d76cb9f30c8351..2a4171f11bb166c84691864773dc095580353bfc 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -113,8 +113,10 @@ with the same filename but different name
 
   <texture name="Cam_Rotate_In" file_name="bottomtray/Cam_Rotate_In.png" preload="false" />
   <texture name="Cam_Rotate_Out" file_name="bottomtray/Cam_Rotate_Out.png" preload="false" />
+  <texture name="Cam_Rotate_Center" file_name="bottomtray/Cam_Rotate_Center.png" preload="false" />
   <texture name="Cam_Tracking_In" file_name="bottomtray/Cam_Tracking_In.png" preload="false" />
   <texture name="Cam_Tracking_Out" file_name="bottomtray/Cam_Tracking_Out.png" preload="false" />
+  <texture name="Cam_Tracking_Center" file_name="bottomtray/Cam_Tracking_Center.png" preload="false" />
 
   <texture name="Checkbox_Off_Disabled" file_name="widgets/Checkbox_Disabled.png" preload="true" />
   <texture name="Checkbox_On_Disabled" file_name="widgets/Checkbox_On_Disabled.png" preload="true" />