1
0
Fork 1
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:
elsid 2018-07-14 15:05:28 +03:00
parent b33a291a67
commit c771986c56
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
4 changed files with 61 additions and 22 deletions

View file

@ -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");

View file

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

View file

@ -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);
}
});
}

View file

@ -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;
};