From 447c3b94898178e04e4b73af5d79838c72cf7ddf Mon Sep 17 00:00:00 2001
From: Petr Mikheev <ptmikheev@gmail.com>
Date: Sat, 13 Mar 2021 21:51:48 +0100
Subject: [PATCH] Fix 5846

---
 apps/openmw/mwmechanics/character.cpp | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp
index 172ddb25c..99f8632f3 100644
--- a/apps/openmw/mwmechanics/character.cpp
+++ b/apps/openmw/mwmechanics/character.cpp
@@ -2920,8 +2920,8 @@ void CharacterController::updateHeadTracking(float duration)
     if (!head)
         return;
 
-    float zAngleRadians = 0.f;
-    float xAngleRadians = 0.f;
+    double zAngleRadians = 0.f;
+    double xAngleRadians = 0.f;
 
     if (!mHeadTrackTarget.isEmpty())
     {
@@ -2954,15 +2954,16 @@ void CharacterController::updateHeadTracking(float duration)
         const osg::Vec3f actorDirection = mPtr.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0);
 
         zAngleRadians = std::atan2(actorDirection.x(), actorDirection.y()) - std::atan2(direction.x(), direction.y());
+        zAngleRadians = Misc::normalizeAngle(zAngleRadians - mAnimation->getHeadYaw()) + mAnimation->getHeadYaw();
+        zAngleRadians *= (1 - direction.z() * direction.z());
         xAngleRadians = std::asin(direction.z());
     }
 
     const double xLimit = osg::DegreesToRadians(40.0);
     const double zLimit = osg::DegreesToRadians(30.0);
     double zLimitOffset = mAnimation->getUpperBodyYawRadians();
-    xAngleRadians = osg::clampBetween(Misc::normalizeAngle(xAngleRadians), -xLimit, xLimit);
-    zAngleRadians = osg::clampBetween(Misc::normalizeAngle(zAngleRadians),
-                                      -zLimit + zLimitOffset, zLimit + zLimitOffset);
+    xAngleRadians = osg::clampBetween(xAngleRadians, -xLimit, xLimit);
+    zAngleRadians = osg::clampBetween(zAngleRadians, -zLimit + zLimitOffset, zLimit + zLimitOffset);
 
     float factor = duration*5;
     factor = std::min(factor, 1.f);