NavigationMesh.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. /// \file
  4. #pragma once
  5. #include "../Container/ArrayPtr.h"
  6. #include "../Container/HashSet.h"
  7. #include "../Math/BoundingBox.h"
  8. #include "../Math/Matrix3x4.h"
  9. #include "../Scene/Component.h"
  10. #include <memory>
  11. #ifdef DT_POLYREF64
  12. using dtPolyRef = uint64_t;
  13. #else
  14. using dtPolyRef = unsigned int;
  15. #endif
  16. class dtNavMesh;
  17. class dtNavMeshQuery;
  18. class dtQueryFilter;
  19. namespace Urho3D
  20. {
  21. enum NavmeshPartitionType
  22. {
  23. NAVMESH_PARTITION_WATERSHED = 0,
  24. NAVMESH_PARTITION_MONOTONE
  25. };
  26. class Geometry;
  27. class NavArea;
  28. struct FindPathData;
  29. struct NavBuildData;
  30. /// Description of a navigation mesh geometry component, with transform and bounds information.
  31. struct NavigationGeometryInfo
  32. {
  33. /// Component.
  34. Component* component_;
  35. /// Geometry LOD level if applicable.
  36. i32 lodLevel_;
  37. /// Transform relative to the navigation mesh root node.
  38. Matrix3x4 transform_;
  39. /// Bounding box relative to the navigation mesh root node.
  40. BoundingBox boundingBox_;
  41. };
  42. /// A flag representing the type of path point- none, the start of a path segment, the end of one, or an off-mesh connection.
  43. enum NavigationPathPointFlag
  44. {
  45. NAVPATHFLAG_NONE = 0,
  46. NAVPATHFLAG_START = 0x01,
  47. NAVPATHFLAG_END = 0x02,
  48. NAVPATHFLAG_OFF_MESH = 0x04
  49. };
  50. struct URHO3D_API NavigationPathPoint
  51. {
  52. /// World-space position of the path point.
  53. Vector3 position_;
  54. /// Detour flag.
  55. NavigationPathPointFlag flag_;
  56. /// Detour area ID.
  57. unsigned char areaID_;
  58. };
  59. /// Navigation mesh component. Collects the navigation geometry from child nodes with the Navigable component and responds to path queries.
  60. class URHO3D_API NavigationMesh : public Component
  61. {
  62. URHO3D_OBJECT(NavigationMesh, Component);
  63. friend class CrowdManager;
  64. public:
  65. /// Construct.
  66. explicit NavigationMesh(Context* context);
  67. /// Destruct.
  68. ~NavigationMesh() override;
  69. /// Register object factory.
  70. /// @nobind
  71. static void RegisterObject(Context* context);
  72. /// Visualize the component as debug geometry.
  73. void DrawDebugGeometry(DebugRenderer* debug, bool depthTest) override;
  74. /// Set tile size.
  75. /// @property
  76. void SetTileSize(int size);
  77. /// Set cell size.
  78. /// @property
  79. void SetCellSize(float size);
  80. /// Set cell height.
  81. /// @property
  82. void SetCellHeight(float height);
  83. /// Set navigation agent height.
  84. /// @property
  85. void SetAgentHeight(float height);
  86. /// Set navigation agent radius.
  87. /// @property
  88. void SetAgentRadius(float radius);
  89. /// Set navigation agent max vertical climb.
  90. /// @property
  91. void SetAgentMaxClimb(float maxClimb);
  92. /// Set navigation agent max slope.
  93. /// @property
  94. void SetAgentMaxSlope(float maxSlope);
  95. /// Set region minimum size.
  96. /// @property
  97. void SetRegionMinSize(float size);
  98. /// Set region merge size.
  99. /// @property
  100. void SetRegionMergeSize(float size);
  101. /// Set edge max length.
  102. /// @property
  103. void SetEdgeMaxLength(float length);
  104. /// Set edge max error.
  105. /// @property
  106. void SetEdgeMaxError(float error);
  107. /// Set detail sampling distance.
  108. /// @property
  109. void SetDetailSampleDistance(float distance);
  110. /// Set detail sampling maximum error.
  111. /// @property
  112. void SetDetailSampleMaxError(float error);
  113. /// Set padding of the navigation mesh bounding box. Having enough padding allows to add geometry on the extremities of the navigation mesh when doing partial rebuilds.
  114. /// @property
  115. void SetPadding(const Vector3& padding);
  116. /// Set the cost of an area.
  117. void SetAreaCost(unsigned areaID, float cost);
  118. /// Allocate the navigation mesh without building any tiles. Bounding box is not padded. Return true if successful.
  119. virtual bool Allocate(const BoundingBox& boundingBox, unsigned maxTiles);
  120. /// Rebuild the navigation mesh. Return true if successful.
  121. virtual bool Build();
  122. /// Rebuild part of the navigation mesh contained by the world-space bounding box. Return true if successful.
  123. virtual bool Build(const BoundingBox& boundingBox);
  124. /// Rebuild part of the navigation mesh in the rectangular area. Return true if successful.
  125. virtual bool Build(const IntVector2& from, const IntVector2& to);
  126. /// Return tile data.
  127. /// @manualbind
  128. virtual Vector<byte> GetTileData(const IntVector2& tile) const;
  129. /// Add tile to navigation mesh.
  130. virtual bool AddTile(const Vector<byte>& tileData);
  131. /// Remove tile from navigation mesh.
  132. virtual void RemoveTile(const IntVector2& tile);
  133. /// Remove all tiles from navigation mesh.
  134. virtual void RemoveAllTiles();
  135. /// Return whether the navigation mesh has tile.
  136. bool HasTile(const IntVector2& tile) const;
  137. /// Return bounding box of the tile in the node space.
  138. BoundingBox GetTileBoundingBox(const IntVector2& tile) const;
  139. /// Return index of the tile at the position.
  140. IntVector2 GetTileIndex(const Vector3& position) const;
  141. /// Find the nearest point on the navigation mesh to a given point. Extents specifies how far out from the specified point to check along each axis.
  142. Vector3 FindNearestPoint
  143. (const Vector3& point, const Vector3& extents = Vector3::ONE, const dtQueryFilter* filter = nullptr, dtPolyRef* nearestRef = nullptr);
  144. /// Try to move along the surface from one point to another.
  145. Vector3 MoveAlongSurface(const Vector3& start, const Vector3& end, const Vector3& extents = Vector3::ONE, int maxVisited = 3,
  146. const dtQueryFilter* filter = nullptr);
  147. /// Find a path between world space points. Return non-empty list of points if successful. Extents specifies how far off the navigation mesh the points can be.
  148. void FindPath(Vector<Vector3>& dest, const Vector3& start, const Vector3& end, const Vector3& extents = Vector3::ONE,
  149. const dtQueryFilter* filter = nullptr);
  150. /// Find a path between world space points. Return non-empty list of navigation path points if successful. Extents specifies how far off the navigation mesh the points can be.
  151. void FindPath
  152. (Vector<NavigationPathPoint>& dest, const Vector3& start, const Vector3& end, const Vector3& extents = Vector3::ONE,
  153. const dtQueryFilter* filter = nullptr);
  154. /// Return a random point on the navigation mesh.
  155. Vector3 GetRandomPoint(const dtQueryFilter* filter = nullptr, dtPolyRef* randomRef = nullptr);
  156. /// Return a random point on the navigation mesh within a circle. The circle radius is only a guideline and in practice the returned point may be further away.
  157. Vector3 GetRandomPointInCircle
  158. (const Vector3& center, float radius, const Vector3& extents = Vector3::ONE, const dtQueryFilter* filter = nullptr,
  159. dtPolyRef* randomRef = nullptr);
  160. /// Return distance to wall from a point. Maximum search radius must be specified.
  161. float GetDistanceToWall
  162. (const Vector3& point, float radius, const Vector3& extents = Vector3::ONE, const dtQueryFilter* filter = nullptr,
  163. Vector3* hitPos = nullptr, Vector3* hitNormal = nullptr);
  164. /// Perform a walkability raycast on the navigation mesh between start and end and return the point where a wall was hit, or the end point if no walls.
  165. Vector3 Raycast
  166. (const Vector3& start, const Vector3& end, const Vector3& extents = Vector3::ONE, const dtQueryFilter* filter = nullptr,
  167. Vector3* hitNormal = nullptr);
  168. /// Add debug geometry to the debug renderer.
  169. void DrawDebugGeometry(bool depthTest);
  170. /// Return the given name of this navigation mesh.
  171. String GetMeshName() const { return meshName_; }
  172. /// Set the name of this navigation mesh.
  173. void SetMeshName(const String& newName);
  174. /// Return tile size.
  175. /// @property
  176. int GetTileSize() const { return tileSize_; }
  177. /// Return cell size.
  178. /// @property
  179. float GetCellSize() const { return cellSize_; }
  180. /// Return cell height.
  181. /// @property
  182. float GetCellHeight() const { return cellHeight_; }
  183. /// Return navigation agent height.
  184. /// @property
  185. float GetAgentHeight() const { return agentHeight_; }
  186. /// Return navigation agent radius.
  187. /// @property
  188. float GetAgentRadius() const { return agentRadius_; }
  189. /// Return navigation agent max vertical climb.
  190. /// @property
  191. float GetAgentMaxClimb() const { return agentMaxClimb_; }
  192. /// Return navigation agent max slope.
  193. /// @property
  194. float GetAgentMaxSlope() const { return agentMaxSlope_; }
  195. /// Return region minimum size.
  196. /// @property
  197. float GetRegionMinSize() const { return regionMinSize_; }
  198. /// Return region merge size.
  199. /// @property
  200. float GetRegionMergeSize() const { return regionMergeSize_; }
  201. /// Return edge max length.
  202. /// @property
  203. float GetEdgeMaxLength() const { return edgeMaxLength_; }
  204. /// Return edge max error.
  205. /// @property
  206. float GetEdgeMaxError() const { return edgeMaxError_; }
  207. /// Return detail sampling distance.
  208. /// @property
  209. float GetDetailSampleDistance() const { return detailSampleDistance_; }
  210. /// Return detail sampling maximum error.
  211. /// @property
  212. float GetDetailSampleMaxError() const { return detailSampleMaxError_; }
  213. /// Return navigation mesh bounding box padding.
  214. /// @property
  215. const Vector3& GetPadding() const { return padding_; }
  216. /// Get the current cost of an area.
  217. float GetAreaCost(unsigned areaID) const;
  218. /// Return whether has been initialized with valid navigation data.
  219. /// @property
  220. bool IsInitialized() const { return navMesh_ != nullptr; }
  221. /// Return local space bounding box of the navigation mesh.
  222. /// @property
  223. const BoundingBox& GetBoundingBox() const { return boundingBox_; }
  224. /// Return world space bounding box of the navigation mesh.
  225. /// @property
  226. BoundingBox GetWorldBoundingBox() const;
  227. /// Return number of tiles.
  228. /// @property
  229. IntVector2 GetNumTiles() const { return IntVector2(numTilesX_, numTilesZ_); }
  230. /// Set the partition type used for polygon generation.
  231. /// @property
  232. void SetPartitionType(NavmeshPartitionType partitionType);
  233. /// Return Partition Type.
  234. /// @property
  235. NavmeshPartitionType GetPartitionType() const { return partitionType_; }
  236. /// Set navigation data attribute.
  237. virtual void SetNavigationDataAttr(const Vector<byte>& value);
  238. /// Return navigation data attribute.
  239. virtual Vector<byte> GetNavigationDataAttr() const;
  240. /// Draw debug geometry for OffMeshConnection components.
  241. /// @property
  242. void SetDrawOffMeshConnections(bool enable) { drawOffMeshConnections_ = enable; }
  243. /// Return whether to draw OffMeshConnection components.
  244. /// @property
  245. bool GetDrawOffMeshConnections() const { return drawOffMeshConnections_; }
  246. /// Draw debug geometry for NavArea components.
  247. /// @property
  248. void SetDrawNavAreas(bool enable) { drawNavAreas_ = enable; }
  249. /// Return whether to draw NavArea components.
  250. /// @property
  251. bool GetDrawNavAreas() const { return drawNavAreas_; }
  252. private:
  253. /// Write tile data.
  254. void WriteTile(Serializer& dest, int x, int z) const;
  255. /// Read tile data to the navigation mesh.
  256. bool ReadTile(Deserializer& source, bool silent);
  257. protected:
  258. /// Collect geometry from under Navigable components.
  259. void CollectGeometries(Vector<NavigationGeometryInfo>& geometryList);
  260. /// Visit nodes and collect navigable geometry.
  261. void CollectGeometries(Vector<NavigationGeometryInfo>& geometryList, Node* node, HashSet<Node*>& processedNodes, bool recursive);
  262. /// Get geometry data within a bounding box.
  263. void GetTileGeometry(NavBuildData* build, Vector<NavigationGeometryInfo>& geometryList, BoundingBox& box);
  264. /// Add a triangle mesh to the geometry data.
  265. void AddTriMeshGeometry(NavBuildData* build, Geometry* geometry, const Matrix3x4& transform);
  266. /// Build one tile of the navigation mesh. Return true if successful.
  267. virtual bool BuildTile(Vector<NavigationGeometryInfo>& geometryList, int x, int z);
  268. /// Build tiles in the rectangular area. Return number of built tiles.
  269. unsigned BuildTiles(Vector<NavigationGeometryInfo>& geometryList, const IntVector2& from, const IntVector2& to);
  270. /// Ensure that the navigation mesh query is initialized. Return true if successful.
  271. bool InitializeQuery();
  272. /// Release the navigation mesh and the query.
  273. virtual void ReleaseNavigationMesh();
  274. /// Identifying name for this navigation mesh.
  275. String meshName_;
  276. /// Detour navigation mesh.
  277. dtNavMesh* navMesh_;
  278. /// Detour navigation mesh query.
  279. dtNavMeshQuery* navMeshQuery_;
  280. /// Detour navigation mesh query filter.
  281. std::unique_ptr<dtQueryFilter> queryFilter_;
  282. /// Temporary data for finding a path.
  283. std::unique_ptr<FindPathData> pathData_;
  284. /// Tile size.
  285. int tileSize_;
  286. /// Cell size.
  287. float cellSize_;
  288. /// Cell height.
  289. float cellHeight_;
  290. /// Navigation agent height.
  291. float agentHeight_;
  292. /// Navigation agent radius.
  293. float agentRadius_;
  294. /// Navigation agent max vertical climb.
  295. float agentMaxClimb_;
  296. /// Navigation agent max slope.
  297. float agentMaxSlope_;
  298. /// Region minimum size.
  299. float regionMinSize_;
  300. /// Region merge size.
  301. float regionMergeSize_;
  302. /// Edge max length.
  303. float edgeMaxLength_;
  304. /// Edge max error.
  305. float edgeMaxError_;
  306. /// Detail sampling distance.
  307. float detailSampleDistance_;
  308. /// Detail sampling maximum error.
  309. float detailSampleMaxError_;
  310. /// Bounding box padding.
  311. Vector3 padding_;
  312. /// Number of tiles in X direction.
  313. int numTilesX_;
  314. /// Number of tiles in Z direction.
  315. int numTilesZ_;
  316. /// Whole navigation mesh bounding box.
  317. BoundingBox boundingBox_;
  318. /// Type of the heightfield partitioning.
  319. NavmeshPartitionType partitionType_;
  320. /// Keep internal build resources for debug draw modes.
  321. bool keepInterResults_;
  322. /// Debug draw OffMeshConnection components.
  323. bool drawOffMeshConnections_;
  324. /// Debug draw NavArea components.
  325. bool drawNavAreas_;
  326. /// NavAreas for this NavMesh.
  327. Vector<WeakPtr<NavArea>> areas_;
  328. };
  329. /// Register Navigation library objects.
  330. /// @nobind
  331. void URHO3D_API RegisterNavigationLibrary(Context* context);
  332. }