Add getPathFromDijkstraSearch function (#211)
This adds a method to dtNavMeshQuery that allows users to retrieve paths from the nodes explored by the previous Dijkstra search. This is useful after Dijkstra searches to retrieve arbitrary paths inside the explored area.
This commit is contained in:
parent
c464d91fe8
commit
2a0c31b8ef
@ -296,6 +296,20 @@ public:
|
|||||||
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
||||||
int* resultCount, const int maxResult) const;
|
int* resultCount, const int maxResult) const;
|
||||||
|
|
||||||
|
/// Gets a path from the explored nodes in the previous search.
|
||||||
|
/// @param[in] endRef The reference id of the end polygon.
|
||||||
|
/// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
|
||||||
|
/// [(polyRef) * @p pathCount]
|
||||||
|
/// @param[out] pathCount The number of polygons returned in the @p path array.
|
||||||
|
/// @param[in] maxPath The maximum number of polygons the @p path array can hold. [Limit: >= 0]
|
||||||
|
/// @returns The status flags. Returns DT_FAILURE | DT_INVALID_PARAM if any parameter is wrong, or if
|
||||||
|
/// @p endRef was not explored in the previous search. Returns DT_SUCCESS | DT_BUFFER_TOO_SMALL
|
||||||
|
/// if @p path cannot contain the entire path. In this case it is filled to capacity with a partial path.
|
||||||
|
/// Otherwise returns DT_SUCCESS.
|
||||||
|
/// @remarks The result of this function depends on the state of the query object. For that reason it should only
|
||||||
|
/// be used immediately after one of the two Dijkstra searches, findPolysAroundCircle or findPolysAroundShape.
|
||||||
|
dtStatus getPathFromDijkstraSearch(dtPolyRef endRef, dtPolyRef* path, int* pathCount, int maxPath) const;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// @name Local Query Functions
|
/// @name Local Query Functions
|
||||||
///@{
|
///@{
|
||||||
@ -525,6 +539,9 @@ private:
|
|||||||
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
|
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
|
||||||
int* straightPathCount, const int maxStraightPath, const int options) const;
|
int* straightPathCount, const int maxStraightPath, const int options) const;
|
||||||
|
|
||||||
|
// Gets the path leading to the specified end node.
|
||||||
|
dtStatus getPathToNode(class dtNode* endNode, dtPolyRef* path, int* pathCount, int maxPath) const;
|
||||||
|
|
||||||
const dtNavMesh* m_nav; ///< Pointer to navmesh data.
|
const dtNavMesh* m_nav; ///< Pointer to navmesh data.
|
||||||
|
|
||||||
struct dtQueryData
|
struct dtQueryData
|
||||||
|
@ -1022,16 +1022,12 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
|
|||||||
dtAssert(m_nodePool);
|
dtAssert(m_nodePool);
|
||||||
dtAssert(m_openList);
|
dtAssert(m_openList);
|
||||||
|
|
||||||
|
if (pathCount)
|
||||||
*pathCount = 0;
|
*pathCount = 0;
|
||||||
|
|
||||||
if (!startRef || !endRef)
|
|
||||||
return DT_FAILURE | DT_INVALID_PARAM;
|
|
||||||
|
|
||||||
if (!maxPath)
|
|
||||||
return DT_FAILURE | DT_INVALID_PARAM;
|
|
||||||
|
|
||||||
// Validate input
|
// Validate input
|
||||||
if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef))
|
if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef) ||
|
||||||
|
!startPos || !endPos || !filter || maxPath <= 0 || !path || !pathCount)
|
||||||
return DT_FAILURE | DT_INVALID_PARAM;
|
return DT_FAILURE | DT_INVALID_PARAM;
|
||||||
|
|
||||||
if (startRef == endRef)
|
if (startRef == endRef)
|
||||||
@ -1194,41 +1190,55 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = getPathToNode(lastBestNode, path, pathCount, maxPath);
|
||||||
|
|
||||||
if (lastBestNode->id != endRef)
|
if (lastBestNode->id != endRef)
|
||||||
status |= DT_PARTIAL_RESULT;
|
status |= DT_PARTIAL_RESULT;
|
||||||
|
|
||||||
// Reverse the path.
|
|
||||||
dtNode* prev = 0;
|
|
||||||
dtNode* node = lastBestNode;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
dtNode* next = m_nodePool->getNodeAtIdx(node->pidx);
|
|
||||||
node->pidx = m_nodePool->getNodeIdx(prev);
|
|
||||||
prev = node;
|
|
||||||
node = next;
|
|
||||||
}
|
|
||||||
while (node);
|
|
||||||
|
|
||||||
// Store path
|
|
||||||
node = prev;
|
|
||||||
int n = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
path[n++] = node->id;
|
|
||||||
if (n >= maxPath)
|
|
||||||
{
|
|
||||||
status |= DT_BUFFER_TOO_SMALL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
node = m_nodePool->getNodeAtIdx(node->pidx);
|
|
||||||
}
|
|
||||||
while (node);
|
|
||||||
|
|
||||||
*pathCount = n;
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dtStatus dtNavMeshQuery::getPathToNode(dtNode* endNode, dtPolyRef* path, int* pathCount, int maxPath) const
|
||||||
|
{
|
||||||
|
// Find the length of the entire path.
|
||||||
|
dtNode* curNode = endNode;
|
||||||
|
int length = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
length++;
|
||||||
|
curNode = m_nodePool->getNodeAtIdx(curNode->pidx);
|
||||||
|
} while (curNode);
|
||||||
|
|
||||||
|
// If the path cannot be fully stored then advance to the last node we will be able to store.
|
||||||
|
curNode = endNode;
|
||||||
|
int writeCount;
|
||||||
|
for (writeCount = length; writeCount > maxPath; writeCount--)
|
||||||
|
{
|
||||||
|
dtAssert(curNode);
|
||||||
|
|
||||||
|
curNode = m_nodePool->getNodeAtIdx(curNode->pidx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write path
|
||||||
|
for (int i = writeCount - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
dtAssert(curNode);
|
||||||
|
|
||||||
|
path[i] = curNode->id;
|
||||||
|
curNode = m_nodePool->getNodeAtIdx(curNode->pidx);
|
||||||
|
}
|
||||||
|
|
||||||
|
dtAssert(!curNode);
|
||||||
|
|
||||||
|
*pathCount = dtMin(length, maxPath);
|
||||||
|
|
||||||
|
if (length > maxPath)
|
||||||
|
return DT_SUCCESS | DT_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
return DT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @par
|
/// @par
|
||||||
///
|
///
|
||||||
/// @warning Calling any non-slice methods before calling finalizeSlicedFindPath()
|
/// @warning Calling any non-slice methods before calling finalizeSlicedFindPath()
|
||||||
@ -3031,6 +3041,21 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dtStatus dtNavMeshQuery::getPathFromDijkstraSearch(dtPolyRef endRef, dtPolyRef* path, int* pathCount, int maxPath) const
|
||||||
|
{
|
||||||
|
if (!m_nav->isValidPolyRef(endRef) || !path || !pathCount || maxPath < 0)
|
||||||
|
return DT_FAILURE | DT_INVALID_PARAM;
|
||||||
|
|
||||||
|
*pathCount = 0;
|
||||||
|
|
||||||
|
dtNode* endNode;
|
||||||
|
if (m_nodePool->findNodes(endRef, &endNode, 1) != 1 ||
|
||||||
|
(endNode->flags & DT_NODE_CLOSED) == 0)
|
||||||
|
return DT_FAILURE | DT_INVALID_PARAM;
|
||||||
|
|
||||||
|
return getPathToNode(endNode, path, pathCount, maxPath);
|
||||||
|
}
|
||||||
|
|
||||||
/// @par
|
/// @par
|
||||||
///
|
///
|
||||||
/// This method is optimized for a small search radius and small number of result
|
/// This method is optimized for a small search radius and small number of result
|
||||||
|
Loading…
x
Reference in New Issue
Block a user