TDME2  1.9.200
PathFinding.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <stack>
4 #include <string>
5 #include <tuple>
6 #include <unordered_map>
7 #include <unordered_set>
8 #include <variant>
9 #include <vector>
10 
11 #include <tdme/tdme.h>
14 #include <tdme/engine/Transform.h>
15 #include <tdme/engine/fwd-tdme.h>
16 #include <tdme/math/Math.h>
17 #include <tdme/math/Vector3.h>
18 #include <tdme/utilities/Console.h>
19 #include <tdme/utilities/FlowMap.h>
22 #include <tdme/utilities/Pool.h>
23 
24 using std::get;
25 using std::map;
26 using std::stack;
27 using std::string;
28 using std::to_string;
29 using std::tuple;
30 using std::unordered_map;
31 using std::unordered_set;
32 using std::vector;
33 
38 using tdme::math::Math;
45 
46 /**
47  * Path finding class
48  * @author Andreas Drewke
49  */
51 {
52 public:
53  static constexpr bool VERBOSE { true };
54 
55  // forbid class copy
57 
58  /**
59  * Public constructor
60  * @param world world
61  * @param sloping sloping
62  * @param stepsMax steps max
63  * @param actorHeight actor height
64  * @param stepSize step size
65  * @param stepSizeLast step size last
66  * @param actorStepUpMax actor step up max
67  * @param skipOnCollisionTypeIds skip cells with given collision type ids
68  * @param maxTries max tries
69  * @param flowMapStepSize flow map step size
70  * @param flowMapScaleActorBoundingVolumes flow map scale actor bounding volumes
71  */
73  World* world,
74  bool sloping = false,
75  int stepsMax = 1000,
76  float actorHeight = 2.0f,
77  float stepSize = 0.5f,
78  float stepSizeLast = 0.75f,
79  float actorStepUpMax = 0.25f,
80  uint16_t skipOnCollisionTypeIds = 0,
81  int maxTries = 5,
82  float flowMapStepSize = 0.5f,
84  );
85 
86  /**
87  * Destructor
88  */
89  ~PathFinding();
90 
91  /**
92  * Set navigation map which allows fast look ups if Terrain::STEP_SIZE dimensioned cells are walkable
93  * @param navigationMap navigation map
94  */
96  this->navigationMap = navigationMap;
97  }
98 
99  /**
100  * @return step size
101  */
102  inline float getStepSize() {
103  return stepSize;
104  }
105 
106  /**
107  * Clear caches
108  */
109  inline void reset() {
110  walkableCache.clear();
111  walkableSlopeCache.clear();
112  }
113 
114  /**
115  * Return path finding node id of given x, y, z position components
116  * @param x x
117  * @param y y
118  * @param z z
119  * @return path finding node id of given x, y, z position components
120  */
121  inline const tuple<int, int, int> toId(float x, float y, float z) {
122  return toId(x, y, z, stepSize);
123  }
124 
125  /**
126  * Return path finding node id of given x, y, z position components
127  * @param x x
128  * @param y y
129  * @param z z
130  * @param stepSize step size
131  * @return path finding node id of given x, y, z position components
132  */
133  inline static const tuple<int, int, int> toId(float x, float y, float z, float stepSize) {
134  return tuple<int, int, int> {
135  static_cast<int>(Math::ceil(x / stepSize)),
136  static_cast<int>(Math::ceil(y / 0.1f)),
137  static_cast<int>(Math::ceil(z / stepSize))
138  };
139  }
140 
141  /**
142  * Align position component
143  * @param value value which is usually a position vector 3 position component
144  * @param stepSize step size
145  */
146  inline static float alignPositionComponent(float value, float stepSize) {
147  return Math::floor(value / stepSize) * stepSize;
148  }
149 
150  /**
151  * Align position component
152  * @param value value which is usually a position vector 3 position component
153  */
154  inline float alignPositionComponent(float value) {
155  return alignPositionComponent(value, stepSize);
156  }
157 
158  /**
159  * Returns integer position component
160  * @param value value
161  * @param stepSize step size
162  * @return integer position component
163  */
164  inline static int getIntegerPositionComponent(float value, float stepSize) {
165  return static_cast<int>(alignPositionComponent(value, stepSize) / stepSize);
166  }
167 
168  /**
169  * Returns integer position component
170  * @param value value
171  * @return integer position component
172  */
173  inline int getIntegerPositionComponent(float value) {
174  return getIntegerPositionComponent(value, stepSize);
175  }
176 
177  /**
178  * Return string representation of given x,z integer flow map position representation for path finding id
179  * @param x x
180  * @param y y
181  * @param z z
182  * @return string representation
183  */
184  inline static const tuple<int, int, int> toIdInt(int x, int y, int z) {
185  return tuple<int, int, int> {
186  x,
187  y,
188  z
189  };
190  }
191 
192  /**
193  * Finds path to given end position
194  * @param startPosition start position
195  * @param endPosition end position
196  * @param collisionTypeIds collision type ids
197  * @param path path from actor to target
198  * @param alternativeEndSteps alternative end steps
199  * @param maxTriesOverride max tries override or -1 for default
200  * @param customTest custom test
201  * @return success
202  */
203  inline bool findPath(const Vector3& startPosition, const Vector3& endPosition, const uint16_t collisionTypeIds, vector<Vector3>& path, int alternativeEndSteps = 0, int maxTriesOverride = -1, PathFindingCustomTest* customTest = nullptr) {
204  return findPathCustom(startPosition, endPosition, stepSize, 1.0f, collisionTypeIds, path, alternativeEndSteps, maxTriesOverride, customTest);
205  }
206 
207 
208  /**
209  * Finds path to given end position for flow maps
210  * @param startPosition start position
211  * @param endPosition end position
212  * @param collisionTypeIds collision type ids
213  * @param path path from actor to target
214  * @param alternativeEndSteps alternative end steps
215  * @param maxTriesOverride max tries override or -1 for default
216  * @param customTest custom test
217  * @return success
218  */
219  inline bool findFlowMapPath(const Vector3& startPosition, const Vector3& endPosition, const uint16_t collisionTypeIds, vector<Vector3>& path, int alternativeEndSteps = 0, int maxTriesOverride = -1, PathFindingCustomTest* customTest = nullptr) {
220  return findPathCustom(startPosition, endPosition, flowMapStepSize, flowMapScaleActorBoundingVolumes, collisionTypeIds, path, alternativeEndSteps, maxTriesOverride, customTest);
221  }
222 
223  /**
224  * Finds path to given end position
225  * @param startPosition start position
226  * @param endPosition end position
227  * @param stepSize step size
228  * @param scaleActorBoundingVolumes scale actor bounding volumes
229  * @param collisionTypeIds collision type ids
230  * @param path path from actor to target
231  * @param alternativeEndSteps alternative end steps
232  * @param maxTriesOverride max tries override or -1 for default
233  * @param customTest custom test
234  * @return success
235  */
236  bool findPathCustom(const Vector3& startPosition, const Vector3& endPosition, float stepSize, float scaleActorBoundingVolumes, const uint16_t collisionTypeIds, vector<Vector3>& path, int alternativeEndSteps = 0, int maxTriesOverride = -1, PathFindingCustomTest* customTest = nullptr);
237 
238  /**
239  * Checks if a cell is walkable
240  * @param x x
241  * @param y y
242  * @param z z
243  * @param height y stepped up
244  * @param stepSize step size
245  * @param scaleActorBoundingVolumes scale actor bounding volumes
246  * @param flowMapRequest flow map request
247  * @param collisionTypeIds collision type ids or 0 for default
248  * @param ignoreStepUpMax ignore step up max
249  * @return if cell is walkable
250  */
251  bool isWalkable(float x, float y, float z, float& height, float stepSize, float scaleActorBoundingVolumes, bool flowMapRequest, uint16_t collisionTypeIds = 0, bool ignoreStepUpMax = false);
252 
253  /**
254  * Create flow map
255  * @param endPositions end positions
256  * @param center flow map center
257  * @param depth flow map depth
258  * @param width flow map width
259  * @param collisionTypeIds collision type ids
260  * @param path path to test along
261  * @param complete complete
262  * @param customTest custom test
263  * @return flow map
264  */
265  FlowMap* createFlowMap(const vector<Vector3>& endPositions, const Vector3& center, float depth, float width, const uint16_t collisionTypeIds, const vector<Vector3>& path = vector<Vector3>(), bool complete = true, PathFindingCustomTest* customTest = nullptr);
266 
267  /**
268  * Generate direct path from start to end
269  * @param start start
270  * @param end end
271  * @return path nodes
272  */
273  const vector<Vector3> generateDirectPath(const Vector3& start, const Vector3& end);
274 private:
275  /**
276  * Path finding node
277  */
278  struct PathFindingNode final
279  {
280  /**
281  * Node id
282  */
283  tuple<int, int, int> id;
284 
285  /**
286  * Has previous node
287  */
289 
290  /**
291  * Previous node
292  */
293  tuple<int, int, int> previousNodeId;
294 
295  /**
296  * Position
297  */
299 
300  /**
301  * Estimated costs to the end plus calculated costs from start to this node
302  */
303  float costsAll;
304 
305  /**
306  * Calculated costs up to this point (from all previous nodes up to this node) to get to this coordinates from start
307  */
309 
310  /**
311  * Estimated costs to get to the end
312  */
314 
315  /**
316  * Integer position along x axis
317  */
318  int x;
319 
320  /**
321  * Integer position along y axis
322  */
323  int y;
324 
325  /**
326  * Integer position along z axis
327  */
328  int z;
329  };
330 
331  /**
332  * Path finding node pool
333  */
334  class PathFindingNodesPool: public Pool<PathFindingNode> {
335  public:
336  /**
337  * Public constructor
338  */
340  }
341 
342  protected:
343  /**
344  * Instantiate a path finding node
345  */
346  inline PathFindingNode* instantiate() override {
347  return new PathFindingNode();
348  }
349 
350  };
351 
353  std::size_t operator()(const tuple<int, int, int>& k) const {
354  std::hash<uint64_t> hashVal;
355  return hashVal(get<0>(k) ^ get<1>(k) ^ get<2>(k));
356  }
357  };
358 
360  std::size_t operator()(const tuple<uint8_t, uint8_t, int, int, int, uint16_t, bool>& k) const {
361  std::hash<uint64_t> hashVal;
362  return hashVal(static_cast<int>(get<0>(k)) ^ static_cast<int>(get<1>(k)) ^ get<2>(k) ^ get<3>(k) ^ get<4>(k) ^ static_cast<int>(get<5>(k)) ^ static_cast<int>(get<6>(k)));
363  }
364  };
365 
367  std::size_t operator()(const tuple<uint8_t, uint8_t, int, int, int, uint16_t, int16_t>& k) const {
368  std::hash<uint64_t> hashVal;
369  return hashVal(static_cast<int>(get<0>(k)) ^ static_cast<int>(get<1>(k)) ^ get<2>(k) ^ get<3>(k) ^ get<4>(k) ^ static_cast<int>(get<5>(k)) ^ static_cast<int>(get<6>(k)));
370  }
371  };
372 
373  /**
374  * Computes non square rooted distance between a and b
375  * @param a node a
376  * @param b node b
377  * @return non square rooted distance
378  */
379  inline float computeDistance(const PathFindingNode* a, const PathFindingNode* b) {
380  return a->position.clone().sub(b->position).computeLengthSquared();
381  }
382 
383  /**
384  * Computes minimal non square rooted distance between node and end point
385  * @param node node
386  * @return non square rooted distance
387  */
388  inline float computeDistanceToEnd(const PathFindingNode* node) {
390  }
391 
392  /**
393  * Returns if nodes are equals
394  * @param a a
395  * @param bX b x coordinate
396  * @param bY b y coordinate
397  * @param bZ b z coordinate
398  * @return if node a == node b
399  */
400  inline bool equals(const PathFindingNode* a, float bX, float bY, float bZ) {
401  return a->position.clone().sub(Vector3(bX, bY, bZ)).computeLengthSquared() < Math::square(0.1f);
402  }
403 
404  /**
405  * Returns if nodes are equals for (last node test)
406  * @param a a
407  * @param lastNode b
408  * @return if node a == node b
409  */
410  inline bool equalsLastNode(const PathFindingNode* a, const PathFindingNode* b) {
412  }
413 
414  /**
415  * Checks if a cell is walkable
416  * @param x x
417  * @param y y
418  * @param z z
419  * @param height y stepped up
420  * @param stepSize step size
421  * @param scaleActorBoundingVolumes scale actor bounding volumes
422  * @param flowMapRequest flow map request
423  * @param customTest custom test
424  * @param collisionTypeIds collision type ids or 0 for default
425  * @param ignoreStepUpMax ignore step up max
426  * @return if cell is walkable
427  */
428  bool isWalkableInternal(float x, float y, float z, float& height, float stepSize, float scaleActorBoundingVolumes, bool flowMapRequest, PathFindingCustomTest* customTest = nullptr, uint16_t collisionTypeIds = 0, bool ignoreStepUpMax = false);
429 
430  /**
431  * Checks if a cell is slope walkable
432  * @param x x
433  * @param y y
434  * @param z z
435  * @param successorX x
436  * @param successorY y
437  * @param successorZ z
438  * @param stepSize step size
439  * @param scaleActorBoundingVolumes scale actor bounding volumes
440  * @param customTest custom test
441  * @param collisionTypeIds collision type ids or 0 for default
442  * @return if cell is walkable
443  */
444  bool isSlopeWalkableInternal(float x, float y, float z, float successorX, float successorY, float successorZ, float stepSize, float scaleActorBoundingVolumes, bool flowMapRequest, PathFindingCustomTest* customTest = nullptr, uint16_t collisionTypeIds = 0);
445 
446  /**
447  * Processes one step in AStar path finding
448  * @param node node
449  * @param stepSize step size
450  * @param scaleActorBoundingVolumes scale actor bounding volumes
451  * @param nodesToTest nodes to test or nullptr, applies to flow cost map generation
452  * @param flowMapRequest flow map request
453  * @param customTest custom test
454  * @return step status
455  */
456  void step(PathFindingNode* node, float stepSize, float scaleActorBoundingVolumes, const unordered_set<tuple<int, int, int>, PathFindingNodeId_Hash>* nodesToTest, bool flowMapRequest, PathFindingCustomTest* customTest = nullptr);
457 
458  // properties
459  World* world { nullptr };
460  bool sloping;
461  int stepsMax;
462  float actorHeight;
463  float stepSize;
468  int maxTries;
472  unordered_map<tuple<int, int, int>, PathFindingNode*, PathFindingNodeId_Hash> openNodes;
473  unordered_map<tuple<int, int, int>, PathFindingNode*, PathFindingNodeId_Hash> closedNodes;
475  unordered_map<tuple<uint8_t, uint8_t, int, int, int, uint16_t, bool>, float, WalkableCache_Hash> walkableCache;
476  unordered_map<tuple<uint8_t, uint8_t, int, int, int, uint16_t, int16_t>, float, WalkableSlopeCache_Hash> walkableSlopeCache;
477  Texture* navigationMap { nullptr };
478 };
Texture entity.
Definition: Texture.h:24
Transform which contain scale, rotations and translation.
Definition: Transform.h:29
Dynamic physics world class.
Definition: World.h:38
Standard math functions.
Definition: Math.h:19
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
Vector3 & setY(float y)
Sets y component.
Definition: Vector3.h:126
float computeLengthSquared() const
Definition: Vector3.h:281
Vector3 clone() const
Clones this vector3.
Definition: Vector3.h:374
Vector3 & sub(float scalar)
Subtracts a scalar.
Definition: Vector3.h:177
Console class.
Definition: Console.h:29
PathFindingNode * instantiate() override
Instantiate a path finding node.
Definition: PathFinding.h:346
Path finding class.
Definition: PathFinding.h:51
unordered_map< tuple< uint8_t, uint8_t, int, int, int, uint16_t, bool >, float, WalkableCache_Hash > walkableCache
Definition: PathFinding.h:475
PathFindingNodesPool pathFindingNodesPool
Definition: PathFinding.h:474
unordered_map< tuple< int, int, int >, PathFindingNode *, PathFindingNodeId_Hash > closedNodes
Definition: PathFinding.h:473
const vector< Vector3 > generateDirectPath(const Vector3 &start, const Vector3 &end)
Generate direct path from start to end.
FlowMap * createFlowMap(const vector< Vector3 > &endPositions, const Vector3 &center, float depth, float width, const uint16_t collisionTypeIds, const vector< Vector3 > &path=vector< Vector3 >(), bool complete=true, PathFindingCustomTest *customTest=nullptr)
Create flow map.
bool isWalkable(float x, float y, float z, float &height, float stepSize, float scaleActorBoundingVolumes, bool flowMapRequest, uint16_t collisionTypeIds=0, bool ignoreStepUpMax=false)
Checks if a cell is walkable.
bool findFlowMapPath(const Vector3 &startPosition, const Vector3 &endPosition, const uint16_t collisionTypeIds, vector< Vector3 > &path, int alternativeEndSteps=0, int maxTriesOverride=-1, PathFindingCustomTest *customTest=nullptr)
Finds path to given end position for flow maps.
Definition: PathFinding.h:219
bool equalsLastNode(const PathFindingNode *a, const PathFindingNode *b)
Returns if nodes are equals for (last node test)
Definition: PathFinding.h:410
static const tuple< int, int, int > toId(float x, float y, float z, float stepSize)
Return path finding node id of given x, y, z position components.
Definition: PathFinding.h:133
PathFinding(World *world, bool sloping=false, int stepsMax=1000, float actorHeight=2.0f, float stepSize=0.5f, float stepSizeLast=0.75f, float actorStepUpMax=0.25f, uint16_t skipOnCollisionTypeIds=0, int maxTries=5, float flowMapStepSize=0.5f, float flowMapScaleActorBoundingVolumes=1.0f)
Public constructor.
Definition: PathFinding.cpp:56
static const tuple< int, int, int > toIdInt(int x, int y, int z)
Return string representation of given x,z integer flow map position representation for path finding i...
Definition: PathFinding.h:184
bool isSlopeWalkableInternal(float x, float y, float z, float successorX, float successorY, float successorZ, float stepSize, float scaleActorBoundingVolumes, bool flowMapRequest, PathFindingCustomTest *customTest=nullptr, uint16_t collisionTypeIds=0)
Checks if a cell is slope walkable.
float computeDistance(const PathFindingNode *a, const PathFindingNode *b)
Computes non square rooted distance between a and b.
Definition: PathFinding.h:379
float computeDistanceToEnd(const PathFindingNode *node)
Computes minimal non square rooted distance between node and end point.
Definition: PathFinding.h:388
void setNavigationMap(Texture *navigationMap)
Set navigation map which allows fast look ups if Terrain::STEP_SIZE dimensioned cells are walkable.
Definition: PathFinding.h:95
bool equals(const PathFindingNode *a, float bX, float bY, float bZ)
Returns if nodes are equals.
Definition: PathFinding.h:400
static constexpr bool VERBOSE
Definition: PathFinding.h:53
bool findPath(const Vector3 &startPosition, const Vector3 &endPosition, const uint16_t collisionTypeIds, vector< Vector3 > &path, int alternativeEndSteps=0, int maxTriesOverride=-1, PathFindingCustomTest *customTest=nullptr)
Finds path to given end position.
Definition: PathFinding.h:203
static int getIntegerPositionComponent(float value, float stepSize)
Returns integer position component.
Definition: PathFinding.h:164
bool findPathCustom(const Vector3 &startPosition, const Vector3 &endPosition, float stepSize, float scaleActorBoundingVolumes, const uint16_t collisionTypeIds, vector< Vector3 > &path, int alternativeEndSteps=0, int maxTriesOverride=-1, PathFindingCustomTest *customTest=nullptr)
Finds path to given end position.
const tuple< int, int, int > toId(float x, float y, float z)
Return path finding node id of given x, y, z position components.
Definition: PathFinding.h:121
void reset()
Clear caches.
Definition: PathFinding.h:109
float alignPositionComponent(float value)
Align position component.
Definition: PathFinding.h:154
unordered_map< tuple< uint8_t, uint8_t, int, int, int, uint16_t, int16_t >, float, WalkableSlopeCache_Hash > walkableSlopeCache
Definition: PathFinding.h:476
bool isWalkableInternal(float x, float y, float z, float &height, float stepSize, float scaleActorBoundingVolumes, bool flowMapRequest, PathFindingCustomTest *customTest=nullptr, uint16_t collisionTypeIds=0, bool ignoreStepUpMax=false)
Checks if a cell is walkable.
Definition: PathFinding.cpp:87
int getIntegerPositionComponent(float value)
Returns integer position component.
Definition: PathFinding.h:173
static float alignPositionComponent(float value, float stepSize)
Align position component.
Definition: PathFinding.h:146
unordered_map< tuple< int, int, int >, PathFindingNode *, PathFindingNodeId_Hash > openNodes
Definition: PathFinding.h:472
void step(PathFindingNode *node, float stepSize, float scaleActorBoundingVolumes, const unordered_set< tuple< int, int, int >, PathFindingNodeId_Hash > *nodesToTest, bool flowMapRequest, PathFindingCustomTest *customTest=nullptr)
Processes one step in AStar path finding.
Pool template class.
Definition: Pool.h:20
Path finding custom test interface.
std::size_t operator()(const tuple< int, int, int > &k) const
Definition: PathFinding.h:353
int y
Integer position along y axis.
Definition: PathFinding.h:323
int z
Integer position along z axis.
Definition: PathFinding.h:328
tuple< int, int, int > id
Node id.
Definition: PathFinding.h:283
int x
Integer position along x axis.
Definition: PathFinding.h:318
tuple< int, int, int > previousNodeId
Previous node.
Definition: PathFinding.h:293
float costsAll
Estimated costs to the end plus calculated costs from start to this node.
Definition: PathFinding.h:303
float costsEstimated
Estimated costs to get to the end.
Definition: PathFinding.h:313
float costsReachPoint
Calculated costs up to this point (from all previous nodes up to this node) to get to this coordinate...
Definition: PathFinding.h:308
std::size_t operator()(const tuple< uint8_t, uint8_t, int, int, int, uint16_t, bool > &k) const
Definition: PathFinding.h:360
std::size_t operator()(const tuple< uint8_t, uint8_t, int, int, int, uint16_t, int16_t > &k) const
Definition: PathFinding.h:367
#define FORBID_CLASS_COPY(CLASS)
Definition: tdme.h:6