mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-20 18:39:39 +00:00
Prioritise NavMesh jobs first to remove and last to add
When player move fast enough, tiles update for specific area square couldn't catch player move. Tiles to be removed are left in the queue with lower priority then tiles to be added which are nearest to player. This can lead to overflow for amount of tiles. So we try to do remove first. But we detect change type approximately using mixed change type, because even if we do it precise, change type could change while job is in queue.
This commit is contained in:
parent
b33a291a67
commit
c771986c56
4 changed files with 61 additions and 22 deletions
|
@ -9,16 +9,22 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
using DetourNavigator::ChangeType;
|
||||
using DetourNavigator::TilePosition;
|
||||
|
||||
int getDistance(const TilePosition& lhs, const TilePosition& rhs)
|
||||
int getManhattanDistance(const TilePosition& lhs, const TilePosition& rhs)
|
||||
{
|
||||
return std::abs(lhs.x() - rhs.x()) + std::abs(lhs.y() - rhs.y());
|
||||
}
|
||||
|
||||
std::pair<int, int> makePriority(const TilePosition& changedTile, const TilePosition& playerTile)
|
||||
std::tuple<ChangeType, int, int> makePriority(const TilePosition& position, const ChangeType changeType,
|
||||
const TilePosition& playerTile)
|
||||
{
|
||||
return std::make_pair(getDistance(changedTile, playerTile), getDistance(changedTile, TilePosition {0, 0}));
|
||||
return std::make_tuple(
|
||||
changeType,
|
||||
getManhattanDistance(position, playerTile),
|
||||
getManhattanDistance(position, TilePosition {0, 0})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +66,7 @@ namespace DetourNavigator
|
|||
|
||||
void AsyncNavMeshUpdater::post(const osg::Vec3f& agentHalfExtents,
|
||||
const std::shared_ptr<NavMeshCacheItem>& navMeshCacheItem, const TilePosition& playerTile,
|
||||
const std::set<TilePosition>& changedTiles)
|
||||
const std::map<TilePosition, ChangeType>& changedTiles)
|
||||
{
|
||||
log("post jobs playerTile=", playerTile);
|
||||
|
||||
|
@ -73,9 +79,9 @@ namespace DetourNavigator
|
|||
|
||||
for (const auto& changedTile : changedTiles)
|
||||
{
|
||||
if (mPushed[agentHalfExtents].insert(changedTile).second)
|
||||
mJobs.push(Job {agentHalfExtents, navMeshCacheItem, changedTile,
|
||||
makePriority(changedTile, playerTile)});
|
||||
if (mPushed[agentHalfExtents].insert(changedTile.first).second)
|
||||
mJobs.push(Job {agentHalfExtents, navMeshCacheItem, changedTile.first,
|
||||
makePriority(changedTile.first, changedTile.second, playerTile)});
|
||||
}
|
||||
|
||||
log("posted ", mJobs.size(), " jobs");
|
||||
|
|
|
@ -22,6 +22,13 @@ class dtNavMesh;
|
|||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
enum class ChangeType
|
||||
{
|
||||
remove = 0,
|
||||
mixed = 1,
|
||||
add = 2,
|
||||
};
|
||||
|
||||
class AsyncNavMeshUpdater
|
||||
{
|
||||
public:
|
||||
|
@ -29,7 +36,7 @@ namespace DetourNavigator
|
|||
~AsyncNavMeshUpdater();
|
||||
|
||||
void post(const osg::Vec3f& agentHalfExtents, const std::shared_ptr<NavMeshCacheItem>& mNavMeshCacheItem,
|
||||
const TilePosition& playerTile, const std::set<TilePosition>& changedTiles);
|
||||
const TilePosition& playerTile, const std::map<TilePosition, ChangeType>& changedTiles);
|
||||
|
||||
void wait();
|
||||
|
||||
|
@ -39,7 +46,7 @@ namespace DetourNavigator
|
|||
osg::Vec3f mAgentHalfExtents;
|
||||
std::shared_ptr<NavMeshCacheItem> mNavMeshCacheItem;
|
||||
TilePosition mChangedTile;
|
||||
std::pair<int, int> mPriority;
|
||||
std::tuple<ChangeType, int, int> mPriority;
|
||||
|
||||
friend inline bool operator <(const Job& lhs, const Job& rhs)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,16 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
using DetourNavigator::ChangeType;
|
||||
|
||||
ChangeType addChangeType(const ChangeType current, const ChangeType add)
|
||||
{
|
||||
return current == add ? current : ChangeType::mixed;
|
||||
}
|
||||
}
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
NavMeshManager::NavMeshManager(const Settings& settings)
|
||||
|
@ -26,7 +36,7 @@ namespace DetourNavigator
|
|||
{
|
||||
if (!mRecastMeshManager.addObject(id, shape, transform))
|
||||
return false;
|
||||
addChangedTiles(shape, transform);
|
||||
addChangedTiles(shape, transform, ChangeType::add);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -34,7 +44,7 @@ namespace DetourNavigator
|
|||
{
|
||||
if (!mRecastMeshManager.updateObject(id, transform))
|
||||
return false;
|
||||
addChangedTiles(shape, transform);
|
||||
addChangedTiles(shape, transform, ChangeType::mixed);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -43,7 +53,7 @@ namespace DetourNavigator
|
|||
const auto object = mRecastMeshManager.removeObject(id);
|
||||
if (!object)
|
||||
return false;
|
||||
addChangedTiles(object->mShape, object->mTransform);
|
||||
addChangedTiles(object->mShape, object->mTransform, ChangeType::remove);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -72,7 +82,7 @@ namespace DetourNavigator
|
|||
return;
|
||||
mLastRecastMeshManagerRevision = mRecastMeshManager.getRevision();
|
||||
mPlayerTile = playerTile;
|
||||
std::set<TilePosition> tilesToPost;
|
||||
std::map<TilePosition, ChangeType> tilesToPost;
|
||||
const auto& cached = getCached(agentHalfExtents);
|
||||
const auto changedTiles = mChangedTiles.find(agentHalfExtents);
|
||||
{
|
||||
|
@ -80,10 +90,16 @@ namespace DetourNavigator
|
|||
if (changedTiles != mChangedTiles.end())
|
||||
{
|
||||
for (const auto& tile : changedTiles->second)
|
||||
if (locked->getTileAt(tile.x(), tile.y(), 0))
|
||||
tilesToPost.insert(tile);
|
||||
if (locked->getTileAt(tile.first.x(), tile.first.y(), 0))
|
||||
{
|
||||
auto tileToPost = tilesToPost.find(tile.first);
|
||||
if (tileToPost == tilesToPost.end())
|
||||
tilesToPost.insert(tile);
|
||||
else
|
||||
tileToPost->second = addChangeType(tileToPost->second, tile.second);
|
||||
}
|
||||
for (const auto& tile : tilesToPost)
|
||||
changedTiles->second.erase(tile);
|
||||
changedTiles->second.erase(tile.first);
|
||||
if (changedTiles->second.empty())
|
||||
mChangedTiles.erase(changedTiles);
|
||||
}
|
||||
|
@ -94,8 +110,10 @@ namespace DetourNavigator
|
|||
return;
|
||||
const auto shouldAdd = shouldAddTile(tile, playerTile, maxTiles);
|
||||
const auto presentInNavMesh = bool(locked->getTileAt(tile.x(), tile.y(), 0));
|
||||
if ((shouldAdd && !presentInNavMesh) || (!shouldAdd && presentInNavMesh))
|
||||
tilesToPost.insert(tile);
|
||||
if (shouldAdd && !presentInNavMesh)
|
||||
tilesToPost.insert(std::make_pair(tile, ChangeType::add));
|
||||
else if (!shouldAdd && presentInNavMesh)
|
||||
tilesToPost.insert(std::make_pair(tile, ChangeType::mixed));
|
||||
});
|
||||
}
|
||||
mAsyncNavMeshUpdater.post(agentHalfExtents, cached, playerTile, tilesToPost);
|
||||
|
@ -120,12 +138,20 @@ namespace DetourNavigator
|
|||
return mCache;
|
||||
}
|
||||
|
||||
void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform)
|
||||
void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform,
|
||||
const ChangeType changeType)
|
||||
{
|
||||
getTilesPositions(shape, transform, mSettings, [&] (const TilePosition& v) {
|
||||
for (const auto& cached : mCache)
|
||||
if (cached.second)
|
||||
mChangedTiles[cached.first].insert(v);
|
||||
{
|
||||
auto& tiles = mChangedTiles[cached.first];
|
||||
auto tile = tiles.find(v);
|
||||
if (tile == tiles.end())
|
||||
tiles.insert(std::make_pair(v, changeType));
|
||||
else
|
||||
tile->second = addChangeType(tile->second, changeType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -45,13 +45,13 @@ namespace DetourNavigator
|
|||
const Settings& mSettings;
|
||||
TileCachedRecastMeshManager mRecastMeshManager;
|
||||
std::map<osg::Vec3f, std::shared_ptr<NavMeshCacheItem>> mCache;
|
||||
std::map<osg::Vec3f, std::set<TilePosition>> mChangedTiles;
|
||||
std::map<osg::Vec3f, std::map<TilePosition, ChangeType>> mChangedTiles;
|
||||
AsyncNavMeshUpdater mAsyncNavMeshUpdater;
|
||||
std::size_t mGenerationCounter = 0;
|
||||
boost::optional<TilePosition> mPlayerTile;
|
||||
std::size_t mLastRecastMeshManagerRevision = 0;
|
||||
|
||||
void addChangedTiles(const btCollisionShape& shape, const btTransform& transform);
|
||||
void addChangedTiles(const btCollisionShape& shape, const btTransform& transform, const ChangeType changeType);
|
||||
|
||||
const std::shared_ptr<NavMeshCacheItem>& getCached(const osg::Vec3f& agentHalfExtents) const;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue