1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 19:15:41 +00:00

loadingscreen

Signed-off-by: Bret Curtis <psi29a@gmail.com>
This commit is contained in:
bzzt lost a hitlab login 2020-05-07 13:37:00 +00:00 committed by Bret Curtis
parent da92ad329b
commit ffbed7ee38
8 changed files with 88 additions and 12 deletions

View file

@ -174,6 +174,8 @@ namespace MWWorld
public: public:
TerrainPreloadItem(const std::vector<osg::ref_ptr<Terrain::View> >& views, Terrain::World* world, const std::vector<CellPreloader::PositionCellGrid>& preloadPositions) TerrainPreloadItem(const std::vector<osg::ref_ptr<Terrain::View> >& views, Terrain::World* world, const std::vector<CellPreloader::PositionCellGrid>& preloadPositions)
: mAbort(false) : mAbort(false)
, mProgress(views.size())
, mProgressRange(0)
, mTerrainViews(views) , mTerrainViews(views)
, mWorld(world) , mWorld(world)
, mPreloadPositions(preloadPositions) , mPreloadPositions(preloadPositions)
@ -191,7 +193,7 @@ namespace MWWorld
for (unsigned int i=0; i<mTerrainViews.size() && i<mPreloadPositions.size() && !mAbort; ++i) for (unsigned int i=0; i<mTerrainViews.size() && i<mPreloadPositions.size() && !mAbort; ++i)
{ {
mTerrainViews[i]->reset(); mTerrainViews[i]->reset();
mWorld->preload(mTerrainViews[i], mPreloadPositions[i].first, mPreloadPositions[i].second, mAbort); mWorld->preload(mTerrainViews[i], mPreloadPositions[i].first, mPreloadPositions[i].second, mAbort, mProgress[i], mProgressRange);
} }
} }
@ -200,8 +202,13 @@ namespace MWWorld
mAbort = true; mAbort = true;
} }
int getProgress() const { return !mProgress.empty() ? mProgress[0].load() : 0; }
int getProgressRange() const { return !mProgress.empty() && mProgress[0].load() ? mProgressRange : 0; }
private: private:
std::atomic<bool> mAbort; std::atomic<bool> mAbort;
std::vector<std::atomic<int>> mProgress;
int mProgressRange;
std::vector<osg::ref_ptr<Terrain::View> > mTerrainViews; std::vector<osg::ref_ptr<Terrain::View> > mTerrainViews;
Terrain::World* mWorld; Terrain::World* mWorld;
std::vector<CellPreloader::PositionCellGrid> mPreloadPositions; std::vector<CellPreloader::PositionCellGrid> mPreloadPositions;
@ -328,9 +335,6 @@ namespace MWWorld
} }
mPreloadCells.erase(found); mPreloadCells.erase(found);
if (cell->isExterior() && mTerrainPreloadItem && mTerrainPreloadItem->isDone())
mTerrainPreloadItem->storeViews(0.0);
} }
} }
@ -415,6 +419,38 @@ namespace MWWorld
mUnrefQueue = unrefQueue; mUnrefQueue = unrefQueue;
} }
bool CellPreloader::getTerrainPreloadInProgress(int& progress, int& progressRange, double timestamp)
{
if (!mTerrainPreloadItem)
return false;
else if (mTerrainPreloadItem->isDone())
{
mTerrainPreloadItem->storeViews(timestamp);
mTerrainPreloadItem = nullptr;
return false;
}
else
{
progress = mTerrainPreloadItem->getProgress();
progressRange = mTerrainPreloadItem->getProgressRange();
return !progress || progress < progressRange;
}
}
void CellPreloader::abortTerrainPreloadExcept(const osg::Vec3f& exceptPos)
{
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
{
const float resetThreshold = ESM::Land::REAL_SIZE;
for (auto pos : mTerrainPreloadPositions)
if ((pos.first-exceptPos).length2() < resetThreshold*resetThreshold)
return;
mTerrainPreloadItem->abort();
mTerrainPreloadItem->waitTillDone();
mTerrainPreloadItem = nullptr;
}
}
void CellPreloader::setTerrainPreloadPositions(const std::vector<CellPreloader::PositionCellGrid> &positions) void CellPreloader::setTerrainPreloadPositions(const std::vector<CellPreloader::PositionCellGrid> &positions)
{ {
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone()) if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
@ -436,8 +472,12 @@ namespace MWWorld
} }
mTerrainPreloadPositions = positions; mTerrainPreloadPositions = positions;
mTerrainPreloadItem = new TerrainPreloadItem(mTerrainViews, mTerrain, positions);
mWorkQueue->addWorkItem(mTerrainPreloadItem); if (!positions.empty())
{
mTerrainPreloadItem = new TerrainPreloadItem(mTerrainViews, mTerrain, positions);
mWorkQueue->addWorkItem(mTerrainPreloadItem);
}
} }
} }

