aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;