Hook up the "Use Ground Plane" toggle.

The "Use Ground Plane" toggle is now functional.  When disabled, the terrain layer spawner will say "terrain exists = false" for any point in its bounds unless there's also a Terrain Height Gradient List component with a valid entry.  When enabled, it will always say "terrain exists = true", and it will return the min height of the spawner box as the ground plane if there's no valid Terrain Height Gradient List height provider.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>
monroegm-disable-blank-issue-2
Mike Balfour 4 years ago
parent 20edb35cdc
commit 97b0eddcb4

@ -161,14 +161,17 @@ namespace Terrain
// 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);
if (gradientId.IsValid())
{
// 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);
}
}
const float height = AZ::Lerp(m_cachedShapeBounds.GetMin().GetZ(), m_cachedShapeBounds.GetMax().GetZ(), maxSample);

@ -222,20 +222,31 @@ float TerrainSystem::GetHeightSynchronous(float x, float y, Sampler sampler, boo
float TerrainSystem::GetTerrainAreaHeight(float x, float y, bool& terrainExists) const
{
AZ::Vector3 inPosition((float)x, (float)y, m_currentSettings.m_worldBounds.GetMin().GetZ());
float height = m_currentSettings.m_worldBounds.GetMin().GetZ();
const float worldMin = m_currentSettings.m_worldBounds.GetMin().GetZ();
AZ::Vector3 inPosition(x, y, worldMin);
float height = worldMin;
terrainExists = false;
AZStd::shared_lock<AZStd::shared_mutex> lock(m_areaMutex);
for (auto& [areaId, areaBounds] : m_registeredAreas)
for (auto& [areaId, areaData] : m_registeredAreas)
{
inPosition.SetZ(areaBounds.GetMin().GetZ());
if (areaBounds.Contains(inPosition))
const float areaMin = areaData.m_areaBounds.GetMin().GetZ();
inPosition.SetZ(areaMin);
if (areaData.m_areaBounds.Contains(inPosition))
{
AZ::Vector3 outPosition;
Terrain::TerrainAreaHeightRequestBus::Event(
areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, terrainExists);
height = outPosition.GetZ();
if (!terrainExists)
{
// If the terrain height provider doesn't have any data, then check the area's "use ground plane" setting.
// If it's set, then create a default ground plane by saying terrain exists at the minimum height for the area.
// Otherwise, we'll set the height at the terrain world minimum and say it doesn't exist.
terrainExists = areaData.m_useGroundPlane;
height = areaData.m_useGroundPlane ? areaMin : worldMin;
}
break;
}
}
@ -395,12 +406,12 @@ AZ::EntityId TerrainSystem::FindBestAreaEntityAtPosition(float x, float y, AZ::A
AZStd::shared_lock<AZStd::shared_mutex> lock(m_areaMutex);
// The areas are sorted into priority order: the first area that contains inPosition is the most suitable.
for (const auto& [areaId, areaBounds] : m_registeredAreas)
for (const auto& [areaId, areaData] : m_registeredAreas)
{
inPosition.SetZ(areaBounds.GetMin().GetZ());
if (areaBounds.Contains(inPosition))
inPosition.SetZ(areaData.m_areaBounds.GetMin().GetZ());
if (areaData.m_areaBounds.Contains(inPosition))
{
bounds = areaBounds;
bounds = areaData.m_areaBounds;
return areaId;
}
}
@ -548,7 +559,12 @@ void TerrainSystem::RegisterArea(AZ::EntityId areaId)
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
AZ::Aabb aabb = AZ::Aabb::CreateNull();
LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
m_registeredAreas[areaId] = aabb;
// Cache off whether or not this layer spawner should have a default ground plane when no other terrain height data exists.
bool useGroundPlane = false;
Terrain::TerrainSpawnerRequestBus::EventResult(useGroundPlane, areaId, &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane);
m_registeredAreas[areaId] = { aabb, useGroundPlane };
m_dirtyRegion.AddAabb(aabb);
m_terrainHeightDirty = true;
m_terrainSurfacesDirty = true;
@ -565,10 +581,10 @@ void TerrainSystem::UnregisterArea(AZ::EntityId areaId)
m_registeredAreas,
[areaId, this](const auto& item)
{
auto const& [entityId, aabb] = item;
auto const& [entityId, areaData] = item;
if (areaId == entityId)
{
m_dirtyRegion.AddAabb(aabb);
m_dirtyRegion.AddAabb(areaData.m_areaBounds);
m_terrainHeightDirty = true;
m_terrainSurfacesDirty = true;
return true;
@ -585,10 +601,10 @@ void TerrainSystem::RefreshArea(AZ::EntityId areaId, AzFramework::Terrain::Terra
auto areaAabb = m_registeredAreas.find(areaId);
AZ::Aabb oldAabb = (areaAabb != m_registeredAreas.end()) ? areaAabb->second : AZ::Aabb::CreateNull();
AZ::Aabb oldAabb = (areaAabb != m_registeredAreas.end()) ? areaAabb->second.m_areaBounds : AZ::Aabb::CreateNull();
AZ::Aabb newAabb = AZ::Aabb::CreateNull();
LmbrCentral::ShapeComponentRequestsBus::EventResult(newAabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
m_registeredAreas[areaId] = newAabb;
m_registeredAreas[areaId].m_areaBounds = newAabb;
AZ::Aabb expandedAabb = oldAabb;
expandedAabb.AddAabb(newAabb);

@ -168,7 +168,14 @@ namespace Terrain
bool m_terrainSurfacesDirty = false;
AZ::Aabb m_dirtyRegion;
// Cached data for each terrain area to use when looking up terrain data.
struct TerrainAreaData
{
AZ::Aabb m_areaBounds{ AZ::Aabb::CreateNull() };
bool m_useGroundPlane{ false };
};
mutable AZStd::shared_mutex m_areaMutex;
AZStd::map<AZ::EntityId, AZ::Aabb, TerrainLayerPriorityComparator> m_registeredAreas;
AZStd::map<AZ::EntityId, TerrainAreaData, TerrainLayerPriorityComparator> m_registeredAreas;
};
} // namespace Terrain

Loading…
Cancel
Save