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) {