From 12ce82980ce7db03fbc9eb9bd35b895416eb6b05 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 25 Jan 2022 16:33:53 +0100 Subject: [PATCH 1/6] Revert "Limit and filter navmesh input (#5858)" This reverts commit ecc654a36939d8627f21b228c6ddbdf7b09464b8. --- apps/navmeshtool/navmesh.cpp | 37 ++++----- apps/openmw/mwworld/scene.cpp | 7 +- .../detournavigator/gettilespositions.cpp | 15 ++-- .../tilecachedrecastmeshmanager.cpp | 8 -- components/CMakeLists.txt | 1 - .../detournavigator/gettilespositions.cpp | 66 ---------------- .../detournavigator/gettilespositions.hpp | 77 +++++++++++++------ components/detournavigator/navigatorimpl.cpp | 1 - components/detournavigator/navmeshmanager.cpp | 18 +---- .../detournavigator/recastmeshbuilder.cpp | 12 --- components/detournavigator/settingsutils.hpp | 5 -- .../tilecachedrecastmeshmanager.cpp | 22 +----- .../tilecachedrecastmeshmanager.hpp | 7 +- 13 files changed, 81 insertions(+), 195 deletions(-) delete mode 100644 components/detournavigator/gettilespositions.cpp diff --git a/apps/navmeshtool/navmesh.cpp b/apps/navmeshtool/navmesh.cpp index 100ddaf22a..4187197947 100644 --- a/apps/navmeshtool/navmesh.cpp +++ b/apps/navmeshtool/navmesh.cpp @@ -35,7 +35,6 @@ #include #include #include -#include namespace NavMeshTool { @@ -181,36 +180,26 @@ namespace NavMeshTool SceneUtil::WorkQueue workQueue(threadsNumber); auto navMeshTileConsumer = std::make_shared(std::move(db)); std::size_t tiles = 0; - std::mt19937_64 random; for (const std::unique_ptr& input : data.mNavMeshInputs) { - std::vector worldspaceTiles; - DetourNavigator::getTilesPositions( - DetourNavigator::makeTilesPositionsRange( - Misc::Convert::toOsg(input->mAabb.m_min), - Misc::Convert::toOsg(input->mAabb.m_max), - settings.mRecast - ), - [&] (const TilePosition& tilePosition) { worldspaceTiles.push_back(tilePosition); } - ); + Misc::Convert::toOsg(input->mAabb.m_min), Misc::Convert::toOsg(input->mAabb.m_max), settings.mRecast, + [&] (const TilePosition& tilePosition) + { + workQueue.addWorkItem(new GenerateNavMeshTile( + input->mWorldspace, + tilePosition, + RecastMeshProvider(input->mTileCachedRecastMeshManager), + agentHalfExtents, + settings, + navMeshTileConsumer + )); - tiles += worldspaceTiles.size(); + ++tiles; + }); navMeshTileConsumer->mExpected = tiles; - - std::shuffle(worldspaceTiles.begin(), worldspaceTiles.end(), random); - - for (const TilePosition& tilePosition : worldspaceTiles) - workQueue.addWorkItem(new GenerateNavMeshTile( - input->mWorldspace, - tilePosition, - RecastMeshProvider(input->mTileCachedRecastMeshManager), - agentHalfExtents, - settings, - navMeshTileConsumer - )); } navMeshTileConsumer->wait(); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index fc02f205ff..054e26e855 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -511,7 +511,8 @@ namespace MWWorld if (mCurrentCell == nullptr) return; - mNavigator.updatePlayerPosition(pos); + const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + mNavigator.updatePlayerPosition(player.getRefData().getPosition().asVec3()); if (!mCurrentCell->isExterior()) return; @@ -822,8 +823,6 @@ namespace MWWorld loadingListener->setProgressRange(cell->count()); - mNavigator.updatePlayerPosition(position.asVec3()); - // Load cell. mPagedRefs.clear(); loadCell(cell, loadingListener, changeEvent); @@ -857,8 +856,6 @@ 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/gettilespositions.cpp b/apps/openmw_test_suite/detournavigator/gettilespositions.cpp index 8121c19205..ced33a99f0 100644 --- a/apps/openmw_test_suite/detournavigator/gettilespositions.cpp +++ b/apps/openmw_test_suite/detournavigator/gettilespositions.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include @@ -37,35 +36,35 @@ namespace TEST_F(DetourNavigatorGetTilesPositionsTest, for_object_in_single_tile_should_return_one_tile) { - getTilesPositions(makeTilesPositionsRange(osg::Vec3f(2, 2, 0), osg::Vec3f(31, 31, 1), mSettings), mCollect); + getTilesPositions(osg::Vec3f(2, 2, 0), osg::Vec3f(31, 31, 1), mSettings, mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0))); } TEST_F(DetourNavigatorGetTilesPositionsTest, for_object_with_x_bounds_in_two_tiles_should_return_two_tiles) { - getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 31, 1), mSettings), mCollect); + getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 31, 1), mSettings, mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0), TilePosition(1, 0))); } TEST_F(DetourNavigatorGetTilesPositionsTest, for_object_with_y_bounds_in_two_tiles_should_return_two_tiles) { - getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 32, 1), mSettings), mCollect); + getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 32, 1), mSettings, mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0), TilePosition(0, 1))); } TEST_F(DetourNavigatorGetTilesPositionsTest, tiling_works_only_for_x_and_y_coordinates) { - getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 31, 32), mSettings), mCollect); + getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 31, 32), mSettings, mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0))); } TEST_F(DetourNavigatorGetTilesPositionsTest, tiling_should_work_with_negative_coordinates) { - getTilesPositions(makeTilesPositionsRange(osg::Vec3f(-31, -31, 0), osg::Vec3f(31, 31, 1), mSettings), mCollect); + getTilesPositions(osg::Vec3f(-31, -31, 0), osg::Vec3f(31, 31, 1), mSettings, mCollect); EXPECT_THAT(mTilesPositions, ElementsAre( TilePosition(-1, -1), @@ -79,7 +78,7 @@ namespace { mSettings.mBorderSize = 1; - getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(31.5, 31.5, 1), mSettings), mCollect); + getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(31.5, 31.5, 1), mSettings, mCollect); EXPECT_THAT(mTilesPositions, ElementsAre( TilePosition(-1, -1), @@ -98,7 +97,7 @@ namespace { mSettings.mRecastScaleFactor = 0.5; - getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 32, 1), mSettings), mCollect); + getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 32, 1), mSettings, mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0))); } diff --git a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp index 631e4105ba..c44ebc5155 100644 --- a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp @@ -90,10 +90,6 @@ 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); })); @@ -141,10 +137,6 @@ 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/CMakeLists.txt b/components/CMakeLists.txt index ae06f3f2b0..89b27b0d94 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -208,7 +208,6 @@ add_component_dir(detournavigator serialization navmeshdbutils recast - gettilespositions ) add_component_dir(loadinglistener diff --git a/components/detournavigator/gettilespositions.cpp b/components/detournavigator/gettilespositions.cpp deleted file mode 100644 index e74a22e5ba..0000000000 --- a/components/detournavigator/gettilespositions.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "gettilespositions.hpp" -#include "settings.hpp" -#include "settingsutils.hpp" -#include "tileposition.hpp" -#include "tilebounds.hpp" - -#include - -#include - -namespace DetourNavigator -{ - TilesPositionsRange makeTilesPositionsRange(const osg::Vec3f& aabbMin, const osg::Vec3f& aabbMax, - const RecastSettings& settings) - { - osg::Vec3f min = toNavMeshCoordinates(settings, aabbMin); - osg::Vec3f max = toNavMeshCoordinates(settings, aabbMax); - - const float border = getBorderSize(settings); - min -= osg::Vec3f(border, border, border); - max += osg::Vec3f(border, border, border); - - TilePosition minTile = getTilePosition(settings, min); - TilePosition maxTile = getTilePosition(settings, max); - - if (minTile.x() > maxTile.x()) - std::swap(minTile.x(), maxTile.x()); - - if (minTile.y() > maxTile.y()) - std::swap(minTile.y(), maxTile.y()); - - return {minTile, maxTile}; - } - - TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape, const btTransform& transform, - 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); - } - - TilesPositionsRange makeTilesPositionsRange(const int cellSize, const btVector3& shift, - const RecastSettings& settings) - { - using Misc::Convert::toOsg; - - const int halfCellSize = cellSize / 2; - const btTransform transform(btMatrix3x3::getIdentity(), shift); - btVector3 aabbMin = transform(btVector3(-halfCellSize, -halfCellSize, 0)); - btVector3 aabbMax = transform(btVector3(halfCellSize, halfCellSize, 0)); - - aabbMin.setX(std::min(aabbMin.x(), aabbMax.x())); - aabbMin.setY(std::min(aabbMin.y(), aabbMax.y())); - - aabbMax.setX(std::max(aabbMin.x(), aabbMax.x())); - aabbMax.setY(std::max(aabbMin.y(), aabbMax.y())); - - return makeTilesPositionsRange(toOsg(aabbMin), toOsg(aabbMax), settings); - } -} diff --git a/components/detournavigator/gettilespositions.hpp b/components/detournavigator/gettilespositions.hpp index 9d3df7ef65..707db0b512 100644 --- a/components/detournavigator/gettilespositions.hpp +++ b/components/detournavigator/gettilespositions.hpp @@ -1,43 +1,72 @@ #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H -#include "tilebounds.hpp" +#include "settings.hpp" +#include "settingsutils.hpp" #include "tileposition.hpp" -class btVector3; -class btTransform; -class btCollisionShape; +#include -namespace osg -{ - class Vec3f; -} +#include + +#include namespace DetourNavigator { - struct RecastSettings; - - struct TilesPositionsRange + template + void getTilesPositions(const osg::Vec3f& aabbMin, const osg::Vec3f& aabbMax, + const RecastSettings& settings, Callback&& callback) { - TilePosition mMin; - TilePosition mMax; - }; + auto min = toNavMeshCoordinates(settings, aabbMin); + auto max = toNavMeshCoordinates(settings, aabbMax); - TilesPositionsRange makeTilesPositionsRange(const osg::Vec3f& aabbMin, - const osg::Vec3f& aabbMax, const RecastSettings& settings); + const auto border = getBorderSize(settings); + min -= osg::Vec3f(border, border, border); + max += osg::Vec3f(border, border, border); - TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape, - const btTransform& transform, const TileBounds& bounds, const RecastSettings& settings); + auto minTile = getTilePosition(settings, min); + auto maxTile = getTilePosition(settings, max); - TilesPositionsRange makeTilesPositionsRange(const int cellSize, const btVector3& shift, - const RecastSettings& settings); + if (minTile.x() > maxTile.x()) + std::swap(minTile.x(), maxTile.x()); + + if (minTile.y() > maxTile.y()) + std::swap(minTile.y(), maxTile.y()); + + for (int tileX = minTile.x(); tileX <= maxTile.x(); ++tileX) + for (int tileY = minTile.y(); tileY <= maxTile.y(); ++tileY) + callback(TilePosition {tileX, tileY}); + } template - void getTilesPositions(const TilesPositionsRange& range, Callback&& callback) + void getTilesPositions(const btCollisionShape& shape, const btTransform& transform, + const RecastSettings& settings, Callback&& callback) { - for (int tileX = range.mMin.x(); tileX <= range.mMax.x(); ++tileX) - for (int tileY = range.mMin.y(); tileY <= range.mMax.y(); ++tileY) - callback(TilePosition {tileX, tileY}); + btVector3 aabbMin; + btVector3 aabbMax; + shape.getAabb(transform, aabbMin, aabbMax); + + getTilesPositions(Misc::Convert::toOsg(aabbMin), Misc::Convert::toOsg(aabbMax), settings, std::forward(callback)); + } + + template + void getTilesPositions(const int cellSize, const btVector3& shift, + const RecastSettings& settings, Callback&& callback) + { + using Misc::Convert::toOsg; + + const auto halfCellSize = cellSize / 2; + const btTransform transform(btMatrix3x3::getIdentity(), shift); + auto aabbMin = transform(btVector3(-halfCellSize, -halfCellSize, 0)); + auto aabbMax = transform(btVector3(halfCellSize, halfCellSize, 0)); + + aabbMin.setX(std::min(aabbMin.x(), aabbMax.x())); + aabbMin.setY(std::min(aabbMin.y(), aabbMax.y())); + + aabbMax.setX(std::max(aabbMin.x(), aabbMax.x())); + aabbMax.setY(std::max(aabbMin.y(), aabbMax.y())); + + getTilesPositions(toOsg(aabbMin), toOsg(aabbMax), settings, std::forward(callback)); } } diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index 82a156bb97..85d86e6b2b 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -5,7 +5,6 @@ #include #include #include -#include namespace DetourNavigator { diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index e8da5a0d61..399af8a6a9 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -9,7 +9,6 @@ #include #include -#include #include @@ -42,18 +41,6 @@ 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) @@ -217,7 +204,6 @@ 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)) @@ -276,7 +262,7 @@ namespace DetourNavigator void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform, const ChangeType changeType) { - getTilesPositions(makeTilesPositionsRange(shape, transform, mRecastMeshManager.getBounds(), mSettings.mRecast), + getTilesPositions(shape, transform, mSettings.mRecast, [&] (const TilePosition& v) { addChangedTile(v, changeType); }); } @@ -286,7 +272,7 @@ namespace DetourNavigator if (cellSize == std::numeric_limits::max()) return; - getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings.mRecast), + getTilesPositions(cellSize, shift, mSettings.mRecast, [&] (const TilePosition& v) { addChangedTile(v, changeType); }); } diff --git a/components/detournavigator/recastmeshbuilder.cpp b/components/detournavigator/recastmeshbuilder.cpp index 08e7002cf8..0f7552aa77 100644 --- a/components/detournavigator/recastmeshbuilder.cpp +++ b/components/detournavigator/recastmeshbuilder.cpp @@ -20,7 +20,6 @@ #include #include #include -#include namespace DetourNavigator { @@ -41,16 +40,6 @@ namespace DetourNavigator { return static_cast(cellSize) / (dataSize - 1); } - - bool isNan(const RecastMeshTriangle& triangle) - { - for (std::size_t i = 0; i < 3; ++i) - if (std::isnan(triangle.mVertices[i].x()) - || std::isnan(triangle.mVertices[i].y()) - || std::isnan(triangle.mVertices[i].z())) - return true; - return false; - } } Mesh makeMesh(std::vector&& triangles, const osg::Vec3f& shift) @@ -275,7 +264,6 @@ namespace DetourNavigator std::shared_ptr RecastMeshBuilder::create(std::size_t generation, std::size_t revision) && { - mTriangles.erase(std::remove_if(mTriangles.begin(), mTriangles.end(), isNan), mTriangles.end()); std::sort(mTriangles.begin(), mTriangles.end()); std::sort(mWater.begin(), mWater.end()); Mesh mesh = makeMesh(std::move(mTriangles)); diff --git a/components/detournavigator/settingsutils.hpp b/components/detournavigator/settingsutils.hpp index e38da2d0e1..285920e5a0 100644 --- a/components/detournavigator/settingsutils.hpp +++ b/components/detournavigator/settingsutils.hpp @@ -37,11 +37,6 @@ 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 b3750ad171..bf3df92d6e 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -4,7 +4,6 @@ #include "settingsutils.hpp" #include -#include #include #include @@ -15,18 +14,6 @@ namespace DetourNavigator : mSettings(settings) {} - 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); @@ -48,8 +35,7 @@ namespace DetourNavigator std::vector tilesPositions; { const std::lock_guard lock(mMutex); - getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mBounds, mSettings), - [&] (const TilePosition& tilePosition) + getTilesPositions(shape.getShape(), transform, mSettings, [&] (const TilePosition& tilePosition) { if (addTile(id, shape, transform, areaType, tilePosition, mTiles)) tilesPositions.push_back(tilePosition); @@ -104,8 +90,7 @@ namespace DetourNavigator else { const btVector3 shift = Misc::Convert::toBullet(getWaterShift3d(cellPosition, cellSize, level)); - getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings), - [&] (const TilePosition& tilePosition) + getTilesPositions(cellSize, shift, mSettings, [&] (const TilePosition& tilePosition) { const std::lock_guard lock(mMutex); auto tile = mTiles.find(tilePosition); @@ -163,8 +148,7 @@ namespace DetourNavigator bool result = false; - getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings), - [&] (const TilePosition& tilePosition) + getTilesPositions(cellSize, shift, mSettings, [&] (const TilePosition& tilePosition) { const std::lock_guard lock(mMutex); auto tile = mTiles.find(tilePosition); diff --git a/components/detournavigator/tilecachedrecastmeshmanager.hpp b/components/detournavigator/tilecachedrecastmeshmanager.hpp index d99dc3e27e..23171f0925 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.hpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.hpp @@ -20,10 +20,6 @@ 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); @@ -61,7 +57,7 @@ namespace DetourNavigator changed = true; } }; - getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mBounds, mSettings), onTilePosition); + getTilesPositions(shape.getShape(), transform, mSettings, onTilePosition); std::sort(newTiles.begin(), newTiles.end()); for (const auto& tile : currentTiles) { @@ -113,7 +109,6 @@ namespace DetourNavigator const RecastSettings& mSettings; mutable std::mutex mMutex; - TileBounds mBounds; std::string mWorldspace; TilesMap mTiles; std::unordered_map> mObjectsTilesPositions; From d1d29a24524d062bd36a944b59ca86005e0ed271 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 18 Dec 2021 00:05:50 +0100 Subject: [PATCH 2/6] Shuffle tile positions before adding to queue for processing --- apps/navmeshtool/navmesh.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/apps/navmeshtool/navmesh.cpp b/apps/navmeshtool/navmesh.cpp index 4187197947..36ed448e72 100644 --- a/apps/navmeshtool/navmesh.cpp +++ b/apps/navmeshtool/navmesh.cpp @@ -35,6 +35,7 @@ #include #include #include +#include namespace NavMeshTool { @@ -180,26 +181,31 @@ namespace NavMeshTool SceneUtil::WorkQueue workQueue(threadsNumber); auto navMeshTileConsumer = std::make_shared(std::move(db)); std::size_t tiles = 0; + std::mt19937_64 random; for (const std::unique_ptr& input : data.mNavMeshInputs) { + std::vector worldspaceTiles; + DetourNavigator::getTilesPositions( Misc::Convert::toOsg(input->mAabb.m_min), Misc::Convert::toOsg(input->mAabb.m_max), settings.mRecast, - [&] (const TilePosition& tilePosition) - { - workQueue.addWorkItem(new GenerateNavMeshTile( - input->mWorldspace, - tilePosition, - RecastMeshProvider(input->mTileCachedRecastMeshManager), - agentHalfExtents, - settings, - navMeshTileConsumer - )); + [&] (const TilePosition& tilePosition) { worldspaceTiles.push_back(tilePosition); }); - ++tiles; - }); + tiles += worldspaceTiles.size(); navMeshTileConsumer->mExpected = tiles; + + std::shuffle(worldspaceTiles.begin(), worldspaceTiles.end(), random); + + for (const TilePosition& tilePosition : worldspaceTiles) + workQueue.addWorkItem(new GenerateNavMeshTile( + input->mWorldspace, + tilePosition, + RecastMeshProvider(input->mTileCachedRecastMeshManager), + agentHalfExtents, + settings, + navMeshTileConsumer + )); } navMeshTileConsumer->wait(); From bba7beb0c58f259aaffd8ccd59e0ae03c1907855 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 18 Dec 2021 00:37:32 +0100 Subject: [PATCH 3/6] Split tiles position range creation and iteration over --- apps/navmeshtool/navmesh.cpp | 9 ++- .../detournavigator/gettilespositions.cpp | 15 ++-- components/CMakeLists.txt | 1 + .../detournavigator/gettilespositions.cpp | 62 +++++++++++++++ .../detournavigator/gettilespositions.hpp | 78 ++++++------------- components/detournavigator/navigatorimpl.cpp | 1 + components/detournavigator/navmeshmanager.cpp | 5 +- .../tilecachedrecastmeshmanager.cpp | 10 ++- .../tilecachedrecastmeshmanager.hpp | 2 +- 9 files changed, 114 insertions(+), 69 deletions(-) create mode 100644 components/detournavigator/gettilespositions.cpp diff --git a/apps/navmeshtool/navmesh.cpp b/apps/navmeshtool/navmesh.cpp index 36ed448e72..100ddaf22a 100644 --- a/apps/navmeshtool/navmesh.cpp +++ b/apps/navmeshtool/navmesh.cpp @@ -188,8 +188,13 @@ namespace NavMeshTool std::vector worldspaceTiles; DetourNavigator::getTilesPositions( - Misc::Convert::toOsg(input->mAabb.m_min), Misc::Convert::toOsg(input->mAabb.m_max), settings.mRecast, - [&] (const TilePosition& tilePosition) { worldspaceTiles.push_back(tilePosition); }); + DetourNavigator::makeTilesPositionsRange( + Misc::Convert::toOsg(input->mAabb.m_min), + Misc::Convert::toOsg(input->mAabb.m_max), + settings.mRecast + ), + [&] (const TilePosition& tilePosition) { worldspaceTiles.push_back(tilePosition); } + ); tiles += worldspaceTiles.size(); diff --git a/apps/openmw_test_suite/detournavigator/gettilespositions.cpp b/apps/openmw_test_suite/detournavigator/gettilespositions.cpp index ced33a99f0..8121c19205 100644 --- a/apps/openmw_test_suite/detournavigator/gettilespositions.cpp +++ b/apps/openmw_test_suite/detournavigator/gettilespositions.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -36,35 +37,35 @@ namespace TEST_F(DetourNavigatorGetTilesPositionsTest, for_object_in_single_tile_should_return_one_tile) { - getTilesPositions(osg::Vec3f(2, 2, 0), osg::Vec3f(31, 31, 1), mSettings, mCollect); + getTilesPositions(makeTilesPositionsRange(osg::Vec3f(2, 2, 0), osg::Vec3f(31, 31, 1), mSettings), mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0))); } TEST_F(DetourNavigatorGetTilesPositionsTest, for_object_with_x_bounds_in_two_tiles_should_return_two_tiles) { - getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 31, 1), mSettings, mCollect); + getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 31, 1), mSettings), mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0), TilePosition(1, 0))); } TEST_F(DetourNavigatorGetTilesPositionsTest, for_object_with_y_bounds_in_two_tiles_should_return_two_tiles) { - getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 32, 1), mSettings, mCollect); + getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 32, 1), mSettings), mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0), TilePosition(0, 1))); } TEST_F(DetourNavigatorGetTilesPositionsTest, tiling_works_only_for_x_and_y_coordinates) { - getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 31, 32), mSettings, mCollect); + getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(31, 31, 32), mSettings), mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0))); } TEST_F(DetourNavigatorGetTilesPositionsTest, tiling_should_work_with_negative_coordinates) { - getTilesPositions(osg::Vec3f(-31, -31, 0), osg::Vec3f(31, 31, 1), mSettings, mCollect); + getTilesPositions(makeTilesPositionsRange(osg::Vec3f(-31, -31, 0), osg::Vec3f(31, 31, 1), mSettings), mCollect); EXPECT_THAT(mTilesPositions, ElementsAre( TilePosition(-1, -1), @@ -78,7 +79,7 @@ namespace { mSettings.mBorderSize = 1; - getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(31.5, 31.5, 1), mSettings, mCollect); + getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(31.5, 31.5, 1), mSettings), mCollect); EXPECT_THAT(mTilesPositions, ElementsAre( TilePosition(-1, -1), @@ -97,7 +98,7 @@ namespace { mSettings.mRecastScaleFactor = 0.5; - getTilesPositions(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 32, 1), mSettings, mCollect); + getTilesPositions(makeTilesPositionsRange(osg::Vec3f(0, 0, 0), osg::Vec3f(32, 32, 1), mSettings), mCollect); EXPECT_THAT(mTilesPositions, ElementsAre(TilePosition(0, 0))); } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 89b27b0d94..ae06f3f2b0 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -208,6 +208,7 @@ add_component_dir(detournavigator serialization navmeshdbutils recast + gettilespositions ) add_component_dir(loadinglistener diff --git a/components/detournavigator/gettilespositions.cpp b/components/detournavigator/gettilespositions.cpp new file mode 100644 index 0000000000..d427eb3e12 --- /dev/null +++ b/components/detournavigator/gettilespositions.cpp @@ -0,0 +1,62 @@ +#include "gettilespositions.hpp" +#include "settings.hpp" +#include "settingsutils.hpp" +#include "tileposition.hpp" + +#include + +#include + +namespace DetourNavigator +{ + TilesPositionsRange makeTilesPositionsRange(const osg::Vec3f& aabbMin, const osg::Vec3f& aabbMax, + const RecastSettings& settings) + { + osg::Vec3f min = toNavMeshCoordinates(settings, aabbMin); + osg::Vec3f max = toNavMeshCoordinates(settings, aabbMax); + + const float border = getBorderSize(settings); + min -= osg::Vec3f(border, border, border); + max += osg::Vec3f(border, border, border); + + TilePosition minTile = getTilePosition(settings, min); + TilePosition maxTile = getTilePosition(settings, max); + + if (minTile.x() > maxTile.x()) + std::swap(minTile.x(), maxTile.x()); + + if (minTile.y() > maxTile.y()) + std::swap(minTile.y(), maxTile.y()); + + return {minTile, maxTile}; + } + + TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape, const btTransform& transform, + const RecastSettings& settings) + { + btVector3 aabbMin; + btVector3 aabbMax; + shape.getAabb(transform, aabbMin, aabbMax); + + return makeTilesPositionsRange(Misc::Convert::toOsg(aabbMin), Misc::Convert::toOsg(aabbMax), settings); + } + + TilesPositionsRange makeTilesPositionsRange(const int cellSize, const btVector3& shift, + const RecastSettings& settings) + { + using Misc::Convert::toOsg; + + const int halfCellSize = cellSize / 2; + const btTransform transform(btMatrix3x3::getIdentity(), shift); + btVector3 aabbMin = transform(btVector3(-halfCellSize, -halfCellSize, 0)); + btVector3 aabbMax = transform(btVector3(halfCellSize, halfCellSize, 0)); + + aabbMin.setX(std::min(aabbMin.x(), aabbMax.x())); + aabbMin.setY(std::min(aabbMin.y(), aabbMax.y())); + + aabbMax.setX(std::max(aabbMin.x(), aabbMax.x())); + aabbMax.setY(std::max(aabbMin.y(), aabbMax.y())); + + return makeTilesPositionsRange(toOsg(aabbMin), toOsg(aabbMax), settings); + } +} diff --git a/components/detournavigator/gettilespositions.hpp b/components/detournavigator/gettilespositions.hpp index 707db0b512..946f3e64f2 100644 --- a/components/detournavigator/gettilespositions.hpp +++ b/components/detournavigator/gettilespositions.hpp @@ -1,73 +1,43 @@ #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_GETTILESPOSITIONS_H -#include "settings.hpp" -#include "settingsutils.hpp" #include "tileposition.hpp" -#include +class btVector3; +class btTransform; +class btCollisionShape; -#include - -#include +namespace osg +{ + class Vec3f; +} namespace DetourNavigator { - template - void getTilesPositions(const osg::Vec3f& aabbMin, const osg::Vec3f& aabbMax, - const RecastSettings& settings, Callback&& callback) + struct RecastSettings; + + struct TilesPositionsRange { - auto min = toNavMeshCoordinates(settings, aabbMin); - auto max = toNavMeshCoordinates(settings, aabbMax); + TilePosition mMin; + TilePosition mMax; + }; - const auto border = getBorderSize(settings); - min -= osg::Vec3f(border, border, border); - max += osg::Vec3f(border, border, border); + TilesPositionsRange makeTilesPositionsRange(const osg::Vec3f& aabbMin, + const osg::Vec3f& aabbMax, const RecastSettings& settings); - auto minTile = getTilePosition(settings, min); - auto maxTile = getTilePosition(settings, max); + TilesPositionsRange makeTilesPositionsRange(const btCollisionShape& shape, + const btTransform& transform, const RecastSettings& settings); - if (minTile.x() > maxTile.x()) - std::swap(minTile.x(), maxTile.x()); + TilesPositionsRange makeTilesPositionsRange(const int cellSize, const btVector3& shift, + const RecastSettings& settings); - if (minTile.y() > maxTile.y()) - std::swap(minTile.y(), maxTile.y()); - - for (int tileX = minTile.x(); tileX <= maxTile.x(); ++tileX) - for (int tileY = minTile.y(); tileY <= maxTile.y(); ++tileY) + template + void getTilesPositions(const TilesPositionsRange& range, Callback&& callback) + { + for (int tileX = range.mMin.x(); tileX <= range.mMax.x(); ++tileX) + for (int tileY = range.mMin.y(); tileY <= range.mMax.y(); ++tileY) callback(TilePosition {tileX, tileY}); } - - template - void getTilesPositions(const btCollisionShape& shape, const btTransform& transform, - const RecastSettings& settings, Callback&& callback) - { - btVector3 aabbMin; - btVector3 aabbMax; - shape.getAabb(transform, aabbMin, aabbMax); - - getTilesPositions(Misc::Convert::toOsg(aabbMin), Misc::Convert::toOsg(aabbMax), settings, std::forward(callback)); - } - - template - void getTilesPositions(const int cellSize, const btVector3& shift, - const RecastSettings& settings, Callback&& callback) - { - using Misc::Convert::toOsg; - - const auto halfCellSize = cellSize / 2; - const btTransform transform(btMatrix3x3::getIdentity(), shift); - auto aabbMin = transform(btVector3(-halfCellSize, -halfCellSize, 0)); - auto aabbMax = transform(btVector3(halfCellSize, halfCellSize, 0)); - - aabbMin.setX(std::min(aabbMin.x(), aabbMax.x())); - aabbMin.setY(std::min(aabbMin.y(), aabbMax.y())); - - aabbMax.setX(std::max(aabbMin.x(), aabbMax.x())); - aabbMax.setY(std::max(aabbMin.y(), aabbMax.y())); - - getTilesPositions(toOsg(aabbMin), toOsg(aabbMax), settings, std::forward(callback)); - } } #endif diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index 85d86e6b2b..82a156bb97 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace DetourNavigator { diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index 399af8a6a9..9fba4ad611 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -9,6 +9,7 @@ #include #include +#include #include @@ -262,7 +263,7 @@ namespace DetourNavigator void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform, const ChangeType changeType) { - getTilesPositions(shape, transform, mSettings.mRecast, + getTilesPositions(makeTilesPositionsRange(shape, transform, mSettings.mRecast), [&] (const TilePosition& v) { addChangedTile(v, changeType); }); } @@ -272,7 +273,7 @@ namespace DetourNavigator if (cellSize == std::numeric_limits::max()) return; - getTilesPositions(cellSize, shift, mSettings.mRecast, + getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings.mRecast), [&] (const TilePosition& v) { addChangedTile(v, changeType); }); } diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index bf3df92d6e..17ba7afc39 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -4,6 +4,7 @@ #include "settingsutils.hpp" #include +#include #include #include @@ -35,7 +36,8 @@ namespace DetourNavigator std::vector tilesPositions; { const std::lock_guard lock(mMutex); - getTilesPositions(shape.getShape(), transform, mSettings, [&] (const TilePosition& tilePosition) + getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mSettings), + [&] (const TilePosition& tilePosition) { if (addTile(id, shape, transform, areaType, tilePosition, mTiles)) tilesPositions.push_back(tilePosition); @@ -90,7 +92,8 @@ namespace DetourNavigator else { const btVector3 shift = Misc::Convert::toBullet(getWaterShift3d(cellPosition, cellSize, level)); - getTilesPositions(cellSize, shift, mSettings, [&] (const TilePosition& tilePosition) + getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings), + [&] (const TilePosition& tilePosition) { const std::lock_guard lock(mMutex); auto tile = mTiles.find(tilePosition); @@ -148,7 +151,8 @@ namespace DetourNavigator bool result = false; - getTilesPositions(cellSize, shift, mSettings, [&] (const TilePosition& tilePosition) + getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings), + [&] (const TilePosition& tilePosition) { const std::lock_guard lock(mMutex); auto tile = mTiles.find(tilePosition); diff --git a/components/detournavigator/tilecachedrecastmeshmanager.hpp b/components/detournavigator/tilecachedrecastmeshmanager.hpp index 23171f0925..88face24ce 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.hpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.hpp @@ -57,7 +57,7 @@ namespace DetourNavigator changed = true; } }; - getTilesPositions(shape.getShape(), transform, mSettings, onTilePosition); + getTilesPositions(makeTilesPositionsRange(shape.getShape(), transform, mSettings), onTilePosition); std::sort(newTiles.begin(), newTiles.end()); for (const auto& tile : currentTiles) { From a9ae263acd7031c6d5f16a91233cc250890c3118 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 23 Jan 2022 16:44:46 +0100 Subject: [PATCH 4/6] Reuse existing player position --- apps/openmw/mwworld/scene.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 054e26e855..5b74fe63f4 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -511,8 +511,7 @@ namespace MWWorld if (mCurrentCell == nullptr) return; - const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - mNavigator.updatePlayerPosition(player.getRefData().getPosition().asVec3()); + mNavigator.updatePlayerPosition(pos); if (!mCurrentCell->isExterior()) return; From b0ef20c30348e52c38464777db9a33ecf693f877 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 23 Jan 2022 14:47:20 +0100 Subject: [PATCH 5/6] Cull navmesh objects by scene bounds If object is too big iteration over all tiles covering it can take too much time. Limit bounds to a square around a player position to cover only tiles that will be present in navmesh based on max tiles number option. --- apps/openmw/mwworld/scene.cpp | 4 ++++ .../tilecachedrecastmeshmanager.cpp | 8 ++++++++ .../detournavigator/gettilespositions.cpp | 8 ++++++-- .../detournavigator/gettilespositions.hpp | 3 ++- components/detournavigator/navmeshmanager.cpp | 15 ++++++++++++++- components/detournavigator/settingsutils.hpp | 5 +++++ .../tilecachedrecastmeshmanager.cpp | 17 ++++++++++++++++- .../tilecachedrecastmeshmanager.hpp | 7 ++++++- 8 files changed, 61 insertions(+), 6 deletions(-) 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; From 9069e97dce21ca0adf795b74b220247bde32471e Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 23 Jan 2022 15:12:27 +0100 Subject: [PATCH 6/6] Filter out triangles with NaN coordinates Sorting a vector with such values gives invalid result because comparison with NaN is always false. --- components/detournavigator/recastmeshbuilder.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/components/detournavigator/recastmeshbuilder.cpp b/components/detournavigator/recastmeshbuilder.cpp index 0f7552aa77..08e7002cf8 100644 --- a/components/detournavigator/recastmeshbuilder.cpp +++ b/components/detournavigator/recastmeshbuilder.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace DetourNavigator { @@ -40,6 +41,16 @@ namespace DetourNavigator { return static_cast(cellSize) / (dataSize - 1); } + + bool isNan(const RecastMeshTriangle& triangle) + { + for (std::size_t i = 0; i < 3; ++i) + if (std::isnan(triangle.mVertices[i].x()) + || std::isnan(triangle.mVertices[i].y()) + || std::isnan(triangle.mVertices[i].z())) + return true; + return false; + } } Mesh makeMesh(std::vector&& triangles, const osg::Vec3f& shift) @@ -264,6 +275,7 @@ namespace DetourNavigator std::shared_ptr RecastMeshBuilder::create(std::size_t generation, std::size_t revision) && { + mTriangles.erase(std::remove_if(mTriangles.begin(), mTriangles.end(), isNan), mTriangles.end()); std::sort(mTriangles.begin(), mTriangles.end()); std::sort(mWater.begin(), mWater.end()); Mesh mesh = makeMesh(std::move(mTriangles));