TerrainWorldDebuggerComponent.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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/Asset/AssetCommon.h>
  10. #include <AzCore/Component/Component.h>
  11. #include <AzCore/Math/Vector3.h>
  12. #include <AzFramework/Entity/EntityDebugDisplayBus.h>
  13. #include <AzFramework/Terrain/TerrainDataRequestBus.h>
  14. #include <AzFramework/Visibility/BoundsBus.h>
  15. #include <TerrainSystem/TerrainSystem.h>
  16. namespace LmbrCentral
  17. {
  18. template<typename, typename>
  19. class EditorWrappedComponentBase;
  20. }
  21. namespace Terrain
  22. {
  23. class TerrainDebugQueryVisualizerConfig
  24. {
  25. public:
  26. AZ_CLASS_ALLOCATOR(TerrainDebugQueryVisualizerConfig, AZ::SystemAllocator);
  27. AZ_RTTI(TerrainDebugQueryVisualizerConfig, "{6FA6540D-D90A-44AC-8F5D-35071689291B}");
  28. TerrainDebugQueryVisualizerConfig() = default;
  29. virtual ~TerrainDebugQueryVisualizerConfig() = default;
  30. bool DrawQueriesDisabled()
  31. {
  32. return !m_drawQueries;
  33. }
  34. bool DisableHeights()
  35. {
  36. return !(m_drawQueries && m_drawHeights);
  37. }
  38. bool DisableNormals()
  39. {
  40. return !(m_drawQueries && m_drawNormals);
  41. }
  42. bool DisableCenterPosition()
  43. {
  44. return !m_drawQueries || m_useCameraPosition;
  45. }
  46. bool m_drawQueries{ false };
  47. AzFramework::Terrain::TerrainDataRequests::Sampler m_sampler{ AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR };
  48. size_t m_pointsPerDirection{ 32 };
  49. float m_spacing{ 0.5f };
  50. bool m_drawHeights{ true };
  51. float m_heightPointSize{ 1.0f / 16.0f };
  52. bool m_drawNormals{ true };
  53. float m_normalHeight{ 1.0f };
  54. bool m_useCameraPosition{ true };
  55. AZ::Vector3 m_centerPosition{ AZ::Vector3(0.0f) };
  56. };
  57. class TerrainWorldDebuggerConfig
  58. : public AZ::ComponentConfig
  59. {
  60. public:
  61. AZ_CLASS_ALLOCATOR(TerrainWorldDebuggerConfig, AZ::SystemAllocator);
  62. AZ_RTTI(TerrainWorldDebuggerConfig, "{92686FA9-2C0B-47F1-8E2D-F2F302CDE5AA}", AZ::ComponentConfig);
  63. static void Reflect(AZ::ReflectContext* context);
  64. bool m_drawWireframe{ true };
  65. bool m_drawWorldBounds{ true };
  66. bool m_drawLastDirtyRegion{ false };
  67. TerrainDebugQueryVisualizerConfig m_debugQueries;
  68. };
  69. class TerrainWorldDebuggerComponent
  70. : public AZ::Component
  71. , private AzFramework::EntityDebugDisplayEventBus::Handler
  72. , private AzFramework::BoundsRequestBus::Handler
  73. , private AzFramework::Terrain::TerrainDataNotificationBus::Handler
  74. {
  75. public:
  76. template<typename, typename>
  77. friend class LmbrCentral::EditorWrappedComponentBase;
  78. AZ_COMPONENT(TerrainWorldDebuggerComponent, "{ECA1F4CB-5395-41FD-B6ED-FFD2C80096E2}");
  79. static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services);
  80. static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services);
  81. static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services);
  82. static void Reflect(AZ::ReflectContext* context);
  83. TerrainWorldDebuggerComponent(const TerrainWorldDebuggerConfig& configuration);
  84. TerrainWorldDebuggerComponent() = default;
  85. ~TerrainWorldDebuggerComponent() override;
  86. //////////////////////////////////////////////////////////////////////////
  87. // AZ::Component interface implementation
  88. void Activate() override;
  89. void Deactivate() override;
  90. bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override;
  91. bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override;
  92. //////////////////////////////////////////////////////////////////////////
  93. // EntityDebugDisplayEventBus
  94. // Ideally this would use ViewportDebugDisplayEventBus::DisplayViewport, but that doesn't currently work in game mode,
  95. // so instead we use this plus the BoundsRequestBus with a large AABB to get ourselves rendered.
  96. void DisplayEntityViewport(
  97. const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
  98. //////////////////////////////////////////////////////////////////////////
  99. // BoundsRequestBus
  100. AZ::Aabb GetWorldBounds() const override;
  101. AZ::Aabb GetLocalBounds() const override;
  102. //////////////////////////////////////////////////////////////////////////
  103. // AzFramework::Terrain::TerrainDataNotificationBus
  104. void OnTerrainDataChanged(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask) override;
  105. private:
  106. TerrainWorldDebuggerConfig m_configuration;
  107. // Cache our debug wireframe representation in "sectors" of data so that we can easily control how far out we draw
  108. // the wireframe representation in each direction.
  109. struct WireframeSector
  110. {
  111. WireframeSector() = default;
  112. ~WireframeSector() = default;
  113. WireframeSector(const WireframeSector& other);
  114. WireframeSector(WireframeSector&& other);
  115. WireframeSector& operator=(const WireframeSector& other);
  116. WireframeSector& operator=(WireframeSector&& other);
  117. void Reset();
  118. // This should only be called within the scope of a lock on m_sectorStateMutex.
  119. void SetDirty();
  120. AZStd::shared_ptr<AzFramework::Terrain::TerrainJobContext> m_jobContext;
  121. AZStd::unique_ptr<AZStd::semaphore> m_jobCompletionEvent;
  122. AZStd::recursive_mutex m_sectorStateMutex;
  123. AZ::Aabb m_aabb{ AZ::Aabb::CreateNull() };
  124. AZStd::vector<AZ::Vector3> m_lineVertices;
  125. AZStd::vector<AZ::Vector3> m_sectorVertices;
  126. AZStd::vector<bool> m_sectorVertexExists;
  127. bool m_isDirty{ true };
  128. };
  129. void RebuildSectorWireframe(WireframeSector& sector, float gridResolution);
  130. void MarkDirtySectors(const AZ::Aabb& dirtyRegion);
  131. void DrawLastDirtyRegion(AzFramework::DebugDisplayRequests& debugDisplay);
  132. void DrawWorldBounds(AzFramework::DebugDisplayRequests& debugDisplay);
  133. void DrawWireframe(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay);
  134. void DrawQueries(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay);
  135. // Each sector contains an N x N grid of squares that it will draw. Since this is a count of the number of terrain grid points
  136. // in each direction, the actual world size will depend on the terrain grid resolution in each direction.
  137. static constexpr int32_t SectorSizeInGridPoints = 10;
  138. // For each grid point we will draw half a square ( _| ), so we need 4 vertices for the two lines.
  139. static constexpr int32_t VerticesPerGridPoint = 4;
  140. // Pre-calculate the total number of vertices per sector (N x N grid points, with 4 vertices per grid point)
  141. static constexpr int32_t VerticesPerSector = (SectorSizeInGridPoints * SectorSizeInGridPoints) * VerticesPerGridPoint;
  142. // AuxGeom has limits to the number of lines it can draw in a frame, so we'll cap how many total sectors to draw.
  143. static constexpr int32_t MaxVerticesToDraw = 500000;
  144. static constexpr int32_t MaxSectorsToDraw = MaxVerticesToDraw / VerticesPerSector;
  145. // Structure to keep track of all our current wireframe sectors, so that we don't have to recalculate them every frame.
  146. AZStd::vector<WireframeSector> m_wireframeSectors;
  147. // The size in sectors of our wireframe grid in each direction (i.e. a 5 x 5 sector grid has a sectorGridSize of 5)
  148. int32_t m_sectorGridSize{ 0 };
  149. AZ::Aabb m_lastDirtyRegion{ AZ::Aabb::CreateNull() };
  150. AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask m_lastDirtyData =
  151. AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask::None;
  152. };
  153. }