diff --git a/Gems/SurfaceData/Code/CMakeLists.txt b/Gems/SurfaceData/Code/CMakeLists.txt index 54363d265e..860053ca42 100644 --- a/Gems/SurfaceData/Code/CMakeLists.txt +++ b/Gems/SurfaceData/Code/CMakeLists.txt @@ -18,9 +18,10 @@ ly_add_target( Include BUILD_DEPENDENCIES PRIVATE - Legacy::CryCommon Gem::LmbrCentral PUBLIC + AZ::AzCore + AZ::AzFramework Gem::Atom_RPI.Public Gem::Atom_Feature_Common.Static ) @@ -37,7 +38,6 @@ ly_add_target( Include BUILD_DEPENDENCIES PRIVATE - Legacy::CryCommon Gem::SurfaceData.Static Gem::LmbrCentral RUNTIME_DEPENDENCIES @@ -66,7 +66,6 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) Include BUILD_DEPENDENCIES PRIVATE - Legacy::CryCommon AZ::AzToolsFramework Gem::SurfaceData.Static Gem::LmbrCentral.Editor @@ -97,7 +96,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) BUILD_DEPENDENCIES PRIVATE AZ::AzTest - Legacy::CryCommon Gem::SurfaceData.Static Gem::LmbrCentral ) diff --git a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataProviderRequestBus.h b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataProviderRequestBus.h index c6b9ba3390..b3c8667679 100644 --- a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataProviderRequestBus.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataProviderRequestBus.h @@ -30,6 +30,10 @@ namespace SurfaceData //! allows multiple threads to call using MutexType = AZStd::recursive_mutex; + //! Get all of the surface points that this provider has at the given input position. + //! @param inPosition - The input position to query. Only XY are guaranteed to be valid, Z should be ignored. + //! @param surfacePointList - The output list of surface points generated, if any. Each provider is expected to + //! append to this list, not overwrite it. virtual void GetSurfacePoints(const AZ::Vector3& inPosition, SurfacePointList& surfacePointList) const = 0; }; diff --git a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataSystemRequestBus.h b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataSystemRequestBus.h index 709650f428..8dd3e02a53 100644 --- a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataSystemRequestBus.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataSystemRequestBus.h @@ -39,7 +39,7 @@ namespace SurfaceData // The input positions are chosen by starting at the min sides of inRegion and incrementing by stepSize. This method is inclusive // on the min sides of the AABB, and exclusive on the max sides (i.e. for a box of (0,0) - (4,4), the point (0,0) is included but (4,4) isn't). virtual void GetSurfacePointsFromRegion(const AZ::Aabb& inRegion, const AZ::Vector2 stepSize, const SurfaceTagVector& desiredTags, - SurfacePointListPerPosition& surfacePointListPerPosition) const = 0; + SurfacePointLists& surfacePointLists) const = 0; virtual SurfaceDataRegistryHandle RegisterSurfaceDataProvider(const SurfaceDataRegistryEntry& entry) = 0; virtual void UnregisterSurfaceDataProvider(const SurfaceDataRegistryHandle& handle) = 0; diff --git a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataTypes.h b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataTypes.h index 0adc208962..6d39efaa9f 100644 --- a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataTypes.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataTypes.h @@ -34,7 +34,7 @@ namespace SurfaceData }; using SurfacePointList = AZStd::vector; - using SurfacePointListPerPosition = AZStd::vector>; + using SurfacePointLists = AZStd::vector; struct SurfaceDataRegistryEntry { diff --git a/Gems/SurfaceData/Code/Include/SurfaceData/Tests/SurfaceDataTestMocks.h b/Gems/SurfaceData/Code/Include/SurfaceData/Tests/SurfaceDataTestMocks.h index 11171215f7..5e8acdc4c5 100644 --- a/Gems/SurfaceData/Code/Include/SurfaceData/Tests/SurfaceDataTestMocks.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/Tests/SurfaceDataTestMocks.h @@ -200,7 +200,7 @@ namespace UnitTest } void GetSurfacePointsFromRegion([[maybe_unused]] const AZ::Aabb& inRegion, [[maybe_unused]] const AZ::Vector2 stepSize, [[maybe_unused]] const SurfaceData::SurfaceTagVector& desiredTags, - [[maybe_unused]] SurfaceData::SurfacePointListPerPosition& surfacePointListPerPosition) const override + [[maybe_unused]] SurfaceData::SurfacePointLists& surfacePointListPerPosition) const override { } diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp index 9038d2f082..9c53b13fdc 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp +++ b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp @@ -195,12 +195,11 @@ namespace SurfaceData { const AZ::u32 entryAddress = entryPair.first; const SurfaceDataRegistryEntry& entry = entryPair.second; - AZ::Vector3 point2d(inPosition.GetX(), inPosition.GetY(), entry.m_bounds.GetMax().GetZ()); - if (!entry.m_bounds.IsValid() || entry.m_bounds.Contains(point2d)) + if (!entry.m_bounds.IsValid() || AabbContains2D(entry.m_bounds, inPosition)) { if (!hasDesiredTags || hasModifierTags || HasMatchingTags(desiredTags, entry.m_tags)) { - SurfaceDataProviderRequestBus::Event(entryAddress, &SurfaceDataProviderRequestBus::Events::GetSurfacePoints, point2d, surfacePointList); + SurfaceDataProviderRequestBus::Event(entryAddress, &SurfaceDataProviderRequestBus::Events::GetSurfacePoints, inPosition, surfacePointList); } } } @@ -212,8 +211,7 @@ namespace SurfaceData { const AZ::u32 entryAddress = entryPair.first; const SurfaceDataRegistryEntry& entry = entryPair.second; - AZ::Vector3 point2d(inPosition.GetX(), inPosition.GetY(), entry.m_bounds.GetMax().GetZ()); - if (!entry.m_bounds.IsValid() || entry.m_bounds.Contains(point2d)) + if (!entry.m_bounds.IsValid() || AabbContains2D(entry.m_bounds, inPosition)) { SurfaceDataModifierRequestBus::Event(entryAddress, &SurfaceDataModifierRequestBus::Events::ModifySurfacePoints, surfacePointList); } @@ -227,12 +225,19 @@ namespace SurfaceData } } - void SurfaceDataSystemComponent::GetSurfacePointsFromRegion(const AZ::Aabb& inRegion, const AZ::Vector2 stepSize, const SurfaceTagVector& desiredTags, SurfacePointListPerPosition& surfacePointListPerPosition) const + void SurfaceDataSystemComponent::GetSurfacePointsFromRegion(const AZ::Aabb& inRegion, const AZ::Vector2 stepSize, + const SurfaceTagVector& desiredTags, SurfacePointLists& surfacePointLists) const { AZStd::lock_guard registrationLock(m_registrationMutex); - surfacePointListPerPosition.clear(); - surfacePointListPerPosition.reserve(aznumeric_cast(ceil(inRegion.GetXExtent() / stepSize.GetX())) * aznumeric_cast(ceil(inRegion.GetYExtent() / stepSize.GetY()))); + const size_t totalQueryPositions = aznumeric_cast(ceil(inRegion.GetXExtent() / stepSize.GetX())) * + aznumeric_cast(ceil(inRegion.GetYExtent() / stepSize.GetY())); + + AZStd::vector inPositions; + inPositions.reserve(totalQueryPositions); + + surfacePointLists.clear(); + surfacePointLists.reserve(totalQueryPositions); // Initialize our list-per-position list with every input position to query from the region. // This is inclusive on the min sides of inRegion, and exclusive on the max sides. @@ -240,7 +245,8 @@ namespace SurfaceData { for (float x = inRegion.GetMin().GetX(); x < inRegion.GetMax().GetX(); x += stepSize.GetX()) { - surfacePointListPerPosition.emplace_back(AZ::Vector3(x, y, AZ::Constants::FloatMax), SurfaceData::SurfacePointList{}); + inPositions.emplace_back(AZ::Vector3(x, y, AZ::Constants::FloatMax)); + surfacePointLists.emplace_back(SurfaceData::SurfacePointList{}); } } @@ -259,14 +265,14 @@ namespace SurfaceData ( alwaysApplies || AabbOverlaps2D(entry.m_bounds, inRegion) ) ) { - for (auto& surfacePointListAndPoint : surfacePointListPerPosition) + for (size_t index = 0; index < totalQueryPositions; index++) { - const auto& point2d = surfacePointListAndPoint.first; - SurfacePointList& surfacePointList = surfacePointListAndPoint.second; - AZ::Vector3 point3d(point2d.GetX(), point2d.GetY(), entry.m_bounds.GetMax().GetZ()); - if (alwaysApplies || entry.m_bounds.Contains(point3d)) + const auto& inPosition = inPositions[index]; + SurfacePointList& surfacePointList = surfacePointLists[index]; + if (alwaysApplies || AabbContains2D(entry.m_bounds, inPosition)) { - SurfaceDataProviderRequestBus::Event(entryPair.first, &SurfaceDataProviderRequestBus::Events::GetSurfacePoints, point3d, surfacePointList); + SurfaceDataProviderRequestBus::Event( + entryPair.first, &SurfaceDataProviderRequestBus::Events::GetSurfacePoints, inPosition, surfacePointList); } } } @@ -284,14 +290,13 @@ namespace SurfaceData if (alwaysApplies || AabbOverlaps2D(entry.m_bounds, inRegion)) { - for (auto& surfacePointListAndPoint : surfacePointListPerPosition) + for (size_t index = 0; index < totalQueryPositions; index++) { - const auto& point2d = surfacePointListAndPoint.first; - SurfacePointList& surfacePointList = surfacePointListAndPoint.second; + const auto& inPosition = inPositions[index]; + SurfacePointList& surfacePointList = surfacePointLists[index]; if (!surfacePointList.empty()) { - AZ::Vector3 point3d(point2d.GetX(), point2d.GetY(), entry.m_bounds.GetMax().GetZ()); - if (alwaysApplies || entry.m_bounds.Contains(point3d)) + if (alwaysApplies || AabbContains2D(entry.m_bounds, inPosition)) { SurfaceDataModifierRequestBus::Event(entryPair.first, &SurfaceDataModifierRequestBus::Events::ModifySurfacePoints, surfacePointList); } @@ -304,9 +309,8 @@ namespace SurfaceData // same XY coordinates and extremely similar Z values. This produces results that are sorted in decreasing Z order. // Also, this filters out any remaining points that don't match the desired tag list. This can happen when a surface provider // doesn't add a desired tag, and a surface modifier has the *potential* to add it, but then doesn't. - for (auto& surfacePointListAndPoint : surfacePointListPerPosition) + for (auto& surfacePointList : surfacePointLists) { - auto& surfacePointList = surfacePointListAndPoint.second; if (!surfacePointList.empty()) { CombineSortAndFilterNeighboringPoints(surfacePointList, hasDesiredTags, desiredTags); diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h index 70c20b9643..c329103efb 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h +++ b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h @@ -39,7 +39,9 @@ namespace SurfaceData //////////////////////////////////////////////////////////////////////// // SurfaceDataSystemRequestBus implementation void GetSurfacePoints(const AZ::Vector3& inPosition, const SurfaceTagVector& desiredTags, SurfacePointList& surfacePointList) const override; - void GetSurfacePointsFromRegion(const AZ::Aabb& inRegion, const AZ::Vector2 stepSize, const SurfaceTagVector& desiredTags, SurfacePointListPerPosition& surfacePointListPerPosition) const override; + void GetSurfacePointsFromRegion( + const AZ::Aabb& inRegion, const AZ::Vector2 stepSize, const SurfaceTagVector& desiredTags, + SurfacePointLists& surfacePointListPerPosition) const override; SurfaceDataRegistryHandle RegisterSurfaceDataProvider(const SurfaceDataRegistryEntry& entry) override; void UnregisterSurfaceDataProvider(const SurfaceDataRegistryHandle& handle) override; diff --git a/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp b/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp index 9d182312a4..177abd3824 100644 --- a/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp +++ b/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp @@ -7,9 +7,6 @@ */ #include -#include -#include -#include #include #include @@ -26,28 +23,6 @@ #include #include -struct MockGlobalEnvironment -{ - MockGlobalEnvironment() - { - m_stubEnv.pCryPak = &m_stubPak; - m_stubEnv.pConsole = &m_stubConsole; - m_stubEnv.pSystem = &m_stubSystem; - gEnv = &m_stubEnv; - } - - ~MockGlobalEnvironment() - { - gEnv = nullptr; - } - -private: - SSystemGlobalEnvironment m_stubEnv; - testing::NiceMock m_stubPak; - testing::NiceMock m_stubConsole; - testing::NiceMock m_stubSystem; -}; - // Simple class for mocking out a surface provider, so that we can control exactly what points we expect to query in our tests. // This can be used to either provide a surface or modify a surface. class MockSurfaceProvider @@ -210,8 +185,6 @@ TEST(SurfaceDataTest, ComponentsWithComponentApplication) appDesc.m_recordingMode = AZ::Debug::AllocationRecords::RECORD_FULL; appDesc.m_stackRecordLevels = 20; - MockGlobalEnvironment mocks; - AZ::ComponentApplication app; AZ::Entity* systemEntity = app.Create(appDesc); ASSERT_TRUE(systemEntity != nullptr); @@ -259,18 +232,17 @@ public: m_application.Destroy(); } - bool ValidateRegionListSize(AZ::Aabb bounds, AZ::Vector2 stepSize, const SurfaceData::SurfacePointListPerPosition& outputList) + bool ValidateRegionListSize(AZ::Aabb bounds, AZ::Vector2 stepSize, const SurfaceData::SurfacePointLists& outputLists) { // We expect the output list to contain width * height output entries. // The right edge of the AABB should be treated as exclusive, so a 4x4 box with 1 step size will produce 16 entries (0, 1, 2, 3 on each dimension), // but a 4.1 x 4.1 box with 1 step size will produce 25 entries (0, 1, 2, 3, 4 on each dimension). - return (outputList.size() == aznumeric_cast(ceil(bounds.GetXExtent() * stepSize.GetX()) * ceil(bounds.GetYExtent() * stepSize.GetY()))); + return (outputLists.size() == aznumeric_cast(ceil(bounds.GetXExtent() * stepSize.GetX()) * ceil(bounds.GetYExtent() * stepSize.GetY()))); } AZ::ComponentApplication m_application; AZ::Entity* m_systemEntity; - MockGlobalEnvironment m_mocks; // Test Surface Data tags that we can use for testing query functionality const AZ::Crc32 m_testSurface1Crc = AZ::Crc32("test_surface1"); @@ -501,7 +473,7 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion) // Query for all the surface points from (0, 0, 16) - (4, 4, 16) with a step size of 1. // Note that the Z range is deliberately chosen to be outside the surface provider range to demonstrate // that it is ignored when selecting points. - SurfaceData::SurfacePointListPerPosition availablePointsPerPosition; + SurfaceData::SurfacePointLists availablePointsPerPosition; AZ::Vector2 stepSize(1.0f, 1.0f); AZ::Aabb regionBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f, 0.0f, 16.0f), AZ::Vector3(4.0f, 4.0f, 16.0f)); SurfaceData::SurfaceTagVector testTags = providerTags; @@ -513,19 +485,15 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion) EXPECT_TRUE(ValidateRegionListSize(regionBounds, stepSize, availablePointsPerPosition)); // We expect every entry in the output list to have two surface points, at heights 0 and 4, sorted in - // decreasing height order. The XY positions should match the query positions, and the masks list should - // be the same size as the set of masks the provider owns. We *could* check every mask as well for completeness, - // but that seems like overkill. - for (auto& queryPosition : availablePointsPerPosition) + // decreasing height order. The masks list should be the same size as the set of masks the provider owns. + // We *could* check every mask as well for completeness, but that seems like overkill. + for (auto& pointList : availablePointsPerPosition) { - const SurfaceData::SurfacePointList& pointList = queryPosition.second; EXPECT_TRUE(pointList.size() == 2); EXPECT_TRUE(pointList[0].m_position.GetZ() == 4.0f); EXPECT_TRUE(pointList[1].m_position.GetZ() == 0.0f); for (auto& point : pointList) { - EXPECT_TRUE(queryPosition.first.GetX() == point.m_position.GetX()); - EXPECT_TRUE(queryPosition.first.GetY() == point.m_position.GetY()); EXPECT_TRUE(point.m_masks.size() == providerTags.size()); } } @@ -543,7 +511,7 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_NoMatchingMas // Query for all the surface points from (0, 0, 0) - (4, 4, 4) with a step size of 1. // We only include a surface tag that does NOT exist in the surface provider. - SurfaceData::SurfacePointListPerPosition availablePointsPerPosition; + SurfaceData::SurfacePointLists availablePointsPerPosition; AZ::Vector2 stepSize(1.0f, 1.0f); AZ::Aabb regionBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f), AZ::Vector3(4.0f)); SurfaceData::SurfaceTagVector testTags = { SurfaceData::SurfaceTag(m_testSurfaceNoMatchCrc) }; @@ -558,7 +526,7 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_NoMatchingMas // any of the masks from our mock surface provider. for (auto& queryPosition : availablePointsPerPosition) { - EXPECT_TRUE(queryPosition.second.size() == 0); + EXPECT_TRUE(queryPosition.size() == 0); } } @@ -573,7 +541,7 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_NoMatchingReg AZ::Vector3(0.0f), AZ::Vector3(8.0f), AZ::Vector3(0.25f, 0.25f, 4.0f)); // Query for all the surface points from (16, 16) - (20, 20) with a step size of 1. - SurfaceData::SurfacePointListPerPosition availablePointsPerPosition; + SurfaceData::SurfacePointLists availablePointsPerPosition; AZ::Vector2 stepSize(1.0f, 1.0f); AZ::Aabb regionBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(16.0f), AZ::Vector3(20.0f)); SurfaceData::SurfaceTagVector testTags = providerTags; @@ -586,9 +554,8 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_NoMatchingReg // We expect every entry in the output list to have no surface points, since the input points don't overlap with // our surface provider. - for (auto& queryPosition : availablePointsPerPosition) + for (auto& pointList : availablePointsPerPosition) { - const SurfaceData::SurfacePointList& pointList = queryPosition.second; EXPECT_TRUE(pointList.size() == 0); } } @@ -626,7 +593,7 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_ProviderModif for (auto& tagTest : tagTests) { - SurfaceData::SurfacePointListPerPosition availablePointsPerPosition; + SurfaceData::SurfacePointLists availablePointsPerPosition; AZ::Vector2 stepSize(1.0f, 1.0f); AZ::Aabb regionBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f), AZ::Vector3(4.0f)); SurfaceData::SurfaceTagVector testTags = tagTest; @@ -639,9 +606,8 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_ProviderModif // We expect every entry in the output list to have two surface points (with heights 0 and 4), // and each point should have both the "test_surface1" and "test_surface2" tag. - for (auto& queryPosition : availablePointsPerPosition) + for (auto& pointList : availablePointsPerPosition) { - const SurfaceData::SurfacePointList& pointList = queryPosition.second; EXPECT_TRUE(pointList.size() == 2); for (auto& point : pointList) { @@ -673,7 +639,7 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_SimilarPoints // Query for all the surface points from (0, 0) - (4, 4) with a step size of 1. - SurfaceData::SurfacePointListPerPosition availablePointsPerPosition; + SurfaceData::SurfacePointLists availablePointsPerPosition; AZ::Vector2 stepSize(1.0f, 1.0f); AZ::Aabb regionBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f), AZ::Vector3(4.0f)); SurfaceData::SurfaceTagVector testTags = { SurfaceData::SurfaceTag(m_testSurface1Crc), SurfaceData::SurfaceTag(m_testSurface2Crc) }; @@ -686,9 +652,8 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_SimilarPoints // We expect every entry in the output list to have two surface points, not four. The two points // should have both surface tags on them. - for (auto& queryPosition : availablePointsPerPosition) + for (auto& pointList : availablePointsPerPosition) { - const SurfaceData::SurfacePointList& pointList = queryPosition.second; EXPECT_TRUE(pointList.size() == 2); for (auto& point : pointList) { @@ -718,7 +683,7 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_DissimilarPoi // Query for all the surface points from (0, 0) - (4, 4) with a step size of 1. - SurfaceData::SurfacePointListPerPosition availablePointsPerPosition; + SurfaceData::SurfacePointLists availablePointsPerPosition; AZ::Vector2 stepSize(1.0f, 1.0f); AZ::Aabb regionBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f), AZ::Vector3(4.0f)); SurfaceData::SurfaceTagVector testTags = { SurfaceData::SurfaceTag(m_testSurface1Crc), SurfaceData::SurfaceTag(m_testSurface2Crc) }; @@ -731,9 +696,8 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_DissimilarPoi // We expect every entry in the output list to have four surface points with one tag each, // because the points are far enough apart that they won't merge. - for (auto& queryPosition : availablePointsPerPosition) + for (auto& pointList : availablePointsPerPosition) { - const SurfaceData::SurfacePointList& pointList = queryPosition.second; EXPECT_TRUE(pointList.size() == 4); for (auto& point : pointList) { diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp index dbaae0118a..03011db2f3 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp @@ -146,41 +146,38 @@ namespace Terrain void TerrainSurfaceDataSystemComponent::GetSurfacePoints( const AZ::Vector3& inPosition, SurfaceData::SurfacePointList& surfacePointList) const { - if (m_terrainBoundsIsValid) + if (!m_terrainBoundsIsValid) { - auto enumerationCallback = [&](AzFramework::Terrain::TerrainDataRequests* terrain) -> bool - { - if (terrain->GetTerrainAabb().Contains(inPosition)) - { - bool isTerrainValidAtPoint = false; - AzFramework::SurfaceData::SurfacePoint terrainSurfacePoint; - terrain->GetSurfacePoint( - inPosition, terrainSurfacePoint, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR, - &isTerrainValidAtPoint); - - const bool isHole = !isTerrainValidAtPoint; - - SurfaceData::SurfacePoint point; - point.m_entityId = GetEntityId(); - point.m_position = terrainSurfacePoint.m_position; - point.m_normal = terrainSurfacePoint.m_normal; - - // Always add a "terrain" or "terrainHole" tag. - const AZ::Crc32 terrainTag = isHole ? Constants::s_terrainHoleTagCrc : Constants::s_terrainTagCrc; - SurfaceData::AddMaxValueForMasks(point.m_masks, terrainTag, 1.0f); - - // Add all of the surface tags that the terrain has at this point. - for (auto& tag : terrainSurfacePoint.m_surfaceTags) - { - SurfaceData::AddMaxValueForMasks(point.m_masks, tag.m_surfaceType, tag.m_weight); - } - surfacePointList.push_back(point); - } - // Only one handler should exist. - return false; - }; - AzFramework::Terrain::TerrainDataRequestBus::EnumerateHandlers(enumerationCallback); + return; } + + bool isTerrainValidAtPoint = false; + AzFramework::SurfaceData::SurfacePoint terrainSurfacePoint; + AzFramework::Terrain::TerrainDataRequestBus::Broadcast(&AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfacePoint, + inPosition, terrainSurfacePoint, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR, + &isTerrainValidAtPoint); + + const bool isHole = !isTerrainValidAtPoint; + + SurfaceData::SurfacePoint point; + point.m_entityId = GetEntityId(); + point.m_position = terrainSurfacePoint.m_position; + point.m_normal = terrainSurfacePoint.m_normal; + + // Preallocate enough space for all of our terrain's surface tags, plus the default "terrain" / "terrainHole" tag. + point.m_masks.reserve(terrainSurfacePoint.m_surfaceTags.size() + 1); + + // Add all of the surface tags that the terrain has at this point. + for (auto& tag : terrainSurfacePoint.m_surfaceTags) + { + point.m_masks[tag.m_surfaceType] = tag.m_weight; + } + + // Always add a "terrain" or "terrainHole" tag. + const AZ::Crc32 terrainTag = isHole ? Constants::s_terrainHoleTagCrc : Constants::s_terrainTagCrc; + point.m_masks[terrainTag] = 1.0f; + + surfacePointList.push_back(point); } AZ::Aabb TerrainSurfaceDataSystemComponent::GetSurfaceAabb() const diff --git a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp index e497fcec12..9cd9c1a7cb 100644 --- a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp @@ -1099,7 +1099,7 @@ namespace Vegetation // 0 = lower left corner, 0.5 = center const float texelOffset = (sectorPointSnapMode == SnapMode::Center) ? 0.5f : 0.0f; - SurfaceData::SurfacePointListPerPosition availablePointsPerPosition; + SurfaceData::SurfacePointLists availablePointsPerPosition; AZ::Vector2 stepSize(vegStep, vegStep); AZ::Vector3 regionOffset(texelOffset * vegStep, texelOffset * vegStep, 0.0f); AZ::Aabb regionBounds = sectorInfo.m_bounds; @@ -1127,7 +1127,7 @@ namespace Vegetation uint claimIndex = 0; for (auto& availablePoints : availablePointsPerPosition) { - for (auto& surfacePoint : availablePoints.second) + for (auto& surfacePoint : availablePoints) { sectorInfo.m_baseContext.m_availablePoints.push_back(); ClaimPoint& claimPoint = sectorInfo.m_baseContext.m_availablePoints.back(); diff --git a/Gems/Vegetation/Code/Tests/VegetationMocks.h b/Gems/Vegetation/Code/Tests/VegetationMocks.h index a3bd80392d..8a8bfe6b76 100644 --- a/Gems/Vegetation/Code/Tests/VegetationMocks.h +++ b/Gems/Vegetation/Code/Tests/VegetationMocks.h @@ -341,7 +341,7 @@ namespace UnitTest } void GetSurfacePointsFromRegion([[maybe_unused]] const AZ::Aabb& inRegion, [[maybe_unused]] const AZ::Vector2 stepSize, [[maybe_unused]] const SurfaceData::SurfaceTagVector& desiredTags, - [[maybe_unused]] SurfaceData::SurfacePointListPerPosition& surfacePointListPerPosition) const override + [[maybe_unused]] SurfaceData::SurfacePointLists& surfacePointListPerPosition) const override { }