base_rand refactor
This commit is contained in:
parent
d2e1be0df9
commit
380f63cacf
@ -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
|
#if PlatformIsWindows
|
||||||
# define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081)
|
# define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081)
|
||||||
u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
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);
|
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
# error rand_true not implemented for this platform
|
# error TrueRand not implemented for this platform
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ========================== *
|
////////////////////////////////
|
||||||
* Stateful prng
|
//~ Stateful randomness
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
u64 rand_u64_from_state(RandState *state)
|
u64 RandU64FromState(RandState *state)
|
||||||
{
|
{
|
||||||
u64 seed = state->seed;
|
u64 seed = state->seed;
|
||||||
if (seed == 0) {
|
if (seed == 0) {
|
||||||
rand_true(STRING_FROM_STRUCT(&seed));
|
TrueRand(STRING_FROM_STRUCT(&seed));
|
||||||
state->seed = 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"
|
/* Based on Jon Maiga's "mx3"
|
||||||
* https://jonkagstrom.com/mx3/mx3_rev2.html
|
* https://jonkagstrom.com/mx3/mx3_rev2.html
|
||||||
*/
|
*/
|
||||||
u64 rand_u64_from_seed(u64 seed)
|
u64 RandU64FromSeed(u64 seed)
|
||||||
{
|
{
|
||||||
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
||||||
seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d;
|
seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d;
|
||||||
@ -47,12 +45,12 @@ u64 rand_u64_from_seed(u64 seed)
|
|||||||
return 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,25 @@
|
|||||||
|
////////////////////////////////
|
||||||
|
//~ Rand types
|
||||||
|
|
||||||
Struct(RandState) {
|
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; /* 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 counter;
|
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);
|
//- True randomness
|
||||||
u64 rand_u64_from_seeds(u64 seed_a, u64 seed_b);
|
void TrueRand(String buffer);
|
||||||
f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end);
|
|
||||||
|
//- 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);
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
UID uid_true_rand(void)
|
UID uid_true_rand(void)
|
||||||
{
|
{
|
||||||
UID res = ZI;
|
UID res = ZI;
|
||||||
rand_true(STRING_FROM_STRUCT(&res));
|
TrueRand(STRING_FROM_STRUCT(&res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,8 +14,8 @@ UID uid_combine(UID a, UID b)
|
|||||||
res.lo = (a.lo * 3) + b.lo;
|
res.lo = (a.lo * 3) + b.lo;
|
||||||
res.hi += res.lo;
|
res.hi += res.lo;
|
||||||
res.lo += res.hi;
|
res.lo += res.hi;
|
||||||
res.hi = rand_u64_from_seed(res.hi);
|
res.hi = RandU64FromSeed(res.hi);
|
||||||
res.lo = rand_u64_from_seed(res.lo);
|
res.lo = RandU64FromSeed(res.lo);
|
||||||
res.hi += res.lo;
|
res.hi += res.lo;
|
||||||
res.lo += res.hi;
|
res.lo += res.hi;
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@ -2035,7 +2035,7 @@ internal struct command_descriptor_heap *command_list_push_descriptor_heap(struc
|
|||||||
|
|
||||||
internal u64 command_buffer_hash_from_size(u64 size)
|
internal u64 command_buffer_hash_from_size(u64 size)
|
||||||
{
|
{
|
||||||
u64 hash = rand_u64_from_seed(size);
|
u64 hash = RandU64FromSeed(size);
|
||||||
return hash;
|
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.flags = K_UintFromU32(shade_flags);
|
||||||
sig.tex_width = K_UintFromU32(render_size.x);
|
sig.tex_width = K_UintFromU32(render_size.x);
|
||||||
sig.tex_height = K_UintFromU32(render_size.y);
|
sig.tex_height = K_UintFromU32(render_size.y);
|
||||||
sig.frame_seed = K_Uint4FromU32((u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF),
|
sig.frame_seed = K_Uint4FromU32((u32)(RandU64FromState(&rsig->rand) & 0xFFFFFFFF),
|
||||||
(u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF),
|
(u32)(RandU64FromState(&rsig->rand) & 0xFFFFFFFF),
|
||||||
(u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF),
|
(u32)(RandU64FromState(&rsig->rand) & 0xFFFFFFFF),
|
||||||
(u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF));
|
(u32)(RandU64FromState(&rsig->rand) & 0xFFFFFFFF));
|
||||||
sig.frame_index = K_UintFromU32(rsig->frame_index);
|
sig.frame_index = K_UintFromU32(rsig->frame_index);
|
||||||
sig.camera_offset = K_Float2FromV2(world_to_render_xf.og);
|
sig.camera_offset = K_Float2FromV2(world_to_render_xf.og);
|
||||||
sig.albedo_tex_urid = K_UintFromU32(rsig->albedo->srv_descriptor->index);
|
sig.albedo_tex_urid = K_UintFromU32(rsig->albedo->srv_descriptor->index);
|
||||||
|
|||||||
@ -293,7 +293,7 @@ EntId sim_ent_tile_chunk_id_from_tile_chunk_index(Vec2I32 chunk_index)
|
|||||||
{
|
{
|
||||||
EntId res = ZI;
|
EntId res = ZI;
|
||||||
res.uid = SIM_ENT_TILE_CHUNK_BASIS_UID;
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -270,9 +270,9 @@ internal void test_spawn_entities2(Ent *parent, Vec2 pos)
|
|||||||
/* FIXME: Remove this */
|
/* FIXME: Remove this */
|
||||||
{
|
{
|
||||||
static RandState rand = ZI;
|
static RandState rand = ZI;
|
||||||
f32 r = rand_f64_from_state(&rand, 1, 5);
|
f32 r = RandF64FromState(&rand, 1, 5);
|
||||||
f32 g = rand_f64_from_state(&rand, 1, 5);
|
f32 g = RandF64FromState(&rand, 1, 5);
|
||||||
f32 b = rand_f64_from_state(&rand, 1, 5);
|
f32 b = RandF64FromState(&rand, 1, 5);
|
||||||
e->sprite_emittance = VEC3(r, g, b);
|
e->sprite_emittance = VEC3(r, g, b);
|
||||||
e->sprite_tint = Rgba32F(r / 5, g / 5, b / 5, 1);
|
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));
|
Vec2I32 end = sim_world_tile_index_from_local_tile_index(chunk_index, VEC2I32(wall_end, tile_y));
|
||||||
struct wall_node *node = 0;
|
struct wall_node *node = 0;
|
||||||
if (wall_start == 0) {
|
if (wall_start == 0) {
|
||||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
u64 start_hash = RandU64FromSeed(*(u64 *)&start);
|
||||||
start_hash = rand_u64_from_seeds(start_hash, wall_dir);
|
start_hash = RandU64FromSeeds(start_hash, wall_dir);
|
||||||
DictEntry *entry = dict_get_entry(horizontal_ends_dict, start_hash);
|
DictEntry *entry = dict_get_entry(horizontal_ends_dict, start_hash);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
/* Existing wall exists accross chunk boundary */
|
/* Existing wall exists accross chunk boundary */
|
||||||
@ -546,8 +546,8 @@ internal void test_generate_walls(Snapshot *world)
|
|||||||
}
|
}
|
||||||
node->end = end;
|
node->end = end;
|
||||||
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
u64 end_hash = RandU64FromSeed(*(u64 *)&end);
|
||||||
end_hash = rand_u64_from_seeds(end_hash, wall_dir);
|
end_hash = RandU64FromSeeds(end_hash, wall_dir);
|
||||||
dict_set(scratch.arena, horizontal_ends_dict, end_hash, (u64)node);
|
dict_set(scratch.arena, horizontal_ends_dict, end_hash, (u64)node);
|
||||||
}
|
}
|
||||||
wall_start = -1;
|
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));
|
Vec2I32 end = sim_world_tile_index_from_local_tile_index(chunk_index, VEC2I32(tile_x, wall_end));
|
||||||
struct wall_node *node = 0;
|
struct wall_node *node = 0;
|
||||||
if (wall_start == 0) {
|
if (wall_start == 0) {
|
||||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
u64 start_hash = RandU64FromSeed(*(u64 *)&start);
|
||||||
start_hash = rand_u64_from_seeds(start_hash, wall_dir);
|
start_hash = RandU64FromSeeds(start_hash, wall_dir);
|
||||||
DictEntry *entry = dict_get_entry(vertical_ends_dict, start_hash);
|
DictEntry *entry = dict_get_entry(vertical_ends_dict, start_hash);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
/* Existing wall exists accross chunk boundary */
|
/* Existing wall exists accross chunk boundary */
|
||||||
@ -636,8 +636,8 @@ internal void test_generate_walls(Snapshot *world)
|
|||||||
}
|
}
|
||||||
node->end = end;
|
node->end = end;
|
||||||
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
u64 end_hash = RandU64FromSeed(*(u64 *)&end);
|
||||||
end_hash = rand_u64_from_seeds(end_hash, wall_dir);
|
end_hash = RandU64FromSeeds(end_hash, wall_dir);
|
||||||
dict_set(scratch.arena, vertical_ends_dict, end_hash, (u64)node);
|
dict_set(scratch.arena, vertical_ends_dict, end_hash, (u64)node);
|
||||||
}
|
}
|
||||||
wall_start = -1;
|
wall_start = -1;
|
||||||
@ -748,7 +748,7 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
|||||||
/* Create test blood */
|
/* Create test blood */
|
||||||
/* TODO: Remove this */
|
/* 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);
|
Ent *decal = sim_ent_alloc_sync_src(root);
|
||||||
decal->sprite = sprite_tag_from_path(LIT("sprite/blood.ase"));
|
decal->sprite = sprite_tag_from_path(LIT("sprite/blood.ase"));
|
||||||
decal->sprite_tint = Rgba32F(1, 1, 1, 0.25f);
|
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;
|
f32 perp_range = 0.5;
|
||||||
Vec2 linear_velocity = MulVec2(normal, 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_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_enable_prop(decal, SEPROP_KINEMATIC);
|
||||||
sim_ent_set_linear_velocity(decal, linear_velocity);
|
sim_ent_set_linear_velocity(decal, linear_velocity);
|
||||||
|
|||||||
@ -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)
|
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) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
@ -846,8 +846,8 @@ internal void user_update(P_Window *window)
|
|||||||
if (shake > 0) {
|
if (shake > 0) {
|
||||||
u64 angle_seed0 = ent->id.uid.lo + (u64)(G.ss_blended->sim_time_ns / frequency_ns);
|
u64 angle_seed0 = ent->id.uid.lo + (u64)(G.ss_blended->sim_time_ns / frequency_ns);
|
||||||
u64 angle_seed1 = angle_seed0 + 1;
|
u64 angle_seed1 = angle_seed0 + 1;
|
||||||
f32 angle0 = rand_f64_from_seed(angle_seed0, 0, Tau);
|
f32 angle0 = RandF64FromSeed(angle_seed0, 0, Tau);
|
||||||
f32 angle1 = rand_f64_from_seed(angle_seed1, 0, Tau);
|
f32 angle1 = RandF64FromSeed(angle_seed1, 0, Tau);
|
||||||
|
|
||||||
Vec2 vec0 = Vec2WithLen(Vec2FromAngle(angle0), shake);
|
Vec2 vec0 = Vec2WithLen(Vec2FromAngle(angle0), shake);
|
||||||
/* NOTE: vec1 not completely accurate since shake can change between frames, it's just a prediction */
|
/* NOTE: vec1 not completely accurate since shake can change between frames, it's just a prediction */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user