use rand_state for rng

This commit is contained in:
jacob 2025-02-27 09:17:21 -06:00
parent 48999f5ab4
commit b9530f6c7a
12 changed files with 92 additions and 69 deletions

View File

@ -22,7 +22,6 @@
#include "math.h"
#include "renderer.h"
#include "phys.h"
#include "rng.h"
#include "sock.h"
#include "host.h"
#include "bitbuff.h"

60
src/rand.c Normal file
View File

@ -0,0 +1,60 @@
#include "rand.h"
#include "sys.h"
#include "memory.h"
#include "thread_local.h"
/* Based on Jon Maiga's "mx3"
* (https://jonkagstrom.com/mx3/mx3_rev2.html)
*/
INTERNAL u64 mix64(u64 x)
{
x = (x ^ (x >> 32)) * 0xbea225f9eb34556d;
x = (x ^ (x >> 29)) * 0xbea225f9eb34556d;
x = (x ^ (x >> 32)) * 0xbea225f9eb34556d;
x = (x ^ (x >> 29));
return x;
}
/* ========================== *
* Stateful prng
* ========================== */
u64 rand_u64_from_state(struct rand_state *state)
{
u64 res = state->seed;
while (res == 0) {
sys_true_rand(STRING_FROM_STRUCT(&res));
}
res = mix64(res);
state->seed = res;
return res;
}
f64 rand_f64_from_state(struct rand_state *state, f64 range_start, f64 range_end)
{
if (range_start > range_end) {
f64 swp = range_start;
range_start = range_end;
range_end = swp;
}
return range_start + ((f64)rand_u64_from_state(state) / (f64)U64_MAX) * (range_end - range_start);
}
/* ========================== *
* Seeded prng
* ========================== */
u64 rand_u64_from_seed(u64 seed)
{
return mix64(seed);
}
f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end)
{
if (range_start > range_end) {
f64 swp = range_start;
range_start = range_end;
range_end = swp;
}
return range_start + ((f64)rand_u64_from_seed(seed) / (f64)U64_MAX) * (range_end - range_start);
}

15
src/rand.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef RAND_H
#define RAND_H
struct rand_state {
/* If a state's seed = 0 upon a to a related function, it will be initialized using platform's true rng source */
u64 seed;
};
u64 rand_u64_from_state(struct rand_state *state);
f64 rand_f64_from_state(struct rand_state *state, f64 range_start, f64 range_end);
u64 rand_u64_from_seed(u64 seed);
f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end);
#endif

View File

@ -1,26 +0,0 @@
#include "rng.h"
#include "sys.h"
u32 rng_true_u32(void)
{
u32 v = 0;
sys_true_rand(STRING_FROM_STRUCT(&v));
return v;
}
u64 rng_true_u64(void)
{
u64 v = 0;
sys_true_rand(STRING_FROM_STRUCT(&v));
return v;
}
f32 rng_true_f32(f32 range_start, f32 range_end)
{
return ((f32)rng_true_u32() / (f32)U32_MAX) * (range_end - range_start) + range_start;
}
f64 rng_true_f64(f64 range_start, f64 range_end)
{
return ((f64)rng_true_u64() / (f64)U64_MAX) * (range_end - range_start) + range_start;
}

View File

@ -1,10 +0,0 @@
#ifndef RNG_H
#define RNG_H
/* Rand */
u32 rng_true_u32(void);
u64 rng_true_u64(void);
f32 rng_true_f32(f32 range_start, f32 range_end);
f64 rng_true_f64(f64 range_start, f64 range_end);
#endif

View File

@ -269,7 +269,7 @@ struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id)
struct sim_ent_id sim_ent_random_id(void)
{
struct sim_ent_id res = ZI;
res.uid = uid_rand();
res.uid = uid_true_rand();
return res;
}

View File

