From 42e989150434ab6c6ad870fca40e55b96a6c9fe4 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Tue, 14 Mar 2017 20:27:55 +0100
Subject: [PATCH] Fix issues caused by loading multiple views into the same
 terrain View

---
 apps/openmw/mwworld/cellpreloader.cpp | 34 +++++++++++++++++----------
 apps/openmw/mwworld/cellpreloader.hpp |  2 +-
 2 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp
index 649d17334..9e9c85320 100644
--- a/apps/openmw/mwworld/cellpreloader.cpp
+++ b/apps/openmw/mwworld/cellpreloader.cpp
@@ -198,9 +198,7 @@ namespace MWWorld
         , mMaxCacheSize(0)
         , mPreloadInstances(true)
         , mLastResourceCacheUpdate(0.0)
-        , mTerrainView(NULL)
     {
-        mTerrainView = mTerrain->createView();
     }
 
     CellPreloader::~CellPreloader()
@@ -210,7 +208,6 @@ namespace MWWorld
             mTerrainPreloadItem->waitTillDone();
             mTerrainPreloadItem = NULL;
         }
-        mTerrainView = NULL;
 
         if (mUpdateCacheItem)
         {
@@ -372,8 +369,8 @@ namespace MWWorld
     class TerrainPreloadItem : public SceneUtil::WorkItem
     {
     public:
-        TerrainPreloadItem(Terrain::View* view, Terrain::World* world, const std::vector<osg::Vec3f>& preloadPositions)
-            : mView(view)
+        TerrainPreloadItem(const std::vector<osg::ref_ptr<Terrain::View> >& views, Terrain::World* world, const std::vector<osg::Vec3f>& preloadPositions)
+            : mTerrainViews(views)
             , mWorld(world)
             , mPreloadPositions(preloadPositions)
         {
@@ -381,32 +378,43 @@ namespace MWWorld
 
         virtual void doWork()
         {
-            for (std::vector<osg::Vec3f>::const_iterator it = mPreloadPositions.begin(); it != mPreloadPositions.end(); ++it)
-                mWorld->preload(mView, *it);
-
-            mView->reset(0);
+            for (unsigned int i=0; i<mTerrainViews.size() && i<mPreloadPositions.size(); ++i)
+            {
+                mWorld->preload(mTerrainViews[i], mPreloadPositions[i]);
+                mTerrainViews[i]->reset(0);
+            }
         }
 
     private:
-        Terrain::View* mView;
+        std::vector<osg::ref_ptr<Terrain::View> > mTerrainViews;
         Terrain::World* mWorld;
         std::vector<osg::Vec3f> mPreloadPositions;
     };
 
     void CellPreloader::setTerrainPreloadPositions(const std::vector<osg::Vec3f> &positions)
     {
-        if (!mTerrainView)
-            return;
         if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
             return;
         else if (positions == mTerrainPreloadPositions)
             return;
         else
         {
+            if (mTerrainViews.size() > positions.size())
+            {
+                for (unsigned int i=positions.size(); i<mTerrainViews.size(); ++i)
+                    mUnrefQueue->push(mTerrainViews[i]);
+                mTerrainViews.resize(positions.size());
+            }
+            else if (mTerrainViews.size() < positions.size())
+            {
+                for (unsigned int i=mTerrainViews.size(); i<positions.size(); ++i)
+                    mTerrainViews.push_back(mTerrain->createView());
+            }
+
             // TODO: provide some way of giving the preloaded view to the main thread when we enter the cell
             // right now, we just use it to make sure the resources are preloaded
             mTerrainPreloadPositions = positions;
-            mTerrainPreloadItem = new TerrainPreloadItem(mTerrainView, mTerrain, positions);
+            mTerrainPreloadItem = new TerrainPreloadItem(mTerrainViews, mTerrain, positions);
             mWorkQueue->addWorkItem(mTerrainPreloadItem);
         }
     }
diff --git a/apps/openmw/mwworld/cellpreloader.hpp b/apps/openmw/mwworld/cellpreloader.hpp
index e188f21ee..df878a55d 100644
--- a/apps/openmw/mwworld/cellpreloader.hpp
+++ b/apps/openmw/mwworld/cellpreloader.hpp
@@ -103,7 +103,7 @@ namespace MWWorld
         // Cells that are currently being preloaded, or have already finished preloading
         PreloadMap mPreloadCells;
 
-        osg::ref_ptr<Terrain::View> mTerrainView;
+        std::vector<osg::ref_ptr<Terrain::View> > mTerrainViews;
         std::vector<osg::Vec3f> mTerrainPreloadPositions;
         osg::ref_ptr<SceneUtil::WorkItem> mTerrainPreloadItem;
         osg::ref_ptr<SceneUtil::WorkItem> mUpdateCacheItem;