#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H #include "recastmesh.hpp" #include "sharednavmesh.hpp" #include "tileposition.hpp" #include #include #include #include #include #include #include #include #include #include class dtNavMesh; namespace DetourNavigator { struct NavMeshCacheItem { SharedNavMesh mValue; std::size_t mRecastMeshRevision; std::atomic_size_t mNavMeshRevision; NavMeshCacheItem(const NavMeshPtr& value, std::size_t revision) : mValue(value), mRecastMeshRevision(revision), mNavMeshRevision(0) {} }; class AsyncNavMeshUpdater { public: AsyncNavMeshUpdater(const Settings& settings); ~AsyncNavMeshUpdater(); void post(const osg::Vec3f& agentHalfExtents, const std::shared_ptr& recastMesh, const std::shared_ptr& navMeshCacheItem, const TilePosition& playerTile, const std::set& changedTiles); void wait(); private: struct Job { osg::Vec3f mAgentHalfExtents; std::shared_ptr mNavMeshCacheItem; TilePosition mChangedTile; std::pair mPriority; friend inline bool operator <(const Job& lhs, const Job& rhs) { return lhs.mPriority > rhs.mPriority; } }; using Jobs = std::priority_queue>; std::reference_wrapper mSettings; std::atomic_bool mShouldStop; std::mutex mMutex; std::condition_variable mHasJob; std::condition_variable mDone; Jobs mJobs; std::mutex mRecastMeshMutex; std::shared_ptr mRecastMesh; std::thread mThread; void process() throw(); void processJob(const Job& job); boost::optional getNextJob(); void notifyHasJob(); void writeDebugFiles(const Job& job, const RecastMesh& recastMesh) const; std::shared_ptr getRecastMesh(); void setRecastMesh(const std::shared_ptr& value); }; } #endif