mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:23:52 +00:00
avoid pagerebuild when reloading a same save
Signed-off-by: Bret Curtis <psi29a@gmail.com>
This commit is contained in:
parent
6fa12a6eb8
commit
b27b76e325
8 changed files with 110 additions and 67 deletions
|
@ -339,6 +339,7 @@ namespace MWRender
|
||||||
ObjectPaging::ObjectPaging(Resource::SceneManager* sceneManager)
|
ObjectPaging::ObjectPaging(Resource::SceneManager* sceneManager)
|
||||||
: GenericResourceManager<ChunkId>(nullptr)
|
: GenericResourceManager<ChunkId>(nullptr)
|
||||||
, mSceneManager(sceneManager)
|
, mSceneManager(sceneManager)
|
||||||
|
, mRefTrackerLocked(false)
|
||||||
{
|
{
|
||||||
mActiveGrid = Settings::Manager::getBool("object paging active grid", "Terrain");
|
mActiveGrid = Settings::Manager::getBool("object paging active grid", "Terrain");
|
||||||
mDebugBatches = Settings::Manager::getBool("object paging debug batches", "Terrain");
|
mDebugBatches = Settings::Manager::getBool("object paging debug batches", "Terrain");
|
||||||
|
@ -403,9 +404,9 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||||
if (activeGrid)
|
if (activeGrid)
|
||||||
for (auto ref : mBlacklist)
|
for (auto ref : getRefTracker().mBlacklist)
|
||||||
refs.erase(ref);
|
refs.erase(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,8 +490,8 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||||
if (mDisabled.count(pair.first))
|
if (getRefTracker().mDisabled.count(pair.first))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,14 +684,16 @@ namespace MWRender
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||||
if (enabled && !mDisabled.erase(refnum)) return false;
|
if (enabled && !getWritableRefTracker().mDisabled.erase(refnum)) return false;
|
||||||
if (!enabled && !mDisabled.insert(refnum).second) return false;
|
if (!enabled && !getWritableRefTracker().mDisabled.insert(refnum).second) return false;
|
||||||
|
if (mRefTrackerLocked) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearCacheFunctor ccf;
|
ClearCacheFunctor ccf;
|
||||||
ccf.mPosition = pos;
|
ccf.mPosition = pos;
|
||||||
mCache->call(ccf);
|
mCache->call(ccf);
|
||||||
|
if (ccf.mToClear.empty()) return false;
|
||||||
for (auto chunk : ccf.mToClear)
|
for (auto chunk : ccf.mToClear)
|
||||||
mCache->removeFromObjectCache(chunk);
|
mCache->removeFromObjectCache(chunk);
|
||||||
return true;
|
return true;
|
||||||
|
@ -702,8 +705,9 @@ namespace MWRender
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||||
if (!mBlacklist.insert(refnum).second) return false;
|
if (!getWritableRefTracker().mBlacklist.insert(refnum).second) return false;
|
||||||
|
if (mRefTrackerLocked) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearCacheFunctor ccf;
|
ClearCacheFunctor ccf;
|
||||||
|
@ -719,12 +723,25 @@ namespace MWRender
|
||||||
|
|
||||||
void ObjectPaging::clear()
|
void ObjectPaging::clear()
|
||||||
{
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||||
|
mRefTrackerNew.mDisabled.clear();
|
||||||
|
mRefTrackerNew.mBlacklist.clear();
|
||||||
|
mRefTrackerLocked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectPaging::unlockCache()
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
if (!mRefTrackerLocked) return false;
|
||||||
mDisabled.clear();
|
{
|
||||||
mBlacklist.clear();
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||||
|
mRefTrackerLocked = false;
|
||||||
|
if (mRefTracker == mRefTrackerNew)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
mRefTracker = mRefTrackerNew;
|
||||||
}
|
}
|
||||||
mCache->clear();
|
mCache->clear();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GetRefnumsFunctor
|
struct GetRefnumsFunctor
|
||||||
|
|
|
@ -41,6 +41,10 @@ namespace MWRender
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
/// Must be called after clear() before rendering starts.
|
||||||
|
/// @return true if view needs rebuild
|
||||||
|
bool unlockCache();
|
||||||
|
|
||||||
void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;
|
void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;
|
||||||
|
|
||||||
void getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out);
|
void getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out);
|
||||||
|
@ -54,9 +58,19 @@ namespace MWRender
|
||||||
float mMinSizeMergeFactor;
|
float mMinSizeMergeFactor;
|
||||||
float mMinSizeCostMultiplier;
|
float mMinSizeCostMultiplier;
|
||||||
|
|
||||||
OpenThreads::Mutex mDisabledMutex;
|
OpenThreads::Mutex mRefTrackerMutex;
|
||||||
|
struct RefTracker
|
||||||
|
{
|
||||||
std::set<ESM::RefNum> mDisabled;
|
std::set<ESM::RefNum> mDisabled;
|
||||||
std::set<ESM::RefNum> mBlacklist;
|
std::set<ESM::RefNum> mBlacklist;
|
||||||
|
bool operator==(const RefTracker&other) { return mDisabled == other.mDisabled && mBlacklist == other.mBlacklist; }
|
||||||
|
};
|
||||||
|
RefTracker mRefTracker;
|
||||||
|
RefTracker mRefTrackerNew;
|
||||||
|
bool mRefTrackerLocked;
|
||||||
|
|
||||||
|
const RefTracker& getRefTracker() const { return mRefTracker; }
|
||||||
|
RefTracker& getWritableRefTracker() { return mRefTrackerLocked ? mRefTrackerNew : mRefTracker; }
|
||||||
|
|
||||||
OpenThreads::Mutex mSizeCacheMutex;
|
OpenThreads::Mutex mSizeCacheMutex;
|
||||||
typedef std::map<ESM::RefNum, float> SizeCache;
|
typedef std::map<ESM::RefNum, float> SizeCache;
|
||||||
|
|
|
@ -1511,6 +1511,15 @@ namespace MWRender
|
||||||
if (mObjectPaging->blacklistObject(type, refnum, ptr.getCellRef().getPosition().asVec3()))
|
if (mObjectPaging->blacklistObject(type, refnum, ptr.getCellRef().getPosition().asVec3()))
|
||||||
mTerrain->rebuildViews();
|
mTerrain->rebuildViews();
|
||||||
}
|
}
|
||||||
|
bool RenderingManager::pagingUnlockCache()
|
||||||
|
{
|
||||||
|
if (mObjectPaging && mObjectPaging->unlockCache())
|
||||||
|
{
|
||||||
|
mTerrain->rebuildViews();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
void RenderingManager::getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out)
|
void RenderingManager::getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out)
|
||||||
{
|
{
|
||||||
if (mObjectPaging)
|
if (mObjectPaging)
|
||||||
|
|
|
@ -244,6 +244,7 @@ namespace MWRender
|
||||||
|
|
||||||
bool pagingEnableObject(int type, const MWWorld::ConstPtr& ptr, bool enabled);
|
bool pagingEnableObject(int type, const MWWorld::ConstPtr& ptr, bool enabled);
|
||||||
void pagingBlacklistObject(int type, const MWWorld::ConstPtr &ptr);
|
void pagingBlacklistObject(int type, const MWWorld::ConstPtr &ptr);
|
||||||
|
bool pagingUnlockCache();
|
||||||
void getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out);
|
void getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -419,36 +419,44 @@ namespace MWWorld
|
||||||
mUnrefQueue = unrefQueue;
|
mUnrefQueue = unrefQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CellPreloader::getTerrainPreloadInProgress(int& progress, int& progressRange, double timestamp)
|
bool CellPreloader::syncTerrainLoad(const std::vector<CellPreloader::PositionCellGrid> &positions, int& progress, int& progressRange, double timestamp)
|
||||||
{
|
{
|
||||||
if (!mTerrainPreloadItem)
|
if (!mTerrainPreloadItem)
|
||||||
return false;
|
return true;
|
||||||
else if (mTerrainPreloadItem->isDone())
|
else if (mTerrainPreloadItem->isDone())
|
||||||
{
|
{
|
||||||
mTerrainPreloadItem->storeViews(timestamp);
|
if (mTerrainPreloadItem->storeViews(timestamp))
|
||||||
|
{
|
||||||
mTerrainPreloadItem = nullptr;
|
mTerrainPreloadItem = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setTerrainPreloadPositions(std::vector<CellPreloader::PositionCellGrid>());
|
||||||
|
setTerrainPreloadPositions(positions);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
progress = mTerrainPreloadItem->getProgress();
|
progress = mTerrainPreloadItem->getProgress();
|
||||||
progressRange = mTerrainPreloadItem->getProgressRange();
|
progressRange = mTerrainPreloadItem->getProgressRange();
|
||||||
return !progress || progress < progressRange;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellPreloader::abortTerrainPreloadExcept(const CellPreloader::PositionCellGrid& exceptPos)
|
void CellPreloader::abortTerrainPreloadExcept(const CellPreloader::PositionCellGrid *exceptPos)
|
||||||
{
|
|
||||||
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
|
|
||||||
{
|
{
|
||||||
const float resetThreshold = ESM::Land::REAL_SIZE;
|
const float resetThreshold = ESM::Land::REAL_SIZE;
|
||||||
for (auto pos : mTerrainPreloadPositions)
|
for (auto pos : mTerrainPreloadPositions)
|
||||||
if ((pos.first-exceptPos.first).length2() < resetThreshold*resetThreshold && pos.second == exceptPos.second)
|
if (exceptPos && (pos.first-exceptPos->first).length2() < resetThreshold*resetThreshold && pos.second == exceptPos->second)
|
||||||
return;
|
return;
|
||||||
|
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
|
||||||
|
{
|
||||||
mTerrainPreloadItem->abort();
|
mTerrainPreloadItem->abort();
|
||||||
mTerrainPreloadItem->waitTillDone();
|
mTerrainPreloadItem->waitTillDone();
|
||||||
mTerrainPreloadItem = nullptr;
|
|
||||||
}
|
}
|
||||||
|
setTerrainPreloadPositions(std::vector<CellPreloader::PositionCellGrid>());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contains(const std::vector<CellPreloader::PositionCellGrid>& container, const std::vector<CellPreloader::PositionCellGrid>& contained)
|
bool contains(const std::vector<CellPreloader::PositionCellGrid>& container, const std::vector<CellPreloader::PositionCellGrid>& contained)
|
||||||
|
|
|
@ -72,8 +72,8 @@ 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);
|
bool syncTerrainLoad(const std::vector<CellPreloader::PositionCellGrid> &positions, int& progress, int& progressRange, double timestamp);
|
||||||
void abortTerrainPreloadExcept(const PositionCellGrid &exceptPos);
|
void abortTerrainPreloadExcept(const PositionCellGrid *exceptPos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Resource::ResourceSystem* mResourceSystem;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
|
|
@ -510,13 +510,10 @@ namespace MWWorld
|
||||||
|
|
||||||
osg::Vec2i newCell = getNewGridCenter(pos, &mCurrentGridCenter);
|
osg::Vec2i newCell = getNewGridCenter(pos, &mCurrentGridCenter);
|
||||||
if (newCell != mCurrentGridCenter)
|
if (newCell != mCurrentGridCenter)
|
||||||
{
|
changeCellGrid(pos, newCell.x(), newCell.y());
|
||||||
preloadTerrain(pos);
|
|
||||||
changeCellGrid(newCell.x(), newCell.y());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::changeCellGrid (int playerCellX, int playerCellY, bool changeEvent)
|
void Scene::changeCellGrid (const osg::Vec3f &pos, int playerCellX, int playerCellY, bool changeEvent)
|
||||||
{
|
{
|
||||||
CellStoreCollection::iterator active = mActiveCells.begin();
|
CellStoreCollection::iterator active = mActiveCells.begin();
|
||||||
while (active!=mActiveCells.end())
|
while (active!=mActiveCells.end())
|
||||||
|
@ -538,8 +535,8 @@ namespace MWWorld
|
||||||
osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter);
|
osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter);
|
||||||
mRendering.setActiveGrid(newGrid);
|
mRendering.setActiveGrid(newGrid);
|
||||||
|
|
||||||
|
preloadTerrain(pos, true);
|
||||||
mPagedRefs.clear();
|
mPagedRefs.clear();
|
||||||
checkTerrainLoaded();
|
|
||||||
mRendering.getPagedRefnums(newGrid, mPagedRefs);
|
mRendering.getPagedRefnums(newGrid, mPagedRefs);
|
||||||
|
|
||||||
std::size_t refsToLoad = 0;
|
std::size_t refsToLoad = 0;
|
||||||
|
@ -867,9 +864,7 @@ namespace MWWorld
|
||||||
if (changeEvent)
|
if (changeEvent)
|
||||||
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
|
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
|
||||||
|
|
||||||
preloadTerrain(position.asVec3());
|
changeCellGrid(position.asVec3(), x, y, changeEvent);
|
||||||
checkTerrainLoaded();
|
|
||||||
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);
|
||||||
|
@ -878,29 +873,6 @@ namespace MWWorld
|
||||||
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;
|
||||||
|
@ -1145,12 +1117,36 @@ namespace MWWorld
|
||||||
mPreloader->preload(cell, mRendering.getReferenceTime());
|
mPreloader->preload(cell, mRendering.getReferenceTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::preloadTerrain(const osg::Vec3f &pos)
|
void Scene::preloadTerrain(const osg::Vec3f &pos, bool sync)
|
||||||
{
|
{
|
||||||
std::vector<PositionCellGrid> vec;
|
std::vector<PositionCellGrid> vec;
|
||||||
vec.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos)));
|
vec.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos)));
|
||||||
mPreloader->abortTerrainPreloadExcept(vec[0]);
|
if (sync && mRendering.pagingUnlockCache())
|
||||||
|
mPreloader->abortTerrainPreloadExcept(nullptr);
|
||||||
|
else
|
||||||
|
mPreloader->abortTerrainPreloadExcept(&vec[0]);
|
||||||
mPreloader->setTerrainPreloadPositions(vec);
|
mPreloader->setTerrainPreloadPositions(vec);
|
||||||
|
if (!sync) return;
|
||||||
|
|
||||||
|
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||||
|
Loading::ScopedLoad load(loadingListener);
|
||||||
|
int progress = 0, initialProgress = -1, progressRange = 0;
|
||||||
|
while (!mPreloader->syncTerrainLoad(vec, 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::reloadTerrain()
|
void Scene::reloadTerrain()
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace MWWorld
|
||||||
osg::Vec2i mCurrentGridCenter;
|
osg::Vec2i mCurrentGridCenter;
|
||||||
|
|
||||||
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
||||||
void changeCellGrid (int playerCellX, int playerCellY, bool changeEvent = true);
|
void changeCellGrid (const osg::Vec3f &pos, int playerCellX, int playerCellY, bool changeEvent = true);
|
||||||
|
|
||||||
typedef std::pair<osg::Vec3f, osg::Vec4i> PositionCellGrid;
|
typedef std::pair<osg::Vec3f, osg::Vec4i> PositionCellGrid;
|
||||||
|
|
||||||
|
@ -102,8 +102,6 @@ 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;
|
||||||
|
|
||||||
|
@ -115,7 +113,7 @@ namespace MWWorld
|
||||||
~Scene();
|
~Scene();
|
||||||
|
|
||||||
void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false);
|
void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false);
|
||||||
void preloadTerrain(const osg::Vec3f& pos);
|
void preloadTerrain(const osg::Vec3f& pos, bool sync=false);
|
||||||
void reloadTerrain();
|
void reloadTerrain();
|
||||||
|
|
||||||
void unloadCell (CellStoreCollection::iterator iter, bool test = false);
|
void unloadCell (CellStoreCollection::iterator iter, bool test = false);
|
||||||
|
|
Loading…
Reference in a new issue