#include "vf/RandomTick.h" #include "vf/Chunk.h" namespace vf { namespace { uint64_t mix64(uint64_t x) { x += 0x9e3779b97f4a7c15ull; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ull; x = (x ^ (x >> 27)) * 0x94d049bb133111ebull; return x ^ (x >> 31); } uint64_t fold(uint64_t acc, uint64_t value) { return mix64(acc ^ (mix64(value) + 0x9e3779b97f4a7c15ull + (acc << 6) + (acc >> 2))); } uint64_t asBits(int v) { return static_cast(static_cast(v)); } } // namespace RandomTick::RandomTick(uint32_t worldSeed, int ticksPerChunk) : seed(worldSeed), ticks(ticksPerChunk < 0 ? 0 : ticksPerChunk) {} uint64_t RandomTick::hash(const Vec3i& chunkCoord, long long tick, uint32_t index) const { uint64_t h = mix64(static_cast(seed) + 0x100000001b3ull); h = fold(h, asBits(chunkCoord.x)); h = fold(h, asBits(chunkCoord.y)); h = fold(h, asBits(chunkCoord.z)); h = fold(h, static_cast(tick)); h = fold(h, static_cast(index)); return h; } void RandomTick::sampleLocal(const Vec3i& chunkCoord, long long tick, std::vector& out) const { out.clear(); out.reserve(static_cast(ticks)); for (int i = 0; i < ticks; ++i) { uint64_t h = hash(chunkCoord, tick, static_cast(i)); int x = static_cast((h & 0xffffull) % static_cast(chunkSize)); int y = static_cast(((h >> 21) & 0xffffull) % static_cast(chunkSize)); int z = static_cast(((h >> 42) & 0xffffull) % static_cast(chunkSize)); out.push_back(Vec3i{x, y, z}); } } std::vector RandomTick::sampleLocal(const Vec3i& chunkCoord, long long tick) const { std::vector out; sampleLocal(chunkCoord, tick, out); return out; } void RandomTick::sampleGlobal(const Vec3i& chunkCoord, long long tick, std::vector& out) const { sampleLocal(chunkCoord, tick, out); for (Vec3i& cell : out) { cell.x += chunkCoord.x * chunkSize; cell.y += chunkCoord.y * chunkSize; cell.z += chunkCoord.z * chunkSize; } } std::vector RandomTick::sampleGlobal(const Vec3i& chunkCoord, long long tick) const { std::vector out; sampleGlobal(chunkCoord, tick, out); return out; } } // namespace vf