Fix for Issue 70: more const methods, Fix for Issue 72: changed to more accuracte tile connection test.

This commit is contained in:
Mikko Mononen 2010-04-22 13:13:27 +00:00
parent 4c1a122a91
commit 1769d70e5c
3 changed files with 115 additions and 59 deletions

View File

@ -217,7 +217,7 @@ public:
// Params: // Params:
// x,y - (in) Location of the tile to get. // x,y - (in) Location of the tile to get.
// Returns: pointer to tile if tile exists or 0 tile does not exists. // Returns: pointer to tile if tile exists or 0 tile does not exists.
dtMeshTile* getTileAt(int x, int y); dtMeshTile* getTileAt(int x, int y) const;
// Returns reference to tile at specified location. // Returns reference to tile at specified location.
// Params: // Params:
@ -269,7 +269,8 @@ public:
// filter - (in) path polygon filter. // filter - (in) path polygon filter.
// nearestPt[3] - (out, opt) The nearest point on found polygon, null if not needed. // 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. // Returns: Reference identifier for the polygon, or 0 if no polygons found.
dtPolyRef findNearestPoly(const float* center, const float* extents, dtQueryFilter* filter, float* nearestPt); dtPolyRef findNearestPoly(const float* center, const float* extents,
const dtQueryFilter* filter, float* nearestPt) const;
// Returns polygons which touch the query box. // Returns polygons which touch the query box.
// Params: // Params:
@ -279,8 +280,8 @@ public:
// polys - (out) array holding the search result. // polys - (out) array holding the search result.
// maxPolys - (in) The max number of polygons the polys array can hold. // maxPolys - (in) The max number of polygons the polys array can hold.
// Returns: Number of polygons in search result array. // Returns: Number of polygons in search result array.
int queryPolygons(const float* center, const float* extents, dtQueryFilter* filter, int queryPolygons(const float* center, const float* extents, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys); dtPolyRef* polys, const int maxPolys) const;
// Finds path from start polygon to end polygon. // Finds path from start polygon to end polygon.
// If target polygon canno be reached through the navigation graph, // If target polygon canno be reached through the navigation graph,
@ -298,8 +299,8 @@ public:
// Returns: Number of polygons in search result array. // Returns: Number of polygons in search result array.
int findPath(dtPolyRef startRef, dtPolyRef endRef, int findPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos, const float* startPos, const float* endPos,
dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* path, const int maxPathSize); dtPolyRef* path, const int maxPathSize) const;
// Finds a straight path from start to end locations within the corridor // Finds a straight path from start to end locations within the corridor
// described by the path polygons. // described by the path polygons.
@ -320,7 +321,7 @@ public:
int findStraightPath(const float* startPos, const float* endPos, int findStraightPath(const float* startPos, const float* endPos,
const dtPolyRef* path, const int pathSize, const dtPolyRef* path, const int pathSize,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
const int maxStraightPathSize); const int maxStraightPathSize) const;
// Moves towards end position a long the path corridor. // Moves towards end position a long the path corridor.
// The start location is assumed to be roughly at inside the first polygon on the path. // The start location is assumed to be roughly at inside the first polygon on the path.
@ -333,7 +334,7 @@ public:
// pathSize - (in) number of polygons on the path. // pathSize - (in) number of polygons on the path.
// Returns: Index to the path polygon where the result position lies. // Returns: Index to the path polygon where the result position lies.
int moveAlongPathCorridor(const float* startPos, const float* endPos, float* resultPos, int moveAlongPathCorridor(const float* startPos, const float* endPos, float* resultPos,
const dtPolyRef* path, const int pathSize); const dtPolyRef* path, const int pathSize) const;
// Castst 'walkability' ray along the navmesh surface from startPos towards the endPos. // Castst 'walkability' ray along the navmesh surface from startPos towards the endPos.
// Params: // Params:
@ -346,8 +347,8 @@ public:
// path - (out) visited path polygons. // path - (out) visited path polygons.
// pathSize - (in) max number of polygons in the path array. // pathSize - (in) max number of polygons in the path array.
// Returns: Number of polygons visited or 0 if failed. // Returns: Number of polygons visited or 0 if failed.
int raycast(dtPolyRef startRef, const float* startPos, const float* endPos, dtQueryFilter* filter, int raycast(dtPolyRef startRef, const float* startPos, const float* endPos, const dtQueryFilter* filter,
float& t, float* hitNormal, dtPolyRef* path, const int pathSize); float& t, float* hitNormal, dtPolyRef* path, const int pathSize) const;
// Returns distance to nearest wall from the specified location. // Returns distance to nearest wall from the specified location.
// Params: // Params:
@ -359,7 +360,7 @@ public:
// hitNormal[3] - (out) normal of the nearest hit. // hitNormal[3] - (out) normal of the nearest hit.
// Returns: Distance to nearest wall from the test location. // Returns: Distance to nearest wall from the test location.
float findDistanceToWall(dtPolyRef centerRef, const float* centerPos, float maxRadius, float findDistanceToWall(dtPolyRef centerRef, const float* centerPos, float maxRadius,
dtQueryFilter* filter, float* hitPos, float* hitNormal); const dtQueryFilter* filter, float* hitPos, float* hitNormal) const;
// Finds polygons found along the navigation graph which touch the specified circle. // Finds polygons found along the navigation graph which touch the specified circle.
// Params: // Params:
@ -372,9 +373,9 @@ public:
// resultCost - (out, opt) search cost at each result polygon. // resultCost - (out, opt) search cost at each result polygon.
// maxResult - (int) maximum capacity of search results. // maxResult - (int) maximum capacity of search results.
// Returns: Number of results. // Returns: Number of results.
int findPolysAround(dtPolyRef centerRef, const float* centerPos, float radius, dtQueryFilter* filter, int findPolysAround(dtPolyRef centerRef, const float* centerPos, float radius, const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
const int maxResult); const int maxResult) const;
// Returns closest point on navigation polygon. // Returns closest point on navigation polygon.
// Uses detail polygons to find the closest point to the navigation polygon surface. // Uses detail polygons to find the closest point to the navigation polygon surface.
@ -483,11 +484,11 @@ public:
private: private:
// Returns neighbour tile based on side. // Returns neighbour tile based on side.
dtMeshTile* getNeighbourTileAt(int x, int y, int side); dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
// Returns all polygons in neighbour tile based on portal defined by the segment. // Returns all polygons in neighbour tile based on portal defined by the segment.
int findConnectingPolys(const float* va, const float* vb, int findConnectingPolys(const float* va, const float* vb,
dtMeshTile* tile, int side, const dtMeshTile* tile, int side,
dtPolyRef* con, float* conarea, int maxcon); dtPolyRef* con, float* conarea, int maxcon) const;
// Builds internal polygons links for a tile. // Builds internal polygons links for a tile.
void connectIntLinks(dtMeshTile* tile); void connectIntLinks(dtMeshTile* tile);
@ -503,11 +504,11 @@ private:
void unconnectExtLinks(dtMeshTile* tile, int side); void unconnectExtLinks(dtMeshTile* tile, int side);
// Queries polygons within a tile. // Queries polygons within a tile.
int queryPolygonsInTile(dtMeshTile* tile, const float* qmin, const float* qmax, dtQueryFilter* filter, int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys); dtPolyRef* polys, const int maxPolys) const;
// Find nearest polygon within a tile. // Find nearest polygon within a tile.
dtPolyRef findNearestPolyInTile(dtMeshTile* tile, const float* center, const float* extents, dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents,
dtQueryFilter* filter, float* nearestPt); const dtQueryFilter* filter, float* nearestPt) const;
// Returns closest point on polygon. // Returns closest point on polygon.
bool closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip, const float* pos, float* closest) const; bool closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip, const float* pos, float* closest) const;

