diff --git a/Detour/Include/DetourNode.h b/Detour/Include/DetourNode.h index b68c922..811135f 100644 --- a/Detour/Include/DetourNode.h +++ b/Detour/Include/DetourNode.h @@ -48,7 +48,12 @@ public: ~dtNodePool(); inline void operator=(const dtNodePool&) {} void clear(); - dtNode* getNode(dtPolyRef id); + + /* Get a dtNode by ref. If there is none then - allocate + * There can be more than one node for the same polyRef, in which case they are seqential + * nb [in] the number of extra nodes to allocate if needed + */ + dtNode* getNode(dtPolyRef id, int nExtra=0); dtNode* findNode(dtPolyRef id); inline unsigned int getNodeIdx(const dtNode* node) const @@ -82,6 +87,7 @@ public: inline int getHashSize() const { return m_hashSize; } inline dtNodeIndex getFirst(int bucket) const { return m_first[bucket]; } inline dtNodeIndex getNext(int i) const { return m_next[i]; } + inline int getNodeCount() const { return m_nodeCount;} private: diff --git a/Detour/Source/DetourNavMeshQuery.cpp b/Detour/Source/DetourNavMeshQuery.cpp index bdbee00..9856094 100644 --- a/Detour/Source/DetourNavMeshQuery.cpp +++ b/Detour/Source/DetourNavMeshQuery.cpp @@ -1047,12 +1047,22 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) continue; - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); + // deal explicitly with crossing tile boundaries + int crossSide = 0, extraNodes = 0; + if (bestTile->links[i].side != 0xff) + { + extraNodes = 3; + crossSide = bestTile->links[i].side >> 1; + } + + // get the node + dtNode* neighbourNode = m_nodePool->getNode(neighbourRef, extraNodes); if (!neighbourNode) { status |= DT_OUT_OF_NODES; continue; } + neighbourNode += crossSide; // If the node is visited the first time, calculate node position. if (neighbourNode->flags == 0) @@ -1304,12 +1314,21 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) if (!m_query.filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) continue; - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); + // deal explicitly with crossing tile boundaries + int crossSide = 0, extraNodes = 0; + if (bestTile->links[i].side != 0xff) + { + extraNodes = 3; + crossSide = bestTile->links[i].side >> 1; + } + + dtNode* neighbourNode = m_nodePool->getNode(neighbourRef, extraNodes); if (!neighbourNode) { m_query.status |= DT_OUT_OF_NODES; continue; } + neighbourNode += crossSide; // If the node is visited the first time, calculate node position. if (neighbourNode->flags == 0) @@ -3370,5 +3389,18 @@ bool dtNavMeshQuery::isInClosedList(dtPolyRef ref) const { if (!m_nodePool) return false; const dtNode* node = m_nodePool->findNode(ref); - return node && node->flags & DT_NODE_CLOSED; + if (!node) + return false; + + const dtNode* last=m_nodePool->getNodeAtIdx(m_nodePool->getNodeCount() -1); + + do // several nodes might be allocated for the same ref + { + if (node->flags & DT_NODE_CLOSED) + return true; + + node++; + } while (nodeid == ref); + + return false; } diff --git a/Detour/Source/DetourNode.cpp b/Detour/Source/DetourNode.cpp index 57cb206..f1e121d 100644 --- a/Detour/Source/DetourNode.cpp +++ b/Detour/Source/DetourNode.cpp @@ -97,7 +97,7 @@ dtNode* dtNodePool::findNode(dtPolyRef id) return 0; } -dtNode* dtNodePool::getNode(dtPolyRef id) +dtNode* dtNodePool::getNode(dtPolyRef id, int nExtra) { unsigned int bucket = dtHashRef(id) & (m_hashSize-1); dtNodeIndex i = m_first[bucket]; @@ -108,25 +108,33 @@ dtNode* dtNodePool::getNode(dtPolyRef id) return &m_nodes[i]; i = m_next[i]; } - - if (m_nodeCount >= m_maxNodes) + + if (m_nodeCount + nExtra >= m_maxNodes) return 0; - + + // add to hash table i = (dtNodeIndex)m_nodeCount; - m_nodeCount++; - - // Init node - node = &m_nodes[i]; - node->pidx = 0; - node->cost = 0; - node->total = 0; - node->id = id; - node->flags = 0; - m_next[i] = m_first[bucket]; m_first[bucket] = i; + + dtNode* ret = &m_nodes[i]; + + for ( ; nExtra >= 0; --nExtra) + { + i = (dtNodeIndex)m_nodeCount; + m_nodeCount++; - return node; + // Init node + node = &m_nodes[i]; + node->pidx = 0; + node->cost = 0; + node->total = 0; + node->id = id; + node->flags = 0; + } + + + return ret; }