|
|
|
@ -1,8 +1,9 @@
|
|
|
|
|
#include "cellpreloader.hpp"
|
|
|
|
|
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <atomic>
|
|
|
|
|
#include <limits>
|
|
|
|
|
#include <span>
|
|
|
|
|
|
|
|
|
|
#include <osg/Stats>
|
|
|
|
|
|
|
|
|
@ -26,32 +27,27 @@
|
|
|
|
|
#include "cellstore.hpp"
|
|
|
|
|
#include "class.hpp"
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
namespace MWWorld
|
|
|
|
|
{
|
|
|
|
|
template <class Contained>
|
|
|
|
|
bool contains(const std::vector<MWWorld::CellPreloader::PositionCellGrid>& container, const Contained& contained,
|
|
|
|
|
float tolerance)
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
for (const auto& pos : contained)
|
|
|
|
|
bool contains(std::span<const PositionCellGrid> positions, const PositionCellGrid& contained, float tolerance)
|
|
|
|
|
{
|
|
|
|
|
bool found = false;
|
|
|
|
|
for (const auto& pos2 : container)
|
|
|
|
|
{
|
|
|
|
|
if ((pos.first - pos2.first).length2() < tolerance * tolerance && pos.second == pos2.second)
|
|
|
|
|
{
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!found)
|
|
|
|
|
return false;
|
|
|
|
|
const float squaredTolerance = tolerance * tolerance;
|
|
|
|
|
const auto predicate = [&](const PositionCellGrid& v) {
|
|
|
|
|
return (contained.mPosition - v.mPosition).length2() < squaredTolerance
|
|
|
|
|
&& contained.mCellBounds == v.mCellBounds;
|
|
|
|
|
};
|
|
|
|
|
return std::ranges::any_of(positions, predicate);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace MWWorld
|
|
|
|
|
{
|
|
|
|
|
bool contains(
|
|
|
|
|
std::span<const PositionCellGrid> container, std::span<const PositionCellGrid> contained, float tolerance)
|
|
|
|
|
{
|
|
|
|
|
const auto predicate = [&](const PositionCellGrid& v) { return contains(container, v, tolerance); };
|
|
|
|
|
return std::ranges::all_of(contained, predicate);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ListModelsVisitor
|
|
|
|
|
{
|
|
|
|
@ -169,12 +165,12 @@ namespace MWWorld
|
|
|
|
|
class TerrainPreloadItem : public SceneUtil::WorkItem
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
TerrainPreloadItem(const std::vector<osg::ref_ptr<Terrain::View>>& views, Terrain::World* world,
|
|
|
|
|
const std::vector<CellPreloader::PositionCellGrid>& preloadPositions)
|
|
|
|
|
explicit TerrainPreloadItem(const std::vector<osg::ref_ptr<Terrain::View>>& views, Terrain::World* world,
|
|
|
|
|
std::span<const PositionCellGrid> preloadPositions)
|
|
|
|
|
: mAbort(false)
|
|
|
|
|
, mTerrainViews(views)
|
|
|
|
|
, mWorld(world)
|
|
|
|
|
, mPreloadPositions(preloadPositions)
|
|
|
|
|
, mPreloadPositions(preloadPositions.begin(), preloadPositions.end())
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -183,8 +179,8 @@ namespace MWWorld
|
|
|
|
|
for (unsigned int i = 0; i < mTerrainViews.size() && i < mPreloadPositions.size() && !mAbort; ++i)
|
|
|
|
|
{
|
|
|
|
|
mTerrainViews[i]->reset();
|
|
|
|
|
mWorld->preload(mTerrainViews[i], mPreloadPositions[i].first, mPreloadPositions[i].second, mAbort,
|
|
|
|
|
mLoadingReporter);
|
|
|
|
|
mWorld->preload(mTerrainViews[i], mPreloadPositions[i].mPosition, mPreloadPositions[i].mCellBounds,
|
|
|
|
|
mAbort, mLoadingReporter);
|
|
|
|
|
}
|
|
|
|
|
mLoadingReporter.complete();
|
|
|
|
|
}
|
|
|
|
@ -197,7 +193,7 @@ namespace MWWorld
|
|
|
|
|
std::atomic<bool> mAbort;
|
|
|
|
|
std::vector<osg::ref_ptr<Terrain::View>> mTerrainViews;
|
|
|
|
|
Terrain::World* mWorld;
|
|
|
|
|
std::vector<CellPreloader::PositionCellGrid> mPreloadPositions;
|
|
|
|
|
std::vector<PositionCellGrid> mPreloadPositions;
|
|
|
|
|
Loading::Reporter mLoadingReporter;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -375,19 +371,19 @@ namespace MWWorld
|
|
|
|
|
mTerrainPreloadItem->wait(listener);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellPreloader::abortTerrainPreloadExcept(const CellPreloader::PositionCellGrid* exceptPos)
|
|
|
|
|
void CellPreloader::abortTerrainPreloadExcept(const PositionCellGrid* exceptPos)
|
|
|
|
|
{
|
|
|
|
|
if (exceptPos && contains(mTerrainPreloadPositions, std::array{ *exceptPos }, Constants::CellSizeInUnits))
|
|
|
|
|
if (exceptPos != nullptr && contains(mTerrainPreloadPositions, *exceptPos, Constants::CellSizeInUnits))
|
|
|
|
|
return;
|
|
|
|
|
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
|
|
|
|
|
{
|
|
|
|
|
mTerrainPreloadItem->abort();
|
|
|
|
|
mTerrainPreloadItem->waitTillDone();
|
|
|
|
|
}
|
|
|
|
|
setTerrainPreloadPositions(std::vector<CellPreloader::PositionCellGrid>());
|
|
|
|
|
setTerrainPreloadPositions({});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellPreloader::setTerrainPreloadPositions(const std::vector<CellPreloader::PositionCellGrid>& positions)
|
|
|
|
|
void CellPreloader::setTerrainPreloadPositions(std::span<const PositionCellGrid> positions)
|
|
|
|
|
{
|
|
|
|
|
if (positions.empty())
|
|
|
|
|
{
|
|
|
|
@ -408,7 +404,7 @@ namespace MWWorld
|
|
|
|
|
mTerrainViews.emplace_back(mTerrain->createView());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mTerrainPreloadPositions = positions;
|
|
|
|
|
mTerrainPreloadPositions.assign(positions.begin(), positions.end());
|
|
|
|
|
if (!positions.empty())
|
|
|
|
|
{
|
|
|
|
|
mTerrainPreloadItem = new TerrainPreloadItem(mTerrainViews, mTerrain, positions);
|
|
|
|
@ -417,10 +413,10 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CellPreloader::isTerrainLoaded(const CellPreloader::PositionCellGrid& position, double referenceTime) const
|
|
|
|
|
bool CellPreloader::isTerrainLoaded(const PositionCellGrid& position, double referenceTime) const
|
|
|
|
|
{
|
|
|
|
|
return mLoadedTerrainTimestamp + mResourceSystem->getSceneManager()->getExpiryDelay() > referenceTime
|
|
|
|
|
&& contains(mLoadedTerrainPositions, std::array{ position }, Constants::CellSizeInUnits);
|
|
|
|
|
&& contains(mLoadedTerrainPositions, position, Constants::CellSizeInUnits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellPreloader::setTerrain(Terrain::World* terrain)
|
|
|
|
|