15#include <toast/hash.hpp>
20enum class FractureStream : uint8_t {
30constexpr auto streamSeed(uint64_t seed, FractureStream stream)
noexcept -> uint64_t {
31 toast::hashCombine(seed,
static_cast<uint64_t
>(stream));
36constexpr auto unitFloat(uint64_t bits)
noexcept ->
float {
39 return static_cast<float>(bits >> 40) * 0x1.0p-24f;
42inline auto sphereDirection(
float u,
float v)
noexcept -> glm::vec3 {
43 float z = (u * 2.0f) - 1.0f;
44 float ring = std::sqrt(glm::max(1.0f - (z * z), 0.0f));
45 float phi = v * 2.0f * std::numbers::pi_v<float>;
46 return {ring * std::cos(phi), ring * std::sin(phi), z};
50constexpr auto hashCell(uint64_t seed, glm::ivec3 cell)
noexcept -> uint64_t {
51 toast::hashCombine(seed,
static_cast<uint64_t
>(cell.x));
52 toast::hashCombine(seed,
static_cast<uint64_t
>(cell.y));
53 toast::hashCombine(seed,
static_cast<uint64_t
>(cell.z));
58inline auto fractureSeed(
BodyID source,
ShapeID shape, glm::vec3 local_point, uint64_t tick)
noexcept -> uint64_t {
61 toast::hashCombine(seed, (
static_cast<uint64_t
>(source.generation) << 32) | source.slot);
62 toast::hashCombine(seed, (
static_cast<uint64_t
>(shape.generation) << 32) | source.slot);
63 seed = hashCell(seed, glm::ivec3(glm::floor(local_point / voxel::k_voxel_size)));
64 toast::hashCombine(seed, tick);
65 return seed != 0 ? seed : 1;
69constexpr auto hash01(uint64_t seed, glm::ivec3 cell)
noexcept ->
float {
70 return unitFloat(hashCell(seed, cell));
74inline auto hashUnit3(uint64_t seed, uint64_t index)
noexcept -> glm::vec3 {
75 toast::hashCombine(seed, index);
76 return sphereDirection(unitFloat(seed), unitFloat(seed << 24));
80inline auto valueNoise3(uint64_t seed, glm::vec3 p)
noexcept ->
float {
82 glm::vec3 base = glm::floor(p);
83 glm::ivec3 cell = {base};
84 glm::vec3 t = p - base;
85 glm::vec3 w = t * t * (3.0f - (2.0f * t));
87#define LARP(a, b, c) std::lerp(a, b, c)
89 auto at = [&](
int x,
int y,
int z) {
return hash01(seed, cell + glm::ivec3 {x, y, z}); };
90 float x00 = LARP(at(0, 0, 0), at(1, 0, 0), w.x);
91 float x01 = LARP(at(0, 1, 0), at(1, 1, 0), w.x);
92 float x10 = LARP(at(0, 0, 1), at(1, 0, 1), w.x);
93 float x11 = LARP(at(0, 1, 1), at(1, 1, 1), w.x);
94 return LARP(LARP(x00, x10, w.y), LARP(x01, x11, w.y), w.z);
102 explicit constexpr Rng(uint64_t seed) noexcept : state(seed) { }
104 constexpr auto next()
noexcept -> uint64_t {
105 state += toast::k_golden_gamma;
106 return toast::splitmix64(state);
109 constexpr auto uniform()
noexcept ->
float {
return unitFloat(next()); }
111 constexpr auto range(
float lo,
float hi)
noexcept ->
float {
return lo + ((hi - lo) * uniform()); }
113 constexpr auto below(uint32_t count)
noexcept -> uint32_t {
return static_cast<uint32_t
>(((next() >> 32) * count) >> 32); }
115 constexpr auto chance(
float probability)
noexcept ->
bool {
return uniform() < probability; }
117 auto direction()
noexcept -> glm::vec3 {
118 uint64_t bits = next();
119 return sphereDirection(unitFloat(bits), unitFloat(bits << 24));
Body identifiers, creation data, and copied runtime state.
Shape identifiers, geometry, and runtime records.