diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index c71ad38665..b1d17b0a61 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -84,6 +84,7 @@ add_openmw_dir (mwworld store esmstore fallback actionrepair actionsoulgem livecellref actiondoor contentloader esmloader actiontrap cellreflist cellref weather projectilemanager cellpreloader datetimemanager groundcoverstore magiceffects cell ptrregistry + positioncellgrid ) add_openmw_dir (mwphysics diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp index e08d576835..2881471b25 100644 --- a/apps/openmw/mwworld/cellpreloader.cpp +++ b/apps/openmw/mwworld/cellpreloader.cpp @@ -1,8 +1,9 @@ #include "cellpreloader.hpp" -#include +#include #include #include +#include #include @@ -26,32 +27,27 @@ #include "cellstore.hpp" #include "class.hpp" -namespace +namespace MWWorld { - template - bool contains(const std::vector& container, const Contained& contained, - float tolerance) + namespace { - for (const auto& pos : contained) + bool contains(std::span 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 container, std::span 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>& views, Terrain::World* world, - const std::vector& preloadPositions) + explicit TerrainPreloadItem(const std::vector>& views, Terrain::World* world, + std::span 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 mAbort; std::vector> mTerrainViews; Terrain::World* mWorld; - std::vector mPreloadPositions; + std::vector 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()); + setTerrainPreloadPositions({}); } - void CellPreloader::setTerrainPreloadPositions(const std::vector& positions) + void CellPreloader::setTerrainPreloadPositions(std::span 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) diff --git a/apps/openmw/mwworld/cellpreloader.hpp b/apps/openmw/mwworld/cellpreloader.hpp index aa8f2c73be..405ba96a2e 100644 --- a/apps/openmw/mwworld/cellpreloader.hpp +++ b/apps/openmw/mwworld/cellpreloader.hpp @@ -1,15 +1,14 @@ #ifndef OPENMW_MWWORLD_CELLPRELOADER_H #define OPENMW_MWWORLD_CELLPRELOADER_H -#include +#include "positioncellgrid.hpp" -#include +#include -#include -#include #include #include +#include namespace osg { @@ -79,12 +78,11 @@ namespace MWWorld void setWorkQueue(osg::ref_ptr workQueue); - typedef std::pair PositionCellGrid; - void setTerrainPreloadPositions(const std::vector& positions); + void setTerrainPreloadPositions(std::span positions); void syncTerrainLoad(Loading::Listener& listener); void abortTerrainPreloadExcept(const PositionCellGrid* exceptPos); - bool isTerrainLoaded(const CellPreloader::PositionCellGrid& position, double referenceTime) const; + bool isTerrainLoaded(const PositionCellGrid& position, double referenceTime) const; void setTerrain(Terrain::World* terrain); void reportStats(unsigned int frameNumber, osg::Stats& stats) const; diff --git a/apps/openmw/mwworld/positioncellgrid.hpp b/apps/openmw/mwworld/positioncellgrid.hpp new file mode 100644 index 0000000000..cbb8e3300a --- /dev/null +++ b/apps/openmw/mwworld/positioncellgrid.hpp @@ -0,0 +1,16 @@ +#ifndef OPENMW_APPS_OPENMW_MWWORLD_POSITIONCELLGRID_H +#define OPENMW_APPS_OPENMW_MWWORLD_POSITIONCELLGRID_H + +#include +#include + +namespace MWWorld +{ + struct PositionCellGrid + { + osg::Vec3f mPosition; + osg::Vec4i mCellBounds; + }; +} + +#endif diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 169e4bfd21..5f585c1d26 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -603,7 +603,7 @@ namespace MWWorld mPreloader->setTerrain(mRendering.getTerrain()); if (mRendering.pagingUnlockCache()) mPreloader->abortTerrainPreloadExcept(nullptr); - if (!mPreloader->isTerrainLoaded(std::make_pair(pos, newGrid), mRendering.getReferenceTime())) + if (!mPreloader->isTerrainLoaded(PositionCellGrid{ pos, newGrid }, mRendering.getReferenceTime())) preloadTerrain(pos, playerCellIndex.mWorldspace, true); mPagedRefs.clear(); mRendering.getPagedRefnums(newGrid, mPagedRefs); @@ -1093,26 +1093,25 @@ namespace MWWorld osg::Vec3f predictedPos = playerPos + moved / dt * mPredictionTime; if (mCurrentCell->isExterior()) - exteriorPositions.emplace_back( - predictedPos, gridCenterToBounds(getNewGridCenter(predictedPos, &mCurrentGridCenter))); + exteriorPositions.push_back(PositionCellGrid{ + predictedPos, gridCenterToBounds(getNewGridCenter(predictedPos, &mCurrentGridCenter)) }); mLastPlayerPos = playerPos; if (mPreloadEnabled) { if (mPreloadDoors) - preloadTeleportDoorDestinations(playerPos, predictedPos, exteriorPositions); + preloadTeleportDoorDestinations(playerPos, predictedPos); if (mPreloadExteriorGrid) preloadExteriorGrid(playerPos, predictedPos); if (mPreloadFastTravel) - preloadFastTravelDestinations(playerPos, predictedPos, exteriorPositions); + preloadFastTravelDestinations(playerPos, exteriorPositions); } mPreloader->setTerrainPreloadPositions(exteriorPositions); } - void Scene::preloadTeleportDoorDestinations( - const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos, std::vector& exteriorPositions) + void Scene::preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos) { std::vector teleportDoors; for (const MWWorld::CellStore* cellStore : mActiveCells) @@ -1232,10 +1231,9 @@ namespace MWWorld void Scene::preloadTerrain(const osg::Vec3f& pos, ESM::RefId worldspace, bool sync) { ESM::ExteriorCellLocation cellPos = ESM::positionToExteriorCellLocation(pos.x(), pos.y(), worldspace); - std::vector vec; - vec.emplace_back(pos, gridCenterToBounds({ cellPos.mX, cellPos.mY })); - mPreloader->abortTerrainPreloadExcept(vec.data()); - mPreloader->setTerrainPreloadPositions(vec); + const PositionCellGrid position{ pos, gridCenterToBounds({ cellPos.mX, cellPos.mY }) }; + mPreloader->abortTerrainPreloadExcept(&position); + mPreloader->setTerrainPreloadPositions(std::span(&position, 1)); if (!sync) return; @@ -1249,7 +1247,7 @@ namespace MWWorld void Scene::reloadTerrain() { - mPreloader->setTerrainPreloadPositions(std::vector()); + mPreloader->setTerrainPreloadPositions({}); } struct ListFastTravelDestinationsVisitor @@ -1282,12 +1280,10 @@ namespace MWWorld std::vector mList; }; - void Scene::preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& /*predictedPos*/, - std::vector& exteriorPositions) // ignore predictedPos here since opening dialogue with - // travel service takes extra time + void Scene::preloadFastTravelDestinations( + const osg::Vec3f& playerPos, std::vector& exteriorPositions) { - const MWWorld::ConstPtr player = mWorld.getPlayerPtr(); - ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, player.getRefData().getPosition().asVec3()); + ListFastTravelDestinationsVisitor listVisitor(mPreloadDistance, playerPos); ESM::RefId extWorldspace = mWorld.getCurrentWorldspace(); for (MWWorld::CellStore* cellStore : mActiveCells) { @@ -1305,7 +1301,7 @@ namespace MWWorld const ESM::ExteriorCellLocation cellIndex = ESM::positionToExteriorCellLocation(pos.x(), pos.y(), extWorldspace); preloadCellWithSurroundings(mWorld.getWorldModel().getExterior(cellIndex)); - exteriorPositions.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos))); + exteriorPositions.push_back(PositionCellGrid{ pos, gridCenterToBounds(getNewGridCenter(pos)) }); } } } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 91feff8746..93d814ec51 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -5,6 +5,7 @@ #include #include +#include "positioncellgrid.hpp" #include "ptr.hpp" #include @@ -122,14 +123,11 @@ namespace MWWorld void requestChangeCellGrid(const osg::Vec3f& position, const osg::Vec2i& cell, bool changeEvent = true); - typedef std::pair PositionCellGrid; - void preloadCells(float dt); - void preloadTeleportDoorDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos, - std::vector& exteriorPositions); + void preloadTeleportDoorDestinations(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& exteriorPositions); + void preloadFastTravelDestinations( + const osg::Vec3f& playerPos, std::vector& exteriorPositions); osg::Vec4i gridCenterToBounds(const osg::Vec2i& centerCell) const; osg::Vec2i getNewGridCenter(const osg::Vec3f& pos, const osg::Vec2i* currentGridCenter = nullptr) const; diff --git a/components/terrain/viewdata.hpp b/components/terrain/viewdata.hpp index b8b0b8a1f9..3014ba53f0 100644 --- a/components/terrain/viewdata.hpp +++ b/components/terrain/viewdata.hpp @@ -70,7 +70,6 @@ namespace Terrain mNodes.clear(); } } - const osg::Vec4i& getActiveGrid() const { return mActiveGrid; } unsigned int getWorldUpdateRevision() const { return mWorldUpdateRevision; } void setWorldUpdateRevision(int updateRevision) { mWorldUpdateRevision = updateRevision; }