progress & fix buddy bug
This commit is contained in:
parent
6fa3517d7a
commit
f000bd7e65
22
src/buddy.c
22
src/buddy.c
@ -73,6 +73,18 @@ INTERNAL struct buddy_block *buddy_block_get_unused(struct buddy_ctx *ctx, struc
|
|||||||
{
|
{
|
||||||
struct buddy_block *block = NULL;
|
struct buddy_block *block = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (level->tier > 30) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* TODO: Tier oob check */
|
/* TODO: Tier oob check */
|
||||||
if (level->first_unused_block) {
|
if (level->first_unused_block) {
|
||||||
block = level->first_unused_block;
|
block = level->first_unused_block;
|
||||||
@ -156,17 +168,15 @@ INTERNAL struct buddy_block *buddy_block_get_unused(struct buddy_ctx *ctx, struc
|
|||||||
INTERNAL void buddy_block_mark_unused(struct buddy_block *block)
|
INTERNAL void buddy_block_mark_unused(struct buddy_block *block)
|
||||||
{
|
{
|
||||||
block->used = false;
|
block->used = false;
|
||||||
struct buddy_block *sibling = block->sibling;
|
|
||||||
struct buddy_level *level = block->level;
|
struct buddy_level *level = block->level;
|
||||||
if (sibling && !sibling->used) {
|
struct buddy_block *parent = block->parent;
|
||||||
|
struct buddy_block *sibling = block->sibling;
|
||||||
|
if (!sibling->used && parent != NULL) {
|
||||||
/* Merge siblings */
|
/* Merge siblings */
|
||||||
struct buddy_ctx *ctx = level->ctx;
|
struct buddy_ctx *ctx = level->ctx;
|
||||||
struct buddy_block *parent = block->parent;
|
|
||||||
buddy_block_release_internal(ctx, level, block);
|
buddy_block_release_internal(ctx, level, block);
|
||||||
buddy_block_release_internal(ctx, level, sibling);
|
buddy_block_release_internal(ctx, level, sibling);
|
||||||
if (parent) {
|
buddy_block_mark_unused(parent);
|
||||||
buddy_block_mark_unused(parent);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (level->first_unused_block) {
|
if (level->first_unused_block) {
|
||||||
block->next = level->first_unused_block;
|
block->next = level->first_unused_block;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ INTERNAL BOOL CALLBACK enum_func(HMODULE module, LPCWSTR type, LPCWSTR wstr_entr
|
|||||||
{
|
{
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
struct rc_search_params *params = (struct rc_search_params *)udata;
|
struct rc_search_params *params = (struct rc_search_params *)udata;
|
||||||
struct string entry_name_lower = string_lower(scratch.arena, string_from_wstr(scratch.arena, (LPWSTR)wstr_entry_name));
|
struct string entry_name_lower = string_lower(scratch.arena, string_from_wstr_no_limit(scratch.arena, (LPWSTR)wstr_entry_name));
|
||||||
params->found = false;
|
params->found = false;
|
||||||
params->data = STRING(0, 0);
|
params->data = STRING(0, 0);
|
||||||
if (string_eq(entry_name_lower, params->name_lower)) {
|
if (string_eq(entry_name_lower, params->name_lower)) {
|
||||||
|
|||||||
@ -115,7 +115,7 @@ INLINE void ix_pause(void)
|
|||||||
_mm_pause();
|
_mm_pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE i64 ix_clock(void)
|
INLINE u64 ix_clock(void)
|
||||||
{
|
{
|
||||||
return __rdtsc();
|
return __rdtsc();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
|
|||||||
__prof;
|
__prof;
|
||||||
struct phys_collision_data_array res = ZI;
|
struct phys_collision_data_array res = ZI;
|
||||||
res.a = arena_dry_push(arena, struct phys_collision_data);
|
res.a = arena_dry_push(arena, struct phys_collision_data);
|
||||||
u64 tick_id = ctx->tick_id;
|
u64 tick = ctx->tick;
|
||||||
struct sim_ent_lookup *contact_lookup = ctx->contact_lookup;
|
struct sim_ent_lookup *contact_lookup = ctx->contact_lookup;
|
||||||
struct sim_ent_lookup *debug_lookup = ctx->debug_lookup;
|
struct sim_ent_lookup *debug_lookup = ctx->debug_lookup;
|
||||||
struct space *space = ctx->space;
|
struct space *space = ctx->space;
|
||||||
@ -133,7 +133,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
|
|||||||
|
|
||||||
/* TODO: Should we recalculate normal as more contact points are added? */
|
/* TODO: Should we recalculate normal as more contact points are added? */
|
||||||
sim_ent_enable_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT);
|
sim_ent_enable_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT);
|
||||||
sim_ent_activate(constraint_ent, tick_id);
|
sim_ent_activate(constraint_ent, tick);
|
||||||
ASSERT(!constraint_entry); /* Existing entry should never be present here */
|
ASSERT(!constraint_entry); /* Existing entry should never be present here */
|
||||||
sim_ent_lookup_set(contact_lookup, key, constraint_ent->handle);
|
sim_ent_lookup_set(contact_lookup, key, constraint_ent->handle);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, collision
|
|||||||
|
|
||||||
/* Structure containing data used for a single physics step */
|
/* Structure containing data used for a single physics step */
|
||||||
struct phys_ctx {
|
struct phys_ctx {
|
||||||
u64 tick_id;
|
u64 tick;
|
||||||
struct space *space;
|
struct space *space;
|
||||||
struct sim_ent_store *store;
|
struct sim_ent_store *store;
|
||||||
struct sim_ent_lookup *contact_lookup;
|
struct sim_ent_lookup *contact_lookup;
|
||||||
|
|||||||
224
src/sim.c
224
src/sim.c
@ -2,9 +2,9 @@
|
|||||||
#include "sim_ent.h"
|
#include "sim_ent.h"
|
||||||
#include "sim_client.h"
|
#include "sim_client.h"
|
||||||
#include "sim_msg.h"
|
#include "sim_msg.h"
|
||||||
|
#include "sim_snapshot.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "world.h"
|
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "scratch.h"
|
#include "scratch.h"
|
||||||
@ -18,41 +18,10 @@
|
|||||||
#include "byteio.h"
|
#include "byteio.h"
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
|
||||||
struct sim_ctx {
|
|
||||||
struct arena arena;
|
|
||||||
struct atomic_i32 sim_thread_shutdown;
|
|
||||||
struct sys_thread sim_thread;
|
|
||||||
|
|
||||||
u64 last_phys_iteration;
|
|
||||||
|
|
||||||
struct sprite_scope *sprite_frame_scope;
|
|
||||||
|
|
||||||
struct host *host;
|
|
||||||
|
|
||||||
/* TODO: Remove this (testing) */
|
|
||||||
b32 extra_spawn;
|
|
||||||
b32 should_reset_level;
|
|
||||||
|
|
||||||
struct sim_ent *root;
|
|
||||||
|
|
||||||
/* Bookkeeping structures */
|
|
||||||
struct sim_ent_lookup contact_lookup;
|
|
||||||
#if COLLIDER_DEBUG
|
|
||||||
struct sim_ent_lookup collision_debug_lookup;
|
|
||||||
#endif
|
|
||||||
struct space *space;
|
|
||||||
|
|
||||||
/* Tick */
|
|
||||||
struct world tick;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Ctx
|
* Ctx
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sim_thread_entry_point, arg);
|
|
||||||
INTERNAL void test_sim_world_alloc(struct sim_ctx *ctx);
|
|
||||||
INTERNAL void test_sim_world_release(struct sim_ctx *ctx);
|
|
||||||
|
|
||||||
struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr,
|
struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr,
|
||||||
struct phys_startup_receipt *phys_sr,
|
struct phys_startup_receipt *phys_sr,
|
||||||
@ -70,33 +39,6 @@ struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr,
|
|||||||
/* Intialize host */
|
/* Intialize host */
|
||||||
ctx->host = host_alloc(host_port);
|
ctx->host = host_alloc(host_port);
|
||||||
|
|
||||||
/* Initialize empty world */
|
|
||||||
test_sim_world_alloc(ctx);
|
|
||||||
|
|
||||||
ctx->sim_thread = sys_thread_alloc(&sim_thread_entry_point, ctx, LIT("[P2] Sim thread"));
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sim_ctx_release(struct sim_ctx *ctx)
|
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
atomic_i32_eval_exchange(&ctx->sim_thread_shutdown, true);
|
|
||||||
sys_thread_wait_release(&ctx->sim_thread);
|
|
||||||
|
|
||||||
test_sim_world_release(ctx);
|
|
||||||
host_release(ctx->host);
|
|
||||||
arena_release(&ctx->arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Reset
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
/* TODO: Remove this */
|
|
||||||
|
|
||||||
INTERNAL void test_sim_world_alloc(struct sim_ctx *ctx)
|
|
||||||
{
|
|
||||||
/* Create bookkeeping */
|
/* Create bookkeeping */
|
||||||
ctx->contact_lookup = sim_ent_lookup_alloc(4096);
|
ctx->contact_lookup = sim_ent_lookup_alloc(4096);
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
@ -104,21 +46,29 @@ INTERNAL void test_sim_world_alloc(struct sim_ctx *ctx)
|
|||||||
#endif
|
#endif
|
||||||
ctx->space = space_alloc(SPACE_CELL_SIZE, SPACE_CELL_BUCKETS_SQRT);
|
ctx->space = space_alloc(SPACE_CELL_SIZE, SPACE_CELL_BUCKETS_SQRT);
|
||||||
|
|
||||||
/* Re-create world */
|
/* Create emtpy snapshot */
|
||||||
world_alloc(&ctx->tick);
|
sim_snapshot_alloc(&ctx->world);
|
||||||
ctx->tick.timescale = SIM_TIMESCALE;
|
ctx->world.world_timescale = SIM_TIMESCALE;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void test_sim_world_release(struct sim_ctx *ctx)
|
void sim_ctx_release(struct sim_ctx *ctx)
|
||||||
{
|
{
|
||||||
/* Release world */
|
__prof;
|
||||||
world_release(&ctx->tick);
|
|
||||||
|
/* Release snapshot */
|
||||||
|
sim_snapshot_release(&ctx->world);
|
||||||
|
|
||||||
/* Release bookkeeping */
|
/* Release bookkeeping */
|
||||||
space_release(ctx->space);
|
space_release(ctx->space);
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
sim_ent_lookup_release(&ctx->collision_debug_lookup);
|
sim_ent_lookup_release(&ctx->collision_debug_lookup);
|
||||||
#endif
|
#endif
|
||||||
sim_ent_lookup_release(&ctx->contact_lookup);
|
sim_ent_lookup_release(&ctx->contact_lookup);
|
||||||
|
|
||||||
|
host_release(ctx->host);
|
||||||
|
arena_release(&ctx->arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -129,7 +79,7 @@ INTERNAL void test_sim_world_release(struct sim_ctx *ctx)
|
|||||||
|
|
||||||
INTERNAL void spawn_test_entities(struct sim_ctx *ctx)
|
INTERNAL void spawn_test_entities(struct sim_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct sim_ent *root = sim_ent_from_handle(ctx->tick.ent_store, ctx->tick.ent_store->root);
|
struct sim_ent *root = sim_ent_from_handle(ctx->world.ent_store, ctx->world.ent_store->root);
|
||||||
root->mass_unscaled = F32_INFINITY;
|
root->mass_unscaled = F32_INFINITY;
|
||||||
root->inertia_unscaled = F32_INFINITY;
|
root->inertia_unscaled = F32_INFINITY;
|
||||||
|
|
||||||
@ -199,13 +149,11 @@ INTERNAL void spawn_test_entities(struct sim_ctx *ctx)
|
|||||||
e->linear_ground_friction = 0.001;
|
e->linear_ground_friction = 0.001;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ctx->extra_spawn = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct sim_ent *spawn_test_player(struct sim_ctx *ctx)
|
INTERNAL struct sim_ent *spawn_test_player(struct sim_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct sim_ent_store *store = ctx->tick.ent_store;
|
struct sim_ent_store *store = ctx->world.ent_store;
|
||||||
struct sim_ent *root = sim_ent_from_handle(store, store->root);
|
struct sim_ent *root = sim_ent_from_handle(store, store->root);
|
||||||
|
|
||||||
/* Player */
|
/* Player */
|
||||||
@ -224,21 +172,11 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_ctx *ctx)
|
|||||||
//f32 r = PI / 4;
|
//f32 r = PI / 4;
|
||||||
f32 r = 0;
|
f32 r = 0;
|
||||||
|
|
||||||
if (!ctx->extra_spawn) {
|
{
|
||||||
sim_ent_enable_prop(e, SIM_ENT_PROP_TEST);
|
sim_ent_enable_prop(e, SIM_ENT_PROP_TEST);
|
||||||
e->sprite = sprite_tag_from_path(LIT("res/graphics/tim.ase"));
|
e->sprite = sprite_tag_from_path(LIT("res/graphics/tim.ase"));
|
||||||
e->mass_unscaled = 10;
|
e->mass_unscaled = 10;
|
||||||
e->inertia_unscaled = 5;
|
e->inertia_unscaled = 5;
|
||||||
} else {
|
|
||||||
sim_ent_enable_prop(e, SIM_ENT_PROP_TEST);
|
|
||||||
e->sprite = sprite_tag_from_path(LIT("res/graphics/tim.ase"));
|
|
||||||
e->mass_unscaled = 10;
|
|
||||||
e->inertia_unscaled = 5;
|
|
||||||
#if 0
|
|
||||||
e->sprite = sprite_tag_from_path(LIT("res/graphics/box.ase"));
|
|
||||||
e->mass_unscaled = 100;
|
|
||||||
e->inertia_unscaled = 100;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e->local_collider.points[0] = v2_with_len(V2(0.08f, 0.17f), 0.15f);
|
e->local_collider.points[0] = v2_with_len(V2(0.08f, 0.17f), 0.15f);
|
||||||
@ -281,8 +219,8 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_ctx *ctx)
|
|||||||
e->layer = SIM_LAYER_RELATIVE_WEAPON;
|
e->layer = SIM_LAYER_RELATIVE_WEAPON;
|
||||||
|
|
||||||
sim_ent_enable_prop(e, SIM_ENT_PROP_WEAPON);
|
sim_ent_enable_prop(e, SIM_ENT_PROP_WEAPON);
|
||||||
//e->trigger_delay = 1.0f / 10.0f;
|
e->trigger_delay = 1.0f / 10.0f;
|
||||||
e->trigger_delay = 1.0f / 100.0f;
|
//e->trigger_delay = 1.0f / 100.0f;
|
||||||
|
|
||||||
player_ent->equipped = e->handle;
|
player_ent->equipped = e->handle;
|
||||||
}
|
}
|
||||||
@ -292,7 +230,7 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_ctx *ctx)
|
|||||||
|
|
||||||
INTERNAL struct sim_ent *spawn_test_player_camera(struct sim_ctx *ctx, struct sim_ent *player_ent)
|
INTERNAL struct sim_ent *spawn_test_player_camera(struct sim_ctx *ctx, struct sim_ent *player_ent)
|
||||||
{
|
{
|
||||||
struct sim_ent_store *store = ctx->tick.ent_store;
|
struct sim_ent_store *store = ctx->world.ent_store;
|
||||||
struct sim_ent *root = sim_ent_from_handle(store, store->root);
|
struct sim_ent *root = sim_ent_from_handle(store, store->root);
|
||||||
|
|
||||||
struct sim_ent *camera_ent = sim_ent_nil();
|
struct sim_ent *camera_ent = sim_ent_nil();
|
||||||
@ -319,7 +257,7 @@ INTERNAL struct sim_ent *spawn_test_player_camera(struct sim_ctx *ctx, struct si
|
|||||||
INTERNAL void release_entities_with_prop(struct sim_ctx *ctx, enum sim_ent_prop prop)
|
INTERNAL void release_entities_with_prop(struct sim_ctx *ctx, enum sim_ent_prop prop)
|
||||||
{
|
{
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
struct sim_ent_store *store = ctx->tick.ent_store;
|
struct sim_ent_store *store = ctx->world.ent_store;
|
||||||
struct space *space = ctx->space;
|
struct space *space = ctx->space;
|
||||||
|
|
||||||
struct sim_ent **ents_to_release = arena_dry_push(scratch.arena, struct sim_ent *);
|
struct sim_ent **ents_to_release = arena_dry_push(scratch.arena, struct sim_ent *);
|
||||||
@ -366,7 +304,7 @@ INTERNAL void release_entities_with_prop(struct sim_ctx *ctx, enum sim_ent_prop
|
|||||||
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, udata)
|
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, udata)
|
||||||
{
|
{
|
||||||
struct sim_ctx *ctx = (struct sim_ctx *)udata;
|
struct sim_ctx *ctx = (struct sim_ctx *)udata;
|
||||||
struct sim_ent_store *store = ctx->tick.ent_store;
|
struct sim_ent_store *store = ctx->world.ent_store;
|
||||||
struct sim_ent *root = sim_ent_from_handle(store, store->root);
|
struct sim_ent *root = sim_ent_from_handle(store, store->root);
|
||||||
|
|
||||||
for (u64 i = 0; i < collision_data_array.count; ++i) {
|
for (u64 i = 0; i < collision_data_array.count; ++i) {
|
||||||
@ -451,45 +389,41 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, ud
|
|||||||
* Update
|
* Update
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
void sim_update(struct sim_ctx *ctx, i64 target_dt_ns)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Reset level if necessary
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
if (ctx->should_reset_level) {
|
|
||||||
logf_info("Clearing level");
|
|
||||||
ctx->should_reset_level = false;
|
|
||||||
ctx->extra_spawn = false;
|
|
||||||
test_sim_world_release(ctx);
|
|
||||||
test_sim_world_alloc(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Begin frame
|
* Begin frame
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
++ctx->tick.tick_id;
|
++ctx->world.tick;
|
||||||
|
|
||||||
ctx->tick.dt_ns = NS_FROM_SECONDS(max_f64(0.0, dt * ctx->tick.timescale));
|
ctx->world.real_dt_ns = max_i64(0, target_dt_ns);
|
||||||
ctx->tick.time_ns += ctx->tick.dt_ns;
|
ctx->world.real_time_ns += ctx->world.real_dt_ns;
|
||||||
|
|
||||||
f64 time = SECONDS_FROM_NS(ctx->tick.time_ns);
|
ctx->world.world_dt_ns = max_i64(0, target_dt_ns * ctx->world.world_timescale);
|
||||||
|
ctx->world.world_time_ns += ctx->world.world_dt_ns;
|
||||||
|
|
||||||
|
f64 sim_time = SECONDS_FROM_NS(ctx->world.world_time_ns);
|
||||||
ctx->sprite_frame_scope = sprite_scope_begin();
|
ctx->sprite_frame_scope = sprite_scope_begin();
|
||||||
ctx->root = sim_ent_from_handle(ctx->tick.ent_store, ctx->tick.ent_store->root);
|
|
||||||
|
|
||||||
struct sim_ent *root = ctx->root;
|
f64 real_dt = SECONDS_FROM_NS(ctx->world.real_dt_ns);
|
||||||
struct sim_ent_store *ent_store = ctx->tick.ent_store;
|
f64 real_time = SECONDS_FROM_NS(ctx->world.real_time_ns);
|
||||||
|
f64 world_dt = SECONDS_FROM_NS(ctx->world.world_dt_ns);
|
||||||
|
f64 world_time = SECONDS_FROM_NS(ctx->world.world_time_ns);
|
||||||
|
(UNUSED)real_dt;
|
||||||
|
(UNUSED)real_time;
|
||||||
|
(UNUSED)world_dt;
|
||||||
|
(UNUSED)world_time;
|
||||||
|
|
||||||
|
struct sim_ent *root = sim_ent_from_handle(ctx->world.ent_store, ctx->world.ent_store->root);;
|
||||||
|
struct sim_ent_store *ent_store = ctx->world.ent_store;
|
||||||
struct space *space = ctx->space;
|
struct space *space = ctx->space;
|
||||||
struct sprite_scope *sprite_frame_scope = ctx->sprite_frame_scope;
|
struct sprite_scope *sprite_frame_scope = ctx->sprite_frame_scope;
|
||||||
|
|
||||||
(UNUSED)dt;
|
|
||||||
(UNUSED)time;
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Spawn test entities
|
* Spawn test entities
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -520,8 +454,8 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
|
|
||||||
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ACTIVE)) {
|
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ACTIVE)) {
|
||||||
u64 atick = ent->activation_tick;
|
u64 atick = ent->activation_tick;
|
||||||
if (atick != 0 || ctx->tick.tick_id >= atick) {
|
if (atick != 0 || ctx->world.tick >= atick) {
|
||||||
sim_ent_activate(ent, ctx->tick.tick_id);
|
sim_ent_activate(ent, ctx->world.tick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -548,17 +482,19 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
|
|
||||||
struct sim_cmd_list *client_cmds;
|
struct sim_cmd_list *client_cmds;
|
||||||
{
|
{
|
||||||
struct sim_cmd_list sim_cmds = ZI;
|
host_update(ctx->host);
|
||||||
struct host_event_array host_events = host_pop_events(scratch.arena, ctx->host);
|
struct host_event_array host_events = host_pop_events(scratch.arena, ctx->host);
|
||||||
|
|
||||||
|
struct sim_cmd_list sim_cmds = ZI;
|
||||||
sim_cmds_from_host_events(scratch.arena, host_events, &sim_cmds);
|
sim_cmds_from_host_events(scratch.arena, host_events, &sim_cmds);
|
||||||
|
|
||||||
/* Create connecting clients */
|
/* Create connecting clients */
|
||||||
for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
|
for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
|
||||||
enum sim_cmd_kind kind = cmd->kind;
|
enum sim_cmd_kind kind = cmd->kind;
|
||||||
struct host_channel_id channel_id = cmd->channel_id;
|
struct host_channel_id channel_id = cmd->channel_id;
|
||||||
struct sim_client *client = sim_client_from_channel_id(ctx->tick.client_store, channel_id);
|
struct sim_client *client = sim_client_from_channel_id(ctx->world.client_store, channel_id);
|
||||||
if (!client->valid && kind == SIM_CMD_KIND_SIM_CLIENT_CONNECT && !host_channel_id_is_nil(channel_id)) {
|
if (!client->valid && kind == SIM_CMD_KIND_SIM_CLIENT_CONNECT && !host_channel_id_is_nil(channel_id)) {
|
||||||
client = sim_client_alloc(ctx->tick.client_store, channel_id);
|
client = sim_client_alloc(ctx->world.client_store, channel_id);
|
||||||
/* TODO: Create player ent not here */
|
/* TODO: Create player ent not here */
|
||||||
/* FIXME: Player ent never released upon disconnect */
|
/* FIXME: Player ent never released upon disconnect */
|
||||||
struct sim_ent *player_ent = spawn_test_player(ctx);
|
struct sim_ent *player_ent = spawn_test_player(ctx);
|
||||||
@ -571,13 +507,13 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Split cmds by client */
|
/* Split cmds by client */
|
||||||
client_cmds = arena_push_array_zero(scratch.arena, struct sim_cmd_list, ctx->tick.client_store->num_reserved);
|
client_cmds = arena_push_array_zero(scratch.arena, struct sim_cmd_list, ctx->world.client_store->num_reserved);
|
||||||
{
|
{
|
||||||
struct sim_cmd *cmd = sim_cmds.first;
|
struct sim_cmd *cmd = sim_cmds.first;
|
||||||
while (cmd) {
|
while (cmd) {
|
||||||
struct sim_cmd *next = cmd->next;
|
struct sim_cmd *next = cmd->next;
|
||||||
struct host_channel_id channel_id = cmd->channel_id;
|
struct host_channel_id channel_id = cmd->channel_id;
|
||||||
struct sim_client *client = sim_client_from_channel_id(ctx->tick.client_store, channel_id);
|
struct sim_client *client = sim_client_from_channel_id(ctx->world.client_store, channel_id);
|
||||||
if (client->valid) {
|
if (client->valid) {
|
||||||
struct sim_cmd_list *cmd_list = &client_cmds[client->handle.idx];
|
struct sim_cmd_list *cmd_list = &client_cmds[client->handle.idx];
|
||||||
if (cmd_list->last) {
|
if (cmd_list->last) {
|
||||||
@ -598,8 +534,8 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Process client cmds */
|
/* Process client cmds */
|
||||||
for (u64 i = 0; i < ctx->tick.client_store->num_reserved; ++i) {
|
for (u64 i = 0; i < ctx->world.client_store->num_reserved; ++i) {
|
||||||
struct sim_client *client = &ctx->tick.client_store->clients[i];
|
struct sim_client *client = &ctx->world.client_store->clients[i];
|
||||||
if (client->valid) {
|
if (client->valid) {
|
||||||
struct host_channel_id channel_id = client->channel_id;
|
struct host_channel_id channel_id = client->channel_id;
|
||||||
struct sim_cmd_list cmds = client_cmds[client->handle.idx];
|
struct sim_cmd_list cmds = client_cmds[client->handle.idx];
|
||||||
@ -659,7 +595,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
/* Clear level */
|
/* Clear level */
|
||||||
case SIM_CMD_KIND_CLEAR_ALL:
|
case SIM_CMD_KIND_CLEAR_ALL:
|
||||||
{
|
{
|
||||||
ctx->should_reset_level = true;
|
/* TODO */
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
/* Spawn test */
|
/* Spawn test */
|
||||||
@ -691,7 +627,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||||
|
|
||||||
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) {
|
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) {
|
||||||
struct sim_client *client = sim_client_from_handle(ctx->tick.client_store, ent->controlling_client);
|
struct sim_client *client = sim_client_from_handle(ctx->world.client_store, ent->controlling_client);
|
||||||
if (client->valid) {
|
if (client->valid) {
|
||||||
ent->control = client->control;
|
ent->control = client->control;
|
||||||
/* TODO: Move this */
|
/* TODO: Move this */
|
||||||
@ -719,7 +655,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
{
|
{
|
||||||
struct sprite_sheet_span span = sprite_sheet_get_span(sheet, ent->sprite_span_name);
|
struct sprite_sheet_span span = sprite_sheet_get_span(sheet, ent->sprite_span_name);
|
||||||
|
|
||||||
f64 time_in_frame = ent->animation_time_in_frame + dt;
|
f64 time_in_frame = ent->animation_time_in_frame + world_dt;
|
||||||
u64 frame_index = ent->animation_frame;
|
u64 frame_index = ent->animation_frame;
|
||||||
if (frame_index < span.start || frame_index > span.end) {
|
if (frame_index < span.start || frame_index > span.end) {
|
||||||
frame_index = span.start;
|
frame_index = span.start;
|
||||||
@ -899,9 +835,9 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
struct sim_ent *ent = &ent_store->entities[ent_index];
|
struct sim_ent *ent = &ent_store->entities[ent_index];
|
||||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||||
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGERED_THIS_TICK)) continue;
|
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGERED_THIS_TICK)) continue;
|
||||||
if ((time - ent->last_triggered < ent->trigger_delay) && ent->last_triggered != 0) continue;
|
if ((sim_time - ent->last_triggered < ent->trigger_delay) && ent->last_triggered != 0) continue;
|
||||||
|
|
||||||
ent->last_triggered = time;
|
ent->last_triggered = sim_time;
|
||||||
|
|
||||||
/* Fire weapon */
|
/* Fire weapon */
|
||||||
if (sim_ent_has_prop(ent, SIM_ENT_PROP_WEAPON)) {
|
if (sim_ent_has_prop(ent, SIM_ENT_PROP_WEAPON)) {
|
||||||
@ -1019,7 +955,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set correction rate dynamically since motor velocity is only set for one frame */
|
/* Set correction rate dynamically since motor velocity is only set for one frame */
|
||||||
joint_ent->motor_joint_data.correction_rate = 10 * dt;
|
joint_ent->motor_joint_data.correction_rate = 10 * world_dt;
|
||||||
|
|
||||||
|
|
||||||
/* Solve for final angle using law of sines */
|
/* Solve for final angle using law of sines */
|
||||||
@ -1072,7 +1008,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
f32 diff = math_unwind_angle(new_angle - xform_get_rotation(joint_xf));
|
f32 diff = math_unwind_angle(new_angle - xform_get_rotation(joint_xf));
|
||||||
if (math_fabs(diff) > angle_error_allowed) {
|
if (math_fabs(diff) > angle_error_allowed) {
|
||||||
/* Instantly snap joint ent to new angle */
|
/* Instantly snap joint ent to new angle */
|
||||||
new_vel = diff / dt;
|
new_vel = diff / real_dt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sim_ent_set_angular_velocity(joint_ent, new_vel);
|
sim_ent_set_angular_velocity(joint_ent, new_vel);
|
||||||
@ -1112,8 +1048,8 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
* Create mouse joints from client debug drag
|
* Create mouse joints from client debug drag
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
for (u64 i = 0; i < ctx->tick.client_store->num_reserved; ++i) {
|
for (u64 i = 0; i < ctx->world.client_store->num_reserved; ++i) {
|
||||||
struct sim_client *client = &ctx->tick.client_store->clients[i];
|
struct sim_client *client = &ctx->world.client_store->clients[i];
|
||||||
if (client->valid) {
|
if (client->valid) {
|
||||||
struct v2 cursor = client->cursor_pos;
|
struct v2 cursor = client->cursor_pos;
|
||||||
b32 start_dragging = client->dbg_drag_start;
|
b32 start_dragging = client->dbg_drag_start;
|
||||||
@ -1182,7 +1118,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
|
|
||||||
{
|
{
|
||||||
struct phys_ctx phys = ZI;
|
struct phys_ctx phys = ZI;
|
||||||
phys.tick_id = ctx->tick.tick_id;
|
phys.tick = ctx->world.tick;
|
||||||
phys.store = ent_store;
|
phys.store = ent_store;
|
||||||
phys.space = space;
|
phys.space = space;
|
||||||
phys.contact_lookup = &ctx->contact_lookup;
|
phys.contact_lookup = &ctx->contact_lookup;
|
||||||
@ -1193,7 +1129,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Step */
|
/* Step */
|
||||||
ctx->last_phys_iteration = phys_step(&phys, dt, ctx->last_phys_iteration);
|
ctx->last_phys_iteration = phys_step(&phys, world_dt, ctx->last_phys_iteration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -1207,7 +1143,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
|
|
||||||
struct v2 end = sim_ent_get_xform(ent).og;
|
struct v2 end = sim_ent_get_xform(ent).og;
|
||||||
|
|
||||||
struct v2 tick_velocity = v2_mul(ent->tracer_start_velocity, dt);
|
struct v2 tick_velocity = v2_mul(ent->tracer_start_velocity, world_dt);
|
||||||
struct v2 gradient_start = v2_add(ent->tracer_gradient_start, tick_velocity);
|
struct v2 gradient_start = v2_add(ent->tracer_gradient_start, tick_velocity);
|
||||||
struct v2 gradient_end = v2_add(ent->tracer_gradient_end, tick_velocity);
|
struct v2 gradient_end = v2_add(ent->tracer_gradient_end, tick_velocity);
|
||||||
|
|
||||||
@ -1229,7 +1165,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||||
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_BULLET)) continue;
|
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_BULLET)) continue;
|
||||||
|
|
||||||
if (ent->activation_tick == ctx->tick.tick_id) {
|
if (ent->activation_tick == ctx->world.tick) {
|
||||||
struct sim_ent *src = sim_ent_from_handle(ent_store, ent->bullet_src);
|
struct sim_ent *src = sim_ent_from_handle(ent_store, ent->bullet_src);
|
||||||
struct xform src_xf = sim_ent_get_xform(src);
|
struct xform src_xf = sim_ent_get_xform(src);
|
||||||
|
|
||||||
@ -1307,7 +1243,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
|
|
||||||
/* Lerp camera */
|
/* Lerp camera */
|
||||||
if (ent->camera_applied_lerp_continuity_gen_plus_one == ent->camera_lerp_continuity_gen + 1) {
|
if (ent->camera_applied_lerp_continuity_gen_plus_one == ent->camera_lerp_continuity_gen + 1) {
|
||||||
f32 t = 1 - math_pow(2.f, -20.f * (f32)dt);
|
f32 t = 1 - math_pow(2.f, -20.f * (f32)world_dt);
|
||||||
xf = xform_lerp(xf, ent->camera_xform_target, t);
|
xf = xform_lerp(xf, ent->camera_xform_target, t);
|
||||||
} else {
|
} else {
|
||||||
/* Skip lerp */
|
/* Skip lerp */
|
||||||
@ -1340,7 +1276,7 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||||
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_QUAKE)) continue;
|
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_QUAKE)) continue;
|
||||||
|
|
||||||
ent->quake_intensity = max_f32(0, ent->quake_intensity - (ent->quake_fade * dt));
|
ent->quake_intensity = max_f32(0, ent->quake_intensity - (ent->quake_fade * world_dt));
|
||||||
if (ent->quake_intensity <= 0) {
|
if (ent->quake_intensity <= 0) {
|
||||||
sim_ent_enable_prop(ent, SIM_ENT_PROP_RELEASE_NEXT_TICK);
|
sim_ent_enable_prop(ent, SIM_ENT_PROP_RELEASE_NEXT_TICK);
|
||||||
}
|
}
|
||||||
@ -1385,15 +1321,16 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
* Publish tick
|
* Publish tick
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
for (u64 i = 0; i < ctx->tick.client_store->num_reserved; ++i) {
|
for (u64 i = 0; i < ctx->world.client_store->num_reserved; ++i) {
|
||||||
struct sim_client *client = &ctx->tick.client_store->clients[i];
|
struct sim_client *client = &ctx->world.client_store->clients[i];
|
||||||
if (client->valid) {
|
if (client->valid) {
|
||||||
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
/* TODO: Not like this */
|
/* TODO: Not like this */
|
||||||
struct sim_event snapshot_event = ZI;
|
struct sim_event snapshot_event = ZI;
|
||||||
|
snapshot_event.tick = ctx->world.tick;
|
||||||
snapshot_event.kind = SIM_EVENT_KIND_SNAPSHOT;
|
snapshot_event.kind = SIM_EVENT_KIND_SNAPSHOT;
|
||||||
snapshot_event.snapshot_data = sim_string_from_tick(temp.arena, client, &ctx->tick);
|
snapshot_event.snapshot_data = sim_snapshot_encode(temp.arena, client, &ctx->world);
|
||||||
|
|
||||||
struct sim_event_list l = ZI;
|
struct sim_event_list l = ZI;
|
||||||
l.first = &snapshot_event;
|
l.first = &snapshot_event;
|
||||||
@ -1418,20 +1355,3 @@ INTERNAL void sim_update(struct sim_ctx *ctx, f64 dt)
|
|||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Sim thread
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sim_thread_entry_point, arg)
|
|
||||||
{
|
|
||||||
struct sim_ctx *ctx = (struct sim_ctx *)arg;
|
|
||||||
i64 last_frame_ns = 0;
|
|
||||||
i64 target_dt_ns = NS_FROM_SECONDS(SIM_FPS > (0) ? (1.0 / SIM_FPS) : 0);
|
|
||||||
while (!atomic_i32_eval(&ctx->sim_thread_shutdown)) {
|
|
||||||
__profscope(sim_update_w_sleep);
|
|
||||||
sleep_frame(last_frame_ns, target_dt_ns);
|
|
||||||
last_frame_ns = sys_time_ns();
|
|
||||||
sim_update(ctx, (1.0 / SIM_FPS));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
26
src/sim.h
26
src/sim.h
@ -1,7 +1,9 @@
|
|||||||
#ifndef SIM_H
|
#ifndef SIM_H
|
||||||
#define SIM_H
|
#define SIM_H
|
||||||
|
|
||||||
struct sim_ctx;
|
#include "sim_ent.h"
|
||||||
|
#include "sim_snapshot.h"
|
||||||
|
|
||||||
struct sprite_startup_receipt;
|
struct sprite_startup_receipt;
|
||||||
struct phys_startup_receipt;
|
struct phys_startup_receipt;
|
||||||
struct host_startup_receipt;
|
struct host_startup_receipt;
|
||||||
@ -16,6 +18,26 @@ struct host_startup_receipt;
|
|||||||
#define SIM_LAYER_RELATIVE_DEFAULT 0
|
#define SIM_LAYER_RELATIVE_DEFAULT 0
|
||||||
#define SIM_LAYER_RELATIVE_WEAPON 1
|
#define SIM_LAYER_RELATIVE_WEAPON 1
|
||||||
|
|
||||||
|
struct sim_ctx {
|
||||||
|
struct arena arena;
|
||||||
|
|
||||||
|
u64 last_phys_iteration;
|
||||||
|
|
||||||
|
struct sprite_scope *sprite_frame_scope;
|
||||||
|
|
||||||
|
struct host *host;
|
||||||
|
|
||||||
|
/* Bookkeeping structures */
|
||||||
|
struct sim_ent_lookup contact_lookup;
|
||||||
|
#if COLLIDER_DEBUG
|
||||||
|
struct sim_ent_lookup collision_debug_lookup;
|
||||||
|
#endif
|
||||||
|
struct space *space;
|
||||||
|
|
||||||
|
/* Tick */
|
||||||
|
struct sim_snapshot world;
|
||||||
|
};
|
||||||
|
|
||||||
/* TODO: Get rid of startup receipts */
|
/* TODO: Get rid of startup receipts */
|
||||||
struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr,
|
struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr,
|
||||||
struct phys_startup_receipt *phys_sr,
|
struct phys_startup_receipt *phys_sr,
|
||||||
@ -24,5 +46,7 @@ struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr,
|
|||||||
|
|
||||||
void sim_ctx_release(struct sim_ctx *ctx);
|
void sim_ctx_release(struct sim_ctx *ctx);
|
||||||
|
|
||||||
|
void sim_update(struct sim_ctx *ctx, i64 target_dt_ns);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#include "host.h"
|
#include "host.h"
|
||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "arena.h"
|
||||||
|
|
||||||
#define CHANNEL_LOOKUP_BUCKETS 4096
|
#define CHANNEL_LOOKUP_BUCKETS 4096
|
||||||
|
|
||||||
@ -21,11 +22,11 @@ struct sim_client_channel_lookup_bucket {
|
|||||||
* Store
|
* Store
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sim_client_store *sim_client_store_alloc(void)
|
struct sim_client_store *sim_client_store_alloc(u64 arena_reserve)
|
||||||
{
|
{
|
||||||
struct arena arena = arena_alloc(GIGABYTE(64));
|
struct arena arena = arena_alloc(arena_reserve);
|
||||||
u64 num_channel_lookup_buckets = CHANNEL_LOOKUP_BUCKETS;
|
u64 num_channel_lookup_buckets = CHANNEL_LOOKUP_BUCKETS;
|
||||||
u64 channel_lookup_buckets = arena_push_array_zero(&arena, struct sim_client_channel_lookup_bucket, num_channel_lookup_buckets);
|
struct sim_client_channel_lookup_bucket *channel_lookup_buckets = arena_push_array_zero(&arena, struct sim_client_channel_lookup_bucket, num_channel_lookup_buckets);
|
||||||
|
|
||||||
struct sim_client_store *store = arena_push_zero(&arena, struct sim_client_store);
|
struct sim_client_store *store = arena_push_zero(&arena, struct sim_client_store);
|
||||||
store->clients = arena_dry_push(&arena, struct sim_client);
|
store->clients = arena_dry_push(&arena, struct sim_client);
|
||||||
|
|||||||
@ -52,7 +52,7 @@ INLINE struct sim_client_store *client_store_nil(void)
|
|||||||
return &_g_sim_client_store_nil;
|
return &_g_sim_client_store_nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sim_client_store *sim_client_store_alloc(void);
|
struct sim_client_store *sim_client_store_alloc(u64 arena_reserve);
|
||||||
void sim_client_store_release(struct sim_client_store *store);
|
void sim_client_store_release(struct sim_client_store *store);
|
||||||
struct sim_client_store *client_store_from_client(struct sim_client *client);
|
struct sim_client_store *client_store_from_client(struct sim_client *client);
|
||||||
struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct sim_client_handle handle);
|
struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct sim_client_handle handle);
|
||||||
|
|||||||
@ -37,9 +37,9 @@ INTERNAL void store_make_root(struct sim_ent_store *store)
|
|||||||
store->root = root->handle;
|
store->root = root->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sim_ent_store *sim_ent_store_alloc(void)
|
struct sim_ent_store *sim_ent_store_alloc(u64 arena_reserve)
|
||||||
{
|
{
|
||||||
struct arena arena = arena_alloc(GIGABYTE(64));
|
struct arena arena = arena_alloc(arena_reserve);
|
||||||
struct sim_ent_store *store = arena_push_zero(&arena, struct sim_ent_store);
|
struct sim_ent_store *store = arena_push_zero(&arena, struct sim_ent_store);
|
||||||
store->valid = true;
|
store->valid = true;
|
||||||
store->arena = arena;
|
store->arena = arena;
|
||||||
@ -500,9 +500,9 @@ struct sim_ent_lookup_key sim_ent_lookup_key_from_two_handles(struct sim_ent_han
|
|||||||
* Activate
|
* Activate
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_ent_activate(struct sim_ent *ent, u64 current_tick_id)
|
void sim_ent_activate(struct sim_ent *ent, u64 current_tick)
|
||||||
{
|
{
|
||||||
sim_ent_enable_prop(ent, SIM_ENT_PROP_ACTIVE);
|
sim_ent_enable_prop(ent, SIM_ENT_PROP_ACTIVE);
|
||||||
ent->activation_tick = current_tick_id;
|
ent->activation_tick = current_tick;
|
||||||
++ent->continuity_gen;
|
++ent->continuity_gen;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -372,7 +372,7 @@ INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Entity store */
|
/* Entity store */
|
||||||
struct sim_ent_store *sim_ent_store_alloc(void);
|
struct sim_ent_store *sim_ent_store_alloc(u64 arena_reserve);
|
||||||
void sim_ent_store_release(struct sim_ent_store *store);
|
void sim_ent_store_release(struct sim_ent_store *store);
|
||||||
void sim_ent_store_copy_replace(struct sim_ent_store *dest, struct sim_ent_store *src);
|
void sim_ent_store_copy_replace(struct sim_ent_store *dest, struct sim_ent_store *src);
|
||||||
|
|
||||||
@ -414,6 +414,6 @@ void sim_ent_lookup_remove(struct sim_ent_lookup *l, struct sim_ent_lookup_entry
|
|||||||
struct sim_ent_lookup_key sim_ent_lookup_key_from_two_handles(struct sim_ent_handle h0, struct sim_ent_handle h1);
|
struct sim_ent_lookup_key sim_ent_lookup_key_from_two_handles(struct sim_ent_handle h0, struct sim_ent_handle h1);
|
||||||
|
|
||||||
/* Activate */
|
/* Activate */
|
||||||
void sim_ent_activate(struct sim_ent *ent, u64 current_tick_id);
|
void sim_ent_activate(struct sim_ent *ent, u64 current_tick);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include "sim_msg.h"
|
#include "sim_msg.h"
|
||||||
|
#include "sim_snapshot.h"
|
||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
#include "byteio.h"
|
#include "byteio.h"
|
||||||
#include "world.h"
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Sim cmd
|
* Sim cmd
|
||||||
@ -135,6 +135,7 @@ struct string sim_string_from_events(struct arena *arena, struct sim_event_list
|
|||||||
for (struct sim_event *event = events.first; event; event = event->next) {
|
for (struct sim_event *event = events.first; event; event = event->next) {
|
||||||
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
|
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
|
||||||
u64 start = bw_pos(&bw);
|
u64 start = bw_pos(&bw);
|
||||||
|
bw_write_var_uint(&bw, event->tick);
|
||||||
bw_write_i8(&bw, event->kind);
|
bw_write_i8(&bw, event->kind);
|
||||||
|
|
||||||
switch (event->kind) {
|
switch (event->kind) {
|
||||||
@ -179,6 +180,7 @@ void sim_events_from_host_events(struct arena *arena, struct host_event_array ho
|
|||||||
u64 event_size = br_read_u64(&br);
|
u64 event_size = br_read_u64(&br);
|
||||||
u64 event_pos_end = br_pos(&br) + event_size;
|
u64 event_pos_end = br_pos(&br) + event_size;
|
||||||
|
|
||||||
|
sim_event->tick = br_read_var_uint(&br);
|
||||||
sim_event->kind = br_read_i8(&br);
|
sim_event->kind = br_read_i8(&br);
|
||||||
switch (sim_event->kind) {
|
switch (sim_event->kind) {
|
||||||
case SIM_EVENT_KIND_SNAPSHOT:
|
case SIM_EVENT_KIND_SNAPSHOT:
|
||||||
@ -210,72 +212,77 @@ void sim_events_from_host_events(struct arena *arena, struct host_event_array ho
|
|||||||
* Snapshot
|
* Snapshot
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string sim_string_from_tick(struct arena *arena, struct sim_client *client, struct world *tick)
|
struct string sim_snapshot_encode(struct arena *arena, struct sim_client *client, struct sim_snapshot *snapshot)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct byte_writer bw = bw_from_arena(arena);
|
struct byte_writer bw = bw_from_arena(arena);
|
||||||
|
|
||||||
bw_write_var_uint(&bw, tick->continuity_gen);
|
bw_write_var_uint(&bw, snapshot->continuity_gen);
|
||||||
bw_write_var_uint(&bw, tick->tick_id);
|
bw_write_var_sint(&bw, snapshot->publishtime_ns);
|
||||||
bw_write_var_sint(&bw, tick->publishtime_ns);
|
|
||||||
|
|
||||||
bw_write_f64(&bw, tick->timescale);
|
bw_write_var_sint(&bw, snapshot->real_dt_ns);
|
||||||
bw_write_var_sint(&bw, tick->dt_ns);
|
bw_write_var_sint(&bw, snapshot->real_time_ns);
|
||||||
bw_write_var_sint(&bw, tick->time_ns);
|
|
||||||
|
bw_write_f64(&bw, snapshot->world_timescale);
|
||||||
|
bw_write_var_sint(&bw, snapshot->world_dt_ns);
|
||||||
|
bw_write_var_sint(&bw, snapshot->world_time_ns);
|
||||||
|
|
||||||
bw_write_var_uint(&bw, client->handle.gen);
|
bw_write_var_uint(&bw, client->handle.gen);
|
||||||
bw_write_var_uint(&bw, client->handle.idx);
|
bw_write_var_uint(&bw, client->handle.idx);
|
||||||
|
|
||||||
/* Client store */
|
/* Client store */
|
||||||
u64 num_clients = tick->client_store->num_reserved;
|
u64 num_clients = snapshot->client_store->num_reserved;
|
||||||
bw_write_var_uint(&bw, num_clients);
|
bw_write_var_uint(&bw, num_clients);
|
||||||
|
|
||||||
struct string clients_src = ZI;
|
struct string clients_src = ZI;
|
||||||
clients_src.text = (u8 *)tick->client_store->clients;
|
clients_src.text = (u8 *)snapshot->client_store->clients;
|
||||||
clients_src.len = sizeof(struct sim_client) * num_clients;
|
clients_src.len = sizeof(struct sim_client) * num_clients;
|
||||||
br_write_bytes(&bw, clients_src);
|
br_write_bytes(&bw, clients_src);
|
||||||
|
|
||||||
/* Entity store */
|
/* Entity store */
|
||||||
u64 num_entities = tick->ent_store->num_reserved;
|
u64 num_entities = snapshot->ent_store->num_reserved;
|
||||||
bw_write_var_uint(&bw, num_entities);
|
bw_write_var_uint(&bw, num_entities);
|
||||||
|
|
||||||
struct string entities_src = ZI;
|
struct string entities_src = ZI;
|
||||||
entities_src.text = (u8 *)tick->ent_store->entities;
|
entities_src.text = (u8 *)snapshot->ent_store->entities;
|
||||||
entities_src.len = sizeof(struct sim_ent) * num_entities;
|
entities_src.len = sizeof(struct sim_ent) * num_entities;
|
||||||
br_write_bytes(&bw, entities_src);
|
br_write_bytes(&bw, entities_src);
|
||||||
|
|
||||||
return bw_get_written(&bw);
|
return bw_get_written(&bw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_tick_from_string(struct string str, struct world *tick_out)
|
void sim_snapshot_decode(struct string str, struct sim_snapshot *snapshot, u64 tick)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct byte_reader br = br_from_buffer(str);
|
struct byte_reader br = br_from_buffer(str);
|
||||||
|
|
||||||
tick_out->continuity_gen = br_read_var_uint(&br);
|
snapshot->tick = tick;
|
||||||
tick_out->tick_id = br_read_var_uint(&br);
|
snapshot->continuity_gen = br_read_var_uint(&br);
|
||||||
tick_out->publishtime_ns = br_read_var_sint(&br);
|
snapshot->publishtime_ns = br_read_var_sint(&br);
|
||||||
|
|
||||||
tick_out->timescale = br_read_f64(&br);
|
snapshot->real_dt_ns = br_read_var_sint(&br);
|
||||||
tick_out->dt_ns = br_read_var_sint(&br);
|
snapshot->real_time_ns = br_read_var_sint(&br);
|
||||||
tick_out->time_ns = br_read_var_sint(&br);
|
|
||||||
|
|
||||||
tick_out->local_client.gen = br_read_var_uint(&br);
|
snapshot->world_timescale = br_read_f64(&br);
|
||||||
tick_out->local_client.idx = br_read_var_uint(&br);
|
snapshot->world_dt_ns = br_read_var_sint(&br);
|
||||||
|
snapshot->world_time_ns = br_read_var_sint(&br);
|
||||||
|
|
||||||
|
snapshot->local_client.gen = br_read_var_uint(&br);
|
||||||
|
snapshot->local_client.idx = br_read_var_uint(&br);
|
||||||
|
|
||||||
/* Client store */
|
/* Client store */
|
||||||
u64 num_clients = br_read_var_uint(&br);
|
u64 num_clients = br_read_var_uint(&br);
|
||||||
arena_push_array(&tick_out->client_store->arena, struct sim_client, num_clients - tick_out->client_store->num_reserved);
|
arena_push_array(&snapshot->client_store->arena, struct sim_client, num_clients - snapshot->client_store->num_reserved);
|
||||||
tick_out->client_store->num_reserved = num_clients;
|
snapshot->client_store->num_reserved = num_clients;
|
||||||
|
|
||||||
tick_out->client_store->num_allocated = 0;
|
snapshot->client_store->num_allocated = 0;
|
||||||
struct sim_client *clients_src = br_seek(&br, num_clients * sizeof(struct sim_client));
|
struct sim_client *clients_src = br_seek(&br, num_clients * sizeof(struct sim_client));
|
||||||
if (clients_src) {
|
if (clients_src) {
|
||||||
for (u64 i = 0; i < num_clients; ++i) {
|
for (u64 i = 0; i < num_clients; ++i) {
|
||||||
struct sim_client *src = &clients_src[i];
|
struct sim_client *src = &clients_src[i];
|
||||||
struct sim_client *dst = &tick_out->client_store->clients[i];
|
struct sim_client *dst = &snapshot->client_store->clients[i];
|
||||||
if (dst->valid) {
|
if (dst->valid) {
|
||||||
++tick_out->client_store->num_allocated;
|
++snapshot->client_store->num_allocated;
|
||||||
}
|
}
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
}
|
}
|
||||||
@ -283,17 +290,17 @@ void sim_tick_from_string(struct string str, struct world *tick_out)
|
|||||||
|
|
||||||
/* Entity store */
|
/* Entity store */
|
||||||
u64 num_entities = br_read_var_uint(&br);
|
u64 num_entities = br_read_var_uint(&br);
|
||||||
arena_push_array(&tick_out->ent_store->arena, struct sim_ent, num_entities - tick_out->ent_store->num_reserved);
|
arena_push_array(&snapshot->ent_store->arena, struct sim_ent, num_entities - snapshot->ent_store->num_reserved);
|
||||||
tick_out->ent_store->num_reserved = num_entities;
|
snapshot->ent_store->num_reserved = num_entities;
|
||||||
|
|
||||||
tick_out->ent_store->num_allocated = 0;
|
snapshot->ent_store->num_allocated = 0;
|
||||||
struct sim_ent *entities_src = br_seek(&br, num_entities * sizeof(struct sim_ent));
|
struct sim_ent *entities_src = br_seek(&br, num_entities * sizeof(struct sim_ent));
|
||||||
if (entities_src) {
|
if (entities_src) {
|
||||||
for (u64 i = 0; i < num_entities; ++i) {
|
for (u64 i = 0; i < num_entities; ++i) {
|
||||||
struct sim_ent *src = &entities_src[i];
|
struct sim_ent *src = &entities_src[i];
|
||||||
struct sim_ent *dst = &tick_out->ent_store->entities[i];
|
struct sim_ent *dst = &snapshot->ent_store->entities[i];
|
||||||
if (dst->valid) {
|
if (dst->valid) {
|
||||||
++tick_out->ent_store->num_allocated;
|
++snapshot->ent_store->num_allocated;
|
||||||
}
|
}
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
|
||||||
struct world;
|
struct sim_snapshot;
|
||||||
struct sim_client;
|
struct sim_client;
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -83,6 +83,7 @@ enum sim_event_kind {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct sim_event {
|
struct sim_event {
|
||||||
|
u64 tick;
|
||||||
enum sim_event_kind kind;
|
enum sim_event_kind kind;
|
||||||
struct host_channel_id channel_id;
|
struct host_channel_id channel_id;
|
||||||
|
|
||||||
@ -106,7 +107,7 @@ void sim_events_from_host_events(struct arena *arena, struct host_event_array ho
|
|||||||
* Snapshot
|
* Snapshot
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string sim_string_from_tick(struct arena *arena, struct sim_client *client, struct world *tick);
|
struct string sim_snapshot_encode(struct arena *arena, struct sim_client *client, struct sim_snapshot *snapshot);
|
||||||
void sim_tick_from_string(struct string str, struct world *tick_out);
|
void sim_snapshot_decode(struct string str, struct sim_snapshot *snapshot, u64 tick);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
18
src/sim_snapshot.c
Normal file
18
src/sim_snapshot.c
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "sim_snapshot.h"
|
||||||
|
#include "sim_ent.h"
|
||||||
|
#include "sim_client.h"
|
||||||
|
#include "arena.h"
|
||||||
|
#include "scratch.h"
|
||||||
|
|
||||||
|
void sim_snapshot_alloc(struct sim_snapshot *sim_snapshot)
|
||||||
|
{
|
||||||
|
MEMZERO_STRUCT(sim_snapshot);
|
||||||
|
sim_snapshot->client_store = sim_client_store_alloc(GIGABYTE(64));
|
||||||
|
sim_snapshot->ent_store = sim_ent_store_alloc(GIGABYTE(64));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sim_snapshot_release(struct sim_snapshot *sim_snapshot)
|
||||||
|
{
|
||||||
|
sim_ent_store_release(sim_snapshot->ent_store);
|
||||||
|
sim_client_store_release(sim_snapshot->client_store);
|
||||||
|
}
|
||||||
30
src/sim_snapshot.h
Normal file
30
src/sim_snapshot.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef SIM_SNAPSHOT_H
|
||||||
|
#define SIM_SNAPSHOT_H
|
||||||
|
|
||||||
|
#include "sim_ent.h"
|
||||||
|
#include "sim_client.h"
|
||||||
|
|
||||||
|
struct sim_snapshot {
|
||||||
|
u64 continuity_gen; /* Starts at 1 */
|
||||||
|
u64 tick; /* Starts at 1 */
|
||||||
|
i64 publishtime_ns; /* When was this tick simulated in program time */
|
||||||
|
|
||||||
|
/* Real time (increases with clock assuming no lag) */
|
||||||
|
i64 real_dt_ns;
|
||||||
|
i64 real_time_ns;
|
||||||
|
|
||||||
|
/* World time (affected by timescale) */
|
||||||
|
f64 world_timescale;
|
||||||
|
i64 world_dt_ns;
|
||||||
|
i64 world_time_ns;
|
||||||
|
|
||||||
|
struct sim_client_handle local_client;
|
||||||
|
|
||||||
|
struct sim_client_store *client_store;
|
||||||
|
struct sim_ent_store *ent_store;
|
||||||
|
};
|
||||||
|
|
||||||
|
void sim_snapshot_alloc(struct sim_snapshot *sim_snapshot);
|
||||||
|
void sim_snapshot_release(struct sim_snapshot *sim_snapshot);
|
||||||
|
|
||||||
|
#endif
|
||||||
110
src/user.c
110
src/user.c
@ -3,6 +3,7 @@
|
|||||||
#include "sim.h"
|
#include "sim.h"
|
||||||
#include "sim_ent.h"
|
#include "sim_ent.h"
|
||||||
#include "sim_msg.h"
|
#include "sim_msg.h"
|
||||||
|
#include "sim_snapshot.h"
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
@ -14,7 +15,6 @@
|
|||||||
#include "scratch.h"
|
#include "scratch.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "world.h"
|
|
||||||
#include "mixer.h"
|
#include "mixer.h"
|
||||||
#include "atomic.h"
|
#include "atomic.h"
|
||||||
#include "collider.h"
|
#include "collider.h"
|
||||||
@ -30,12 +30,6 @@ struct bind_state {
|
|||||||
u32 num_releases; /* How many times was this bind released since last frame */
|
u32 num_releases; /* How many times was this bind released since last frame */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct blend_tick {
|
|
||||||
struct blend_tick *next;
|
|
||||||
struct blend_tick *prev;
|
|
||||||
struct world world;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct second_stat {
|
struct second_stat {
|
||||||
u64 last_second_start;
|
u64 last_second_start;
|
||||||
u64 last_second_end;
|
u64 last_second_end;
|
||||||
@ -46,6 +40,9 @@ GLOBAL struct {
|
|||||||
struct atomic_i32 user_thread_shutdown;
|
struct atomic_i32 user_thread_shutdown;
|
||||||
struct sys_thread user_thread;
|
struct sys_thread user_thread;
|
||||||
|
|
||||||
|
struct atomic_i32 sim_thread_shutdown;
|
||||||
|
struct sys_thread sim_thread;
|
||||||
|
|
||||||
struct arena arena;
|
struct arena arena;
|
||||||
struct sys_window *window;
|
struct sys_window *window;
|
||||||
struct sim_ctx *sim_ctx;
|
struct sim_ctx *sim_ctx;
|
||||||
@ -70,9 +67,7 @@ GLOBAL struct {
|
|||||||
|
|
||||||
struct xform world_to_ui_xf;
|
struct xform world_to_ui_xf;
|
||||||
|
|
||||||
struct blend_tick *head_free_blend_tick;
|
struct sim_snapshot world;
|
||||||
struct blend_tick *head_blend_tick;
|
|
||||||
struct world world;
|
|
||||||
|
|
||||||
struct bind_state bind_states[USER_BIND_KIND_COUNT];
|
struct bind_state bind_states[USER_BIND_KIND_COUNT];
|
||||||
|
|
||||||
@ -87,8 +82,6 @@ GLOBAL struct {
|
|||||||
struct arena sys_events_arena;
|
struct arena sys_events_arena;
|
||||||
|
|
||||||
/* Per-frame */
|
/* Per-frame */
|
||||||
i64 time_ns;
|
|
||||||
i64 dt_ns;
|
|
||||||
struct v2 screen_size;
|
struct v2 screen_size;
|
||||||
struct v2 screen_cursor;
|
struct v2 screen_cursor;
|
||||||
struct v2 ui_screen_offset;
|
struct v2 ui_screen_offset;
|
||||||
@ -136,6 +129,23 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Sim thread
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_sim_thread_entry_point, arg)
|
||||||
|
{
|
||||||
|
struct sim_ctx *ctx = (struct sim_ctx *)arg;
|
||||||
|
i64 last_frame_ns = 0;
|
||||||
|
i64 target_dt_ns = NS_FROM_SECONDS(1) / SIM_FPS;;
|
||||||
|
while (!atomic_i32_eval(&G.sim_thread_shutdown)) {
|
||||||
|
__profscope(sim_update_w_sleep);
|
||||||
|
sleep_frame(last_frame_ns, target_dt_ns);
|
||||||
|
last_frame_ns = sys_time_ns();
|
||||||
|
sim_update(ctx, target_dt_ns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -171,7 +181,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
|||||||
G.arena = arena_alloc(GIGABYTE(64));
|
G.arena = arena_alloc(GIGABYTE(64));
|
||||||
G.sys_events_mutex = sys_mutex_alloc();
|
G.sys_events_mutex = sys_mutex_alloc();
|
||||||
G.sys_events_arena = arena_alloc(GIGABYTE(64));
|
G.sys_events_arena = arena_alloc(GIGABYTE(64));
|
||||||
world_alloc(&G.world);
|
sim_snapshot_alloc(&G.world);
|
||||||
|
|
||||||
//struct sock_address bind_addr = sock_address_from_any_local_interface_with_dynamic_port();
|
//struct sock_address bind_addr = sock_address_from_any_local_interface_with_dynamic_port();
|
||||||
G.host = host_alloc(0);
|
G.host = host_alloc(0);
|
||||||
@ -188,6 +198,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
|||||||
if (connect_address_str.len == 0) {
|
if (connect_address_str.len == 0) {
|
||||||
G.sim_ctx = sim_ctx_alloc(sprite_sr, phys_sr, host_sr, 12345);
|
G.sim_ctx = sim_ctx_alloc(sprite_sr, phys_sr, host_sr, 12345);
|
||||||
G.connect_address_str = LIT("127.0.0.1:12345");
|
G.connect_address_str = LIT("127.0.0.1:12345");
|
||||||
|
G.sim_thread = sys_thread_alloc(&user_sim_thread_entry_point, G.sim_ctx, LIT("[P2] Sim thread"));
|
||||||
} else {
|
} else {
|
||||||
G.connect_address_str = string_copy(&G.arena, connect_address_str);
|
G.connect_address_str = string_copy(&G.arena, connect_address_str);
|
||||||
}
|
}
|
||||||
@ -207,6 +218,8 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(user_shutdown)
|
|||||||
sys_thread_wait_release(&G.user_thread);
|
sys_thread_wait_release(&G.user_thread);
|
||||||
|
|
||||||
if (G.sim_ctx) {
|
if (G.sim_ctx) {
|
||||||
|
atomic_i32_eval_exchange(&G.sim_thread_shutdown, true);
|
||||||
|
sys_thread_wait_release(&G.sim_thread);
|
||||||
sim_ctx_release(G.sim_ctx);
|
sim_ctx_release(G.sim_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,11 +265,11 @@ INTERNAL struct blend_tick *blend_tick_alloc(void)
|
|||||||
bt = G.head_free_blend_tick;
|
bt = G.head_free_blend_tick;
|
||||||
G.head_free_blend_tick = bt->next;
|
G.head_free_blend_tick = bt->next;
|
||||||
*bt = (struct blend_tick) {
|
*bt = (struct blend_tick) {
|
||||||
.world = bt->world
|
.sim_snapshot = bt->sim_snapshot
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
bt = arena_push_zero(&G.arena, struct blend_tick);
|
bt = arena_push_zero(&G.arena, struct blend_tick);
|
||||||
world_alloc(&bt->world);
|
sim_snapshot_alloc(&bt->sim_snapshot);
|
||||||
}
|
}
|
||||||
if (G.head_blend_tick) {
|
if (G.head_blend_tick) {
|
||||||
bt->next = G.head_blend_tick;
|
bt->next = G.head_blend_tick;
|
||||||
@ -289,8 +302,8 @@ INTERNAL void blend_tick_release(struct blend_tick *bt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct interp_ticks {
|
struct interp_ticks {
|
||||||
struct world *from_tick;
|
struct sim_snapshot *from_tick;
|
||||||
struct world *to_tick;
|
struct sim_snapshot *to_tick;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
||||||
@ -298,28 +311,28 @@ INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
|||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
/* Find newest stored tick */
|
/* Find newest stored tick */
|
||||||
struct world *newest_tick = NULL;
|
struct sim_snapshot *newest_tick = NULL;
|
||||||
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
|
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
|
||||||
if (!newest_tick || bt->world.tick_id > newest_tick->tick_id) {
|
if (!newest_tick || bt->sim_snapshot.tick > newest_tick->tick) {
|
||||||
newest_tick = &bt->world;
|
newest_tick = &bt->sim_snapshot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct world *from_tick;
|
struct sim_snapshot *from_tick;
|
||||||
struct world *to_tick;
|
struct sim_snapshot *to_tick;
|
||||||
if (newest_tick && sim_get_latest_tick_continuity_gen() == newest_tick->continuity_gen) {
|
if (newest_tick && sim_get_latest_tick_continuity_gen() == newest_tick->continuity_gen) {
|
||||||
/* Pull new tick from sim thread if necessary */
|
/* Pull new tick from sim thread if necessary */
|
||||||
if (!newest_tick || sim_get_latest_tick_id() > newest_tick->tick_id) {
|
if (!newest_tick || sim_get_latest_tick() > newest_tick->tick) {
|
||||||
struct blend_tick *latest_bt = blend_tick_alloc();
|
struct blend_tick *latest_bt = blend_tick_alloc();
|
||||||
newest_tick = &latest_bt->world;
|
newest_tick = &latest_bt->sim_snapshot;
|
||||||
sim_get_latest_tick(newest_tick);
|
sim_get_latest_tick(newest_tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find oldest tick */
|
/* Find oldest tick */
|
||||||
struct world *oldest_tick = NULL;
|
struct sim_snapshot *oldest_tick = NULL;
|
||||||
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
|
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
|
||||||
if (!oldest_tick || bt->world.tick_id < oldest_tick->tick_id) {
|
if (!oldest_tick || bt->sim_snapshot.tick < oldest_tick->tick) {
|
||||||
oldest_tick = &bt->world;
|
oldest_tick = &bt->sim_snapshot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,14 +340,14 @@ INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
|||||||
from_tick = oldest_tick;
|
from_tick = oldest_tick;
|
||||||
to_tick = newest_tick;
|
to_tick = newest_tick;
|
||||||
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
|
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
|
||||||
i64 bt_time_ns = bt->world.publishtime_ns;
|
i64 bt_time_ns = bt->sim_snapshot.publishtime_ns;
|
||||||
|
|
||||||
if (bt_time_ns < blend_time_ns && bt_time_ns > from_tick->publishtime_ns) {
|
if (bt_time_ns < blend_time_ns && bt_time_ns > from_tick->publishtime_ns) {
|
||||||
from_tick = &bt->world;
|
from_tick = &bt->sim_snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bt_time_ns > blend_time_ns && bt_time_ns < to_tick->publishtime_ns) {
|
if (bt_time_ns > blend_time_ns && bt_time_ns < to_tick->publishtime_ns) {
|
||||||
to_tick = &bt->world;
|
to_tick = &bt->sim_snapshot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,7 +358,7 @@ INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
|||||||
u64 bts_to_free_count = 0;
|
u64 bts_to_free_count = 0;
|
||||||
|
|
||||||
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
|
for (struct blend_tick *bt = G.head_blend_tick; bt; bt = bt->next) {
|
||||||
i64 bt_time_ns = bt->world.publishtime_ns;
|
i64 bt_time_ns = bt->sim_snapshot.publishtime_ns;
|
||||||
if (bt_time_ns < from_tick->publishtime_ns) {
|
if (bt_time_ns < from_tick->publishtime_ns) {
|
||||||
*arena_push(scratch.arena, struct blend_tick *) = bt;
|
*arena_push(scratch.arena, struct blend_tick *) = bt;
|
||||||
++bts_to_free_count;
|
++bts_to_free_count;
|
||||||
@ -378,7 +391,7 @@ INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
|||||||
|
|
||||||
/* Allocate new blend tick */
|
/* Allocate new blend tick */
|
||||||
struct blend_tick *bt = blend_tick_alloc();
|
struct blend_tick *bt = blend_tick_alloc();
|
||||||
struct world *tick = &bt->world;
|
struct sim_snapshot *tick = &bt->sim_snapshot;
|
||||||
sim_get_latest_tick(tick);
|
sim_get_latest_tick(tick);
|
||||||
|
|
||||||
from_tick = tick;
|
from_tick = tick;
|
||||||
@ -527,8 +540,6 @@ INTERNAL void user_update(void)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
i64 now_ns = sys_time_ns();
|
i64 now_ns = sys_time_ns();
|
||||||
G.dt_ns = max_f64(0.0, now_ns - G.time_ns);
|
|
||||||
G.time_ns += G.dt_ns;
|
|
||||||
G.screen_size = sys_window_get_size(G.window);
|
G.screen_size = sys_window_get_size(G.window);
|
||||||
|
|
||||||
struct sim_ent_store *store = G.world.ent_store;
|
struct sim_ent_store *store = G.world.ent_store;
|
||||||
@ -550,8 +561,8 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
/* Pull ticks */
|
/* Pull ticks */
|
||||||
struct interp_ticks interp_ticks = pull_ticks(blend_time_ns);
|
struct interp_ticks interp_ticks = pull_ticks(blend_time_ns);
|
||||||
struct world *t0 = interp_ticks.from_tick;
|
struct sim_snapshot *t0 = interp_ticks.from_tick;
|
||||||
struct world *t1 = interp_ticks.to_tick;
|
struct sim_snapshot *t1 = interp_ticks.to_tick;
|
||||||
|
|
||||||
f32 tick_blend = 0;
|
f32 tick_blend = 0;
|
||||||
{
|
{
|
||||||
@ -565,11 +576,11 @@ INTERNAL void user_update(void)
|
|||||||
tick_blend = clamp_f32(tick_blend, 0.0f, 1.0f);
|
tick_blend = clamp_f32(tick_blend, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
world_copy_replace(&G.world, t0);
|
world_copy_replace(&G.sim_snapshot, t0);
|
||||||
|
|
||||||
/* Blend world globals */
|
/* Blend world globals */
|
||||||
G.world.time_ns = math_lerp_i64(t0->time_ns, t1->time_ns, (f64)tick_blend);
|
G.sim_snapshot.time_ns = math_lerp_i64(t0->time_ns, t1->time_ns, (f64)tick_blend);
|
||||||
G.world.dt_ns = math_lerp_i64(t0->dt_ns, t1->dt_ns, (f64)tick_blend);
|
G.sim_snapshot.dt_ns = math_lerp_i64(t0->dt_ns, t1->dt_ns, (f64)tick_blend);
|
||||||
|
|
||||||
/* Blend entities */
|
/* Blend entities */
|
||||||
u64 num_entities = min_u64(t0->ent_store->num_reserved, t1->ent_store->num_reserved);
|
u64 num_entities = min_u64(t0->ent_store->num_reserved, t1->ent_store->num_reserved);
|
||||||
@ -617,8 +628,8 @@ INTERNAL void user_update(void)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct interp_ticks interp_ticks = pull_ticks(G.time);
|
struct interp_ticks interp_ticks = pull_ticks(G.time);
|
||||||
world_copy_replace(&G.world, interp_ticks.to_tick);
|
world_copy_replace(&G.sim_snapshot, interp_ticks.to_tick);
|
||||||
tick_is_first_frame = G.world.tick_id == 0;
|
tick_is_first_frame = G.sim_snapshot.tick == 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -629,6 +640,7 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
struct sim_event_list sim_events = ZI;
|
struct sim_event_list sim_events = ZI;
|
||||||
{
|
{
|
||||||
|
host_update(G.host);
|
||||||
struct host_event_array host_events = host_pop_events(scratch.arena, G.host);
|
struct host_event_array host_events = host_pop_events(scratch.arena, G.host);
|
||||||
sim_events_from_host_events(scratch.arena, host_events, &sim_events);
|
sim_events_from_host_events(scratch.arena, host_events, &sim_events);
|
||||||
}
|
}
|
||||||
@ -647,6 +659,7 @@ INTERNAL void user_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (struct sim_event *event = sim_events.first; event; event = event->next) {
|
for (struct sim_event *event = sim_events.first; event; event = event->next) {
|
||||||
|
u64 tick = event->tick;
|
||||||
enum sim_event_kind kind = event->kind;
|
enum sim_event_kind kind = event->kind;
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
@ -663,7 +676,7 @@ INTERNAL void user_update(void)
|
|||||||
case SIM_EVENT_KIND_SNAPSHOT:
|
case SIM_EVENT_KIND_SNAPSHOT:
|
||||||
{
|
{
|
||||||
struct string snapshot_data = event->snapshot_data;
|
struct string snapshot_data = event->snapshot_data;
|
||||||
sim_tick_from_string(snapshot_data, &G.world);
|
sim_snapshot_decode(snapshot_data, &G.world, tick);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
@ -782,7 +795,7 @@ INTERNAL void user_update(void)
|
|||||||
f32 shake = ent->shake;
|
f32 shake = ent->shake;
|
||||||
if (shake > 0) {
|
if (shake > 0) {
|
||||||
u64 basis = hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&ent->handle));
|
u64 basis = hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&ent->handle));
|
||||||
u64 angle_seed0 = basis + (u64)(G.world.time_ns / frequency_ns);
|
u64 angle_seed0 = basis + (u64)(G.world.world_time_ns / frequency_ns);
|
||||||
u64 angle_seed1 = angle_seed0 + 1;
|
u64 angle_seed1 = angle_seed0 + 1;
|
||||||
f32 angle0 = rng_noise_f32(angle_seed0, 0, TAU);
|
f32 angle0 = rng_noise_f32(angle_seed0, 0, TAU);
|
||||||
f32 angle1 = rng_noise_f32(angle_seed1, 0, TAU);
|
f32 angle1 = rng_noise_f32(angle_seed1, 0, TAU);
|
||||||
@ -792,7 +805,7 @@ INTERNAL void user_update(void)
|
|||||||
struct v2 vec1 = v2_with_len(v2_from_angle(angle1), shake);
|
struct v2 vec1 = v2_with_len(v2_from_angle(angle1), shake);
|
||||||
|
|
||||||
/* TODO: Cubic interp? */
|
/* TODO: Cubic interp? */
|
||||||
f32 blend = (f32)(G.world.time_ns % frequency_ns) / (f32)frequency_ns;
|
f32 blend = (f32)(G.world.world_time_ns % frequency_ns) / (f32)frequency_ns;
|
||||||
struct v2 vec = v2_lerp(vec0, vec1, blend);
|
struct v2 vec = v2_lerp(vec0, vec1, blend);
|
||||||
|
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
struct xform xf = sim_ent_get_xform(ent);
|
||||||
@ -1620,13 +1633,16 @@ INTERNAL void user_update(void)
|
|||||||
if (font) {
|
if (font) {
|
||||||
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.time_ns))));
|
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("sim tick: %F"), FMT_UINT(G.world.tick)));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("world time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.world.time_ns))));
|
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("sim real time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.world.real_time_ns))));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("entities: %F/%F"), FMT_UINT(G.world.ent_store->num_allocated), FMT_UINT(G.world.ent_store->num_reserved)));
|
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("sim world time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.world.world_time_ns))));
|
||||||
|
pos.y += spacing;
|
||||||
|
|
||||||
|
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("sim entities: %F/%F"), FMT_UINT(G.world.ent_store->num_allocated), FMT_UINT(G.world.ent_store->num_reserved)));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|||||||
34
src/world.c
34
src/world.c
@ -1,34 +0,0 @@
|
|||||||
#include "world.h"
|
|
||||||
#include "sim_ent.h"
|
|
||||||
#include "sim_client.h"
|
|
||||||
#include "arena.h"
|
|
||||||
#include "scratch.h"
|
|
||||||
|
|
||||||
void world_alloc(struct world *world)
|
|
||||||
{
|
|
||||||
MEMZERO_STRUCT(world);
|
|
||||||
world->client_store = sim_client_store_alloc();
|
|
||||||
world->ent_store = sim_ent_store_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
void world_release(struct world *world)
|
|
||||||
{
|
|
||||||
sim_ent_store_release(world->ent_store);
|
|
||||||
sim_client_store_release(world->client_store);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void world_copy_replace(struct world *dest, struct world *src)
|
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
|
||||||
struct world *old = arena_push(scratch.arena, struct world);
|
|
||||||
*old = *dest;
|
|
||||||
|
|
||||||
MEMCPY_STRUCT(dest, src);
|
|
||||||
dest->ent_store = old->ent_store;
|
|
||||||
sim_ent_store_copy_replace(dest->ent_store, src->ent_store);
|
|
||||||
|
|
||||||
scratch_end(scratch);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
30
src/world.h
30
src/world.h
@ -1,30 +0,0 @@
|
|||||||
#ifndef WORLD_H
|
|
||||||
#define WORLD_H
|
|
||||||
|
|
||||||
#include "sim_ent.h"
|
|
||||||
#include "sim_client.h"
|
|
||||||
|
|
||||||
struct world {
|
|
||||||
u64 continuity_gen; /* Starts at 1 */
|
|
||||||
u64 tick_id; /* Starts at 1 */
|
|
||||||
i64 publishtime_ns; /* When was this tick simulated in program time */
|
|
||||||
|
|
||||||
/* World time */
|
|
||||||
f64 timescale;
|
|
||||||
i64 dt_ns;
|
|
||||||
i64 time_ns;
|
|
||||||
|
|
||||||
struct sim_client_handle local_client;
|
|
||||||
|
|
||||||
struct sim_client_store *client_store;
|
|
||||||
struct sim_ent_store *ent_store;
|
|
||||||
};
|
|
||||||
|
|
||||||
void world_alloc(struct world *world);
|
|
||||||
void world_release(struct world *world);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void world_copy_replace(struct world *dest, struct world *src);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Loading…
Reference in New Issue
Block a user