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:
commit
2e9c9a6d7e
3 changed files with 48 additions and 18 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue