1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-31 07:06:45 +00:00

Merge branch 'pagingforone' into 'master'

Prevent object paging from leaking Vvardenfell into other exteriors

See merge request OpenMW/openmw!3234
This commit is contained in:
psi29a 2023-07-16 08:43:52 +00:00
commit 2e9c9a6d7e
3 changed files with 48 additions and 18 deletions

View file

@ -453,8 +453,9 @@ namespace MWRender
} }
}; };
ObjectPaging::ObjectPaging(Resource::SceneManager* sceneManager) ObjectPaging::ObjectPaging(Resource::SceneManager* sceneManager, ESM::RefId worldspace)
: GenericResourceManager<ChunkId>(nullptr) : GenericResourceManager<ChunkId>(nullptr)
, Terrain::QuadTreeWorld::ChunkManager(worldspace)
, mSceneManager(sceneManager) , mSceneManager(sceneManager)
, mRefTrackerLocked(false) , mRefTrackerLocked(false)
{ {
@ -466,19 +467,11 @@ namespace MWRender
mMinSizeCostMultiplier = Settings::Manager::getFloat("object paging min size cost multiplier", "Terrain"); mMinSizeCostMultiplier = Settings::Manager::getFloat("object paging min size cost multiplier", "Terrain");
} }
osg::ref_ptr<osg::Node> ObjectPaging::createChunk(float size, const osg::Vec2f& center, bool activeGrid, std::map<ESM::RefNum, ESM::CellRef> ObjectPaging::collectESM3References(
const osg::Vec3f& viewPoint, bool compile, unsigned char lod) float size, const osg::Vec2i& startCell, ESM::ReadersCache& readers) const
{ {
osg::Vec2i startCell = osg::Vec2i(std::floor(center.x() - size / 2.f), std::floor(center.y() - size / 2.f));
osg::Vec3f worldCenter = osg::Vec3f(center.x(), center.y(), 0) * ESM::Land::REAL_SIZE;
osg::Vec3f relativeViewPoint = viewPoint - worldCenter;
std::map<ESM::RefNum, ESM::CellRef> refs; std::map<ESM::RefNum, ESM::CellRef> refs;
ESM::ReadersCache readers; const auto& store = MWBase::Environment::get().getWorld()->getStore();
const auto& world = MWBase::Environment::get().getWorld();
const auto& store = world->getStore();
for (int cellX = startCell.x(); cellX < startCell.x() + size; ++cellX) for (int cellX = startCell.x(); cellX < startCell.x() + size; ++cellX)
{ {
for (int cellY = startCell.y(); cellY < startCell.y() + size; ++cellY) for (int cellY = startCell.y(); cellY < startCell.y() + size; ++cellY)
@ -537,6 +530,30 @@ namespace MWRender
} }
} }
} }
return refs;
}
osg::ref_ptr<osg::Node> ObjectPaging::createChunk(float size, const osg::Vec2f& center, bool activeGrid,
const osg::Vec3f& viewPoint, bool compile, unsigned char lod)
{
osg::Vec2i startCell = osg::Vec2i(std::floor(center.x() - size / 2.f), std::floor(center.y() - size / 2.f));
osg::Vec3f worldCenter = osg::Vec3f(center.x(), center.y(), 0) * getCellSize(mWorldspace);
osg::Vec3f relativeViewPoint = viewPoint - worldCenter;
std::map<ESM::RefNum, ESM::CellRef> refs;
ESM::ReadersCache readers;
const auto& world = MWBase::Environment::get().getWorld();
const auto& store = world->getStore();
if (mWorldspace == ESM::Cell::sDefaultWorldspaceId)
{
refs = collectESM3References(size, startCell, readers);
}
else
{
// TODO
}
if (activeGrid) if (activeGrid)
{ {
@ -563,11 +580,12 @@ namespace MWRender
// Since ObjectPaging does not handle VisController, we can just ignore both types of nodes. // Since ObjectPaging does not handle VisController, we can just ignore both types of nodes.
constexpr auto copyMask = ~Mask_UpdateVisitor; constexpr auto copyMask = ~Mask_UpdateVisitor;
const auto smallestDistanceToChunk = (size > 1 / 8.f) ? (size * ESM::Land::REAL_SIZE) : 0.f; auto cellSize = getCellSize(mWorldspace);
const auto smallestDistanceToChunk = (size > 1 / 8.f) ? (size * cellSize) : 0.f;
const auto higherDistanceToChunk = [&] { const auto higherDistanceToChunk = [&] {
if (!activeGrid) if (!activeGrid)
return smallestDistanceToChunk + 1; return smallestDistanceToChunk + 1;
return ((size < 1) ? 5 : 3) * ESM::Land::REAL_SIZE * size + 1; return ((size < 1) ? 5 : 3) * cellSize * size + 1;
}(); }();
AnalyzeVisitor analyzeVisitor(copyMask); AnalyzeVisitor analyzeVisitor(copyMask);
@ -581,7 +599,7 @@ namespace MWRender
osg::Vec3f pos = ref.mPos.asVec3(); osg::Vec3f pos = ref.mPos.asVec3();
if (size < 1.f) if (size < 1.f)
{ {
osg::Vec3f cellPos = pos / ESM::Land::REAL_SIZE; osg::Vec3f cellPos = pos / cellSize;
if ((minBound.x() > std::floor(minBound.x()) && cellPos.x() < minBound.x()) if ((minBound.x() > std::floor(minBound.x()) && cellPos.x() < minBound.x())
|| (minBound.y() > std::floor(minBound.y()) && cellPos.y() < minBound.y()) || (minBound.y() > std::floor(minBound.y()) && cellPos.y() < minBound.y())
|| (maxBound.x() < std::ceil(maxBound.x()) && cellPos.x() >= maxBound.x()) || (maxBound.x() < std::ceil(maxBound.x()) && cellPos.x() >= maxBound.x())
@ -858,7 +876,7 @@ namespace MWRender
{ {
if (mActiveGridOnly && !std::get<2>(id)) if (mActiveGridOnly && !std::get<2>(id))
return false; return false;
pos /= ESM::Land::REAL_SIZE; pos /= getCellSize(mWorldspace);
clampToCell(pos); clampToCell(pos);
osg::Vec2f center = std::get<0>(id); osg::Vec2f center = std::get<0>(id);
float halfSize = std::get<1>(id) / 2; float halfSize = std::get<1>(id) / 2;
@ -872,6 +890,7 @@ namespace MWRender
} }
osg::Vec3f mPosition; osg::Vec3f mPosition;
osg::Vec2i mCell; osg::Vec2i mCell;
ESM::RefId mWorldspace;
std::set<MWRender::ChunkId> mToClear; std::set<MWRender::ChunkId> mToClear;
bool mActiveGridOnly = false; bool mActiveGridOnly = false;
}; };
@ -895,6 +914,7 @@ namespace MWRender
ClearCacheFunctor ccf; ClearCacheFunctor ccf;
ccf.mPosition = pos; ccf.mPosition = pos;
ccf.mCell = cell; ccf.mCell = cell;
ccf.mWorldspace = mWorldspace;
mCache->call(ccf); mCache->call(ccf);
if (ccf.mToClear.empty()) if (ccf.mToClear.empty())
return false; return false;
@ -921,6 +941,7 @@ namespace MWRender
ccf.mPosition = pos; ccf.mPosition = pos;
ccf.mCell = cell; ccf.mCell = cell;
ccf.mActiveGridOnly = true; ccf.mActiveGridOnly = true;
ccf.mWorldspace = mWorldspace;
mCache->call(ccf); mCache->call(ccf);
if (ccf.mToClear.empty()) if (ccf.mToClear.empty())
return false; return false;

View file

@ -16,6 +16,11 @@ namespace MWWorld
class ESMStore; class ESMStore;
} }
namespace ESM
{
class ReadersCache;
}
namespace MWRender namespace MWRender
{ {
@ -24,7 +29,7 @@ namespace MWRender
class ObjectPaging : public Resource::GenericResourceManager<ChunkId>, public Terrain::QuadTreeWorld::ChunkManager class ObjectPaging : public Resource::GenericResourceManager<ChunkId>, public Terrain::QuadTreeWorld::ChunkManager
{ {
public: public:
ObjectPaging(Resource::SceneManager* sceneManager); ObjectPaging(Resource::SceneManager* sceneManager, ESM::RefId worldspace);
~ObjectPaging() = default; ~ObjectPaging() = default;
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags, osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags,
@ -78,6 +83,9 @@ namespace MWRender
const RefTracker& getRefTracker() const { return mRefTracker; } const RefTracker& getRefTracker() const { return mRefTracker; }
RefTracker& getWritableRefTracker() { return mRefTrackerLocked ? mRefTrackerNew : mRefTracker; } RefTracker& getWritableRefTracker() { return mRefTrackerLocked ? mRefTrackerNew : mRefTracker; }
std::map<ESM::RefNum, ESM::CellRef> collectESM3References(
float size, const osg::Vec2i& startCell, ESM::ReadersCache& readers) const;
std::mutex mSizeCacheMutex; std::mutex mSizeCacheMutex;
typedef std::map<ESM::RefNum, float> SizeCache; typedef std::map<ESM::RefNum, float> SizeCache;
SizeCache mSizeCache; SizeCache mSizeCache;

View file

@ -1342,7 +1342,8 @@ namespace MWRender
lodFactor, vertexLodMod, maxCompGeometrySize, debugChunks, worldspace); lodFactor, vertexLodMod, maxCompGeometrySize, debugChunks, worldspace);
if (Settings::Manager::getBool("object paging", "Terrain")) if (Settings::Manager::getBool("object paging", "Terrain"))
{ {
newChunkMgr.mObjectPaging = std::make_unique<ObjectPaging>(mResourceSystem->getSceneManager()); newChunkMgr.mObjectPaging
= std::make_unique<ObjectPaging>(mResourceSystem->getSceneManager(), worldspace);
quadTreeWorld->addChunkManager(newChunkMgr.mObjectPaging.get()); quadTreeWorld->addChunkManager(newChunkMgr.mObjectPaging.get());
mResourceSystem->addResourceManager(newChunkMgr.mObjectPaging.get()); mResourceSystem->addResourceManager(newChunkMgr.mObjectPaging.get());
} }