Toast Engine
Loading...
Searching...
No Matches
fracture_random.hpp
Go to the documentation of this file.
1
7
8#pragma once
9
10#include "body.hpp"
11#include "shape.hpp"
12
13#include <glm/glm.hpp>
14#include <numbers>
15#include <toast/hash.hpp>
17
18namespace physics {
19
20enum class FractureStream : uint8_t {
21 edge_noise = 1,
22 shatter_points = 2,
23 granular = 3,
24 debris = 4,
25 edge_lobes = 6,
26 core_split = 7,
27};
28
29[[nodiscard]]
30constexpr auto streamSeed(uint64_t seed, FractureStream stream) noexcept -> uint64_t {
31 toast::hashCombine(seed, static_cast<uint64_t>(stream));
32 return seed;
33}
34
35[[nodiscard]]
36constexpr auto unitFloat(uint64_t bits) noexcept -> float {
37 // this function takes the main 24 bits from a u64 number and converts it
38 // to a floating point number on the range [0, 1]
39 return static_cast<float>(bits >> 40) * 0x1.0p-24f;
40}
41
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};
47}
48
49[[nodiscard]]
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));
54 return seed;
55}
56
57[[nodiscard]]
58inline auto fractureSeed(BodyID source, ShapeID shape, glm::vec3 local_point, uint64_t tick) noexcept -> uint64_t {
59 // calculates the seed of one hit
60 uint64_t seed = 0;
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;
66}
67
68[[nodiscard]]
69constexpr auto hash01(uint64_t seed, glm::ivec3 cell) noexcept -> float {
70 return unitFloat(hashCell(seed, cell));
71}
72
73[[nodiscard]]
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));
77}
78
79[[nodiscard]]
80inline auto valueNoise3(uint64_t seed, glm::vec3 p) noexcept -> float {
81 // trilinear of the random
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));
86
87#define LARP(a, b, c) std::lerp(a, b, c)
88
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);
95
96#undef LARP
97}
98
99struct Rng {
100 uint64_t state = 0;
101
102 explicit constexpr Rng(uint64_t seed) noexcept : state(seed) { }
103
104 constexpr auto next() noexcept -> uint64_t {
105 state += toast::k_golden_gamma;
106 return toast::splitmix64(state);
107 }
108
109 constexpr auto uniform() noexcept -> float { return unitFloat(next()); }
110
111 constexpr auto range(float lo, float hi) noexcept -> float { return lo + ((hi - lo) * uniform()); }
112
113 constexpr auto below(uint32_t count) noexcept -> uint32_t { return static_cast<uint32_t>(((next() >> 32) * count) >> 32); }
114
115 constexpr auto chance(float probability) noexcept -> bool { return uniform() < probability; }
116
117 auto direction() noexcept -> glm::vec3 {
118 uint64_t bits = next();
119 return sphereDirection(unitFloat(bits), unitFloat(bits << 24));
120 }
121};
122
123}
Body identifiers, creation data, and copied runtime state.
Shape identifiers, geometry, and runtime records.
Definition body.hpp:20
Definition shape.hpp:29