View file

@ -72,6 +72,9 @@ namespace MWWorld
typedef std::pair<osg::Vec3f, osg::Vec4i> PositionCellGrid; typedef std::pair<osg::Vec3f, osg::Vec4i> PositionCellGrid;
void setTerrainPreloadPositions(const std::vector<PositionCellGrid>& positions); void setTerrainPreloadPositions(const std::vector<PositionCellGrid>& positions);
bool getTerrainPreloadInProgress(int& progress, int& progressRange, double timestamp);
void abortTerrainPreloadExcept(const osg::Vec3f& exceptPos);
private: private:
Resource::ResourceSystem* mResourceSystem; Resource::ResourceSystem* mResourceSystem;
Resource::BulletShapeManager* mBulletShapeManager; Resource::BulletShapeManager* mBulletShapeManager;

View file

@ -849,15 +849,42 @@ namespace MWWorld
if (changeEvent) if (changeEvent)
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5); MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
preloadTerrain(position.asVec3());
changeCellGrid(x, y, changeEvent); changeCellGrid(x, y, changeEvent);
CellStore* current = MWBase::Environment::get().getWorld()->getExterior(x, y); CellStore* current = MWBase::Environment::get().getWorld()->getExterior(x, y);
changePlayerCell(current, position, adjustPlayerPos); changePlayerCell(current, position, adjustPlayerPos);
checkTerrainLoaded();
if (changeEvent) if (changeEvent)
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5); MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
} }
void Scene::checkTerrainLoaded()
{
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::ScopedLoad load(loadingListener);
int progress = 0, initialProgress = -1, progressRange = 0;
while (mPreloader->getTerrainPreloadInProgress(progress, progressRange, mRendering.getReferenceTime()))
{
if (initialProgress == -1)
{
loadingListener->setLabel("#{sLoadingMessage4}");
initialProgress = progress;
}
if (progress)
{
loadingListener->setProgressRange(std::max(0, progressRange-initialProgress));
loadingListener->setProgress(progress-initialProgress);
}
else
loadingListener->setProgress(0);
OpenThreads::Thread::microSleep(5000);
}
}
CellStore* Scene::getCurrentCell () CellStore* Scene::getCurrentCell ()
{ {
return mCurrentCell; return mCurrentCell;
@ -1102,6 +1129,7 @@ namespace MWWorld
void Scene::preloadTerrain(const osg::Vec3f &pos) void Scene::preloadTerrain(const osg::Vec3f &pos)
{ {
mPreloader->abortTerrainPreloadExcept(pos);
std::vector<PositionCellGrid> vec; std::vector<PositionCellGrid> vec;
vec.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos))); vec.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos)));
mPreloader->setTerrainPreloadPositions(vec); mPreloader->setTerrainPreloadPositions(vec);

View file

@ -101,6 +101,8 @@ namespace MWWorld
void preloadExteriorGrid(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, std::vector<PositionCellGrid>& exteriorPositions); void preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos, std::vector<PositionCellGrid>& exteriorPositions);
void checkTerrainLoaded();
osg::Vec4i gridCenterToBounds(const osg::Vec2i &centerCell) const; osg::Vec4i gridCenterToBounds(const osg::Vec2i &centerCell) const;
osg::Vec2i getNewGridCenter(const osg::Vec3f &pos, const osg::Vec2i *currentGridCenter = nullptr) const; osg::Vec2i getNewGridCenter(const osg::Vec3f &pos, const osg::Vec2i *currentGridCenter = nullptr) const;

View file

