BVB Source Codes

CRYENGINE Show MNMPathfinder.h Source code

Return Download CRYENGINE: download MNMPathfinder.h Source code - Download CRYENGINE Source code - Type:.h
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    -------------------------------------------------------------------------
  5.    File name:   MNMPathfinder.h
  6.    $Id$
  7.    Description:
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 06.05.2011 : Created by Francesco Roccucci
  12.  
  13.  *********************************************************************/
  14.  
  15. #ifndef _MNMPATHFINDER_H_
  16. #define _MNMPATHFINDER_H_
  17.  
  18. #include "Navigation/MNM/MNM.h"
  19. #include "Navigation/MNM/NavMesh.h"
  20. #include "NavPath.h"
  21. #include "Navigation/PathHolder.h"
  22. #include <CryPhysics/AgePriorityQueue.h>
  23. #include <CryAISystem/INavigationSystem.h>
  24. #include <CryAISystem/IPathfinder.h>
  25.  
  26. //////////////////////////////////////////////////////////////////////////
  27.  
  28. namespace MNM
  29. {
  30. namespace PathfinderUtils
  31. {
  32. struct QueuedRequest
  33. {
  34.         QueuedRequest()
  35.                 : pRequester(NULL)
  36.                 , agentTypeID(0)
  37.         {
  38.                 SetupDangerousLocationsData();
  39.         }
  40.  
  41.         QueuedRequest(const IAIPathAgent* _pRequester, NavigationAgentTypeID _agentTypeID, const MNMPathRequest& _request)
  42.                 : pRequester(_pRequester)
  43.                 , agentTypeID(_agentTypeID)
  44.                 , requestParams(_request)
  45.         {
  46.                 SetupDangerousLocationsData();
  47.         }
  48.  
  49.         const IAIPathAgent*            pRequester;
  50.         NavigationAgentTypeID          agentTypeID;
  51.         MNMPathRequest                 requestParams;
  52.  
  53.         const MNM::DangerousAreasList& GetDangersInfos() { return dangerousAreas; }
  54.  
  55. private:
  56.         void SetupDangerousLocationsData();
  57.         // Setup different danger types
  58.         void SetupAttentionTargetDanger();
  59.         void SetupExplosiveDangers();
  60.         void SetupGroupMatesAvoidance();
  61.  
  62.         MNM::DangerousAreasList dangerousAreas;
  63. };
  64.  
  65. struct ProcessingRequest
  66. {
  67.         ProcessingRequest()
  68.                 : pRequester(NULL)
  69.                 , meshID(0)
  70.                 , fromTriangleID(0)
  71.                 , toTriangleID(0)
  72.                 , data()
  73.                 , queuedID(0)
  74.         {
  75.  
  76.         }
  77.  
  78.         ILINE void Reset()         { (*this) = ProcessingRequest(); }
  79.         ILINE bool IsValid() const { return (queuedID != 0); };
  80.  
  81.         const IAIPathAgent* pRequester;
  82.         NavigationMeshID    meshID;
  83.         MNM::TriangleID     fromTriangleID;
  84.         MNM::TriangleID     toTriangleID;
  85.  
  86.         QueuedRequest       data;
  87.         MNM::QueuedPathID   queuedID;
  88. };
  89.  
  90. typedef size_t ProcessingContextId;
  91. const static ProcessingContextId kInvalidProcessingContextId = ~0ul;
  92.  
  93. struct ProcessingContext
  94. {
  95.         enum EProcessingStatus
  96.         {
  97.                 Invalid,
  98.                 Reserved,
  99.                 InProgress,
  100.                 FindWayCompleted,
  101.                 Completed,
  102.         };
  103.  
  104.         ProcessingContext(const size_t maxWaySize)
  105.                 : pWayQuery(NULL)
  106.                 , queryResult(maxWaySize)
  107.                 , status(Invalid)
  108.         {}
  109.  
  110.         ~ProcessingContext()
  111.         {
  112.                 SAFE_DELETE(pWayQuery);
  113.         }
  114.  
  115.         void Reset()
  116.         {
  117.                 processingRequest.Reset();
  118.                 SAFE_DELETE(pWayQuery);
  119.                 queryResult.Reset();
  120.                 workingSet.Reset();
  121.  
  122.                 status = Invalid;
  123.                 jobState = JobManager::SJobState();
  124.         }
  125.  
  126.         const char* GetStatusAsString() const
  127.         {
  128.                 switch (status)
  129.                 {
  130.                 case Invalid:
  131.                         return "Invalid";
  132.                 case Reserved:
  133.                         return "Reserved";
  134.                 case InProgress:
  135.                         return "InProgress";
  136.                 case FindWayCompleted:
  137.                         return "FindWayCompleted";
  138.                 case Completed:
  139.                         return "Completed";
  140.                 default:
  141.                         assert(0);
  142.                         return "Error. Unknown status";
  143.                 }
  144.         }
  145.  
  146.         ProcessingRequest            processingRequest;
  147.         CNavMesh::WayQueryRequest*   pWayQuery;
  148.         CNavMesh::WayQueryResult     queryResult;
  149.         CNavMesh::WayQueryWorkingSet workingSet;
  150.  
  151.         volatile EProcessingStatus   status;
  152.         JobManager::SJobState        jobState;
  153. };
  154.  
  155. struct IsProcessingRequestRelatedToQueuedPathId
  156. {
  157.         IsProcessingRequestRelatedToQueuedPathId(MNM::QueuedPathID _idToCheck)
  158.                 : idToCheck(_idToCheck)
  159.         {}
  160.  
  161.         bool operator()(const ProcessingContext& requestToEvaluate)
  162.         {
  163.                 return requestToEvaluate.processingRequest.queuedID == idToCheck;
  164.         }
  165.  
  166. private:
  167.         MNM::QueuedPathID idToCheck;
  168. };
  169.  
  170. class ProcessingContextsPool
  171. {
  172. public:
  173.         typedef std::vector<ProcessingContext> Pool;
  174.         typedef Pool::iterator                 PoolIterator;
  175.         typedef Pool::const_iterator           PoolConstIterator;
  176.         typedef Functor1<ProcessingContext&>   ProcessingOperation;
  177.  
  178.         ProcessingContextsPool(const size_t maxAmountOfTrianglesToCalculateWay = 512)
  179.                 : m_pool(gAIEnv.CVars.MNMPathfinderConcurrentRequests, ProcessingContext(maxAmountOfTrianglesToCalculateWay))
  180.                 , m_maxAmountOfTrianglesToCalculateWay(maxAmountOfTrianglesToCalculateWay)
  181.         {
  182.         }
  183.  
  184.         struct IsProcessCompleted
  185.         {
  186.                 bool operator()(const ProcessingContext& context) { return context.status == ProcessingContext::Completed; }
  187.         };
  188.  
  189.         struct IsProcessInvalid
  190.         {
  191.                 bool operator()(const ProcessingContext& context) { return context.status == ProcessingContext::Invalid; }
  192.         };
  193.  
  194.         size_t              GetFreeSlotsCount() const     { return std::count_if(m_pool.begin(), m_pool.end(), IsProcessInvalid()); }
  195.         size_t              GetOccupiedSlotsCount() const { return std::count_if(m_pool.begin(), m_pool.end(), IsProcessCompleted()); }
  196.         size_t              GetMaxSlots() const           { return m_pool.size(); }
  197.  
  198.         ProcessingContextId GetFirstAvailableContextId()
  199.         {
  200.                 PoolIterator freeElement = std::find_if(m_pool.begin(), m_pool.end(), IsProcessInvalid());
  201.                 if (freeElement != m_pool.end())
  202.                 {
  203.                         const ProcessingContextId newIndex = freeElement - m_pool.begin();
  204.                         freeElement->status = ProcessingContext::Reserved;
  205.                         return newIndex;
  206.                 }
  207.  
  208.                 return kInvalidProcessingContextId;
  209.         }
  210.  
  211.         ProcessingContext& GetContextAtPosition(ProcessingContextId processingContextId)
  212.         {
  213.                 CRY_ASSERT_MESSAGE(processingContextId >= 0 && processingContextId < m_pool.size(), "ProcessingContextsPool::GetContextAtPosition Trying to access an invalid element of the pool.");
  214.                 return m_pool[processingContextId];
  215.         }
  216.  
  217.         void ReleaseContext(ProcessingContextId processingContextIdToRemove)
  218.         {
  219.                 if (processingContextIdToRemove != kInvalidProcessingContextId && processingContextIdToRemove < m_pool.size())
  220.                 {
  221.                         m_pool[processingContextIdToRemove].status = ProcessingContext::Invalid;
  222.                 }
  223.         }
  224.  
  225.         void ExecuteFunctionOnElements(const ProcessingOperation& operation)
  226.         {
  227.                 std::for_each(m_pool.begin(), m_pool.end(), operation);
  228.         }
  229.  
  230.         struct InvalidateCompletedProcess
  231.         {
  232.                 void operator()(ProcessingContext& context) { if (context.status == ProcessingContext::Completed) context.Reset(); }
  233.         };
  234.  
  235.         struct ResetProcessingContext
  236.         {
  237.                 void operator()(ProcessingContext& context) { context.Reset(); }
  238.         };
  239.  
  240.         void CleanupFinishedRequests()
  241.         {
  242.                 std::for_each(m_pool.begin(), m_pool.end(), InvalidateCompletedProcess());
  243.         }
  244.  
  245.         struct IsProcessRelatedToPathId
  246.         {
  247.                 IsProcessRelatedToPathId(const MNM::QueuedPathID _requestIdToSearch)
  248.                         : requestIdToSearch(_requestIdToSearch)
  249.                 {}
  250.  
  251.                 bool operator()(const ProcessingContext& context) { return context.processingRequest.queuedID == requestIdToSearch; }
  252.         private:
  253.                 MNM::QueuedPathID requestIdToSearch;
  254.         };
  255.  
  256.         void CancelPathRequest(MNM::QueuedPathID requestId)
  257.         {
  258.                 PoolIterator end = m_pool.end();
  259.                 PoolIterator element = std::find_if(m_pool.begin(), end, IsProcessRelatedToPathId(requestId));
  260.                 if (element != end)
  261.                 {
  262.                         gEnv->GetJobManager()->WaitForJob(element->jobState);
  263.                         element->status = ProcessingContext::Invalid;
  264.                 }
  265.         }
  266.  
  267.         void Reset()
  268.         {
  269.                 m_pool.clear();
  270.                 m_pool.resize(gAIEnv.CVars.MNMPathfinderConcurrentRequests, ProcessingContext(m_maxAmountOfTrianglesToCalculateWay));
  271.                 std::for_each(m_pool.begin(), m_pool.end(), ResetProcessingContext());
  272.         }
  273.  
  274. private:
  275.         Pool   m_pool;
  276.         size_t m_maxAmountOfTrianglesToCalculateWay;
  277. };
  278.  
  279. struct PathfindingFailedEvent
  280. {
  281.         PathfindingFailedEvent()
  282.                 : requestId(MNM::Constants::eQueuedPathID_InvalidID)
  283.                 , request()
  284.         {
  285.         }
  286.  
  287.         PathfindingFailedEvent(const MNM::QueuedPathID& _requestId, const MNM::PathfinderUtils::QueuedRequest& _request)
  288.                 : requestId(_requestId)
  289.                 , request(_request)
  290.         {}
  291.  
  292.         MNM::QueuedPathID                   requestId;
  293.         MNM::PathfinderUtils::QueuedRequest request;
  294. };
  295.  
  296. struct IsPathfindingFailedEventRelatedToRequest
  297. {
  298.         IsPathfindingFailedEventRelatedToRequest(const MNM::QueuedPathID requestId) : requestIdToCheck(requestId) {}
  299.  
  300.         const bool operator()(PathfindingFailedEvent& event) { return event.requestId == requestIdToCheck; }
  301.  
  302.         MNM::QueuedPathID requestIdToCheck;
  303. };
  304.  
  305. struct PathfindingCompletedEvent
  306. {
  307.         PathfindingCompletedEvent()
  308.         {
  309.                 eventData.pPath.reset(new CNavPath());
  310.         }
  311.  
  312.         CNavPath                 eventNavPath;
  313.         MNMPathRequestResult     eventResults;
  314.         MNMPathRequestResult     eventData;
  315.         MNMPathRequest::Callback callback;
  316.         MNM::QueuedPathID        requestId;
  317. };
  318.  
  319. struct IsPathfindingCompletedEventRelatedToRequest
  320. {
  321.         IsPathfindingCompletedEventRelatedToRequest(const MNM::QueuedPathID requestId) : requestIdToCheck(requestId) {}
  322.  
  323.         const bool operator()(PathfindingCompletedEvent& event) { return event.requestId == requestIdToCheck; }
  324.  
  325.         MNM::QueuedPathID requestIdToCheck;
  326. };
  327.  
  328. typedef CryMT::vector<PathfindingFailedEvent>    PathfinderFailedEventQueue;
  329. typedef CryMT::vector<PathfindingCompletedEvent> PathfinderCompletedEventQueue;
  330. }
  331. }
  332.  
  333. // -----------------------------------------------------------------------------
  334.  
  335. class CMNMPathfinder : public IMNMPathfinder
  336. {
  337. public:
  338.  
  339.         CMNMPathfinder();
  340.         ~CMNMPathfinder();
  341.  
  342.         void                      Reset();
  343.  
  344.         virtual MNM::QueuedPathID RequestPathTo(const IAIPathAgent* pRequester, const MNMPathRequest& request);
  345.         virtual void              CancelPathRequest(MNM::QueuedPathID requestId);
  346.  
  347.         void                      WaitForJobsToFinish();
  348.  
  349.         bool                      CheckIfPointsAreOnStraightWalkableLine(const NavigationMeshID& meshID, const Vec3& source, const Vec3& destination, float heightOffset = 0.2f) const;
  350.  
  351.         void                      Update();
  352.  
  353.         void                      SetupNewValidPathRequests();
  354.         void                      DispatchResults();
  355.  
  356.         size_t                    GetRequestQueueSize() const { return m_requestedPathsQueue.size(); }
  357.  
  358.         void                      OnNavigationMeshChanged(NavigationMeshID meshId, MNM::TileID tileId);
  359.  
  360.         // Utility function, which takes a triangles way found by MNM::CNavMesh::FindWay() and converts it into a way-point path.
  361.         static bool ConstructPathFromFoundWay(
  362.           const MNM::CNavMesh::WayQueryResult& way,
  363.           const MNM::CNavMesh& navMesh,
  364.           const OffMeshNavigationManager* pOffMeshNavigationManager,
  365.           const Vec3& startLocation,
  366.           const Vec3& endLocation,
  367.           CPathHolder<PathPointDescriptor>& outputPath);
  368.  
  369. private:
  370.  
  371.         MNM::QueuedPathID QueuePathRequest(IAIPathAgent* pRequester, const MNMPathRequest& request);
  372.  
  373.         void              SpawnJobs();
  374.         void              SpawnAppropriateJobIfPossible(MNM::PathfinderUtils::ProcessingContext& processingContext);
  375.         void              ExecuteAppropriateOperationIfPossible(MNM::PathfinderUtils::ProcessingContext& processingContext);
  376.         void              SpawnPathfinderProcessingJob(MNM::PathfinderUtils::ProcessingContext& processingContext);
  377.         void              SpawnPathConstructionJob(MNM::PathfinderUtils::ProcessingContext& processingContext);
  378.         void              WaitForJobToFinish(MNM::PathfinderUtils::ProcessingContext& processingContext);
  379.         void              ProcessPathRequest(MNM::PathfinderUtils::ProcessingContext& processingContext);
  380.         void              ConstructPathIfWayWasFound(MNM::PathfinderUtils::ProcessingContext& processingContext);
  381.  
  382.         bool              SetupForNextPathRequest(MNM::QueuedPathID requestID, MNM::PathfinderUtils::QueuedRequest& request, MNM::PathfinderUtils::ProcessingContext& processingContext);
  383.         void              PathRequestFailed(MNM::QueuedPathID requestID, const MNM::PathfinderUtils::QueuedRequest& request);
  384.  
  385.         void              CancelResultDispatchingForRequest(MNM::QueuedPathID requestId);
  386.  
  387.         void              DebugAllStatistics();
  388.         void              DebugStatistics(MNM::PathfinderUtils::ProcessingContext& processingContext, const float textY);
  389.  
  390.         friend void       ProcessPathRequestJob(MNM::PathfinderUtils::ProcessingContext* pProcessingContext);
  391.         friend void       ConstructPathIfWayWasFoundJob(MNM::PathfinderUtils::ProcessingContext* pProcessingContext);
  392.  
  393.         typedef AgePriorityQueue<MNM::PathfinderUtils::QueuedRequest> RequestQueue;
  394.         RequestQueue m_requestedPathsQueue;
  395.  
  396.         MNM::PathfinderUtils::ProcessingContextsPool        m_processingContextsPool;
  397.         MNM::PathfinderUtils::PathfinderFailedEventQueue    m_pathfindingFailedEventsToDispatch;
  398.         MNM::PathfinderUtils::PathfinderCompletedEventQueue m_pathfindingCompletedEventsToDispatch;
  399. };
  400.  
  401. #endif // _MNMPATHFINDER_H_
  402.  
downloadMNMPathfinder.h Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top