From 023c87b21595353b98edce6176b38f8dca52f288 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 7 Feb 2016 05:13:46 -0800 Subject: [PATCH] Preload cell when the player goes near a teleport door. It works! --- apps/openmw/mwworld/cellpreloader.cpp | 2 + apps/openmw/mwworld/scene.cpp | 58 +++++++++++++++++++++++++++ apps/openmw/mwworld/scene.hpp | 3 ++ 3 files changed, 63 insertions(+) diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp index 16bf920bb..f1366a8b2 100644 --- a/apps/openmw/mwworld/cellpreloader.cpp +++ b/apps/openmw/mwworld/cellpreloader.cpp @@ -66,6 +66,7 @@ namespace MWWorld /// Preload work to be called from the worker thread. virtual void doWork() { + osg::Timer preloadTimer; for (MeshList::const_iterator it = mMeshes.begin(); it != mMeshes.end(); ++it) { try @@ -81,6 +82,7 @@ namespace MWWorld // error will be shown when visiting the cell } } + std::cout << "preloaded " << mPreloadedNodes.size() << " nodes in " << preloadTimer.time_m() << std::endl; } private: diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 70a461b5b..912a39e7c 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -193,6 +193,13 @@ namespace MWWorld void Scene::update (float duration, bool paused) { + mPreloadTimer += duration; + if (mPreloadTimer > 1.f) + { + preloadCells(); + mPreloadTimer = 0.f; + } + mRendering.update (duration, paused); } @@ -440,6 +447,7 @@ namespace MWWorld Scene::Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics) : mCurrentCell (0), mCellChanged (false), mPhysics(physics), mRendering(rendering) + , mPreloadTimer(0.f) { mPreloader.reset(new CellPreloader(rendering.getResourceSystem(), physics->getShapeManager())); } @@ -603,4 +611,54 @@ namespace MWWorld return Ptr(); } + + void Scene::preloadCells() + { + std::vector teleportDoors; + for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); + iter!=mActiveCells.end(); ++iter) + { + const MWWorld::CellStore* cellStore = *iter; + typedef MWWorld::CellRefList::List DoorList; + const DoorList &doors = cellStore->getReadOnlyDoors().mList; + for (DoorList::const_iterator doorIt = doors.begin(); doorIt != doors.end(); ++doorIt) + { + if (!doorIt->mRef.getTeleport()) { + continue; + } + teleportDoors.push_back(MWWorld::ConstPtr(&*doorIt, cellStore)); + } + } + + const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + const float preloadDist = 500.f; + + for (std::vector::iterator it = teleportDoors.begin(); it != teleportDoors.end(); ++it) + { + const MWWorld::ConstPtr& door = *it; + float sqrDistToPlayer = (player.getRefData().getPosition().asVec3() - door.getRefData().getPosition().asVec3()).length2(); + + if (sqrDistToPlayer < preloadDist*preloadDist) + { + MWWorld::CellStore* targetCell = NULL; + try + { + if (!door.getCellRef().getDestCell().empty()) + targetCell = MWBase::Environment::get().getWorld()->getInterior(door.getCellRef().getDestCell()); + else + { + int x,y; + MWBase::Environment::get().getWorld()->positionToIndex (door.getCellRef().getDoorDest().pos[0], door.getCellRef().getDoorDest().pos[1], x, y); + targetCell = MWBase::Environment::get().getWorld()->getExterior(x, y); + } + } + catch (std::exception& e) + { + // ignore error for now, would spam the log too much + } + if (targetCell) + mPreloader->preload(targetCell, mRendering.getReferenceTime()); + } + } + } } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index b428d0ddd..4ac0d0666 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -58,6 +58,7 @@ namespace MWWorld MWPhysics::PhysicsSystem *mPhysics; MWRender::RenderingManager& mRendering; std::auto_ptr mPreloader; + float mPreloadTimer; void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener); @@ -112,6 +113,8 @@ namespace MWWorld bool isCellActive(const CellStore &cell); Ptr searchPtrViaActorId (int actorId); + + void preloadCells(); }; }