@ -243,7 +243,6 @@ namespace MWWorld
if (bypass && !mStartCell.empty()) if (bypass && !mStartCell.empty())
{ {
ESM::Position pos; ESM::Position pos;
if (findExteriorPosition (mStartCell, pos)) if (findExteriorPosition (mStartCell, pos))
{ {
changeToExteriorCell (pos, true); changeToExteriorCell (pos, true);
@ -384,9 +383,9 @@ namespace MWWorld
mPlayer->readRecord(reader, type); mPlayer->readRecord(reader, type);
if (getPlayerPtr().isInCell()) if (getPlayerPtr().isInCell())
{ {
mWorldScene->preloadCell(getPlayerPtr().getCell(), true);
if (getPlayerPtr().getCell()->isExterior()) if (getPlayerPtr().getCell()->isExterior())
mWorldScene->preloadTerrain(getPlayerPtr().getRefData().getPosition().asVec3()); mWorldScene->preloadTerrain(getPlayerPtr().getRefData().getPosition().asVec3());
mWorldScene->preloadCell(getPlayerPtr().getCell(), true);
} }
break; break;
default: default:

View file

@ -509,7 +509,7 @@ View* QuadTreeWorld::createView()
return new ViewData; return new ViewData;
} }
void QuadTreeWorld::preload(View *view, const osg::Vec3f &viewPoint, const osg::Vec4i &grid, std::atomic<bool> &abort) void QuadTreeWorld::preload(View *view, const osg::Vec3f &viewPoint, const osg::Vec4i &grid, std::atomic<bool> &abort, std::atomic<int> &progress, int& progressTotal)
{ {
ensureQuadTreeBuilt(); ensureQuadTreeBuilt();
@ -519,12 +519,16 @@ void QuadTreeWorld::preload(View *view, const osg::Vec3f &viewPoint, const osg::
DefaultLodCallback lodCallback(mLodFactor, MIN_SIZE, grid); DefaultLodCallback lodCallback(mLodFactor, MIN_SIZE, grid);
mRootNode->traverseNodes(vd, viewPoint, &lodCallback, mViewDistance); mRootNode->traverseNodes(vd, viewPoint, &lodCallback, mViewDistance);
const float cellWorldSize = mStorage->getCellWorldSize(); if (!progressTotal)
for (unsigned int i=0; i<vd->getNumEntries(); ++i)
progressTotal += vd->getEntry(i).mNode->getSize();
const float cellWorldSize = mStorage->getCellWorldSize();
for (unsigned int i=0; i<vd->getNumEntries() && !abort; ++i) for (unsigned int i=0; i<vd->getNumEntries() && !abort; ++i)
{ {
ViewData::Entry& entry = vd->getEntry(i); ViewData::Entry& entry = vd->getEntry(i);
loadRenderingNode(entry, vd, mVertexLodMod, cellWorldSize, grid, mChunkManagers, true); loadRenderingNode(entry, vd, mVertexLodMod, cellWorldSize, grid, mChunkManagers, true);
progress += entry.mNode->getSize();
} }
vd->markUnchanged(); vd->markUnchanged();
} }

View file

@ -38,7 +38,7 @@ namespace Terrain
virtual void unloadCell(int x, int y); virtual void unloadCell(int x, int y);
View* createView(); View* createView();
void preload(View* view, const osg::Vec3f& eyePoint, const osg::Vec4i &cellgrid, std::atomic<bool>& abort); void preload(View* view, const osg::Vec3f& eyePoint, const osg::Vec4i &cellgrid, std::atomic<bool>& abort, std::atomic<int>& progress, int& progressRange);
void storeView(const View* view, double referenceTime); void storeView(const View* view, double referenceTime);
void reportStats(unsigned int frameNumber, osg::Stats* stats); void reportStats(unsigned int frameNumber, osg::Stats* stats);

View file

@ -147,7 +147,7 @@ namespace Terrain
/// @note Thread safe, as long as you do not attempt to load into the same view from multiple threads. /// @note Thread safe, as long as you do not attempt to load into the same view from multiple threads.
virtual void preload(View* view, const osg::Vec3f& viewPoint, const osg::Vec4i &cellgrid, std::atomic<bool>& abort) {} virtual void preload(View* view, const osg::Vec3f& viewPoint, const osg::Vec4i &cellgrid, std::atomic<bool>& abort, std::atomic<int>& progress, int& progressRange) {}
/// Store a preloaded view into the cache with the intent that the next rendering traversal can use it. /// Store a preloaded view into the cache with the intent that the next rendering traversal can use it.
/// @note Not thread safe. /// @note Not thread safe.