diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 5b74fe63f4..fc02f205ff 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -822,6 +822,8 @@ namespace MWWorld loadingListener->setProgressRange(cell->count()); + mNavigator.updatePlayerPosition(position.asVec3()); + // Load cell. mPagedRefs.clear(); loadCell(cell, loadingListener, changeEvent); @@ -855,6 +857,8 @@ namespace MWWorld if (changeEvent) MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5); + mNavigator.updatePlayerPosition(position.asVec3()); + changeCellGrid(position.asVec3(), x, y, changeEvent); CellStore* current = MWBase::Environment::get().getWorld()->getExterior(x, y); diff --git a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp index c44ebc5155..631e4105ba 100644 --- a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp @@ -90,6 +90,10 @@ namespace const btBoxShape boxShape(btVector3(20, 20, 100)); const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0)); const CollisionShape shape(mInstance, boxShape, mObjectTransform); + TileBounds bounds; + bounds.mMin = osg::Vec2f(-1000, -1000); + bounds.mMax = osg::Vec2f(1000, 1000); + manager.setBounds(bounds); manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground); EXPECT_TRUE(manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [&] (const auto& v) { onChangedTile(v); })); @@ -137,6 +141,10 @@ namespace TEST_F(DetourNavigatorTileCachedRecastMeshManagerTest, get_mesh_for_moved_object_should_return_recast_mesh_for_each_used_tile) { TileCachedRecastMeshManager manager(mSettings); + TileBounds bounds; + bounds.mMin = osg::Vec2f(-1000, -1000); + bounds.mMax = osg::Vec2f(1000, 1000); + manager.setBounds(bounds); manager.setWorldspace("worldspace"); const btBoxShape boxShape(btVector3(20, 20, 100)); diff --git a/components/detournavigator/gettilespositions.cpp b/components/detournavigator/gettilespositions.cpp index d427eb3e12..e74a22e5ba 100644 --- a/components/detournavigator/gettilespositions.cpp +++ b/components/detournavigator/gettilespositions.cpp @@ -2,6 +2,7 @@ #include "settings.hpp" #include "settingsutils.hpp" #include "tileposition.hpp" +#include "tilebounds.hpp" #include @@ -32,12 +33,15 @@ namespace DetourNavigator } TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape, const btTransform& transform, - const RecastSettings& settings) + const TileBounds& bounds, const RecastSettings& settings) { btVector3 aabbMin; btVector3 aabbMax; shape.getAabb(transform, aabbMin, aabbMax); - + aabbMin.setX(std::max(aabbMin.x(), bounds.mMin.x())); + aabbMin.setY(std::max(aabbMin.y(), bounds.mMin.y())); + aabbMax.setX(std::min(aabbMax.x(), bounds.mMax.x())); + aabbMax.setY(std::min(aabbMax.y(), bounds.mMax.y())); return makeTilesPositionsRange(Misc::Convert::toOsg(aabbMin), Misc::Convert::toOsg(aabbMax), settings); } diff --git a/components/detournavigator/gettilespositions.hpp b/components/detournavigator/gettilespositions.hpp index 946f3e64f2..9d3df7ef65 100644 --- a/components/detournavigator/gettilespositions.hpp +++ b/components/detournavigator/gettilespositions.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H +#include "tilebounds.hpp" #include "tileposition.hpp" class btVector3; @@ -26,7 +27,7 @@ namespace DetourNavigator const osg::Vec3f& aabbMax, const RecastSettings& settings); TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape, - const btTransform& transform, const RecastSettings& settings); + const btTransform& transform, const TileBounds& bounds, const RecastSettings& settings); TilesPositionsRange makeTilesPositionsRange(const int cellSize, const btVector3& shift, const RecastSettings& settings); diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index 9fba4ad611..e8da5a0d61 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -42,6 +42,18 @@ namespace namespace DetourNavigator { + namespace + { + TileBounds makeBounds(const RecastSettings& settings, const osg::Vec2f& center, int maxTiles) + { + const float radius = fromNavMeshCoordinates(settings, std::ceil(std::sqrt(static_cast(maxTiles) / osg::PIf) + 1) * getTileSize(settings)); + TileBounds result; + result.mMin = center - osg::Vec2f(radius, radius); + result.mMax = center + osg::Vec2f(radius, radius); + return result; + } + } + NavMeshManager::NavMeshManager(const Settings& settings, std::unique_ptr&& db) : mSettings(settings) , mRecastMeshManager(settings.mRecast) @@ -205,6 +217,7 @@ namespace DetourNavigator } } const auto maxTiles = std::min(mSettings.mMaxTilesNumber, navMesh.getParams()->maxTiles); + mRecastMeshManager.setBounds(makeBounds(mSettings.mRecast, osg::Vec2f(playerPosition.x(), playerPosition.y()), maxTiles)); mRecastMeshManager.forEachTile([&] (const TilePosition& tile, CachedRecastMeshManager& recastMeshManager) { if (tilesToPost.count(tile)) @@ -263,7 +276,7 @@ namespace DetourNavigator void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform, const ChangeType changeType) { - getTilesPositions(makeTilesPositionsRange(shape, transform, mSettings.mRecast), + getTilesPositions(makeTilesPositionsRange(shape, transform, mRecastMeshManager.getBounds(), mSettings.mRecast), [&] (const TilePosition& v) { addChangedTile(v, changeType); }); } diff --git a/components/detournavigator/settingsutils.hpp b/components/detournavigator/settingsutils.hpp index 285920e5a0..e38da2d0e1 100644 --- a/components/detournavigator/settingsutils.hpp +++ b/components/detournavigator/settingsutils.hpp @@ -37,6 +37,11 @@ namespace DetourNavigator }; } + inline float fromNavMeshCoordinates(const RecastSettings& settings, float value) + { + return value / settings.mRecastScaleFactor; + } + inline osg::Vec3f fromNavMeshCoordinates(const RecastSettings& settings, osg::Vec3f position) { const auto factor = 1.0f / settings.mRecastScaleFactor; diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index 17ba7afc39..ced5a28656 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -8,13 +8,28 @@ #include #include +#include namespace DetourNavigator { TileCachedRecastMeshManager::TileCachedRecastMeshManager(const RecastSettings& settings) : mSettings(settings) + , mBounds {osg::Vec2f(-std::numeric_limits::max(), -std::numeric_limits::max()), + osg::Vec2f(std::numeric_limits::max(), std::numeric_limits::max())} {} + TileBounds TileCachedRecastMeshManager::getBounds() const + { + const std::lock_guard lock(mMutex); + return mBounds; + } + + void TileCachedRecastMeshManager::setBounds(const TileBounds& bounds) + { + const std::lock_guard lock(mMutex); + mBounds = bounds; + } + std::string TileCachedRecastMeshManager::getWorldspace() const { const std::lock_guard lock(mMutex); @@ -36,7 +51,7 @@ namespace DetourNavigator std::vector tilesPositions; { const std::lock_guard lock(mMutex); - getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mSettings), + getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mBounds, mSettings), [&] (const TilePosition& tilePosition) { if (addTile(id, shape, transform, areaType, tilePosition, mTiles)) diff --git a/components/detournavigator/tilecachedrecastmeshmanager.hpp b/components/detournavigator/tilecachedrecastmeshmanager.hpp index 88face24ce..d99dc3e27e 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.hpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.hpp @@ -20,6 +20,10 @@ namespace DetourNavigator public: explicit TileCachedRecastMeshManager(const RecastSettings& settings); + TileBounds getBounds() const; + + void setBounds(const TileBounds& bounds); + std::string getWorldspace() const; void setWorldspace(std::string_view worldspace); @@ -57,7 +61,7 @@ namespace DetourNavigator changed = true; } }; - getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mSettings), onTilePosition); + getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mBounds, mSettings), onTilePosition); std::sort(newTiles.begin(), newTiles.end()); for (const auto& tile : currentTiles) { @@ -109,6 +113,7 @@ namespace DetourNavigator const RecastSettings& mSettings; mutable std::mutex mMutex; + TileBounds mBounds; std::string mWorldspace; TilesMap mTiles; std::unordered_map> mObjectsTilesPositions;