RecastNavigationPhysXProviderComponentController.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <AzCore/Component/Component.h>
  10. #include <AzCore/Task/TaskExecutor.h>
  11. #include <AzCore/Task/TaskGraph.h>
  12. #include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
  13. #include <RecastNavigation/RecastHelpers.h>
  14. #include <Misc/RecastNavigationPhysXProviderConfig.h>
  15. #include <RecastNavigation/RecastNavigationProviderBus.h>
  16. namespace RecastNavigation
  17. {
  18. //! Common logic for Recast navigation tiled collector components. Recommended use is as a base class.
  19. //! The method provided are not thread-safe. Synchronize as necessary at the higher level.
  20. class RecastNavigationPhysXProviderComponentController
  21. : public RecastNavigationProviderRequestBus::Handler
  22. {
  23. friend class EditorRecastNavigationPhysXProviderComponent;
  24. public:
  25. AZ_CLASS_ALLOCATOR(RecastNavigationPhysXProviderComponentController, AZ::SystemAllocator);
  26. AZ_RTTI(RecastNavigationPhysXProviderComponentController, "{182D93F8-9E76-409B-9939-6816509A6F52}");
  27. RecastNavigationPhysXProviderComponentController();
  28. explicit RecastNavigationPhysXProviderComponentController(const RecastNavigationPhysXProviderConfig& config);
  29. ~RecastNavigationPhysXProviderComponentController() override = default;
  30. static void Reflect(AZ::ReflectContext* context);
  31. void Activate(const AZ::EntityComponentIdPair& entityComponentIdPair);
  32. void Deactivate();
  33. void SetConfiguration(const RecastNavigationPhysXProviderConfig& config);
  34. const RecastNavigationPhysXProviderConfig& GetConfiguration() const;
  35. static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
  36. static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
  37. static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
  38. //! RecastNavigationProviderRequestBus overrides ...
  39. //! @{
  40. AZStd::vector<AZStd::shared_ptr<TileGeometry>> CollectGeometry(float tileSize, float borderSize) override;
  41. bool CollectGeometryAsync(float tileSize, float borderSize, AZStd::function<void(AZStd::shared_ptr<TileGeometry>)> tileCallback) override;
  42. AZ::Aabb GetWorldBounds() const override;
  43. int GetNumberOfTiles(float tileSize) const override;
  44. //! @}
  45. //! A container of PhysX overlap scene hits (has PhysX colliders and their position/orientation).
  46. using QueryHits = AZStd::vector<AzPhysics::SceneQueryHit>;
  47. //! Blocking call. Collects all the relevant PhysX geometry within a provided volume.
  48. //! @param tileSize the result is packaged in tiles, which are squares covering the provided volume of @worldVolume
  49. //! @param borderSize an additional extend in all direction around the tile volume, this additional geometry will allow Recast to connect tiles together.
  50. //! @param worldVolume the overall volume to collect static PhysX geometry
  51. //! @returns an array of tiles, each containing indexed geometry
  52. AZStd::vector<AZStd::shared_ptr<TileGeometry>> CollectGeometryImpl(
  53. float tileSize,
  54. float borderSize,
  55. const AZ::Aabb& worldVolume);
  56. //! Async variant of @CollectGeometryImpl. Tiles are returned via a callback @tileCallback.
  57. //! Calls on @tileCallback will come from a task graph (not a main thread).
  58. //! Is expected that the context for callback function will persist until all the tiles are processed.
  59. //!
  60. //! Note: the callback will be called at least once and one time for each tile geometry.
  61. //! For example if two tiles are found the following callbacks will be made:
  62. //! tileCallback(tile1);
  63. //! tileCallback(tile2);
  64. //! tileCallback({}); //-- this indicates the end of the operation
  65. //!
  66. //! @param tileSize the result is packaged in tiles, which are squares covering the provided volume of @worldVolume
  67. //! @param borderSize an additional extend in all direction around the tile volume, this additional geometry will allow Recast to connect tiles together
  68. //! @param worldVolume worldVolume the overall volume to collect static PhysX geometry
  69. //! @param tileCallback an empty tile indicates the end of the operation, otherwise a valid shared_ptr is returned with tile geometry
  70. //! @returns true if an async operation was scheduled, false otherwise
  71. bool CollectGeometryAsyncImpl(
  72. float tileSize,
  73. float borderSize,
  74. const AZ::Aabb& worldVolume,
  75. AZStd::function<void(AZStd::shared_ptr<TileGeometry>)> tileCallback);
  76. //! Finds all the static PhysX colliders within a given volume.
  77. //! @param volume the world to look for static colliders
  78. //! @param overlapHits (out) found colliders will be attached to this container
  79. void CollectCollidersWithinVolume(const AZ::Aabb& volume, QueryHits& overlapHits);
  80. //! Given a container of static colliders return indexed triangle data.
  81. //! @param geometry (out) triangle data will be added
  82. //! @param overlapHits (in) an array of static PhysX colliders
  83. void AppendColliderGeometry(TileGeometry& geometry, const QueryHits& overlapHits);
  84. //! Returns the built-in names for the PhysX scene, either Editor or game scene.
  85. const char* GetSceneName() const;
  86. protected:
  87. void OnConfigurationChanged();
  88. AZ::EntityComponentIdPair m_entityComponentIdPair;
  89. RecastNavigationPhysXProviderConfig m_config;
  90. AzPhysics::CollisionGroup m_collisionGroup;
  91. //! A way to check if we should stop tile processing (because we might be deactivating, for example).
  92. AZStd::atomic<bool> m_shouldProcessTiles{ true };
  93. //! If true, an update operation is in progress.
  94. AZStd::atomic<bool> m_updateInProgress{ false };
  95. //! Task graph objects to collect geometry data in tiles over a grid.
  96. AZ::TaskGraph m_taskGraph{ "RecastNavigation PhysX" };
  97. AZ::TaskExecutor m_taskExecutor;
  98. AZStd::unique_ptr<AZ::TaskGraphEvent> m_taskGraphEvent;
  99. AZ::TaskDescriptor m_taskDescriptor{ "Collect Geometry", "Recast Navigation" };
  100. };
  101. } // namespace RecastNavigation