From c68cecb1ebc7151e06b91ae5f3263e42c6cf24dd Mon Sep 17 00:00:00 2001 From: psi29a Date: Mon, 28 Jun 2021 10:44:43 +0000 Subject: [PATCH] Merge branch 'optimize_off_mesh_connections' into 'master' Optimize off mesh connections See merge request OpenMW/openmw!969 (cherry picked from commit 9dcea247d2cd7d25d719fabc142cef5360233e2a) 3e98db8d Fix styleguide 7f65a2c4 Remove unused code 81e569c3 Move OffMeshConnectionsManager implementation into cpp a8ba9a0e Cleanup unused tile positions from OffMeshConnectionsManager ff1af5e8 Use only off mesh connections starting or ending in a given tile 1552e7e3 Add pathgrid edges as one direction off mesh connection --- components/CMakeLists.txt | 1 + components/detournavigator/makenavmesh.cpp | 2 +- components/detournavigator/navigatorimpl.cpp | 10 +- .../offmeshconnectionsmanager.cpp | 95 +++++++++++++++++++ .../offmeshconnectionsmanager.hpp | 80 +--------------- 5 files changed, 105 insertions(+), 83 deletions(-) create mode 100644 components/detournavigator/offmeshconnectionsmanager.cpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 06ae0791d..7860f492c 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -183,6 +183,7 @@ add_component_dir(detournavigator raycast navmeshtileview oscillatingrecastmeshobject + offmeshconnectionsmanager ) set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index bcfd1b22f..422fdffb1 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -389,7 +389,7 @@ namespace const auto offMeshConVerts = getOffMeshVerts(offMeshConnections); const std::vector offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents)); - const std::vector offMeshConDir(offMeshConnections.size(), DT_OFFMESH_CON_BIDIR); + const std::vector offMeshConDir(offMeshConnections.size(), 0); const std::vector offMeshConAreas = getOffMeshConAreas(offMeshConnections); const std::vector offMeshConFlags = getOffMeshFlags(offMeshConnections); diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index b7b3bbd58..1aa4768de 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -55,12 +55,10 @@ namespace DetourNavigator { if (addObject(id, static_cast(shapes), transform)) { - mNavMeshManager.addOffMeshConnection( - id, - toNavMeshCoordinates(mSettings, shapes.mConnectionStart), - toNavMeshCoordinates(mSettings, shapes.mConnectionEnd), - AreaType_door - ); + const osg::Vec3f start = toNavMeshCoordinates(mSettings, shapes.mConnectionStart); + const osg::Vec3f end = toNavMeshCoordinates(mSettings, shapes.mConnectionEnd); + mNavMeshManager.addOffMeshConnection(id, start, end, AreaType_door); + mNavMeshManager.addOffMeshConnection(id, end, start, AreaType_door); return true; } return false; diff --git a/components/detournavigator/offmeshconnectionsmanager.cpp b/components/detournavigator/offmeshconnectionsmanager.cpp new file mode 100644 index 000000000..a673ae3e6 --- /dev/null +++ b/components/detournavigator/offmeshconnectionsmanager.cpp @@ -0,0 +1,95 @@ +#include "offmeshconnectionsmanager.hpp" +#include "settings.hpp" +#include "settingsutils.hpp" +#include "tileposition.hpp" +#include "objectid.hpp" +#include "offmeshconnection.hpp" + +#include +#include +#include + +namespace DetourNavigator +{ + OffMeshConnectionsManager::OffMeshConnectionsManager(const Settings& settings) + : mSettings(settings) + {} + + void OffMeshConnectionsManager::add(const ObjectId id, const OffMeshConnection& value) + { + const auto values = mValues.lock(); + + values->mById.insert(std::make_pair(id, value)); + + const auto startTilePosition = getTilePosition(mSettings, value.mStart); + const auto endTilePosition = getTilePosition(mSettings, value.mEnd); + + values->mByTilePosition[startTilePosition].insert(id); + + if (startTilePosition != endTilePosition) + values->mByTilePosition[endTilePosition].insert(id); + } + + std::set OffMeshConnectionsManager::remove(const ObjectId id) + { + const auto values = mValues.lock(); + + const auto byId = values->mById.equal_range(id); + + if (byId.first == byId.second) + return {}; + + std::set removed; + + std::for_each(byId.first, byId.second, [&] (const auto& v) { + const auto startTilePosition = getTilePosition(mSettings, v.second.mStart); + const auto endTilePosition = getTilePosition(mSettings, v.second.mEnd); + + removed.emplace(startTilePosition); + if (startTilePosition != endTilePosition) + removed.emplace(endTilePosition); + }); + + for (const TilePosition& tilePosition : removed) + { + const auto it = values->mByTilePosition.find(tilePosition); + if (it == values->mByTilePosition.end()) + continue; + it->second.erase(id); + if (it->second.empty()) + values->mByTilePosition.erase(it); + } + + values->mById.erase(byId.first, byId.second); + + return removed; + } + + std::vector OffMeshConnectionsManager::get(const TilePosition& tilePosition) + { + std::vector result; + + const auto values = mValues.lock(); + + const auto itByTilePosition = values->mByTilePosition.find(tilePosition); + + if (itByTilePosition == values->mByTilePosition.end()) + return result; + + std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(), + [&] (const ObjectId v) + { + const auto byId = values->mById.equal_range(v); + std::for_each(byId.first, byId.second, [&] (const auto& v) + { + if (getTilePosition(mSettings, v.second.mStart) == tilePosition + || getTilePosition(mSettings, v.second.mEnd) == tilePosition) + result.push_back(v.second); + }); + }); + + std::sort(result.begin(), result.end()); + + return result; + } +} diff --git a/components/detournavigator/offmeshconnectionsmanager.hpp b/components/detournavigator/offmeshconnectionsmanager.hpp index 1ad96e3b9..20a6427cd 100644 --- a/components/detournavigator/offmeshconnectionsmanager.hpp +++ b/components/detournavigator/offmeshconnectionsmanager.hpp @@ -2,16 +2,12 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTIONSMANAGER_H #include "settings.hpp" -#include "settingsutils.hpp" #include "tileposition.hpp" #include "objectid.hpp" #include "offmeshconnection.hpp" #include -#include - -#include #include #include #include @@ -22,73 +18,13 @@ namespace DetourNavigator class OffMeshConnectionsManager { public: - OffMeshConnectionsManager(const Settings& settings) - : mSettings(settings) - {} + OffMeshConnectionsManager(const Settings& settings); - void add(const ObjectId id, const OffMeshConnection& value) - { - const auto values = mValues.lock(); + void add(const ObjectId id, const OffMeshConnection& value); - values->mById.insert(std::make_pair(id, value)); + std::set remove(const ObjectId id); - const auto startTilePosition = getTilePosition(mSettings, value.mStart); - const auto endTilePosition = getTilePosition(mSettings, value.mEnd); - - values->mByTilePosition[startTilePosition].insert(id); - - if (startTilePosition != endTilePosition) - values->mByTilePosition[endTilePosition].insert(id); - } - - std::set remove(const ObjectId id) - { - const auto values = mValues.lock(); - - const auto byId = values->mById.equal_range(id); - - if (byId.first == byId.second) { - return {}; - } - - std::set removed; - - std::for_each(byId.first, byId.second, [&] (const auto& v) { - const auto startTilePosition = getTilePosition(mSettings, v.second.mStart); - const auto endTilePosition = getTilePosition(mSettings, v.second.mEnd); - - removed.emplace(startTilePosition); - if (startTilePosition != endTilePosition) - removed.emplace(endTilePosition); - }); - - values->mById.erase(byId.first, byId.second); - - return removed; - } - - std::vector get(const TilePosition& tilePosition) - { - std::vector result; - - const auto values = mValues.lock(); - - const auto itByTilePosition = values->mByTilePosition.find(tilePosition); - - if (itByTilePosition == values->mByTilePosition.end()) - return result; - - std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(), - [&] (const ObjectId v) - { - const auto byId = values->mById.equal_range(v); - std::for_each(byId.first, byId.second, [&] (const auto& v) { result.push_back(v.second); }); - }); - - std::sort(result.begin(), result.end()); - - return result; - } + std::vector get(const TilePosition& tilePosition); private: struct Values @@ -99,14 +35,6 @@ namespace DetourNavigator const Settings& mSettings; Misc::ScopeGuarded mValues; - - void removeByTilePosition(std::map>& valuesByTilePosition, - const TilePosition& tilePosition, const ObjectId id) - { - const auto it = valuesByTilePosition.find(tilePosition); - if (it != valuesByTilePosition.end()) - it->second.erase(id); - } }; }