From fc5cd703bb189d774a1d843d44e508772389a1c7 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Fri, 30 Mar 2012 16:34:36 +0200
Subject: [PATCH] maps are now rendered with correct rotation, however for
 interiors the arrow is wrong

---
 apps/openmw/mwrender/localmap.cpp         | 37 +++++++++++++++++------
 apps/openmw/mwrender/localmap.hpp         |  5 +--
 apps/openmw/mwrender/renderingmanager.cpp |  2 +-
 3 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp
index 803899110c..063b253019 100644
--- a/apps/openmw/mwrender/localmap.cpp
+++ b/apps/openmw/mwrender/localmap.cpp
@@ -17,7 +17,8 @@ LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWWorld::Environment* en
     mRendering = rend;
     mEnvironment = env;
 
-    mCameraRotNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
+    mCameraPosNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
+    mCameraRotNode = mCameraPosNode->createChildSceneNode();
     mCameraNode = mCameraRotNode->createChildSceneNode();
 
     mCellCamera = mRendering->getScene()->createCamera("CellCamera");
@@ -101,6 +102,8 @@ void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell)
     int x = cell->cell->data.gridX;
     int y = cell->cell->data.gridY;
 
+    mCameraPosNode->setPosition(Vector3(0,0,0));
+
     render((x+0.5)*sSize, (-y-0.5)*sSize, -10000, 10000, sSize, sSize, name);
 }
 
@@ -110,17 +113,26 @@ void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell,
     mInterior = true;
     mBounds = bounds;
 
-    Vector2 z(bounds.getMaximum().y, bounds.getMinimum().y);
-    Vector2 min(bounds.getMinimum().x, bounds.getMinimum().z);
-    Vector2 max(bounds.getMaximum().x, bounds.getMaximum().z);
+    Vector2 z(mBounds.getMaximum().y, mBounds.getMinimum().y);
 
     const Vector2& north = mEnvironment->mWorld->getNorthVector(cell);
-    Radian angle(std::atan2(north.x, north.y));
+    Radian angle(std::atan2(-north.x, -north.y));
     mCameraRotNode->setOrientation(Quaternion(Math::Cos(angle/2.f), 0, Math::Sin(angle/2.f), 0));
 
-    Vector2 length = max-min;
+    mBounds.merge(mCameraRotNode->convertWorldToLocalPosition(bounds.getCorner(AxisAlignedBox::NEAR_LEFT_BOTTOM)));
+    mBounds.merge(mCameraRotNode->convertWorldToLocalPosition(bounds.getCorner(AxisAlignedBox::FAR_LEFT_BOTTOM)));
+    mBounds.merge(mCameraRotNode->convertWorldToLocalPosition(bounds.getCorner(AxisAlignedBox::NEAR_RIGHT_BOTTOM)));
+    mBounds.merge(mCameraRotNode->convertWorldToLocalPosition(bounds.getCorner(AxisAlignedBox::FAR_RIGHT_BOTTOM)));
+
     Vector2 center(bounds.getCenter().x, bounds.getCenter().z);
 
+    Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
+    Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().z);
+
+    Vector2 length = max-min;
+
+    mCameraPosNode->setPosition(Vector3(center.x, 0, center.y));
+
     // divide into segments
     const int segsX = std::ceil( length.x / sSize );
     const int segsY = std::ceil( length.y / sSize );
@@ -134,7 +146,7 @@ void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell,
             Vector2 start = min + Vector2(sSize*x,sSize*y);
             Vector2 newcenter = start + 4096;
 
-            render(newcenter.x, newcenter.y, z.y, z.x, sSize, sSize,
+            render(newcenter.x - center.x, newcenter.y - center.y, z.y, z.x, sSize, sSize,
                 cell->cell->name + "_" + coordStr(x,y));
         }
     }
@@ -227,7 +239,7 @@ void LocalMap::render(const float x, const float y,
     mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, fStart, fEnd);
 }
 
-void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3& direction)
+void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation)
 {
     if (sFogOfWarSkip != 0)
     {
@@ -240,9 +252,13 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3&
     int x,y;
     Vector3 _pos(position.x, 0, position.z);
     _pos = mCameraRotNode->convertWorldToLocalPosition(_pos);
+
+    //if (mInterior)
+       /// \todo
+
     Vector2 pos(_pos.x, _pos.z);
 
-    Vector3 playerdirection = mCameraRotNode->convertWorldToLocalPosition(direction);
+    Vector3 playerdirection = -mCameraRotNode->convertWorldToLocalOrientation(orientation).zAxis();
 
     if (!mInterior)
     {
@@ -279,6 +295,9 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3&
 
         texName = mInteriorName + "_" + coordStr(x,y);
     }
+
+    //std::cout << " x,y " << x << ", " << y << " u,v " << u << "," << v << std::endl;
+
     mEnvironment->mWindowManager->setPlayerPos(u, v);
     mEnvironment->mWindowManager->setPlayerDir(playerdirection.x, -playerdirection.z);
 
diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp
index 42603885a0..cb294a6568 100644
--- a/apps/openmw/mwrender/localmap.hpp
+++ b/apps/openmw/mwrender/localmap.hpp
@@ -44,9 +44,9 @@ namespace MWRender
          * @remarks This is used to draw a "fog of war" effect
          * to hide areas on the map the player has not discovered yet.
          * @param position (OGRE coordinates)
-         * @param view direction (OGRE coordinates)
+         * @param camera orientation (OGRE coordinates)
          */
-        void updatePlayer (const Ogre::Vector3& position, const Ogre::Vector3& direction);
+        void updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation);
 
         /**
          * Save the fog of war for the current cell to disk.
@@ -74,6 +74,7 @@ namespace MWRender
 
         Ogre::Camera* mCellCamera;
         Ogre::SceneNode* mCameraNode;
+        Ogre::SceneNode* mCameraPosNode;
         Ogre::SceneNode* mCameraRotNode;
 
         void render(const float x, const float y,
diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp
index c947b67f5c..5df93ab32e 100644
--- a/apps/openmw/mwrender/renderingmanager.cpp
+++ b/apps/openmw/mwrender/renderingmanager.cpp
@@ -171,7 +171,7 @@ void RenderingManager::update (float duration){
     
     mRendering.update(duration);
 
-    mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealDirection() );
+    mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealOrientation() );
 
     checkUnderwater();
 }