diff options
Diffstat (limited to 'dep/recastnavigation/Detour/DetourNavMeshQuery.cpp')
-rw-r--r-- | dep/recastnavigation/Detour/DetourNavMeshQuery.cpp | 1019 |
1 files changed, 242 insertions, 777 deletions
diff --git a/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp b/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp index e6557cf707e..ec0c30460a9 100644 --- a/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp +++ b/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp @@ -81,7 +81,7 @@ float dtQueryFilter::getCost(const float* pa, const float* pb, const dtPolyRef /*curRef*/, const dtMeshTile* /*curTile*/, const dtPoly* curPoly, const dtPolyRef /*nextRef*/, const dtMeshTile* /*nextTile*/, const dtPoly* /*nextPoly*/) const { - return dtVdist(pa, pb) * m_areaCost[curPoly->getArea()]; + return dtVdist(pa, pb) * m_areaCost[curPoly->area]; } #else inline bool dtQueryFilter::passFilter(const dtPolyRef /*ref*/, @@ -217,281 +217,6 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes) return DT_SUCCESS; } -dtStatus dtNavMeshQuery::findRandomPoint(const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const -{ - dtAssert(m_nav); - - // Randomly pick one tile. Assume that all tiles cover roughly the same area. - const dtMeshTile* tile = 0; - float tsum = 0.0f; - for (int i = 0; i < m_nav->getMaxTiles(); i++) - { - const dtMeshTile* t = m_nav->getTile(i); - if (!t || !t->header) continue; - - // Choose random tile using reservoi sampling. - const float area = 1.0f; // Could be tile area too. - tsum += area; - const float u = frand(); - if (u*tsum <= area) - tile = t; - } - if (!tile) - return DT_FAILURE; - - // Randomly pick one polygon weighted by polygon area. - const dtPoly* poly = 0; - dtPolyRef polyRef = 0; - const dtPolyRef base = m_nav->getPolyRefBase(tile); - - float areaSum = 0.0f; - for (int i = 0; i < tile->header->polyCount; ++i) - { - const dtPoly* p = &tile->polys[i]; - // Do not return off-mesh connection polygons. - if (p->getType() != DT_POLYTYPE_GROUND) - continue; - // Must pass filter - const dtPolyRef ref = base | (dtPolyRef)i; - if (!filter->passFilter(ref, tile, p)) - continue; - - // Calc area of the polygon. - float polyArea = 0.0f; - for (int j = 2; j < p->vertCount; ++j) - { - const float* va = &tile->verts[p->verts[0]*3]; - const float* vb = &tile->verts[p->verts[j-1]*3]; - const float* vc = &tile->verts[p->verts[j]*3]; - polyArea += dtTriArea2D(va,vb,vc); - } - - // Choose random polygon weighted by area, using reservoi sampling. - areaSum += polyArea; - const float u = frand(); - if (u*areaSum <= polyArea) - { - poly = p; - polyRef = ref; - } - } - - if (!poly) - return DT_FAILURE; - - // Randomly pick point on polygon. - const float* v = &tile->verts[poly->verts[0]*3]; - float verts[3*DT_VERTS_PER_POLYGON]; - float areas[DT_VERTS_PER_POLYGON]; - dtVcopy(&verts[0*3],v); - for (int j = 1; j < poly->vertCount; ++j) - { - v = &tile->verts[poly->verts[j]*3]; - dtVcopy(&verts[j*3],v); - } - - const float s = frand(); - const float t = frand(); - - float pt[3]; - dtRandomPointInConvexPoly(verts, poly->vertCount, areas, s, t, pt); - - float h = 0.0f; - dtStatus status = getPolyHeight(polyRef, pt, &h); - if (dtStatusFailed(status)) - return status; - pt[1] = h; - - dtVcopy(randomPt, pt); - *randomRef = polyRef; - - return DT_SUCCESS; -} - -dtStatus dtNavMeshQuery::findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - const dtMeshTile* startTile = 0; - const dtPoly* startPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(startRef, &startTile, &startPoly); - if (!filter->passFilter(startRef, startTile, startPoly)) - return DT_FAILURE | DT_INVALID_PARAM; - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, centerPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - dtStatus status = DT_SUCCESS; - - const float radiusSqr = dtSqr(radius); - float areaSum = 0.0f; - - const dtMeshTile* randomTile = 0; - const dtPoly* randomPoly = 0; - dtPolyRef randomPolyRef = 0; - - while (!m_openList->empty()) - { - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Place random locations on on ground. - if (bestPoly->getType() == DT_POLYTYPE_GROUND) - { - // Calc area of the polygon. - float polyArea = 0.0f; - for (int j = 2; j < bestPoly->vertCount; ++j) - { - const float* va = &bestTile->verts[bestPoly->verts[0]*3]; - const float* vb = &bestTile->verts[bestPoly->verts[j-1]*3]; - const float* vc = &bestTile->verts[bestPoly->verts[j]*3]; - polyArea += dtTriArea2D(va,vb,vc); - } - // Choose random polygon weighted by area, using reservoi sampling. - areaSum += polyArea; - const float u = frand(); - if (u*areaSum <= polyArea) - { - randomTile = bestTile; - randomPoly = bestPoly; - randomPolyRef = bestRef; - } - } - - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - const dtLink* link = &bestTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours and do not follow back to parent. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Expand to neighbour - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Do not advance if the polygon is excluded by the filter. - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - // Find edge and calc distance to the edge. - float va[3], vb[3]; - if (!getPortalPoints(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) - continue; - - // If the circle is not touching the next polygon, skip it. - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); - if (distSqr > radiusSqr) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Cost - if (neighbourNode->flags == 0) - dtVlerp(neighbourNode->pos, va, vb, 0.5f); - - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - m_openList->modify(neighbourNode); - } - else - { - neighbourNode->flags = DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - } - } - - if (!randomPoly) - return DT_FAILURE; - - // Randomly pick point on polygon. - const float* v = &randomTile->verts[randomPoly->verts[0]*3]; - float verts[3*DT_VERTS_PER_POLYGON]; - float areas[DT_VERTS_PER_POLYGON]; - dtVcopy(&verts[0*3],v); - for (int j = 1; j < randomPoly->vertCount; ++j) - { - v = &randomTile->verts[randomPoly->verts[j]*3]; - dtVcopy(&verts[j*3],v); - } - - const float s = frand(); - const float t = frand(); - - float pt[3]; - dtRandomPointInConvexPoly(verts, randomPoly->vertCount, areas, s, t, pt); - - float h = 0.0f; - dtStatus stat = getPolyHeight(randomPolyRef, pt, &h); - if (dtStatusFailed(status)) - return stat; - pt[1] = h; - - dtVcopy(randomPt, pt); - *randomRef = randomPolyRef; - - return DT_SUCCESS; -} - - ////////////////////////////////////////////////////////////////////////////////////////// /// @par @@ -516,99 +241,92 @@ dtStatus dtNavMeshQuery::closestPointOnPoly(dtPolyRef ref, const float* pos, flo if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) return DT_FAILURE; - closestPointOnPolyInTile(tile, poly, pos, closest); - + if (closestPointOnPolyInTile(tile, poly, pos, closest) != DT_SUCCESS) + return DT_FAILURE; return DT_SUCCESS; } -void dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, - const float* pos, float* closest) const +dtStatus dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, + const float* pos, float* closest) const { - // Off-mesh connections don't have detail polygons. - if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - { - const float* v0 = &tile->verts[poly->verts[0]*3]; - const float* v1 = &tile->verts[poly->verts[1]*3]; - const float d0 = dtVdist(pos, v0); - const float d1 = dtVdist(pos, v1); - const float u = d0 / (d0+d1); - dtVlerp(closest, v0, v1, u); - return; - } - - const unsigned int ip = (unsigned int)(poly - tile->polys); - const dtPolyDetail* pd = &tile->detailMeshes[ip]; - - // Clamp point to be inside the polygon. - float verts[DT_VERTS_PER_POLYGON*3]; - float edged[DT_VERTS_PER_POLYGON]; - float edget[DT_VERTS_PER_POLYGON]; - const int nv = poly->vertCount; - for (int i = 0; i < nv; ++i) - dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]); - - dtVcopy(closest, pos); - if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)) - { - // Point is outside the polygon, dtClamp to nearest edge. - float dmin = FLT_MAX; - int imin = -1; - for (int i = 0; i < nv; ++i) - { - if (edged[i] < dmin) - { - dmin = edged[i]; - imin = i; - } - } - const float* va = &verts[imin*3]; - const float* vb = &verts[((imin+1)%nv)*3]; - dtVlerp(closest, va, vb, edget[imin]); - } - - // Find height at the location. - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - float h; - if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h)) - { - closest[1] = h; - break; - } - } - -/* float closestDistSqr = FLT_MAX; - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - - float pt[3]; - dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]); - float d = dtVdistSqr(pos, pt); - - if (d < closestDistSqr) - { - dtVcopy(closest, pt); - closestDistSqr = d; - } - }*/ + const unsigned int ip = (unsigned int)(poly - tile->polys); + const dtPolyDetail* pd = &tile->detailMeshes[ip]; + + // TODO: The commented out version finds 'cylinder distance' instead of 'sphere distance' to the navmesh. + // Test and enable. + /* + // Clamp point to be inside the polygon. + float verts[DT_VERTS_PER_POLYGON*3]; + float edged[DT_VERTS_PER_POLYGON]; + float edget[DT_VERTS_PER_POLYGON]; + const int nv = poly->vertCount; + for (int i = 0; i < nv; ++i) + dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]); + + dtVcopy(closest, pos); + if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)) + { + // Point is outside the polygon, dtClamp to nearest edge. + float dmin = FLT_MAX; + int imin = -1; + for (int i = 0; i < nv; ++i) + { + if (edged[i] < dmin) + { + dmin = edged[i]; + imin = i; + } + } + const float* va = &verts[imin*3]; + const float* vb = &verts[((imin+1)%nv)*3]; + dtVlerp(closest, va, vb, edget[imin]); + } + + // Find height at the location. + for (int j = 0; j < pd->triCount; ++j) + { + const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; + const float* v[3]; + for (int k = 0; k < 3; ++k) + { + if (t[k] < poly->vertCount) + v[k] = &tile->verts[poly->verts[t[k]]*3]; + else + v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; + } + float h; + if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h)) + { + closest[1] = h; + break; + } + } + */ + float closestDistSqr = FLT_MAX; + for (int j = 0; j < pd->triCount; ++j) + { + const unsigned char* t = &tile->detailTris[(pd->triBase + j) * 4]; + const float* v[3]; + for (int k = 0; k < 3; ++k) + { + if (t[k] < poly->vertCount) + v[k] = &tile->verts[poly->verts[t[k]] * 3]; + else + v[k] = &tile->detailVerts[(pd->vertBase + (t[k] - poly->vertCount)) * 3]; + } + + float pt[3]; + dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]); + float d = dtVdistSqr(pos, pt); + + if (d < closestDistSqr) + { + dtVcopy(closest, pt); + closestDistSqr = d; + } + } + + return DT_SUCCESS; } /// @par @@ -752,7 +470,8 @@ dtStatus dtNavMeshQuery::findNearestPoly(const float* center, const float* exten { dtPolyRef ref = polys[i]; float closestPtPoly[3]; - closestPointOnPoly(ref, center, closestPtPoly); + if (closestPointOnPoly(ref, center, closestPtPoly) != DT_SUCCESS) + continue; float d = dtVdistSqr(center, closestPtPoly); if (d < nearestDistanceSqr) { @@ -790,7 +509,8 @@ dtPolyRef dtNavMeshQuery::findNearestPolyInTile(const dtMeshTile* tile, const fl dtPolyRef ref = polys[i]; const dtPoly* poly = &tile->polys[m_nav->decodePolyIdPoly(ref)]; float closestPtPoly[3]; - closestPointOnPolyInTile(tile, poly, center, closestPtPoly); + if (closestPointOnPolyInTile(tile, poly, center, closestPtPoly) != DT_SUCCESS) + continue; float d = dtVdistSqr(center, closestPtPoly); if (d < nearestDistanceSqr) @@ -872,15 +592,8 @@ int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmi const dtPolyRef base = m_nav->getPolyRefBase(tile); for (int i = 0; i < tile->header->polyCount; ++i) { - const dtPoly* p = &tile->polys[i]; - // Do not return off-mesh connection polygons. - if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - // Must pass filter - const dtPolyRef ref = base | (dtPolyRef)i; - if (!filter->passFilter(ref, tile, p)) - continue; // Calc polygon bounds. + dtPoly* p = &tile->polys[i]; const float* v = &tile->verts[p->verts[0]*3]; dtVcopy(bmin, v); dtVcopy(bmax, v); @@ -892,8 +605,12 @@ int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmi } if (dtOverlapBounds(qmin,qmax, bmin,bmax)) { - if (n < maxPolys) - polys[n++] = ref; + const dtPolyRef ref = base | (dtPolyRef)i; + if (filter->passFilter(ref, tile, p)) + { + if (n < maxPolys) + polys[n++] = ref; + } } } return n; @@ -924,23 +641,18 @@ dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents m_nav->calcTileLoc(bmin, &minx, &miny); m_nav->calcTileLoc(bmax, &maxx, &maxy); - static const int MAX_NEIS = 32; - const dtMeshTile* neis[MAX_NEIS]; - int n = 0; for (int y = miny; y <= maxy; ++y) { for (int x = minx; x <= maxx; ++x) { - const int nneis = m_nav->getTilesAt(x,y,neis,MAX_NEIS); - for (int j = 0; j < nneis; ++j) + const dtMeshTile* tile = m_nav->getTileAt(x,y); + if (!tile) continue; + n += queryPolygonsInTile(tile, bmin, bmax, filter, polys+n, maxPolys-n); + if (n >= maxPolys) { - n += queryPolygonsInTile(neis[j], bmin, bmax, filter, polys+n, maxPolys-n); - if (n >= maxPolys) - { - *polyCount = n; - return DT_SUCCESS | DT_BUFFER_TOO_SMALL; - } + *polyCount = n; + return DT_SUCCESS; } } } @@ -1003,8 +715,6 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, dtNode* lastBestNode = startNode; float lastBestNodeCost = startNode->total; - dtStatus status = DT_SUCCESS; - while (!m_openList->empty()) { // Remove node from open list and put it in closed list. @@ -1054,10 +764,7 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; continue; - } // If the node is visited the first time, calculate node position. if (neighbourNode->flags == 0) @@ -1110,7 +817,7 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, // Add or update the node. neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); + neighbourNode->flags &= ~DT_NODE_CLOSED; neighbourNode->cost = cost; neighbourNode->total = total; @@ -1135,9 +842,6 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, } } - if (lastBestNode->id != endRef) - status |= DT_PARTIAL_RESULT; - // Reverse the path. dtNode* prev = 0; dtNode* node = lastBestNode; @@ -1156,18 +860,13 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, do { path[n++] = node->id; - if (n >= maxPath) - { - status |= DT_BUFFER_TOO_SMALL; - break; - } node = m_nodePool->getNodeAtIdx(node->pidx); } - while (node); + while (node && n < maxPath); *pathCount = n; - return status; + return DT_SUCCESS; } /// @par @@ -1227,7 +926,7 @@ dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef return m_query.status; } -dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) +dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter) { if (!dtStatusInProgress(m_query.status)) return m_query.status; @@ -1253,10 +952,7 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) if (bestNode->id == m_query.endRef) { m_query.lastBestNode = bestNode; - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - m_query.status = DT_SUCCESS | details; - if (doneIters) - *doneIters = iter; + m_query.status = DT_SUCCESS; return m_query.status; } @@ -1269,8 +965,6 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) { // The polygon has disappeared during the sliced query, fail. m_query.status = DT_FAILURE; - if (doneIters) - *doneIters = iter; return m_query.status; } @@ -1286,8 +980,6 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) { // The polygon has disappeared during the sliced query, fail. m_query.status = DT_FAILURE; - if (doneIters) - *doneIters = iter; return m_query.status; } } @@ -1311,10 +1003,7 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); if (!neighbourNode) - { - m_query.status |= DT_OUT_OF_NODES; continue; - } // If the node is visited the first time, calculate node position. if (neighbourNode->flags == 0) @@ -1367,7 +1056,7 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) // Add or update the node. neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); + neighbourNode->flags &= ~DT_NODE_CLOSED; neighbourNode->cost = cost; neighbourNode->total = total; @@ -1394,13 +1083,7 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) // Exhausted all nodes, but could not find path. if (m_openList->empty()) - { - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - m_query.status = DT_SUCCESS | details; - } - - if (doneIters) - *doneIters = iter; + m_query.status = DT_SUCCESS; return m_query.status; } @@ -1427,10 +1110,6 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, { // Reverse the path. dtAssert(m_query.lastBestNode); - - if (m_query.lastBestNode->id != m_query.endRef) - m_query.status |= DT_PARTIAL_RESULT; - dtNode* prev = 0; dtNode* node = m_query.lastBestNode; do @@ -1447,24 +1126,17 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, do { path[n++] = node->id; - if (n >= maxPath) - { - m_query.status |= DT_BUFFER_TOO_SMALL; - break; - } node = m_nodePool->getNodeAtIdx(node->pidx); } - while (node); + while (node && n < maxPath); } - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - // Reset query. memset(&m_query, 0, sizeof(dtQueryData)); *pathCount = n; - return DT_SUCCESS | details; + return DT_SUCCESS; } dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize, @@ -1477,7 +1149,7 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing return DT_FAILURE; } - if (dtStatusFailed(m_query.status)) + if (m_query.status != DT_SUCCESS && m_query.status != DT_IN_PROGRESS) { // Reset query. memset(&m_query, 0, sizeof(dtQueryData)); @@ -1505,9 +1177,7 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing if (!node) { - m_query.status |= DT_PARTIAL_RESULT; - dtAssert(m_query.lastBestNode); - node = m_query.lastBestNode; + return DT_FAILURE; } // Reverse the path. @@ -1525,128 +1195,24 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing do { path[n++] = node->id; - if (n >= maxPath) - { - m_query.status |= DT_BUFFER_TOO_SMALL; - break; - } node = m_nodePool->getNodeAtIdx(node->pidx); } - while (node); + while (node && n < maxPath); } - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - // Reset query. memset(&m_query, 0, sizeof(dtQueryData)); *pathCount = n; - return DT_SUCCESS | details; -} - - -dtStatus dtNavMeshQuery::appendVertex(const float* pos, const unsigned char flags, const dtPolyRef ref, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath) const -{ - if ((*straightPathCount) > 0 && dtVequal(&straightPath[((*straightPathCount)-1)*3], pos)) - { - // The vertices are equal, update flags and poly. - if (straightPathFlags) - straightPathFlags[(*straightPathCount)-1] = flags; - if (straightPathRefs) - straightPathRefs[(*straightPathCount)-1] = ref; - } - else - { - // Append new vertex. - dtVcopy(&straightPath[(*straightPathCount)*3], pos); - if (straightPathFlags) - straightPathFlags[(*straightPathCount)] = flags; - if (straightPathRefs) - straightPathRefs[(*straightPathCount)] = ref; - (*straightPathCount)++; - // If reached end of path or there is no space to append more vertices, return. - if (flags == DT_STRAIGHTPATH_END || (*straightPathCount) >= maxStraightPath) - { - return DT_SUCCESS | (((*straightPathCount) >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); - } - } - return DT_IN_PROGRESS; + return DT_SUCCESS; } -dtStatus dtNavMeshQuery::appendPortals(const int startIdx, const int endIdx, const float* endPos, const dtPolyRef* path, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath, const int options) const -{ - const float* startPos = &straightPath[(*straightPathCount-1)*3]; - // Append or update last vertex - dtStatus stat = 0; - for (int i = startIdx; i < endIdx; i++) - { - // Calculate portal - const dtPolyRef from = path[i]; - const dtMeshTile* fromTile = 0; - const dtPoly* fromPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly))) - return DT_FAILURE | DT_INVALID_PARAM; - - const dtPolyRef to = path[i+1]; - const dtMeshTile* toTile = 0; - const dtPoly* toPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(to, &toTile, &toPoly))) - return DT_FAILURE | DT_INVALID_PARAM; - - float left[3], right[3]; - if (dtStatusFailed(getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right))) - break; - - if (options & DT_STRAIGHTPATH_AREA_CROSSINGS) - { - // Skip intersection if only area crossings are requested. - if (fromPoly->getArea() == toPoly->getArea()) - continue; - } - - // Append intersection - float s,t; - if (dtIntersectSegSeg2D(startPos, endPos, left, right, s, t)) - { - float pt[3]; - dtVlerp(pt, left,right, t); - - stat = appendVertex(pt, 0, path[i+1], - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - if (stat != DT_IN_PROGRESS) - return stat; - } - } - return DT_IN_PROGRESS; -} -/// @par -/// -/// This method peforms what is often called 'string pulling'. -/// -/// The start position is clamped to the first polygon in the path, and the -/// end position is clamped to the last. So the start and end positions should -/// normally be within or very near the first and last polygons respectively. -/// -/// The returned polygon references represent the reference id of the polygon -/// that is entered at the associated path position. The reference id associated -/// with the end point will always be zero. This allows, for example, matching -/// off-mesh link points to their representative polygons. -/// -/// If the provided result buffers are too small for the entire result set, -/// they will be filled as far as possible from the start toward the end -/// position. -/// dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* endPos, const dtPolyRef* path, const int pathSize, float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath, const int options) const + int* straightPathCount, const int maxStraightPath) const { dtAssert(m_nav); @@ -1658,23 +1224,29 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en if (!path[0]) return DT_FAILURE | DT_INVALID_PARAM; - dtStatus stat = 0; + int n = 0; // TODO: Should this be callers responsibility? float closestStartPos[3]; if (dtStatusFailed(closestPointOnPolyBoundary(path[0], startPos, closestStartPos))) return DT_FAILURE | DT_INVALID_PARAM; - - float closestEndPos[3]; - if (dtStatusFailed(closestPointOnPolyBoundary(path[pathSize-1], endPos, closestEndPos))) - return DT_FAILURE | DT_INVALID_PARAM; // Add start point. - stat = appendVertex(closestStartPos, DT_STRAIGHTPATH_START, path[0], - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - if (stat != DT_IN_PROGRESS) - return stat; + dtVcopy(&straightPath[n*3], closestStartPos); + if (straightPathFlags) + straightPathFlags[n] = DT_STRAIGHTPATH_START; + if (straightPathRefs) + straightPathRefs[n] = path[0]; + n++; + if (n >= maxStraightPath) + { + *straightPathCount = n; + return DT_SUCCESS; + } + + float closestEndPos[3]; + if (closestPointOnPolyBoundary(path[pathSize-1], endPos, closestEndPos) != DT_SUCCESS) + return DT_FAILURE; if (pathSize > 1) { @@ -1702,28 +1274,17 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en // Next portal. if (dtStatusFailed(getPortalPoints(path[i], path[i+1], left, right, fromType, toType))) { - // Failed to get portal points, in practice this means that path[i+1] is invalid polygon. - // Clamp the end point to path[i], and return the path so far. + if (closestPointOnPolyBoundary(path[i], endPos, closestEndPos) != DT_SUCCESS) + return DT_FAILURE; - if (dtStatusFailed(closestPointOnPolyBoundary(path[i], endPos, closestEndPos))) - { - // This should only happen when the first polygon is invalid. - return DT_FAILURE | DT_INVALID_PARAM; - } - - // Apeend portals along the current straight path segment. - if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) - { - stat = appendPortals(apexIndex, i, closestEndPos, path, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath, options); - } - - stat = appendVertex(closestEndPos, 0, path[i], - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); + dtVcopy(&straightPath[n*3], closestEndPos); + if (straightPathFlags) + straightPathFlags[n] = 0; + if (straightPathRefs) + straightPathRefs[n] = path[i]; + n++; - return DT_SUCCESS | DT_PARTIAL_RESULT | ((*straightPathCount >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); + return DT_SUCCESS; } // If starting really close the portal, advance. @@ -1755,16 +1316,6 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en } else { - // Append portals along the current straight path segment. - if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) - { - stat = appendPortals(apexIndex, leftIndex, portalLeft, path, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath, options); - if (stat != DT_IN_PROGRESS) - return stat; - } - dtVcopy(portalApex, portalLeft); apexIndex = leftIndex; @@ -1775,12 +1326,30 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION; dtPolyRef ref = leftPolyRef; - // Append or update vertex - stat = appendVertex(portalApex, flags, ref, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - if (stat != DT_IN_PROGRESS) - return stat; + if (!dtVequal(&straightPath[(n-1)*3], portalApex)) + { + // Append new vertex. + dtVcopy(&straightPath[n*3], portalApex); + if (straightPathFlags) + straightPathFlags[n] = flags; + if (straightPathRefs) + straightPathRefs[n] = ref; + n++; + // If reached end of path or there is no space to append more vertices, return. + if (flags == DT_STRAIGHTPATH_END || n >= maxStraightPath) + { + *straightPathCount = n; + return DT_SUCCESS; + } + } + else + { + // The vertices are equal, update flags and poly. + if (straightPathFlags) + straightPathFlags[n-1] = flags; + if (straightPathRefs) + straightPathRefs[n-1] = ref; + } dtVcopy(portalLeft, portalApex); dtVcopy(portalRight, portalApex); @@ -1806,16 +1375,6 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en } else { - // Append portals along the current straight path segment. - if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) - { - stat = appendPortals(apexIndex, rightIndex, portalRight, path, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath, options); - if (stat != DT_IN_PROGRESS) - return stat; - } - dtVcopy(portalApex, portalRight); apexIndex = rightIndex; @@ -1825,13 +1384,31 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en else if (rightPolyType == DT_POLYTYPE_OFFMESH_CONNECTION) flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION; dtPolyRef ref = rightPolyRef; - - // Append or update vertex - stat = appendVertex(portalApex, flags, ref, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - if (stat != DT_IN_PROGRESS) - return stat; + + if (!dtVequal(&straightPath[(n-1)*3], portalApex)) + { + // Append new vertex. + dtVcopy(&straightPath[n*3], portalApex); + if (straightPathFlags) + straightPathFlags[n] = flags; + if (straightPathRefs) + straightPathRefs[n] = ref; + n++; + // If reached end of path or there is no space to append more vertices, return. + if (flags == DT_STRAIGHTPATH_END || n >= maxStraightPath) + { + *straightPathCount = n; + return DT_SUCCESS; + } + } + else + { + // The vertices are equal, update flags and poly. + if (straightPathFlags) + straightPathFlags[n-1] = flags; + if (straightPathRefs) + straightPathRefs[n-1] = ref; + } dtVcopy(portalLeft, portalApex); dtVcopy(portalRight, portalApex); @@ -1845,23 +1422,25 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en } } } - - // Append portals along the current straight path segment. - if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) - { - stat = appendPortals(apexIndex, pathSize-1, closestEndPos, path, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath, options); - if (stat != DT_IN_PROGRESS) - return stat; - } } - - stat = appendVertex(closestEndPos, DT_STRAIGHTPATH_END, 0, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - return DT_SUCCESS | ((*straightPathCount >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); + // If the point already exists, remove it and add reappend the actual end location. + if (n > 0 && dtVequal(&straightPath[(n-1)*3], closestEndPos)) + n--; + + // Add end point. + if (n < maxStraightPath) + { + dtVcopy(&straightPath[n*3], closestEndPos); + if (straightPathFlags) + straightPathFlags[n] = DT_STRAIGHTPATH_END; + if (straightPathRefs) + straightPathRefs[n] = 0; + n++; + } + + *straightPathCount = n; + return DT_SUCCESS; } /// @par @@ -1899,8 +1478,6 @@ dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* start if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE | DT_INVALID_PARAM; - dtStatus status = DT_SUCCESS; - static const int MAX_STACK = 48; dtNode* stack[MAX_STACK]; int nstack = 0; @@ -2064,21 +1641,16 @@ dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* start do { visited[n++] = node->id; - if (n >= maxVisitedSize) - { - status |= DT_BUFFER_TOO_SMALL; - break; - } node = m_tinyNodePool->getNodeAtIdx(node->pidx); } - while (node); + while (node && n < maxVisitedSize); } dtVcopy(resultPos, bestPos); *visitedCount = n; - return status; + return DT_SUCCESS; } @@ -2181,7 +1753,7 @@ dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mi { float left[3], right[3]; unsigned char fromType, toType; - if (dtStatusFailed(getPortalPoints(from, to, left,right, fromType, toType))) + if (!getPortalPoints(from, to, left,right, fromType, toType)) return DT_FAILURE | DT_INVALID_PARAM; mid[0] = (left[0]+right[0])*0.5f; mid[1] = (left[1]+right[1])*0.5f; @@ -2262,8 +1834,6 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons hitNormal[1] = 0; hitNormal[2] = 0; - dtStatus status = DT_SUCCESS; - while (curRef) { // Cast ray against current polygon. @@ -2288,7 +1858,7 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons // Could not hit the polygon, keep the old t and report hit. if (pathCount) *pathCount = n; - return status; + return DT_SUCCESS; } // Keep track of furthest t so far. if (tmax > *t) @@ -2297,8 +1867,6 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons // Store visited polygons. if (n < maxPath) path[n++] = curRef; - else - status |= DT_BUFFER_TOO_SMALL; // Ray end is completely inside the polygon. if (segMax == -1) @@ -2306,7 +1874,7 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons *t = FLT_MAX; if (pathCount) *pathCount = n; - return status; + return DT_SUCCESS; } // Follow neighbours. @@ -2408,7 +1976,7 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons if (pathCount) *pathCount = n; - return status; + return DT_SUCCESS; } // No hit, advance to neighbour polygon. @@ -2418,7 +1986,7 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons if (pathCount) *pathCount = n; - return status; + return DT_SUCCESS; } /// @par @@ -2477,8 +2045,6 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* startNode->flags = DT_NODE_OPEN; m_openList->push(startNode); - dtStatus status = DT_SUCCESS; - int n = 0; if (n < maxResult) { @@ -2490,10 +2056,6 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* resultCost[n] = 0; ++n; } - else - { - status |= DT_BUFFER_TOO_SMALL; - } const float radiusSqr = dtSqr(radius); @@ -2549,10 +2111,7 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; continue; - } if (neighbourNode->flags & DT_NODE_CLOSED) continue; @@ -2568,7 +2127,7 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* continue; neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); + neighbourNode->flags &= ~DT_NODE_CLOSED; neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); neighbourNode->total = total; @@ -2588,10 +2147,6 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* resultCost[n] = neighbourNode->total; ++n; } - else - { - status |= DT_BUFFER_TOO_SMALL; - } neighbourNode->flags = DT_NODE_OPEN; m_openList->push(neighbourNode); } @@ -2600,7 +2155,7 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* *resultCount = n; - return status; + return DT_SUCCESS; } /// @par @@ -2657,8 +2212,6 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v startNode->flags = DT_NODE_OPEN; m_openList->push(startNode); - dtStatus status = DT_SUCCESS; - int n = 0; if (n < maxResult) { @@ -2670,10 +2223,6 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v resultCost[n] = 0; ++n; } - else - { - status |= DT_BUFFER_TOO_SMALL; - } while (!m_openList->empty()) { @@ -2729,10 +2278,7 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; continue; - } if (neighbourNode->flags & DT_NODE_CLOSED) continue; @@ -2748,7 +2294,7 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v continue; neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); + neighbourNode->flags &= ~DT_NODE_CLOSED; neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); neighbourNode->total = total; @@ -2768,10 +2314,6 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v resultCost[n] = neighbourNode->total; ++n; } - else - { - status |= DT_BUFFER_TOO_SMALL; - } neighbourNode->flags = DT_NODE_OPEN; m_openList->push(neighbourNode); } @@ -2780,7 +2322,7 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v *resultCount = n; - return status; + return DT_SUCCESS; } /// @par @@ -2836,8 +2378,6 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* float pa[DT_VERTS_PER_POLYGON*3]; float pb[DT_VERTS_PER_POLYGON*3]; - dtStatus status = DT_SUCCESS; - int n = 0; if (n < maxResult) { @@ -2846,10 +2386,6 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* resultParent[n] = 0; ++n; } - else - { - status |= DT_BUFFER_TOO_SMALL; - } while (nstack) { @@ -2963,10 +2499,6 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* resultParent[n] = curRef; ++n; } - else - { - status |= DT_BUFFER_TOO_SMALL; - } if (nstack < MAX_STACK) { @@ -2977,18 +2509,17 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* *resultCount = n; - return status; + return DT_SUCCESS; } struct dtSegInterval { - dtPolyRef ref; short tmin, tmax; }; static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts, - const short tmin, const short tmax, const dtPolyRef ref) + const short tmin, const short tmax) { if (nints+1 > maxInts) return; // Find insertion point. @@ -3003,7 +2534,6 @@ static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts, if (nints-idx) memmove(ints+idx+1, ints+idx, sizeof(dtSegInterval)*(nints-idx)); // Store - ints[idx].ref = ref; ints[idx].tmin = tmin; ints[idx].tmax = tmax; nints++; @@ -3021,8 +2551,7 @@ static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts, /// maximum segments per polygon of the source navigation mesh. /// dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, - float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount, - const int maxSegments) const + float* segments, int* segmentCount, const int maxSegments) const { dtAssert(m_nav); @@ -3038,10 +2567,6 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* dtSegInterval ints[MAX_INTERVAL]; int nints; - const bool storePortals = segmentRefs != 0; - - dtStatus status = DT_SUCCESS; - for (int i = 0, j = (int)poly->vertCount-1; i < (int)poly->vertCount; j = i++) { // Skip non-solid edges. @@ -3061,95 +2586,54 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly); if (filter->passFilter(link->ref, neiTile, neiPoly)) { - insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax, link->ref); + insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax); } } } } } - else + else if (poly->neis[j]) { // Internal edge - dtPolyRef neiRef = 0; - if (poly->neis[j]) - { - const unsigned int idx = (unsigned int)(poly->neis[j]-1); - neiRef = m_nav->getPolyRefBase(tile) | idx; - if (!filter->passFilter(neiRef, tile, &tile->polys[idx])) - neiRef = 0; - } - - // If the edge leads to another polygon and portals are not stored, skip. - if (neiRef != 0 && !storePortals) + const unsigned int idx = (unsigned int)(poly->neis[j]-1); + const dtPolyRef ref = m_nav->getPolyRefBase(tile) | idx; + if (filter->passFilter(ref, tile, &tile->polys[idx])) continue; - - if (n < maxSegments) - { - const float* vj = &tile->verts[poly->verts[j]*3]; - const float* vi = &tile->verts[poly->verts[i]*3]; - float* seg = &segmentVerts[n*6]; - dtVcopy(seg+0, vj); - dtVcopy(seg+3, vi); - if (segmentRefs) - segmentRefs[n] = neiRef; - n++; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - continue; } // Add sentinels - insertInterval(ints, nints, MAX_INTERVAL, -1, 0, 0); - insertInterval(ints, nints, MAX_INTERVAL, 255, 256, 0); + insertInterval(ints, nints, MAX_INTERVAL, -1, 0); + insertInterval(ints, nints, MAX_INTERVAL, 255, 256); - // Store segments. + // Store segment. const float* vj = &tile->verts[poly->verts[j]*3]; const float* vi = &tile->verts[poly->verts[i]*3]; for (int k = 1; k < nints; ++k) { - // Portal segment. - if (storePortals && ints[k].ref) + // Find the space inbetween the opening areas. + const int imin = ints[k-1].tmax; + const int imax = ints[k].tmin; + if (imin == imax) continue; + if (imin == 0 && imax == 255) { - const float tmin = ints[k].tmin/255.0f; - const float tmax = ints[k].tmax/255.0f; if (n < maxSegments) { - float* seg = &segmentVerts[n*6]; - dtVlerp(seg+0, vj,vi, tmin); - dtVlerp(seg+3, vj,vi, tmax); - if (segmentRefs) - segmentRefs[n] = ints[k].ref; + float* seg = &segments[n*6]; n++; - } - else - { - status |= DT_BUFFER_TOO_SMALL; + dtVcopy(seg+0, vj); + dtVcopy(seg+3, vi); } } - - // Wall segment. - const int imin = ints[k-1].tmax; - const int imax = ints[k].tmin; - if (imin != imax) + else { const float tmin = imin/255.0f; const float tmax = imax/255.0f; if (n < maxSegments) { - float* seg = &segmentVerts[n*6]; + float* seg = &segments[n*6]; + n++; dtVlerp(seg+0, vj,vi, tmin); dtVlerp(seg+3, vj,vi, tmax); - if (segmentRefs) - segmentRefs[n] = 0; - n++; - } - else - { - status |= DT_BUFFER_TOO_SMALL; } } } @@ -3157,7 +2641,7 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* *segmentCount = n; - return status; + return DT_SUCCESS; } /// @par @@ -3196,8 +2680,6 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen float radiusSqr = dtSqr(maxRadius); - dtStatus status = DT_SUCCESS; - while (!m_openList->empty()) { dtNode* bestNode = m_openList->pop(); @@ -3305,10 +2787,7 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; continue; - } if (neighbourNode->flags & DT_NODE_CLOSED) continue; @@ -3327,7 +2806,7 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen continue; neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); + neighbourNode->flags &= ~DT_NODE_CLOSED; neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); neighbourNode->total = total; @@ -3347,23 +2826,9 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen dtVsub(hitNormal, centerPos, hitPos); dtVnormalize(hitNormal); - *hitDist = dtSqrt(radiusSqr); + *hitDist = sqrtf(radiusSqr); - return status; -} - -bool dtNavMeshQuery::isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const -{ - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - dtStatus status = m_nav->getTileAndPolyByRef(ref, &tile, &poly); - // If cannot get polygon, assume it does not exists and boundary is invalid. - if (dtStatusFailed(status)) - return false; - // If cannot pass filter, assume flags has changed and boundary is invalid. - if (!filter->passFilter(ref, tile, poly)) - return false; - return true; + return DT_SUCCESS; } /// @par |