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:
parent
da92ad329b
commit
ffbed7ee38
8 changed files with 88 additions and 12 deletions
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 ¢erCell) const;
|
osg::Vec4i gridCenterToBounds(const osg::Vec2i ¢erCell) 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;
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in a new issue