diff --git a/src/sim.c b/src/sim.c index 85a43768..05e85cf3 100644 --- a/src/sim.c +++ b/src/sim.c @@ -73,9 +73,9 @@ struct sim_startup_receipt sim_startup(void) 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->_local_xform = XFORM_IDENT; + G.nil_ent->_xform = XFORM_IDENT; + G.nil_ent->_is_xform_dirty = false; G.nil_ent->friction = 0.5f; G.nil_ent->mass_unscaled = 1; G.nil_ent->inertia_unscaled = 1; diff --git a/src/sim_ent.c b/src/sim_ent.c index 8d1ef916..07b021c7 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -26,7 +26,7 @@ INTERNAL struct sim_ent *sim_ent_alloc_internal(struct sim_snapshot *ss) ent->ss = ss; ent->valid = true; ent->handle = handle; - ent->cached_global_xform_dirty = true; + ent->_is_xform_dirty = true; ++ss->num_ents_allocated; return ent; } @@ -197,10 +197,10 @@ void sim_ent_activate(struct sim_ent *ent, u64 current_tick) 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(ss, ent->first); child->valid; child = sim_ent_from_handle(ss, child->next)) { - if (child->cached_global_xform_dirty) { + if (child->_is_xform_dirty) { break; } else { - child->cached_global_xform_dirty = true; + child->_is_xform_dirty = true; sim_ent_mark_child_xforms_dirty(ss, child); } } @@ -209,20 +209,20 @@ INTERNAL void sim_ent_mark_child_xforms_dirty(struct sim_snapshot *ss, struct si 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_xform_dirty) { if (ent->is_top) { - xf = ent->local_xform; + xf = ent->_local_xform; } else { 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; + xf = xform_mul(xf, ent->_local_xform); + ent->_xform = xf; + ent->_is_xform_dirty = false; } - ent->cached_global_xform = xf; - ent->cached_global_xform_dirty = false; + ent->_xform = xf; + ent->_is_xform_dirty = false; } else { - xf = ent->cached_global_xform; + xf = ent->_xform; } return xf; } @@ -230,53 +230,53 @@ INTERNAL struct xform sim_ent_get_xform_internal(struct sim_snapshot *ss, struct struct xform sim_ent_get_xform(struct sim_ent *ent) { struct xform xf; - if (ent->cached_global_xform_dirty) { + if (ent->_is_xform_dirty) { if (ent->is_top) { - xf = ent->local_xform; + xf = ent->_local_xform; } else { 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; + xf = xform_mul(xf, ent->_local_xform); + ent->_xform = xf; + ent->_is_xform_dirty = false; } - ent->cached_global_xform = xf; - ent->cached_global_xform_dirty = false; + ent->_xform = xf; + ent->_is_xform_dirty = false; } else { - xf = ent->cached_global_xform; + xf = ent->_xform; } return xf; } struct xform sim_ent_get_local_xform(struct sim_ent *ent) { - return ent->local_xform; + return ent->_local_xform; } void sim_ent_set_xform(struct sim_ent *ent, struct xform xf) { - if (!xform_eq(xf, ent->cached_global_xform)) { + if (!xform_eq(xf, ent->_xform)) { struct sim_snapshot *ss = ent->ss; /* Update local xform */ if (ent->is_top) { - ent->local_xform = xf; + ent->_local_xform = xf; } else { 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->_local_xform = xform_mul(xform_invert(parent_global), xf); } - ent->cached_global_xform = xf; - ent->cached_global_xform_dirty = false; + ent->_xform = xf; + ent->_is_xform_dirty = false; sim_ent_mark_child_xforms_dirty(ss, ent); } } 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; + if (!xform_eq(xf, ent->_local_xform)) { + ent->_local_xform = xf; + ent->_is_xform_dirty = true; sim_ent_mark_child_xforms_dirty(ent->ss, ent); } } @@ -334,7 +334,7 @@ void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && e0->handle.gen == e1->handle.gen && e0->continuity_gen == e1->continuity_gen) { - e->local_xform = xform_lerp(e0->local_xform, e1->local_xform, blend); + e->_local_xform = xform_lerp(e0->_local_xform, e1->_local_xform, blend); if (e->is_top) { /* TODO: Cache parent & child xforms in sim */ diff --git a/src/sim_ent.h b/src/sim_ent.h index 267e423b..307ed276 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -76,7 +76,7 @@ struct sim_ent { /* Is ent a child of the root ent */ b32 is_top; - /* The handle of the top level parent of the ent */ + /* The handle of the top level parent of the ent tree (if ent is top then this will be its own handle) */ struct sim_ent_handle top; /* Tree */ @@ -98,11 +98,10 @@ struct sim_ent { /* ====================================================================== */ /* Position */ - /* Access with xform getters/setters */ - /* TODO: Prefix with '_' to signal against direct access */ - 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; + /* Access with xform get/set */ + struct xform _local_xform; /* Transform in relation to parent ent (or the world if ent has no parent) */ + struct xform _xform; /* Calculated from ent tree */ + b32 _is_xform_dirty; /* ====================================================================== */ /* Activation */ diff --git a/src/sim_step.c b/src/sim_step.c index dcf02466..26020b5d 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -453,9 +453,11 @@ INTERNAL void release_entities_with_prop(struct sim_snapshot *ss_blended, enum s scratch_end(scratch); } #else -INTERNAL void release_entities_with_prop(struct sim_snapshot *world, enum sim_ent_prop prop) +INTERNAL void release_entities_with_prop(struct sim_step_ctx *ctx, enum sim_ent_prop prop) { struct temp_arena scratch = scratch_begin_no_conflict(); + struct sim_snapshot *world = ctx->world; + struct space *space = ctx->accel->space; struct sim_ent **ents_to_release = arena_dry_push(scratch.arena, struct sim_ent *); u64 ents_to_release_count = 0; @@ -467,6 +469,18 @@ INTERNAL void release_entities_with_prop(struct sim_snapshot *world, enum sim_en } } + /* Release references */ + for (u64 i = 0; i < ents_to_release_count; ++i) { + struct sim_ent *ent = ents_to_release[i]; + /* Release space entry */ + { + struct space_entry *space_entry = space_entry_from_handle(space, ent->space_handle); + if (space_entry->valid) { + space_entry_release(space_entry); + } + } + } + /* Release from snapshot */ /* TODO: Breadth first iteration to only release parent entities (since * child entities will be released along with parent anyway) */ @@ -599,7 +613,7 @@ void sim_step(struct sim_step_ctx *ctx) * Release entities * ========================== */ - release_entities_with_prop(world, SIM_ENT_PROP_RELEASE); + release_entities_with_prop(ctx, SIM_ENT_PROP_RELEASE); if (ctx->is_master) { /* ========================== * @@ -1513,7 +1527,7 @@ void sim_step(struct sim_step_ctx *ctx) * Release entities * ========================== */ - release_entities_with_prop(world, SIM_ENT_PROP_RELEASE); + release_entities_with_prop(ctx, SIM_ENT_PROP_RELEASE); /* ========================== * * End frame diff --git a/src/string.c b/src/string.c index 2ea09625..418ee1f9 100644 --- a/src/string.c +++ b/src/string.c @@ -159,6 +159,17 @@ struct string string_from_float(struct arena *arena, f64 f, u32 precision) }; } +struct string string_from_handle(struct arena *arena, u64 v0, u64 v1) +{ + struct string res = ZI; + res.text = arena_dry_push(arena, u8); + res.len += string_copy(arena, LIT("h")).len; + res.len += string_from_uint(arena, v0, 16).len; + res.len += string_copy(arena, LIT("x")).len; + res.len += string_from_uint(arena, v1, 16).len; + return res; +} + /* ========================== * * String operations * ========================== */ @@ -465,6 +476,10 @@ struct string string_formatv(struct arena *arena, struct string fmt, va_list arg parsed_str = string_from_float(arena, arg.value.f.val, arg.value.f.precision); } break; + case FMT_TYPE_HANDLE: { + parsed_str = string_from_handle(arena, arg.value.handle.h64[0], arg.value.handle.h64[1]); + } break; + case FMT_TYPE_END: { /* Unexpected end. Not enough FMT args passed to function. */ ASSERT(false); diff --git a/src/string.h b/src/string.h index 8dfaa7ef..6aed1fa4 100644 --- a/src/string.h +++ b/src/string.h @@ -15,6 +15,7 @@ struct string string_from_uint(struct arena *arena, u64 n, u32 base); struct string string_from_int(struct arena *arena, i64 n, u32 base); struct string string_from_ptr(struct arena *arena, void *ptr); struct string string_from_float(struct arena *arena, f64 f, u32 precision); +struct string string_from_handle(struct arena *arena, u64 v0, u64 v1); /* ========================== * * String operations @@ -43,15 +44,16 @@ enum fmt_type { FMT_TYPE_NONE, /* Arbitrary magic numbers to avoid accidental non-fmt arguments */ - FMT_TYPE_CHAR = 0xC6ECD1, - FMT_TYPE_STR = 0xC6ECD2, - FMT_TYPE_UINT = 0xC6ECD3, - FMT_TYPE_SINT = 0xC6ECD4, - FMT_TYPE_HEX = 0xC6ECD5, - FMT_TYPE_PTR = 0xC6ECD6, - FMT_TYPE_FLOAT = 0xC6ECD7, + FMT_TYPE_CHAR = 0x0f5281df, + FMT_TYPE_STR = 0x0a5ffa9a, + FMT_TYPE_UINT = 0x0746f19b, + FMT_TYPE_SINT = 0x08603694, + FMT_TYPE_HEX = 0x0a3d0792, + FMT_TYPE_PTR = 0x0c4519e4, + FMT_TYPE_FLOAT = 0x04814143, + FMT_TYPE_HANDLE = 0x0f112992, - FMT_TYPE_END = 0xAD32F3 + FMT_TYPE_END = 0x0ecbc5ae }; struct fmt_arg { @@ -66,6 +68,9 @@ struct fmt_arg { f64 val; u32 precision; } f; + struct { + u64 h64[2]; + } handle; } value; }; @@ -79,6 +84,7 @@ struct fmt_arg { #define FMT_PTR(v) (struct fmt_arg) {.type = FMT_TYPE_PTR, .value.ptr = (v)} #define FMT_FLOAT(v) FMT_FLOAT_P(v, DEFAULT_FMT_PRECISION) #define FMT_FLOAT_P(v, p) (struct fmt_arg) {.type = FMT_TYPE_FLOAT, .value.f.val = (v), .value.f.precision = p} +#define FMT_HANDLE(v) (struct fmt_arg) {.type = FMT_TYPE_HANDLE, .value.handle.h64[0] = (v).idx, .value.handle.h64[1] = (v).gen} #define string_format(arena, fmt, ...) _string_format((arena), (fmt), __VA_ARGS__, FMT_END) struct string _string_format(struct arena *arena, struct string fmt, ...); diff --git a/src/user.c b/src/user.c index 6f1f137b..4c27c2fe 100644 --- a/src/user.c +++ b/src/user.c @@ -199,6 +199,11 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr, /* TODO: Remove this */ G.connect_address_str = string_copy(&G.arena, connect_address_str); + /* Initialize average dts to a reasonable value */ + for (u64 i = 0; i < ARRAY_COUNT(G.local_to_user_snapshot_publish_dts_ns); ++i) { + G.local_to_user_snapshot_publish_dts_ns[i] = NS_FROM_SECONDS(1) / SIM_TICKS_PER_SECOND; + } + /* Sys events */ G.sys_events_mutex = sys_mutex_alloc(); G.sys_events_arena = arena_alloc(GIGABYTE(64)); @@ -358,21 +363,22 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e } if (!sim_ent_handle_eq(ent->parent, SIM_ENT_ROOT_HANDLE)) { - res.len += string_format(arena, LIT("parent: <%F:%F>\n"), FMT_UINT(ent->parent.idx), FMT_UINT(ent->parent.gen)).len; + res.len += string_format(arena, LIT("parent: <%F>\n"), FMT_HANDLE(ent->parent)).len; } if (!sim_ent_handle_eq(ent->next, SIM_ENT_NIL_HANDLE) || !sim_ent_handle_eq(ent->prev, SIM_ENT_NIL_HANDLE)) { - res.len += string_format(arena, LIT("prev: <%F:%F>\n"), FMT_UINT(ent->prev.idx), FMT_UINT(ent->prev.gen)).len; - res.len += string_format(arena, LIT("next: <%F:%F>\n"), FMT_UINT(ent->next.idx), FMT_UINT(ent->next.gen)).len; + res.len += string_format(arena, LIT("prev: <%F>\n"), FMT_HANDLE(ent->prev)).len; + res.len += string_format(arena, LIT("next: <%F>\n"), FMT_HANDLE(ent->next)).len; } if (!sim_ent_handle_eq(ent->first, SIM_ENT_NIL_HANDLE) || !sim_ent_handle_eq(ent->last, SIM_ENT_NIL_HANDLE)) { - res.len += string_format(arena, LIT("first child: <%F:%F>\n"), FMT_UINT(ent->first.idx), FMT_UINT(ent->first.gen)).len; - res.len += string_format(arena, LIT("last child: <%F:%F>\n"), FMT_UINT(ent->last.idx), FMT_UINT(ent->last.gen)).len; - struct sim_ent *child = sim_ent_from_handle(ss, ent->first); + if (!sim_ent_handle_eq(ent->first, ent->last) || !child->valid) { + res.len += string_format(arena, LIT("first child: <%F>\n"), FMT_HANDLE(ent->first)).len; + res.len += string_format(arena, LIT("last child: <%F>\n"), FMT_HANDLE(ent->last)).len; + } while (child->valid) { - res.len += string_format(arena, LIT("\nCHILD <%F:%F>\n"), FMT_UINT(child->handle.idx), FMT_UINT(child->handle.gen)).len; + res.len += string_format(arena, LIT("\nCHILD <%F>\n"), FMT_HANDLE(child->handle)).len; struct string child_text = get_ent_debug_text(scratch.arena, child); res.len += string_indent(arena, child_text, 4).len; child = sim_ent_from_handle(ss, child->next); @@ -1556,11 +1562,8 @@ INTERNAL void user_update(void) struct string dbg_text = ZI; dbg_text.text = arena_dry_push(temp.arena, u8); - - dbg_text.len += string_format(temp.arena, LIT("ENT <%F:%F>\n"), FMT_UINT(ent->handle.idx), FMT_UINT(ent->handle.gen)).len; - + dbg_text.len += string_format(temp.arena, LIT("ENT <%F>\n"), FMT_HANDLE(ent->handle)).len; dbg_text.len += get_ent_debug_text(temp.arena, ent).len; - draw_text(G.ui_cmd_buffer, font, pos, dbg_text); arena_temp_end(temp);