NavigationMesh.h 15 KB

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