diff --git a/src/base/base_rand.c b/src/base/base_rand.c index cfac7143..15f5fa4b 100644 --- a/src/base/base_rand.c +++ b/src/base/base_rand.c @@ -1,44 +1,42 @@ -/* TODO: Use a value that gives good precision when dividing into range 0 -> 1 */ -#define F64_RAND_MAX U64Max +//////////////////////////////// +//~ True randomness #if PlatformIsWindows # define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081) u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags); -void rand_true(String buffer) +void TrueRand(String buffer) { BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0); } #else -# error rand_true not implemented for this platform +# error TrueRand not implemented for this platform #endif -/* ========================== * - * Stateful prng - * ========================== */ +//////////////////////////////// +//~ Stateful randomness -u64 rand_u64_from_state(RandState *state) +u64 RandU64FromState(RandState *state) { u64 seed = state->seed; if (seed == 0) { - rand_true(STRING_FROM_STRUCT(&seed)); + TrueRand(STRING_FROM_STRUCT(&seed)); state->seed = seed; } - return seed ^ rand_u64_from_seed(++state->counter); + return seed ^ RandU64FromSeed(++state->counter); } -f64 rand_f64_from_state(RandState *state, f64 range_start, f64 range_end) +f64 RandF64FromState(RandState *state, f64 range_start, f64 range_end) { - return range_start + (range_end - range_start) * ((f64)(rand_u64_from_state(state) % F64_RAND_MAX) / (f64)F64_RAND_MAX); + return range_start + (range_end - range_start) * ((f64)(RandU64FromState(state) % RandMaxF64) / (f64)RandMaxF64); } -/* ========================== * - * Seeded prng - * ========================== */ +//////////////////////////////// +//~ Seeded randomness - /* Based on Jon Maiga's "mx3" - * https://jonkagstrom.com/mx3/mx3_rev2.html - */ -u64 rand_u64_from_seed(u64 seed) +/* Based on Jon Maiga's "mx3" + * https://jonkagstrom.com/mx3/mx3_rev2.html + */ +u64 RandU64FromSeed(u64 seed) { seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d; seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d; @@ -47,12 +45,12 @@ u64 rand_u64_from_seed(u64 seed) return seed; } -u64 rand_u64_from_seeds(u64 seed_a, u64 seed_b) +u64 RandU64FromSeeds(u64 seed_a, u64 seed_b) { - return rand_u64_from_seed((seed_a * 3) + seed_b); + return RandU64FromSeed((seed_a * 3) + seed_b); } -f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end) +f64 RandF64FromSeed(u64 seed, f64 range_start, f64 range_end) { - return range_start + (range_end - range_start) * ((f64)(rand_u64_from_seed(seed) % F64_RAND_MAX) / (f64)F64_RAND_MAX); + return range_start + (range_end - range_start) * ((f64)(RandU64FromSeed(seed) % RandMaxF64) / (f64)RandMaxF64); } diff --git a/src/base/base_rand.h b/src/base/base_rand.h index 29b4e5d2..8fa3a4d4 100644 --- a/src/base/base_rand.h +++ b/src/base/base_rand.h @@ -1,14 +1,25 @@ +//////////////////////////////// +//~ Rand types + Struct(RandState) { - /* If a state's seed == 0 upon a call to a related function, it will be initialized using platform's true rng source */ - u64 seed; + u64 seed; /* If a state's seed == 0 upon a call to a related function, it will be initialized using platform's true rng source */ u64 counter; }; -void rand_true(String buffer); +/* TODO: Use a value that gives good precision when dividing into range 0 -> 1 */ +#define RandMaxF64 U64Max -u64 rand_u64_from_state(RandState *state); -f64 rand_f64_from_state(RandState *state, f64 range_start, f64 range_end); +//////////////////////////////// +//~ Rand operations -u64 rand_u64_from_seed(u64 seed); -u64 rand_u64_from_seeds(u64 seed_a, u64 seed_b); -f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end); +//- True randomness +void TrueRand(String buffer); + +//- Stateful randomness +u64 RandU64FromState(RandState *state); +f64 RandF64FromState(RandState *state, f64 range_start, f64 range_end); + +//- Seeded randomness +u64 RandU64FromSeed(u64 seed); +u64 RandU64FromSeeds(u64 seed_a, u64 seed_b); +f64 RandF64FromSeed(u64 seed, f64 range_start, f64 range_end); diff --git a/src/base/base_uid.c b/src/base/base_uid.c index d0ca9f23..c9b7d3bb 100644 --- a/src/base/base_uid.c +++ b/src/base/base_uid.c @@ -2,7 +2,7 @@ UID uid_true_rand(void) { UID res = ZI; - rand_true(STRING_FROM_STRUCT(&res)); + TrueRand(STRING_FROM_STRUCT(&res)); return res; } @@ -14,8 +14,8 @@ UID uid_combine(UID a, UID b) res.lo = (a.lo * 3) + b.lo; res.hi += res.lo; res.lo += res.hi; - res.hi = rand_u64_from_seed(res.hi); - res.lo = rand_u64_from_seed(res.lo); + res.hi = RandU64FromSeed(res.hi); + res.lo = RandU64FromSeed(res.lo); res.hi += res.lo; res.lo += res.hi; return res; diff --git a/src/gp/gp_core_dx12.c b/src/gp/gp_core_dx12.c index d2a9caf1..128002b1 100644 --- a/src/gp/gp_core_dx12.c +++ b/src/gp/gp_core_dx12.c @@ -2035,7 +2035,7 @@ internal struct command_descriptor_heap *command_list_push_descriptor_heap(struc internal u64 command_buffer_hash_from_size(u64 size) { - u64 hash = rand_u64_from_seed(size); + u64 hash = RandU64FromSeed(size); return hash; } @@ -3003,10 +3003,10 @@ G_Resource *gp_run_render(G_RenderSig *gp_render_sig, G_RenderParams params) sig.flags = K_UintFromU32(shade_flags); sig.tex_width = K_UintFromU32(render_size.x); sig.tex_height = K_UintFromU32(render_size.y); - sig.frame_seed = K_Uint4FromU32((u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF), - (u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF), - (u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF), - (u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF)); + sig.frame_seed = K_Uint4FromU32((u32)(RandU64FromState(&rsig->rand) & 0xFFFFFFFF), + (u32)(RandU64FromState(&rsig->rand) & 0xFFFFFFFF), + (u32)(RandU64FromState(&rsig->rand) & 0xFFFFFFFF), + (u32)(RandU64FromState(&rsig->rand) & 0xFFFFFFFF)); sig.frame_index = K_UintFromU32(rsig->frame_index); sig.camera_offset = K_Float2FromV2(world_to_render_xf.og); sig.albedo_tex_urid = K_UintFromU32(rsig->albedo->srv_descriptor->index); diff --git a/src/sim/sim_ent.c b/src/sim/sim_ent.c index 2ef5f29a..c1cf82a2 100644 --- a/src/sim/sim_ent.c +++ b/src/sim/sim_ent.c @@ -293,7 +293,7 @@ EntId sim_ent_tile_chunk_id_from_tile_chunk_index(Vec2I32 chunk_index) { EntId res = ZI; res.uid = SIM_ENT_TILE_CHUNK_BASIS_UID; - res.uid = uid_combine(res.uid, MakeUID(rand_u64_from_seed(chunk_index.x), rand_u64_from_seed(chunk_index.y))); + res.uid = uid_combine(res.uid, MakeUID(RandU64FromSeed(chunk_index.x), RandU64FromSeed(chunk_index.y))); return res; } diff --git a/src/sim/sim_step.c b/src/sim/sim_step.c index 6da9391b..d4d4ca10 100644 --- a/src/sim/sim_step.c +++ b/src/sim/sim_step.c @@ -270,9 +270,9 @@ internal void test_spawn_entities2(Ent *parent, Vec2 pos) /* FIXME: Remove this */ { static RandState rand = ZI; - f32 r = rand_f64_from_state(&rand, 1, 5); - f32 g = rand_f64_from_state(&rand, 1, 5); - f32 b = rand_f64_from_state(&rand, 1, 5); + f32 r = RandF64FromState(&rand, 1, 5); + f32 g = RandF64FromState(&rand, 1, 5); + f32 b = RandF64FromState(&rand, 1, 5); e->sprite_emittance = VEC3(r, g, b); e->sprite_tint = Rgba32F(r / 5, g / 5, b / 5, 1); } @@ -528,8 +528,8 @@ internal void test_generate_walls(Snapshot *world) Vec2I32 end = sim_world_tile_index_from_local_tile_index(chunk_index, VEC2I32(wall_end, tile_y)); struct wall_node *node = 0; if (wall_start == 0) { - u64 start_hash = rand_u64_from_seed(*(u64 *)&start); - start_hash = rand_u64_from_seeds(start_hash, wall_dir); + u64 start_hash = RandU64FromSeed(*(u64 *)&start); + start_hash = RandU64FromSeeds(start_hash, wall_dir); DictEntry *entry = dict_get_entry(horizontal_ends_dict, start_hash); if (entry) { /* Existing wall exists accross chunk boundary */ @@ -546,8 +546,8 @@ internal void test_generate_walls(Snapshot *world) } node->end = end; if (wall_end == SIM_TILES_PER_CHUNK_SQRT) { - u64 end_hash = rand_u64_from_seed(*(u64 *)&end); - end_hash = rand_u64_from_seeds(end_hash, wall_dir); + u64 end_hash = RandU64FromSeed(*(u64 *)&end); + end_hash = RandU64FromSeeds(end_hash, wall_dir); dict_set(scratch.arena, horizontal_ends_dict, end_hash, (u64)node); } wall_start = -1; @@ -618,8 +618,8 @@ internal void test_generate_walls(Snapshot *world) Vec2I32 end = sim_world_tile_index_from_local_tile_index(chunk_index, VEC2I32(tile_x, wall_end)); struct wall_node *node = 0; if (wall_start == 0) { - u64 start_hash = rand_u64_from_seed(*(u64 *)&start); - start_hash = rand_u64_from_seeds(start_hash, wall_dir); + u64 start_hash = RandU64FromSeed(*(u64 *)&start); + start_hash = RandU64FromSeeds(start_hash, wall_dir); DictEntry *entry = dict_get_entry(vertical_ends_dict, start_hash); if (entry) { /* Existing wall exists accross chunk boundary */ @@ -636,8 +636,8 @@ internal void test_generate_walls(Snapshot *world) } node->end = end; if (wall_end == SIM_TILES_PER_CHUNK_SQRT) { - u64 end_hash = rand_u64_from_seed(*(u64 *)&end); - end_hash = rand_u64_from_seeds(end_hash, wall_dir); + u64 end_hash = RandU64FromSeed(*(u64 *)&end); + end_hash = RandU64FromSeeds(end_hash, wall_dir); dict_set(scratch.arena, vertical_ends_dict, end_hash, (u64)node); } wall_start = -1; @@ -748,7 +748,7 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) /* Create test blood */ /* TODO: Remove this */ { - Xform xf = XformFromTrs(TRS(.t = point, .r = rand_f64_from_state(&step_ctx->rand, 0, Tau))); + Xform xf = XformFromTrs(TRS(.t = point, .r = RandF64FromState(&step_ctx->rand, 0, Tau))); Ent *decal = sim_ent_alloc_sync_src(root); decal->sprite = sprite_tag_from_path(LIT("sprite/blood.ase")); decal->sprite_tint = Rgba32F(1, 1, 1, 0.25f); @@ -757,10 +757,10 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) f32 perp_range = 0.5; Vec2 linear_velocity = MulVec2(normal, 0.5); - linear_velocity = AddVec2(linear_velocity, MulVec2(PerpVec2(normal), rand_f64_from_state(&step_ctx->rand, -perp_range, perp_range))); + linear_velocity = AddVec2(linear_velocity, MulVec2(PerpVec2(normal), RandF64FromState(&step_ctx->rand, -perp_range, perp_range))); f32 angular_velocity_range = 5; - f32 angular_velocity = rand_f64_from_state(&step_ctx->rand, -angular_velocity_range, angular_velocity_range); + f32 angular_velocity = RandF64FromState(&step_ctx->rand, -angular_velocity_range, angular_velocity_range); sim_ent_enable_prop(decal, SEPROP_KINEMATIC); sim_ent_set_linear_velocity(decal, linear_velocity); diff --git a/src/sprite/sprite_core.c b/src/sprite/sprite_core.c index 1b7f1bc4..c24eddfb 100644 --- a/src/sprite/sprite_core.c +++ b/src/sprite/sprite_core.c @@ -276,7 +276,7 @@ b32 sprite_tag_eq(S_Tag t1, S_Tag t2) internal struct cache_entry_hash cache_entry_hash_from_tag_hash(u64 tag_hash, enum cache_entry_kind kind) { - return (struct cache_entry_hash) { .v = rand_u64_from_seed(tag_hash + kind) }; + return (struct cache_entry_hash) { .v = RandU64FromSeed(tag_hash + kind) }; } /* ========================== * diff --git a/src/user/user_core.c b/src/user/user_core.c index c21dd7af..d97f4983 100644 --- a/src/user/user_core.c +++ b/src/user/user_core.c @@ -846,8 +846,8 @@ internal void user_update(P_Window *window) if (shake > 0) { u64 angle_seed0 = ent->id.uid.lo + (u64)(G.ss_blended->sim_time_ns / frequency_ns); u64 angle_seed1 = angle_seed0 + 1; - f32 angle0 = rand_f64_from_seed(angle_seed0, 0, Tau); - f32 angle1 = rand_f64_from_seed(angle_seed1, 0, Tau); + f32 angle0 = RandF64FromSeed(angle_seed0, 0, Tau); + f32 angle1 = RandF64FromSeed(angle_seed1, 0, Tau); Vec2 vec0 = Vec2WithLen(Vec2FromAngle(angle0), shake); /* NOTE: vec1 not completely accurate since shake can change between frames, it's just a prediction */