2018-03-13 22:49:08 +00:00
|
|
|
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
|
|
|
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
|
|
|
|
|
2022-06-16 22:28:44 +00:00
|
|
|
#include "agentbounds.hpp"
|
2022-02-01 00:21:47 +00:00
|
|
|
#include "changetype.hpp"
|
2022-08-11 22:09:49 +00:00
|
|
|
#include "guardednavmeshcacheitem.hpp"
|
2018-04-16 19:57:35 +00:00
|
|
|
#include "navmeshcacheitem.hpp"
|
2021-07-09 20:51:42 +00:00
|
|
|
#include "navmeshdb.hpp"
|
2018-09-30 22:33:25 +00:00
|
|
|
#include "navmeshtilescache.hpp"
|
2018-08-26 20:27:38 +00:00
|
|
|
#include "offmeshconnectionsmanager.hpp"
|
2022-08-11 22:09:49 +00:00
|
|
|
#include "sharednavmeshcacheitem.hpp"
|
2022-08-28 12:52:12 +00:00
|
|
|
#include "stats.hpp"
|
2018-04-15 22:07:18 +00:00
|
|
|
#include "tilecachedrecastmeshmanager.hpp"
|
2018-04-01 00:44:16 +00:00
|
|
|
#include "tileposition.hpp"
|
2021-05-14 19:06:29 +00:00
|
|
|
#include "waitconditiontype.hpp"
|
2018-03-13 22:49:08 +00:00
|
|
|
|
|
|
|
#include <atomic>
|
2018-04-20 22:39:21 +00:00
|
|
|
#include <chrono>
|
2018-03-13 22:49:08 +00:00
|
|
|
#include <condition_variable>
|
2021-05-14 17:57:11 +00:00
|
|
|
#include <deque>
|
2022-06-26 17:36:03 +00:00
|
|
|
#include <iosfwd>
|
2021-08-05 21:18:03 +00:00
|
|
|
#include <list>
|
2018-03-13 22:49:08 +00:00
|
|
|
#include <memory>
|
|
|
|
#include <mutex>
|
2021-05-14 17:57:11 +00:00
|
|
|
#include <optional>
|
2018-04-01 00:44:16 +00:00
|
|
|
#include <set>
|
2018-03-13 22:49:08 +00:00
|
|
|
#include <thread>
|
2021-05-14 17:57:11 +00:00
|
|
|
#include <tuple>
|
2018-03-13 22:49:08 +00:00
|
|
|
|
|
|
|
class dtNavMesh;
|
|
|
|
|
2021-05-05 16:13:17 +00:00
|
|
|
namespace Loading
|
|
|
|
{
|
|
|
|
class Listener;
|
|
|
|
}
|
|
|
|
|
2018-03-13 22:49:08 +00:00
|
|
|
namespace DetourNavigator
|
|
|
|
{
|
2021-08-05 22:05:09 +00:00
|
|
|
enum class JobState
|
|
|
|
{
|
|
|
|
Initial,
|
|
|
|
WithDbResult,
|
|
|
|
};
|
|
|
|
|
2021-08-05 21:18:03 +00:00
|
|
|
struct Job
|
|
|
|
{
|
2021-08-05 22:05:09 +00:00
|
|
|
const std::size_t mId;
|
2022-06-16 22:28:44 +00:00
|
|
|
const AgentBounds mAgentBounds;
|
2021-08-07 00:23:43 +00:00
|
|
|
const std::weak_ptr<GuardedNavMeshCacheItem> mNavMeshCacheItem;
|
2023-01-21 13:54:46 +00:00
|
|
|
const std::string mWorldspace;
|
2021-08-07 00:23:43 +00:00
|
|
|
const TilePosition mChangedTile;
|
|
|
|
const std::chrono::steady_clock::time_point mProcessTime;
|
|
|
|
unsigned mTryNumber = 0;
|
2021-08-17 10:10:22 +00:00
|
|
|
ChangeType mChangeType;
|
2021-08-05 21:18:03 +00:00
|
|
|
int mDistanceToPlayer;
|
2021-08-07 00:23:43 +00:00
|
|
|
const int mDistanceToOrigin;
|
2021-08-05 22:05:09 +00:00
|
|
|
JobState mState = JobState::Initial;
|
|
|
|
std::vector<std::byte> mInput;
|
|
|
|
std::shared_ptr<RecastMesh> mRecastMesh;
|
|
|
|
std::optional<TileData> mCachedTileData;
|
|
|
|
std::unique_ptr<PreparedNavMeshData> mGeneratedNavMeshData;
|
2021-08-07 00:23:43 +00:00
|
|
|
|
2022-06-16 22:28:44 +00:00
|
|
|
Job(const AgentBounds& agentBounds, std::weak_ptr<GuardedNavMeshCacheItem> navMeshCacheItem,
|
2023-01-21 13:54:46 +00:00
|
|
|
std::string_view worldspace, const TilePosition& changedTile, ChangeType changeType, int distanceToPlayer,
|
2021-08-07 00:23:43 +00:00
|
|
|
std::chrono::steady_clock::time_point processTime);
|
2021-08-05 21:18:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
using JobIt = std::list<Job>::iterator;
|
|
|
|
|
2021-08-05 22:05:09 +00:00
|
|
|
enum class JobStatus
|
|
|
|
{
|
|
|
|
Done,
|
|
|
|
Fail,
|
|
|
|
MemoryCacheMiss,
|
|
|
|
};
|
|
|
|
|
2022-06-26 17:36:03 +00:00
|
|
|
std::ostream& operator<<(std::ostream& stream, JobStatus value);
|
2021-08-05 22:05:09 +00:00
|
|
|
|
|
|
|
class DbJobQueue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void push(JobIt job);
|
|
|
|
|
2022-05-08 19:28:43 +00:00
|
|
|
std::optional<JobIt> pop();
|
2021-08-05 22:05:09 +00:00
|
|
|
|
|
|
|
void update(TilePosition playerTile, int maxTiles);
|
|
|
|
|
|
|
|
void stop();
|
|
|
|
|
2022-08-28 12:52:12 +00:00
|
|
|
DbJobQueueStats getStats() const;
|
2021-08-05 22:05:09 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
mutable std::mutex mMutex;
|
|
|
|
std::condition_variable mHasJob;
|
|
|
|
std::deque<JobIt> mJobs;
|
|
|
|
bool mShouldStop = false;
|
2022-08-27 11:49:49 +00:00
|
|
|
std::size_t mWritingJobs = 0;
|
|
|
|
std::size_t mReadingJobs = 0;
|
2021-08-05 22:05:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class AsyncNavMeshUpdater;
|
|
|
|
|
|
|
|
class DbWorker
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbWorker(AsyncNavMeshUpdater& updater, std::unique_ptr<NavMeshDb>&& db, TileVersion version,
|
2021-12-16 21:40:02 +00:00
|
|
|
const RecastSettings& recastSettings, bool writeToDb);
|
2021-08-05 22:05:09 +00:00
|
|
|
|
|
|
|
~DbWorker();
|
|
|
|
|
2022-08-28 12:52:12 +00:00
|
|
|
DbWorkerStats getStats() const;
|
2021-08-05 22:05:09 +00:00
|
|
|
|
|
|
|
void enqueueJob(JobIt job);
|
|
|
|
|
|
|
|
void updateJobs(TilePosition playerTile, int maxTiles) { mQueue.update(playerTile, maxTiles); }
|
|
|
|
|
|
|
|
void stop();
|
|
|
|
|
|
|
|
private:
|
|
|
|
AsyncNavMeshUpdater& mUpdater;
|
|
|
|
const RecastSettings& mRecastSettings;
|
|
|
|
const std::unique_ptr<NavMeshDb> mDb;
|
|
|
|
const TileVersion mVersion;
|
2022-03-10 17:34:35 +00:00
|
|
|
bool mWriteToDb;
|
2021-08-05 22:05:09 +00:00
|
|
|
TileId mNextTileId;
|
|
|
|
ShapeId mNextShapeId;
|
|
|
|
DbJobQueue mQueue;
|
|
|
|
std::atomic_bool mShouldStop{ false };
|
|
|
|
std::atomic_size_t mGetTileCount{ 0 };
|
|
|
|
std::thread mThread;
|
|
|
|
|
|
|
|
inline void run() noexcept;
|
|
|
|
|
|
|
|
inline void processJob(JobIt job);
|
|
|
|
|
|
|
|
inline void processReadingJob(JobIt job);
|
|
|
|
|
|
|
|
inline void processWritingJob(JobIt job);
|
|
|
|
};
|
|
|
|
|
2018-03-13 22:49:08 +00:00
|
|
|
class AsyncNavMeshUpdater
|
|
|
|
{
|
|
|
|
public:
|
2018-08-26 20:27:38 +00:00
|
|
|
AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager,
|
2021-07-09 20:51:42 +00:00
|
|
|
OffMeshConnectionsManager& offMeshConnectionsManager, std::unique_ptr<NavMeshDb>&& db);
|
2018-03-13 22:49:08 +00:00
|
|
|
~AsyncNavMeshUpdater();
|
|
|
|
|
2022-06-16 22:28:44 +00:00
|
|
|
void post(const AgentBounds& agentBounds, const SharedNavMeshCacheItem& navMeshCacheItem,
|
2023-01-21 13:54:46 +00:00
|
|
|
const TilePosition& playerTile, std::string_view worldspace,
|
2021-07-09 20:51:42 +00:00
|
|
|
const std::map<TilePosition, ChangeType>& changedTiles);
|
2018-03-13 22:49:08 +00:00
|
|
|
|
2022-09-05 07:23:14 +00:00
|
|
|
void wait(WaitConditionType waitConditionType, Loading::Listener* listener);
|
2018-03-13 22:49:08 +00:00
|
|
|
|
2022-03-10 17:34:35 +00:00
|
|
|
void stop();
|
|
|
|
|
2022-08-28 12:52:12 +00:00
|
|
|
AsyncNavMeshUpdaterStats getStats() const;
|
2021-08-05 22:05:09 +00:00
|
|
|
|
|
|
|
void enqueueJob(JobIt job);
|
|
|
|
|
|
|
|
void removeJob(JobIt job);
|
2019-03-17 17:18:53 +00:00
|
|
|
|
2018-03-13 22:49:08 +00:00
|
|
|
private:
|
|
|
|
std::reference_wrapper<const Settings> mSettings;
|
2018-04-15 22:07:18 +00:00
|
|
|
std::reference_wrapper<TileCachedRecastMeshManager> mRecastMeshManager;
|
2018-08-26 20:27:38 +00:00
|
|
|
std::reference_wrapper<OffMeshConnectionsManager> mOffMeshConnectionsManager;
|
2018-03-13 22:49:08 +00:00
|
|
|
std::atomic_bool mShouldStop;
|
2019-03-17 17:18:53 +00:00
|
|
|
mutable std::mutex mMutex;
|
2018-03-13 22:49:08 +00:00
|
|
|
std::condition_variable mHasJob;
|
|
|
|
std::condition_variable mDone;
|
2020-02-22 21:03:44 +00:00
|
|
|
std::condition_variable mProcessed;
|
2021-08-05 21:18:03 +00:00
|
|
|
std::list<Job> mJobs;
|
|
|
|
std::deque<JobIt> mWaiting;
|
2022-06-16 22:28:44 +00:00
|
|
|
std::set<std::tuple<AgentBounds, TilePosition>> mPushed;
|
2018-09-29 19:57:41 +00:00
|
|
|
Misc::ScopeGuarded<TilePosition> mPlayerTile;
|
2018-09-30 22:33:25 +00:00
|
|
|
NavMeshTilesCache mNavMeshTilesCache;
|
2022-06-16 22:28:44 +00:00
|
|
|
Misc::ScopeGuarded<std::set<std::tuple<AgentBounds, TilePosition>>> mProcessingTiles;
|
|
|
|
std::map<std::tuple<AgentBounds, TilePosition>, std::chrono::steady_clock::time_point> mLastUpdates;
|
|
|
|
std::set<std::tuple<AgentBounds, TilePosition>> mPresentTiles;
|
2018-09-22 14:49:57 +00:00
|
|
|
std::vector<std::thread> mThreads;
|
2021-08-05 22:05:09 +00:00
|
|
|
std::unique_ptr<DbWorker> mDbWorker;
|
|
|
|
std::atomic_size_t mDbGetTileHits{ 0 };
|
2018-03-13 22:49:08 +00:00
|
|
|
|
2020-10-10 10:08:27 +00:00
|
|
|
void process() noexcept;
|
2018-03-13 22:49:08 +00:00
|
|
|
|
2021-08-05 22:05:09 +00:00
|
|
|
JobStatus processJob(Job& job);
|
2018-03-13 22:49:08 +00:00
|
|
|
|
2021-08-05 22:05:09 +00:00
|
|
|
inline JobStatus processInitialJob(Job& job, GuardedNavMeshCacheItem& navMeshCacheItem);
|
|
|
|
|
|
|
|
inline JobStatus processJobWithDbResult(Job& job, GuardedNavMeshCacheItem& navMeshCacheItem);
|
|
|
|
|
|
|
|
inline JobStatus handleUpdateNavMeshStatus(UpdateNavMeshStatus status, const Job& job,
|
|
|
|
const GuardedNavMeshCacheItem& navMeshCacheItem, const RecastMesh& recastMesh);
|
2018-03-13 22:49:08 +00:00
|
|
|
|
2021-08-05 22:05:09 +00:00
|
|
|
JobIt getNextJob();
|
2019-04-08 17:14:17 +00:00
|
|
|
|
2021-08-05 21:18:03 +00:00
|
|
|
void postThreadJob(JobIt job, std::deque<JobIt>& queue);
|
2019-04-08 17:14:17 +00:00
|
|
|
|
2018-04-20 23:57:01 +00:00
|
|
|
void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
|
2018-04-04 00:20:48 +00:00
|
|
|
|
2023-07-20 19:09:47 +00:00
|
|
|
bool lockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile);
|
2019-04-08 17:14:17 +00:00
|
|
|
|
2023-07-20 19:09:47 +00:00
|
|
|
void unlockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile);
|
2020-02-22 20:13:08 +00:00
|
|
|
|
2021-05-05 16:13:17 +00:00
|
|
|
inline std::size_t getTotalJobs() const;
|
|
|
|
|
2020-02-20 23:05:50 +00:00
|
|
|
void cleanupLastUpdates();
|
2021-05-05 16:13:17 +00:00
|
|
|
|
2022-09-05 07:23:14 +00:00
|
|
|
inline void waitUntilJobsDoneForNotPresentTiles(Loading::Listener* listener);
|
2021-05-14 19:06:29 +00:00
|
|
|
|
2021-09-18 13:52:03 +00:00
|
|
|
inline void waitUntilAllJobsDone();
|
2018-03-13 22:49:08 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|