View File

@ -135,7 +135,7 @@ bool dtIntersectSegmentPoly2D(const float* p0, const float* p1,
else else
continue; continue;
} }
float t = n / d; const float t = n / d;
if (d < 0) if (d < 0)
{ {
// segment S is entering across this edge // segment S is entering across this edge

View File

@ -46,23 +46,75 @@ inline bool overlapRects(const float* amin, const float* amax,
return overlap; return overlap;
} }
static void calcRect(const float* va, const float* vb, inline bool overlapSlabs(const float* amin, const float* amax,
float* bmin, float* bmax, const float* bmin, const float* bmax,
int side, float padx, float pady) const float px, const float py)
{
// Check for horizontal overlap.
const float minx = dtMax(amin[0]-px,bmin[0]-px);
const float maxx = dtMin(amax[0]+px,bmax[0]+px);
if (minx > maxx)
return false;
// Check vertical overlap.
const float ad = (amax[1]-amin[1]) / (amax[0]-amin[0]);
const float ak = amin[1] - ad*amin[0];
const float bd = (bmax[1]-bmin[1]) / (bmax[0]-bmin[0]);
const float bk = bmin[1] - bd*bmin[0];
const float aminy = ad*minx + ak;
const float amaxy = ad*maxx + ak;
const float bminy = bd*minx + bk;
const float bmaxy = bd*maxx + bk;
const float dmin = bminy - aminy;
const float dmax = bmaxy - amaxy;
// Crossing segments always overlap.
if (dmin*dmax < 0)
return true;
// Check for overlap at endpoints.
const float thr = dtSqr(py*2);
if (dmin*dmin <= thr || dmax*dmax <= thr)
return true;
return false;
}
static void calcSlabEndPoints(const float* va, const float* vb, float* bmin, float* bmax, const int side)
{ {
if (side == 0 || side == 4) if (side == 0 || side == 4)
{ {
bmin[0] = dtMin(va[2],vb[2]) + padx; if (va[2] < vb[2])
bmin[1] = dtMin(va[1],vb[1]) - pady; {
bmax[0] = dtMax(va[2],vb[2]) - padx; bmin[0] = va[2];
bmax[1] = dtMax(va[1],vb[1]) + pady; bmin[1] = va[1];
bmax[0] = vb[2];
bmax[1] = vb[1];
}
else
{
bmin[0] = vb[2];
bmin[1] = vb[1];
bmax[0] = va[2];
bmax[1] = va[1];
}
} }
else if (side == 2 || side == 6) else if (side == 2 || side == 6)
{ {
bmin[0] = dtMin(va[0],vb[0]) + padx; if (va[0] < vb[0])
bmin[1] = dtMin(va[1],vb[1]) - pady; {
bmax[0] = dtMax(va[0],vb[0]) - padx; bmin[0] = va[0];
bmax[1] = dtMax(va[1],vb[1]) + pady; bmin[1] = va[1];
bmax[0] = vb[0];
bmax[1] = vb[1];
}
else
{
bmin[0] = vb[0];
bmin[1] = vb[1];
bmax[0] = va[0];
bmax[1] = va[1];
}
} }
} }
@ -90,7 +142,7 @@ inline void freeLink(dtMeshTile* tile, unsigned int link)
} }
inline bool passFilter(dtQueryFilter* filter, unsigned short flags) inline bool passFilter(const dtQueryFilter* filter, unsigned short flags)
{ {
return (flags & filter->includeFlags) != 0 && (flags & filter->excludeFlags) == 0; return (flags & filter->includeFlags) != 0 && (flags & filter->excludeFlags) == 0;
} }
@ -219,13 +271,13 @@ const dtNavMeshParams* dtNavMesh::getParams() const
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
int dtNavMesh::findConnectingPolys(const float* va, const float* vb, int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
dtMeshTile* tile, int side, const dtMeshTile* tile, int side,
dtPolyRef* con, float* conarea, int maxcon) dtPolyRef* con, float* conarea, int maxcon) const
{ {
if (!tile) return 0; if (!tile) return 0;
float amin[2], amax[2]; float amin[2], amax[2];
calcRect(va,vb, amin,amax, side, 0.01f, tile->header->walkableClimb); calcSlabEndPoints(va,vb, amin,amax, side);
// Remove links pointing to 'side' and compact the links array. // Remove links pointing to 'side' and compact the links array.
float bmin[2], bmax[2]; float bmin[2], bmax[2];
@ -245,8 +297,10 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
// Check if the segments touch. // Check if the segments touch.
const float* vc = &tile->verts[poly->verts[j]*3]; const float* vc = &tile->verts[poly->verts[j]*3];
const float* vd = &tile->verts[poly->verts[(j+1) % nv]*3]; const float* vd = &tile->verts[poly->verts[(j+1) % nv]*3];
calcRect(vc,vd, bmin,bmax, side, 0.01f, tile->header->walkableClimb); calcSlabEndPoints(vc,vd, bmin,bmax, side);
if (!overlapRects(amin,amax, bmin,bmax)) continue;
if (!overlapSlabs(amin,amax, bmin,bmax, 0.01f, tile->header->walkableClimb)) continue;
// Add return value. // Add return value.
if (n < maxcon) if (n < maxcon)
{ {
@ -642,7 +696,7 @@ dtTileRef dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, dtTil
return getTileRef(tile); return getTileRef(tile);
} }
dtMeshTile* dtNavMesh::getTileAt(int x, int y) dtMeshTile* dtNavMesh::getTileAt(int x, int y) const
{ {
// Find tile based on hash. // Find tile based on hash.
int h = computeTileHash(x,y,m_tileLutMask); int h = computeTileHash(x,y,m_tileLutMask);
@ -696,7 +750,7 @@ const dtMeshTile* dtNavMesh::getTileByPolyRef(dtPolyRef ref, int* polyIndex) con
return &m_tiles[it]; return &m_tiles[it];
} }
dtMeshTile* dtNavMesh::getNeighbourTileAt(int x, int y, int side) dtMeshTile* dtNavMesh::getNeighbourTileAt(int x, int y, int side) const
{ {
switch (side) switch (side)
{ {
@ -1090,7 +1144,8 @@ float dtNavMesh::getAreaCost(const int area) const
return -1; return -1;
} }
dtPolyRef dtNavMesh::findNearestPoly(const float* center, const float* extents, dtQueryFilter* filter, float* nearestPt) dtPolyRef dtNavMesh::findNearestPoly(const float* center, const float* extents,
const dtQueryFilter* filter, float* nearestPt) const
{ {
// Get nearby polygons from proximity grid. // Get nearby polygons from proximity grid.
dtPolyRef polys[128]; dtPolyRef polys[128];
@ -1118,8 +1173,8 @@ dtPolyRef dtNavMesh::findNearestPoly(const float* center, const float* extents,
return nearest; return nearest;
} }
dtPolyRef dtNavMesh::findNearestPolyInTile(dtMeshTile* tile, const float* center, const float* extents, dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents,
dtQueryFilter* filter, float* nearestPt) const dtQueryFilter* filter, float* nearestPt) const
{ {
float bmin[3], bmax[3]; float bmin[3], bmax[3];
dtVsub(bmin, center, extents); dtVsub(bmin, center, extents);
@ -1151,9 +1206,9 @@ dtPolyRef dtNavMesh::findNearestPolyInTile(dtMeshTile* tile, const float* center
return nearest; return nearest;
} }
int dtNavMesh::queryPolygonsInTile(dtMeshTile* tile, const float* qmin, const float* qmax, int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax,
dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys) dtPolyRef* polys, const int maxPolys) const
{ {
if (tile->bvTree) if (tile->bvTree)
{ {
@ -1239,8 +1294,8 @@ int dtNavMesh::queryPolygonsInTile(dtMeshTile* tile, const float* qmin, const fl
} }
} }
int dtNavMesh::queryPolygons(const float* center, const float* extents, dtQueryFilter* filter, int dtNavMesh::queryPolygons(const float* center, const float* extents, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys) dtPolyRef* polys, const int maxPolys) const
{ {
float bmin[3], bmax[3]; float bmin[3], bmax[3];
dtVsub(bmin, center, extents); dtVsub(bmin, center, extents);
@ -1257,7 +1312,7 @@ int dtNavMesh::queryPolygons(const float* center, const float* extents, dtQueryF
{ {
for (int x = minx; x <= maxx; ++x) for (int x = minx; x <= maxx; ++x)
{ {
dtMeshTile* tile = getTileAt(x,y); const dtMeshTile* tile = getTileAt(x,y);
if (!tile) continue; if (!tile) continue;
n += queryPolygonsInTile(tile, bmin, bmax, filter, polys+n, maxPolys-n); n += queryPolygonsInTile(tile, bmin, bmax, filter, polys+n, maxPolys-n);
if (n >= maxPolys) return n; if (n >= maxPolys) return n;
@ -1269,8 +1324,8 @@ int dtNavMesh::queryPolygons(const float* center, const float* extents, dtQueryF
int dtNavMesh::findPath(dtPolyRef startRef, dtPolyRef endRef, int dtNavMesh::findPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos, const float* startPos, const float* endPos,
dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* path, const int maxPathSize) dtPolyRef* path, const int maxPathSize) const
{ {
if (!startRef || !endRef) if (!startRef || !endRef)
return 0; return 0;
@ -1468,7 +1523,7 @@ int dtNavMesh::findPath(dtPolyRef startRef, dtPolyRef endRef,
int dtNavMesh::findStraightPath(const float* startPos, const float* endPos, int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
const dtPolyRef* path, const int pathSize, const dtPolyRef* path, const int pathSize,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
const int maxStraightPathSize) const int maxStraightPathSize) const
{ {
if (!maxStraightPathSize) if (!maxStraightPathSize)
return 0; return 0;
@ -1688,7 +1743,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
// Moves towards end position a long the path corridor. // Moves towards end position a long the path corridor.
// Returns: Index to the result path polygon. // Returns: Index to the result path polygon.
int dtNavMesh::moveAlongPathCorridor(const float* startPos, const float* endPos, float* resultPos, int dtNavMesh::moveAlongPathCorridor(const float* startPos, const float* endPos, float* resultPos,
const dtPolyRef* path, const int pathSize) const dtPolyRef* path, const int pathSize) const
{ {
if (!pathSize) if (!pathSize)
return 0; return 0;
@ -1966,8 +2021,8 @@ unsigned char dtNavMesh::getPolyArea(dtPolyRef ref) const
return poly->area; return poly->area;
} }
int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float* endPos, dtQueryFilter* filter, int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float* endPos, const dtQueryFilter* filter,
float& t, float* hitNormal, dtPolyRef* path, const int pathSize) float& t, float* hitNormal, dtPolyRef* path, const int pathSize) const
{ {
t = 0; t = 0;
@ -2121,9 +2176,9 @@ int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float*
return n; return n;
} }
int dtNavMesh::findPolysAround(dtPolyRef centerRef, const float* centerPos, float radius, dtQueryFilter* filter, int dtNavMesh::findPolysAround(dtPolyRef centerRef, const float* centerPos, float radius, const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
const int maxResult) const int maxResult) const
{ {
if (!centerRef) return 0; if (!centerRef) return 0;
if (!getPolyByRef(centerRef)) return 0; if (!getPolyByRef(centerRef)) return 0;
@ -2266,8 +2321,8 @@ int dtNavMesh::findPolysAround(dtPolyRef centerRef, const float* centerPos, floa
return n; return n;
} }
float dtNavMesh::findDistanceToWall(dtPolyRef centerRef, const float* centerPos, float maxRadius, dtQueryFilter* filter, float dtNavMesh::findDistanceToWall(dtPolyRef centerRef, const float* centerPos, float maxRadius, const dtQueryFilter* filter,
float* hitPos, float* hitNormal) float* hitPos, float* hitNormal) const
{ {
if (!centerRef) return 0; if (!centerRef) return 0;
if (!getPolyByRef(centerRef)) return 0; if (!getPolyByRef(centerRef)) return 0;