From ab84a43a8338bec430ad404025e1d7cdb8898af5 Mon Sep 17 00:00:00 2001 From: pruiksma Date: Tue, 25 May 2021 21:34:53 -0500 Subject: [PATCH] Update to HaltonSequence to make it easier to fill your own custom structures with halton sequences. --- Code/Framework/AzCore/AzCore/Math/Random.h | 19 +++++--- .../AzCore/Tests/Math/RandomTests.cpp | 48 +++++++++++++++++-- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Random.h b/Code/Framework/AzCore/AzCore/Math/Random.h index 8b28f6aaad..52f054310f 100644 --- a/Code/Framework/AzCore/AzCore/Math/Random.h +++ b/Code/Framework/AzCore/AzCore/Math/Random.h @@ -127,16 +127,13 @@ namespace AZ m_increments.fill(1); // By default increment by 1 between each number. } - //! Returns a Halton sequence in an array of N length - template - AZStd::array, N> GetHaltonSequence() + template + void FillHaltonSequence(Iterator begin, Iterator end) { - AZStd::array, N> result; - AZStd::array indices = m_offsets; // Generator that returns the Halton number for all bases for a single entry. - auto f = [&] () + auto f = [&]() { AZStd::array item; for (auto d = 0; d < Dimensions; ++d) @@ -147,7 +144,15 @@ namespace AZ return item; }; - AZStd::generate(result.begin(), result.end(), f); + AZStd::generate(begin, end, f); + } + + //! Returns a Halton sequence in an array of N length + template + AZStd::array, N> GetHaltonSequence() + { + AZStd::array, N> result; + FillHaltonSequence(result.begin(), result.end()); return result; } diff --git a/Code/Framework/AzCore/Tests/Math/RandomTests.cpp b/Code/Framework/AzCore/Tests/Math/RandomTests.cpp index ace7d99704..95b92d21fe 100644 --- a/Code/Framework/AzCore/Tests/Math/RandomTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/RandomTests.cpp @@ -24,7 +24,7 @@ namespace UnitTest EXPECT_FLOAT_EQ(5981.0f / 15625.0f, GetHaltonNumber(4321, 5)); } - TEST(MATH_Random, HaltonSequence) + TEST(MATH_Random, HaltonSequenceStandard) { HaltonSequence<3> sequence({ 2, 3, 5 }); auto regularSequence = sequence.GetHaltonSequence<5>(); @@ -48,7 +48,11 @@ namespace UnitTest EXPECT_FLOAT_EQ(5.0f / 8.0f, regularSequence[4][0]); EXPECT_FLOAT_EQ(7.0f / 9.0f, regularSequence[4][1]); EXPECT_FLOAT_EQ(1.0f / 25.0f, regularSequence[4][2]); - + } + + TEST(MATH_Random, HaltonSequenceOffsets) + { + HaltonSequence<3> sequence({ 2, 3, 5 }); sequence.SetOffsets({ 1, 2, 3 }); auto offsetSequence = sequence.GetHaltonSequence<2>(); @@ -59,10 +63,15 @@ namespace UnitTest EXPECT_FLOAT_EQ(3.0f / 4.0f, offsetSequence[1][0]); EXPECT_FLOAT_EQ(4.0f / 9.0f, offsetSequence[1][1]); EXPECT_FLOAT_EQ(1.0f / 25.0f, offsetSequence[1][2]); - + } + + TEST(MATH_Random, HaltonSequenceIncrements) + { + HaltonSequence<3> sequence({ 2, 3, 5 }); + sequence.SetOffsets({ 1, 2, 3 }); sequence.SetIncrements({ 1, 2, 3 }); auto incrementedSequence = sequence.GetHaltonSequence<2>(); - + EXPECT_FLOAT_EQ(1.0f / 4.0f, incrementedSequence[0][0]); EXPECT_FLOAT_EQ(1.0f / 9.0f, incrementedSequence[0][1]); EXPECT_FLOAT_EQ(4.0f / 5.0f, incrementedSequence[0][2]); @@ -71,4 +80,35 @@ namespace UnitTest EXPECT_FLOAT_EQ(7.0f / 9.0f, incrementedSequence[1][1]); EXPECT_FLOAT_EQ(11.0f / 25.0f, incrementedSequence[1][2]); } + + TEST(MATH_Random, FillHaltonSequence) + { + HaltonSequence<3> sequence({ 2, 3, 5 }); + auto regularSequence = sequence.GetHaltonSequence<5>(); + + struct Point + { + Point() = default; + Point(AZStd::array arr) + :x(arr[0]) + ,y(arr[1]) + ,z(arr[2]) + {} + + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + }; + + AZStd::array ownedContainer; + sequence.FillHaltonSequence(ownedContainer.begin(), ownedContainer.end()); + + for (uint32_t i = 0; i < regularSequence.size(); ++i) + { + EXPECT_FLOAT_EQ(regularSequence[i][0], ownedContainer[i].x); + EXPECT_FLOAT_EQ(regularSequence[i][1], ownedContainer[i].y); + EXPECT_FLOAT_EQ(regularSequence[i][2], ownedContainer[i].z); + } + } + }