recastnavigation_v1.6.0/Detour/Include/DetourNavMeshQuery.h

391 lines
20 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"
#include "DetourStatus.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.
/// @param ref [in] reference to the polygon test.
/// @param tile [in] pointer to the tile of the polygon test.
/// @param 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'.
/// @param pa [in] segment start position.
/// @param pb [in] segment end position.
/// @param prevRef, prevTile, prevPoly [in] data describing the previous polygon, can be null.
/// @param curRef, curTile, curPoly [in] data describing the current polygon.
/// @param 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
/// @name 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.
/// @param nav [in] pointer to navigation mesh data.
/// @param 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.
/// @param center[3] [in] The center of the search box.
/// @param extents[3] [in] The extents of the search box.
/// @param filter [in] path polygon filter.
/// @param nearestRef [out] Reference to the nearest polygon.
/// @param 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.
/// @param center[3] [in] the center of the search box.
/// @param extents[3] [in] the extents of the search box.
/// @param filter [in] path polygon filter.
/// @param polys [out] array holding the search result.
/// @param polyCount [out] Number of polygons in search result array.
/// @param 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.
/// @param startRef [in] ref to path start polygon.
/// @param endRef [in] ref to path end polygon.
/// @param startPos[3] [in] Path start location.
/// @param endPos[3] [in] Path end location.
/// @param filter [in] path polygon filter.
/// @param path [out] array holding the search result.
/// @param pathCount [out] Number of polygons in search result array.
/// @param 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().
/// @param startRef [in] ref to path start polygon.
/// @param endRef [in] ref to path end polygon.
/// @param startPos[3] [in] Path start location.
/// @param endPos[3] [in] Path end location.
/// @param 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.
/// @param maxIter [in] Max number of iterations to update.
/// @param 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.
/// @param path [out] array holding the search result.
/// @param pathCount [out] Number of polygons in search result array.
/// @param 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.
/// @param existing [out] Array of polygons in the existing path.
/// @param existingSize [out] Number of polygons in existing path array.
/// @param path [out] array holding the search result.
/// @param pathCount [out] Number of polygons in search result array.
/// @param 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.
/// @param startPos[3] [in] Path start location.
/// @param endPos[3] [in] Path end location.
/// @param path [in] Array of connected polygons describing the corridor.
/// @param pathSize [in] Number of polygons in path array.
/// @param straightPath [out] Points describing the straight path.
/// @param straightPathFlags [out, opt] Flags describing each point type, see dtStraightPathFlags.
/// @param straightPathRefs [out, opt] References to polygons at point locations.
/// @param straightPathCount [out] Number of points in the path.
/// @param 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.
/// @param startRef [in] ref to the polygon where startPos lies.
/// @param startPos[3] [in] start position of the mover.
/// @param endPos[3] [in] desired end position of the mover.
/// @param filter [in] path polygon filter.
/// @param resultPos[3] [out] new position of the mover.
/// @param visited [out] array of visited polygons.
/// @param visitedCount [out] Number of entries in the visited array.
/// @param 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.
/// @param startRef [in] ref to the polygon where the start lies.
/// @param startPos[3] [in] start position of the query.
/// @param endPos[3] [in] end position of the query.
/// @param t [out] hit parameter along the segment, FLT_MAX if no hit.
/// @param hitNormal[3] [out] normal of the nearest hit.
/// @param filter [in] path polygon filter.
/// @param path [out,opt] visited path polygons.
/// @param pathCount [out,opt] Number of polygons visited.
/// @param 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.
/// @param startRef [in] ref to the polygon where the center lies.
/// @param centerPos[3] [in] center if the query circle.
/// @param maxRadius [in] max search radius.
/// @param filter [in] path polygon filter.
/// @param hitDist [out] distance to nearest wall from the test location.
/// @param hitPos[3] [out] location of the nearest hit.
/// @param 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.
/// @param startRef [in] ref to the polygon where the search starts.
/// @param centerPos[3] [in] center if the query circle.
/// @param radius [in] radius of the query circle.
/// @param filter [in] path polygon filter.
/// @param resultRef [out, opt] refs to the polygons touched by the circle.
/// @param resultParent [out, opt] parent of each result polygon.
/// @param resultCost [out, opt] search cost at each result polygon.
/// @param resultCount [out, opt] Number of results.
/// @param 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.
/// @param startRef [in] ref to the polygon where the search starts.
/// @param verts[3*n] [in] vertices describing convex polygon shape (CCW).
/// @param nverts [in] number of vertices in the polygon.
/// @param filter [in] path polygon filter.
/// @param resultRef [out, opt] refs to the polygons touched by the circle.
/// @param resultParent [out, opt] parent of each result polygon.
/// @param resultCost [out, opt] search cost at each result polygon.
/// @param resultCount [out] number of results.
/// @param 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.
/// @param startRef [in] ref to the polygon where the search starts.
/// @param centerPos[3] [in] center if the query circle.
/// @param radius [in] radius of the query circle.
/// @param filter [in] path polygon filter.
/// @param resultRef [out] refs to the polygons touched by the circle.
/// @param resultParent [out, opt] parent of each result polygon.
/// @param resultCount [out] number of results.
/// @param 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.
/// @param ref [in] ref to the polygon.
/// @param filter [in] path polygon filter.
/// @param segmentVerts[6*maxSegments] [out] wall segments (2 endpoints per segment).
/// @param segmentRefs[maxSegments] [out,opt] reference to a neighbour.
/// @param segmentCount [out] number of wall segments.
/// @param 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.
/// @param ref [in] ref to the polygon.
/// @param pos[3] [in] the point to check.
/// @param 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.
/// @param ref [in] ref to the polygon.
/// @param pos[3] [in] the point to check.
/// @param 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.
/// @param ref [in] ref to the polygon.
/// @param pos[3] [in] the point where to locate the height.
/// @param height [out] height at the location.
/// @returns true if over polygon.
dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const;
// Returns true if polygon reference points to valid data and passes the filter.
bool isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) 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