2018-03-13 22:49:08 +00:00
|
|
|
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
|
|
|
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
|
|
|
|
|
2018-04-16 19:57:35 +00:00
|
|
|
#include "navmeshcacheitem.hpp"
|
2018-08-26 20:27:38 +00:00
|
|
|
#include "offmeshconnectionsmanager.hpp"
|
2018-04-15 22:07:18 +00:00
|
|
|
#include "tilecachedrecastmeshmanager.hpp"
|
2018-04-01 00:44:16 +00:00
|
|
|
#include "tileposition.hpp"
|
2018-09-30 22:33:25 +00:00
|
|
|
#include "navmeshtilescache.hpp"
|
2018-03-13 22:49:08 +00:00
|
|
|
|
|
|
|
#include <osg/Vec3f>
|
|
|
|
|
|
|
|
#include <boost/optional.hpp>
|
|
|
|
|
|
|
|
#include <atomic>
|
2018-04-20 22:39:21 +00:00
|
|
|
#include <chrono>
|
2018-03-13 22:49:08 +00:00
|
|
|
#include <condition_variable>
|
|
|
|
#include <memory>
|
|
|
|
#include <mutex>
|
2018-04-01 17:24:02 +00:00
|
|
|
#include <queue>
|
2018-04-01 00:44:16 +00:00
|
|
|
#include <set>
|
2018-03-13 22:49:08 +00:00
|
|
|
#include <thread>
|
|
|
|
|
|
|
|
class dtNavMesh;
|
|
|
|
|
|
|
|
namespace DetourNavigator
|
|
|
|
{
|
2018-07-14 12:05:28 +00:00
|
|
|
enum class ChangeType
|
|
|
|
{
|
|
|
|
remove = 0,
|
|
|
|
mixed = 1,
|
|
|
|
add = 2,
|
2018-11-03 13:41:36 +00:00
|
|
|
update = 3,
|
2018-07-14 12:05:28 +00:00
|
|
|
};
|
|
|
|
|
2020-02-20 23:05:50 +00:00
|
|
|
inline std::ostream& operator <<(std::ostream& stream, ChangeType value)
|
|
|
|
{
|
|
|
|
switch (value) {
|
|
|
|
case ChangeType::remove:
|
|
|
|
return stream << "ChangeType::remove";
|
|
|
|
case ChangeType::mixed:
|
|
|
|
return stream << "ChangeType::mixed";
|
|
|
|
case ChangeType::add:
|
|
|
|
return stream << "ChangeType::add";
|
|
|
|
case ChangeType::update:
|
|
|
|
return stream << "ChangeType::update";
|
|
|
|
}
|
|
|
|
return stream << "ChangeType::" << static_cast<int>(value);
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
OffMeshConnectionsManager& offMeshConnectionsManager);
|
2018-03-13 22:49:08 +00:00
|
|
|
~AsyncNavMeshUpdater();
|
|
|
|
|
2018-09-30 22:33:25 +00:00
|
|
|
void post(const osg::Vec3f& agentHalfExtents, const SharedNavMeshCacheItem& mNavMeshCacheItem,
|
2018-07-14 12:05:28 +00:00
|
|
|
const TilePosition& playerTile, const std::map<TilePosition, ChangeType>& changedTiles);
|
2018-03-13 22:49:08 +00:00
|
|
|
|
|
|
|
void wait();
|
|
|
|
|
2019-03-17 17:18:53 +00:00
|
|
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
|
|
|
|
2018-03-13 22:49:08 +00:00
|
|
|
private:
|
|
|
|
struct Job
|
|
|
|
{
|
|
|
|
osg::Vec3f mAgentHalfExtents;
|
2019-03-10 13:04:44 +00:00
|
|
|
std::weak_ptr<GuardedNavMeshCacheItem> mNavMeshCacheItem;
|
2018-04-01 17:24:02 +00:00
|
|
|
TilePosition mChangedTile;
|
2019-03-08 12:28:32 +00:00
|
|
|
unsigned mTryNumber;
|
2019-03-08 12:23:36 +00:00
|
|
|
ChangeType mChangeType;
|
|
|
|
int mDistanceToPlayer;
|
|
|
|
int mDistanceToOrigin;
|
2020-02-20 23:05:50 +00:00
|
|
|
std::chrono::steady_clock::time_point mProcessTime;
|
2019-03-08 12:23:36 +00:00
|
|
|
|
2020-02-20 23:05:50 +00:00
|
|
|
std::tuple<std::chrono::steady_clock::time_point, unsigned, ChangeType, int, int> getPriority() const
|
2019-03-08 12:23:36 +00:00
|
|
|
{
|
2020-02-20 23:05:50 +00:00
|
|
|
return std::make_tuple(mProcessTime, mTryNumber, mChangeType, mDistanceToPlayer, mDistanceToOrigin);
|
2019-03-08 12:23:36 +00:00
|
|
|
}
|
2018-04-01 17:24:02 +00:00
|
|
|
|
|
|
|
friend inline bool operator <(const Job& lhs, const Job& rhs)
|
|
|
|
{
|
2019-03-08 12:23:36 +00:00
|
|
|
return lhs.getPriority() > rhs.getPriority();
|
2018-04-01 17:24:02 +00:00
|
|
|
}
|
2018-03-13 22:49:08 +00:00
|
|
|
};
|
|
|
|
|
2018-04-01 17:24:02 +00:00
|
|
|
using Jobs = std::priority_queue<Job, std::deque<Job>>;
|
2019-04-08 17:14:17 +00:00
|
|
|
using Pushed = std::map<osg::Vec3f, std::set<TilePosition>>;
|
|
|
|
|
|
|
|
struct Queue
|
|
|
|
{
|
|
|
|
Jobs mJobs;
|
|
|
|
Pushed mPushed;
|
|
|
|
|
|
|
|
Queue() = default;
|
|
|
|
};
|
2018-03-13 22:49:08 +00:00
|
|
|
|
|
|
|
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;
|
2018-03-13 22:49:08 +00:00
|
|
|
Jobs mJobs;
|
2018-04-20 23:57:01 +00:00
|
|
|
std::map<osg::Vec3f, std::set<TilePosition>> mPushed;
|
2018-09-29 19:57:41 +00:00
|
|
|
Misc::ScopeGuarded<TilePosition> mPlayerTile;
|
|
|
|
Misc::ScopeGuarded<boost::optional<std::chrono::steady_clock::time_point>> mFirstStart;
|
2018-09-30 22:33:25 +00:00
|
|
|
NavMeshTilesCache mNavMeshTilesCache;
|
2019-04-08 17:14:17 +00:00
|
|
|
Misc::ScopeGuarded<std::map<osg::Vec3f, std::map<TilePosition, std::thread::id>>> mProcessingTiles;
|
2020-02-20 23:05:50 +00:00
|
|
|
std::map<osg::Vec3f, std::map<TilePosition, std::chrono::steady_clock::time_point>> mLastUpdates;
|
2019-04-08 17:14:17 +00:00
|
|
|
std::map<std::thread::id, Queue> mThreadsQueues;
|
2018-09-22 14:49:57 +00:00
|
|
|
std::vector<std::thread> mThreads;
|
2018-03-13 22:49:08 +00:00
|
|
|
|
|
|
|
void process() throw();
|
|
|
|
|
2019-03-08 12:28:32 +00:00
|
|
|
bool processJob(const Job& job);
|
2018-03-13 22:49:08 +00:00
|
|
|
|
|
|
|
boost::optional<Job> getNextJob();
|
|
|
|
|
2020-02-20 23:05:50 +00:00
|
|
|
boost::optional<Job> getJob(Jobs& jobs, Pushed& pushed, bool changeLastUpdate);
|
2019-04-08 17:14:17 +00:00
|
|
|
|
|
|
|
void postThreadJob(Job&& job, Queue& queue);
|
|
|
|
|
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
|
|
|
|
2018-09-29 19:57:41 +00:00
|
|
|
std::chrono::steady_clock::time_point setFirstStart(const std::chrono::steady_clock::time_point& value);
|
2019-03-08 12:28:32 +00:00
|
|
|
|
|
|
|
void repost(Job&& job);
|
2019-04-08 17:14:17 +00:00
|
|
|
|
|
|
|
std::thread::id lockTile(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile);
|
|
|
|
|
|
|
|
void unlockTile(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile);
|
2020-02-22 20:13:08 +00:00
|
|
|
|
|
|
|
inline std::size_t getTotalThreadJobsUnsafe() const;
|
2020-02-20 23:05:50 +00:00
|
|
|
|
|
|
|
void cleanupLastUpdates();
|
2018-03-13 22:49:08 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|