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
pull/593/head
psi29a 4 years ago
parent 0394f848cd
commit c68cecb1eb

@ -183,6 +183,7 @@ add_component_dir(detournavigator
raycast raycast
navmeshtileview navmeshtileview
oscillatingrecastmeshobject oscillatingrecastmeshobject
offmeshconnectionsmanager
) )
set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui

@ -389,7 +389,7 @@ namespace
const auto offMeshConVerts = getOffMeshVerts(offMeshConnections); const auto offMeshConVerts = getOffMeshVerts(offMeshConnections);
const std::vector<float> offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents)); const std::vector<float> offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents));
const std::vector<unsigned char> offMeshConDir(offMeshConnections.size(), DT_OFFMESH_CON_BIDIR); const std::vector<unsigned char> offMeshConDir(offMeshConnections.size(), 0);
const std::vector<unsigned char> offMeshConAreas = getOffMeshConAreas(offMeshConnections); const std::vector<unsigned char> offMeshConAreas = getOffMeshConAreas(offMeshConnections);
const std::vector<unsigned short> offMeshConFlags = getOffMeshFlags(offMeshConnections); const std::vector<unsigned short> offMeshConFlags = getOffMeshFlags(offMeshConnections);

@ -55,12 +55,10 @@ namespace DetourNavigator
{ {
if (addObject(id, static_cast<const ObjectShapes&>(shapes), transform)) if (addObject(id, static_cast<const ObjectShapes&>(shapes), transform))
{ {
mNavMeshManager.addOffMeshConnection( const osg::Vec3f start = toNavMeshCoordinates(mSettings, shapes.mConnectionStart);
id, const osg::Vec3f end = toNavMeshCoordinates(mSettings, shapes.mConnectionEnd);
toNavMeshCoordinates(mSettings, shapes.mConnectionStart), mNavMeshManager.addOffMeshConnection(id, start, end, AreaType_door);
toNavMeshCoordinates(mSettings, shapes.mConnectionEnd), mNavMeshManager.addOffMeshConnection(id, end, start, AreaType_door);
AreaType_door
);
return true; return true;
} }
return false; return false;

@ -0,0 +1,95 @@
#include "offmeshconnectionsmanager.hpp"
#include "settings.hpp"
#include "settingsutils.hpp"
#include "tileposition.hpp"
#include "objectid.hpp"
#include "offmeshconnection.hpp"
#include <algorithm>
#include <vector>
#include <set>
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<TilePosition> 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<TilePosition> 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<OffMeshConnection> OffMeshConnectionsManager::get(const TilePosition& tilePosition)
{
std::vector<OffMeshConnection> 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;
}
}

@ -2,16 +2,12 @@
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTIONSMANAGER_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTIONSMANAGER_H
#include "settings.hpp" #include "settings.hpp"
#include "settingsutils.hpp"
#include "tileposition.hpp" #include "tileposition.hpp"
#include "objectid.hpp" #include "objectid.hpp"
#include "offmeshconnection.hpp" #include "offmeshconnection.hpp"
#include <components/misc/guarded.hpp> #include <components/misc/guarded.hpp>
#include <osg/Vec3f>
#include <algorithm>
#include <map> #include <map>
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
@ -22,73 +18,13 @@ namespace DetourNavigator
class OffMeshConnectionsManager class OffMeshConnectionsManager
{ {
public: public:
OffMeshConnectionsManager(const Settings& settings) OffMeshConnectionsManager(const Settings& settings);
: mSettings(settings)
{}
void 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<TilePosition> 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<TilePosition> removed;
std::for_each(byId.first, byId.second, [&] (const auto& v) { void add(const ObjectId id, const OffMeshConnection& value);
const auto startTilePosition = getTilePosition(mSettings, v.second.mStart);
const auto endTilePosition = getTilePosition(mSettings, v.second.mEnd);
removed.emplace(startTilePosition); std::set<TilePosition> remove(const ObjectId id);
if (startTilePosition != endTilePosition)
removed.emplace(endTilePosition);
});
values->mById.erase(byId.first, byId.second); std::vector<OffMeshConnection> get(const TilePosition& tilePosition);
return removed;
}
std::vector<OffMeshConnection> get(const TilePosition& tilePosition)
{
std::vector<OffMeshConnection> 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;
}
private: private:
struct Values struct Values
@ -99,14 +35,6 @@ namespace DetourNavigator
const Settings& mSettings; const Settings& mSettings;
Misc::ScopeGuarded<Values> mValues; Misc::ScopeGuarded<Values> mValues;
void removeByTilePosition(std::map<TilePosition, std::unordered_set<ObjectId>>& valuesByTilePosition,
const TilePosition& tilePosition, const ObjectId id)
{
const auto it = valuesByTilePosition.find(tilePosition);
if (it != valuesByTilePosition.end())
it->second.erase(id);
}
}; };
} }

Loading…
Cancel
Save