diff --git a/src/Partition.h b/src/Partition.h index 5598205..9aa3e7c 100644 --- a/src/Partition.h +++ b/src/Partition.h @@ -43,7 +43,6 @@ typedef std::unordered_map DictOfBalls; typedef std::vector VectorOfBalls; typedef std::vector VectorOfStaticCollidables; typedef std::pair DictEntry; -typedef std::unordered_map> MapOfBoxes; typedef std::vector VectorOfBoxes; typedef std::back_insert_iterator< VectorOfBoxes > BoxVectorInsertor; @@ -80,12 +79,6 @@ class Key if (iz > k.iz) return false; return n()((ix<<3) + (iy<<2) + (iz<<1) + n); - } - - int64_t ix; int64_t iy; int64_t iz; @@ -108,6 +101,27 @@ class Key } }; +struct KeyHash +{ + size_t operator()(const Key& key) const noexcept + { + size_t seed = 0; + const auto combine = [&seed](int64_t value) + { + const size_t valueHash = std::hash{}(value); + seed ^= valueHash + static_cast(0x9e3779b9U) + (seed << 6) + (seed >> 2); + }; + + combine(key.ix); + combine(key.iy); + combine(key.iz); + combine(key.n); + return seed; + } +}; + +typedef std::unordered_map MapOfBoxes; + class Partition { @@ -204,4 +218,4 @@ class Partition BoxAllocator mBoxAllocator; }; -#endif \ No newline at end of file +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f46edd4..d5ce201 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,6 +12,7 @@ target_sources(DestinyTest PRIVATE TestAABB.cpp TestBoxShape.cpp TestCollision.cpp + TestPartition.cpp TestPlane.cpp TestTriangle.cpp TestVector3d.cpp diff --git a/tests/TestPartition.cpp b/tests/TestPartition.cpp new file mode 100644 index 0000000..95ba5a2 --- /dev/null +++ b/tests/TestPartition.cpp @@ -0,0 +1,44 @@ +// Copyright © 2026 CCP ehf. + +#include "StdAfx.h" + +TEST(PartitionKeyHash, SeparatesCoordinatesThatPreviouslyCollided) +{ + const Key first(1, 0, 0, 16); + const Key second(0, 2, 0, 16); + + // The previous linear hash produced 24 for both keys: + // (1 << 3) + 16 == (2 << 2) + 16. + EXPECT_NE(KeyHash{}(first), KeyHash{}(second)); +} + +TEST(PartitionKeyHash, RetainsEveryDistinctBoxKey) +{ + MapOfBoxes boxes; + constexpr int gridSize = 16; + + for (int64_t ix = 0; ix < gridSize; ++ix) + { + for (int64_t iy = 0; iy < gridSize; ++iy) + { + for (int64_t iz = 0; iz < gridSize; ++iz) + { + boxes.emplace(Key(ix, iy, iz, gridSize), nullptr); + } + } + } + + EXPECT_EQ(boxes.size(), static_cast(gridSize * gridSize * gridSize)); + + for (int64_t ix = 0; ix < gridSize; ++ix) + { + for (int64_t iy = 0; iy < gridSize; ++iy) + { + for (int64_t iz = 0; iz < gridSize; ++iz) + { + const auto found = boxes.find(Key(ix, iy, iz, gridSize)); + ASSERT_NE(found, boxes.end()); + } + } + } +}