From fd550a7119add8e648042442c391ad94233a6dba Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 11 Feb 2025 12:52:56 -0600 Subject: [PATCH] refactor ent store into snapshot --- src/app.c | 3 +- src/phys.c | 143 +++++++++++++-------------- src/phys.h | 5 +- src/sim.c | 126 ++++++++++++------------ src/sim.h | 2 - src/sim_encode.c | 20 ++-- src/sim_ent.c | 234 ++++++++++++--------------------------------- src/sim_ent.h | 77 +++++---------- src/sim_snapshot.c | 94 +++++++++++++----- src/sim_snapshot.h | 10 +- src/user.c | 27 +++--- src/user.h | 2 - 12 files changed, 321 insertions(+), 422 deletions(-) diff --git a/src/app.c b/src/app.c index 122cd953..25aa6675 100644 --- a/src/app.c +++ b/src/app.c @@ -225,9 +225,8 @@ void app_entry_point(struct string args_str) struct sound_startup_receipt sound_sr = sound_startup(&work_sr, &asset_cache_sr, &resource_sr); struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr); struct phys_startup_receipt phys_sr = phys_startup(); - struct sim_ent_startup_receipt sim_ent_sr = sim_ent_startup(); struct sim_snapshot_startup_receipt sim_snapshot_sr = sim_snapshot_startup(); - struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &asset_cache_sr, &sound_sr, &mixer_sr, &phys_sr, &host_sr, &sim_ent_sr, &sim_snapshot_sr, args_str, &window); + struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &asset_cache_sr, &sound_sr, &mixer_sr, &phys_sr, &host_sr, &sim_snapshot_sr, args_str, &window); struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr); (UNUSED)user_sr; diff --git a/src/phys.c b/src/phys.c index 8b249f25..6e0b3157 100644 --- a/src/phys.c +++ b/src/phys.c @@ -1,4 +1,5 @@ #include "phys.h" +#include "sim_snapshot.h" #include "sim_ent.h" #include "math.h" #include "scratch.h" @@ -43,15 +44,16 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a __prof; struct phys_collision_data_array res = ZI; res.a = arena_dry_push(arena, struct phys_collision_data); - u64 tick = ctx->tick; + struct sim_snapshot *ss = ctx->ss; struct sim_ent_lookup *contact_lookup = ctx->contact_lookup; struct sim_ent_lookup *debug_lookup = ctx->debug_lookup; struct space *space = ctx->space; - struct sim_ent_store *store = ctx->store; - struct sim_ent *root = sim_ent_from_handle(store, SIM_ENT_ROOT_HANDLE); - for (u64 check0_index = 0; check0_index < store->num_reserved; ++check0_index) { - struct sim_ent *check0 = &store->entities[check0_index]; + struct sim_ent *root = sim_ent_from_handle(ss, SIM_ENT_ROOT_HANDLE); + u64 tick = ss->tick; + + for (u64 check0_index = 0; check0_index < ss->num_ents_reserved; ++check0_index) { + struct sim_ent *check0 = &ss->ents[check0_index]; if (!sim_ent_is_valid_and_active(check0)) continue; if (!(sim_ent_has_prop(check0, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check0, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (check0->local_collider.count <= 0) continue; @@ -63,7 +65,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a struct space_iter iter = space_iter_begin_aabb(space, aabb); struct space_entry *space_entry; while ((space_entry = space_iter_next(&iter))) { - struct sim_ent *check1 = sim_ent_from_handle(store, space_entry->ent); + struct sim_ent *check1 = sim_ent_from_handle(ss, space_entry->ent); if (check1 == check0) continue; if (!sim_ent_is_valid_and_active(check1)) continue; if (!(sim_ent_has_prop(check1, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check1, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; @@ -93,11 +95,11 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a } struct sim_ent_lookup_key key = sim_ent_lookup_key_from_two_handles(e0->handle, e1->handle); - struct sim_ent_lookup_entry *constraint_entry= sim_ent_lookup_get(contact_lookup, key); + struct sim_ent_lookup_entry *constraint_entry = sim_ent_lookup_get(contact_lookup, key); struct sim_ent *constraint_ent = sim_ent_nil(); if (constraint_entry) { - constraint_ent = sim_ent_from_handle(store, constraint_entry->entity); + constraint_ent = sim_ent_from_handle(ss, constraint_entry->ent); if (sim_ent_is_valid_and_active(constraint_ent)) { if (constraint_ent->contact_constraint_data.last_phys_iteration >= phys_iteration) { /* Already processed constraint this iteration */ @@ -236,7 +238,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a struct sim_ent *dbg_ent = sim_ent_nil(); struct sim_ent_lookup_entry *dbg_entry = sim_ent_lookup_get(debug_lookup, key); if (dbg_entry) { - dbg_ent = sim_ent_from_handle(store, dbg_entry->entity); + dbg_ent = sim_ent_from_handle(ss, dbg_entry->entity); } if (!dbg_ent->valid) { @@ -282,18 +284,18 @@ void phys_prepare_contacts(struct phys_ctx *ctx, u64 phys_iteration) { __prof; struct sim_ent_lookup *contact_lookup = ctx->contact_lookup; - struct sim_ent_store *store = ctx->store; + struct sim_snapshot *ss = ctx->ss; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *constraint_ent = &store->entities[sim_ent_index]; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *constraint_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(constraint_ent)) continue; if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue; struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data; u32 num_points = constraint->num_points; - struct sim_ent *e0 = sim_ent_from_handle(store, constraint->e0); - struct sim_ent *e1 = sim_ent_from_handle(store, constraint->e1); + struct sim_ent *e0 = sim_ent_from_handle(ss, constraint->e0); + struct sim_ent *e1 = sim_ent_from_handle(ss, constraint->e1); if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) { struct v2 normal = constraint->normal; struct v2 tangent = v2_perp(normal); @@ -375,14 +377,14 @@ void phys_prepare_contacts(struct phys_ctx *ctx, u64 phys_iteration) #if COLLIDER_DEBUG struct sim_ent_lookup *debug_lookup = ctx->debug_lookup; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *dbg_ent = &store->entities[sim_ent_index]; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *dbg_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(dbg_ent)) continue; if (!sim_ent_has_prop(dbg_ent, SIM_ENT_PROP_COLLISION_DEBUG)) continue; struct phys_collision_debug *dbg = &dbg_ent->collision_debug_data; - struct sim_ent *e0 = sim_ent_from_handle(store, dbg->e0); - struct sim_ent *e1 = sim_ent_from_handle(store, dbg->e1); + struct sim_ent *e0 = sim_ent_from_handle(ss, dbg->e0); + struct sim_ent *e1 = sim_ent_from_handle(ss, dbg->e1); if (!sim_ent_is_valid_and_active(e0) || !sim_ent_is_valid_and_active(e1) @@ -409,17 +411,17 @@ void phys_prepare_contacts(struct phys_ctx *ctx, u64 phys_iteration) void phys_warm_start_contacts(struct phys_ctx *ctx) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *constraint_ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *constraint_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(constraint_ent)) continue; if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue; struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data; u32 num_points = constraint->num_points; - struct sim_ent *e0 = sim_ent_from_handle(store, constraint->e0); - struct sim_ent *e1 = sim_ent_from_handle(store, constraint->e1); + struct sim_ent *e0 = sim_ent_from_handle(ss, constraint->e0); + struct sim_ent *e1 = sim_ent_from_handle(ss, constraint->e1); if (num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && !constraint->skip_solve) { struct xform e0_xf = sim_ent_get_xform(e0); @@ -464,16 +466,16 @@ void phys_warm_start_contacts(struct phys_ctx *ctx) void phys_solve_contacts(struct phys_ctx *ctx, f32 dt, b32 apply_bias) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *constraint_ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *constraint_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(constraint_ent)) continue; if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue; struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data; - struct sim_ent *e0 = sim_ent_from_handle(store, constraint->e0); - struct sim_ent *e1 = sim_ent_from_handle(store, constraint->e1); + struct sim_ent *e0 = sim_ent_from_handle(ss, constraint->e0); + struct sim_ent *e1 = sim_ent_from_handle(ss, constraint->e1); struct v2 v0 = e0->linear_velocity; struct v2 v1 = e1->linear_velocity; @@ -595,16 +597,16 @@ struct phys_motor_joint phys_motor_joint_from_def(struct phys_motor_joint_def de void phys_prepare_motor_joints(struct phys_ctx *ctx) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *joint_ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue; struct phys_motor_joint *joint = &joint_ent->motor_joint_data; - struct sim_ent *e0 = sim_ent_from_handle(store, joint->e0); - struct sim_ent *e1 = sim_ent_from_handle(store, joint->e1); + struct sim_ent *e0 = sim_ent_from_handle(ss, joint->e0); + struct sim_ent *e1 = sim_ent_from_handle(ss, joint->e1); if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) { struct xform e0_xf = sim_ent_get_xform(e0); @@ -659,16 +661,16 @@ void phys_prepare_motor_joints(struct phys_ctx *ctx) void phys_warm_start_motor_joints(struct phys_ctx *ctx) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *joint_ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue; struct phys_motor_joint *joint = &joint_ent->motor_joint_data; - struct sim_ent *e0 = sim_ent_from_handle(store, joint->e0); - struct sim_ent *e1 = sim_ent_from_handle(store, joint->e1); + struct sim_ent *e0 = sim_ent_from_handle(ss, joint->e0); + struct sim_ent *e1 = sim_ent_from_handle(ss, joint->e1); struct xform e0_xf = sim_ent_get_xform(e0); struct xform e1_xf = sim_ent_get_xform(e1); @@ -691,16 +693,16 @@ void phys_warm_start_motor_joints(struct phys_ctx *ctx) void phys_solve_motor_joints(struct phys_ctx *ctx, f32 dt) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *joint_ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue; struct phys_motor_joint *joint = &joint_ent->motor_joint_data; - struct sim_ent *e0 = sim_ent_from_handle(store, joint->e0); - struct sim_ent *e1 = sim_ent_from_handle(store, joint->e1); + struct sim_ent *e0 = sim_ent_from_handle(ss, joint->e0); + struct sim_ent *e1 = sim_ent_from_handle(ss, joint->e1); struct xform e0_xf = sim_ent_get_xform(e0); struct xform e1_xf = sim_ent_get_xform(e1); @@ -784,14 +786,14 @@ struct phys_mouse_joint phys_mouse_joint_from_def(struct phys_mouse_joint_def de void phys_prepare_mouse_joints(struct phys_ctx *ctx) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *joint_ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue; struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data; - struct sim_ent *ent = sim_ent_from_handle(store, joint->target); + struct sim_ent *ent = sim_ent_from_handle(ss, joint->target); if (sim_ent_is_valid_and_active(ent)) { struct xform xf = sim_ent_get_xform(ent); @@ -831,14 +833,14 @@ void phys_prepare_mouse_joints(struct phys_ctx *ctx) void phys_warm_start_mouse_joints(struct phys_ctx *ctx) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *joint_ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue; struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data; - struct sim_ent *ent = sim_ent_from_handle(store, joint->target); + struct sim_ent *ent = sim_ent_from_handle(ss, joint->target); if (sim_ent_is_valid_and_active(ent)) { f32 inv_m = joint->inv_m; f32 inv_i = joint->inv_i; @@ -853,14 +855,14 @@ void phys_warm_start_mouse_joints(struct phys_ctx *ctx) void phys_solve_mouse_joints(struct phys_ctx *ctx, f32 dt) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *joint_ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue; struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data; - struct sim_ent *ent = sim_ent_from_handle(store, joint->target); + struct sim_ent *ent = sim_ent_from_handle(ss, joint->target); if (sim_ent_is_valid_and_active(ent)) { struct v2 v = ent->linear_velocity; f32 w = ent->angular_velocity; @@ -940,9 +942,9 @@ INTERNAL struct xform get_derived_xform(struct sim_ent *ent, f32 dt) void phys_integrate_forces(struct phys_ctx *ctx, f32 dt) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; b32 is_dynamic = sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC); @@ -982,9 +984,9 @@ void phys_integrate_forces(struct phys_ctx *ctx, f32 dt) void phys_integrate_velocities(struct phys_ctx *ctx, f32 dt) { __prof; - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC) && !sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC)) continue; @@ -1005,12 +1007,12 @@ void phys_integrate_velocities(struct phys_ctx *ctx, f32 dt) f32 phys_determine_earliest_toi_for_bullets(struct phys_ctx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations) { __prof; - struct sim_ent_store *store = ctx->store; + struct sim_snapshot *ss = ctx->ss; struct space *space = ctx->space; f32 smallest_t = 1; - for (u64 e0_index = 0; e0_index < store->num_reserved; ++e0_index) { - struct sim_ent *e0 = &store->entities[e0_index]; + for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) { + struct sim_ent *e0 = &ss->ents[e0_index]; if (!sim_ent_is_valid_and_active(e0)) continue; if (!(sim_ent_has_prop(e0, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (!sim_ent_has_prop(e0, SIM_ENT_PROP_BULLET)) continue; @@ -1028,7 +1030,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_ctx *ctx, f32 step_dt, f struct space_iter iter = space_iter_begin_aabb(space, combined_aabb); struct space_entry *entry; while ((entry = space_iter_next(&iter))) { - struct sim_ent *e1 = sim_ent_from_handle(store, entry->ent); + struct sim_ent *e1 = sim_ent_from_handle(ss, entry->ent); if (e1 == e0) continue; if (!sim_ent_is_valid_and_active(e1)) continue; if (!(sim_ent_has_prop(e1, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; @@ -1055,9 +1057,9 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_ctx *ctx, f32 step_dt, f void phys_update_aabbs(struct phys_ctx *ctx) { - struct sim_ent_store *store = ctx->store; - for (u64 sim_ent_index = 0; sim_ent_index < store->num_reserved; ++sim_ent_index) { - struct sim_ent *ent = &store->entities[sim_ent_index]; + struct sim_snapshot *ss = ctx->ss; + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (ent->local_collider.count <= 0) continue; @@ -1075,11 +1077,12 @@ void phys_update_aabbs(struct phys_ctx *ctx) * Step * ========================== */ -u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration) +/* Returns phys iteration to be fed into next step. Supplied iteration must be > 0. */ +u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_iteration) { __prof; phys_integrate_forces(ctx, timestep); - u64 phys_iteration = last_phys_iteration; + u64 phys_iteration = last_iteration; f32 remaining_dt = timestep; while (remaining_dt > 0) { diff --git a/src/phys.h b/src/phys.h index f6ffaeda..9820c4f2 100644 --- a/src/phys.h +++ b/src/phys.h @@ -5,7 +5,6 @@ #include "math.h" struct space; -struct sim_ent_store; struct sim_ent_lookup; struct phys_contact_constraint; @@ -30,9 +29,8 @@ typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, collision /* Structure containing data used for a single physics step */ struct phys_ctx { - u64 tick; + struct sim_snapshot *ss; struct space *space; - struct sim_ent_store *store; struct sim_ent_lookup *contact_lookup; phys_collision_callback_func *pre_solve_callback; @@ -210,7 +208,6 @@ void phys_update_aabbs(struct phys_ctx *ctx); * Step * ========================== */ -/* Returns phys iteration to be fed into next step. Supplied iteration must be > 0. */ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 phys_iteration); #endif diff --git a/src/sim.c b/src/sim.c index 23ac927c..9f809f56 100644 --- a/src/sim.c +++ b/src/sim.c @@ -26,7 +26,6 @@ struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr, struct phys_startup_receipt *phys_sr, struct host_startup_receipt *host_sr, - struct sim_ent_startup_receipt *sim_ent_sr, struct sim_snapshot_startup_receipt *sim_snapshot_sr, u16 host_port) { @@ -37,7 +36,6 @@ struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr, (UNUSED)sprite_sr; (UNUSED)phys_sr; (UNUSED)host_sr; - (UNUSED)sim_ent_sr; (UNUSED)sim_snapshot_sr; /* Intialize host */ @@ -83,7 +81,7 @@ void sim_ctx_release(struct sim_ctx *ctx) INTERNAL void spawn_test_entities(struct sim_ctx *ctx) { - struct sim_ent *root = sim_ent_from_handle(ctx->world->ent_store, SIM_ENT_ROOT_HANDLE); + struct sim_ent *root = sim_ent_from_handle(ctx->world, SIM_ENT_ROOT_HANDLE); root->mass_unscaled = F32_INFINITY; root->inertia_unscaled = F32_INFINITY; @@ -156,8 +154,7 @@ INTERNAL void spawn_test_entities(struct sim_ctx *ctx) INTERNAL struct sim_ent *spawn_test_player(struct sim_ctx *ctx) { - struct sim_ent_store *store = ctx->world->ent_store; - struct sim_ent *root = sim_ent_from_handle(store, SIM_ENT_ROOT_HANDLE); + struct sim_ent *root = sim_ent_from_handle(ctx->world, SIM_ENT_ROOT_HANDLE); /* Player */ struct sim_ent *player_ent = sim_ent_nil(); @@ -233,8 +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) { - struct sim_ent_store *store = ctx->world->ent_store; - struct sim_ent *root = sim_ent_from_handle(store, SIM_ENT_ROOT_HANDLE); + struct sim_ent *root = sim_ent_from_handle(ctx->world, SIM_ENT_ROOT_HANDLE); struct sim_ent *camera_ent = sim_ent_nil(); if (player_ent->valid) { @@ -260,13 +256,12 @@ 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) { struct temp_arena scratch = scratch_begin_no_conflict(); - struct sim_ent_store *store = ctx->world->ent_store; struct space *space = ctx->space; struct sim_ent **ents_to_release = arena_dry_push(scratch.arena, struct sim_ent *); u64 ents_to_release_count = 0; - for (u64 ent_index = 0; ent_index < store->num_reserved; ++ent_index) { - struct sim_ent *ent = &store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!ent->valid) continue; if (sim_ent_has_prop(ent, prop)) { @@ -293,7 +288,7 @@ INTERNAL void release_entities_with_prop(struct sim_ctx *ctx, enum sim_ent_prop for (u64 i = 0; i < ents_to_release_count; ++i) { struct sim_ent *ent = ents_to_release[i]; if (ent->valid) { - sim_ent_release(store, ent); + sim_ent_release(ctx->world, ent); } } @@ -307,15 +302,14 @@ 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) { struct sim_ctx *ctx = (struct sim_ctx *)udata; - struct sim_ent_store *store = ctx->world->ent_store; - struct sim_ent *root = sim_ent_from_handle(store, SIM_ENT_ROOT_HANDLE); + struct sim_ent *root = sim_ent_from_handle(ctx->world, SIM_ENT_ROOT_HANDLE); for (u64 i = 0; i < collision_data_array.count; ++i) { struct phys_collision_data *data = &collision_data_array.a[i]; struct phys_contact_constraint *constraint = data->constraint; - struct sim_ent *e0 = sim_ent_from_handle(store, data->e0); - struct sim_ent *e1 = sim_ent_from_handle(store, data->e1); + struct sim_ent *e0 = sim_ent_from_handle(ctx->world, data->e0); + struct sim_ent *e1 = sim_ent_from_handle(ctx->world, data->e1); if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) { /* Bullet hit entity */ @@ -331,7 +325,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, ud normal = v2_neg(normal); vrel = v2_neg(vrel); } - struct sim_ent *src = sim_ent_from_handle(store, bullet->bullet_src); + struct sim_ent *src = sim_ent_from_handle(ctx->world, bullet->bullet_src); if (bullet->bullet_has_hit || sim_ent_handle_eq(src->top, target->top)) { /* Ignore collision if bullet already spent or if weapon and @@ -346,7 +340,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, ud sim_ent_enable_prop(bullet, SIM_ENT_PROP_RELEASE_THIS_TICK); /* Update tracer */ - struct sim_ent *tracer = sim_ent_from_handle(store, bullet->bullet_tracer); + struct sim_ent *tracer = sim_ent_from_handle(ctx->world, bullet->bullet_tracer); if (sim_ent_is_valid_and_active(tracer)) { struct xform xf = sim_ent_get_xform(tracer); xf.og = point; @@ -443,11 +437,10 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) (UNUSED)world_dt; (UNUSED)world_time; - struct sim_ent_store *ent_store = ctx->world->ent_store; struct space *space = ctx->space; struct sprite_scope *sprite_frame_scope = ctx->sprite_frame_scope; - struct sim_ent *root = sim_ent_from_handle(ctx->world->ent_store, SIM_ENT_ROOT_HANDLE); + struct sim_ent *root = sim_ent_from_handle(ctx->world, SIM_ENT_ROOT_HANDLE); /* ========================== * * Spawn test entities @@ -473,8 +466,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Activate entities * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!ent->valid) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ACTIVE)) { @@ -489,8 +482,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Reset triggered entities * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGER_NEXT_TICK)) { @@ -647,8 +640,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Update entity control from client control * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) { @@ -669,8 +662,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Update entities from sprite * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (sprite_tag_is_nil(ent->sprite)) continue; @@ -764,12 +757,12 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Update attachments * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ATTACHED)) continue; - struct sim_ent *parent = sim_ent_from_handle(ent_store, ent->parent); + struct sim_ent *parent = sim_ent_from_handle(ctx->world, ent->parent); struct sprite_tag parent_sprite = parent->sprite; struct sprite_sheet *parent_sheet = sprite_sheet_from_tag_await(sprite_frame_scope, parent_sprite); @@ -790,8 +783,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * ========================== */ #if 0 - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_TEST)) continue; @@ -840,12 +833,12 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Trigger equipped * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED)) { - struct sim_ent *eq = sim_ent_from_handle(ent_store, ent->equipped); + struct sim_ent *eq = sim_ent_from_handle(ctx->world, ent->equipped); if (sim_ent_is_valid_and_active(eq)) { sim_ent_enable_prop(eq, SIM_ENT_PROP_TRIGGERED_THIS_TICK); } @@ -856,8 +849,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Process triggered entities * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGERED_THIS_TICK)) continue; if ((sim_time - ent->last_triggered < ent->trigger_delay) && ent->last_triggered != 0) continue; @@ -919,12 +912,12 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Create motor joints from control move * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) { - struct sim_ent *joint_ent = sim_ent_from_handle(ent_store, ent->move_joint); + struct sim_ent *joint_ent = sim_ent_from_handle(ctx->world, ent->move_joint); if (!sim_ent_is_valid_and_active(joint_ent)) { joint_ent = sim_ent_alloc(root); joint_ent->mass_unscaled = F32_INFINITY; @@ -952,8 +945,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * ========================== */ #if SIM_PLAYER_AIM - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) { @@ -961,7 +954,7 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) struct xform sprite_xf = xform_mul(xf, ent->sprite_local_xform); /* Retrieve / create aim joint */ - struct sim_ent *joint_ent = sim_ent_from_handle(ent_store, ent->aim_joint); + struct sim_ent *joint_ent = sim_ent_from_handle(ctx->world, ent->aim_joint); if (!sim_ent_is_valid_and_active(joint_ent)) { joint_ent = sim_ent_alloc(root); joint_ent->mass_unscaled = F32_INFINITY; @@ -1045,12 +1038,12 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Create motor joints from ground friction (gravity) * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC)) continue; - struct sim_ent *joint_ent = sim_ent_from_handle(ent_store, ent->ground_friction_joint); + struct sim_ent *joint_ent = sim_ent_from_handle(ctx->world, ent->ground_friction_joint); struct phys_motor_joint_def def = ZI; def.e0 = root->handle; @@ -1080,8 +1073,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) b32 start_dragging = client->dbg_drag_start; b32 stop_dragging = client->dbg_drag_stop; - struct sim_ent *joint_ent = sim_ent_from_handle(ent_store, client->dbg_drag_joint_ent); - struct sim_ent *target_ent = sim_ent_from_handle(ent_store, joint_ent->mouse_joint_data.target); + struct sim_ent *joint_ent = sim_ent_from_handle(ctx->world, client->dbg_drag_joint_ent); + struct sim_ent *target_ent = sim_ent_from_handle(ctx->world, joint_ent->mouse_joint_data.target); if (start_dragging) { struct xform mouse_xf = xform_from_pos(cursor); @@ -1089,8 +1082,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) mouse_shape.points[0] = V2(0, 0); mouse_shape.count = 1; - for (u64 sim_ent_index = 0; sim_ent_index < ent_store->num_reserved; ++sim_ent_index) { - struct sim_ent *ent = &ent_store->entities[sim_ent_index]; + for (u64 sim_ent_index = 0; sim_ent_index < ctx->world->num_ents_reserved; ++sim_ent_index) { + struct sim_ent *ent = &ctx->world->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC)) continue; @@ -1145,8 +1138,7 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) { struct phys_ctx phys = ZI; - phys.tick = ctx->world->tick; - phys.store = ent_store; + phys.ss = ctx->world; phys.space = space; phys.contact_lookup = &ctx->contact_lookup; phys.pre_solve_callback = on_collision; @@ -1163,8 +1155,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Update tracers * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_TRACER)) continue; @@ -1187,13 +1179,13 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Initialize bullet kinematics from sources * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_BULLET)) continue; 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(ctx->world, ent->bullet_src); struct xform src_xf = sim_ent_get_xform(src); struct v2 pos = xform_mul_v2(src_xf, ent->bullet_src_pos); @@ -1204,7 +1196,7 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) /* Add shooter velocity to bullet */ { /* TODO: Add angular velocity as well? */ - struct sim_ent *top = sim_ent_from_handle(ent_store, src->top); + struct sim_ent *top = sim_ent_from_handle(ctx->world, src->top); impulse = v2_add(impulse, v2_mul(top->linear_velocity, dt)); } #endif @@ -1216,7 +1208,7 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) sim_ent_apply_linear_impulse_to_center(ent, impulse); /* Initialize tracer */ - struct sim_ent *tracer = sim_ent_from_handle(ent_store, ent->bullet_tracer); + struct sim_ent *tracer = sim_ent_from_handle(ctx->world, ent->bullet_tracer); if (sim_ent_is_valid_and_active(tracer)) { sim_ent_set_xform(tracer, xf); sim_ent_enable_prop(tracer, SIM_ENT_PROP_PHYSICAL_KINEMATIC); @@ -1242,8 +1234,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Update cameras * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_CAMERA)) continue; @@ -1251,7 +1243,7 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) /* Camera follow */ { - struct sim_ent *follow = sim_ent_from_handle(ent_store, ent->camera_follow); + struct sim_ent *follow = sim_ent_from_handle(ctx->world, ent->camera_follow); f32 aspect_ratio = 1.0; { @@ -1283,8 +1275,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) { /* TODO: Update based on distance to quake */ ent->shake = 0; - for (u64 quake_ent_index = 0; quake_ent_index < ent_store->num_reserved; ++quake_ent_index) { - struct sim_ent *quake = &ent_store->entities[quake_ent_index]; + for (u64 quake_ent_index = 0; quake_ent_index < ctx->world->num_ents_reserved; ++quake_ent_index) { + struct sim_ent *quake = &ctx->world->ents[quake_ent_index]; if (!sim_ent_is_valid_and_active(quake)) continue; if (!sim_ent_has_prop(quake, SIM_ENT_PROP_QUAKE)) continue; ent->shake += quake->quake_intensity; @@ -1298,8 +1290,8 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) * Update quakes * ========================== */ - for (u64 ent_index = 0; ent_index < ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < ctx->world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &ctx->world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_QUAKE)) continue; @@ -1326,7 +1318,7 @@ void sim_update(struct sim_ctx *ctx, i64 target_dt_ns) --stack_count; i32 parent_layer = parent->final_layer; - for (struct sim_ent *child = sim_ent_from_handle(ent_store, parent->first); child->valid; child = sim_ent_from_handle(ent_store, child->next)) { + for (struct sim_ent *child = sim_ent_from_handle(ctx->world, parent->first); child->valid; child = sim_ent_from_handle(ctx->world, child->next)) { if (sim_ent_is_valid_and_active(child)) { child->final_layer = parent_layer + child->layer; *arena_push(temp.arena, struct sim_ent *) = child; diff --git a/src/sim.h b/src/sim.h index 02a8ace8..dfbd39ae 100644 --- a/src/sim.h +++ b/src/sim.h @@ -7,7 +7,6 @@ struct sprite_startup_receipt; struct phys_startup_receipt; struct host_startup_receipt; -struct sim_ent_startup_receipt; struct sim_snapshot_startup_receipt; /* ========================== * @@ -149,7 +148,6 @@ struct sim_ctx { struct sim_ctx *sim_ctx_alloc(struct sprite_startup_receipt *sprite_sr, struct phys_startup_receipt *phys_sr, struct host_startup_receipt *host_sr, - struct sim_ent_startup_receipt *sim_ent_sr, struct sim_snapshot_startup_receipt *sim_snapshot_sr, u16 host_port); diff --git a/src/sim_encode.c b/src/sim_encode.c index d5f9f013..46a6c789 100644 --- a/src/sim_encode.c +++ b/src/sim_encode.c @@ -239,11 +239,11 @@ struct string sim_encode_snapshot(struct arena *arena, struct sim_client *client br_write_bytes(&bw, clients_src); /* Entity store */ - u64 num_entities = snapshot->ent_store->num_reserved; + u64 num_entities = snapshot->num_ents_reserved; bw_write_var_uint(&bw, num_entities); struct string entities_src = ZI; - entities_src.text = (u8 *)snapshot->ent_store->entities; + entities_src.text = (u8 *)snapshot->ents; entities_src.len = sizeof(struct sim_ent) * num_entities; br_write_bytes(&bw, entities_src); @@ -287,17 +287,17 @@ void sim_decode_snapshot(struct string str, struct sim_snapshot *snapshot) /* Entity store */ u64 num_entities = br_read_var_uint(&br); - arena_push_array(&snapshot->ent_store->arena, struct sim_ent, num_entities - snapshot->ent_store->num_reserved); - snapshot->ent_store->num_reserved = num_entities; + arena_push_array(&snapshot->ents_arena, struct sim_ent, num_entities - snapshot->num_ents_reserved); + snapshot->num_ents_reserved = num_entities; - snapshot->ent_store->num_allocated = 0; + snapshot->num_ents_allocated = 0; struct sim_ent *entities_src = br_seek(&br, num_entities * sizeof(struct sim_ent)); if (entities_src) { for (u64 i = 0; i < num_entities; ++i) { struct sim_ent *src = &entities_src[i]; - struct sim_ent *dst = &snapshot->ent_store->entities[i]; + struct sim_ent *dst = &snapshot->ents[i]; if (dst->valid) { - ++snapshot->ent_store->num_allocated; + ++snapshot->num_ents_allocated; } *dst = *src; } @@ -581,9 +581,9 @@ struct string sim_encode_snapshot(struct sim_encoder *enc, struct sim_snapshot * br_write_bytes(&bw, clients_src); /* Ents */ - for (u64 i = 0; i < snapshot->ent_store->num_reserved; ++i) { + for (u64 i = 0; i < snapshot->num_ents_reserved; ++i) { bw_write_u8(bw, 1); - struct sim_ent *ent = &snapshot->ent_store->entities[i]; + struct sim_ent *ent = &snapshot->ents[i]; sim_encode_ent(enc, ent); } bw_write_u8(bw, 0); @@ -629,7 +629,7 @@ struct sim_snapshot *sim_decode_snapshot(struct sim_decoder *dec, struct sim_sna /* Ents */ b32 read_entity = br_read_u8(br); while (read_entity) { - sim_decode_ent(dec, snapshot->ent_store); + sim_decode_ent(dec, snapshot); read_entity = br_read_u8(br); }f } diff --git a/src/sim_ent.c b/src/sim_ent.c index 0b59994b..7e36f73d 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -1,202 +1,90 @@ #include "sim_ent.h" +#include "sim_snapshot.h" #include "math.h" -/* Offset in bytes from start of store struct to start of entities array (assume adjacently allocated) */ -#define STORE_ENTITIES_OFFSET (sizeof(struct sim_ent_store) + (sizeof(struct sim_ent_store) % alignof(struct sim_ent))) - -/* ========================== * - * Global state - * ========================== */ - - -GLOBAL struct { - struct sim_ent *nil_ent; - struct sim_ent_store *nil_store; -} G = ZI, DEBUG_ALIAS(G, G_sim_ent); - -/* Accessed via sim_ent_nil() */ -READONLY struct sim_ent **_g_sim_ent_nil = &G.nil_ent; - -/* Accessed via sim_ent_store_nil() */ -READONLY struct sim_ent_store **_g_sim_ent_store_nil = &G.nil_store; - -struct sim_ent_startup_receipt sim_ent_startup(void) -{ - /* Setup nil store */ - G.nil_store = sim_ent_store_alloc(GIGABYTE(1), false); - - /* Setup nil ent */ - G.nil_ent = arena_push_zero(&G.nil_store->arena, struct sim_ent); - ++G.nil_store->num_allocated; - ++G.nil_store->num_reserved; - MEMZERO_STRUCT(G.nil_ent); - G.nil_ent->handle = SIM_ENT_NIL_HANDLE; - G.nil_ent->local_xform = XFORM_IDENT; - G.nil_ent->cached_global_xform = XFORM_IDENT; - G.nil_ent->cached_global_xform_dirty = false; - G.nil_ent->friction = 0.5f; - G.nil_ent->mass_unscaled = 1; - G.nil_ent->inertia_unscaled = 1; - G.nil_ent->sprite_local_xform = XFORM_IDENT; - G.nil_ent->sprite_tint = COLOR_WHITE; - - G.nil_ent->valid = false; - G.nil_store->valid = false; - - arena_set_readonly(&G.nil_store->arena); - return (struct sim_ent_startup_receipt) { 0 }; -} - -/* ========================== * - * Store allocation - * ========================== */ - -INTERNAL struct sim_ent *sim_ent_alloc_internal(struct sim_ent_store *store); - -struct sim_ent_store *sim_ent_store_alloc(u64 arena_reserve, b32 create_root) -{ - struct sim_ent_store *store; - { - struct arena arena = arena_alloc(arena_reserve); - store = arena_push_zero(&arena, struct sim_ent_store); - store->arena = arena; - } - store->valid = true; - - store->entities = arena_dry_push(&store->arena, struct sim_ent); - ASSERT((u8 *)store->entities - (u8 *)store == STORE_ENTITIES_OFFSET); /* Offset must be correct */ - - /* Create root entity */ - if (create_root) { - struct sim_ent *root = sim_ent_alloc_internal(store); - ASSERT(sim_ent_handle_eq(root->handle, SIM_ENT_ROOT_HANDLE)); - root->is_root = true; - } - - return store; -} - -void sim_ent_store_copy(struct sim_ent_store *dst, struct sim_ent_store *src) -{ - i64 commit_diff = (i64)src->arena.pos - (i64)dst->arena.pos; - if (commit_diff > 0) { - arena_push_array(&dst->arena, u8, commit_diff); - } - arena_pop_to(&dst->arena, src->arena.pos); - - dst->first_free = src->first_free; - dst->entities = (struct sim_ent *)((u8 *)dst + ((u8 *)src->entities - (u8 *)src)); - dst->num_allocated = src->num_allocated; - dst->num_reserved = src->num_reserved; - - MEMCPY(dst->entities, src->entities, sizeof(*src->entities) * src->num_reserved); - - /* Re-initialize root in case of copy from nil store */ - struct sim_ent *root = &dst->entities[0]; - root->handle = SIM_ENT_ROOT_HANDLE; - root->valid = true; - root->is_root = true; -} - -void sim_ent_store_release(struct sim_ent_store *store) -{ - arena_release(&store->arena); -} - /* ========================== * * Entity allocation * ========================== */ -INTERNAL struct sim_ent *sim_ent_alloc_internal(struct sim_ent_store *store) +INTERNAL struct sim_ent *sim_ent_alloc_internal(struct sim_snapshot *ss) { - struct sim_ent *entity = NULL; + struct sim_ent *ent = NULL; struct sim_ent_handle handle = ZI; - if (store->first_free.gen) { + if (ss->first_free_ent.gen) { /* Reuse from free list */; - entity = sim_ent_from_handle(store, store->first_free); - handle = entity->handle; + ent = sim_ent_from_handle(ss, ss->first_free_ent); + handle = ent->handle; ++handle.gen; - store->first_free = entity->next_free; + ss->first_free_ent = ent->next_free; } else { /* Make new */ - entity = arena_push(&store->arena, struct sim_ent); - handle = (struct sim_ent_handle) { .gen = 1, .idx = store->num_reserved++ }; + ent = arena_push(&ss->ents_arena, struct sim_ent); + handle = (struct sim_ent_handle) { .gen = 1, .idx = ss->num_ents_reserved++ }; } - *entity = *sim_ent_nil(); - entity->valid = true; - entity->handle = handle; - entity->cached_global_xform_dirty = true; - ++store->num_allocated; - return entity; + *ent = *sim_ent_nil(); + ent->ss = ss; + ent->valid = true; + ent->handle = handle; + ent->cached_global_xform_dirty = true; + ++ss->num_ents_allocated; + return ent; } struct sim_ent *sim_ent_alloc(struct sim_ent *parent) { ASSERT(parent->valid); - struct sim_ent_store *store = sim_ent_store_from_ent(parent); - struct sim_ent *e = sim_ent_alloc_internal(store); + struct sim_snapshot *ss = parent->ss; + struct sim_ent *e = sim_ent_alloc_internal(ss); sim_ent_link_parent(e, parent); return e; } -INTERNAL void sim_ent_release_internal(struct sim_ent_store *store, struct sim_ent *ent) +INTERNAL void sim_ent_release_internal(struct sim_snapshot *ss, struct sim_ent *ent) { /* Release children */ struct sim_ent_handle first_handle = ent->first; if (first_handle.gen) { - for (struct sim_ent *child = sim_ent_from_handle(store, first_handle); child->valid; child = sim_ent_from_handle(store, child->next)) { - sim_ent_release_internal(store, child); + for (struct sim_ent *child = sim_ent_from_handle(ss, first_handle); child->valid; child = sim_ent_from_handle(ss, child->next)) { + sim_ent_release_internal(ss, child); } } /* Release */ ++ent->handle.gen; ent->valid = false; - ent->next_free = store->first_free; - store->first_free = ent->handle; - --store->num_allocated; + ent->next_free = ss->first_free_ent; + ss->first_free_ent = ent->handle; + --ss->num_ents_allocated; } -void sim_ent_release(struct sim_ent_store *store, struct sim_ent *ent) +void sim_ent_release(struct sim_snapshot *ss, struct sim_ent *ent) { if (ent->parent.gen) { sim_ent_unlink_from_parent(ent); } - sim_ent_release_internal(store, ent); + sim_ent_release_internal(ss, ent); } /* ========================== * * Query * ========================== */ -struct sim_ent_store *sim_ent_store_from_ent(struct sim_ent *ent) +/* Returns a valid ent or read-only nil ent. Always safe to read result, need to check `valid` to write. */ +struct sim_ent *sim_ent_from_handle(struct sim_snapshot *ss, struct sim_ent_handle handle) { - if (ent->valid) { - u64 first_ent_addr = (u64)(ent - ent->handle.idx); - struct sim_ent_store *store = (struct sim_ent_store *)(first_ent_addr - STORE_ENTITIES_OFFSET); - ASSERT(store->entities == (struct sim_ent *)first_ent_addr); - return store; - } else { - return sim_ent_store_nil(); - } -} - -/* Returns a valid entity or read-only nil entity. Always safe to read result, need to check `valid` to write. */ -struct sim_ent *sim_ent_from_handle(struct sim_ent_store *store, struct sim_ent_handle handle) -{ - if (handle.gen != 0 && handle.idx < store->num_reserved) { - struct sim_ent *entity = &store->entities[handle.idx]; - if (entity->handle.gen == handle.gen) { - return entity; + if (handle.gen != 0 && handle.idx < ss->num_ents_reserved) { + struct sim_ent *ent = &ss->ents[handle.idx]; + if (ent->handle.gen == handle.gen) { + return ent; } } return sim_ent_nil(); } -struct sim_ent *sim_ent_find_first_match_one(struct sim_ent_store *store, enum sim_ent_prop prop) +struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop) { - u64 count = store->num_reserved; - struct sim_ent *entities = store->entities; + u64 count = ss->num_ents_reserved; + struct sim_ent *entities = ss->ents; for (u64 ent_index = 0; ent_index < count; ++ent_index) { struct sim_ent *ent = &entities[ent_index]; if (ent->valid && sim_ent_has_prop(ent, prop)) { @@ -206,10 +94,10 @@ struct sim_ent *sim_ent_find_first_match_one(struct sim_ent_store *store, enum s return sim_ent_nil(); } -struct sim_ent *sim_ent_find_first_match_all(struct sim_ent_store *store, struct sim_ent_prop_array props) +struct sim_ent *sim_ent_find_first_match_all(struct sim_snapshot *ss, struct sim_ent_prop_array props) { - u64 count = store->num_reserved; - struct sim_ent *entities = store->entities; + u64 count = ss->num_ents_reserved; + struct sim_ent *entities = ss->ents; for (u64 ent_index = 0; ent_index < count; ++ent_index) { struct sim_ent *ent = &entities[ent_index]; if (ent->valid) { @@ -232,27 +120,27 @@ struct sim_ent *sim_ent_find_first_match_all(struct sim_ent_store *store, struct * Xform * ========================== */ -INTERNAL void sim_ent_mark_child_xforms_dirty(struct sim_ent_store *store, struct sim_ent *ent) +INTERNAL void sim_ent_mark_child_xforms_dirty(struct sim_snapshot *ss, struct sim_ent *ent) { - for (struct sim_ent *child = sim_ent_from_handle(store, ent->first); child->valid; child = sim_ent_from_handle(store, child->next)) { + for (struct sim_ent *child = sim_ent_from_handle(ss, ent->first); child->valid; child = sim_ent_from_handle(ss, child->next)) { if (child->cached_global_xform_dirty) { break; } else { child->cached_global_xform_dirty = true; - sim_ent_mark_child_xforms_dirty(store, child); + sim_ent_mark_child_xforms_dirty(ss, child); } } } -INTERNAL struct xform sim_ent_get_xform_w_store(struct sim_ent_store *store, struct sim_ent *ent) +INTERNAL struct xform sim_ent_get_xform_internal(struct sim_snapshot *ss, struct sim_ent *ent) { struct xform xf; if (ent->cached_global_xform_dirty) { if (ent->is_top) { xf = ent->local_xform; } else { - struct sim_ent *parent = sim_ent_from_handle(store, ent->parent); - xf = sim_ent_get_xform_w_store(store, parent); + struct sim_ent *parent = sim_ent_from_handle(ss, ent->parent); + xf = sim_ent_get_xform_internal(ss, parent); xf = xform_mul(xf, ent->local_xform); ent->cached_global_xform = xf; ent->cached_global_xform_dirty = false; @@ -272,9 +160,9 @@ struct xform sim_ent_get_xform(struct sim_ent *ent) if (ent->is_top) { xf = ent->local_xform; } else { - struct sim_ent_store *store = sim_ent_store_from_ent(ent); - struct sim_ent *parent = sim_ent_from_handle(store, ent->parent); - xf = sim_ent_get_xform_w_store(store, parent); + struct sim_snapshot *ss = ent->ss; + struct sim_ent *parent = sim_ent_from_handle(ss, ent->parent); + xf = sim_ent_get_xform_internal(ss, parent); xf = xform_mul(xf, ent->local_xform); ent->cached_global_xform = xf; ent->cached_global_xform_dirty = false; @@ -295,18 +183,18 @@ struct xform sim_ent_get_local_xform(struct sim_ent *ent) void sim_ent_set_xform(struct sim_ent *ent, struct xform xf) { if (!xform_eq(xf, ent->cached_global_xform)) { - struct sim_ent_store *store = sim_ent_store_from_ent(ent); + struct sim_snapshot *ss = ent->ss; /* Update local xform */ if (ent->is_top) { ent->local_xform = xf; } else { - struct sim_ent *parent = sim_ent_from_handle(store, ent->parent); - struct xform parent_global = sim_ent_get_xform_w_store(store, parent); + struct sim_ent *parent = sim_ent_from_handle(ss, ent->parent); + struct xform parent_global = sim_ent_get_xform_internal(ss, parent); ent->local_xform = xform_mul(xform_invert(parent_global), xf); } ent->cached_global_xform = xf; ent->cached_global_xform_dirty = false; - sim_ent_mark_child_xforms_dirty(store, ent); + sim_ent_mark_child_xforms_dirty(ss, ent); } } @@ -315,7 +203,7 @@ void sim_ent_set_local_xform(struct sim_ent *ent, struct xform xf) if (!xform_eq(xf, ent->local_xform)) { ent->local_xform = xf; ent->cached_global_xform_dirty = true; - sim_ent_mark_child_xforms_dirty(sim_ent_store_from_ent(ent), ent); + sim_ent_mark_child_xforms_dirty(ent->ss, ent); } } @@ -369,7 +257,7 @@ void sim_ent_apply_torque(struct sim_ent *ent, f32 torque) void sim_ent_link_parent(struct sim_ent *ent, struct sim_ent *parent) { - struct sim_ent_store *store = sim_ent_store_from_ent(ent); + struct sim_snapshot *ss = ent->ss; if (ent->parent.gen) { /* Unlink from current parent */ @@ -382,7 +270,7 @@ void sim_ent_link_parent(struct sim_ent *ent, struct sim_ent *parent) ent->parent = parent_handle; struct sim_ent_handle last_child_handle = parent->last; - struct sim_ent *last_child = sim_ent_from_handle(store, last_child_handle); + struct sim_ent *last_child = sim_ent_from_handle(ss, last_child_handle); if (last_child->valid) { ent->prev = last_child_handle; last_child->next = handle; @@ -399,15 +287,15 @@ void sim_ent_link_parent(struct sim_ent *ent, struct sim_ent *parent) } } -/* NOTE: Entity will be dangling after calling this, should re-link to root entity. */ +/* NOTE: Entity will be dangling after calling this, should re-link to root ent. */ void sim_ent_unlink_from_parent(struct sim_ent *ent) { - struct sim_ent_store *store = sim_ent_store_from_ent(ent); + struct sim_snapshot *ss = ent->ss; struct sim_ent_handle parent_handle = ent->parent; - struct sim_ent *parent = sim_ent_from_handle(store, parent_handle); - struct sim_ent *prev = sim_ent_from_handle(store, ent->prev); - struct sim_ent *next = sim_ent_from_handle(store, ent->next); + struct sim_ent *parent = sim_ent_from_handle(ss, parent_handle); + struct sim_ent *prev = sim_ent_from_handle(ss, ent->prev); + struct sim_ent *next = sim_ent_from_handle(ss, ent->next); /* Unlink from parent & siblings */ if (prev->valid) { @@ -475,7 +363,7 @@ void sim_ent_lookup_set(struct sim_ent_lookup *l, struct sim_ent_lookup_key key, struct sim_ent_lookup_entry *entry = *slot; if (entry) { /* Set existing entry */ - entry->entity = handle; + entry->ent = handle; } else { /* Allocate entry */ if (l->first_free_entry) { @@ -488,7 +376,7 @@ void sim_ent_lookup_set(struct sim_ent_lookup *l, struct sim_ent_lookup_key key, MEMZERO_STRUCT(entry); entry->key = key; - entry->entity = handle; + entry->ent = handle; if (prev) { entry->prev = prev; prev->next = entry; diff --git a/src/sim_ent.h b/src/sim_ent.h index 8d25a093..ff925ff7 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -56,7 +56,7 @@ struct sim_ent_lookup_key { struct sim_ent_lookup_entry { struct sim_ent_lookup_key key; - struct sim_ent_handle entity; + struct sim_ent_handle ent; struct sim_ent_lookup_entry *next; struct sim_ent_lookup_entry *prev; }; @@ -75,7 +75,7 @@ struct sim_ent_lookup { struct sim_control { struct v2 move; /* Movement direction vector (speed of 0 -> 1) */ - struct v2 focus; /* Focus direction vector (where should the entity look) */ + struct v2 focus; /* Focus direction vector (where should the ent look) */ b32 firing; }; @@ -85,17 +85,18 @@ struct sim_ent { b32 valid; /* Is this ent allocated in memory that can be written to (can always be read) */ struct sim_ent_handle handle; - u64 continuity_gen; - u64 props[(SIM_ENT_PROP_COUNT + 63) / 64]; - struct sim_ent_handle next_free; + struct sim_snapshot *ss; - /* Is this the root entity */ + u64 props[(SIM_ENT_PROP_COUNT + 63) / 64]; + u64 continuity_gen; + + /* Is this the root ent */ b32 is_root; - /* Is entity a child of the root entity */ + /* Is ent a child of the root ent */ b32 is_top; - /* The handle of the top level parent of the entity */ + /* The handle of the top level parent of the ent */ struct sim_ent_handle top; /* Tree */ @@ -104,26 +105,27 @@ struct sim_ent { struct sim_ent_handle prev; struct sim_ent_handle first; struct sim_ent_handle last; + struct sim_ent_handle next_free; /* ====================================================================== */ /* Position */ /* Access with xform getters/setters */ - struct xform local_xform; /* Transform in relation to parent entity (or the world if entity has no parent) */ - struct xform cached_global_xform; /* Calculated from entity tree */ + struct xform local_xform; /* Transform in relation to parent ent (or the world if ent has no parent) */ + struct xform cached_global_xform; /* Calculated from ent tree */ b32 cached_global_xform_dirty; /* ====================================================================== */ /* Activation */ - /* If 0, the entity will auto activate at start of next tick if not already active. */ + /* If 0, the ent will auto activate at start of next tick if not already active. */ u64 activation_tick; /* ====================================================================== */ /* Layer */ i32 layer; - i32 final_layer; /* Calculated each tick from entity tree */ + i32 final_layer; /* Calculated each tick from ent tree */ /* ====================================================================== */ /* Collider */ @@ -180,8 +182,8 @@ struct sim_ent { f32 friction; - f32 mass_unscaled; /* Mass of entity in kg before any transformations */ - f32 inertia_unscaled; /* Inertia of entity in kg*m^2 before any transformations */ + f32 mass_unscaled; /* Mass of ent in kg before any transformations */ + f32 inertia_unscaled; /* Inertia of ent in kg*m^2 before any transformations */ struct sim_ent_handle ground_friction_joint; f32 linear_ground_friction; @@ -206,7 +208,7 @@ struct sim_ent { struct string sprite_collider_slice; /* Collider will sync to bounds of this slice if set */ - struct xform sprite_local_xform; /* Sprite transform in relation to entity */ + struct xform sprite_local_xform; /* Sprite transform in relation to ent */ /* ====================================================================== */ /* Animation */ @@ -219,7 +221,7 @@ struct sim_ent { /* Attachment */ /* SIM_ENT_PROP_ATTACHED */ - /* Slice name on the parent entity's sprite to attach to */ + /* Slice name on the parent ent's sprite to attach to */ struct string attach_slice; /* ====================================================================== */ @@ -295,18 +297,8 @@ struct sim_ent { f32 shake; }; -struct sim_ent_store { - b32 valid; - struct arena arena; - - struct sim_ent_handle first_free; - struct sim_ent *entities; - u64 num_allocated; - u64 num_reserved; -}; - struct sim_ent_array { - struct sim_ent *entities; + struct sim_ent *ents; u64 count; }; @@ -315,13 +307,6 @@ struct sim_ent_prop_array { u64 count; }; -/* ========================== * - * Startup - * ========================== */ - -struct sim_ent_startup_receipt { i32 _; }; -struct sim_ent_startup_receipt sim_ent_startup(void); - /* ========================== * * Handle helpers * ========================== */ @@ -341,12 +326,6 @@ INLINE struct sim_ent *sim_ent_nil(void) return *_g_sim_ent_nil; } -INLINE struct sim_ent_store *sim_ent_store_nil(void) -{ - extern READONLY struct sim_ent_store **_g_sim_ent_store_nil; - return *_g_sim_ent_store_nil; -} - /* ========================== * * Property helpers * ========================== */ @@ -378,17 +357,12 @@ INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent) } /* ========================== * - * Entity functions + * Ent functions * ========================== */ -/* Entity store */ -struct sim_ent_store *sim_ent_store_alloc(u64 arena_reserve, b32 create_root); -void sim_ent_store_copy(struct sim_ent_store *dst, struct sim_ent_store *src); -void sim_ent_store_release(struct sim_ent_store *store); - -/* Entity */ +/* Alloc */ struct sim_ent *sim_ent_alloc(struct sim_ent *parent); -void sim_ent_release(struct sim_ent_store *store, struct sim_ent *ent); +void sim_ent_release(struct sim_snapshot *ss, struct sim_ent *ent); /* Xform */ struct xform sim_ent_get_xform(struct sim_ent *ent); @@ -406,10 +380,9 @@ void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse); void sim_ent_apply_torque(struct sim_ent *ent, f32 torque); /* Query */ -struct sim_ent_store *sim_ent_store_from_ent(struct sim_ent *ent); -struct sim_ent *sim_ent_from_handle(struct sim_ent_store *store, struct sim_ent_handle handle); -struct sim_ent *sim_ent_find_first_match_one(struct sim_ent_store *store, enum sim_ent_prop prop); -struct sim_ent *sim_ent_find_first_match_all(struct sim_ent_store *store, struct sim_ent_prop_array props); +struct sim_ent *sim_ent_from_handle(struct sim_snapshot *ss, struct sim_ent_handle handle); +struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop); +struct sim_ent *sim_ent_find_first_match_all(struct sim_snapshot *ss, struct sim_ent_prop_array props); /* Tree */ void sim_ent_link_parent(struct sim_ent *parent, struct sim_ent *child); diff --git a/src/sim_snapshot.c b/src/sim_snapshot.c index 90c2f141..d3bac0ba 100644 --- a/src/sim_snapshot.c +++ b/src/sim_snapshot.c @@ -20,34 +20,55 @@ GLOBAL struct { struct arena nil_arena; struct sim_snapshot_store *nil_snapshot_store; struct sim_snapshot *nil_snapshot; - + struct sim_ent *nil_ent; struct sim_client *nil_client; } G = ZI, DEBUG_ALIAS(G, G_sim_snapshot); -READONLY struct sim_client **_g_sim_client_nil = &G.nil_client; +/* Accessed via `sim_snapshot_store_nil()` */ +READONLY struct sim_snapshot_store **_g_sim_snapshot_store_nil = &G.nil_snapshot_store; /* Accessed via `sim_snapshot_nil()` */ READONLY struct sim_snapshot **_g_sim_snapshot_nil = &G.nil_snapshot; -/* Accessed via `sim_snapshot_store_nil()` */ -READONLY struct sim_snapshot_store **_g_sim_snapshot_store_nil = &G.nil_snapshot_store; +/* Accessed via `sim_ent_nil()` */ +READONLY struct sim_ent **_g_sim_ent_nil = &G.nil_ent; + +/* Accessed via `sim_client_nil()` */ +READONLY struct sim_client **_g_sim_client_nil = &G.nil_client; struct sim_snapshot_startup_receipt sim_snapshot_startup(void) { G.nil_arena = arena_alloc(GIGABYTE(1)); + /* Nil snapshot store */ G.nil_snapshot_store = arena_push_zero(&G.nil_arena, struct sim_snapshot_store); G.nil_snapshot_store->valid = false; + /* Nil snapshot */ G.nil_snapshot = arena_push_zero(&G.nil_arena, struct sim_snapshot); G.nil_snapshot->valid = false; G.nil_snapshot->store = sim_snapshot_store_nil(); - G.nil_snapshot->ent_store = sim_ent_store_nil(); + /* Nil ent */ + G.nil_ent = arena_push_zero(&G.nil_arena, struct sim_ent); + G.nil_ent->ss = sim_snapshot_nil(); + G.nil_ent->valid = false; + G.nil_ent->handle = SIM_ENT_NIL_HANDLE; + G.nil_ent->local_xform = XFORM_IDENT; + G.nil_ent->cached_global_xform = XFORM_IDENT; + G.nil_ent->cached_global_xform_dirty = false; + G.nil_ent->friction = 0.5f; + G.nil_ent->mass_unscaled = 1; + G.nil_ent->inertia_unscaled = 1; + G.nil_ent->sprite_local_xform = XFORM_IDENT; + G.nil_ent->sprite_tint = COLOR_WHITE; + + /* Nil client */ G.nil_client = arena_push_zero(&G.nil_arena, struct sim_client); - G.nil_client->valid = false; G.nil_client->ss = sim_snapshot_nil(); + G.nil_client->valid = false; + /* Lock nil arena */ arena_set_readonly(&G.nil_arena); return (struct sim_snapshot_startup_receipt ) { 0 }; } @@ -76,16 +97,16 @@ void sim_snapshot_store_release(struct sim_snapshot_store *store) struct sim_snapshot *ss = sim_snapshot_from_tick(store, store->first_tick); while (ss->valid) { struct sim_snapshot *next = sim_snapshot_from_tick(store, ss->next_tick); - sim_ent_store_release(ss->ent_store); arena_release(&ss->clients_arena); + arena_release(&ss->ents_arena); arena_release(&ss->arena); ss = next; } ss = store->first_free_snapshot; while (ss) { struct sim_snapshot *next = ss->next_free; - sim_ent_store_release(ss->ent_store); arena_release(&ss->clients_arena); + arena_release(&ss->ents_arena); arena_release(&ss->arena); ss = next; } @@ -108,29 +129,31 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_snapshot_store *store, struct { struct arena arena = ZI; struct arena clients_arena = ZI; - struct sim_ent_store *ent_store = NULL; + struct arena ents_arena = ZI; { ss = store->first_free_snapshot; if (ss) { /* Re-use existing snasphot arenas */ store->first_free_snapshot = ss->next_free; - arena = ss->arena; + ents_arena = ss->ents_arena; clients_arena = ss->clients_arena; - ent_store = ss->ent_store; - arena_reset(&ss->arena); - arena_reset(&ss->clients_arena); + arena = ss->arena; } else { /* Arenas allocated here will be released along with the entire snasphot store */ arena = arena_alloc(GIGABYTE(64)); clients_arena = arena_alloc(GIGABYTE(64)); - ent_store = sim_ent_store_alloc(GIGABYTE(64), true); - ss = arena_push(&arena, struct sim_snapshot); + ents_arena = arena_alloc(GIGABYTE(64)); } - MEMZERO_STRUCT(ss); } + arena_reset(&arena); + ss = arena_push_zero(&arena, struct sim_snapshot); ss->arena = arena; + ss->clients_arena = clients_arena; - ss->ent_store = ent_store; + arena_reset(&ss->clients_arena); + + ss->ents_arena = ents_arena; + arena_reset(&ss->ents_arena); } ss->tick = tick; @@ -148,7 +171,7 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_snapshot_store *store, struct ss->continuity_gen = src->continuity_gen; ss->local_client = src->local_client; - /* Copy src clients */ + /* Copy client lookup buckets */ if (src->num_client_lookup_buckets > 0) { ss->num_client_lookup_buckets = src->num_client_lookup_buckets; ss->client_lookup_buckets = arena_push_array(&ss->arena, struct sim_client_lookup_bucket, ss->num_client_lookup_buckets); @@ -157,6 +180,8 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_snapshot_store *store, struct ss->num_client_lookup_buckets = CLIENT_LOOKUP_BUCKETS; ss->client_lookup_buckets = arena_push_array_zero(&ss->arena, struct sim_client_lookup_bucket, ss->num_client_lookup_buckets); } + + /* Copy clients */ ss->first_free_client = src->first_free_client; ss->num_clients_allocated = src->num_clients_allocated; ss->num_clients_reserved = src->num_clients_reserved; @@ -168,8 +193,29 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_snapshot_store *store, struct dst_client->ss = ss; } - /* Copy src entities */ - sim_ent_store_copy(ss->ent_store, src->ent_store); + /* Copy entities */ + ss->first_free_ent = src->first_free_ent; + ss->num_ents_allocated = src->num_ents_allocated; + ss->num_ents_reserved = src->num_ents_reserved; + ss->ents = arena_push_array(&ss->ents_arena, struct sim_ent, ss->num_ents_reserved); + if (ss->num_ents_reserved == 0) { + /* Create root ent if copying from nil store */ + struct sim_ent *root = arena_push(&ss->ents_arena, struct sim_ent); + *root = *sim_ent_nil(); + root->ss = ss; + root->handle = SIM_ENT_ROOT_HANDLE; + root->valid = true; + root->is_root = true; + ++ss->num_ents_allocated; + ++ss->num_ents_reserved; + } else { + for (u64 i = 0; i < ss->num_ents_reserved; ++i) { + struct sim_ent *dst_ent = &ss->ents[i]; + struct sim_ent *src_ent = &src->ents[i]; + *dst_ent = *src_ent; + dst_ent->ss = ss; + } + } /* Release duplicate tick if it exists */ { @@ -342,11 +388,11 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_snapshot_store *sto /* Blend entities */ { __profscope(snapshot_lerp_entities); - u64 num_entities = min_u64(ss0->ent_store->num_reserved, ss1->ent_store->num_reserved); + u64 num_entities = min_u64(ss0->num_ents_reserved, ss1->num_ents_reserved); for (u64 i = 0; i < num_entities; ++i) { - struct sim_ent *e = &ss->ent_store->entities[i]; - struct sim_ent *e0 = &ss0->ent_store->entities[i]; - struct sim_ent *e1 = &ss1->ent_store->entities[i]; + struct sim_ent *e = &ss->ents[i]; + struct sim_ent *e0 = &ss0->ents[i]; + struct sim_ent *e1 = &ss1->ents[i]; sim_ent_lerp(e, e0, e1, blend); } } diff --git a/src/sim_snapshot.h b/src/sim_snapshot.h index 0a470cb0..5fbfe1ea 100644 --- a/src/sim_snapshot.h +++ b/src/sim_snapshot.h @@ -50,9 +50,11 @@ struct sim_snapshot { /* Which client in the client store represents the local host in the original snapshot */ struct sim_client_handle local_client; - /* Clients */ + /* Client lookup */ struct sim_client_lookup_bucket *client_lookup_buckets; u64 num_client_lookup_buckets; + + /* Clients */ struct arena clients_arena; struct sim_client *clients; struct sim_client_handle first_free_client; @@ -60,7 +62,11 @@ struct sim_snapshot { u64 num_clients_reserved; /* Entities */ - struct sim_ent_store *ent_store; + struct arena ents_arena; + struct sim_ent *ents; + struct sim_ent_handle first_free_ent; + u64 num_ents_allocated; + u64 num_ents_reserved; }; /* ========================== * diff --git a/src/user.c b/src/user.c index 59bbf0cc..934d7561 100644 --- a/src/user.c +++ b/src/user.c @@ -160,7 +160,6 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr, struct mixer_startup_receipt *mixer_sr, struct phys_startup_receipt *phys_sr, struct host_startup_receipt *host_sr, - struct sim_ent_startup_receipt *sim_ent_sr, struct sim_snapshot_startup_receipt *sim_snapshot_sr, struct string connect_address_str, struct sys_window *window) @@ -201,7 +200,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr, sys_window_register_event_callback(G.window, &window_event_callback); if (connect_address_str.len == 0) { - G.local_sim_ctx = sim_ctx_alloc(sprite_sr, phys_sr, host_sr, sim_ent_sr, sim_snapshot_sr, 12345); + G.local_sim_ctx = sim_ctx_alloc(sprite_sr, phys_sr, host_sr, sim_snapshot_sr, 12345); G.connect_address_str = LIT("127.0.0.1:12345"); G.local_sim_thread = sys_thread_alloc(&user_local_sim_thread_entry_point, G.local_sim_ctx, LIT("[P2] Local sim thread")); } else { @@ -636,15 +635,15 @@ INTERNAL void user_update(void) * ========================== */ struct sim_client *local_client = sim_client_from_handle(G.world, G.world->local_client); - struct sim_ent *local_player = sim_ent_from_handle(G.world->ent_store, local_client->control_ent); - struct sim_ent *local_camera = sim_ent_from_handle(G.world->ent_store, local_client->camera_ent); + struct sim_ent *local_player = sim_ent_from_handle(G.world, local_client->control_ent); + struct sim_ent *local_camera = sim_ent_from_handle(G.world, local_client->camera_ent); /* ========================== * * Apply shake * ========================== */ - for (u64 ent_index = 0; ent_index < G.world->ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &G.world->ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < G.world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &G.world->ents[ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; /* How much time between camera shakes */ @@ -811,8 +810,8 @@ INTERNAL void user_update(void) /* Copy valid entities */ { __profscope(copy_sprites_for_sorting); - for (u64 ent_index = 0; ent_index < G.world->ent_store->num_reserved; ++ent_index) { - struct sim_ent *ent = &G.world->ent_store->entities[ent_index]; + for (u64 ent_index = 0; ent_index < G.world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &G.world->ents[ent_index]; if (sim_ent_is_valid_and_active(ent)) { *arena_push(scratch.arena, struct sim_ent *) = ent; ++sorted_count; @@ -839,7 +838,7 @@ INTERNAL void user_update(void) struct sprite_tag sprite = ent->sprite; - struct sim_ent *parent = sim_ent_from_handle(G.world->ent_store, ent->parent); + struct sim_ent *parent = sim_ent_from_handle(G.world, ent->parent); struct xform xf = sim_ent_get_xform(ent); struct xform parent_xf = sim_ent_get_xform(parent); @@ -1024,8 +1023,8 @@ INTERNAL void user_update(void) /* Draw contact constraint */ if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) { struct phys_contact_constraint *data = &ent->contact_constraint_data; - struct sim_ent *e0 = sim_ent_from_handle(G.world->ent_store, data->e0); - struct sim_ent *e1 = sim_ent_from_handle(G.world->ent_store, data->e1); + struct sim_ent *e0 = sim_ent_from_handle(G.world, data->e0); + struct sim_ent *e1 = sim_ent_from_handle(G.world, data->e1); (UNUSED)e0; (UNUSED)e1; @@ -1098,8 +1097,8 @@ INTERNAL void user_update(void) if (sim_ent_has_prop(ent, SIM_ENT_PROP_COLLISION_DEBUG)) { struct phys_collision_debug *data = &ent->collision_debug_data; struct collider_collision_points_result collider_res = data->res; - struct sim_ent *e0 = sim_ent_from_handle(G.world->ent_store, data->e0); - struct sim_ent *e1 = sim_ent_from_handle(G.world->ent_store, data->e1); + struct sim_ent *e0 = sim_ent_from_handle(G.world, data->e0); + struct sim_ent *e1 = sim_ent_from_handle(G.world, data->e1); struct collider_shape e0_collider = e0->local_collider; struct collider_shape e1_collider = e1->local_collider; (UNUSED)e0_collider; @@ -1499,7 +1498,7 @@ INTERNAL void user_update(void) pos.y += spacing; pos.y += spacing; - draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("user 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("user entities: %F/%F"), FMT_UINT(G.world->num_ents_allocated), FMT_UINT(G.world->num_ents_reserved))); pos.y += spacing; draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("user tick: %F"), FMT_UINT(G.world->tick))); diff --git a/src/user.h b/src/user.h index 4c17dbd2..f700e12f 100644 --- a/src/user.h +++ b/src/user.h @@ -12,7 +12,6 @@ struct sound_startup_receipt; struct mixer_startup_receipt; struct phys_startup_receipt; struct host_startup_receipt; -struct sim_ent_startup_receipt; struct sim_snapshot_startup_receipt; enum user_bind_kind { @@ -62,7 +61,6 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr, struct mixer_startup_receipt *mixer_sr, struct phys_startup_receipt *phys_sr, struct host_startup_receipt *host_sr, - struct sim_ent_startup_receipt *sim_ent_sr, struct sim_snapshot_startup_receipt *sim_snapshot_sr, struct string connect_address_str, struct sys_window *window);