Merge branch 'pagingforone' into 'master'

Prevent object paging from leaking Vvardenfell into other exteriors

See merge request OpenMW/openmw!3234
revert-6246b479
psi29a 1 year ago
commit 2e9c9a6d7e

@ -453,8 +453,9 @@ namespace MWRender
}
};
ObjectPaging::ObjectPaging(Resource::SceneManager* sceneManager)
ObjectPaging::ObjectPaging(Resource::SceneManager* sceneManager, ESM::RefId worldspace)
: GenericResourceManager<ChunkId>(nullptr)
, Terrain::QuadTreeWorld::ChunkManager(worldspace)
, mSceneManager(sceneManager)
, mRefTrackerLocked(false)
{
@ -466,19 +467,11 @@ namespace MWRender
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,
const osg::Vec3f& viewPoint, bool compile, unsigned char lod)
std::map<ESM::RefNum, ESM::CellRef> ObjectPaging::collectESM3References(
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;
ESM::ReadersCache readers;
const auto& world = MWBase::Environment::get().getWorld();
const auto& store = world->getStore();
const auto& store = MWBase::Environment::get().getWorld()->getStore();
for (int cellX = startCell.x(); cellX < startCell.x() + size; ++cellX)
{
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)
{
@ -563,11 +580,12 @@ namespace MWRender
// Since ObjectPaging does not handle VisController, we can just ignore both types of nodes.
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 = [&] {
if (!activeGrid)
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);
@ -581,7 +599,7 @@ namespace MWRender
osg::Vec3f pos = ref.mPos.asVec3();
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())
|| (minBound.y() > std::floor(minBound.y()) && cellPos.y() < minBound.y())
|| (maxBound.x() < std::ceil(maxBound.x()) && cellPos.x() >= maxBound.x())
@ -858,7 +876,7 @@ namespace MWRender
{
if (mActiveGridOnly && !std::get<2>(id))
return false;
pos /= ESM::Land::REAL_SIZE;
pos /= getCellSize(mWorldspace);
clampToCell(pos);
osg::Vec2f center = std::get<0>(id);
float halfSize = std::get<1>(id) / 2;
@ -872,6 +890,7 @@ namespace MWRender
}
osg::Vec3f mPosition;
osg::Vec2i mCell;
ESM::RefId mWorldspace;
std::set<MWRender::ChunkId> mToClear;
bool mActiveGridOnly = false;
};
@ -895,6 +914,7 @@ namespace MWRender
ClearCacheFunctor ccf;
ccf.mPosition = pos;
ccf.mCell = cell;
ccf.mWorldspace = mWorldspace;
mCache->call(ccf);
if (ccf.mToClear.empty())
return false;
@ -921,6 +941,7 @@ namespace MWRender
ccf.mPosition = pos;
ccf.mCell = cell;
ccf.mActiveGridOnly = true;
ccf.mWorldspace = mWorldspace;
mCache->call(ccf);
if (ccf.mToClear.empty())
return false;

@ -16,6 +16,11 @@ namespace MWWorld
class ESMStore;
}
namespace ESM
{
class ReadersCache;
}
namespace MWRender
{
@ -24,7 +29,7 @@ namespace MWRender
class ObjectPaging : public Resource::GenericResourceManager<ChunkId>, public Terrain::QuadTreeWorld::ChunkManager
{
public:
ObjectPaging(Resource::SceneManager* sceneManager);
ObjectPaging(Resource::SceneManager* sceneManager, ESM::RefId worldspace);
~ObjectPaging() = default;
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; }
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;
typedef std::map<ESM::RefNum, float> SizeCache;
SizeCache mSizeCache;

@ -1342,7 +1342,8 @@ namespace MWRender
lodFactor, vertexLodMod, maxCompGeometrySize, debugChunks, worldspace);
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());
mResourceSystem->addResourceManager(newChunkMgr.mObjectPaging.get());
}

Loading…
Cancel
Save