From a2d87d5f5b55939735a11e21bf2b0831f251a183 Mon Sep 17 00:00:00 2001
From: greye <greye@null.net>
Date: Thu, 9 Aug 2012 10:24:18 +0400
Subject: [PATCH] added camera flip control, fixed input rotation axis

---
 apps/openmw/mwinput/mouselookevent.cpp |  2 +-
 apps/openmw/mwrender/player.cpp        | 32 +++++++++++++++++++++++---
 apps/openmw/mwrender/player.hpp        |  2 ++
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/apps/openmw/mwinput/mouselookevent.cpp b/apps/openmw/mwinput/mouselookevent.cpp
index 4138c481c..f318ce666 100644
--- a/apps/openmw/mwinput/mouselookevent.cpp
+++ b/apps/openmw/mwinput/mouselookevent.cpp
@@ -24,5 +24,5 @@ void MouseLookEvent::event(Type type, int index, const void *p)
     float y = arg->state.Y.rel * sensY;
 
     MWBase::World *world = MWBase::Environment::get().getWorld();
-    world->rotateObject(world->getPlayer().getPlayer(), -y, 0.f, -x, true);
+    world->rotateObject(world->getPlayer().getPlayer(), -y, 0.f, x, true);
 }
diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp
index a71d9da68..0d101a839 100644
--- a/apps/openmw/mwrender/player.cpp
+++ b/apps/openmw/mwrender/player.cpp
@@ -24,14 +24,16 @@ namespace MWRender
         // we are only interested in X and Y rotation
 
         // Rotate around X axis
-        Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X);
+        Ogre::Quaternion xr(Ogre::Degree(rot.x), Ogre::Vector3::UNIT_X);
 
         // Rotate around Y axis
-        Ogre::Quaternion yr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Y);
+        Ogre::Quaternion yr(Ogre::Degree(-rot.z), Ogre::Vector3::UNIT_Y);
 
         pitchNode->setOrientation(xr);
         yawNode->setOrientation(yr);
 
+        controlFlip();
+
         return !mVanityModeEnabled;
     }
 
@@ -51,8 +53,32 @@ namespace MWRender
         Ogre::SceneNode *yawNode = pitchNode->getParentSceneNode();
 
         pitchNode->pitch(Ogre::Degree(rot.x));
-        yawNode->yaw(Ogre::Degree(rot.z));
+        yawNode->yaw(Ogre::Degree(-rot.z));
+
+        controlFlip();
 
         return !mVanityModeEnabled;
     }
+
+    void Player::controlFlip()
+    {
+        Ogre::SceneNode *pitchNode = mCamera->getParentSceneNode();
+        Ogre::Quaternion orient = pitchNode->getOrientation();
+
+        float pitchAngle =
+            (2 * Ogre::Degree(Ogre::Math::ACos(orient.w)).valueDegrees());
+
+        // Limit the pitch between -90 degress and +90 degrees, Quake3-style.
+        if (pitchAngle > 90.0f)
+        {
+            Ogre::Real sqrt = Ogre::Math::Sqrt(0.5f);
+            if (orient.x > 0) {
+                // Set orientation to 90 degrees on X-axis.
+                pitchNode->setOrientation(Ogre::Quaternion(sqrt, sqrt, 0, 0));
+            } else if (orient.x < 0) {
+                // Sets orientation to -90 degrees on X-axis.
+                pitchNode->setOrientation(Ogre::Quaternion(sqrt, -sqrt, 0, 0));
+            }
+        }
+    }
 }
diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp
index a145997a9..35333c9f1 100644
--- a/apps/openmw/mwrender/player.hpp
+++ b/apps/openmw/mwrender/player.hpp
@@ -27,6 +27,8 @@ namespace MWRender
         bool mFirstPersonView;
         bool mVanityModeEnabled;
 
+        void controlFlip();
+
     public:
 
         Player (Ogre::Camera *camera, Ogre::SceneNode* mNode);