1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-08 09:37:53 +00:00
OpenMW/components/detournavigator/asyncnavmeshupdater.hpp
elsid c771986c56
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.
2018-10-13 22:16:31 +03:00

94 lines
2.5 KiB
C++

#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
#include "navmeshcacheitem.hpp"
#include "tilecachedrecastmeshmanager.hpp"
#include "tileposition.hpp"
#include <osg/Vec3f>
#include <boost/optional.hpp>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
#include <set>
#include <thread>
class dtNavMesh;
namespace DetourNavigator
{
enum class ChangeType
{
remove = 0,
mixed = 1,
add = 2,
};
class AsyncNavMeshUpdater
{
public:
AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager);
~AsyncNavMeshUpdater();
void post(const osg::Vec3f& agentHalfExtents, const std::shared_ptr<NavMeshCacheItem>& mNavMeshCacheItem,
const TilePosition& playerTile, const std::map<TilePosition, ChangeType>& changedTiles);
void wait();
private:
struct Job
{
osg::Vec3f mAgentHalfExtents;
std::shared_ptr<NavMeshCacheItem> mNavMeshCacheItem;
TilePosition mChangedTile;
std::tuple<ChangeType, int, int> mPriority;
friend inline bool operator <(const Job& lhs, const Job& rhs)
{
return lhs.mPriority > rhs.mPriority;
}
};
using Jobs = std::priority_queue<Job, std::deque<Job>>;
std::reference_wrapper<const Settings> mSettings;
std::reference_wrapper<TileCachedRecastMeshManager> mRecastMeshManager;
std::atomic_bool mShouldStop;
std::mutex mMutex;
std::condition_variable mHasJob;
std::condition_variable mDone;
Jobs mJobs;
std::map<osg::Vec3f, std::set<TilePosition>> mPushed;
std::mutex mPlayerTileMutex;
TilePosition mPlayerTile;
std::mutex mFirstStartMutex;
boost::optional<std::chrono::steady_clock::time_point> mFirstStart;
std::thread mThread;
void process() throw();
void processJob(const Job& job);
boost::optional<Job> getNextJob();
void notifyHasJob();
void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
std::chrono::steady_clock::time_point getFirstStart();
void setFirstStart(const std::chrono::steady_clock::time_point& value);
TilePosition getPlayerTile();
void setPlayerTile(const TilePosition& value);
};
}
#endif