@par If the end polygon cannot be reached through the navigation graph, the last polygon in the path will be the nearest the end polygon. If the path array is to small to hold the full result, it will be filled as far as possible from the start polygon toward the end polygon. The start and end positions are used to calculate traversal costs. (The y-values impact the result.)
| 1000 | /// (The y-values impact the result.) |
| 1001 | /// |
| 1002 | dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, |
| 1003 | const float* startPos, const float* endPos, |
| 1004 | const dtQueryFilter* filter, |
| 1005 | dtPolyRef* path, int* pathCount, const int maxPath) const |
| 1006 | { |
| 1007 | dtAssert(m_nav); |
| 1008 | dtAssert(m_nodePool); |
| 1009 | dtAssert(m_openList); |
| 1010 | |
| 1011 | if (!pathCount) |
| 1012 | return DT_FAILURE | DT_INVALID_PARAM; |
| 1013 | |
| 1014 | *pathCount = 0; |
| 1015 | |
| 1016 | // Validate input |
| 1017 | if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef) || |
| 1018 | !startPos || !dtVisfinite(startPos) || |
| 1019 | !endPos || !dtVisfinite(endPos) || |
| 1020 | !filter || !path || maxPath <= 0) |
| 1021 | { |
| 1022 | return DT_FAILURE | DT_INVALID_PARAM; |
| 1023 | } |
| 1024 | |
| 1025 | if (startRef == endRef) |
| 1026 | { |
| 1027 | path[0] = startRef; |
| 1028 | *pathCount = 1; |
| 1029 | return DT_SUCCESS; |
| 1030 | } |
| 1031 | |
| 1032 | m_nodePool->clear(); |
| 1033 | m_openList->clear(); |
| 1034 | |
| 1035 | dtNode* startNode = m_nodePool->getNode(startRef); |
| 1036 | dtVcopy(startNode->pos, startPos); |
| 1037 | startNode->pidx = 0; |
| 1038 | startNode->cost = 0; |
| 1039 | startNode->total = dtVdist(startPos, endPos) * H_SCALE; |
| 1040 | startNode->id = startRef; |
| 1041 | startNode->flags = DT_NODE_OPEN; |
| 1042 | m_openList->push(startNode); |
| 1043 | |
| 1044 | dtNode* lastBestNode = startNode; |
| 1045 | float lastBestNodeCost = startNode->total; |
| 1046 | |
| 1047 | bool outOfNodes = false; |
| 1048 | |
| 1049 | while (!m_openList->empty()) |
| 1050 | { |
| 1051 | // Remove node from open list and put it in closed list. |
| 1052 | dtNode* bestNode = m_openList->pop(); |
| 1053 | bestNode->flags &= ~DT_NODE_OPEN; |
| 1054 | bestNode->flags |= DT_NODE_CLOSED; |
| 1055 | |
| 1056 | // Reached the goal, stop searching. |
| 1057 | if (bestNode->id == endRef) |
| 1058 | { |
| 1059 | lastBestNode = bestNode; |