@ -11,7 +11,7 @@
#include "log.h"
#include "phys.h"
#include "collider.h"
#include "rng.h"
#include "rand.h"
#include "space.h"
#include "bitbuff.h"
#include "host.h"
@ -74,7 +74,7 @@ INTERNAL void spawn_test_entities(struct sim_step_ctx *ctx, struct v2 offset)
e->layer = SIM_LAYER_SHOULDERS;
sim_ent_enable_prop(e, SIM_ENT_PROP_PHYSICAL_DYNAMIC);
e->mass_unscaled = 1;
e->mass_unscaled = 10;
e->inertia_unscaled = 10;
e->linear_ground_friction = 250;
e->angular_ground_friction = 200;
@ -299,7 +299,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, st
/* Create test blood */
/* TODO: Remove this */
{
struct xform xf = XFORM_TRS(.t = point, .r = rng_true_f32(0, TAU));
struct xform xf = XFORM_TRS(.t = point, .r = rand_f64_from_state(&step_ctx->rand, 0, TAU));
struct sim_ent *decal = sim_ent_alloc_sync_src(root);
decal->sprite = sprite_tag_from_path(LIT("res/graphics/blood.ase"));
decal->sprite_tint = RGBA_32_F(1, 1, 1, 0.25f);
@ -308,10 +308,10 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, st
f32 perp_range = 0.5;
struct v2 linear_velocity = v2_mul(normal, 0.5);
linear_velocity = v2_add(linear_velocity, v2_mul(v2_perp(normal), rng_true_f32(-perp_range, perp_range)));
linear_velocity = v2_add(linear_velocity, v2_mul(v2_perp(normal), rand_f64_from_state(&step_ctx->rand, -perp_range, perp_range)));
f32 angular_velocity_range = 5;
f32 angular_velocity = rng_true_f32(-angular_velocity_range, angular_velocity_range);
f32 angular_velocity = rand_f64_from_seed(&step_ctx->rand, -angular_velocity_range, angular_velocity_range);
sim_ent_enable_prop(decal, SIM_ENT_PROP_PHYSICAL_KINEMATIC);
sim_ent_set_linear_velocity(decal, linear_velocity);

View File

@ -1,6 +1,8 @@
#ifndef SIM_STEP_H
#define SIM_STEP_H
#include "rand.h"
struct space;
struct sim_snapshot;
struct sim_snapshot_list;
@ -27,6 +29,7 @@ void sim_accel_reset(struct sim_snapshot *ss, struct sim_accel *accel);
struct sim_step_ctx {
b32 is_master;
struct sim_accel *accel;
struct rand_state rand; /* TODO: Replace with per-sim rand for deterministic rng */
struct sim_snapshot *world; /* The world to simulate */
i64 sim_dt_ns; /* How much sim time should progress */

View File

@ -1,9 +1,9 @@
#include "uid.h"
#include "rand.h"
#include "sys.h"
#include "util.h"
/* Returns a uid generated from the system's random number generator */
struct uid uid_rand(void)
struct uid uid_true_rand(void)
{
struct uid res = ZI;
sys_true_rand(STRING_FROM_STRUCT(&res));
@ -14,8 +14,7 @@ struct uid uid_rand(void)
struct uid uid_combine(struct uid a, struct uid b)
{
struct uid res;
/* Add bits of a+b to an arbitrary random constant (to prevent (a=0 + b=0) from returning a uid=0) */
res.hi = 0x958d53b0e2fd8e3f + a.hi + b.hi;
res.lo = 0x7038ffd46e0868c7 + a.lo + b.lo;
res.hi = rand_u64_from_seed(a.hi + b.hi);
res.lo = rand_u64_from_seed(a.lo + b.lo);
return res;
}

View File

@ -1,7 +1,7 @@
#ifndef UID_H
#define UID_H
struct uid uid_rand(void);
struct uid uid_true_rand(void);
struct uid uid_combine(struct uid a, struct uid b);
#endif

View File

@ -15,7 +15,7 @@
#include "mixer.h"
#include "atomic.h"
#include "collider.h"
#include "rng.h"
#include "rand.h"
#include "log.h"
#include "sock.h"
#include "host.h"
@ -752,8 +752,8 @@ INTERNAL void user_update(void)
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 = ((f32)mix64(angle_seed0) / (f32)U64_MAX) * TAU;
f32 angle1 = ((f32)mix64(angle_seed1) / (f32)U64_MAX) * TAU;
f32 angle0 = rand_f64_from_seed(angle_seed0, 0, TAU);
f32 angle1 = rand_f64_from_seed(angle_seed1, 0, TAU);
struct v2 vec0 = v2_with_len(v2_from_angle(angle0), shake);
/* NOTE: vec1 not completely accurate since shake can change between frames, just a prediction */

View File

@ -30,23 +30,6 @@ INLINE u64 hash_fnv64(u64 seed, struct string s)
return hash;
}
/* ========================== *
* Bit mixing
* ========================== */
/* Based on Jon Maiga's "mx3"
* (https://jonkagstrom.com/mx3/mx3_rev2.html)
*/
INLINE u64 mix64(u64 x)
{
x = (x ^ (x >> 32)) * 0xbea225f9eb34556d;
x = (x ^ (x >> 29)) * 0xbea225f9eb34556d;
x = (x ^ (x >> 32)) * 0xbea225f9eb34556d;
x = (x ^ (x >> 29));
return x;
}
/* ========================== *
* Merge sort
* ========================== */