First pass terrain cleanup (#3753)

* First pass cleanup of some terrain components.

Signed-off-by: Ken Pruiksma <pruiksma@amazon.com>

* Adding basic culling to terrain sectors

Signed-off-by: Ken Pruiksma <pruiksma@amazon.com>

* Adding default value for m_transform

Signed-off-by: Ken Pruiksma <pruiksma@amazon.com>
This commit is contained in:
Ken Pruiksma
2021-08-31 19:05:03 -05:00
committed by GitHub
parent d838a0fcbc
commit 0c7dfce5a0
7 changed files with 122 additions and 173 deletions
@@ -85,8 +85,10 @@ namespace Terrain
void TerrainWorldComponent::Activate()
{
TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::SetWorldMin, m_configuration.m_worldMin);
TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::SetWorldMax, m_configuration.m_worldMax);
TerrainSystemServiceRequestBus::Broadcast(
&TerrainSystemServiceRequestBus::Events::SetWorldBounds,
AZ::Aabb::CreateFromMinMax(m_configuration.m_worldMin, m_configuration.m_worldMax)
);
TerrainSystemServiceRequestBus::Broadcast(
&TerrainSystemServiceRequestBus::Events::SetHeightQueryResolution, m_configuration.m_heightQueryResolution);
@@ -92,20 +92,13 @@ namespace Terrain
{
m_wireframeBounds = AZ::Aabb::CreateNull();
TerrainSystemServiceRequestBus::Broadcast(
&TerrainSystemServiceRequestBus::Events::SetDebugWireframe, m_configuration.m_drawWireframe);
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId());
AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId());
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusConnect();
}
void TerrainWorldDebuggerComponent::Deactivate()
{
TerrainSystemServiceRequestBus::Broadcast(
&TerrainSystemServiceRequestBus::Events::SetDebugWireframe, false);
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusDisconnect();
AzFramework::BoundsRequestBus::Handler::BusDisconnect();
AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
@@ -10,12 +10,14 @@
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Math/Frustum.h>
#include <Atom/Utils/Utils.h>
#include <Atom/RHI/DrawPacketBuilder.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RPI.Public/Shader/Shader.h>
#include <Atom/RPI.Public/RPIUtils.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Public/AuxGeom/AuxGeomFeatureProcessorInterface.h>
@@ -34,6 +36,7 @@ namespace Terrain
namespace
{
const uint32_t DEFAULT_UploadBufferSize = 512 * 1024; // 512k
const char* TerrainFPName = "TerrainFeatureProcessor";
}
namespace ShaderInputs
@@ -59,7 +62,7 @@ namespace Terrain
void TerrainFeatureProcessor::Activate()
{
m_areaData.clear();
m_areaData = {};
InitializeAtomStuff();
EnableSceneNotification();
@@ -69,43 +72,18 @@ namespace Terrain
{
m_rhiSystem = AZ::RHI::RHISystemInterface::Get();
m_rhiSystem->GetDrawListTagRegistry()->AcquireTag(AZ::Name("Terrain"));
{
// Load the shader
const char* terrainShaderFilePath = "Shaders/Terrain/Terrain.azshader";
AZ::Data::AssetId shaderAssetId;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
shaderAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
terrainShaderFilePath, azrtti_typeid<AZ::RPI::ShaderAsset>(), false);
if (!shaderAssetId.IsValid())
{
AZ_Error("Terrain", false, "Failed to get shader asset id with path %s", terrainShaderFilePath);
return;
}
auto shaderAsset = AZ::Data::AssetManager::Instance().GetAsset<AZ::RPI::ShaderAsset>(shaderAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
shaderAsset.BlockUntilLoadComplete();
if (!shaderAsset.IsReady())
{
AZ_Error("Terrain", false, "Failed to get shader asset with path %s", terrainShaderFilePath);
return;
}
m_shader = AZ::RPI::Shader::FindOrCreate(shaderAsset);
constexpr const char* TerrainShaderFilePath = "Shaders/Terrain/Terrain.azshader";
m_shader = AZ::RPI::LoadShader(TerrainShaderFilePath);
if (!m_shader)
{
AZ_Error("Terrain", false, "Failed to find or create a shader instance from shader asset '%s'", terrainShaderFilePath);
AZ_Error(TerrainFPName, false, "Failed to find or create a shader instance from shader asset '%s'", TerrainShaderFilePath);
return;
}
// Create the data layout
m_pipelineStateDescriptor = AZ::RHI::PipelineStateDescriptorForDraw{};
{
AZ::RHI::InputStreamLayoutBuilder layoutBuilder;
@@ -124,41 +102,41 @@ namespace Terrain
m_perObjectSrgAsset = m_shader->FindShaderResourceGroupLayout(AZ::Name{"ObjectSrg"});
if (!m_perObjectSrgAsset)
{
AZ_Error("Terrain", false, "Failed to get shader resource group asset");
AZ_Error(TerrainFPName, false, "Failed to get shader resource group asset");
return;
}
else if (!m_perObjectSrgAsset->IsFinalized())
{
AZ_Error("Terrain", false, "Shader resource group asset is not loaded");
AZ_Error(TerrainFPName, false, "Shader resource group asset is not loaded");
return;
}
const AZ::RHI::ShaderResourceGroupLayout* shaderResourceGroupLayout = &(*m_perObjectSrgAsset);
m_heightmapImageIndex = shaderResourceGroupLayout->FindShaderInputImageIndex(AZ::Name(ShaderInputs::HeightmapImage));
AZ_Error("Terrain", m_heightmapImageIndex.IsValid(), "Failed to find shader input image %s.", ShaderInputs::HeightmapImage);
AZ_Error(TerrainFPName, m_heightmapImageIndex.IsValid(), "Failed to find shader input image %s.", ShaderInputs::HeightmapImage);
m_modelToWorldIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::ModelToWorld));
AZ_Error("Terrain", m_modelToWorldIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::ModelToWorld);
AZ_Error(TerrainFPName, m_modelToWorldIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::ModelToWorld);
m_heightScaleIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::HeightScale));
AZ_Error("Terrain", m_heightScaleIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::HeightScale);
AZ_Error(TerrainFPName, m_heightScaleIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::HeightScale);
m_uvMinIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::UvMin));
AZ_Error("Terrain", m_uvMinIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::UvMin);
AZ_Error(TerrainFPName, m_uvMinIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::UvMin);
m_uvMaxIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::UvMax));
AZ_Error("Terrain", m_uvMaxIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::UvMax);
AZ_Error(TerrainFPName, m_uvMaxIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::UvMax);
m_uvStepIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::UvStep));
AZ_Error("Terrain", m_uvStepIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::UvStep);
AZ_Error(TerrainFPName, m_uvStepIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::UvStep);
// If this fails to run now, it's ok, we'll initialize it in OnRenderPipelineAdded later.
bool success = GetParentScene()->ConfigurePipelineState(m_shader->GetDrawListTag(), m_pipelineStateDescriptor);
if (success)
{
m_pipelineState = m_shader->AcquirePipelineState(m_pipelineStateDescriptor);
AZ_Assert(m_pipelineState, "Failed to acquire default pipeline state for shader '%s'", terrainShaderFilePath);
AZ_Assert(m_pipelineState, "Failed to acquire default pipeline state for shader '%s'", TerrainShaderFilePath);
}
}
@@ -172,7 +150,7 @@ namespace Terrain
if (resultCode != AZ::RHI::ResultCode::Success)
{
AZ_Error("Terrain", false, "Failed to create host buffer pool from RPI");
AZ_Error(TerrainFPName, false, "Failed to create host buffer pool from RPI");
return;
}
@@ -180,7 +158,7 @@ namespace Terrain
if (!InitializeRenderBuffers())
{
AZ_Error("Terrain", false, "Failed to create Terrain render buffers!");
AZ_Error(TerrainFPName, false, "Failed to create Terrain render buffers!");
return;
}
}
@@ -210,7 +188,7 @@ namespace Terrain
DisableSceneNotification();
DestroyRenderBuffers();
m_areaData.clear();
m_areaData = {};
if (m_hostPool)
{
@@ -226,7 +204,6 @@ namespace Terrain
}
void TerrainFeatureProcessor::UpdateTerrainData(
AZ::EntityId areaId,
const AZ::Transform& transform,
const AZ::Aabb& worldBounds,
[[maybe_unused]] float sampleSpacing,
@@ -234,37 +211,33 @@ namespace Terrain
{
if (!worldBounds.IsValid())
{
m_areaData.erase(areaId);
return;
}
TerrainAreaData areaData;
areaData.m_transform = transform;
areaData.m_heightScale = worldBounds.GetZExtent();
areaData.m_terrainBounds = worldBounds;
areaData.m_heightmapImageHeight = height;
areaData.m_heightmapImageWidth = width;
m_areaData.m_transform = transform;
m_areaData.m_heightScale = worldBounds.GetZExtent();
m_areaData.m_terrainBounds = worldBounds;
m_areaData.m_heightmapImageHeight = height;
m_areaData.m_heightmapImageWidth = width;
// Create heightmap image data
{
areaData.m_propertiesDirty = true;
m_areaData.m_propertiesDirty = true;
AZ::RHI::Size imageSize;
imageSize.m_width = width;
imageSize.m_height = height;
AZ::Data::Instance<AZ::RPI::StreamingImagePool> streamingImagePool = AZ::RPI::ImageSystemInterface::Get()->GetSystemStreamingPool();
areaData.m_heightmapImage = AZ::RPI::StreamingImage::CreateFromCpuData(*streamingImagePool,
m_areaData.m_heightmapImage = AZ::RPI::StreamingImage::CreateFromCpuData(*streamingImagePool,
AZ::RHI::ImageDimension::Image2D,
imageSize,
AZ::RHI::Format::R32_FLOAT,
(uint8_t*)heightData.data(),
heightData.size() * sizeof(float));
AZ_Error("Terrain", areaData.m_heightmapImage, "Failed to initialize the heightmap image!");
AZ_Error(TerrainFPName, m_areaData.m_heightmapImage, "Failed to initialize the heightmap image!");
}
m_areaData.insert_or_assign(areaId, areaData);
}
void TerrainFeatureProcessor::ProcessSurfaces(const FeatureProcessor::RenderPacket& process)
@@ -276,31 +249,30 @@ namespace Terrain
return;
}
if (m_areaData.empty())
if (!m_areaData.m_terrainBounds.IsValid())
{
return;
}
m_drawPackets.clear();
m_processSrgs.clear();
AZ::RHI::DrawPacketBuilder drawPacketBuilder;
uint32_t numIndices = static_cast<uint32_t>(m_gridIndices.size());
AZ::RHI::DrawIndexed drawIndexed;
drawIndexed.m_indexCount = numIndices;
drawIndexed.m_indexOffset = 0;
drawIndexed.m_vertexOffset = 0;
for (auto& [areaId, areaData] : m_areaData)
if (m_areaData.m_propertiesDirty)
{
m_sectorData.clear();
AZ::RHI::DrawPacketBuilder drawPacketBuilder;
uint32_t numIndices = static_cast<uint32_t>(m_gridIndices.size());
AZ::RHI::DrawIndexed drawIndexed;
drawIndexed.m_indexCount = numIndices;
drawIndexed.m_indexOffset = 0;
drawIndexed.m_vertexOffset = 0;
float xFirstPatchStart =
areaData.m_terrainBounds.GetMin().GetX() - fmod(areaData.m_terrainBounds.GetMin().GetX(), m_gridMeters);
float xLastPatchStart = areaData.m_terrainBounds.GetMax().GetX() - fmod(areaData.m_terrainBounds.GetMax().GetX(), m_gridMeters);
m_areaData.m_terrainBounds.GetMin().GetX() - fmod(m_areaData.m_terrainBounds.GetMin().GetX(), m_gridMeters);
float xLastPatchStart = m_areaData.m_terrainBounds.GetMax().GetX() - fmod(m_areaData.m_terrainBounds.GetMax().GetX(), m_gridMeters);
float yFirstPatchStart =
areaData.m_terrainBounds.GetMin().GetY() - fmod(areaData.m_terrainBounds.GetMin().GetY(), m_gridMeters);
float yLastPatchStart = areaData.m_terrainBounds.GetMax().GetY() - fmod(areaData.m_terrainBounds.GetMax().GetY(), m_gridMeters);
m_areaData.m_terrainBounds.GetMin().GetY() - fmod(m_areaData.m_terrainBounds.GetMin().GetY(), m_gridMeters);
float yLastPatchStart = m_areaData.m_terrainBounds.GetMax().GetY() - fmod(m_areaData.m_terrainBounds.GetMax().GetY(), m_gridMeters);
for (float yPatch = yFirstPatchStart; yPatch <= yLastPatchStart; yPatch += m_gridMeters)
{
@@ -310,62 +282,70 @@ namespace Terrain
drawPacketBuilder.SetDrawArguments(drawIndexed);
drawPacketBuilder.SetIndexBufferView(m_indexBufferView);
auto m_resourceGroup = AZ::RPI::ShaderResourceGroup::Create(m_shader->GetAsset(), m_shader->GetSupervariantIndex(), AZ::Name("ObjectSrg"));
auto resourceGroup = AZ::RPI::ShaderResourceGroup::Create(m_shader->GetAsset(), m_shader->GetSupervariantIndex(), AZ::Name("ObjectSrg"));
//auto m_resourceGroup = AZ::RPI::ShaderResourceGroup::Create(m_shader->GetAsset(), AZ::Name("ObjectSrg"));
if (!m_resourceGroup)
if (!resourceGroup)
{
AZ_Error("Terrain", false, "Failed to create shader resource group");
AZ_Error(TerrainFPName, false, "Failed to create shader resource group");
return;
}
float uvMin[2] = { 0.0f, 0.0f };
float uvMax[2] = { 1.0f, 1.0f };
uvMin[0] = (float)((xPatch - areaData.m_terrainBounds.GetMin().GetX()) / areaData.m_terrainBounds.GetXExtent());
uvMin[1] = (float)((yPatch - areaData.m_terrainBounds.GetMin().GetY()) / areaData.m_terrainBounds.GetYExtent());
uvMin[0] = (float)((xPatch - m_areaData.m_terrainBounds.GetMin().GetX()) / m_areaData.m_terrainBounds.GetXExtent());
uvMin[1] = (float)((yPatch - m_areaData.m_terrainBounds.GetMin().GetY()) / m_areaData.m_terrainBounds.GetYExtent());
uvMax[0] =
(float)(((xPatch + m_gridMeters) - areaData.m_terrainBounds.GetMin().GetX()) / areaData.m_terrainBounds.GetXExtent());
(float)(((xPatch + m_gridMeters) - m_areaData.m_terrainBounds.GetMin().GetX()) / m_areaData.m_terrainBounds.GetXExtent());
uvMax[1] =
(float)(((yPatch + m_gridMeters) - areaData.m_terrainBounds.GetMin().GetY()) / areaData.m_terrainBounds.GetYExtent());
(float)(((yPatch + m_gridMeters) - m_areaData.m_terrainBounds.GetMin().GetY()) / m_areaData.m_terrainBounds.GetYExtent());
float uvStep[2] =
{
1.0f / areaData.m_heightmapImageWidth, 1.0f / areaData.m_heightmapImageHeight,
1.0f / m_areaData.m_heightmapImageWidth, 1.0f / m_areaData.m_heightmapImageHeight,
};
AZ::Transform transform = areaData.m_transform;
transform.SetTranslation(xPatch, yPatch, areaData.m_transform.GetTranslation().GetZ());
AZ::Transform transform = m_areaData.m_transform;
transform.SetTranslation(xPatch, yPatch, m_areaData.m_transform.GetTranslation().GetZ());
AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(transform);
m_resourceGroup->SetImage(m_heightmapImageIndex, areaData.m_heightmapImage);
m_resourceGroup->SetConstant(m_modelToWorldIndex, matrix3x4);
m_resourceGroup->SetConstant(m_heightScaleIndex, areaData.m_heightScale);
m_resourceGroup->SetConstant(m_uvMinIndex, uvMin);
m_resourceGroup->SetConstant(m_uvMaxIndex, uvMax);
m_resourceGroup->SetConstant(m_uvStepIndex, uvStep);
m_resourceGroup->Compile();
m_processSrgs.push_back(m_resourceGroup);
if (m_resourceGroup != nullptr)
{
drawPacketBuilder.AddShaderResourceGroup(m_resourceGroup->GetRHIShaderResourceGroup());
}
resourceGroup->SetImage(m_heightmapImageIndex, m_areaData.m_heightmapImage);
resourceGroup->SetConstant(m_modelToWorldIndex, matrix3x4);
resourceGroup->SetConstant(m_heightScaleIndex, m_areaData.m_heightScale);
resourceGroup->SetConstant(m_uvMinIndex, uvMin);
resourceGroup->SetConstant(m_uvMaxIndex, uvMax);
resourceGroup->SetConstant(m_uvStepIndex, uvStep);
resourceGroup->Compile();
drawPacketBuilder.AddShaderResourceGroup(resourceGroup->GetRHIShaderResourceGroup());
AZ::RHI::DrawPacketBuilder::DrawRequest drawRequest;
drawRequest.m_listTag = m_drawListTag;
drawRequest.m_pipelineState = m_pipelineState.get();
drawRequest.m_streamBufferViews = m_vertexBufferViews;
drawRequest.m_streamBufferViews = AZStd::array_view<AZ::RHI::StreamBufferView>(&m_vertexBufferView, 1);
drawPacketBuilder.AddDrawItem(drawRequest);
const AZ::RHI::DrawPacket* drawPacket = drawPacketBuilder.End();
m_drawPackets.emplace_back(drawPacket);
for (auto& view : process.m_views)
{
view->AddDrawPacket(drawPacket);
}
m_sectorData.emplace_back(
drawPacketBuilder.End(),
AZ::Aabb::CreateFromMinMax(
AZ::Vector3(xPatch, yPatch, m_areaData.m_terrainBounds.GetMin().GetZ()),
AZ::Vector3(xPatch + m_gridMeters, yPatch + m_gridMeters, m_areaData.m_terrainBounds.GetMax().GetZ())
),
resourceGroup
);
}
}
}
for (auto& view : process.m_views)
{
AZ::Frustum viewFrustum = AZ::Frustum::CreateFromMatrixColumnMajor(view->GetWorldToClipMatrix());
for (auto& sectorData : m_sectorData)
{
if (viewFrustum.IntersectAabb(sectorData.m_aabb) != AZ::IntersectResult::Exterior)
{
view->AddDrawPacket(sectorData.m_drawPacket.get());
}
}
}
@@ -413,9 +393,6 @@ namespace Terrain
m_indexBuffer->SetName(AZ::Name("TerrainIndexBuffer"));
m_vertexBuffer->SetName(AZ::Name("TerrainVertexBuffer"));
// We only need one vertex buffer view.
m_vertexBufferViews.resize(1);
AZStd::vector<AZ::RHI::Ptr<AZ::RHI::Buffer>> buffers = { m_indexBuffer , m_vertexBuffer };
// Fill our buffers with the vertex/index data
@@ -433,7 +410,7 @@ namespace Terrain
if (result != AZ::RHI::ResultCode::Success)
{
AZ_Error("Terrain", false, "Failed to create GPU buffers for Terrain");
AZ_Error(TerrainFPName, false, "Failed to create GPU buffers for Terrain");
return false;
}
@@ -462,10 +439,10 @@ namespace Terrain
const uint64_t elementSize = m_gridVertices.size() * sizeof(Vertex);
memcpy(mappedData, m_gridVertices.data(), elementSize);
m_vertexBufferViews[bufferIndex - 1] = AZ::RHI::StreamBufferView(
m_vertexBufferView = AZ::RHI::StreamBufferView(
*buffer, 0, static_cast<uint32_t>(elementSize), static_cast<uint32_t>(sizeof(Vertex)));
AZ::RHI::ValidateStreamBufferViews(m_pipelineStateDescriptor.m_inputStreamLayout, m_vertexBufferViews);
AZ::RHI::ValidateStreamBufferViews(m_pipelineStateDescriptor.m_inputStreamLayout, { { m_vertexBufferView } });
}
m_hostPool->UnmapBuffer(*buffer);
@@ -479,9 +456,8 @@ namespace Terrain
m_indexBuffer.reset();
m_vertexBuffer.reset();
m_vertexBufferViews.clear();
m_processSrgs.clear();
m_indexBufferView = {};
m_vertexBufferView = {};
m_pipelineStateDescriptor = AZ::RHI::PipelineStateDescriptorForDraw{};
m_pipelineState = nullptr;
@@ -47,16 +47,12 @@ namespace Terrain
void Deactivate() override;
void Render(const AZ::RPI::FeatureProcessor::RenderPacket& packet) override;
void UpdateTerrainData(AZ::EntityId areaId, const AZ::Transform& transform, const AZ::Aabb& worldBounds, float sampleSpacing,
void UpdateTerrainData(const AZ::Transform& transform, const AZ::Aabb& worldBounds, float sampleSpacing,
uint32_t width, uint32_t height, const AZStd::vector<float>& heightData);
void RemoveTerrainData(AZ::EntityId areaId)
{
m_areaData.erase(areaId);
}
void RemoveTerrainData()
{
m_areaData.clear();
m_areaData = {};
}
private:
@@ -122,13 +118,13 @@ namespace Terrain
AZ::RHI::Ptr<AZ::RHI::Buffer> m_indexBuffer;
AZ::RHI::Ptr<AZ::RHI::Buffer> m_vertexBuffer;
AZ::RHI::IndexBufferView m_indexBufferView;
AZStd::fixed_vector<AZ::RHI::StreamBufferView, AZ::RHI::Limits::Pipeline::StreamCountMax> m_vertexBufferViews;
AZ::RHI::StreamBufferView m_vertexBufferView;
// Per-area data
struct TerrainAreaData
{
AZ::Transform m_transform;
AZ::Aabb m_terrainBounds;
AZ::Transform m_transform{ AZ::Transform::CreateIdentity() };
AZ::Aabb m_terrainBounds{ AZ::Aabb::CreateNull() };
float m_heightScale;
AZ::Data::Instance<AZ::RPI::StreamingImage> m_heightmapImage;
uint32_t m_heightmapImageWidth;
@@ -136,10 +132,21 @@ namespace Terrain
bool m_propertiesDirty{ true };
};
AZStd::unordered_map<AZ::EntityId, TerrainAreaData> m_areaData;
TerrainAreaData m_areaData;
// These could either be per-area or system-level
AZStd::vector<AZStd::unique_ptr<const AZ::RHI::DrawPacket>> m_drawPackets;
AZStd::vector<AZ::Data::Instance<AZ::RPI::ShaderResourceGroup>> m_processSrgs;
struct SectorData
{
AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> m_srg;
AZ::Aabb m_aabb;
AZStd::unique_ptr<const AZ::RHI::DrawPacket> m_drawPacket;
SectorData(const AZ::RHI::DrawPacket* drawPacket, AZ::Aabb aabb, AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> srg)
: m_srg(srg)
, m_aabb(aabb)
, m_drawPacket(drawPacket)
{}
};
AZStd::vector<SectorData> m_sectorData;
};
}
@@ -49,15 +49,9 @@ void TerrainSystem::Deactivate()
m_terrainSettingsDirty = true;
}
void TerrainSystem::SetWorldMin(AZ::Vector3 worldOrigin)
{
m_requestedSettings.m_worldBounds.SetMin(worldOrigin);
m_terrainSettingsDirty = true;
}
void TerrainSystem::SetWorldMax(AZ::Vector3 worldBounds)
{
m_requestedSettings.m_worldBounds.SetMax(worldBounds);
void TerrainSystem::SetWorldBounds(const AZ::Aabb& worldBounds)
{
m_requestedSettings.m_worldBounds = worldBounds;
m_terrainSettingsDirty = true;
}
@@ -67,13 +61,6 @@ void TerrainSystem::SetHeightQueryResolution(AZ::Vector2 queryResolution)
m_terrainSettingsDirty = true;
}
void TerrainSystem::SetDebugWireframe(bool wireframeEnabled)
{
m_requestedSettings.m_debugWireframeEnabled = wireframeEnabled;
m_terrainSettingsDirty = true;
}
AZ::Aabb TerrainSystem::GetTerrainAabb() const
{
return m_currentSettings.m_worldBounds;
@@ -378,13 +365,6 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
terrainSettingsChanged = true;
}
if (m_requestedSettings.m_debugWireframeEnabled != m_currentSettings.m_debugWireframeEnabled)
{
m_dirtyRegion = AZ::Aabb::CreateNull();
m_terrainHeightDirty = true;
terrainSettingsChanged = true;
}
if (m_requestedSettings.m_heightQueryResolution != m_currentSettings.m_heightQueryResolution)
{
m_dirtyRegion = AZ::Aabb::CreateNull();
@@ -409,7 +389,6 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
{
AZStd::shared_lock<AZStd::shared_mutex> lock(m_areaMutex);
AZ::EntityId entityId(0);
AZ::Transform transform = AZ::Transform::CreateTranslation(m_currentSettings.m_worldBounds.GetCenter());
uint32_t width = aznumeric_cast<uint32_t>(
@@ -417,7 +396,7 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
uint32_t height = aznumeric_cast<uint32_t>(
(float)m_currentSettings.m_worldBounds.GetYExtent() / m_currentSettings.m_heightQueryResolution.GetY());
AZStd::vector<float> pixels;
pixels.resize(width * height);
pixels.resize_no_construct(width * height);
const uint32_t pixelDataSize = width * height * sizeof(float);
memset(pixels.data(), 0, pixelDataSize);
@@ -454,8 +433,7 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
if (terrainFeatureProcessor)
{
terrainFeatureProcessor->UpdateTerrainData(
entityId, transform, m_currentSettings.m_worldBounds, m_currentSettings.m_heightQueryResolution.GetX(), width, height,
pixels);
transform, m_currentSettings.m_worldBounds, m_currentSettings.m_heightQueryResolution.GetX(), width, height, pixels);
}
}
@@ -36,11 +36,9 @@ namespace Terrain
///////////////////////////////////////////
// TerrainSystemServiceRequestBus::Handler Impl
void SetWorldMin(AZ::Vector3 worldOrigin) override;
void SetWorldMax(AZ::Vector3 worldBounds) override;
void SetWorldBounds(const AZ::Aabb& worldBounds) override;
void SetHeightQueryResolution(AZ::Vector2 queryResolution) override;
void SetDebugWireframe(bool wireframeEnabled) override;
void Activate() override;
void Deactivate() override;
@@ -103,7 +101,6 @@ namespace Terrain
{
AZ::Aabb m_worldBounds;
AZ::Vector2 m_heightQueryResolution{ 1.0f };
bool m_debugWireframeEnabled{ false };
bool m_systemActive{ false };
};
@@ -39,10 +39,8 @@ namespace Terrain
virtual void Activate() = 0;
virtual void Deactivate() = 0;
virtual void SetWorldMin(AZ::Vector3 worldOrigin) = 0;
virtual void SetWorldMax(AZ::Vector3 worldBounds) = 0;
virtual void SetWorldBounds(const AZ::Aabb& worldBounds) = 0;
virtual void SetHeightQueryResolution(AZ::Vector2 queryResolution) = 0;
virtual void SetDebugWireframe(bool wireframeEnabled) = 0;
// register an area to override terrain
virtual void RegisterArea(AZ::EntityId areaId) = 0;
@@ -111,8 +109,6 @@ namespace Terrain
virtual void GetHeight(const AZ::Vector3& inPosition, AZ::Vector3& outPosition, Sampler sampleFilter = Sampler::DEFAULT) = 0;
virtual void GetNormal(const AZ::Vector3& inPosition, AZ::Vector3& outNormal, Sampler sampleFilter = Sampler::DEFAULT) = 0;
//virtual void GetSurfaceWeights(const AZ::Vector3& inPosition, SurfaceTagWeightMap& outSurfaceWeights, Sampler sampleFilter = DEFAULT) = 0;
//virtual void GetSurfacePoint(const AZ::Vector3& inPosition, SurfacePoint& outSurfacePoint, SurfacePointDataMask dataMask = DEFAULT, Sampler sampleFilter = DEFAULT) = 0;
};
using TerrainAreaHeightRequestBus = AZ::EBus<TerrainAreaHeightRequests>;