From 641e76eca9f2c0b7f4d5bf1f83d6b8b884d9ecc5 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 14 Jan 2022 10:09:14 -0800 Subject: [PATCH 01/11] Convert the loops using the Get* functions in Terrain physics and debugger components to use the new ProcessRegion* functions. Signed-off-by: amzn-sj --- .../TerrainPhysicsColliderComponent.cpp | 80 ++++++++----------- .../TerrainWorldDebuggerComponent.cpp | 37 +++------ 2 files changed, 45 insertions(+), 72 deletions(-) diff --git a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp index c51728a5c3..4a8b4680b3 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp @@ -284,21 +284,14 @@ namespace Terrain heights.clear(); heights.reserve(gridWidth * gridHeight); - for (int32_t row = 0; row < gridHeight; row++) + auto perPositionHeightCallback = [&heights, worldCenterZ] + ([[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) { - const float y = row * gridResolution.GetY() + worldSize.GetMin().GetY(); - for (int32_t col = 0; col < gridWidth; col++) - { - const float x = col * gridResolution.GetX() + worldSize.GetMin().GetX(); - float height = 0.0f; + heights.emplace_back(surfacePoint.m_position.GetZ() - worldCenterZ); + }; - AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( - height, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats, x, y, - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT, nullptr); - - heights.emplace_back(height - worldCenterZ); - } - } + AzFramework::Terrain::TerrainDataRequestBus::Broadcast(&AzFramework::Terrain::TerrainDataRequests::ProcessHeightsFromRegion, + worldSize, gridResolution, perPositionHeightCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT); } uint8_t TerrainPhysicsColliderComponent::GetMaterialIdIndex(const Physics::MaterialId& materialId, const AZStd::vector& materialList) const @@ -350,42 +343,37 @@ namespace Terrain AZStd::vector materialList = GetMaterialList(); - for (int32_t row = 0; row < gridHeight; row++) + auto perPositionCallback = [&heightMaterials, &materialList, this, worldCenterZ, worldHeightBoundsMin, worldHeightBoundsMax] + (size_t xIndex, size_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, bool terrainExists) { - const float y = row * gridResolution.GetY() + worldSize.GetMin().GetY(); - for (int32_t col = 0; col < gridWidth; col++) + float height = surfacePoint.m_position.GetZ(); + + // Any heights that fall outside the range of our bounding box will get turned into holes. + if ((height < worldHeightBoundsMin) || (height > worldHeightBoundsMax)) { - const float x = col * gridResolution.GetX() + worldSize.GetMin().GetX(); - float height = 0.0f; - - bool terrainExists = true; - AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( - height, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats, x, y, - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT, &terrainExists); - - // Any heights that fall outside the range of our bounding box will get turned into holes. - if ((height < worldHeightBoundsMin) || (height > worldHeightBoundsMax)) - { - height = worldHeightBoundsMin; - terrainExists = false; - } - - // Find the best surface tag at this point. - AzFramework::SurfaceData::SurfaceTagWeight surfaceWeight; - AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( - surfaceWeight, &AzFramework::Terrain::TerrainDataRequests::GetMaxSurfaceWeightFromFloats, x, y, - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT, nullptr); - - Physics::HeightMaterialPoint point; - point.m_height = height - worldCenterZ; - point.m_quadMeshType = terrainExists ? Physics::QuadMeshType::SubdivideUpperLeftToBottomRight : Physics::QuadMeshType::Hole; - - Physics::MaterialId materialId = FindMaterialIdForSurfaceTag(surfaceWeight.m_surfaceType); - point.m_materialIndex = GetMaterialIdIndex(materialId, materialList); - - heightMaterials.emplace_back(point); + height = worldHeightBoundsMin; + terrainExists = false; } - } + + // Find the best surface tag at this point. + // We want the MaxSurfaceWeight. The ProcessSurfacePoints callback has surface weights sorted. + // So, we pick the value at the front of the list. + AzFramework::SurfaceData::SurfaceTagWeight surfaceWeight; + if (!surfacePoint.m_surfaceTags.empty()) + { + surfaceWeight = *surfacePoint.m_surfaceTags.begin(); + } + + Physics::HeightMaterialPoint point; + point.m_height = height - worldCenterZ; + point.m_quadMeshType = terrainExists ? Physics::QuadMeshType::SubdivideUpperLeftToBottomRight : Physics::QuadMeshType::Hole; + Physics::MaterialId materialId = FindMaterialIdForSurfaceTag(surfaceWeight.m_surfaceType); + point.m_materialIndex = GetMaterialIdIndex(materialId, materialList); + heightMaterials.emplace_back(point); + }; + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast(&AzFramework::Terrain::TerrainDataRequests::ProcessSurfacePointsFromRegion, + worldSize, gridResolution, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT); } AZ::Vector2 TerrainPhysicsColliderComponent::GetHeightfieldGridSpacing() const diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp index f3e0d59537..46be621307 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp @@ -354,44 +354,29 @@ namespace Terrain // For each terrain height value in the region, create the _| grid lines for that point and cache off the height value // for use with subsequent grid line calculations. auto ProcessHeightValue = [gridResolution, &previousHeight, &rowHeights, §or] - (uint32_t xIndex, uint32_t yIndex, const AZ::Vector3& position, [[maybe_unused]] bool terrainExists) + (uint32_t xIndex, uint32_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) { // Don't add any vertices for the first column or first row. These grid lines will be handled by an adjacent sector, if // there is one. if ((xIndex > 0) && (yIndex > 0)) { - float x = position.GetX() - gridResolution.GetX(); - float y = position.GetY() - gridResolution.GetY(); + float x = surfacePoint.m_position.GetX() - gridResolution.GetX(); + float y = surfacePoint.m_position.GetY() - gridResolution.GetY(); - sector.m_lineVertices.emplace_back(AZ::Vector3(x, position.GetY(), previousHeight)); - sector.m_lineVertices.emplace_back(position); + sector.m_lineVertices.emplace_back(AZ::Vector3(x, surfacePoint.m_position.GetY(), previousHeight)); + sector.m_lineVertices.emplace_back(surfacePoint.m_position); - sector.m_lineVertices.emplace_back(AZ::Vector3(position.GetX(), y, rowHeights[xIndex])); - sector.m_lineVertices.emplace_back(position); + sector.m_lineVertices.emplace_back(AZ::Vector3(surfacePoint.m_position.GetX(), y, rowHeights[xIndex])); + sector.m_lineVertices.emplace_back(surfacePoint.m_position); } // Save off the heights so that we can use them to draw subsequent columns and rows. - previousHeight = position.GetZ(); - rowHeights[xIndex] = position.GetZ(); + previousHeight = surfacePoint.m_position.GetZ(); + rowHeights[xIndex] = surfacePoint.m_position.GetZ(); }; - // This set of nested loops will get replaced with a call to ProcessHeightsFromRegion once the API exists. - for (size_t yIndex = 0; yIndex < numSamplesY; yIndex++) - { - float y = region.GetMin().GetY() + (gridResolution.GetY() * yIndex); - for (size_t xIndex = 0; xIndex < numSamplesX; xIndex++) - { - float x = region.GetMin().GetX() + (gridResolution.GetX() * xIndex); - - float height = worldMinZ; - bool terrainExists = false; - AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( - height, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats, x, y, - AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists); - ProcessHeightValue( - aznumeric_cast(xIndex), aznumeric_cast(yIndex), AZ::Vector3(x, y, height), terrainExists); - } - } + AzFramework::Terrain::TerrainDataRequestBus::Broadcast(&AzFramework::Terrain::TerrainDataRequests::ProcessHeightsFromRegion, + region, gridResolution, ProcessHeightValue, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT); } void TerrainWorldDebuggerComponent::OnTerrainDataChanged(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask) From 6ac1211ae92889e0d8c8c72a2bdc18df1c2bfd24 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 14 Jan 2022 16:40:08 -0800 Subject: [PATCH 02/11] Add unit tests for ProcessSurfaceWeightsFromRegion and ProcessSurfacePointsFromRegion. Signed-off-by: amzn-sj --- Gems/Terrain/Code/Tests/TerrainSystemTest.cpp | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp index a5798a3dad..2eebc1b824 100644 --- a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp @@ -902,4 +902,168 @@ namespace UnitTest terrainSystem->ProcessNormalsFromRegion(testRegionBox, stepSize, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR); } + + TEST_F(TerrainSystemTest, TerrainProcessSurfaceWeightsFromRegion) + { + const AZ::Aabb spawnerBox = AZ::Aabb::CreateFromMinMaxValues(-10.0f, -10.0f, -5.0f, 10.0f, 10.0f, 15.0f); + auto entity = CreateAndActivateMockTerrainLayerSpawner( + spawnerBox, + [](AZ::Vector3& position, bool& terrainExists) + { + position.SetZ(1.0f); + terrainExists = true; + }); + + // Create and activate the terrain system with our testing defaults for world bounds, and a query resolution at 1 meter intervals. + const AZ::Vector2 queryResolution(1.0f); + auto terrainSystem = CreateAndActivateTerrainSystem(queryResolution); + + const AZ::Aabb testRegionBox = AZ::Aabb::CreateFromMinMaxValues(-3.0f, -3.0f, -1.0f, 3.0f, 3.0f, 1.0f); + const AZ::Vector2 stepSize(1.0f); + + const SurfaceData::SurfaceTag tag1 = SurfaceData::SurfaceTag("tag1"); + const SurfaceData::SurfaceTag tag2 = SurfaceData::SurfaceTag("tag2"); + const SurfaceData::SurfaceTag tag3 = SurfaceData::SurfaceTag("tag3"); + + AzFramework::SurfaceData::SurfaceTagWeight tagWeight1; + tagWeight1.m_surfaceType = tag1; + tagWeight1.m_weight = 1.0f; + + AzFramework::SurfaceData::SurfaceTagWeight tagWeight2; + tagWeight2.m_surfaceType = tag2; + tagWeight2.m_weight = 0.7f; + + AzFramework::SurfaceData::SurfaceTagWeight tagWeight3; + tagWeight3.m_surfaceType = tag3; + tagWeight3.m_weight = 0.3f; + + NiceMock mockSurfaceRequests(entity->GetId()); + ON_CALL(mockSurfaceRequests, GetSurfaceWeights).WillByDefault( + [&tagWeight1, &tagWeight2, &tagWeight3](const AZ::Vector3& position, AzFramework::SurfaceData::SurfaceTagWeightList& surfaceWeights) + { + surfaceWeights.clear(); + float absYPos = fabsf(position.GetY()); + if (absYPos < 1.0f) + { + surfaceWeights.push_back(tagWeight1); + } + else if(absYPos < 2.0f) + { + surfaceWeights.push_back(tagWeight2); + } + else + { + surfaceWeights.push_back(tagWeight3); + } + } + ); + + auto perPositionCallback = [&tagWeight1, &tagWeight2, &tagWeight3](size_t xIndex, size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + constexpr float epsilon = 0.0001f; + float absYPos = fabsf(surfacePoint.m_position.GetY()); + if (absYPos < 1.0f) + { + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight1.m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight1.m_weight, epsilon); + } + else if(absYPos < 2.0f) + { + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight2.m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight2.m_weight, epsilon); + } + else + { + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight3.m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight3.m_weight, epsilon); + } + }; + + terrainSystem->ProcessSurfaceWeightsFromRegion(testRegionBox, stepSize, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR); + } + + TEST_F(TerrainSystemTest, TerrainProcessSurfacePointsFromRegion) + { + const AZ::Aabb spawnerBox = AZ::Aabb::CreateFromMinMaxValues(-10.0f, -10.0f, -5.0f, 10.0f, 10.0f, 15.0f); + auto entity = CreateAndActivateMockTerrainLayerSpawner( + spawnerBox, + [](AZ::Vector3& position, bool& terrainExists) + { + position.SetZ(position.GetX() + position.GetY()); + terrainExists = true; + }); + + // Create and activate the terrain system with our testing defaults for world bounds, and a query resolution at 1 meter intervals. + const AZ::Vector2 queryResolution(1.0f); + auto terrainSystem = CreateAndActivateTerrainSystem(queryResolution); + + const AZ::Aabb testRegionBox = AZ::Aabb::CreateFromMinMaxValues(-3.0f, -3.0f, -1.0f, 3.0f, 3.0f, 1.0f); + const AZ::Vector2 stepSize(1.0f); + + const SurfaceData::SurfaceTag tag1 = SurfaceData::SurfaceTag("tag1"); + const SurfaceData::SurfaceTag tag2 = SurfaceData::SurfaceTag("tag2"); + const SurfaceData::SurfaceTag tag3 = SurfaceData::SurfaceTag("tag3"); + + AzFramework::SurfaceData::SurfaceTagWeight tagWeight1; + tagWeight1.m_surfaceType = tag1; + tagWeight1.m_weight = 1.0f; + + AzFramework::SurfaceData::SurfaceTagWeight tagWeight2; + tagWeight2.m_surfaceType = tag2; + tagWeight2.m_weight = 0.7f; + + AzFramework::SurfaceData::SurfaceTagWeight tagWeight3; + tagWeight3.m_surfaceType = tag3; + tagWeight3.m_weight = 0.3f; + + NiceMock mockSurfaceRequests(entity->GetId()); + ON_CALL(mockSurfaceRequests, GetSurfaceWeights).WillByDefault( + [&tagWeight1, &tagWeight2, &tagWeight3](const AZ::Vector3& position, AzFramework::SurfaceData::SurfaceTagWeightList& surfaceWeights) + { + surfaceWeights.clear(); + float absYPos = fabsf(position.GetY()); + if (absYPos < 1.0f) + { + surfaceWeights.push_back(tagWeight1); + } + else if(absYPos < 2.0f) + { + surfaceWeights.push_back(tagWeight2); + } + else + { + surfaceWeights.push_back(tagWeight3); + } + } + ); + + auto perPositionCallback = [&tagWeight1, &tagWeight2, &tagWeight3](size_t xIndex, size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + constexpr float epsilon = 0.0001f; + float expectedHeight = surfacePoint.m_position.GetX() + surfacePoint.m_position.GetY(); + + EXPECT_NEAR(surfacePoint.m_position.GetZ(), expectedHeight, epsilon); + + float absYPos = fabsf(surfacePoint.m_position.GetY()); + if (absYPos < 1.0f) + { + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight1.m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight1.m_weight, epsilon); + } + else if(absYPos < 2.0f) + { + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight2.m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight2.m_weight, epsilon); + } + else + { + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight3.m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight3.m_weight, epsilon); + } + }; + + terrainSystem->ProcessSurfacePointsFromRegion(testRegionBox, stepSize, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT); + } } // namespace UnitTest From 8fa04400308138ae9af64c396380a3ee2718d60b Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 14 Jan 2022 16:59:26 -0800 Subject: [PATCH 03/11] Update TerrainPhysicsColliderTests to add mocks for the ProcessRegion functions since the TerrainPhysicsColliderComponent now uses the ProcessRegion functions Signed-off-by: amzn-sj --- .../Tests/TerrainPhysicsColliderTests.cpp | 96 ++++++++++++++++--- 1 file changed, 84 insertions(+), 12 deletions(-) diff --git a/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp b/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp index 340acfbaac..859e618983 100644 --- a/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp +++ b/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp @@ -238,6 +238,33 @@ TEST_F(TerrainPhysicsColliderComponentTest, TerrainPhysicsColliderGetHeightsRetu AZ::Vector2 mockHeightResolution = AZ::Vector2(1.0f); NiceMock terrainListener; ON_CALL(terrainListener, GetTerrainHeightQueryResolution).WillByDefault(Return(mockHeightResolution)); + ON_CALL(terrainListener, ProcessHeightsFromRegion).WillByDefault( + [](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) + { + if (!perPositionCallback) + { + return; + } + + const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (size_t y = 0; y < numSamplesY; y++) + { + float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); + for (size_t x = 0; x < numSamplesX; x++) + { + bool terrainExists = false; + float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); + surfacePoint.m_position.Set(fx, fy, 0.0f); + perPositionCallback(x, y, surfacePoint, terrainExists); + } + } + } + ); int32_t cols, rows; Physics::HeightfieldProviderRequestsBus::Event( @@ -271,8 +298,34 @@ TEST_F(TerrainPhysicsColliderComponentTest, TerrainPhysicsColliderReturnsRelativ AZ::Vector2 mockHeightResolution = AZ::Vector2(1.0f); NiceMock terrainListener; - ON_CALL(terrainListener, GetHeightFromFloats).WillByDefault(Return(mockHeight)); ON_CALL(terrainListener, GetTerrainHeightQueryResolution).WillByDefault(Return(mockHeightResolution)); + ON_CALL(terrainListener, ProcessHeightsFromRegion).WillByDefault( + [mockHeight](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) + { + if (!perPositionCallback) + { + return; + } + + const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (size_t y = 0; y < numSamplesY; y++) + { + float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); + for (size_t x = 0; x < numSamplesX; x++) + { + bool terrainExists = false; + float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); + surfacePoint.m_position.Set(fx, fy, mockHeight); + perPositionCallback(x, y, surfacePoint, terrainExists); + } + } + } + ); // Just return the bounds as setup. This is equivalent to the box being at the origin. NiceMock boxShape(m_entity->GetId()); @@ -416,20 +469,39 @@ TEST_F(TerrainPhysicsColliderComponentTest, TerrainPhysicsColliderGetHeightsAndM NiceMock terrainListener; ON_CALL(terrainListener, GetTerrainHeightQueryResolution).WillByDefault(Return(mockHeightResolution)); - ON_CALL(terrainListener, GetHeightFromFloats).WillByDefault(Return(mockHeight)); - ON_CALL(terrainListener, GetMaxSurfaceWeightFromFloats) - .WillByDefault( - [return1, return2]( - [[maybe_unused]] float x, [[maybe_unused]] float y, - [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter, [[maybe_unused]] bool* terrainExistsPtr) + ON_CALL(terrainListener, ProcessSurfacePointsFromRegion).WillByDefault( + [mockHeight, return1, return2](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) + { + if (!perPositionCallback) { - // return tag1 for the first half of the rows, tag2 for the rest. - if (y < 128.0) + return; + } + + const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (size_t y = 0; y < numSamplesY; y++) + { + float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); + for (size_t x = 0; x < numSamplesX; x++) { - return return1; + surfacePoint.m_surfaceTags.clear(); + bool terrainExists = false; + float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); + surfacePoint.m_position.Set(fx, fy, mockHeight); + if (fy < 128.0) + { + surfacePoint.m_surfaceTags.push_back(return1); + } + surfacePoint.m_surfaceTags.push_back(return2); + perPositionCallback(x, y, surfacePoint, terrainExists); } - return return2; - }); + } + } + ); AZStd::vector heightsAndMaterials; From f05ca0897e0a180123ebb172a5d7bf23ad8eeda1 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Sat, 15 Jan 2022 14:26:58 -0800 Subject: [PATCH 04/11] Fix some warnings and remove an unused function parameter Signed-off-by: amzn-sj --- .../Source/Components/TerrainPhysicsColliderComponent.cpp | 2 +- .../Source/Components/TerrainWorldDebuggerComponent.cpp | 6 +++--- .../Code/Source/Components/TerrainWorldDebuggerComponent.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp index 4a8b4680b3..c74a478dad 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp @@ -344,7 +344,7 @@ namespace Terrain AZStd::vector materialList = GetMaterialList(); auto perPositionCallback = [&heightMaterials, &materialList, this, worldCenterZ, worldHeightBoundsMin, worldHeightBoundsMax] - (size_t xIndex, size_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, bool terrainExists) + ([[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, bool terrainExists) { float height = surfacePoint.m_position.GetZ(); diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp index 46be621307..f684727d33 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp @@ -297,7 +297,7 @@ namespace Terrain { if (sector.m_isDirty) { - RebuildSectorWireframe(sector, heightDataResolution, worldMinZ); + RebuildSectorWireframe(sector, heightDataResolution); } if (!sector.m_lineVertices.empty()) @@ -317,7 +317,7 @@ namespace Terrain } - void TerrainWorldDebuggerComponent::RebuildSectorWireframe(WireframeSector& sector, const AZ::Vector2& gridResolution, float worldMinZ) + void TerrainWorldDebuggerComponent::RebuildSectorWireframe(WireframeSector& sector, const AZ::Vector2& gridResolution) { if (!sector.m_isDirty) { @@ -354,7 +354,7 @@ namespace Terrain // For each terrain height value in the region, create the _| grid lines for that point and cache off the height value // for use with subsequent grid line calculations. auto ProcessHeightValue = [gridResolution, &previousHeight, &rowHeights, §or] - (uint32_t xIndex, uint32_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + (size_t xIndex, size_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) { // Don't add any vertices for the first column or first row. These grid lines will be handled by an adjacent sector, if // there is one. diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.h b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.h index f3bcead8c3..cb308effe6 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.h @@ -93,7 +93,7 @@ namespace Terrain bool m_isDirty{ true }; }; - void RebuildSectorWireframe(WireframeSector& sector, const AZ::Vector2& gridResolution, float worldMinZ); + void RebuildSectorWireframe(WireframeSector& sector, const AZ::Vector2& gridResolution); void MarkDirtySectors(const AZ::Aabb& dirtyRegion); void DrawWorldBounds(AzFramework::DebugDisplayRequests& debugDisplay); void DrawWireframe(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay); From 392d08e2f0272c3bbe62207124e6664fb4c77a4e Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Mon, 17 Jan 2022 17:09:30 -0800 Subject: [PATCH 05/11] Update Terrain renderer code to use the ProcessRegion API functions instead of the Get* functions Signed-off-by: amzn-sj --- .../TerrainDetailMaterialManager.cpp | 76 ++++++++++--------- .../TerrainFeatureProcessor.cpp | 33 ++++---- 2 files changed, 58 insertions(+), 51 deletions(-) diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp index 2bc9e42bff..1f43b476a1 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp @@ -751,50 +751,56 @@ namespace Terrain pixels.resize((quadrantWorldArea.m_max.m_x - quadrantWorldArea.m_min.m_x) * (quadrantWorldArea.m_max.m_y - quadrantWorldArea.m_min.m_y)); uint32_t index = 0; - for (int yPos = quadrantWorldArea.m_min.m_y; yPos < quadrantWorldArea.m_max.m_y; ++yPos) + auto perPositionCallback = [this, &pixels, &index]( + [[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, + [[maybe_unused]] bool terrainExists) { - for (int xPos = quadrantWorldArea.m_min.m_x; xPos < quadrantWorldArea.m_max.m_x; ++xPos) + // Store the top two surface weights in the texture with m_blend storing the relative weight. + bool isFirstMaterial = true; + float firstWeight = 0.0f; + AZ::Vector2 position(surfacePoint.m_position.GetX(), surfacePoint.m_position.GetY()); + for (const auto& surfaceTagWeight : surfacePoint.m_surfaceTags) { - AZ::Vector2 position = AZ::Vector2(xPos * DetailTextureScale, yPos * DetailTextureScale); - AzFramework::SurfaceData::SurfaceTagWeightList surfaceWeights; - AzFramework::Terrain::TerrainDataRequestBus::Broadcast(&AzFramework::Terrain::TerrainDataRequests::GetSurfaceWeightsFromVector2, position, surfaceWeights, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, nullptr); - - // Store the top two surface weights in the texture with m_blend storing the relative weight. - bool isFirstMaterial = true; - float firstWeight = 0.0f; - for (const auto& surfaceTagWeight : surfaceWeights) + if (surfaceTagWeight.m_weight > 0.0f) { - if (surfaceTagWeight.m_weight > 0.0f) + AZ::Crc32 surfaceType = surfaceTagWeight.m_surfaceType; + uint16_t materialId = GetDetailMaterialForSurfaceTypeAndPosition(surfaceType, position); + if (materialId != m_detailMaterials.NoFreeSlot && materialId < 255) { - AZ::Crc32 surfaceType = surfaceTagWeight.m_surfaceType; - uint16_t materialId = GetDetailMaterialForSurfaceTypeAndPosition(surfaceType, position); - if (materialId != m_detailMaterials.NoFreeSlot && materialId < 255) + if (isFirstMaterial) { - if (isFirstMaterial) - { - pixels.at(index).m_material1 = aznumeric_cast(materialId); - firstWeight = surfaceTagWeight.m_weight; - // m_blend only needs to be calculated is material 2 is found, otherwise the initial value of 0 is correct. - isFirstMaterial = false; - } - else - { - pixels.at(index).m_material2 = aznumeric_cast(materialId); - float totalWeight = firstWeight + surfaceTagWeight.m_weight; - float blendWeight = 1.0f - (firstWeight / totalWeight); - pixels.at(index).m_blend = aznumeric_cast(AZStd::round(blendWeight * 255.0f)); - break; - } + pixels.at(index).m_material1 = aznumeric_cast(materialId); + firstWeight = surfaceTagWeight.m_weight; + // m_blend only needs to be calculated is material 2 is found, otherwise the initial value of 0 is correct. + isFirstMaterial = false; + } + else + { + pixels.at(index).m_material2 = aznumeric_cast(materialId); + float totalWeight = firstWeight + surfaceTagWeight.m_weight; + float blendWeight = 1.0f - (firstWeight / totalWeight); + pixels.at(index).m_blend = aznumeric_cast(AZStd::round(blendWeight * 255.0f)); + break; } } - else - { - break; // since the list is ordered, no other materials are in the list with positive weights. - } } - ++index; + else + { + break; // since the list is ordered, no other materials are in the list with positive weights. + } } - } + ++index; + }; + + AZ::Vector3 worldMin(quadrantWorldArea.m_min.m_x * DetailTextureScale, quadrantWorldArea.m_min.m_y * DetailTextureScale, 0.0f); + AZ::Vector3 worldMax(quadrantWorldArea.m_max.m_x * DetailTextureScale, quadrantWorldArea.m_max.m_y * DetailTextureScale, 0.0f); + AZ::Vector2 stepSize(DetailTextureScale); + AZ::Aabb region; + region.Set(worldMin, worldMax); + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast(&AzFramework::Terrain::TerrainDataRequests::ProcessSurfaceWeightsFromRegion, + region, stepSize, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT); const int32_t left = quadrantTextureArea.m_min.m_x; const int32_t top = quadrantTextureArea.m_min.m_y; diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp index 351c34308a..ebc8a16fcb 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp @@ -226,25 +226,26 @@ namespace Terrain auto& surfaceDataContext = SurfaceData::SurfaceDataSystemRequestBus::GetOrCreateContext(false); typename SurfaceData::SurfaceDataSystemRequestBus::Context::DispatchLockGuard scopeLock(surfaceDataContext.m_contextMutex); - for (int32_t y = yStart; y < yEnd; y++) + auto perPositionCallback = [this, &pixels] + ([[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, + [[maybe_unused]] bool terrainExists) { - for (int32_t x = xStart; x < xEnd; x++) - { - bool terrainExists = true; - float terrainHeight = 0.0f; - float xPos = x * m_sampleSpacing; - float yPos = y * m_sampleSpacing; - AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( - terrainHeight, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats, - xPos, yPos, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists); + const float clampedHeight = AZ::GetClamp((surfacePoint.m_position.GetZ() - m_terrainBounds.GetMin().GetZ()) / m_terrainBounds.GetExtents().GetZ(), 0.0f, 1.0f); + const float expandedHeight = AZStd::roundf(clampedHeight * AZStd::numeric_limits::max()); + const uint16_t uint16Height = aznumeric_cast(expandedHeight); - const float clampedHeight = AZ::GetClamp((terrainHeight - m_terrainBounds.GetMin().GetZ()) / m_terrainBounds.GetExtents().GetZ(), 0.0f, 1.0f); - const float expandedHeight = AZStd::roundf(clampedHeight * AZStd::numeric_limits::max()); - const uint16_t uint16Height = aznumeric_cast(expandedHeight); + pixels.push_back(uint16Height); + }; - pixels.push_back(uint16Height); - } - } + AZ::Vector2 stepSize(m_sampleSpacing); + AZ::Vector3 maxBound( + m_dirtyRegion.GetMax().GetX() + m_sampleSpacing, m_dirtyRegion.GetMax().GetY() + m_sampleSpacing, 0.0f); + AZ::Aabb region; + region.Set(m_dirtyRegion.GetMin(), maxBound); + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequests::ProcessHeightsFromRegion, + region, stepSize, perPositionCallback,AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT); } if (m_heightmapImage) From 4b5f4042f201c35c94f1a60c82975342670972d9 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Wed, 19 Jan 2022 16:05:51 -0800 Subject: [PATCH 06/11] Move common code used by multiple tests into functions to reduce code duplication. Signed-off-by: amzn-sj --- .../Tests/TerrainPhysicsColliderTests.cpp | 117 ++++++-------- Gems/Terrain/Code/Tests/TerrainSystemTest.cpp | 149 ++++++++---------- 2 files changed, 111 insertions(+), 155 deletions(-) diff --git a/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp b/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp index 859e618983..2d0933c367 100644 --- a/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp +++ b/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp @@ -69,6 +69,46 @@ protected: m_colliderComponent = m_entity->CreateComponent(Terrain::TerrainPhysicsColliderConfig()); m_app.RegisterComponentDescriptor(m_colliderComponent->CreateDescriptor()); } + + void ProcessRegionLoop(const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter, + AzFramework::SurfaceData::SurfaceTagWeightList* surfaceTags, + float mockHeight) + { + if (!perPositionCallback) + { + return; + } + + const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (size_t y = 0; y < numSamplesY; y++) + { + float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); + for (size_t x = 0; x < numSamplesX; x++) + { + bool terrainExists = false; + float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); + surfacePoint.m_position.Set(fx, fy, mockHeight); + if (surfaceTags) + { + surfacePoint.m_surfaceTags.clear(); + if (fy < 128.0) + { + surfacePoint.m_surfaceTags.push_back(surfaceTags->at(0)); + } + else + { + surfacePoint.m_surfaceTags.push_back(surfaceTags->at(1)); + } + } + perPositionCallback(x, y, surfacePoint, terrainExists); + } + } + } }; TEST_F(TerrainPhysicsColliderComponentTest, ActivateEntityActivateSuccess) @@ -239,30 +279,11 @@ TEST_F(TerrainPhysicsColliderComponentTest, TerrainPhysicsColliderGetHeightsRetu NiceMock terrainListener; ON_CALL(terrainListener, GetTerrainHeightQueryResolution).WillByDefault(Return(mockHeightResolution)); ON_CALL(terrainListener, ProcessHeightsFromRegion).WillByDefault( - [](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, + [this](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) { - if (!perPositionCallback) - { - return; - } - - const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); - const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); - - AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (size_t y = 0; y < numSamplesY; y++) - { - float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); - for (size_t x = 0; x < numSamplesX; x++) - { - bool terrainExists = false; - float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); - surfacePoint.m_position.Set(fx, fy, 0.0f); - perPositionCallback(x, y, surfacePoint, terrainExists); - } - } + ProcessRegionLoop(inRegion, stepSize, perPositionCallback, sampleFilter, nullptr, 0.0f); } ); @@ -300,30 +321,11 @@ TEST_F(TerrainPhysicsColliderComponentTest, TerrainPhysicsColliderReturnsRelativ NiceMock terrainListener; ON_CALL(terrainListener, GetTerrainHeightQueryResolution).WillByDefault(Return(mockHeightResolution)); ON_CALL(terrainListener, ProcessHeightsFromRegion).WillByDefault( - [mockHeight](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, + [this, mockHeight](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) { - if (!perPositionCallback) - { - return; - } - - const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); - const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); - - AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (size_t y = 0; y < numSamplesY; y++) - { - float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); - for (size_t x = 0; x < numSamplesX; x++) - { - bool terrainExists = false; - float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); - surfacePoint.m_position.Set(fx, fy, mockHeight); - perPositionCallback(x, y, surfacePoint, terrainExists); - } - } + ProcessRegionLoop(inRegion, stepSize, perPositionCallback, sampleFilter, nullptr, mockHeight); } ); @@ -467,39 +469,16 @@ TEST_F(TerrainPhysicsColliderComponentTest, TerrainPhysicsColliderGetHeightsAndM return2.m_surfaceType = tag2; return2.m_weight = 1.0f; + AzFramework::SurfaceData::SurfaceTagWeightList surfaceTags = { return1, return2 }; + NiceMock terrainListener; ON_CALL(terrainListener, GetTerrainHeightQueryResolution).WillByDefault(Return(mockHeightResolution)); ON_CALL(terrainListener, ProcessSurfacePointsFromRegion).WillByDefault( - [mockHeight, return1, return2](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, + [this, mockHeight, &surfaceTags](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) { - if (!perPositionCallback) - { - return; - } - - const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); - const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); - - AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (size_t y = 0; y < numSamplesY; y++) - { - float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); - for (size_t x = 0; x < numSamplesX; x++) - { - surfacePoint.m_surfaceTags.clear(); - bool terrainExists = false; - float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); - surfacePoint.m_position.Set(fx, fy, mockHeight); - if (fy < 128.0) - { - surfacePoint.m_surfaceTags.push_back(return1); - } - surfacePoint.m_surfaceTags.push_back(return2); - perPositionCallback(x, y, surfacePoint, terrainExists); - } - } + ProcessRegionLoop(inRegion, stepSize, perPositionCallback, sampleFilter, &surfaceTags, mockHeight); } ); diff --git a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp index 2eebc1b824..ab0847e634 100644 --- a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp @@ -68,6 +68,7 @@ namespace UnitTest AZStd::unique_ptr> m_boxShapeRequests; AZStd::unique_ptr> m_shapeRequests; AZStd::unique_ptr> m_terrainAreaHeightRequests; + AZStd::unique_ptr> m_terrainAreaSurfaceRequests; void SetUp() override { @@ -84,6 +85,7 @@ namespace UnitTest m_boxShapeRequests.reset(); m_shapeRequests.reset(); m_terrainAreaHeightRequests.reset(); + m_terrainAreaSurfaceRequests.reset(); m_app.Destroy(); } @@ -160,6 +162,49 @@ namespace UnitTest ActivateEntity(entity.get()); return entity; } + + void SetupSurfaceWeightMocks(AZ::Entity* entity, AzFramework::SurfaceData::SurfaceTagWeightList& expectedTags) + { + const SurfaceData::SurfaceTag tag1 = SurfaceData::SurfaceTag("tag1"); + const SurfaceData::SurfaceTag tag2 = SurfaceData::SurfaceTag("tag2"); + const SurfaceData::SurfaceTag tag3 = SurfaceData::SurfaceTag("tag3"); + + AzFramework::SurfaceData::SurfaceTagWeight tagWeight1; + tagWeight1.m_surfaceType = tag1; + tagWeight1.m_weight = 1.0f; + expectedTags.push_back(tagWeight1); + + AzFramework::SurfaceData::SurfaceTagWeight tagWeight2; + tagWeight2.m_surfaceType = tag2; + tagWeight2.m_weight = 0.7f; + expectedTags.push_back(tagWeight2); + + AzFramework::SurfaceData::SurfaceTagWeight tagWeight3; + tagWeight3.m_surfaceType = tag3; + tagWeight3.m_weight = 0.3f; + expectedTags.push_back(tagWeight3); + + m_terrainAreaSurfaceRequests = AZStd::make_unique>(entity->GetId()); + ON_CALL(*m_terrainAreaSurfaceRequests, GetSurfaceWeights).WillByDefault( + [tagWeight1, tagWeight2, tagWeight3](const AZ::Vector3& position, AzFramework::SurfaceData::SurfaceTagWeightList& surfaceWeights) + { + surfaceWeights.clear(); + float absYPos = fabsf(position.GetY()); + if (absYPos < 1.0f) + { + surfaceWeights.push_back(tagWeight1); + } + else if(absYPos < 2.0f) + { + surfaceWeights.push_back(tagWeight2); + } + else + { + surfaceWeights.push_back(tagWeight3); + } + } + ); + } }; TEST_F(TerrainSystemTest, TrivialCreateDestroy) @@ -921,62 +966,28 @@ namespace UnitTest const AZ::Aabb testRegionBox = AZ::Aabb::CreateFromMinMaxValues(-3.0f, -3.0f, -1.0f, 3.0f, 3.0f, 1.0f); const AZ::Vector2 stepSize(1.0f); - const SurfaceData::SurfaceTag tag1 = SurfaceData::SurfaceTag("tag1"); - const SurfaceData::SurfaceTag tag2 = SurfaceData::SurfaceTag("tag2"); - const SurfaceData::SurfaceTag tag3 = SurfaceData::SurfaceTag("tag3"); + AzFramework::SurfaceData::SurfaceTagWeightList expectedTags; + SetupSurfaceWeightMocks(entity.get(), expectedTags); - AzFramework::SurfaceData::SurfaceTagWeight tagWeight1; - tagWeight1.m_surfaceType = tag1; - tagWeight1.m_weight = 1.0f; - - AzFramework::SurfaceData::SurfaceTagWeight tagWeight2; - tagWeight2.m_surfaceType = tag2; - tagWeight2.m_weight = 0.7f; - - AzFramework::SurfaceData::SurfaceTagWeight tagWeight3; - tagWeight3.m_surfaceType = tag3; - tagWeight3.m_weight = 0.3f; - - NiceMock mockSurfaceRequests(entity->GetId()); - ON_CALL(mockSurfaceRequests, GetSurfaceWeights).WillByDefault( - [&tagWeight1, &tagWeight2, &tagWeight3](const AZ::Vector3& position, AzFramework::SurfaceData::SurfaceTagWeightList& surfaceWeights) - { - surfaceWeights.clear(); - float absYPos = fabsf(position.GetY()); - if (absYPos < 1.0f) - { - surfaceWeights.push_back(tagWeight1); - } - else if(absYPos < 2.0f) - { - surfaceWeights.push_back(tagWeight2); - } - else - { - surfaceWeights.push_back(tagWeight3); - } - } - ); - - auto perPositionCallback = [&tagWeight1, &tagWeight2, &tagWeight3](size_t xIndex, size_t yIndex, + auto perPositionCallback = [&expectedTags](size_t xIndex, size_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) { constexpr float epsilon = 0.0001f; float absYPos = fabsf(surfacePoint.m_position.GetY()); if (absYPos < 1.0f) { - EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight1.m_surfaceType); - EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight1.m_weight, epsilon); + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, expectedTags[0].m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, expectedTags[0].m_weight, epsilon); } else if(absYPos < 2.0f) { - EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight2.m_surfaceType); - EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight2.m_weight, epsilon); + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, expectedTags[1].m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, expectedTags[1].m_weight, epsilon); } else { - EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight3.m_surfaceType); - EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight3.m_weight, epsilon); + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, expectedTags[2].m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, expectedTags[2].m_weight, epsilon); } }; @@ -1001,44 +1012,10 @@ namespace UnitTest const AZ::Aabb testRegionBox = AZ::Aabb::CreateFromMinMaxValues(-3.0f, -3.0f, -1.0f, 3.0f, 3.0f, 1.0f); const AZ::Vector2 stepSize(1.0f); - const SurfaceData::SurfaceTag tag1 = SurfaceData::SurfaceTag("tag1"); - const SurfaceData::SurfaceTag tag2 = SurfaceData::SurfaceTag("tag2"); - const SurfaceData::SurfaceTag tag3 = SurfaceData::SurfaceTag("tag3"); + AzFramework::SurfaceData::SurfaceTagWeightList expectedTags; + SetupSurfaceWeightMocks(entity.get(), expectedTags); - AzFramework::SurfaceData::SurfaceTagWeight tagWeight1; - tagWeight1.m_surfaceType = tag1; - tagWeight1.m_weight = 1.0f; - - AzFramework::SurfaceData::SurfaceTagWeight tagWeight2; - tagWeight2.m_surfaceType = tag2; - tagWeight2.m_weight = 0.7f; - - AzFramework::SurfaceData::SurfaceTagWeight tagWeight3; - tagWeight3.m_surfaceType = tag3; - tagWeight3.m_weight = 0.3f; - - NiceMock mockSurfaceRequests(entity->GetId()); - ON_CALL(mockSurfaceRequests, GetSurfaceWeights).WillByDefault( - [&tagWeight1, &tagWeight2, &tagWeight3](const AZ::Vector3& position, AzFramework::SurfaceData::SurfaceTagWeightList& surfaceWeights) - { - surfaceWeights.clear(); - float absYPos = fabsf(position.GetY()); - if (absYPos < 1.0f) - { - surfaceWeights.push_back(tagWeight1); - } - else if(absYPos < 2.0f) - { - surfaceWeights.push_back(tagWeight2); - } - else - { - surfaceWeights.push_back(tagWeight3); - } - } - ); - - auto perPositionCallback = [&tagWeight1, &tagWeight2, &tagWeight3](size_t xIndex, size_t yIndex, + auto perPositionCallback = [&expectedTags](size_t xIndex, size_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) { constexpr float epsilon = 0.0001f; @@ -1049,18 +1026,18 @@ namespace UnitTest float absYPos = fabsf(surfacePoint.m_position.GetY()); if (absYPos < 1.0f) { - EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight1.m_surfaceType); - EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight1.m_weight, epsilon); + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, expectedTags[0].m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, expectedTags[0].m_weight, epsilon); } else if(absYPos < 2.0f) { - EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight2.m_surfaceType); - EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight2.m_weight, epsilon); + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, expectedTags[1].m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, expectedTags[1].m_weight, epsilon); } else { - EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, tagWeight3.m_surfaceType); - EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, tagWeight3.m_weight, epsilon); + EXPECT_EQ(surfacePoint.m_surfaceTags[0].m_surfaceType, expectedTags[2].m_surfaceType); + EXPECT_NEAR(surfacePoint.m_surfaceTags[0].m_weight, expectedTags[2].m_weight, epsilon); } }; From 7bba4172ece3aa4d44c9ac1970d7e8c667fc582a Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Wed, 19 Jan 2022 18:04:56 -0800 Subject: [PATCH 07/11] Add a GetNumSamplesFromRegion function which returns the number of samples given a region and step size. Update Terrain Feature Processor to use this function to get the number of samples instead of computing num samples independently. Signed-off-by: amzn-sj --- .../Terrain/TerrainDataRequestBus.h | 4 ++++ .../Mocks/Terrain/MockTerrainDataRequestBus.h | 2 ++ .../TerrainFeatureProcessor.cpp | 24 +++++++++++-------- .../Source/TerrainSystem/TerrainSystem.cpp | 10 ++++++++ .../Code/Source/TerrainSystem/TerrainSystem.h | 4 ++++ 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h index 0d16bf3460..9379485646 100644 --- a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h +++ b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h @@ -161,6 +161,10 @@ namespace AzFramework SurfacePointListFillCallback perPositionCallback, Sampler sampleFilter = Sampler::DEFAULT) const = 0; + //! Returns the number of samples for a given region and step size. + virtual AZStd::pair GetNumSamplesFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize) const = 0; + //! Given a region(aabb) and a step size, call the provided callback function with surface data corresponding to the //! coordinates in the region. virtual void ProcessHeightsFromRegion(const AZ::Aabb& inRegion, diff --git a/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h b/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h index f3a6cc07b3..52ac28ef63 100644 --- a/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h +++ b/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h @@ -92,6 +92,8 @@ namespace UnitTest ProcessSurfaceWeightsFromListOfVector2, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); MOCK_CONST_METHOD3( ProcessSurfacePointsFromListOfVector2, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); + MOCK_CONST_METHOD2( + GetNumSamplesFromRegion, AZStd::pair(const AZ::Aabb&, const AZ::Vector2&)); MOCK_CONST_METHOD4( ProcessHeightsFromRegion, void(const AZ::Aabb&, const AZ::Vector2&, AzFramework::Terrain::SurfacePointRegionFillCallback, Sampler)); MOCK_CONST_METHOD4( diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp index ebc8a16fcb..4232a37264 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp @@ -208,12 +208,21 @@ namespace Terrain } int32_t xStart = aznumeric_cast(AZStd::ceilf(m_dirtyRegion.GetMin().GetX() / m_sampleSpacing)); - int32_t xEnd = aznumeric_cast(AZStd::floorf(m_dirtyRegion.GetMax().GetX() / m_sampleSpacing)) + 1; int32_t yStart = aznumeric_cast(AZStd::ceilf(m_dirtyRegion.GetMin().GetY() / m_sampleSpacing)); - int32_t yEnd = aznumeric_cast(AZStd::floorf(m_dirtyRegion.GetMax().GetY() / m_sampleSpacing)) + 1; - uint32_t updateWidth = xEnd - xStart; - uint32_t updateHeight = yEnd - yStart; + AZ::Vector2 stepSize(m_sampleSpacing); + AZ::Vector3 maxBound( + m_dirtyRegion.GetMax().GetX() + m_sampleSpacing, m_dirtyRegion.GetMax().GetY() + m_sampleSpacing, 0.0f); + AZ::Aabb region; + region.Set(m_dirtyRegion.GetMin(), maxBound); + + AZStd::pair numSamples; + AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( + numSamples, &AzFramework::Terrain::TerrainDataRequests::GetNumSamplesFromRegion, + region, stepSize); + + uint32_t updateWidth = numSamples.first; + uint32_t updateHeight = numSamples.second; AZStd::vector pixels; pixels.reserve(updateWidth * updateHeight); { @@ -238,14 +247,9 @@ namespace Terrain pixels.push_back(uint16Height); }; - AZ::Vector2 stepSize(m_sampleSpacing); - AZ::Vector3 maxBound( - m_dirtyRegion.GetMax().GetX() + m_sampleSpacing, m_dirtyRegion.GetMax().GetY() + m_sampleSpacing, 0.0f); - AZ::Aabb region; - region.Set(m_dirtyRegion.GetMin(), maxBound); AzFramework::Terrain::TerrainDataRequestBus::Broadcast( &AzFramework::Terrain::TerrainDataRequests::ProcessHeightsFromRegion, - region, stepSize, perPositionCallback,AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT); + region, stepSize, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT); } if (m_heightmapImage) diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp index 2ecd13b5ad..4dfa03ed53 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp @@ -690,6 +690,16 @@ void TerrainSystem::ProcessSurfacePointsFromListOfVector2( } } +AZStd::pair TerrainSystem::GetNumSamplesFromRegion( + const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize) const +{ + const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + + return AZStd::make_pair(numSamplesX, numSamplesY); +} + void TerrainSystem::ProcessHeightsFromRegion( const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h index 7c6e0cd91e..2296d48843 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h @@ -163,6 +163,10 @@ namespace Terrain AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, Sampler sampleFilter = Sampler::DEFAULT) const override; + //! Returns the number of samples for a given region and step size. + virtual AZStd::pair GetNumSamplesFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize) const override; + //! Given a region(aabb) and a step size, call the provided callback function with surface data corresponding to the //! coordinates in the region. virtual void ProcessHeightsFromRegion(const AZ::Aabb& inRegion, From 3df7e239ac5e345b4b6815dee0eb56149b96d281 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 20 Jan 2022 09:32:42 -0800 Subject: [PATCH 08/11] Fix build error on PC Signed-off-by: amzn-sj --- .../Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp index 4232a37264..d9bdcb97bc 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp @@ -221,8 +221,8 @@ namespace Terrain numSamples, &AzFramework::Terrain::TerrainDataRequests::GetNumSamplesFromRegion, region, stepSize); - uint32_t updateWidth = numSamples.first; - uint32_t updateHeight = numSamples.second; + uint32_t updateWidth = static_cast(numSamples.first); + uint32_t updateHeight = static_cast(numSamples.second); AZStd::vector pixels; pixels.reserve(updateWidth * updateHeight); { From 0a722b5a0616f6bf919f8644880333e522dd3f36 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 20 Jan 2022 09:48:15 -0800 Subject: [PATCH 09/11] Update comment for clarity Signed-off-by: amzn-sj --- Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h index 2296d48843..3e489730d0 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h @@ -163,7 +163,8 @@ namespace Terrain AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, Sampler sampleFilter = Sampler::DEFAULT) const override; - //! Returns the number of samples for a given region and step size. + //! Returns the number of samples for a given region and step size. The first and second + //! elements of the pair correspond to the X and Y sample counts respectively. virtual AZStd::pair GetNumSamplesFromRegion(const AZ::Aabb& inRegion, const AZ::Vector2& stepSize) const override; From d6cdd1d053bc5abbea00dec0e4396b2fb0efb0b1 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 20 Jan 2022 09:51:38 -0800 Subject: [PATCH 10/11] Update another comment Signed-off-by: amzn-sj --- .../AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h index 9379485646..8b29f2a554 100644 --- a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h +++ b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h @@ -161,7 +161,8 @@ namespace AzFramework SurfacePointListFillCallback perPositionCallback, Sampler sampleFilter = Sampler::DEFAULT) const = 0; - //! Returns the number of samples for a given region and step size. + //! Returns the number of samples for a given region and step size. The first and second + //! elements of the pair correspond to the X and Y sample counts respectively. virtual AZStd::pair GetNumSamplesFromRegion(const AZ::Aabb& inRegion, const AZ::Vector2& stepSize) const = 0; From 8e08e42c86bf9ae30263065c1b5bff93ee832ae6 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 20 Jan 2022 11:01:00 -0800 Subject: [PATCH 11/11] Fix some warnings about unused parameters Signed-off-by: amzn-sj --- .../Code/Tests/TerrainPhysicsColliderTests.cpp | 13 ++++++------- Gems/Terrain/Code/Tests/TerrainSystemTest.cpp | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp b/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp index 2d0933c367..dc43544f05 100644 --- a/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp +++ b/Gems/Terrain/Code/Tests/TerrainPhysicsColliderTests.cpp @@ -72,7 +72,6 @@ protected: void ProcessRegionLoop(const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, - AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter, AzFramework::SurfaceData::SurfaceTagWeightList* surfaceTags, float mockHeight) { @@ -281,9 +280,9 @@ TEST_F(TerrainPhysicsColliderComponentTest, TerrainPhysicsColliderGetHeightsRetu ON_CALL(terrainListener, ProcessHeightsFromRegion).WillByDefault( [this](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, - AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) + [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) { - ProcessRegionLoop(inRegion, stepSize, perPositionCallback, sampleFilter, nullptr, 0.0f); + ProcessRegionLoop(inRegion, stepSize, perPositionCallback, nullptr, 0.0f); } ); @@ -323,9 +322,9 @@ TEST_F(TerrainPhysicsColliderComponentTest, TerrainPhysicsColliderReturnsRelativ ON_CALL(terrainListener, ProcessHeightsFromRegion).WillByDefault( [this, mockHeight](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, - AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) + [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) { - ProcessRegionLoop(inRegion, stepSize, perPositionCallback, sampleFilter, nullptr, mockHeight); + ProcessRegionLoop(inRegion, stepSize, perPositionCallback, nullptr, mockHeight); } ); @@ -476,9 +475,9 @@ TEST_F(TerrainPhysicsColliderComponentTest, TerrainPhysicsColliderGetHeightsAndM ON_CALL(terrainListener, ProcessSurfacePointsFromRegion).WillByDefault( [this, mockHeight, &surfaceTags](const AZ::Aabb& inRegion, const AZ::Vector2& stepSize, AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, - AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) + [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) { - ProcessRegionLoop(inRegion, stepSize, perPositionCallback, sampleFilter, &surfaceTags, mockHeight); + ProcessRegionLoop(inRegion, stepSize, perPositionCallback, &surfaceTags, mockHeight); } ); diff --git a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp index ab0847e634..ddccdbc49c 100644 --- a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp @@ -969,7 +969,7 @@ namespace UnitTest AzFramework::SurfaceData::SurfaceTagWeightList expectedTags; SetupSurfaceWeightMocks(entity.get(), expectedTags); - auto perPositionCallback = [&expectedTags](size_t xIndex, size_t yIndex, + auto perPositionCallback = [&expectedTags]([[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) { constexpr float epsilon = 0.0001f; @@ -1015,7 +1015,7 @@ namespace UnitTest AzFramework::SurfaceData::SurfaceTagWeightList expectedTags; SetupSurfaceWeightMocks(entity.get(), expectedTags); - auto perPositionCallback = [&expectedTags](size_t xIndex, size_t yIndex, + auto perPositionCallback = [&expectedTags]([[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) { constexpr float epsilon = 0.0001f;