refactor ent store into snapshot

This commit is contained in:
jacob 2025-02-11 12:52:56 -06:00
parent e1a1006b32
commit fd550a7119
12 changed files with 321 additions and 422 deletions

View File

@ -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;

View File

@ -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;
@ -97,7 +99,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
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) {

View File

@ -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

126
src/sim.c
View File

@ -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;

View File

@ -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);

View File

@ -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
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;
};
/* ========================== *

View File

@ -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)));

View File

@ -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);