From c68f662c9aa036beb99f9230db1e7846b0f6330e Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 9 Feb 2017 01:24:13 +0100 Subject: [PATCH] Predict player movement when preloading cells to better handle moving at high speed --- apps/openmw/mwworld/scene.cpp | 34 +++++++++++++++++++++------------- apps/openmw/mwworld/scene.hpp | 10 ++++++---- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index c194dcca4..30d021bfd 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -202,9 +202,9 @@ namespace MWWorld if (mPreloadEnabled) { mPreloadTimer += duration; - if (mPreloadTimer > 0.25f) + if (mPreloadTimer > 0.1f) { - preloadCells(); + preloadCells(0.1f); mPreloadTimer = 0.f; } } @@ -461,6 +461,8 @@ namespace MWWorld mechMgr->watchActor(player); MWBase::Environment::get().getWorld()->adjustSky(); + + mLastPlayerPos = pos.asVec3(); } Scene::Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics) @@ -648,17 +650,24 @@ namespace MWWorld return Ptr(); } - void Scene::preloadCells() + void Scene::preloadCells(float dt) { + const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + osg::Vec3f playerPos = player.getRefData().getPosition().asVec3(); + osg::Vec3f moved = playerPos - mLastPlayerPos; + osg::Vec3f predictedPos = playerPos + moved / dt; + + mLastPlayerPos = playerPos; + if (mPreloadDoors) - preloadTeleportDoorDestinations(); + preloadTeleportDoorDestinations(playerPos, predictedPos); if (mPreloadExteriorGrid) - preloadExteriorGrid(); + preloadExteriorGrid(playerPos, predictedPos); if (mPreloadFastTravel) - preloadFastTravelDestinations(); + preloadFastTravelDestinations(playerPos, predictedPos); } - void Scene::preloadTeleportDoorDestinations() + void Scene::preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos) { std::vector teleportDoors; for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); @@ -676,11 +685,11 @@ namespace MWWorld } } - const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); 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(); + float sqrDistToPlayer = (playerPos - door.getRefData().getPosition().asVec3()).length2(); + sqrDistToPlayer = std::min(sqrDistToPlayer, (predictedPos - door.getRefData().getPosition().asVec3()).length2()); if (sqrDistToPlayer < mPreloadDistance*mPreloadDistance) { @@ -703,15 +712,13 @@ namespace MWWorld } } - void Scene::preloadExteriorGrid() + void Scene::preloadExteriorGrid(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos) { if (!MWBase::Environment::get().getWorld()->isCellExterior()) return; int halfGridSizePlusOne = mHalfGridSize + 1; - const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - osg::Vec3f playerPos = player.getRefData().getPosition().asVec3(); int cellX,cellY; getGridCenter(cellX,cellY); @@ -730,6 +737,7 @@ namespace MWWorld MWBase::Environment::get().getWorld()->indexToPosition(cellX+dx, cellY+dy, thisCellCenterX, thisCellCenterY, true); float dist = std::max(std::abs(thisCellCenterX - playerPos.x()), std::abs(thisCellCenterY - playerPos.y())); + dist = std::min(dist,std::max(std::abs(thisCellCenterX - predictedPos.x()), std::abs(thisCellCenterY - predictedPos.y()))); float loadDist = 8192/2 + 8192 - mCellLoadingThreshold + mPreloadDistance; if (dist < loadDist) @@ -789,7 +797,7 @@ namespace MWWorld std::vector mList; }; - void Scene::preloadFastTravelDestinations() + void Scene::preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& /*predictedPos*/) // ignore predictedPos here since opening dialogue with travel service takes extra time { const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3()); diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 33886eed4..970a4cad3 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -68,6 +68,8 @@ namespace MWWorld bool mPreloadDoors; bool mPreloadFastTravel; + osg::Vec3f mLastPlayerPos; + void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener); // Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center @@ -75,10 +77,10 @@ namespace MWWorld void getGridCenter(int& cellX, int& cellY); - void preloadCells(); - void preloadTeleportDoorDestinations(); - void preloadExteriorGrid(); - void preloadFastTravelDestinations(); + void preloadCells(float dt); + void preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos); + void preloadExteriorGrid(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos); + void preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos); void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false);