aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjackpoz <giacomopoz@gmail.com>2014-02-13 22:19:56 +0100
committerjackpoz <giacomopoz@gmail.com>2014-02-13 22:19:56 +0100
commit006d72a8289a3956bc06f528c457e350227e0cef (patch)
treed2cc0beb1aba63e5a4c112e7a6e2a8d1918f425b
parentb9db1ab24e4f818a5eedb00f1992139920855d3d (diff)
Core/MMAPS: Fix invisible wall issue in MMAPS.
Fix invisible wall issues in MMAPS caused by tile connections not being extracted correctly. This reverts aa645683b8b25bfb35cb977678daf5c56c1531e6 and restores an old version of recastnavigation, most likely https://github.com/memononen/recastnavigation/commit/1be9de72d87dcfdecf6bea30f5461745f7d7afe6 . Re-extracting MMAPS is required.
-rw-r--r--dep/recastnavigation/Detour/DetourNavMesh.cpp367
-rw-r--r--dep/recastnavigation/Detour/DetourNavMesh.h70
-rw-r--r--dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp341
-rw-r--r--dep/recastnavigation/Detour/DetourNavMeshBuilder.h8
-rw-r--r--dep/recastnavigation/Detour/DetourNavMeshQuery.cpp1019
-rw-r--r--dep/recastnavigation/Detour/DetourNavMeshQuery.h282
-rw-r--r--dep/recastnavigation/Detour/DetourNode.cpp16
-rw-r--r--dep/recastnavigation/Detour/DetourNode.h15
-rw-r--r--dep/recastnavigation/Recast/CMakeLists.txt1
-rw-r--r--dep/recastnavigation/Recast/Recast.cpp30
-rw-r--r--dep/recastnavigation/Recast/Recast.h280
-rw-r--r--dep/recastnavigation/Recast/RecastArea.cpp170
-rw-r--r--dep/recastnavigation/Recast/RecastContour.cpp60
-rw-r--r--dep/recastnavigation/Recast/RecastFilter.cpp4
-rw-r--r--dep/recastnavigation/Recast/RecastMesh.cpp123
-rw-r--r--dep/recastnavigation/Recast/RecastMeshDetail.cpp29
-rw-r--r--dep/recastnavigation/Recast/RecastRegion.cpp65
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Movement/PathGenerator.cpp2
-rw-r--r--src/tools/mmaps_generator/MapBuilder.cpp15
20 files changed, 808 insertions, 2091 deletions
diff --git a/dep/recastnavigation/Detour/DetourNavMesh.cpp b/dep/recastnavigation/Detour/DetourNavMesh.cpp
index 6b8e2d9d649..49100b09816 100644
--- a/dep/recastnavigation/Detour/DetourNavMesh.cpp
+++ b/dep/recastnavigation/Detour/DetourNavMesh.cpp
@@ -297,7 +297,6 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
float amin[2], amax[2];
calcSlabEndPoints(va,vb, amin,amax, side);
- const float apos = getSlabCoord(va, side);
// Remove links pointing to 'side' and compact the links array.
float bmin[2], bmax[2];
@@ -317,13 +316,6 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
const float* vc = &tile->verts[poly->verts[j]*3];
const float* vd = &tile->verts[poly->verts[(j+1) % nv]*3];
- const float bpos = getSlabCoord(vc, side);
-
- // Segments are not close enough.
- if (dtAbs(apos-bpos) > 0.01f)
- continue;
-
- // Check if the segments touch.
calcSlabEndPoints(vc,vd, bmin,bmax, side);
if (!overlapSlabs(amin,amax, bmin,bmax, 0.01f, tile->header->walkableClimb)) continue;
@@ -342,11 +334,9 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
return n;
}
-void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target)
+void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, int side)
{
- if (!tile || !target) return;
-
- const unsigned int targetNum = decodePolyIdTile(getTileRef(target));
+ if (!tile) return;
for (int i = 0; i < tile->header->polyCount; ++i)
{
@@ -355,8 +345,7 @@ void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target)
unsigned int pj = DT_NULL_LINK;
while (j != DT_NULL_LINK)
{
- if (tile->links[j].side != 0xff &&
- decodePolyIdTile(tile->links[j].ref) == targetNum)
+ if (tile->links[j].side == side)
{
// Revove link.
unsigned int nj = tile->links[j].next;
@@ -387,25 +376,20 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
dtPoly* poly = &tile->polys[i];
// Create new links.
-// unsigned short m = DT_EXT_LINK | (unsigned short)side;
+ unsigned short m = DT_EXT_LINK | (unsigned short)side;
const int nv = poly->vertCount;
for (int j = 0; j < nv; ++j)
{
// Skip non-portal edges.
- if ((poly->neis[j] & DT_EXT_LINK) == 0)
- continue;
-
- const int dir = (int)(poly->neis[j] & 0xff);
- if (side != -1 && dir != side)
- continue;
+ if (poly->neis[j] != m) continue;
// Create new links
const float* va = &tile->verts[poly->verts[j]*3];
const float* vb = &tile->verts[poly->verts[(j+1) % nv]*3];
dtPolyRef nei[4];
float neia[4*2];
- int nnei = findConnectingPolys(va,vb, target, dtOppositeTile(dir), nei,neia,4);
+ int nnei = findConnectingPolys(va,vb, target, dtOppositeTile(side), nei,neia,4);
for (int k = 0; k < nnei; ++k)
{
unsigned int idx = allocLink(tile);
@@ -414,13 +398,13 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
dtLink* link = &tile->links[idx];
link->ref = nei[k];
link->edge = (unsigned char)j;
- link->side = (unsigned char)dir;
+ link->side = (unsigned char)side;
link->next = poly->firstLink;
poly->firstLink = idx;
// Compress portal limits to a byte value.
- if (dir == 0 || dir == 4)
+ if (side == 0 || side == 4)
{
float tmin = (neia[k*2+0]-va[2]) / (vb[2]-va[2]);
float tmax = (neia[k*2+1]-va[2]) / (vb[2]-va[2]);
@@ -429,7 +413,7 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f);
link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f);
}
- else if (dir == 2 || dir == 6)
+ else if (side == 2 || side == 6)
{
float tmin = (neia[k*2+0]-va[0]) / (vb[0]-va[0]);
float tmax = (neia[k*2+1]-va[0]) / (vb[0]-va[0]);
@@ -450,7 +434,7 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
// Connect off-mesh links.
// We are interested on links which land from target tile to this tile.
- const unsigned char oppositeSide = (side == -1) ? 0xff : (unsigned char)dtOppositeTile(side);
+ const unsigned char oppositeSide = (unsigned char)dtOppositeTile(side);
for (int i = 0; i < target->header->offMeshConCount; ++i)
{
@@ -459,9 +443,6 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
continue;
dtPoly* targetPoly = &target->polys[targetCon->poly];
- // Skip off-mesh connections which start location could not be connected at all.
- if (targetPoly->firstLink == DT_NULL_LINK)
- continue;
const float ext[3] = { targetCon->rad, target->header->walkableClimb, targetCon->rad };
@@ -495,19 +476,19 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
// Link target poly to off-mesh connection.
if (targetCon->flags & DT_OFFMESH_CON_BIDIR)
{
- unsigned int tidx = allocLink(tile);
- if (tidx != DT_NULL_LINK)
+ unsigned int idx = allocLink(tile);
+ if (idx != DT_NULL_LINK)
{
const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
dtPoly* landPoly = &tile->polys[landPolyIdx];
- dtLink* link = &tile->links[tidx];
+ dtLink* link = &tile->links[idx];
link->ref = getPolyRefBase(target) | (dtPolyRef)(targetCon->poly);
link->edge = 0xff;
- link->side = (unsigned char)(side == -1 ? 0xff : side);
+ link->side = (unsigned char)side;
link->bmin = link->bmax = 0;
// Add to linked list.
link->next = landPoly->firstLink;
- landPoly->firstLink = tidx;
+ landPoly->firstLink = idx;
}
}
}
@@ -551,13 +532,13 @@ void dtNavMesh::connectIntLinks(dtMeshTile* tile)
}
}
-void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
+void dtNavMesh::connectIntOffMeshLinks(dtMeshTile* tile)
{
if (!tile) return;
dtPolyRef base = getPolyRefBase(tile);
- // Base off-mesh connection start points.
+ // Find Off-mesh connection end points.
for (int i = 0; i < tile->header->offMeshConCount; ++i)
{
dtOffMeshConnection* con = &tile->offMeshCons[i];
@@ -565,96 +546,72 @@ void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
const float ext[3] = { con->rad, tile->header->walkableClimb, con->rad };
- // Find polygon to connect to.
- const float* p = &con->pos[0]; // First vertex
- float nearestPt[3];
- dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt);
- if (!ref) continue;
- // findNearestPoly may return too optimistic results, further check to make sure.
- if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad))
- continue;
- // Make sure the location is on current mesh.
- float* v = &tile->verts[poly->verts[0]*3];
- dtVcopy(v, nearestPt);
-
- // Link off-mesh connection to target poly.
- unsigned int idx = allocLink(tile);
- if (idx != DT_NULL_LINK)
+ for (int j = 0; j < 2; ++j)
{
- dtLink* link = &tile->links[idx];
- link->ref = ref;
- link->edge = (unsigned char)0;
- link->side = 0xff;
- link->bmin = link->bmax = 0;
- // Add to linked list.
- link->next = poly->firstLink;
- poly->firstLink = idx;
- }
+ unsigned char side = j == 0 ? 0xff : con->side;
- // Start end-point is always connect back to off-mesh connection.
- unsigned int tidx = allocLink(tile);
- if (tidx != DT_NULL_LINK)
- {
- const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
- dtPoly* landPoly = &tile->polys[landPolyIdx];
- dtLink* link = &tile->links[tidx];
- link->ref = base | (dtPolyRef)(con->poly);
- link->edge = 0xff;
- link->side = 0xff;
- link->bmin = link->bmax = 0;
- // Add to linked list.
- link->next = landPoly->firstLink;
- landPoly->firstLink = tidx;
+ if (side == 0xff)
+ {
+ // Find polygon to connect to.
+ const float* p = &con->pos[j*3];
+ float nearestPt[3];
+ dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt);
+ if (!ref) continue;
+ // findNearestPoly may return too optimistic results, further check to make sure.
+ if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad))
+ continue;
+ // Make sure the location is on current mesh.
+ float* v = &tile->verts[poly->verts[j]*3];
+ dtVcopy(v, nearestPt);
+
+ // Link off-mesh connection to target poly.
+ unsigned int idx = allocLink(tile);
+ if (idx != DT_NULL_LINK)
+ {
+ dtLink* link = &tile->links[idx];
+ link->ref = ref;
+ link->edge = (unsigned char)j;
+ link->side = 0xff;
+ link->bmin = link->bmax = 0;
+ // Add to linked list.
+ link->next = poly->firstLink;
+ poly->firstLink = idx;
+ }
+
+ // Start end-point is always connect back to off-mesh connection,
+ // Destination end-point only if it is bidirectional link.
+ if (j == 0 || (j == 1 && (con->flags & DT_OFFMESH_CON_BIDIR)))
+ {
+ // Link target poly to off-mesh connection.
+ unsigned int idx = allocLink(tile);
+ if (idx != DT_NULL_LINK)
+ {
+ const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
+ dtPoly* landPoly = &tile->polys[landPolyIdx];
+ dtLink* link = &tile->links[idx];
+ link->ref = base | (dtPolyRef)(con->poly);
+ link->edge = 0xff;
+ link->side = 0xff;
+ link->bmin = link->bmax = 0;
+ // Add to linked list.
+ link->next = landPoly->firstLink;
+ landPoly->firstLink = idx;
+ }
+ }
+
+ }
}
}
}
-void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
- const float* pos, float* closest) const
+dtStatus dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
+ const float* pos, float* closest) const
{
const dtPoly* poly = &tile->polys[ip];
- // 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;
- }
+ float closestDistSqr = FLT_MAX;
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];
@@ -666,13 +623,17 @@ void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip
else
v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3];
}
- float h;
- if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h))
+ float pt[3];
+ dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]);
+ float d = dtVdistSqr(pos, pt);
+ if (d < closestDistSqr)
{
- closest[1] = h;
- break;
+ dtVcopy(closest, pt);
+ closestDistSqr = d;
}
}
+
+ return DT_SUCCESS;
}
dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile,
@@ -694,7 +655,8 @@ dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile,
{
dtPolyRef ref = polys[i];
float closestPtPoly[3];
- closestPointOnPolyInTile(tile, decodePolyIdPoly(ref), center, closestPtPoly);
+ if (closestPointOnPolyInTile(tile, decodePolyIdPoly(ref), center, closestPtPoly) != DT_SUCCESS)
+ continue;
float d = dtVdistSqr(center, closestPtPoly);
if (d < nearestDistanceSqr)
{
@@ -768,11 +730,8 @@ int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, co
dtPolyRef base = getPolyRefBase(tile);
for (int i = 0; i < tile->header->polyCount; ++i)
{
- dtPoly* p = &tile->polys[i];
- // Do not return off-mesh connection polygons.
- if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
- continue;
// Calc polygon bounds.
+ dtPoly* p = &tile->polys[i];
const float* v = &tile->verts[p->verts[0]*3];
dtVcopy(bmin, v);
dtVcopy(bmax, v);
@@ -814,7 +773,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
return DT_FAILURE | DT_WRONG_VERSION;
// Make sure the location is free.
- if (getTileAt(header->x, header->y, header->layer))
+ if (getTileAt(header->x, header->y))
return DT_FAILURE;
// Allocate a tile.
@@ -886,10 +845,6 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
tile->bvTree = (dtBVNode*)d; d += bvtreeSize;
tile->offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize;
- // If there are no items in the bvtree, reset the tree pointer.
- if (!bvtreeSize)
- tile->bvTree = 0;
-
// Build links freelist
tile->linksFreeList = 0;
tile->links[header->maxLinkCount-1].next = DT_NULL_LINK;
@@ -903,36 +858,18 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
tile->flags = flags;
connectIntLinks(tile);
- baseOffMeshLinks(tile);
+ connectIntOffMeshLinks(tile);
// Create connections with neighbour tiles.
- static const int MAX_NEIS = 32;
- dtMeshTile* neis[MAX_NEIS];
- int nneis;
-
- // Connect with layers in current tile.
- nneis = getTilesAt(header->x, header->y, neis, MAX_NEIS);
- for (int j = 0; j < nneis; ++j)
- {
- if (neis[j] != tile)
- {
- connectExtLinks(tile, neis[j], -1);
- connectExtLinks(neis[j], tile, -1);
- }
- connectExtOffMeshLinks(tile, neis[j], -1);
- connectExtOffMeshLinks(neis[j], tile, -1);
- }
-
- // Connect with neighbour tiles.
for (int i = 0; i < 8; ++i)
{
- nneis = getNeighbourTilesAt(header->x, header->y, i, neis, MAX_NEIS);
- for (int j = 0; j < nneis; ++j)
+ dtMeshTile* nei = getNeighbourTileAt(header->x, header->y, i);
+ if (nei)
{
- connectExtLinks(tile, neis[j], i);
- connectExtLinks(neis[j], tile, dtOppositeTile(i));
- connectExtOffMeshLinks(tile, neis[j], i);
- connectExtOffMeshLinks(neis[j], tile, dtOppositeTile(i));
+ connectExtLinks(tile, nei, i);
+ connectExtLinks(nei, tile, dtOppositeTile(i));
+ connectExtOffMeshLinks(tile, nei, i);
+ connectExtOffMeshLinks(nei, tile, dtOppositeTile(i));
}
}
@@ -942,106 +879,55 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
return DT_SUCCESS;
}
-const dtMeshTile* dtNavMesh::getTileAt(const int x, const int y, const int layer) const
+const dtMeshTile* dtNavMesh::getTileAt(int x, int y) const
{
// Find tile based on hash.
int h = computeTileHash(x,y,m_tileLutMask);
dtMeshTile* tile = m_posLookup[h];
while (tile)
{
- if (tile->header &&
- tile->header->x == x &&
- tile->header->y == y &&
- tile->header->layer == layer)
- {
+ if (tile->header && tile->header->x == x && tile->header->y == y)
return tile;
- }
tile = tile->next;
}
return 0;
}
-int dtNavMesh::getNeighbourTilesAt(const int x, const int y, const int side, dtMeshTile** tiles, const int maxTiles) const
+dtMeshTile* dtNavMesh::getNeighbourTileAt(int x, int y, int side) const
{
- int nx = x, ny = y;
switch (side)
{
- case 0: nx++; break;
- case 1: nx++; ny++; break;
- case 2: ny++; break;
- case 3: nx--; ny++; break;
- case 4: nx--; break;
- case 5: nx--; ny--; break;
- case 6: ny--; break;
- case 7: nx++; ny--; break;
+ case 0: x++; break;
+ case 1: x++; y++; break;
+ case 2: y++; break;
+ case 3: x--; y++; break;
+ case 4: x--; break;
+ case 5: x--; y--; break;
+ case 6: y--; break;
+ case 7: x++; y--; break;
};
- return getTilesAt(nx, ny, tiles, maxTiles);
-}
-
-int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile** tiles, const int maxTiles) const
-{
- int n = 0;
-
- // Find tile based on hash.
- int h = computeTileHash(x,y,m_tileLutMask);
- dtMeshTile* tile = m_posLookup[h];
- while (tile)
- {
- if (tile->header &&
- tile->header->x == x &&
- tile->header->y == y)
- {
- if (n < maxTiles)
- tiles[n++] = tile;
- }
- tile = tile->next;
- }
-
- return n;
-}
-
-/// @par
-///
-/// This function will not fail if the tiles array is too small to hold the
-/// entire result set. It will simply fill the array to capacity.
-int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile const** tiles, const int maxTiles) const
-{
- int n = 0;
-
// Find tile based on hash.
int h = computeTileHash(x,y,m_tileLutMask);
dtMeshTile* tile = m_posLookup[h];
while (tile)
{
- if (tile->header &&
- tile->header->x == x &&
- tile->header->y == y)
- {
- if (n < maxTiles)
- tiles[n++] = tile;
- }
+ if (tile->header && tile->header->x == x && tile->header->y == y)
+ return tile;
tile = tile->next;
}
-
- return n;
+ return 0;
}
-
-dtTileRef dtNavMesh::getTileRefAt(const int x, const int y, const int layer) const
+dtTileRef dtNavMesh::getTileRefAt(int x, int y) const
{
// Find tile based on hash.
int h = computeTileHash(x,y,m_tileLutMask);
dtMeshTile* tile = m_posLookup[h];
while (tile)
{
- if (tile->header &&
- tile->header->x == x &&
- tile->header->y == y &&
- tile->header->layer == layer)
- {
+ if (tile->header && tile->header->x == x && tile->header->y == y)
return getTileRef(tile);
- }
tile = tile->next;
}
return 0;
@@ -1084,7 +970,6 @@ void dtNavMesh::calcTileLoc(const float* pos, int* tx, int* ty) const
dtStatus dtNavMesh::getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const
{
- if (!ref) return DT_FAILURE;
unsigned int salt, it, ip;
decodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
@@ -1110,7 +995,6 @@ void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile*
bool dtNavMesh::isValidPolyRef(dtPolyRef ref) const
{
- if (!ref) return false;
unsigned int salt, it, ip;
decodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return false;
@@ -1156,27 +1040,14 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz
}
// Remove connections to neighbour tiles.
- // Create connections with neighbour tiles.
- static const int MAX_NEIS = 32;
- dtMeshTile* neis[MAX_NEIS];
- int nneis;
-
- // Connect with layers in current tile.
- nneis = getTilesAt(tile->header->x, tile->header->y, neis, MAX_NEIS);
- for (int j = 0; j < nneis; ++j)
- {
- if (neis[j] == tile) continue;
- unconnectExtLinks(neis[j], tile);
- }
-
- // Connect with neighbour tiles.
for (int i = 0; i < 8; ++i)
{
- nneis = getNeighbourTilesAt(tile->header->x, tile->header->y, i, neis, MAX_NEIS);
- for (int j = 0; j < nneis; ++j)
- unconnectExtLinks(neis[j], tile);
+ dtMeshTile* nei = getNeighbourTileAt(tile->header->x,tile->header->y,i);
+ if (!nei) continue;
+ unconnectExtLinks(nei, dtOppositeTile(i));
}
-
+
+
// Reset tile.
if (tile->flags & DT_TILE_FREE_DATA)
{
@@ -1220,7 +1091,7 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz
dtTileRef dtNavMesh::getTileRef(const dtMeshTile* tile) const
{
if (!tile) return 0;
- const unsigned int it = (unsigned int)(tile - m_tiles);
+ const unsigned int it = tile - m_tiles;
return (dtTileRef)encodePolyId(tile->salt, it, 0);
}
@@ -1241,7 +1112,7 @@ dtTileRef dtNavMesh::getTileRef(const dtMeshTile* tile) const
dtPolyRef dtNavMesh::getPolyRefBase(const dtMeshTile* tile) const
{
if (!tile) return 0;
- const unsigned int it = (unsigned int)(tile - m_tiles);
+ const unsigned int it = tile - m_tiles;
return encodePolyId(tile->salt, it, 0);
}
@@ -1345,9 +1216,6 @@ dtStatus dtNavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyR
{
unsigned int salt, it, ip;
- if (!polyRef)
- return DT_FAILURE;
-
// Get current polygon
decodePolyId(polyRef, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
@@ -1388,9 +1256,6 @@ const dtOffMeshConnection* dtNavMesh::getOffMeshConnectionByRef(dtPolyRef ref) c
{
unsigned int salt, it, ip;
- if (!ref)
- return 0;
-
// Get current polygon
decodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return 0;
@@ -1411,7 +1276,6 @@ const dtOffMeshConnection* dtNavMesh::getOffMeshConnectionByRef(dtPolyRef ref) c
dtStatus dtNavMesh::setPolyFlags(dtPolyRef ref, unsigned short flags)
{
- if (!ref) return DT_FAILURE;
unsigned int salt, it, ip;
decodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
@@ -1428,7 +1292,6 @@ dtStatus dtNavMesh::setPolyFlags(dtPolyRef ref, unsigned short flags)
dtStatus dtNavMesh::getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const
{
- if (!ref) return DT_FAILURE;
unsigned int salt, it, ip;
decodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
@@ -1444,7 +1307,6 @@ dtStatus dtNavMesh::getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) con
dtStatus dtNavMesh::setPolyArea(dtPolyRef ref, unsigned char area)
{
- if (!ref) return DT_FAILURE;
unsigned int salt, it, ip;
decodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
@@ -1460,7 +1322,6 @@ dtStatus dtNavMesh::setPolyArea(dtPolyRef ref, unsigned char area)
dtStatus dtNavMesh::getPolyArea(dtPolyRef ref, unsigned char* resultArea) const
{
- if (!ref) return DT_FAILURE;
unsigned int salt, it, ip;
decodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
diff --git a/dep/recastnavigation/Detour/DetourNavMesh.h b/dep/recastnavigation/Detour/DetourNavMesh.h
index 9c61a9bb649..7175f8e73eb 100644
--- a/dep/recastnavigation/Detour/DetourNavMesh.h
+++ b/dep/recastnavigation/Detour/DetourNavMesh.h
@@ -44,10 +44,6 @@ typedef uint64_t uint64_d;
// Edited by TC
// We cannot have over 31 bits for either tile nor poly
// without changing polyCount to use 64bits too.
-static const int STATIC_SALT_BITS = 12;
-static const int STATIC_TILE_BITS = 21;
-static const int STATIC_POLY_BITS = 31;
-
/// A handle to a polygon within a navigation mesh tile.
/// @ingroup detour
typedef uint64_d dtPolyRef; // Edited by TC
@@ -70,7 +66,7 @@ static const int DT_VERTS_PER_POLYGON = 6;
static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V';
/// A version number used to detect compatibility of navigation tile data.
-static const int DT_NAVMESH_VERSION = 7;
+static const int DT_NAVMESH_VERSION = 6;
/// A magic number used to detect the compatibility of navigation tile states.
static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S';
@@ -94,6 +90,12 @@ static const unsigned int DT_OFFMESH_CON_BIDIR = 1;
/// @ingroup detour
static const int DT_MAX_AREAS = 64;
+static const int STATIC_SALT_BITS = 12;
+static const int STATIC_TILE_BITS = 21;
+static const int STATIC_POLY_BITS = 31;
+// we cannot have over 31 bits for either tile nor poly
+// without changing polyCount to use 64bits too.
+
/// Tile flags used for various functions and fields.
/// For an example, see dtNavMesh::addTile().
enum dtTileFlags
@@ -110,12 +112,6 @@ enum dtStraightPathFlags
DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is the start of an off-mesh connection.
};
-/// Options for dtNavMeshQuery::findStraightPath.
-enum dtStraightPathOptions
-{
- DT_STRAIGHTPATH_AREA_CROSSINGS = 0x01, ///< Add a vertex at every polygon edge crossing where area changes.
- DT_STRAIGHTPATH_ALL_CROSSINGS = 0x02, ///< Add a vertex at every polygon edge crossing.
-};
/// Flags representing the type of a navigation mesh polygon.
enum dtPolyTypes
@@ -229,7 +225,6 @@ struct dtMeshHeader
int version; ///< Tile data format version number.
int x; ///< The x-position of the tile within the dtNavMesh tile grid. (x, y, layer)
int y; ///< The y-position of the tile within the dtNavMesh tile grid. (x, y, layer)
- int layer; ///< The layer of the tile within the dtNavMesh tile grid. (x, y, layer)
unsigned int userId; ///< The user defined id of the tile.
int polyCount; ///< The number of polygons in the tile.
int vertCount; ///< The number of vertices in the tile.
@@ -352,31 +347,18 @@ public:
void calcTileLoc(const float* pos, int* tx, int* ty) const;
/// Gets the tile at the specified grid location.
- /// @param[in] x The tile's x-location. (x, y, layer)
- /// @param[in] y The tile's y-location. (x, y, layer)
- /// @param[in] layer The tile's layer. (x, y, layer)
- /// @return The tile, or null if the tile does not exist.
- const dtMeshTile* getTileAt(const int x, const int y, const int layer) const;
-
- /// Gets all tiles at the specified grid location. (All layers.)
- /// @param[in] x The tile's x-location. (x, y)
- /// @param[in] y The tile's y-location. (x, y)
- /// @param[out] tiles A pointer to an array of tiles that will hold the result.
- /// @param[in] maxTiles The maximum tiles the tiles parameter can hold.
- /// @return The number of tiles returned in the tiles array.
- int getTilesAt(const int x, const int y,
- dtMeshTile const** tiles, const int maxTiles) const;
+ // Params:
+ // x,y - (in) Location of the tile to get.
+ // Returns: pointer to tile if tile exists or 0 tile does not exists.
+ const dtMeshTile* getTileAt(int x, int y) const;
+
+ // Returns reference to tile at specified location.
+ // Params:
+ // x,y - (in) Location of the tile to get.
+ // Returns: reference to tile if tile exists or 0 tile does not exists.
+ dtTileRef getTileRefAt(int x, int y) const;
- /// Gets the tile reference for the tile at specified grid location.
- /// @param[in] x The tile's x-location. (x, y, layer)
- /// @param[in] y The tile's y-location. (x, y, layer)
- /// @param[in] layer The tile's layer. (x, y, layer)
- /// @return The tile reference of the tile, or 0 if there is none.
- dtTileRef getTileRefAt(int x, int y, int layer) const;
-
- /// Gets the tile reference for the specified tile.
- /// @param[in] tile The tile.
- /// @return The tile reference of the tile.
+ // Returns tile references of a tile based on tile pointer.
dtTileRef getTileRef(const dtMeshTile* tile) const;
/// Gets the tile for the specified tile reference.
@@ -550,13 +532,7 @@ private:
dtMeshTile* getTile(int i);
/// Returns neighbour tile based on side.
- int getTilesAt(const int x, const int y,
- dtMeshTile** tiles, const int maxTiles) const;
-
- /// Returns neighbour tile based on side.
- int getNeighbourTilesAt(const int x, const int y, const int side,
- dtMeshTile** tiles, const int maxTiles) const;
-
+ dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
/// Returns all polygons in neighbour tile based on portal defined by the segment.
int findConnectingPolys(const float* va, const float* vb,
const dtMeshTile* tile, int side,
@@ -565,7 +541,7 @@ private:
/// Builds internal polygons links for a tile.
void connectIntLinks(dtMeshTile* tile);
/// Builds internal polygons links for a tile.
- void baseOffMeshLinks(dtMeshTile* tile);
+ void connectIntOffMeshLinks(dtMeshTile* tile);
/// Builds external polygon links for a tile.
void connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side);
@@ -573,7 +549,7 @@ private:
void connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side);
/// Removes external links at specified side.
- void unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target);
+ void unconnectExtLinks(dtMeshTile* tile, int side);
// TODO: These methods are duplicates from dtNavMeshQuery, but are needed for off-mesh connection finding.
@@ -585,8 +561,8 @@ private:
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center,
const float* extents, float* nearestPt) const;
/// Returns closest point on polygon.
- void closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
- const float* pos, float* closest) const;
+ dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
+ const float* pos, float* closest) const;
dtNavMeshParams m_params; ///< Current initialization params. TODO: do not store this info twice.
float m_orig[3]; ///< Origin of the tile (0,0)
diff --git a/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp b/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
index 9d8471b96a1..fcac215fff4 100644
--- a/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
+++ b/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
@@ -261,6 +261,8 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
return false;
if (!params->polyCount || !params->polys)
return false;
+ if (!params->detailMeshes || !params->detailVerts || !params->detailTris)
+ return false;
const int nvp = params->nvp;
@@ -276,50 +278,10 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
if (!offMeshConClass)
return false;
- // Find tight heigh bounds, used for culling out off-mesh start locations.
- float hmin = FLT_MAX;
- float hmax = -FLT_MAX;
-
- if (params->detailVerts && params->detailVertsCount)
- {
- for (int i = 0; i < params->detailVertsCount; ++i)
- {
- const float h = params->detailVerts[i*3+1];
- hmin = dtMin(hmin,h);
- hmax = dtMax(hmax,h);
- }
- }
- else
- {
- for (int i = 0; i < params->vertCount; ++i)
- {
- const unsigned short* iv = &params->verts[i*3];
- const float h = params->bmin[1] + iv[1] * params->ch;
- hmin = dtMin(hmin,h);
- hmax = dtMax(hmax,h);
- }
- }
- hmin -= params->walkableClimb;
- hmax += params->walkableClimb;
- float bmin[3], bmax[3];
- dtVcopy(bmin, params->bmin);
- dtVcopy(bmax, params->bmax);
- bmin[1] = hmin;
- bmax[1] = hmax;
-
for (int i = 0; i < params->offMeshConCount; ++i)
{
- const float* p0 = &params->offMeshConVerts[(i*2+0)*3];
- const float* p1 = &params->offMeshConVerts[(i*2+1)*3];
- offMeshConClass[i*2+0] = classifyOffMeshPoint(p0, bmin, bmax);
- offMeshConClass[i*2+1] = classifyOffMeshPoint(p1, bmin, bmax);
-
- // Zero out off-mesh start positions which are not even potentially touching the mesh.
- if (offMeshConClass[i*2+0] == 0xff)
- {
- if (p0[1] < bmin[1] || p0[1] > bmax[1])
- offMeshConClass[i*2+0] = 0;
- }
+ offMeshConClass[i*2+0] = classifyOffMeshPoint(&params->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax);
+ offMeshConClass[i*2+1] = classifyOffMeshPoint(&params->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax);
// Cound how many links should be allocated for off-mesh connections.
if (offMeshConClass[i*2+0] == 0xff)
@@ -345,13 +307,23 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
for (int j = 0; j < nvp; ++j)
{
if (p[j] == MESH_NULL_IDX) break;
+ int nj = j+1;
+ if (nj >= nvp || p[nj] == MESH_NULL_IDX) nj = 0;
+ const unsigned short* va = &params->verts[p[j]*3];
+ const unsigned short* vb = &params->verts[p[nj]*3];
+
edgeCount++;
- if (p[nvp+j] & 0x8000)
+ if (params->tileSize > 0)
{
- unsigned short dir = p[nvp+j] & 0xf;
- if (dir != 0xf)
- portalCount++;
+ if (va[0] == params->tileSize && vb[0] == params->tileSize)
+ portalCount++; // x+
+ else if (va[2] == params->tileSize && vb[2] == params->tileSize)
+ portalCount++; // z+
+ else if (va[0] == 0 && vb[0] == 0)
+ portalCount++; // x-
+ else if (va[2] == 0 && vb[2] == 0)
+ portalCount++; // z-
}
}
}
@@ -360,41 +332,18 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
// Find unique detail vertices.
int uniqueDetailVertCount = 0;
- int detailTriCount = 0;
- if (params->detailMeshes)
- {
- // Has detail mesh, count unique detail vertex count and use input detail tri count.
- detailTriCount = params->detailTriCount;
- for (int i = 0; i < params->polyCount; ++i)
- {
- const unsigned short* p = &params->polys[i*nvp*2];
- int ndv = params->detailMeshes[i*4+1];
- int nv = 0;
- for (int j = 0; j < nvp; ++j)
- {
- if (p[j] == MESH_NULL_IDX) break;
- nv++;
- }
- ndv -= nv;
- uniqueDetailVertCount += ndv;
- }
- }
- else
+ for (int i = 0; i < params->polyCount; ++i)
{
- // No input detail mesh, build detail mesh from nav polys.
- uniqueDetailVertCount = 0; // No extra detail verts.
- detailTriCount = 0;
- for (int i = 0; i < params->polyCount; ++i)
+ const unsigned short* p = &params->polys[i*nvp*2];
+ int ndv = params->detailMeshes[i*4+1];
+ int nv = 0;
+ for (int j = 0; j < nvp; ++j)
{
- const unsigned short* p = &params->polys[i*nvp*2];
- int nv = 0;
- for (int j = 0; j < nvp; ++j)
- {
- if (p[j] == MESH_NULL_IDX) break;
- nv++;
- }
- detailTriCount += nv-2;
+ if (p[j] == MESH_NULL_IDX) break;
+ nv++;
}
+ ndv -= nv;
+ uniqueDetailVertCount += ndv;
}
// Calculate data size
@@ -404,8 +353,8 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
const int linksSize = dtAlign4(sizeof(dtLink)*maxLinkCount);
const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount);
const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount);
- const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*detailTriCount);
- const int bvTreeSize = params->buildBvTree ? dtAlign4(sizeof(dtBVNode)*params->polyCount*2) : 0;
+ const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*params->detailTriCount);
+ const int bvTreeSize = dtAlign4(sizeof(dtBVNode)*params->polyCount*2);
const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount);
const int dataSize = headerSize + vertsSize + polysSize + linksSize +
@@ -437,7 +386,6 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
header->version = DT_NAVMESH_VERSION;
header->x = params->tileX;
header->y = params->tileY;
- header->layer = params->tileLayer;
header->userId = params->userId;
header->polyCount = totPolyCount;
header->vertCount = totVertCount;
@@ -446,14 +394,14 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
dtVcopy(header->bmax, params->bmax);
header->detailMeshCount = params->polyCount;
header->detailVertCount = uniqueDetailVertCount;
- header->detailTriCount = detailTriCount;
+ header->detailTriCount = params->detailTriCount;
header->bvQuantFactor = 1.0f / params->cs;
header->offMeshBase = params->polyCount;
header->walkableHeight = params->walkableHeight;
header->walkableRadius = params->walkableRadius;
header->walkableClimb = params->walkableClimb;
header->offMeshConCount = storedOffMeshConCount;
- header->bvNodeCount = params->buildBvTree ? params->polyCount*2 : 0;
+ header->bvNodeCount = params->polyCount*2;
const int offMeshVertsBase = params->vertCount;
const int offMeshPolyBase = params->polyCount;
@@ -497,27 +445,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
{
if (src[j] == MESH_NULL_IDX) break;
p->verts[j] = src[j];
- if (src[nvp+j] & 0x8000)
- {
- // Border or portal edge.
- unsigned short dir = src[nvp+j] & 0xf;
- if (dir == 0xf) // Border
- p->neis[j] = 0;
- else if (dir == 0) // Portal x-
- p->neis[j] = DT_EXT_LINK | 4;
- else if (dir == 1) // Portal z+
- p->neis[j] = DT_EXT_LINK | 2;
- else if (dir == 2) // Portal x+
- p->neis[j] = DT_EXT_LINK | 0;
- else if (dir == 3) // Portal z-
- p->neis[j] = DT_EXT_LINK | 6;
- }
- else
- {
- // Normal connection
- p->neis[j] = src[nvp+j]+1;
- }
-
+ p->neis[j] = (src[nvp+j]+1) & 0xffff;
p->vertCount++;
}
src += nvp*2;
@@ -539,68 +467,61 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
n++;
}
}
-
- // Store detail meshes and vertices.
- // The nav polygon vertices are stored as the first vertices on each mesh.
- // We compress the mesh data by skipping them and using the navmesh coordinates.
- if (params->detailMeshes)
+
+ // Store portal edges.
+ if (params->tileSize > 0)
{
- unsigned short vbase = 0;
for (int i = 0; i < params->polyCount; ++i)
{
- dtPolyDetail& dtl = navDMeshes[i];
- const int vb = (int)params->detailMeshes[i*4+0];
- const int ndv = (int)params->detailMeshes[i*4+1];
- const int nv = navPolys[i].vertCount;
- dtl.vertBase = (unsigned int)vbase;
- dtl.vertCount = (unsigned char)(ndv-nv);
- dtl.triBase = (unsigned int)params->detailMeshes[i*4+2];
- dtl.triCount = (unsigned char)params->detailMeshes[i*4+3];
- // Copy vertices except the first 'nv' verts which are equal to nav poly verts.
- if (ndv-nv)
+ dtPoly* poly = &navPolys[i];
+ for (int j = 0; j < poly->vertCount; ++j)
{
- memcpy(&navDVerts[vbase*3], &params->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv));
- vbase += (unsigned short)(ndv-nv);
+ int nj = j+1;
+ if (nj >= poly->vertCount) nj = 0;
+
+ const unsigned short* va = &params->verts[poly->verts[j]*3];
+ const unsigned short* vb = &params->verts[poly->verts[nj]*3];
+
+ if (va[0] == params->tileSize && vb[0] == params->tileSize) // x+
+ poly->neis[j] = DT_EXT_LINK | 0;
+ else if (va[2] == params->tileSize && vb[2] == params->tileSize) // z+
+ poly->neis[j] = DT_EXT_LINK | 2;
+ else if (va[0] == 0 && vb[0] == 0) // x-
+ poly->neis[j] = DT_EXT_LINK | 4;
+ else if (va[2] == 0 && vb[2] == 0) // z-
+ poly->neis[j] = DT_EXT_LINK | 6;
}
}
- // Store triangles.
- memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount);
}
- else
+
+ // Store detail meshes and vertices.
+ // The nav polygon vertices are stored as the first vertices on each mesh.
+ // We compress the mesh data by skipping them and using the navmesh coordinates.
+ unsigned short vbase = 0;
+ for (int i = 0; i < params->polyCount; ++i)
{
- // Create dummy detail mesh by triangulating polys.
- int tbase = 0;
- for (int i = 0; i < params->polyCount; ++i)
+ dtPolyDetail& dtl = navDMeshes[i];
+ const int vb = (int)params->detailMeshes[i*4+0];
+ const int ndv = (int)params->detailMeshes[i*4+1];
+ const int nv = navPolys[i].vertCount;
+ dtl.vertBase = (unsigned int)vbase;
+ dtl.vertCount = (unsigned char)(ndv-nv);
+ dtl.triBase = (unsigned int)params->detailMeshes[i*4+2];
+ dtl.triCount = (unsigned char)params->detailMeshes[i*4+3];
+ // Copy vertices except the first 'nv' verts which are equal to nav poly verts.
+ if (ndv-nv)
{
- dtPolyDetail& dtl = navDMeshes[i];
- const int nv = navPolys[i].vertCount;
- dtl.vertBase = 0;
- dtl.vertCount = 0;
- dtl.triBase = (unsigned int)tbase;
- dtl.triCount = (unsigned char)(nv-2);
- // Triangulate polygon (local indices).
- for (int j = 2; j < nv; ++j)
- {
- unsigned char* t = &navDTris[tbase*4];
- t[0] = 0;
- t[1] = (unsigned char)(j-1);
- t[2] = (unsigned char)j;
- // Bit for each edge that belongs to poly boundary.
- t[3] = (1<<2);
- if (j == 2) t[3] |= (1<<0);
- if (j == nv-1) t[3] |= (1<<4);
- tbase++;
- }
+ memcpy(&navDVerts[vbase*3], &params->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv));
+ vbase += (unsigned short)(ndv-nv);
}
}
+ // Store triangles.
+ memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount);
// Store and create BVtree.
// TODO: take detail mesh into account! use byte per bbox extent?
- if (params->buildBvTree)
- {
- createBVTree(params->verts, params->vertCount, params->polys, params->polyCount,
- nvp, params->cs, params->ch, params->polyCount*2, navBvtree);
- }
+ createBVTree(params->verts, params->vertCount, params->polys, params->polyCount,
+ nvp, params->cs, params->ch, params->polyCount*2, navBvtree);
// Store Off-Mesh connections.
n = 0;
@@ -632,14 +553,51 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
return true;
}
+inline void swapByte(unsigned char* a, unsigned char* b)
+{
+ unsigned char tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+
+inline void swapEndian(unsigned short* v)
+{
+ unsigned char* x = (unsigned char*)v;
+ swapByte(x+0, x+1);
+}
+
+inline void swapEndian(short* v)
+{
+ unsigned char* x = (unsigned char*)v;
+ swapByte(x+0, x+1);
+}
+
+inline void swapEndian(unsigned int* v)
+{
+ unsigned char* x = (unsigned char*)v;
+ swapByte(x+0, x+3); swapByte(x+1, x+2);
+}
+
+inline void swapEndian(int* v)
+{
+ unsigned char* x = (unsigned char*)v;
+ swapByte(x+0, x+3); swapByte(x+1, x+2);
+}
+
+inline void swapEndian(float* v)
+{
+ unsigned char* x = (unsigned char*)v;
+ swapByte(x+0, x+3); swapByte(x+1, x+2);
+}
+
bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/)
{
dtMeshHeader* header = (dtMeshHeader*)data;
int swappedMagic = DT_NAVMESH_MAGIC;
int swappedVersion = DT_NAVMESH_VERSION;
- dtSwapEndian(&swappedMagic);
- dtSwapEndian(&swappedVersion);
+ swapEndian(&swappedMagic);
+ swapEndian(&swappedVersion);
if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) &&
(header->magic != swappedMagic || header->version != swappedVersion))
@@ -647,31 +605,30 @@ bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/)
return false;
}
- dtSwapEndian(&header->magic);
- dtSwapEndian(&header->version);
- dtSwapEndian(&header->x);
- dtSwapEndian(&header->y);
- dtSwapEndian(&header->layer);
- dtSwapEndian(&header->userId);
- dtSwapEndian(&header->polyCount);
- dtSwapEndian(&header->vertCount);
- dtSwapEndian(&header->maxLinkCount);
- dtSwapEndian(&header->detailMeshCount);
- dtSwapEndian(&header->detailVertCount);
- dtSwapEndian(&header->detailTriCount);
- dtSwapEndian(&header->bvNodeCount);
- dtSwapEndian(&header->offMeshConCount);
- dtSwapEndian(&header->offMeshBase);
- dtSwapEndian(&header->walkableHeight);
- dtSwapEndian(&header->walkableRadius);
- dtSwapEndian(&header->walkableClimb);
- dtSwapEndian(&header->bmin[0]);
- dtSwapEndian(&header->bmin[1]);
- dtSwapEndian(&header->bmin[2]);
- dtSwapEndian(&header->bmax[0]);
- dtSwapEndian(&header->bmax[1]);
- dtSwapEndian(&header->bmax[2]);
- dtSwapEndian(&header->bvQuantFactor);
+ swapEndian(&header->magic);
+ swapEndian(&header->version);
+ swapEndian(&header->x);
+ swapEndian(&header->y);
+ swapEndian(&header->userId);
+ swapEndian(&header->polyCount);
+ swapEndian(&header->vertCount);
+ swapEndian(&header->maxLinkCount);
+ swapEndian(&header->detailMeshCount);
+ swapEndian(&header->detailVertCount);
+ swapEndian(&header->detailTriCount);
+ swapEndian(&header->bvNodeCount);
+ swapEndian(&header->offMeshConCount);
+ swapEndian(&header->offMeshBase);
+ swapEndian(&header->walkableHeight);
+ swapEndian(&header->walkableRadius);
+ swapEndian(&header->walkableClimb);
+ swapEndian(&header->bmin[0]);
+ swapEndian(&header->bmin[1]);
+ swapEndian(&header->bmin[2]);
+ swapEndian(&header->bmax[0]);
+ swapEndian(&header->bmax[1]);
+ swapEndian(&header->bmax[2]);
+ swapEndian(&header->bvQuantFactor);
// Freelist index and pointers are updated when tile is added, no need to swap.
@@ -717,7 +674,7 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
// Vertices
for (int i = 0; i < header->vertCount*3; ++i)
{
- dtSwapEndian(&verts[i]);
+ swapEndian(&verts[i]);
}
// Polys
@@ -727,10 +684,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
// poly->firstLink is update when tile is added, no need to swap.
for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j)
{
- dtSwapEndian(&p->verts[j]);
- dtSwapEndian(&p->neis[j]);
+ swapEndian(&p->verts[j]);
+ swapEndian(&p->neis[j]);
}
- dtSwapEndian(&p->flags);
+ swapEndian(&p->flags);
}
// Links are rebuild when tile is added, no need to swap.
@@ -739,14 +696,14 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
for (int i = 0; i < header->detailMeshCount; ++i)
{
dtPolyDetail* pd = &detailMeshes[i];
- dtSwapEndian(&pd->vertBase);
- dtSwapEndian(&pd->triBase);
+ swapEndian(&pd->vertBase);
+ swapEndian(&pd->triBase);
}
// Detail verts
for (int i = 0; i < header->detailVertCount*3; ++i)
{
- dtSwapEndian(&detailVerts[i]);
+ swapEndian(&detailVerts[i]);
}
// BV-tree
@@ -755,10 +712,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
dtBVNode* node = &bvTree[i];
for (int j = 0; j < 3; ++j)
{
- dtSwapEndian(&node->bmin[j]);
- dtSwapEndian(&node->bmax[j]);
+ swapEndian(&node->bmin[j]);
+ swapEndian(&node->bmax[j]);
}
- dtSwapEndian(&node->i);
+ swapEndian(&node->i);
}
// Off-mesh Connections.
@@ -766,9 +723,9 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
{
dtOffMeshConnection* con = &offMeshCons[i];
for (int j = 0; j < 6; ++j)
- dtSwapEndian(&con->pos[j]);
- dtSwapEndian(&con->rad);
- dtSwapEndian(&con->poly);
+ swapEndian(&con->pos[j]);
+ swapEndian(&con->rad);
+ swapEndian(&con->poly);
}
return true;
diff --git a/dep/recastnavigation/Detour/DetourNavMeshBuilder.h b/dep/recastnavigation/Detour/DetourNavMeshBuilder.h
index c80d1717630..c4a5ac07045 100644
--- a/dep/recastnavigation/Detour/DetourNavMeshBuilder.h
+++ b/dep/recastnavigation/Detour/DetourNavMeshBuilder.h
@@ -83,7 +83,6 @@ struct dtNavMeshCreateParams
unsigned int userId; ///< The user defined id of the tile.
int tileX; ///< The tile's x-grid location within the multi-tile destination mesh. (Along the x-axis.)
int tileY; ///< The tile's y-grid location within the multi-tile desitation mesh. (Along the z-axis.)
- int tileLayer; ///< The tile's layer within the layered destination mesh. [Limit: >= 0] (Along the y-axis.)
float bmin[3]; ///< The minimum bounds of the tile. [(x, y, z)] [Unit: wu]
float bmax[3]; ///< The maximum bounds of the tile. [(x, y, z)] [Unit: wu]
@@ -96,12 +95,7 @@ struct dtNavMeshCreateParams
float walkableClimb; ///< The agent maximum traversable ledge. (Up/Down) [Unit: wu]
float cs; ///< The xz-plane cell size of the polygon mesh. [Limit: > 0] [Unit: wu]
float ch; ///< The y-axis cell height of the polygon mesh. [Limit: > 0] [Unit: wu]
-
- /// True if a bounding volume tree should be built for the tile.
- /// @note The BVTree is not normally needed for layered navigation meshes.
- bool buildBvTree;
-
- /// @}
+ int tileSize; // Tile size (width & height) (vx).
};
/// Builds navigation mesh tile data from the provided tile creation data.
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
diff --git a/dep/recastnavigation/Detour/DetourNavMeshQuery.h b/dep/recastnavigation/Detour/DetourNavMeshQuery.h
index d431bf177bd..31b567e0b50 100644
--- a/dep/recastnavigation/Detour/DetourNavMeshQuery.h
+++ b/dep/recastnavigation/Detour/DetourNavMeshQuery.h
@@ -130,9 +130,30 @@ public:
/// @returns The status flags for the query.
dtStatus init(const dtNavMesh* nav, const int maxNodes);
- /// @name Standard Pathfinding Functions
- // /@{
-
+ // Finds the nearest navigation polygon around the center location.
+ // Params:
+ // center[3] - (in) The center of the search box.
+ // extents[3] - (in) The extents of the search box.
+ // filter - (in) path polygon filter.
+ // nearestRef - (out) Reference to the nearest polygon.
+ // nearestPt[3] - (out, opt) The nearest point on found polygon, null if not needed.
+ // Returns: Reference identifier for the polygon, or 0 if no polygons found.
+ dtStatus findNearestPoly(const float* center, const float* extents,
+ const dtQueryFilter* filter,
+ dtPolyRef* nearestRef, float* nearestPt) const;
+
+ // Returns polygons which overlap the query box.
+ // Params:
+ // center[3] - (in) the center of the search box.
+ // extents[3] - (in) the extents of the search box.
+ // filter - (in) path polygon filter.
+ // polys - (out) array holding the search result.
+ // polyCount - (out) Number of polygons in search result array.
+ // maxPolys - (in) The max number of polygons the polys array can hold.
+ dtStatus queryPolygons(const float* center, const float* extents,
+ const dtQueryFilter* filter,
+ dtPolyRef* polys, int* polyCount, const int maxPolys) const;
+
/// Finds a path from the start polygon to the end polygon.
/// @param[in] startRef The refrence id of the start polygon.
/// @param[in] endRef The reference id of the end polygon.
@@ -148,31 +169,6 @@ public:
const dtQueryFilter* filter,
dtPolyRef* path, int* pathCount, const int maxPath) const;
- /// Finds the straight path from the start to the end position within the polygon corridor.
- /// @param[in] startPos Path start position. [(x, y, z)]
- /// @param[in] endPos Path end position. [(x, y, z)]
- /// @param[in] path An array of polygon references that represent the path corridor.
- /// @param[in] pathSize The number of polygons in the @p path array.
- /// @param[out] straightPath Points describing the straight path. [(x, y, z) * @p straightPathCount].
- /// @param[out] straightPathFlags Flags describing each point. (See: #dtStraightPathFlags) [opt]
- /// @param[out] straightPathRefs The reference id of the polygon that is being entered at each point. [opt]
- /// @param[out] straightPathCount The number of points in the straight path.
- /// @param[in] maxStraightPath The maximum number of points the straight path arrays can hold. [Limit: > 0]
- /// @param[in] options Query options. (see: #dtStraightPathOptions)
- /// @returns The status flags for the query.
- dtStatus 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 = 0) const;
-
- ///@}
- /// @name Sliced Pathfinding Functions
- /// Common use case:
- /// -# Call initSlicedFindPath() to initialize the sliced path query.
- /// -# Call updateSlicedFindPath() until it returns complete.
- /// -# Call finalizeSlicedFindPath() to get the path.
- ///@{
-
/// Intializes a sliced path query.
/// @param[in] startRef The refrence id of the start polygon.
/// @param[in] endRef The reference id of the end polygon.
@@ -185,10 +181,10 @@ public:
const dtQueryFilter* filter);
/// Updates an in-progress sliced path query.
- /// @param[in] maxIter The maximum number of iterations to perform.
- /// @param[out] doneIters The actual number of iterations completed. [opt]
- /// @returns The status flags for the query.
- dtStatus updateSlicedFindPath(const int maxIter, int* doneIters);
+ // Params:
+ // maxIter - (in) max number of iterations to update.
+ // Returns: Path query state.
+ dtStatus updateSlicedFindPath(const int maxIter);
/// Finalizes and returns the results of a sliced path query.
/// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
@@ -209,11 +205,74 @@ public:
/// @returns The status flags for the query.
dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
dtPolyRef* path, int* pathCount, const int maxPath);
-
- ///@}
- /// @name Dijkstra Search Functions
- /// @{
-
+
+ // Finds a straight path from start to end locations within the corridor
+ // described by the path polygons.
+ // Start and end locations will be clamped on the corridor.
+ // The returned polygon references are point to polygon which was entered when
+ // a path point was added. For the end point, zero will be returned. This allows
+ // to match for example off-mesh link points to their representative polygons.
+ // Params:
+ // startPos[3] - (in) Path start location.
+ // endPo[3] - (in) Path end location.
+ // path - (in) Array of connected polygons describing the corridor.
+ // pathSize - (in) Number of polygons in path array.
+ // straightPath - (out) Points describing the straight path.
+ // straightPathFlags - (out, opt) Flags describing each point type, see dtStraightPathFlags.
+ // straightPathRefs - (out, opt) References to polygons at point locations.
+ // straightPathCount - (out) Number of points in the path.
+ // maxStraightPath - (in) The max number of points the straight path array can hold. Must be at least 1.
+ dtStatus 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;
+
+ // Moves from startPos to endPos constrained to the navmesh.
+ // If the endPos is reachable, the resultPos will be endPos,
+ // or else the resultPos will be the nearest point in navmesh.
+ // Note: The resulting point is not projected to the ground, use getPolyHeight() to get height.
+ // Note: The algorithm is optimized for small delta movement and small number of polygons.
+ // Params:
+ // startRef - (in) ref to the polygon where startPos lies.
+ // startPos[3] - (in) start position of the mover.
+ // endPos[3] - (in) desired end position of the mover.
+ // filter - (in) path polygon filter.
+ // resultPos[3] - (out) new position of the mover.
+ // visited - (out) array of visited polygons.
+ // visitedCount - (out) Number of entries in the visited array.
+ // maxVisitedSize - (in) max number of polygons in the visited array.
+ dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos,
+ const dtQueryFilter* filter,
+ float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const;
+
+ // Casts 'walkability' ray along the navmesh surface from startPos towards the endPos.
+ // Params:
+ // startRef - (in) ref to the polygon where the start lies.
+ // startPos[3] - (in) start position of the query.
+ // endPos[3] - (in) end position of the query.
+ // t - (out) hit parameter along the segment, FLT_MAX if no hit.
+ // hitNormal[3] - (out) normal of the nearest hit.
+ // filter - (in) path polygon filter.
+ // path - (out,opt) visited path polygons.
+ // pathCount - (out,opt) Number of polygons visited.
+ // maxPath - (in) max number of polygons in the path array.
+ dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
+ const dtQueryFilter* filter,
+ float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const;
+
+ // Returns distance to nearest wall from the specified location.
+ // Params:
+ // startRef - (in) ref to the polygon where the center lies.
+ // centerPos[3] - (in) center if the query circle.
+ // maxRadius - (in) max search radius.
+ // filter - (in) path polygon filter.
+ // hitDist - (out) distance to nearest wall from the test location.
+ // hitPos[3] - (out) location of the nearest hit.
+ // hitNormal[3] - (out) normal of the nearest hit.
+ dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius,
+ const dtQueryFilter* filter,
+ float* hitDist, float* hitPos, float* hitNormal) const;
+
/// Finds the polygons along the navigation graph that touch the specified circle.
/// @param[in] startRef The reference id of the polygon where the search starts.
/// @param[in] centerPos The center of the search circle. [(x, y, z)]
@@ -249,33 +308,6 @@ public:
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
int* resultCount, const int maxResult) const;
- /// @}
- /// @name Local Query Functions
- ///@{
-
- /// Finds the polygon nearest to the specified center point.
- /// @param[in] center The center of the search box. [(x, y, z)]
- /// @param[in] extents The search distance along each axis. [(x, y, z)]
- /// @param[in] filter The polygon filter to apply to the query.
- /// @param[out] nearestRef The reference id of the nearest polygon.
- /// @param[out] nearestPt The nearest point on the polygon. [opt] [(x, y, z)]
- /// @returns The status flags for the query.
- dtStatus findNearestPoly(const float* center, const float* extents,
- const dtQueryFilter* filter,
- dtPolyRef* nearestRef, float* nearestPt) const;
-
- /// Finds polygons that overlap the search box.
- /// @param[in] center The center of the search box. [(x, y, z)]
- /// @param[in] extents The search distance along each axis. [(x, y, z)]
- /// @param[in] filter The polygon filter to apply to the query.
- /// @param[out] polys The reference ids of the polygons that overlap the query box.
- /// @param[out] polyCount The number of polygons in the search result.
- /// @param[in] maxPolys The maximum number of polygons the search result can hold.
- /// @returns The status flags for the query.
- dtStatus queryPolygons(const float* center, const float* extents,
- const dtQueryFilter* filter,
- dtPolyRef* polys, int* polyCount, const int maxPolys) const;
-
/// Finds the non-overlapping navigation polygons in the local neighbourhood around the center position.
/// @param[in] startRef The reference id of the polygon where the search starts.
/// @param[in] centerPos The center of the query circle. [(x, y, z)]
@@ -291,88 +323,16 @@ public:
const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent,
int* resultCount, const int maxResult) const;
-
- /// Moves from the start to the end position constrained to the navigation mesh.
- /// @param[in] startRef The reference id of the start polygon.
- /// @param[in] startPos A position of the mover within the start polygon. [(x, y, x)]
- /// @param[in] endPos The desired end position of the mover. [(x, y, z)]
- /// @param[in] filter The polygon filter to apply to the query.
- /// @param[out] resultPos The result position of the mover. [(x, y, z)]
- /// @param[out] visited The reference ids of the polygons visited during the move.
- /// @param[out] visitedCount The number of polygons visited during the move.
- /// @param[in] maxVisitedSize The maximum number of polygons the @p visited array can hold.
- /// @returns The status flags for the query.
- dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos,
- const dtQueryFilter* filter,
- float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const;
-
- /// Casts a 'walkability' ray along the surface of the navigation mesh from
- /// the start position toward the end position.
- /// @param[in] startRef The reference id of the start polygon.
- /// @param[in] startPos A position within the start polygon representing
- /// the start of the ray. [(x, y, z)]
- /// @param[in] endPos The position to cast the ray toward. [(x, y, z)]
- /// @param[out] t The hit parameter. (FLT_MAX if no wall hit.)
- /// @param[out] hitNormal The normal of the nearest wall hit. [(x, y, z)]
- /// @param[in] filter The polygon filter to apply to the query.
- /// @param[out] path The reference ids of the visited polygons. [opt]
- /// @param[out] pathCount The number of visited polygons. [opt]
- /// @param[in] maxPath The maximum number of polygons the @p path array can hold.
- /// @returns The status flags for the query.
- dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
- const dtQueryFilter* filter,
- float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const;
-
- /// Finds the distance from the specified position to the nearest polygon wall.
- /// @param[in] startRef The reference id of the polygon containing @p centerPos.
- /// @param[in] centerPos The center of the search circle. [(x, y, z)]
- /// @param[in] maxRadius The radius of the search circle.
- /// @param[in] filter The polygon filter to apply to the query.
- /// @param[out] hitDist The distance to the nearest wall from @p centerPos.
- /// @param[out] hitPos The nearest position on the wall that was hit. [(x, y, z)]
- /// @param[out] hitNormal The normalized ray formed from the wall point to the
- /// source point. [(x, y, z)]
- /// @returns The status flags for the query.
- dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius,
- const dtQueryFilter* filter,
- float* hitDist, float* hitPos, float* hitNormal) const;
/// Returns the segments for the specified polygon, optionally including portals.
- /// @param[in] ref The reference id of the polygon.
- /// @param[in] filter The polygon filter to apply to the query.
- /// @param[out] segmentVerts The segments. [(ax, ay, az, bx, by, bz) * segmentCount]
- /// @param[out] segmentRefs The reference ids of each segment's neighbor polygon.
- /// Or zero if the segment is a wall. [opt] [(parentRef) * @p segmentCount]
- /// @param[out] segmentCount The number of segments returned.
- /// @param[in] maxSegments The maximum number of segments the result arrays can hold.
- /// @returns The status flags for the query.
+ // Params:
+ // ref - (in) ref to the polygon.
+ // filter - (in) path polygon filter.
+ // segments[6*maxSegments] - (out) wall segments (2 endpoints per segment).
+ // segmentCount - (out) number of wall segments.
+ // maxSegments - (in) max number of segments that can be stored in 'segments'.
dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter,
- float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount,
- const int maxSegments) const;
-
- /// Returns random location on navmesh.
- /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon.
- /// @param[in] filter The polygon filter to apply to the query.
- /// @param[in] frand Function returning a random number [0..1).
- /// @param[out] randomRef The reference id of the random location.
- /// @param[out] randomPt The random location.
- /// @returns The status flags for the query.
- dtStatus findRandomPoint(const dtQueryFilter* filter, float (*frand)(),
- dtPolyRef* randomRef, float* randomPt) const;
-
- /// Returns random location on navmesh within the reach of specified location.
- /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon.
- /// The location is not exactly constrained by the circle, but it limits the visited polygons.
- /// @param[in] startRef The reference id of the polygon where the search starts.
- /// @param[in] centerPos The center of the search circle. [(x, y, z)]
- /// @param[in] filter The polygon filter to apply to the query.
- /// @param[in] frand Function returning a random number [0..1).
- /// @param[out] randomRef The reference id of the random location.
- /// @param[out] randomPt The random location. [(x, y, z)]
- /// @returns The status flags for the query.
- dtStatus findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float maxRadius,
- const dtQueryFilter* filter, float (*frand)(),
- dtPolyRef* randomRef, float* randomPt) const;
+ float* segments, int* segmentCount, const int maxSegments) const;
/// Finds the closest point on the specified polygon.
/// @param[in] ref The reference id of the polygon.
@@ -389,6 +349,15 @@ public:
/// @returns The status flags for the query.
dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const;
+ // Returns start and end location of an off-mesh link polygon.
+ // Params:
+ // prevRef - (in) ref to the polygon before the link (used to select direction).
+ // polyRef - (in) ref to the off-mesh link polygon.
+ // startPos[3] - (out) start point of the link.
+ // endPos[3] - (out) end point of the link.
+ // Returns: true if link is found.
+ dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
+
/// Gets the height of the polygon at the provided position using the height detail. (Most accurate.)
/// @param[in] ref The reference id of the polygon.
/// @param[in] pos A position within the xz-bounds of the polygon. [(x, y, z)]
@@ -396,15 +365,6 @@ public:
/// @returns The status flags for the query.
dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const;
- /// @}
- /// @name Miscellaneous Functions
- /// @{
-
- /// Returns true if the polygon reference is valid and passes the filter restrictions.
- /// @param[in] ref The polygon reference to check.
- /// @param[in] filter The filter to apply.
- bool isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const;
-
/// Returns true if the polygon reference is in the closed list.
/// @param[in] ref The reference id of the polygon to check.
/// @returns True if the polygon is in closed list.
@@ -414,12 +374,6 @@ public:
/// @returns The node pool.
class dtNodePool* getNodePool() const { return m_nodePool; }
- /// Gets the navigation mesh the query object is using.
- /// @return The navigation mesh the query object is using.
- const dtNavMesh* getAttachedNavMesh() const { return m_nav; }
-
- /// @}
-
private:
/// Returns neighbour tile based on side.
@@ -432,7 +386,7 @@ private:
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents,
const dtQueryFilter* filter, float* nearestPt) const;
/// Returns closest point on polygon.
- void closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, const float* pos, float* closest) const;
+ dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, const float* pos, float* closest) const;
/// Returns portal points between two polygons.
dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right,
@@ -447,16 +401,6 @@ private:
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
float* mid) const;
- // Appends vertex to a straight path
- dtStatus appendVertex(const float* pos, const unsigned char flags, const dtPolyRef ref,
- float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
- int* straightPathCount, const int maxStraightPath) const;
-
- // Appends intermediate portal points to a straight path.
- dtStatus 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 dtNavMesh* m_nav; ///< Pointer to navmesh data.
struct dtQueryData
diff --git a/dep/recastnavigation/Detour/DetourNode.cpp b/dep/recastnavigation/Detour/DetourNode.cpp
index 4c8215e20d0..03c6e370aac 100644
--- a/dep/recastnavigation/Detour/DetourNode.cpp
+++ b/dep/recastnavigation/Detour/DetourNode.cpp
@@ -47,15 +47,15 @@ dtNodePool::dtNodePool(int maxNodes, int hashSize) :
dtAssert(m_maxNodes > 0);
m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM);
- m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM);
- m_first = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*hashSize, DT_ALLOC_PERM);
+ m_next = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_maxNodes, DT_ALLOC_PERM);
+ m_first = (unsigned short*)dtAlloc(sizeof(unsigned short)*hashSize, DT_ALLOC_PERM);
dtAssert(m_nodes);
dtAssert(m_next);
dtAssert(m_first);
- memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
- memset(m_next, 0xff, sizeof(dtNodeIndex)*m_maxNodes);
+ memset(m_first, 0xff, sizeof(unsigned short)*m_hashSize);
+ memset(m_next, 0xff, sizeof(unsigned short)*m_maxNodes);
}
dtNodePool::~dtNodePool()
@@ -67,14 +67,14 @@ dtNodePool::~dtNodePool()
void dtNodePool::clear()
{
- memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
+ memset(m_first, 0xff, sizeof(unsigned short)*m_hashSize);
m_nodeCount = 0;
}
dtNode* dtNodePool::findNode(dtPolyRef id)
{
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
- dtNodeIndex i = m_first[bucket];
+ unsigned short i = m_first[bucket];
while (i != DT_NULL_IDX)
{
if (m_nodes[i].id == id)
@@ -87,7 +87,7 @@ dtNode* dtNodePool::findNode(dtPolyRef id)
dtNode* dtNodePool::getNode(dtPolyRef id)
{
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
- dtNodeIndex i = m_first[bucket];
+ unsigned short i = m_first[bucket];
dtNode* node = 0;
while (i != DT_NULL_IDX)
{
@@ -99,7 +99,7 @@ dtNode* dtNodePool::getNode(dtPolyRef id)
if (m_nodeCount >= m_maxNodes)
return 0;
- i = (dtNodeIndex)m_nodeCount;
+ i = (unsigned short)m_nodeCount;
m_nodeCount++;
// Init node
diff --git a/dep/recastnavigation/Detour/DetourNode.h b/dep/recastnavigation/Detour/DetourNode.h
index b68c922d038..aec26d2fc57 100644
--- a/dep/recastnavigation/Detour/DetourNode.h
+++ b/dep/recastnavigation/Detour/DetourNode.h
@@ -27,8 +27,7 @@ enum dtNodeFlags
DT_NODE_CLOSED = 0x02,
};
-typedef unsigned short dtNodeIndex;
-static const dtNodeIndex DT_NULL_IDX = (dtNodeIndex)~0;
+static const unsigned short DT_NULL_IDX = 0xffff;
struct dtNode
{
@@ -73,21 +72,21 @@ public:
{
return sizeof(*this) +
sizeof(dtNode)*m_maxNodes +
- sizeof(dtNodeIndex)*m_maxNodes +
- sizeof(dtNodeIndex)*m_hashSize;
+ sizeof(unsigned short)*m_maxNodes +
+ sizeof(unsigned short)*m_hashSize;
}
inline int getMaxNodes() const { return m_maxNodes; }
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 unsigned short getFirst(int bucket) const { return m_first[bucket]; }
+ inline unsigned short getNext(int i) const { return m_next[i]; }
private:
dtNode* m_nodes;
- dtNodeIndex* m_first;
- dtNodeIndex* m_next;
+ unsigned short* m_first;
+ unsigned short* m_next;
const int m_maxNodes;
const int m_hashSize;
int m_nodeCount;
diff --git a/dep/recastnavigation/Recast/CMakeLists.txt b/dep/recastnavigation/Recast/CMakeLists.txt
index 09f20b4ed2f..e5e30294238 100644
--- a/dep/recastnavigation/Recast/CMakeLists.txt
+++ b/dep/recastnavigation/Recast/CMakeLists.txt
@@ -14,7 +14,6 @@ set(Recast_STAT_SRCS
RecastArea.cpp
RecastContour.cpp
RecastFilter.cpp
- RecastLayers.cpp
RecastMesh.cpp
RecastMeshDetail.cpp
RecastRasterization.cpp
diff --git a/dep/recastnavigation/Recast/Recast.cpp b/dep/recastnavigation/Recast/Recast.cpp
index 803daac3bcf..922c9163c13 100644
--- a/dep/recastnavigation/Recast/Recast.cpp
+++ b/dep/recastnavigation/Recast/Recast.cpp
@@ -109,28 +109,6 @@ void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
rcFree(chf);
}
-
-rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet()
-{
- rcHeightfieldLayerSet* lset = (rcHeightfieldLayerSet*)rcAlloc(sizeof(rcHeightfieldLayerSet), RC_ALLOC_PERM);
- memset(lset, 0, sizeof(rcHeightfieldLayerSet));
- return lset;
-}
-
-void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset)
-{
- if (!lset) return;
- for (int i = 0; i < lset->nlayers; ++i)
- {
- rcFree(lset->layers[i].heights);
- rcFree(lset->layers[i].areas);
- rcFree(lset->layers[i].cons);
- }
- rcFree(lset->layers);
- rcFree(lset);
-}
-
-
rcContourSet* rcAllocContourSet()
{
rcContourSet* cset = (rcContourSet*)rcAlloc(sizeof(rcContourSet), RC_ALLOC_PERM);
@@ -439,13 +417,13 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i
if ((top - bot) >= walkableHeight && rcAbs((int)ns.y - (int)s.y) <= walkableClimb)
{
// Mark direction as walkable.
- const int lidx = k - (int)nc.index;
- if (lidx < 0 || lidx > MAX_LAYERS)
+ const int idx = k - (int)nc.index;
+ if (idx < 0 || idx > MAX_LAYERS)
{
- tooHighNeighbour = rcMax(tooHighNeighbour, lidx);
+ tooHighNeighbour = rcMax(tooHighNeighbour, idx);
continue;
}
- rcSetCon(s, dir, lidx);
+ rcSetCon(s, dir, idx);
break;
}
}
diff --git a/dep/recastnavigation/Recast/Recast.h b/dep/recastnavigation/Recast/Recast.h
index fb36aa4c5cf..57e98ea444a 100644
--- a/dep/recastnavigation/Recast/Recast.h
+++ b/dep/recastnavigation/Recast/Recast.h
@@ -65,8 +65,6 @@ enum rcTimerLabel
RC_TIMER_ERODE_AREA,
/// The time to mark a box area. (See: #rcMarkBoxArea)
RC_TIMER_MARK_BOX_AREA,
- /// The time to mark a cylinder area. (See: #rcMarkCylinderArea)
- RC_TIMER_MARK_CYLINDER_AREA,
/// The time to mark a convex polygon area. (See: #rcMarkConvexPolyArea)
RC_TIMER_MARK_CONVEXPOLY_AREA,
/// The total time to build the distance field. (See: #rcBuildDistanceField)
@@ -85,8 +83,6 @@ enum rcTimerLabel
RC_TIMER_BUILD_REGIONS_FLOOD,
/// The time to filter out small regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone)
RC_TIMER_BUILD_REGIONS_FILTER,
- /// The time to build heightfield layers. (See: #rcBuildHeightfieldLayers)
- RC_TIMER_BUILD_LAYERS,
/// The time to build the polygon mesh detail. (See: #rcBuildPolyMeshDetail)
RC_TIMER_BUILD_POLYMESHDETAIL,
/// The time to merge polygon mesh details. (See: #rcMergePolyMeshDetails)
@@ -284,6 +280,9 @@ struct rcHeightfield
rcSpan* freelist; ///< The next free span.
};
+rcHeightfield* rcAllocHeightfield();
+void rcFreeHeightField(rcHeightfield* hf);
+
/// Provides information on the content of a cell column in a compact heightfield.
struct rcCompactCell
{
@@ -309,7 +308,6 @@ struct rcCompactHeightfield
int spanCount; ///< The number of spans in the heightfield.
int walkableHeight; ///< The walkable height used during the build of the field. (See: rcConfig::walkableHeight)
int walkableClimb; ///< The walkable climb used during the build of the field. (See: rcConfig::walkableClimb)
- int borderSize; ///< The AABB border size used during the build of the field. (See: rcConfig::borderSize)
unsigned short maxDistance; ///< The maximum distance value of any span within the field.
unsigned short maxRegions; ///< The maximum region id of any span within the field.
float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]
@@ -322,35 +320,9 @@ struct rcCompactHeightfield
unsigned char* areas; ///< Array containing area id data. [Size: #spanCount]
};
-/// Represents a heightfield layer within a layer set.
-/// @see rcHeightfieldLayerSet
-struct rcHeightfieldLayer
-{
- float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]
- float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]
- float cs; ///< The size of each cell. (On the xz-plane.)
- float ch; ///< The height of each cell. (The minimum increment along the y-axis.)
- int width; ///< The width of the heightfield. (Along the x-axis in cell units.)
- int height; ///< The height of the heightfield. (Along the z-axis in cell units.)
- int minx; ///< The minimum x-bounds of usable data.
- int maxx; ///< The maximum x-bounds of usable data.
- int miny; ///< The minimum y-bounds of usable data. (Along the z-axis.)
- int maxy; ///< The maximum y-bounds of usable data. (Along the z-axis.)
- int hmin; ///< The minimum height bounds of usable data. (Along the y-axis.)
- int hmax; ///< The maximum height bounds of usable data. (Along the y-axis.)
- unsigned char* heights; ///< The heightfield. [Size: (width - borderSize*2) * (h - borderSize*2)]
- unsigned char* areas; ///< Area ids. [Size: Same as #heights]
- unsigned char* cons; ///< Packed neighbor connection information. [Size: Same as #heights]
-};
+rcCompactHeightfield* rcAllocCompactHeightfield();
+void rcFreeCompactHeightfield(rcCompactHeightfield* chf);
-/// Represents a set of heightfield layers.
-/// @ingroup recast
-/// @see rcAllocHeightfieldLayerSet, rcFreeHeightfieldLayerSet
-struct rcHeightfieldLayerSet
-{
- rcHeightfieldLayer* layers; ///< The layers in the set. [Size: #nlayers]
- int nlayers; ///< The number of layers in the set.
-};
/// Represents a simple, non-overlapping contour in field space.
struct rcContour
@@ -373,11 +345,12 @@ struct rcContourSet
float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]
float cs; ///< The size of each cell. (On the xz-plane.)
float ch; ///< The height of each cell. (The minimum increment along the y-axis.)
- int width; ///< The width of the set. (Along the x-axis in cell units.)
- int height; ///< The height of the set. (Along the z-axis in cell units.)
- int borderSize; ///< The AABB border size used to generate the source data from which the contours were derived.
};
+rcContourSet* rcAllocContourSet();
+void rcFreeContourSet(rcContourSet* cset);
+
+
/// Represents a polygon mesh suitable for use in building a navigation mesh.
/// @ingroup recast
struct rcPolyMesh
@@ -395,9 +368,12 @@ struct rcPolyMesh
float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]
float cs; ///< The size of each cell. (On the xz-plane.)
float ch; ///< The height of each cell. (The minimum increment along the y-axis.)
- int borderSize; ///< The AABB border size used to generate the source data from which the mesh was derived.
};
+rcPolyMesh* rcAllocPolyMesh();
+void rcFreePolyMesh(rcPolyMesh* pmesh);
+
+
/// Contains triangle meshes that represent detailed height data associated
/// with the polygons in its associated polygon mesh object.
/// @ingroup recast
@@ -411,71 +387,6 @@ struct rcPolyMeshDetail
int ntris; ///< The number of triangles in #tris.
};
-/// @name Allocation Functions
-/// Functions used to allocate and de-allocate Recast objects.
-/// @see rcAllocSetCustom
-/// @{
-
-/// Allocates a heightfield object using the Recast allocator.
-/// @return A heightfield that is ready for initialization, or null on failure.
-/// @ingroup recast
-/// @see rcCreateHeightfield, rcFreeHeightField
-rcHeightfield* rcAllocHeightfield();
-
-/// Frees the specified heightfield object using the Recast allocator.
-/// @param[in] hf A heightfield allocated using #rcAllocHeightfield
-/// @ingroup recast
-/// @see rcAllocHeightfield
-void rcFreeHeightField(rcHeightfield* hf);
-
-/// Allocates a compact heightfield object using the Recast allocator.
-/// @return A compact heightfield that is ready for initialization, or null on failure.
-/// @ingroup recast
-/// @see rcBuildCompactHeightfield, rcFreeCompactHeightfield
-rcCompactHeightfield* rcAllocCompactHeightfield();
-
-/// Frees the specified compact heightfield object using the Recast allocator.
-/// @param[in] chf A compact heightfield allocated using #rcAllocCompactHeightfield
-/// @ingroup recast
-/// @see rcAllocCompactHeightfield
-void rcFreeCompactHeightfield(rcCompactHeightfield* chf);
-
-/// Allocates a heightfield layer set using the Recast allocator.
-/// @return A heightfield layer set that is ready for initialization, or null on failure.
-/// @ingroup recast
-/// @see rcBuildHeightfieldLayers, rcFreeHeightfieldLayerSet
-rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet();
-
-/// Frees the specified heightfield layer set using the Recast allocator.
-/// @param[in] lset A heightfield layer set allocated using #rcAllocHeightfieldLayerSet
-/// @ingroup recast
-/// @see rcAllocHeightfieldLayerSet
-void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset);
-
-/// Allocates a contour set object using the Recast allocator.
-/// @return A contour set that is ready for initialization, or null on failure.
-/// @ingroup recast
-/// @see rcBuildContours, rcFreeContourSet
-rcContourSet* rcAllocContourSet();
-
-/// Frees the specified contour set using the Recast allocator.
-/// @param[in] cset A contour set allocated using #rcAllocContourSet
-/// @ingroup recast
-/// @see rcAllocContourSet
-void rcFreeContourSet(rcContourSet* cset);
-
-/// Allocates a polygon mesh object using the Recast allocator.
-/// @return A polygon mesh that is ready for initialization, or null on failure.
-/// @ingroup recast
-/// @see rcBuildPolyMesh, rcFreePolyMesh
-rcPolyMesh* rcAllocPolyMesh();
-
-/// Frees the specified polygon mesh using the Recast allocator.
-/// @param[in] pmesh A polygon mesh allocated using #rcAllocPolyMesh
-/// @ingroup recast
-/// @see rcAllocPolyMesh
-void rcFreePolyMesh(rcPolyMesh* pmesh);
-
/// Allocates a detail mesh object using the Recast allocator.
/// @return A detail mesh that is ready for initialization, or null on failure.
/// @ingroup recast
@@ -546,6 +457,32 @@ static const unsigned char RC_WALKABLE_AREA = 63;
/// to another span. (Has no neighbor.)
static const int RC_NOT_CONNECTED = 0x3f;
+// Compact span neighbour helpers.
+inline void rcSetCon(rcCompactSpan& s, int dir, int i)
+{
+ const unsigned int shift = (unsigned int)dir*6;
+ unsigned int con = s.con;
+ s.con = (con & ~(0x3f << shift)) | (((unsigned int)i & 0x3f) << shift);
+}
+
+inline int rcGetCon(const rcCompactSpan& s, int dir)
+{
+ const unsigned int shift = (unsigned int)dir*6;
+ return (s.con >> shift) & 0x3f;
+}
+
+inline int rcGetDirOffsetX(int dir)
+{
+ const int offset[4] = { -1, 0, 1, 0, };
+ return offset[dir&0x03];
+}
+
+inline int rcGetDirOffsetY(int dir)
+{
+ const int offset[4] = { 0, 1, 0, -1 };
+ return offset[dir&0x03];
+}
+
/// @name General helper functions
/// @{
@@ -710,6 +647,13 @@ inline void rcVnormalize(float* v)
v[2] *= d;
}
+inline bool rcVequal(const float* p0, const float* p1)
+{
+ static const float thr = rcSqr(1.0f/16384.0f);
+ const float d = rcVdistSqr(p0, p1);
+ return d < thr;
+}
+
/// @}
/// @name Heightfield Functions
/// @see rcHeightfield
@@ -774,20 +718,18 @@ void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
const int* tris, int nt, unsigned char* areas);
/// Adds a span to the specified heightfield.
-/// @ingroup recast
-/// @param[in,out] ctx The build context to use during the operation.
-/// @param[in,out] hf An initialized heightfield.
-/// @param[in] x The width index where the span is to be added.
-/// [Limits: 0 <= value < rcHeightfield::width]
-/// @param[in] y The height index where the span is to be added.
-/// [Limits: 0 <= value < rcHeightfield::height]
-/// @param[in] smin The minimum height of the span. [Limit: < @p smax] [Units: vx]
-/// @param[in] smax The maximum height of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT] [Units: vx]
-/// @param[in] area The area id of the span. [Limit: <= #RC_WALKABLE_AREA)
-/// @param[in] flagMergeThr The merge theshold. [Limit: >= 0] [Units: vx]
-void rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y,
+// The span addition can set to favor flags. If the span is merged to
+// another span and the new smax is within 'flagMergeThr' units away
+// from the existing span the span flags are merged and stored.
+// Params:
+// solid - (in) heightfield where the spans is added to
+// x,y - (in) location on the heightfield where the span is added
+// smin,smax - (in) spans min/max height
+// flags - (in) span flags (zero or WALKABLE)
+// flagMergeThr - (in) merge threshold.
+void rcAddSpan(rcContext* ctx, rcHeightfield& solid, const int x, const int y,
const unsigned short smin, const unsigned short smax,
- const unsigned char area, const int flagMergeThr);
+ const unsigned short area, const int flagMergeThr);
/// Rasterizes a triangle into the specified heightfield.
/// @ingroup recast
@@ -935,28 +877,6 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
const float hmin, const float hmax, unsigned char areaId,
rcCompactHeightfield& chf);
-/// Helper function to offset voncex polygons for rcMarkConvexPolyArea.
-/// @ingroup recast
-/// @param[in] verts The vertices of the polygon [Form: (x, y, z) * @p nverts]
-/// @param[in] nverts The number of vertices in the polygon.
-/// @param[out] outVerts The offset vertices (should hold up to 2 * @p nverts) [Form: (x, y, z) * return value]
-/// @param[in] maxOutVerts The max number of vertices that can be stored to @p outVerts.
-/// @returns Number of vertices in the offset polygon or 0 if too few vertices in @p outVerts.
-int rcOffsetPoly(const float* verts, const int nverts, const float offset,
- float* outVerts, const int maxOutVerts);
-
-/// Applies the area id to all spans within the specified cylinder.
-/// @ingroup recast
-/// @param[in,out] ctx The build context to use during the operation.
-/// @param[in] pos The center of the base of the cylinder. [Form: (x, y, z)]
-/// @param[in] r The radius of the cylinder.
-/// @param[in] h The height of the cylinder.
-/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA]
-/// @param[in,out] chf A populated compact heightfield.
-void rcMarkCylinderArea(rcContext* ctx, const float* pos,
- const float r, const float h, unsigned char areaId,
- rcCompactHeightfield& chf);
-
/// Builds the distance field for the specified compact heightfield.
/// @ingroup recast
/// @param[in,out] ctx The build context to use during the operation.
@@ -992,68 +912,6 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
const int borderSize, const int minRegionArea, const int mergeRegionArea);
-
-/// Sets the neighbor connection data for the specified direction.
-/// @param[in] s The span to update.
-/// @param[in] dir The direction to set. [Limits: 0 <= value < 4]
-/// @param[in] i The index of the neighbor span.
-inline void rcSetCon(rcCompactSpan& s, int dir, int i)
-{
- const unsigned int shift = (unsigned int)dir*6;
- unsigned int con = s.con;
- s.con = (con & ~(0x3f << shift)) | (((unsigned int)i & 0x3f) << shift);
-}
-
-/// Gets neighbor connection data for the specified direction.
-/// @param[in] s The span to check.
-/// @param[in] dir The direction to check. [Limits: 0 <= value < 4]
-/// @return The neighbor connection data for the specified direction,
-/// or #RC_NOT_CONNECTED if there is no connection.
-inline int rcGetCon(const rcCompactSpan& s, int dir)
-{
- const unsigned int shift = (unsigned int)dir*6;
- return (s.con >> shift) & 0x3f;
-}
-
-/// Gets the standard width (x-axis) offset for the specified direction.
-/// @param[in] dir The direction. [Limits: 0 <= value < 4]
-/// @return The width offset to apply to the current cell position to move
-/// in the direction.
-inline int rcGetDirOffsetX(int dir)
-{
- const int offset[4] = { -1, 0, 1, 0, };
- return offset[dir&0x03];
-}
-
-/// Gets the standard height (z-axis) offset for the specified direction.
-/// @param[in] dir The direction. [Limits: 0 <= value < 4]
-/// @return The height offset to apply to the current cell position to move
-/// in the direction.
-inline int rcGetDirOffsetY(int dir)
-{
- const int offset[4] = { 0, 1, 0, -1 };
- return offset[dir&0x03];
-}
-
-/// @}
-/// @name Layer, Contour, Polymesh, and Detail Mesh Functions
-/// @see rcHeightfieldLayer, rcContourSet, rcPolyMesh, rcPolyMeshDetail
-/// @{
-
-/// Builds a layer set from the specified compact heightfield.
-/// @ingroup recast
-/// @param[in,out] ctx The build context to use during the operation.
-/// @param[in] chf A fully built compact heightfield.
-/// @param[in] borderSize The size of the non-navigable border around the heightfield. [Limit: >=0]
-/// [Units: vx]
-/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area
-/// to be considered walkable. [Limit: >= 3] [Units: vx]
-/// @param[out] lset The resulting layer set. (Must be pre-allocated.)
-/// @returns True if the operation completed successfully.
-bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
- const int borderSize, const int walkableHeight,
- rcHeightfieldLayerSet& lset);
-
/// Builds a contour set from the region outlines in the provided compact heightfield.
/// @ingroup recast
/// @param[in,out] ctx The build context to use during the operation.
@@ -1069,15 +927,13 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
const float maxError, const int maxEdgeLen,
rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES);
-/// Builds a polygon mesh from the provided contours.
-/// @ingroup recast
-/// @param[in,out] ctx The build context to use during the operation.
-/// @param[in] cset A fully built contour set.
-/// @param[in] nvp The maximum number of vertices allowed for polygons generated during the
-/// contour to polygon conversion process. [Limit: >= 3]
-/// @param[out] mesh The resulting polygon mesh. (Must be re-allocated.)
-/// @returns True if the operation completed successfully.
-bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh);
+// Builds connected convex polygon mesh from contour polygons.
+// Params:
+// cset - (in) contour set.
+// nvp - (in) maximum number of vertices per polygon.
+// mesh - (out) poly mesh.
+// Returns false if operation ran out of memory.
+bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh);
/// Merges multiple polygon meshes into a single mesh.
/// @ingroup recast
@@ -1102,14 +958,6 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa
const float sampleDist, const float sampleMaxError,
rcPolyMeshDetail& dmesh);
-/// Copies the poly mesh data from src to dst.
-/// @ingroup recast
-/// @param[in,out] ctx The build context to use during the operation.
-/// @param[in] src The source mesh to copy from.
-/// @param[out] dst The resulting detail mesh. (Must be pre-allocated, must be empty mesh.)
-/// @returns True if the operation completed successfully.
-bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst);
-
/// Merges multiple detail meshes into a single detail mesh.
/// @ingroup recast
/// @param[in,out] ctx The build context to use during the operation.
diff --git a/dep/recastnavigation/Recast/RecastArea.cpp b/dep/recastnavigation/Recast/RecastArea.cpp
index 1a338cd9b8c..4e7b79d301d 100644
--- a/dep/recastnavigation/Recast/RecastArea.cpp
+++ b/dep/recastnavigation/Recast/RecastArea.cpp
@@ -61,26 +61,14 @@ bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf)
const rcCompactCell& c = chf.cells[x+y*w];
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
- if (chf.areas[i] == RC_NULL_AREA)
- {
- dist[i] = 0;
- }
- else
+ if (chf.areas[i] != RC_NULL_AREA)
{
const rcCompactSpan& s = chf.spans[i];
int nc = 0;
for (int dir = 0; dir < 4; ++dir)
{
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
- {
- const int nx = x + rcGetDirOffsetX(dir);
- const int ny = y + rcGetDirOffsetY(dir);
- const int nidx = (int)chf.cells[nx+ny*w].index + rcGetCon(s, dir);
- if (chf.areas[nidx] != RC_NULL_AREA)
- {
- nc++;
- }
- }
+ nc++;
}
// At least one missing neighbour.
if (nc != 4)
@@ -351,8 +339,7 @@ void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigne
rcCompactSpan& s = chf.spans[i];
if ((int)s.y >= miny && (int)s.y <= maxy)
{
- if (chf.areas[i] != RC_NULL_AREA)
- chf.areas[i] = areaId;
+ chf.areas[i] = areaId;
}
}
}
@@ -431,8 +418,6 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
rcCompactSpan& s = chf.spans[i];
- if (chf.areas[i] == RC_NULL_AREA)
- continue;
if ((int)s.y >= miny && (int)s.y <= maxy)
{
float p[3];
@@ -451,152 +436,3 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
}
-
-int rcOffsetPoly(const float* verts, const int nverts, const float offset,
- float* outVerts, const int maxOutVerts)
-{
- const float MITER_LIMIT = 1.20f;
-
- int n = 0;
-
- for (int i = 0; i < nverts; i++)
- {
- const int a = (i+nverts-1) % nverts;
- const int b = i;
- const int c = (i+1) % nverts;
- const float* va = &verts[a*3];
- const float* vb = &verts[b*3];
- const float* vc = &verts[c*3];
- float dx0 = vb[0] - va[0];
- float dy0 = vb[2] - va[2];
- float d0 = dx0*dx0 + dy0*dy0;
- if (d0 > 1e-6f)
- {
- d0 = 1.0f/rcSqrt(d0);
- dx0 *= d0;
- dy0 *= d0;
- }
- float dx1 = vc[0] - vb[0];
- float dy1 = vc[2] - vb[2];
- float d1 = dx1*dx1 + dy1*dy1;
- if (d1 > 1e-6f)
- {
- d1 = 1.0f/rcSqrt(d1);
- dx1 *= d1;
- dy1 *= d1;
- }
- const float dlx0 = -dy0;
- const float dly0 = dx0;
- const float dlx1 = -dy1;
- const float dly1 = dx1;
- float cross = dx1*dy0 - dx0*dy1;
- float dmx = (dlx0 + dlx1) * 0.5f;
- float dmy = (dly0 + dly1) * 0.5f;
- float dmr2 = dmx*dmx + dmy*dmy;
- bool bevel = dmr2 * MITER_LIMIT*MITER_LIMIT < 1.0f;
- if (dmr2 > 1e-6f)
- {
- const float scale = 1.0f / dmr2;
- dmx *= scale;
- dmy *= scale;
- }
-
- if (bevel && cross < 0.0f)
- {
- if (n+2 >= maxOutVerts)
- return 0;
- float d = (1.0f - (dx0*dx1 + dy0*dy1))*0.5f;
- outVerts[n*3+0] = vb[0] + (-dlx0+dx0*d)*offset;
- outVerts[n*3+1] = vb[1];
- outVerts[n*3+2] = vb[2] + (-dly0+dy0*d)*offset;
- n++;
- outVerts[n*3+0] = vb[0] + (-dlx1-dx1*d)*offset;
- outVerts[n*3+1] = vb[1];
- outVerts[n*3+2] = vb[2] + (-dly1-dy1*d)*offset;
- n++;
- }
- else
- {
- if (n+1 >= maxOutVerts)
- return 0;
- outVerts[n*3+0] = vb[0] - dmx*offset;
- outVerts[n*3+1] = vb[1];
- outVerts[n*3+2] = vb[2] - dmy*offset;
- n++;
- }
- }
-
- return n;
-}
-
-
-/// @par
-///
-/// The value of spacial parameters are in world units.
-///
-/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
-void rcMarkCylinderArea(rcContext* ctx, const float* pos,
- const float r, const float h, unsigned char areaId,
- rcCompactHeightfield& chf)
-{
- rcAssert(ctx);
-
- ctx->startTimer(RC_TIMER_MARK_CYLINDER_AREA);
-
- float bmin[3], bmax[3];
- bmin[0] = pos[0] - r;
- bmin[1] = pos[1];
- bmin[2] = pos[2] - r;
- bmax[0] = pos[0] + r;
- bmax[1] = pos[1] + h;
- bmax[2] = pos[2] + r;
- const float r2 = r*r;
-
- int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
- int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
- int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
- int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
- int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
- int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
-
- if (maxx < 0) return;
- if (minx >= chf.width) return;
- if (maxz < 0) return;
- if (minz >= chf.height) return;
-
- if (minx < 0) minx = 0;
- if (maxx >= chf.width) maxx = chf.width-1;
- if (minz < 0) minz = 0;
- if (maxz >= chf.height) maxz = chf.height-1;
-
-
- for (int z = minz; z <= maxz; ++z)
- {
- for (int x = minx; x <= maxx; ++x)
- {
- const rcCompactCell& c = chf.cells[x+z*chf.width];
- for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
- {
- rcCompactSpan& s = chf.spans[i];
-
- if (chf.areas[i] == RC_NULL_AREA)
- continue;
-
- if ((int)s.y >= miny && (int)s.y <= maxy)
- {
- const float sx = chf.bmin[0] + (x+0.5f)*chf.cs;
- const float sz = chf.bmin[2] + (z+0.5f)*chf.cs;
- const float dx = sx - pos[0];
- const float dz = sz - pos[2];
-
- if (dx*dx + dz*dz < r2)
- {
- chf.areas[i] = areaId;
- }
- }
- }
- }
- }
-
- ctx->stopTimer(RC_TIMER_MARK_CYLINDER_AREA);
-}
diff --git a/dep/recastnavigation/Recast/RecastContour.cpp b/dep/recastnavigation/Recast/RecastContour.cpp
index 5c324bcedfe..8500e97f08d 100644
--- a/dep/recastnavigation/Recast/RecastContour.cpp
+++ b/dep/recastnavigation/Recast/RecastContour.cpp
@@ -420,13 +420,15 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified,
// Round based on the segments in lexilogical order so that the
// max tesselation is consistent regardles in which direction
// segments are traversed.
- const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
- if (n > 1)
+ if (bx > ax || (bx == ax && bz > az))
{
- if (bx > ax || (bx == ax && bz > az))
- maxi = (ai + n/2) % pn;
- else
- maxi = (ai + (n+1)/2) % pn;
+ const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
+ maxi = (ai + n/2) % pn;
+ }
+ else
+ {
+ const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
+ maxi = (ai + (n+1)/2) % pn;
}
}
}
@@ -464,7 +466,7 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified,
// and the neighbour region is take from the next raw point.
const int ai = (simplified[i*4+3]+1) % pn;
const int bi = simplified[i*4+3];
- simplified[i*4+3] = (points[ai*4+3] & (RC_CONTOUR_REG_MASK|RC_AREA_BORDER)) | (points[bi*4+3] & RC_BORDER_VERTEX);
+ simplified[i*4+3] = (points[ai*4+3] & RC_CONTOUR_REG_MASK) | (points[bi*4+3] & RC_BORDER_VERTEX);
}
}
@@ -611,26 +613,13 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
const int w = chf.width;
const int h = chf.height;
- const int borderSize = chf.borderSize;
ctx->startTimer(RC_TIMER_BUILD_CONTOURS);
rcVcopy(cset.bmin, chf.bmin);
rcVcopy(cset.bmax, chf.bmax);
- if (borderSize > 0)
- {
- // If the heightfield was build with bordersize, remove the offset.
- const float pad = borderSize*chf.cs;
- cset.bmin[0] += pad;
- cset.bmin[2] += pad;
- cset.bmax[0] -= pad;
- cset.bmax[2] -= pad;
- }
cset.cs = chf.cs;
cset.ch = chf.ch;
- cset.width = chf.width - chf.borderSize*2;
- cset.height = chf.height - chf.borderSize*2;
- cset.borderSize = chf.borderSize;
int maxContours = rcMax((int)chf.maxRegions, 8);
cset.conts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM);
@@ -682,6 +671,8 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
+ ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
+
rcIntArray verts(256);
rcIntArray simplified(64);
@@ -704,17 +695,10 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
verts.resize(0);
simplified.resize(0);
-
- ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
walkContour(x, y, i, chf, flags, verts);
- ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
-
- ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
simplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags);
removeDegenerateSegments(simplified);
- ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
-
// Store region->contour remap info.
// Create contour.
if (simplified.size()/4 >= 3)
@@ -749,16 +733,6 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
return false;
}
memcpy(cont->verts, &simplified[0], sizeof(int)*cont->nverts*4);
- if (borderSize > 0)
- {
- // If the heightfield was build with bordersize, remove the offset.
- for (int j = 0; j < cont->nverts; ++j)
- {
- int* v = &cont->verts[j*4];
- v[0] -= borderSize;
- v[2] -= borderSize;
- }
- }
cont->nrverts = verts.size()/4;
cont->rverts = (int*)rcAlloc(sizeof(int)*cont->nrverts*4, RC_ALLOC_PERM);
@@ -768,16 +742,6 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
return false;
}
memcpy(cont->rverts, &verts[0], sizeof(int)*cont->nrverts*4);
- if (borderSize > 0)
- {
- // If the heightfield was build with bordersize, remove the offset.
- for (int j = 0; j < cont->nrverts; ++j)
- {
- int* v = &cont->rverts[j*4];
- v[0] -= borderSize;
- v[2] -= borderSize;
- }
- }
/* cont->cx = cont->cy = cont->cz = 0;
for (int i = 0; i < cont->nverts; ++i)
@@ -845,6 +809,8 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
}
}
+ ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
+
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS);
return true;
diff --git a/dep/recastnavigation/Recast/RecastFilter.cpp b/dep/recastnavigation/Recast/RecastFilter.cpp
index bf985c362c9..42d9f2c755b 100644
--- a/dep/recastnavigation/Recast/RecastFilter.cpp
+++ b/dep/recastnavigation/Recast/RecastFilter.cpp
@@ -48,7 +48,6 @@ void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb
{
rcSpan* ps = 0;
bool previousWalkable = false;
- unsigned char previousArea = RC_NULL_AREA;
for (rcSpan* s = solid.spans[x + y*w]; s; ps = s, s = s->next)
{
@@ -58,12 +57,11 @@ void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb
if (!walkable && previousWalkable)
{
if (rcAbs((int)s->smax - (int)ps->smax) <= walkableClimb)
- s->area = previousArea;
+ s->area = RC_NULL_AREA;
}
// Copy walkable flag so that it cannot propagate
// past multiple non-walkable objects.
previousWalkable = walkable;
- previousArea = s->area;
}
}
}
diff --git a/dep/recastnavigation/Recast/RecastMesh.cpp b/dep/recastnavigation/Recast/RecastMesh.cpp
index 13aad2af01c..088b67aafd3 100644
--- a/dep/recastnavigation/Recast/RecastMesh.cpp
+++ b/dep/recastnavigation/Recast/RecastMesh.cpp
@@ -59,7 +59,6 @@ static bool buildMeshAdjacency(unsigned short* polys, const int npolys,
unsigned short* t = &polys[i*vertsPerPoly*2];
for (int j = 0; j < vertsPerPoly; ++j)
{
- if (t[j] == RC_MESH_NULL_IDX) break;
unsigned short v0 = t[j];
unsigned short v1 = (j+1 >= vertsPerPoly || t[j+1] == RC_MESH_NULL_IDX) ? t[0] : t[j+1];
if (v0 < v1)
@@ -84,7 +83,6 @@ static bool buildMeshAdjacency(unsigned short* polys, const int npolys,
unsigned short* t = &polys[i*vertsPerPoly*2];
for (int j = 0; j < vertsPerPoly; ++j)
{
- if (t[j] == RC_MESH_NULL_IDX) break;
unsigned short v0 = t[j];
unsigned short v1 = (j+1 >= vertsPerPoly || t[j+1] == RC_MESH_NULL_IDX) ? t[0] : t[j+1];
if (v0 > v1)
@@ -197,7 +195,7 @@ inline bool collinear(const int* a, const int* b, const int* c)
// Returns true iff ab properly intersects cd: they share
// a point interior to both segments. The properness of the
// intersection is ensured by using strict leftness.
-static bool intersectProp(const int* a, const int* b, const int* c, const int* d)
+bool intersectProp(const int* a, const int* b, const int* c, const int* d)
{
// Eliminate improper cases.
if (collinear(a,b,c) || collinear(a,b,d) ||
@@ -550,9 +548,9 @@ static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned sho
// Check if the edge exists
bool exists = false;
- for (int m = 0; m < nedges; ++m)
+ for (int k = 0; k < nedges; ++k)
{
- int* e = &edges[m*3];
+ int* e = &edges[k*3];
if (e[1] == b)
{
// Exists, increment vertex share count.
@@ -895,13 +893,8 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short
return true;
}
-/// @par
-///
-/// @note If the mesh data is to be used to construct a Detour navigation mesh, then the upper
-/// limit must be retricted to <= #DT_VERTS_PER_POLYGON.
-///
-/// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig
-bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh)
+
+bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh)
{
rcAssert(ctx);
@@ -911,7 +904,6 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
rcVcopy(mesh.bmax, cset.bmax);
mesh.cs = cset.cs;
mesh.ch = cset.ch;
- mesh.borderSize = cset.borderSize;
int maxVertices = 0;
int maxTris = 0;
@@ -934,7 +926,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
rcScopedDelete<unsigned char> vflags = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxVertices, RC_ALLOC_TEMP);
if (!vflags)
{
- ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'vflags' (%d).", maxVertices);
+ ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices);
return false;
}
memset(vflags, 0, maxVertices);
@@ -945,7 +937,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices);
return false;
}
- mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris*nvp*2, RC_ALLOC_PERM);
+ mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris*nvp*2*2, RC_ALLOC_PERM);
if (!mesh.polys)
{
ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.polys' (%d).", maxTris*nvp*2);
@@ -1163,37 +1155,6 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Adjacency failed.");
return false;
}
-
- // Find portal edges
- if (mesh.borderSize > 0)
- {
- const int w = cset.width;
- const int h = cset.height;
- for (int i = 0; i < mesh.npolys; ++i)
- {
- unsigned short* p = &mesh.polys[i*2*nvp];
- for (int j = 0; j < nvp; ++j)
- {
- if (p[j] == RC_MESH_NULL_IDX) break;
- // Skip connected edges.
- if (p[nvp+j] != RC_MESH_NULL_IDX)
- continue;
- int nj = j+1;
- if (nj >= nvp || p[nj] == RC_MESH_NULL_IDX) nj = 0;
- const unsigned short* va = &mesh.verts[p[j]*3];
- const unsigned short* vb = &mesh.verts[p[nj]*3];
-
- if ((int)va[0] == 0 && (int)vb[0] == 0)
- p[nvp+j] = 0x8000 | 0;
- else if ((int)va[2] == h && (int)vb[2] == h)
- p[nvp+j] = 0x8000 | 1;
- else if ((int)va[0] == w && (int)vb[0] == w)
- p[nvp+j] = 0x8000 | 2;
- else if ((int)va[2] == 0 && (int)vb[2] == 0)
- p[nvp+j] = 0x8000 | 3;
- }
- }
- }
// Just allocate the mesh flags array. The user is resposible to fill it.
mesh.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*mesh.npolys, RC_ALLOC_PERM);
@@ -1206,11 +1167,11 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
if (mesh.nverts > 0xffff)
{
- ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many vertices %d (max %d). Data can be corrupted.", mesh.nverts, 0xffff);
+ ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many vertices %d (max %d). Data can be corrupted.", mesh.nverts, 0xffff);
}
if (mesh.npolys > 0xffff)
{
- ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff);
+ ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff);
}
ctx->stopTimer(RC_TIMER_BUILD_POLYMESH);
@@ -1310,7 +1271,7 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r
ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'vremap' (%d).", maxVertsPerMesh);
return false;
}
- memset(vremap, 0, sizeof(unsigned short)*maxVertsPerMesh);
+ memset(nextVert, 0, sizeof(int)*maxVerts);
for (int i = 0; i < nmeshes; ++i)
{
@@ -1362,67 +1323,3 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r
return true;
}
-
-bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst)
-{
- rcAssert(ctx);
-
- // Destination must be empty.
- rcAssert(dst.verts == 0);
- rcAssert(dst.polys == 0);
- rcAssert(dst.regs == 0);
- rcAssert(dst.areas == 0);
- rcAssert(dst.flags == 0);
-
- dst.nverts = src.nverts;
- dst.npolys = src.npolys;
- dst.maxpolys = src.npolys;
- dst.nvp = src.nvp;
- rcVcopy(dst.bmin, src.bmin);
- rcVcopy(dst.bmax, src.bmax);
- dst.cs = src.cs;
- dst.ch = src.ch;
- dst.borderSize = src.borderSize;
-
- dst.verts = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.nverts*3, RC_ALLOC_PERM);
- if (!dst.verts)
- {
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.verts' (%d).", src.nverts*3);
- return false;
- }
- memcpy(dst.verts, src.verts, sizeof(unsigned short)*src.nverts*3);
-
- dst.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys*2*src.nvp, RC_ALLOC_PERM);
- if (!dst.polys)
- {
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.polys' (%d).", src.npolys*2*src.nvp);
- return false;
- }
- memcpy(dst.polys, src.polys, sizeof(unsigned short)*src.npolys*2*src.nvp);
-
- dst.regs = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys, RC_ALLOC_PERM);
- if (!dst.regs)
- {
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.regs' (%d).", src.npolys);
- return false;
- }
- memcpy(dst.regs, src.regs, sizeof(unsigned short)*src.npolys);
-
- dst.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*src.npolys, RC_ALLOC_PERM);
- if (!dst.areas)
- {
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.areas' (%d).", src.npolys);
- return false;
- }
- memcpy(dst.areas, src.areas, sizeof(unsigned char)*src.npolys);
-
- dst.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys, RC_ALLOC_PERM);
- if (!dst.flags)
- {
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.flags' (%d).", src.npolys);
- return false;
- }
- memcpy(dst.flags, src.flags, sizeof(unsigned char)*src.npolys);
-
- return true;
-}
diff --git a/dep/recastnavigation/Recast/RecastMeshDetail.cpp b/dep/recastnavigation/Recast/RecastMeshDetail.cpp
index f49d67400c2..77a085c5c2b 100644
--- a/dep/recastnavigation/Recast/RecastMeshDetail.cpp
+++ b/dep/recastnavigation/Recast/RecastMeshDetail.cpp
@@ -267,11 +267,11 @@ static int addEdge(rcContext* ctx, int* edges, int& nedges, const int maxEdges,
int e = findEdge(edges, nedges, s, t);
if (e == UNDEF)
{
- int* edge = &edges[nedges*4];
- edge[0] = s;
- edge[1] = t;
- edge[2] = l;
- edge[3] = r;
+ int* e = &edges[nedges*4];
+ e[0] = s;
+ e[1] = t;
+ e[2] = l;
+ e[3] = r;
return nedges++;
}
else
@@ -554,7 +554,7 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
float dx = vi[0] - vj[0];
float dy = vi[1] - vj[1];
float dz = vi[2] - vj[2];
- float d = rcSqrt(dx*dx + dz*dz);
+ float d = sqrtf(dx*dx + dz*dz);
int nn = 1 + (int)floorf(d/sampleDist);
if (nn >= MAX_VERTS_PER_EDGE) nn = MAX_VERTS_PER_EDGE-1;
if (nverts+nn >= MAX_VERTS)
@@ -583,10 +583,10 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
int maxi = -1;
for (int m = a+1; m < b; ++m)
{
- float dev = distancePtSeg(&edge[m*3],va,vb);
- if (dev > maxd)
+ float d = distancePtSeg(&edge[m*3],va,vb);
+ if (d > maxd)
{
- maxd = dev;
+ maxd = d;
maxi = m;
}
}
@@ -743,7 +743,7 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
static void getHeightData(const rcCompactHeightfield& chf,
const unsigned short* poly, const int npoly,
- const unsigned short* verts, const int bs,
+ const unsigned short* verts,
rcHeightPatch& hp, rcIntArray& stack)
{
// Floodfill the heightfield to get 2D height data,
@@ -775,7 +775,7 @@ static void getHeightData(const rcCompactHeightfield& chf,
az < hp.ymin || az >= hp.ymin+hp.height)
continue;
- const rcCompactCell& c = chf.cells[(ax+bs)+(az+bs)*chf.width];
+ const rcCompactCell& c = chf.cells[ax+az*chf.width];
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
const rcCompactSpan& s = chf.spans[i];
@@ -847,7 +847,7 @@ static void getHeightData(const rcCompactHeightfield& chf,
if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != 0)
continue;
- const int ai = (int)chf.cells[(ax+bs)+(ay+bs)*chf.width].index + rcGetCon(cs, dir);
+ const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(cs, dir);
int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width;
hp.data[idx] = 1;
@@ -903,7 +903,7 @@ static void getHeightData(const rcCompactHeightfield& chf,
if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != RC_UNSET_HEIGHT)
continue;
- const int ai = (int)chf.cells[(ax+bs)+(ay+bs)*chf.width].index + rcGetCon(cs, dir);
+ const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(cs, dir);
const rcCompactSpan& as = chf.spans[ai];
int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width;
@@ -961,7 +961,6 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa
const float cs = mesh.cs;
const float ch = mesh.ch;
const float* orig = mesh.bmin;
- const int borderSize = mesh.borderSize;
rcIntArray edges(64);
rcIntArray tris(512);
@@ -1072,7 +1071,7 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa
hp.ymin = bounds[i*4+2];
hp.width = bounds[i*4+1]-bounds[i*4+0];
hp.height = bounds[i*4+3]-bounds[i*4+2];
- getHeightData(chf, p, npoly, mesh.verts, borderSize, hp, stack);
+ getHeightData(chf, p, npoly, mesh.verts, hp, stack);
// Build detail mesh.
int nverts = 0;
diff --git a/dep/recastnavigation/Recast/RecastRegion.cpp b/dep/recastnavigation/Recast/RecastRegion.cpp
index 76e631cc5fb..2da99abb41b 100644
--- a/dep/recastnavigation/Recast/RecastRegion.cpp
+++ b/dep/recastnavigation/Recast/RecastRegion.cpp
@@ -283,8 +283,6 @@ static bool floodRegion(int x, int y, int i,
if (chf.areas[ai] != area)
continue;
unsigned short nr = srcReg[ai];
- if (nr & RC_BORDER_REG) // Do not take borders into account.
- continue;
if (nr != 0 && nr != r)
ar = nr;
@@ -298,9 +296,9 @@ static bool floodRegion(int x, int y, int i,
const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2);
if (chf.areas[ai2] != area)
continue;
- unsigned short nr2 = srcReg[ai2];
- if (nr2 != 0 && nr2 != r)
- ar = nr2;
+ unsigned short nr = srcReg[ai2];
+ if (nr != 0 && nr != r)
+ ar = nr;
}
}
}
@@ -321,13 +319,16 @@ static bool floodRegion(int x, int y, int i,
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(cs, dir);
if (chf.areas[ai] != area)
continue;
- if (chf.dist[ai] >= lev && srcReg[ai] == 0)
+ if (chf.dist[ai] >= lev)
{
- srcReg[ai] = r;
- srcDist[ai] = 0;
- stack.push(ax);
- stack.push(ay);
- stack.push(ai);
+ if (srcReg[ai] == 0)
+ {
+ srcReg[ai] = r;
+ srcDist[ai] = 0;
+ stack.push(ax);
+ stack.push(ay);
+ stack.push(ai);
+ }
}
}
}
@@ -678,17 +679,17 @@ static void walkContour(int x, int y, int i, int dir,
// Remove adjacent duplicates.
if (cont.size() > 1)
{
- for (int j = 0; j < cont.size(); )
+ for (int i = 0; i < cont.size(); )
{
- int nj = (j+1) % cont.size();
- if (cont[j] == cont[nj])
+ int ni = (i+1) % cont.size();
+ if (cont[i] == cont[ni])
{
- for (int k = j; k < cont.size()-1; ++k)
- cont[k] = cont[k+1];
+ for (int j = i; j < cont.size()-1; ++j)
+ cont[j] = cont[j+1];
cont.pop();
}
else
- ++j;
+ ++i;
}
}
}
@@ -806,14 +807,14 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio
connectsToBorder = true;
continue;
}
- rcRegion& neireg = regions[creg.connections[j]];
- if (neireg.visited)
+ rcRegion& nreg = regions[creg.connections[j]];
+ if (nreg.visited)
continue;
- if (neireg.id == 0 || (neireg.id & RC_BORDER_REG))
+ if (nreg.id == 0 || (nreg.id & RC_BORDER_REG))
continue;
// Visit
- stack.push(neireg.id);
- neireg.visited = true;
+ stack.push(nreg.id);
+ nreg.visited = true;
}
}
@@ -1086,8 +1087,6 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
paintRectRegion(w-bw, w, 0, h, id|RC_BORDER_REG, chf, srcReg); id++;
paintRectRegion(0, w, 0, bh, id|RC_BORDER_REG, chf, srcReg); id++;
paintRectRegion(0, w, h-bh, h, id|RC_BORDER_REG, chf, srcReg); id++;
-
- chf.borderSize = borderSize;
}
rcIntArray prev(256);
@@ -1257,19 +1256,11 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
// const int expandIters = 4 + walkableRadius * 2;
const int expandIters = 8;
- if (borderSize > 0)
- {
- // Make sure border will not overflow.
- const int bw = rcMin(w, borderSize);
- const int bh = rcMin(h, borderSize);
- // Paint regions
- paintRectRegion(0, bw, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
- paintRectRegion(w-bw, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
- paintRectRegion(0, w, 0, bh, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
- paintRectRegion(0, w, h-bh, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
-
- chf.borderSize = borderSize;
- }
+ // Mark border regions.
+ paintRectRegion(0, borderSize, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
+ paintRectRegion(w-borderSize, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
+ paintRectRegion(0, w, 0, borderSize, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
+ paintRectRegion(0, w, h-borderSize, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
while (level > 0)
{
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 961a896a8f7..7cf4f9fa192 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -3550,7 +3550,7 @@ enum PartyResult
};
const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
-#define MMAP_VERSION 4
+#define MMAP_VERSION 3
struct MmapTileHeader
{
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
index 91ad6d2b676..1f36b7c3106 100644
--- a/src/server/game/Movement/PathGenerator.cpp
+++ b/src/server/game/Movement/PathGenerator.cpp
@@ -581,7 +581,7 @@ bool PathGenerator::HaveTile(const G3D::Vector3& p) const
if (tx < 0 || ty < 0)
return false;
- return (_navMesh->getTileAt(tx, ty, 0) != NULL);
+ return (_navMesh->getTileAt(tx, ty) != NULL);
}
uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited)
diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp
index aa02d76fe47..5524b994175 100644
--- a/src/tools/mmaps_generator/MapBuilder.cpp
+++ b/src/tools/mmaps_generator/MapBuilder.cpp
@@ -36,7 +36,7 @@ namespace DisableMgr
}
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
-#define MMAP_VERSION 4
+#define MMAP_VERSION 3
struct MmapTileHeader
{
@@ -701,6 +701,14 @@ namespace MMAP
delete[] dmmerge;
delete[] tiles;
+ // remove padding for extraction
+ for (int i = 0; i < iv.polyMesh->nverts; ++i)
+ {
+ unsigned short* v = &iv.polyMesh->verts[i * 3];
+ v[0] -= (unsigned short)config.borderSize;
+ v[2] -= (unsigned short)config.borderSize;
+ }
+
// set polygons as walkable
// TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off
for (int i = 0; i < iv.polyMesh->npolys; ++i)
@@ -739,8 +747,9 @@ namespace MMAP
rcVcopy(params.bmax, bmax);
params.cs = config.cs;
params.ch = config.ch;
- params.tileLayer = 0;
- params.buildBvTree = true;
+ params.tileSize = VERTEX_PER_MAP;
+ /*params.tileLayer = 0;
+ params.buildBvTree = true;*/
// will hold final navmesh
unsigned char* navData = NULL;