From 4b6c93f2893388cbad57a3ebeae8fd59d52e215a Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Wed, 6 Oct 2021 10:48:01 -0500 Subject: [PATCH] Bugfixes for terrain surface data. (#4508) * Bugfixes for terrain surface data. 1. Changed the TerrainSurfaceDataSystem component to query for all the surface types, now that we have them. 2. Added dependency tracking to the TerrainSurfaceGradientList component so that it will refresh terrain data when any of its data changes. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Addressed PR feedback Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- .../TerrainSurfaceDataSystemComponent.cpp | 10 +++++ .../TerrainSurfaceGradientListComponent.cpp | 44 +++++++++++++++++-- .../TerrainSurfaceGradientListComponent.h | 8 ++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp index 04c94b24d6..0346ff7281 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp @@ -156,9 +156,19 @@ namespace Terrain point.m_entityId = GetEntityId(); point.m_position = AZ::Vector3(inPosition.GetX(), inPosition.GetY(), terrainHeight); point.m_normal = terrain->GetNormal(inPosition); + + // Always add a "terrain" or "terrainHole" tag. const AZ::Crc32 terrainTag = isHole ? SurfaceData::Constants::s_terrainHoleTagCrc : SurfaceData::Constants::s_terrainTagCrc; SurfaceData::AddMaxValueForMasks(point.m_masks, terrainTag, 1.0f); + + // Add all of the surface tags that the terrain has at this point. + AzFramework::SurfaceData::OrderedSurfaceTagWeightSet surfaceWeights; + terrain->GetSurfaceWeights(point.m_position, surfaceWeights); + for (auto& tag : surfaceWeights) + { + SurfaceData::AddMaxValueForMasks(point.m_masks, tag.m_surfaceType, tag.m_weight); + } surfacePointList.push_back(point); } // Only one handler should exist. diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp index 2fbd6a4814..958e175cf3 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp @@ -12,6 +12,7 @@ #include #include +#include namespace Terrain { @@ -33,7 +34,8 @@ namespace Terrain ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement( - AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientMapping::m_gradientEntityId, "Gradient Entity", "ID of Entity providing a gradient.") + AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientMapping::m_gradientEntityId, + "Gradient Entity", "ID of Entity providing a gradient.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) ->UIElement("GradientPreviewer", "Previewer") ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") @@ -68,7 +70,8 @@ namespace Terrain ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement( - AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientListConfig::m_gradientSurfaceMappings, "Gradient to Surface Mappings", "Maps Gradient Entities to Surfaces.") + AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientListConfig::m_gradientSurfaceMappings, + "Gradient to Surface Mappings", "Maps Gradient Entities to Surfaces.") ; } } @@ -109,12 +112,36 @@ namespace Terrain void TerrainSurfaceGradientListComponent::Activate() { + LmbrCentral::DependencyNotificationBus::Handler::BusConnect(GetEntityId()); Terrain::TerrainAreaSurfaceRequestBus::Handler::BusConnect(GetEntityId()); + + // Make sure we get update notifications whenever this entity or any dependent gradient entity changes in any way. + // We'll use that to notify the terrain system that the surface information needs to be refreshed. + m_dependencyMonitor.Reset(); + m_dependencyMonitor.ConnectOwner(GetEntityId()); + m_dependencyMonitor.ConnectDependency(GetEntityId()); + + for (auto& surfaceMapping : m_configuration.m_gradientSurfaceMappings) + { + if (surfaceMapping.m_gradientEntityId != GetEntityId()) + { + m_dependencyMonitor.ConnectDependency(surfaceMapping.m_gradientEntityId); + } + } + + // Notify that the area has changed. + OnCompositionChanged(); } void TerrainSurfaceGradientListComponent::Deactivate() { + m_dependencyMonitor.Reset(); + Terrain::TerrainAreaSurfaceRequestBus::Handler::BusDisconnect(); + LmbrCentral::DependencyNotificationBus::Handler::BusDisconnect(); + + // Since this surface data will no longer exist, notify the terrain system to refresh the area. + OnCompositionChanged(); } bool TerrainSurfaceGradientListComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig) @@ -137,7 +164,9 @@ namespace Terrain return false; } - void TerrainSurfaceGradientListComponent::GetSurfaceWeights(const AZ::Vector3& inPosition, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights) const + void TerrainSurfaceGradientListComponent::GetSurfaceWeights( + const AZ::Vector3& inPosition, + AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights) const { outSurfaceWeights.clear(); @@ -146,7 +175,8 @@ namespace Terrain for (const auto& mapping : m_configuration.m_gradientSurfaceMappings) { float weight = 0.0f; - GradientSignal::GradientRequestBus::EventResult(weight, mapping.m_gradientEntityId, &GradientSignal::GradientRequestBus::Events::GetValue, params); + GradientSignal::GradientRequestBus::EventResult(weight, + mapping.m_gradientEntityId, &GradientSignal::GradientRequestBus::Events::GetValue, params); AzFramework::SurfaceData::SurfaceTagWeight tagWeight; tagWeight.m_surfaceType = mapping.m_surfaceTag; @@ -154,4 +184,10 @@ namespace Terrain outSurfaceWeights.emplace(tagWeight); } } + + void TerrainSurfaceGradientListComponent::OnCompositionChanged() + { + TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::RefreshArea, GetEntityId()); + } + } // namespace Terrain diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h index 799038354c..bb30029f35 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include @@ -47,6 +49,7 @@ namespace Terrain class TerrainSurfaceGradientListComponent : public AZ::Component , public Terrain::TerrainAreaSurfaceRequestBus::Handler + , private LmbrCentral::DependencyNotificationBus::Handler { public: template @@ -72,6 +75,11 @@ namespace Terrain void GetSurfaceWeights(const AZ::Vector3& inPosition, AzFramework::SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights) const override; private: + ////////////////////////////////////////////////////////////////////////// + // LmbrCentral::DependencyNotificationBus + void OnCompositionChanged() override; + TerrainSurfaceGradientListConfig m_configuration; + LmbrCentral::DependencyMonitor m_dependencyMonitor; }; } // namespace Terrain