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:
// x,y - (in) Location of the tile to get.
// 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.
// Params:
@ -269,7 +269,8 @@ public:
// filter - (in) path polygon filter.
// 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.
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.
// Params:
@ -279,8 +280,8 @@ public:
// polys - (out) array holding the search result.
// maxPolys - (in) The max number of polygons the polys array can hold.
// Returns: Number of polygons in search result array.
int queryPolygons(const float* center, const float* extents, dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys);
int queryPolygons(const float* center, const float* extents, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys) const;
// Finds path from start polygon to end polygon.
// If target polygon canno be reached through the navigation graph,
@ -298,8 +299,8 @@ public:
// Returns: Number of polygons in search result array.
int findPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos,
dtQueryFilter* filter,
dtPolyRef* path, const int maxPathSize);
const dtQueryFilter* filter,
dtPolyRef* path, const int maxPathSize) const;
// Finds a straight path from start to end locations within the corridor
// described by the path polygons.
@ -320,7 +321,7 @@ public:
int findStraightPath(const float* startPos, const float* endPos,
const dtPolyRef* path, const int pathSize,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
const int maxStraightPathSize);
const int maxStraightPathSize) const;
// 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.
@ -333,7 +334,7 @@ public:
// pathSize - (in) number of polygons on the path.
// Returns: Index to the path polygon where the result position lies.
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.
// Params:
@ -346,8 +347,8 @@ public:
// path - (out) visited path polygons.
// pathSize - (in) max number of polygons in the path array.
// Returns: Number of polygons visited or 0 if failed.
int raycast(dtPolyRef startRef, const float* startPos, const float* endPos, dtQueryFilter* filter,
float& t, float* hitNormal, dtPolyRef* path, const int pathSize);
int raycast(dtPolyRef startRef, const float* startPos, const float* endPos, const dtQueryFilter* filter,
float& t, float* hitNormal, dtPolyRef* path, const int pathSize) const;
// Returns distance to nearest wall from the specified location.
// Params:
@ -359,7 +360,7 @@ public:
// hitNormal[3] - (out) normal of the nearest hit.
// Returns: Distance to nearest wall from the test location.
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.
// Params:
@ -372,9 +373,9 @@ public:
// resultCost - (out, opt) search cost at each result polygon.
// maxResult - (int) maximum capacity of search 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,
const int maxResult);
const int maxResult) const;
// Returns closest point on navigation polygon.
// Uses detail polygons to find the closest point to the navigation polygon surface.
@ -483,11 +484,11 @@ public:
private:
// 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.
int findConnectingPolys(const float* va, const float* vb,
dtMeshTile* tile, int side,
dtPolyRef* con, float* conarea, int maxcon);
const dtMeshTile* tile, int side,
dtPolyRef* con, float* conarea, int maxcon) const;
// Builds internal polygons links for a tile.
void connectIntLinks(dtMeshTile* tile);
@ -503,11 +504,11 @@ private:
void unconnectExtLinks(dtMeshTile* tile, int side);
// Queries polygons within a tile.
int queryPolygonsInTile(dtMeshTile* tile, const float* qmin, const float* qmax, dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys);
int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys) const;
// Find nearest polygon within a tile.
dtPolyRef findNearestPolyInTile(dtMeshTile* tile, const float* center, const float* extents,
dtQueryFilter* filter, float* nearestPt);
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents,
const dtQueryFilter* filter, float* nearestPt) const;
// Returns closest point on polygon.
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
continue;
}
float t = n / d;
const float t = n / d;
if (d < 0)
{
// segment S is entering across this edge

View File

@ -46,23 +46,75 @@ inline bool overlapRects(const float* amin, const float* amax,
return overlap;
}
static void calcRect(const float* va, const float* vb,
float* bmin, float* bmax,
int side, float padx, float pady)
inline bool overlapSlabs(const float* amin, const float* amax,
const float* bmin, const float* bmax,
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)
{
bmin[0] = dtMin(va[2],vb[2]) + padx;
bmin[1] = dtMin(va[1],vb[1]) - pady;
bmax[0] = dtMax(va[2],vb[2]) - padx;
bmax[1] = dtMax(va[1],vb[1]) + pady;
if (va[2] < vb[2])
{
bmin[0] = va[2];
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)
{
bmin[0] = dtMin(va[0],vb[0]) + padx;
bmin[1] = dtMin(va[1],vb[1]) - pady;
bmax[0] = dtMax(va[0],vb[0]) - padx;
bmax[1] = dtMax(va[1],vb[1]) + pady;
if (va[0] < vb[0])
{
bmin[0] = va[0];
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;
}
@ -219,13 +271,13 @@ const dtNavMeshParams* dtNavMesh::getParams() const
//////////////////////////////////////////////////////////////////////////////////////////
int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
dtMeshTile* tile, int side,
dtPolyRef* con, float* conarea, int maxcon)
const dtMeshTile* tile, int side,
dtPolyRef* con, float* conarea, int maxcon) const
{
if (!tile) return 0;
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.
float bmin[2], bmax[2];
@ -245,8 +297,10 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
// Check if the segments touch.
const float* vc = &tile->verts[poly->verts[j]*3];
const float* vd = &tile->verts[poly->verts[(j+1) % nv]*3];
calcRect(vc,vd, bmin,bmax, side, 0.01f, tile->header->walkableClimb);
if (!overlapRects(amin,amax, bmin,bmax)) continue;
calcSlabEndPoints(vc,vd, bmin,bmax, side);
if (!overlapSlabs(amin,amax, bmin,bmax, 0.01f, tile->header->walkableClimb)) continue;
// Add return value.
if (n < maxcon)
{
@ -642,7 +696,7 @@ dtTileRef dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, dtTil
return getTileRef(tile);
}
dtMeshTile* dtNavMesh::getTileAt(int x, int y)
dtMeshTile* dtNavMesh::getTileAt(int x, int y) const
{
// Find tile based on hash.
int h = computeTileHash(x,y,m_tileLutMask);
@ -696,7 +750,7 @@ const dtMeshTile* dtNavMesh::getTileByPolyRef(dtPolyRef ref, int* polyIndex) con
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)
{
@ -1090,7 +1144,8 @@ float dtNavMesh::getAreaCost(const int area) const
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.
dtPolyRef polys[128];
@ -1118,8 +1173,8 @@ dtPolyRef dtNavMesh::findNearestPoly(const float* center, const float* extents,
return nearest;
}
dtPolyRef dtNavMesh::findNearestPolyInTile(dtMeshTile* tile, const float* center, const float* extents,
dtQueryFilter* filter, float* nearestPt)
dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents,
const dtQueryFilter* filter, float* nearestPt) const
{
float bmin[3], bmax[3];
dtVsub(bmin, center, extents);
@ -1151,9 +1206,9 @@ dtPolyRef dtNavMesh::findNearestPolyInTile(dtMeshTile* tile, const float* center
return nearest;
}
int dtNavMesh::queryPolygonsInTile(dtMeshTile* tile, const float* qmin, const float* qmax,
dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys)
int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax,
const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys) const
{
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,
dtPolyRef* polys, const int maxPolys)
int dtNavMesh::queryPolygons(const float* center, const float* extents, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys) const
{
float bmin[3], bmax[3];
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)
{
dtMeshTile* tile = getTileAt(x,y);
const dtMeshTile* tile = getTileAt(x,y);
if (!tile) continue;
n += queryPolygonsInTile(tile, bmin, bmax, filter, polys+n, maxPolys-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,
const float* startPos, const float* endPos,
dtQueryFilter* filter,
dtPolyRef* path, const int maxPathSize)
const dtQueryFilter* filter,
dtPolyRef* path, const int maxPathSize) const
{
if (!startRef || !endRef)
return 0;
@ -1468,7 +1523,7 @@ int dtNavMesh::findPath(dtPolyRef startRef, dtPolyRef endRef,
int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
const dtPolyRef* path, const int pathSize,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
const int maxStraightPathSize)
const int maxStraightPathSize) const
{
if (!maxStraightPathSize)
return 0;
@ -1688,7 +1743,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
// Moves towards end position a long the path corridor.
// Returns: Index to the result path polygon.
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)
return 0;
@ -1966,8 +2021,8 @@ unsigned char dtNavMesh::getPolyArea(dtPolyRef ref) const
return poly->area;
}
int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float* endPos, dtQueryFilter* filter,
float& t, float* hitNormal, dtPolyRef* path, const int pathSize)
int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float* endPos, const dtQueryFilter* filter,
float& t, float* hitNormal, dtPolyRef* path, const int pathSize) const
{
t = 0;
@ -2121,9 +2176,9 @@ int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float*
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,
const int maxResult)
const int maxResult) const
{
if (!centerRef) return 0;
if (!getPolyByRef(centerRef)) return 0;
@ -2266,8 +2321,8 @@ int dtNavMesh::findPolysAround(dtPolyRef centerRef, const float* centerPos, floa
return n;
}
float dtNavMesh::findDistanceToWall(dtPolyRef centerRef, const float* centerPos, float maxRadius, dtQueryFilter* filter,
float* hitPos, float* hitNormal)
float dtNavMesh::findDistanceToWall(dtPolyRef centerRef, const float* centerPos, float maxRadius, const dtQueryFilter* filter,
float* hitPos, float* hitNormal) const
{
if (!centerRef) return 0;
if (!getPolyByRef(centerRef)) return 0;