1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-03 22:45:35 +00:00

Predict player movement when preloading cells to better handle moving at high speed

This commit is contained in:
scrawl 2017-02-09 01:24:13 +01:00
parent a46593fa74
commit c68f662c9a
2 changed files with 27 additions and 17 deletions

View file

@ -202,9 +202,9 @@ namespace MWWorld
if (mPreloadEnabled) if (mPreloadEnabled)
{ {
mPreloadTimer += duration; mPreloadTimer += duration;
if (mPreloadTimer > 0.25f) if (mPreloadTimer > 0.1f)
{ {
preloadCells(); preloadCells(0.1f);
mPreloadTimer = 0.f; mPreloadTimer = 0.f;
} }
} }
@ -461,6 +461,8 @@ namespace MWWorld
mechMgr->watchActor(player); mechMgr->watchActor(player);
MWBase::Environment::get().getWorld()->adjustSky(); MWBase::Environment::get().getWorld()->adjustSky();
mLastPlayerPos = pos.asVec3();
} }
Scene::Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics) Scene::Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics)
@ -648,17 +650,24 @@ namespace MWWorld
return Ptr(); 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) if (mPreloadDoors)
preloadTeleportDoorDestinations(); preloadTeleportDoorDestinations(playerPos, predictedPos);
if (mPreloadExteriorGrid) if (mPreloadExteriorGrid)
preloadExteriorGrid(); preloadExteriorGrid(playerPos, predictedPos);
if (mPreloadFastTravel) if (mPreloadFastTravel)
preloadFastTravelDestinations(); preloadFastTravelDestinations(playerPos, predictedPos);
} }
void Scene::preloadTeleportDoorDestinations() void Scene::preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos)
{ {
std::vector<MWWorld::ConstPtr> teleportDoors; std::vector<MWWorld::ConstPtr> teleportDoors;
for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); 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<MWWorld::ConstPtr>::iterator it = teleportDoors.begin(); it != teleportDoors.end(); ++it) for (std::vector<MWWorld::ConstPtr>::iterator it = teleportDoors.begin(); it != teleportDoors.end(); ++it)
{ {
const MWWorld::ConstPtr& door = *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) 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()) if (!MWBase::Environment::get().getWorld()->isCellExterior())
return; return;
int halfGridSizePlusOne = mHalfGridSize + 1; int halfGridSizePlusOne = mHalfGridSize + 1;
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
int cellX,cellY; int cellX,cellY;
getGridCenter(cellX,cellY); getGridCenter(cellX,cellY);
@ -730,6 +737,7 @@ namespace MWWorld
MWBase::Environment::get().getWorld()->indexToPosition(cellX+dx, cellY+dy, thisCellCenterX, thisCellCenterY, true); 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())); 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; float loadDist = 8192/2 + 8192 - mCellLoadingThreshold + mPreloadDistance;
if (dist < loadDist) if (dist < loadDist)
@ -789,7 +797,7 @@ namespace MWWorld
std::vector<ESM::Transport::Dest> mList; std::vector<ESM::Transport::Dest> 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(); const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3()); ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3());

View file

@ -68,6 +68,8 @@ namespace MWWorld
bool mPreloadDoors; bool mPreloadDoors;
bool mPreloadFastTravel; bool mPreloadFastTravel;
osg::Vec3f mLastPlayerPos;
void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener); 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 // 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 getGridCenter(int& cellX, int& cellY);
void preloadCells(); void preloadCells(float dt);
void preloadTeleportDoorDestinations(); void preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
void preloadExteriorGrid(); void preloadExteriorGrid(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
void preloadFastTravelDestinations(); void preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false); void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false);