aboutsummaryrefslogtreecommitdiff
path: root/dep/recastnavigation/Detour/DetourNavMeshQuery.h
blob: f5046d8329000686b254c674ce98d5f11934a08f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
//
// 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).
	// Returns: True if succeed, else false.
	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.
	// 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 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.
	// Returns: Path query state.
	dtStatus updateSlicedFindPath(const int maxIter);

	// 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.
	// 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* segments, 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 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;
	
	// 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; }
	
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.
	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,
							 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