From ab84a43a8338bec430ad404025e1d7cdb8898af5 Mon Sep 17 00:00:00 2001 From: pruiksma Date: Tue, 25 May 2021 21:34:53 -0500 Subject: [PATCH 1/3] 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); + } + } + } From d4d533e6a87aa2065ba75abbc349373abc683fac Mon Sep 17 00:00:00 2001 From: pruiksma Date: Tue, 25 May 2021 21:39:34 -0500 Subject: [PATCH 2/3] Add comment to FillHaltonSequence --- Code/Framework/AzCore/AzCore/Math/Random.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Random.h b/Code/Framework/AzCore/AzCore/Math/Random.h index 52f054310f..c30bc4ddb6 100644 --- a/Code/Framework/AzCore/AzCore/Math/Random.h +++ b/Code/Framework/AzCore/AzCore/Math/Random.h @@ -126,7 +126,9 @@ namespace AZ m_offsets.fill(1); // Halton sequences start at index 1. m_increments.fill(1); // By default increment by 1 between each number. } - + + //! Fills a provided container from begin to end with a Halton sequence + //! Entries are expected to be, or implicitely convert to, AZStd::array template void FillHaltonSequence(Iterator begin, Iterator end) { From 19249371508bd24fd754db755084b4328f3e59ec Mon Sep 17 00:00:00 2001 From: pruiksma Date: Wed, 26 May 2021 13:05:07 -0500 Subject: [PATCH 3/3] Fixes from PR review --- Code/Framework/AzCore/AzCore/Math/Random.h | 10 +++++----- Code/Framework/AzCore/Tests/Math/RandomTests.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Random.h b/Code/Framework/AzCore/AzCore/Math/Random.h index c30bc4ddb6..8b2763df50 100644 --- a/Code/Framework/AzCore/AzCore/Math/Random.h +++ b/Code/Framework/AzCore/AzCore/Math/Random.h @@ -127,9 +127,9 @@ namespace AZ m_increments.fill(1); // By default increment by 1 between each number. } - //! Fills a provided container from begin to end with a Halton sequence - //! Entries are expected to be, or implicitely convert to, AZStd::array - template + //! Fills a provided container from begin to end with a Halton sequence. + //! Entries are expected to be, or implicitly converted to, AZStd::array. + template void FillHaltonSequence(Iterator begin, Iterator end) { AZStd::array indices = m_offsets; @@ -149,7 +149,7 @@ namespace AZ AZStd::generate(begin, end, f); } - //! Returns a Halton sequence in an array of N length + //! Returns a Halton sequence in an array of N length. template AZStd::array, N> GetHaltonSequence() { @@ -159,7 +159,7 @@ namespace AZ } //! Sets the offsets per dimension to start generating a sequence from. - //! By default, there is no offset (offset of 0 corresponds to starting at index 1) + //! By default, there is no offset (offset of 0 corresponds to starting at index 1). void SetOffsets(AZStd::array offsets) { m_offsets = offsets; diff --git a/Code/Framework/AzCore/Tests/Math/RandomTests.cpp b/Code/Framework/AzCore/Tests/Math/RandomTests.cpp index 95b92d21fe..7fe3acff54 100644 --- a/Code/Framework/AzCore/Tests/Math/RandomTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/RandomTests.cpp @@ -103,7 +103,7 @@ namespace UnitTest AZStd::array ownedContainer; sequence.FillHaltonSequence(ownedContainer.begin(), ownedContainer.end()); - for (uint32_t i = 0; i < regularSequence.size(); ++i) + for (size_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);