Merge pull request #5328 from aws-lumberyard-dev/terrain/mbalfour/altitude_gradient_infinite_recursion_bug

Prevent infinite recursion with Altitude Gradient.
This commit is contained in:
Mike Balfour
2021-11-04 17:39:23 -05:00
committed by GitHub
2 changed files with 24 additions and 16 deletions
@@ -151,24 +151,29 @@ namespace Terrain
{
float maxSample = 0.0f;
terrainExists = false;
GradientSignal::GradientSampleParams params(AZ::Vector3(inPosition.GetX(), inPosition.GetY(), 0.0f));
// Right now, when the list contains multiple entries, we will use the highest point from each gradient.
// This is needed in part because gradients don't really have world bounds, so they exist everywhere but generally have a value
// of 0 outside their data bounds if they're using bounded data. We should examine the possibility of extending the gradient API
// to provide actual bounds so that it's possible to detect if the gradient even 'exists' in an area, at which point we could just
// make this list a prioritized list from top to bottom for any points that overlap.
for (auto& gradientId : m_configuration.m_gradientEntities)
AZ_WarningOnce("Terrain", !m_isRequestInProgress, "Detected cyclic dependences with terrain height entity references");
if (!m_isRequestInProgress)
{
// If gradients ever provide bounds, or if we add a value threshold in this component, it would be possible for terrain
// to *not* exist at a specific point.
terrainExists = true;
m_isRequestInProgress = true;
GradientSignal::GradientSampleParams params(AZ::Vector3(inPosition.GetX(), inPosition.GetY(), 0.0f));
float sample = 0.0f;
GradientSignal::GradientRequestBus::EventResult(
sample, gradientId, &GradientSignal::GradientRequestBus::Events::GetValue, params);
maxSample = AZ::GetMax(maxSample, sample);
// Right now, when the list contains multiple entries, we will use the highest point from each gradient.
// This is needed in part because gradients don't really have world bounds, so they exist everywhere but generally have a value
// of 0 outside their data bounds if they're using bounded data. We should examine the possibility of extending the gradient
// API to provide actual bounds so that it's possible to detect if the gradient even 'exists' in an area, at which point we
// could just make this list a prioritized list from top to bottom for any points that overlap.
for (auto& gradientId : m_configuration.m_gradientEntities)
{
// If gradients ever provide bounds, or if we add a value threshold in this component, it would be possible for terrain
// to *not* exist at a specific point.
terrainExists = true;
float sample = 0.0f;
GradientSignal::GradientRequestBus::EventResult(
sample, gradientId, &GradientSignal::GradientRequestBus::Events::GetValue, params);
maxSample = AZ::GetMax(maxSample, sample);
}
m_isRequestInProgress = false;
}
const float height = AZ::Lerp(m_cachedShapeBounds.GetMin().GetZ(), m_cachedShapeBounds.GetMax().GetZ(), maxSample);
@@ -91,6 +91,9 @@ namespace Terrain
AZ::Vector2 m_cachedHeightQueryResolution{ 1.0f, 1.0f };
AZ::Aabb m_cachedShapeBounds;
// prevent recursion in case user attaches cyclic dependences
mutable bool m_isRequestInProgress{ false };
LmbrCentral::DependencyMonitor m_dependencyMonitor;
};
}