404 lines
19 KiB
C++
404 lines
19 KiB
C++
//
|
|
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
//
|
|
|
|
#ifndef DETOURNAVMESHQUERY_H
|
|
#define DETOURNAVMESHQUERY_H
|
|
|
|
#include "DetourNavMesh.h"
|
|
|
|
|
|
// Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter.
|
|
// On certain platforms indirect or virtual function call is expensive. The default
|
|
// setting is to use non-virtual functions, the actualy implementations of the functions
|
|
// are declared as inline for maximum speed.
|
|
|
|
//#define DT_VIRTUAL_QUERYFILTER 1
|
|
|
|
// Class for polygon filtering and cost calculation during query operations.
|
|
// - It is possible to derive a custom query filter from dtQueryFilter by overriding
|
|
// the virtual functions passFilter() and getCost().
|
|
// - Both functions should be as fast as possible. Use cached local copy of data
|
|
// instead of accessing your own objects where possible.
|
|
// - You do not need to adhere to the flags and cost logic provided by the default
|
|
// implementation.
|
|
// - In order for the A* to work properly, the cost should be proportional to
|
|
// the travel distance. Using cost modifier less than 1.0 is likely to lead
|
|
// to problems during pathfinding.
|
|
class dtQueryFilter
|
|
{
|
|
float m_areaCost[DT_MAX_AREAS]; // Array storing cost per area type, used by default implementation.
|
|
unsigned short m_includeFlags; // Include poly flags, used by default implementation.
|
|
unsigned short m_excludeFlags; // Exclude poly flags, used by default implementation.
|
|
|
|
public:
|
|
dtQueryFilter();
|
|
|
|
// Returns true if the polygon is can visited.
|
|
// Params:
|
|
// ref - (in) reference to the polygon test.
|
|
// tile - (in) pointer to the tile of the polygon test.
|
|
// poly - (in) pointer to the polygon test.
|
|
#ifdef DT_VIRTUAL_QUERYFILTER
|
|
virtual bool passFilter(const dtPolyRef ref,
|
|
const dtMeshTile* tile,
|
|
const dtPoly* poly) const;
|
|
#else
|
|
bool passFilter(const dtPolyRef ref,
|
|
const dtMeshTile* tile,
|
|
const dtPoly* poly) const;
|
|
#endif
|
|
|
|
// Returns cost to travel from 'pa' to 'pb'.'
|
|
// The segment is fully contained inside 'cur'.
|
|
// 'pa' lies on the edge between 'prev' and 'cur',
|
|
// 'pb' lies on the edge between 'cur' and 'next'.
|
|
// Params:
|
|
// pa - (in) segment start position.
|
|
// pb - (in) segment end position.
|
|
// prevRef, prevTile, prevPoly - (in) data describing the previous polygon, can be null.
|
|
// curRef, curTile, curPoly - (in) data describing the current polygon.
|
|
// nextRef, nextTile, nextPoly - (in) data describing the next polygon, can be null.
|
|
#ifdef DT_VIRTUAL_QUERYFILTER
|
|
virtual float getCost(const float* pa, const float* pb,
|
|
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
|
|
const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly,
|
|
const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const;
|
|
#else
|
|
float getCost(const float* pa, const float* pb,
|
|
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
|
|
const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly,
|
|
const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const;
|
|
#endif
|
|
|
|
// Getters and setters for the default implementation data.
|
|
inline float getAreaCost(const int i) const { return m_areaCost[i]; }
|
|
inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; }
|
|
|
|
inline unsigned short getIncludeFlags() const { return m_includeFlags; }
|
|
inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; }
|
|
|
|
inline unsigned short getExcludeFlags() const { return m_excludeFlags; }
|
|
inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; }
|
|
};
|
|
|
|
class dtNavMeshQuery
|
|
{
|
|
public:
|
|
dtNavMeshQuery();
|
|
~dtNavMeshQuery();
|
|
|
|
// Initializes the nav mesh query.
|
|
// Params:
|
|
// nav - (in) pointer to navigation mesh data.
|
|
// maxNodes - (in) Maximum number of search nodes to use (max 65536).
|
|
dtStatus init(const dtNavMesh* nav, const int maxNodes);
|
|
|
|
// 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.
|
|
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 path from start polygon to end polygon.
|
|
// If target polygon canno be reached through the navigation graph,
|
|
// the last node on the array is nearest node to the end polygon.
|
|
// Start end end positions are needed to calculate more accurate
|
|
// traversal cost at start end end polygons.
|
|
// Params:
|
|
// startRef - (in) ref to path start polygon.
|
|
// endRef - (in) ref to path end polygon.
|
|
// startPos[3] - (in) Path start location.
|
|
// endPos[3] - (in) Path end location.
|
|
// filter - (in) path polygon filter.
|
|
// path - (out) array holding the search result.
|
|
// pathCount - (out) Number of polygons in search result array.
|
|
// maxPath - (in) The max number of polygons the path array can hold. Must be at least 1.
|
|
dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef,
|
|
const float* startPos, const float* endPos,
|
|
const dtQueryFilter* filter,
|
|
dtPolyRef* path, int* pathCount, const int maxPath) const;
|
|
|
|
// Intializes sliced path find query.
|
|
// Note 1: calling any other dtNavMeshQuery method before calling findPathEnd()
|
|
// may results in corrupted data!
|
|
// Note 2: The pointer to filter is store, and used in subsequent
|
|
// calls to updateSlicedFindPath().
|
|
// Params:
|
|
// startRef - (in) ref to path start polygon.
|
|
// endRef - (in) ref to path end polygon.
|
|
// startPos[3] - (in) Path start location.
|
|
// endPos[3] - (in) Path end location.
|
|
// filter - (in) path polygon filter.
|
|
dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef,
|
|
const float* startPos, const float* endPos,
|
|
const dtQueryFilter* filter);
|
|
|
|
// Updates sliced path find query.
|
|
// Params:
|
|
// maxIter - (in) Max number of iterations to update.
|
|
// doneIters - (out,opt) Number of iterations done during the update.
|
|
// Returns: Path query state.
|
|
dtStatus updateSlicedFindPath(const int maxIter, int* doneIters);
|
|
|
|
// Finalizes sliced path find query and returns found path.
|
|
// path - (out) array holding the search result.
|
|
// pathCount - (out) Number of polygons in search result array.
|
|
// maxPath - (in) The max number of polygons the path array can hold.
|
|
dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath);
|
|
|
|
// Finalizes partial sliced path find query and returns path to the furthest
|
|
// polygon on the existing path that was visited during the search.
|
|
// existing - (out) Array of polygons in the existing path.
|
|
// existingSize - (out) Number of polygons in existing path array.
|
|
// path - (out) array holding the search result.
|
|
// pathCount - (out) Number of polygons in search result array.
|
|
// maxPath - (in) The max number of polygons the path array can hold.
|
|
dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
|
|
dtPolyRef* path, int* pathCount, const int maxPath);
|
|
|
|
// 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 polygons found along the navigation graph which touch the specified circle.
|
|
// Params:
|
|
// startRef - (in) ref to the polygon where the search starts.
|
|
// centerPos[3] - (in) center if the query circle.
|
|
// radius - (in) radius of the query circle.
|
|
// filter - (in) path polygon filter.
|
|
// resultRef - (out, opt) refs to the polygons touched by the circle.
|
|
// resultParent - (out, opt) parent of each result polygon.
|
|
// resultCost - (out, opt) search cost at each result polygon.
|
|
// resultCount - (out, opt) Number of results.
|
|
// maxResult - (int) maximum capacity of search results.
|
|
dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius,
|
|
const dtQueryFilter* filter,
|
|
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
|
int* resultCount, const int maxResult) const;
|
|
|
|
// Finds polygons found along the navigation graph which touch the convex polygon shape.
|
|
// Params:
|
|
// startRef - (in) ref to the polygon where the search starts.
|
|
// verts[3*n] - (in) vertices describing convex polygon shape (CCW).
|
|
// nverts - (in) number of vertices in the polygon.
|
|
// filter - (in) path polygon filter.
|
|
// resultRef - (out, opt) refs to the polygons touched by the circle.
|
|
// resultParent - (out, opt) parent of each result polygon.
|
|
// resultCost - (out, opt) search cost at each result polygon.
|
|
// resultCount - (out) number of results.
|
|
// maxResult - (int) maximum capacity of search results.
|
|
dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts,
|
|
const dtQueryFilter* filter,
|
|
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
|
int* resultCount, const int maxResult) const;
|
|
|
|
// Finds non-overlapping local neighbourhood around center location.
|
|
// Note: The algorithm is optimized for small query radius and small number of polygons.
|
|
// Params:
|
|
// startRef - (in) ref to the polygon where the search starts.
|
|
// centerPos[3] - (in) center if the query circle.
|
|
// radius - (in) radius of the query circle.
|
|
// filter - (in) path polygon filter.
|
|
// resultRef - (out) refs to the polygons touched by the circle.
|
|
// resultParent - (out, opt) parent of each result polygon.
|
|
// resultCount - (out) number of results.
|
|
// maxResult - (int) maximum capacity of search results.
|
|
dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius,
|
|
const dtQueryFilter* filter,
|
|
dtPolyRef* resultRef, dtPolyRef* resultParent,
|
|
int* resultCount, const int maxResult) const;
|
|
|
|
// Returns wall segments of specified polygon.
|
|
// If 'segmentRefs' is specified, both the wall and portal segments are returned.
|
|
// Wall segments will have null (0) polyref, and portal segments store the polygon they lead to.
|
|
// Params:
|
|
// ref - (in) ref to the polygon.
|
|
// filter - (in) path polygon filter.
|
|
// segmentVerts[6*maxSegments] - (out) wall segments (2 endpoints per segment).
|
|
// segmentRefs[maxSegments] - (out,opt) reference to a neighbour.
|
|
// 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 closest point on navigation polygon.
|
|
// Uses detail polygons to find the closest point to the navigation polygon surface.
|
|
// Params:
|
|
// ref - (in) ref to the polygon.
|
|
// pos[3] - (in) the point to check.
|
|
// closest[3] - (out) closest point.
|
|
// Returns: true if closest point found.
|
|
dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const;
|
|
|
|
// Returns closest point on navigation polygon boundary.
|
|
// Uses the navigation polygon boundary to snap the point to poly boundary
|
|
// if it is outside the polygon. Much faster than closestPointToPoly. Does not affect height.
|
|
// Params:
|
|
// ref - (in) ref to the polygon.
|
|
// pos[3] - (in) the point to check.
|
|
// closest[3] - (out) closest point.
|
|
// Returns: true if closest point found.
|
|
dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const;
|
|
|
|
// Returns height of the polygon at specified location.
|
|
// Params:
|
|
// ref - (in) ref to the polygon.
|
|
// pos[3] - (in) the point where to locate the height.
|
|
// height - (out) height at the location.
|
|
// Returns: true if over polygon.
|
|
dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const;
|
|
|
|
// Returns true if poly reference ins in closed list.
|
|
bool isInClosedList(dtPolyRef ref) const;
|
|
|
|
class dtNodePool* getNodePool() const { return m_nodePool; }
|
|
|
|
const dtNavMesh* getAttachedNavMesh() const { return m_nav; }
|
|
|
|
private:
|
|
|
|
// Returns neighbour tile based on side.
|
|
dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
|
|
|
|
// Queries polygons within a tile.
|
|
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(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;
|
|
|
|
// Returns portal points between two polygons.
|
|
dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right,
|
|
unsigned char& fromType, unsigned char& toType) const;
|
|
dtStatus getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
|
|
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
|
|
float* left, float* right) const;
|
|
|
|
// Returns edge mid point between two polygons.
|
|
dtStatus getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const;
|
|
dtStatus getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
|
|
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
|
|
float* mid) const;
|
|
|
|
const dtNavMesh* m_nav; // Pointer to navmesh data.
|
|
|
|
struct dtQueryData
|
|
{
|
|
dtStatus status;
|
|
struct dtNode* lastBestNode;
|
|
float lastBestNodeCost;
|
|
dtPolyRef startRef, endRef;
|
|
float startPos[3], endPos[3];
|
|
const dtQueryFilter* filter;
|
|
};
|
|
dtQueryData m_query; // Sliced query state.
|
|
|
|
class dtNodePool* m_tinyNodePool; // Pointer to small node pool.
|
|
class dtNodePool* m_nodePool; // Pointer to node pool.
|
|
class dtNodeQueue* m_openList; // Pointer to open list queue.
|
|
};
|
|
|
|
// Helper function to allocate navmesh query class using Detour allocator.
|
|
dtNavMeshQuery* dtAllocNavMeshQuery();
|
|
void dtFreeNavMeshQuery(dtNavMeshQuery* query);
|
|
|
|
#endif // DETOURNAVMESHQUERY_H
|