improving path aesthetics at tile crossing: in the old code, when a new node is found a single 3D position is associated with it. This position is used regardless of arriving from a new tile. A minor issue on a normal navmesh, this produces many problems when crossing tiles. Points might be located on different borders altogether depending on where one arrived from first.
The new code assigns several (consecutive) dtNodes for polygons that lie on tile boundary. Each node gets its own point. since the nodes are packed together consecutively, it is easy to find the right node by reference even though there are several.
This commit is contained in:
parent
e117234170
commit
d2306cacdd
@ -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:
|
||||
|
||||
|
@ -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 (node<last && node->id == ref);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user