ent handle string formatting

This commit is contained in:
jacob 2025-02-22 11:50:01 -06:00
parent 835762fb5c
commit 34713e0c03
7 changed files with 97 additions and 60 deletions

View File

@ -73,9 +73,9 @@ struct sim_startup_receipt sim_startup(void)
G.nil_ent->ss = sim_snapshot_nil(); G.nil_ent->ss = sim_snapshot_nil();
G.nil_ent->valid = false; G.nil_ent->valid = false;
G.nil_ent->handle = SIM_ENT_NIL_HANDLE; G.nil_ent->handle = SIM_ENT_NIL_HANDLE;
G.nil_ent->local_xform = XFORM_IDENT; G.nil_ent->_local_xform = XFORM_IDENT;
G.nil_ent->cached_global_xform = XFORM_IDENT; G.nil_ent->_xform = XFORM_IDENT;
G.nil_ent->cached_global_xform_dirty = false; G.nil_ent->_is_xform_dirty = false;
G.nil_ent->friction = 0.5f; G.nil_ent->friction = 0.5f;
G.nil_ent->mass_unscaled = 1; G.nil_ent->mass_unscaled = 1;
G.nil_ent->inertia_unscaled = 1; G.nil_ent->inertia_unscaled = 1;

View File

@ -26,7 +26,7 @@ INTERNAL struct sim_ent *sim_ent_alloc_internal(struct sim_snapshot *ss)
ent->ss = ss; ent->ss = ss;
ent->valid = true; ent->valid = true;
ent->handle = handle; ent->handle = handle;
ent->cached_global_xform_dirty = true; ent->_is_xform_dirty = true;
++ss->num_ents_allocated; ++ss->num_ents_allocated;
return ent; 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) 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)) { 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; break;
} else { } else {
child->cached_global_xform_dirty = true; child->_is_xform_dirty = true;
sim_ent_mark_child_xforms_dirty(ss, child); 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) INTERNAL struct xform sim_ent_get_xform_internal(struct sim_snapshot *ss, struct sim_ent *ent)
{ {
struct xform xf; struct xform xf;
if (ent->cached_global_xform_dirty) { if (ent->_is_xform_dirty) {
if (ent->is_top) { if (ent->is_top) {
xf = ent->local_xform; xf = ent->_local_xform;
} else { } else {
struct sim_ent *parent = sim_ent_from_handle(ss, ent->parent); struct sim_ent *parent = sim_ent_from_handle(ss, ent->parent);
xf = sim_ent_get_xform_internal(ss, parent); xf = sim_ent_get_xform_internal(ss, parent);
xf = xform_mul(xf, ent->local_xform); xf = xform_mul(xf, ent->_local_xform);
ent->cached_global_xform = xf; ent->_xform = xf;
ent->cached_global_xform_dirty = false; ent->_is_xform_dirty = false;
} }
ent->cached_global_xform = xf; ent->_xform = xf;
ent->cached_global_xform_dirty = false; ent->_is_xform_dirty = false;
} else { } else {
xf = ent->cached_global_xform; xf = ent->_xform;
} }
return xf; 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 sim_ent_get_xform(struct sim_ent *ent)
{ {
struct xform xf; struct xform xf;
if (ent->cached_global_xform_dirty) { if (ent->_is_xform_dirty) {
if (ent->is_top) { if (ent->is_top) {
xf = ent->local_xform; xf = ent->_local_xform;
} else { } else {
struct sim_snapshot *ss = ent->ss; struct sim_snapshot *ss = ent->ss;
struct sim_ent *parent = sim_ent_from_handle(ss, ent->parent); struct sim_ent *parent = sim_ent_from_handle(ss, ent->parent);
xf = sim_ent_get_xform_internal(ss, parent); xf = sim_ent_get_xform_internal(ss, parent);
xf = xform_mul(xf, ent->local_xform); xf = xform_mul(xf, ent->_local_xform);
ent->cached_global_xform = xf; ent->_xform = xf;
ent->cached_global_xform_dirty = false; ent->_is_xform_dirty = false;
} }
ent->cached_global_xform = xf; ent->_xform = xf;
ent->cached_global_xform_dirty = false; ent->_is_xform_dirty = false;
} else { } else {
xf = ent->cached_global_xform; xf = ent->_xform;
} }
return xf; return xf;
} }
struct xform sim_ent_get_local_xform(struct sim_ent *ent) 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) 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; struct sim_snapshot *ss = ent->ss;
/* Update local xform */ /* Update local xform */
if (ent->is_top) { if (ent->is_top) {
ent->local_xform = xf; ent->_local_xform = xf;
} else { } else {
struct sim_ent *parent = sim_ent_from_handle(ss, ent->parent); struct sim_ent *parent = sim_ent_from_handle(ss, ent->parent);
struct xform parent_global = sim_ent_get_xform_internal(ss, 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->_xform = xf;
ent->cached_global_xform_dirty = false; ent->_is_xform_dirty = false;
sim_ent_mark_child_xforms_dirty(ss, ent); sim_ent_mark_child_xforms_dirty(ss, ent);
} }
} }
void sim_ent_set_local_xform(struct sim_ent *ent, struct xform xf) void sim_ent_set_local_xform(struct sim_ent *ent, struct xform xf)
{ {
if (!xform_eq(xf, ent->local_xform)) { if (!xform_eq(xf, ent->_local_xform)) {
ent->local_xform = xf; ent->_local_xform = xf;
ent->cached_global_xform_dirty = true; ent->_is_xform_dirty = true;
sim_ent_mark_child_xforms_dirty(ent->ss, ent); 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) if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)
&& e0->handle.gen == e1->handle.gen && e0->handle.gen == e1->handle.gen
&& e0->continuity_gen == e1->continuity_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) { if (e->is_top) {
/* TODO: Cache parent & child xforms in sim */ /* TODO: Cache parent & child xforms in sim */

View File

@ -76,7 +76,7 @@ struct sim_ent {
/* Is ent a child of the root ent */ /* Is ent a child of the root ent */
b32 is_top; 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; struct sim_ent_handle top;
/* Tree */ /* Tree */
@ -98,11 +98,10 @@ struct sim_ent {
/* ====================================================================== */ /* ====================================================================== */
/* Position */ /* Position */
/* Access with xform getters/setters */ /* Access with xform get/set */
/* 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 local_xform; /* Transform in relation to parent ent (or the world if ent has no parent) */ struct xform _xform; /* Calculated from ent tree */
struct xform cached_global_xform; /* Calculated from ent tree */ b32 _is_xform_dirty;
b32 cached_global_xform_dirty;
/* ====================================================================== */ /* ====================================================================== */
/* Activation */ /* Activation */

View File

@ -453,9 +453,11 @@ INTERNAL void release_entities_with_prop(struct sim_snapshot *ss_blended, enum s
scratch_end(scratch); scratch_end(scratch);
} }
#else #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 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 *); struct sim_ent **ents_to_release = arena_dry_push(scratch.arena, struct sim_ent *);
u64 ents_to_release_count = 0; 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 */ /* Release from snapshot */
/* TODO: Breadth first iteration to only release parent entities (since /* TODO: Breadth first iteration to only release parent entities (since
* child entities will be released along with parent anyway) */ * 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
* ========================== */ * ========================== */
release_entities_with_prop(world, SIM_ENT_PROP_RELEASE); release_entities_with_prop(ctx, SIM_ENT_PROP_RELEASE);
if (ctx->is_master) { if (ctx->is_master) {
/* ========================== * /* ========================== *
@ -1513,7 +1527,7 @@ void sim_step(struct sim_step_ctx *ctx)
* Release entities * Release entities
* ========================== */ * ========================== */
release_entities_with_prop(world, SIM_ENT_PROP_RELEASE); release_entities_with_prop(ctx, SIM_ENT_PROP_RELEASE);
/* ========================== * /* ========================== *
* End frame * End frame

View File

@ -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 * 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); parsed_str = string_from_float(arena, arg.value.f.val, arg.value.f.precision);
} break; } 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: { case FMT_TYPE_END: {
/* Unexpected end. Not enough FMT args passed to function. */ /* Unexpected end. Not enough FMT args passed to function. */
ASSERT(false); ASSERT(false);

View File

@ -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_int(struct arena *arena, i64 n, u32 base);
struct string string_from_ptr(struct arena *arena, void *ptr); 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_float(struct arena *arena, f64 f, u32 precision);
struct string string_from_handle(struct arena *arena, u64 v0, u64 v1);
/* ========================== * /* ========================== *
* String operations * String operations
@ -43,15 +44,16 @@ enum fmt_type {
FMT_TYPE_NONE, FMT_TYPE_NONE,
/* Arbitrary magic numbers to avoid accidental non-fmt arguments */ /* Arbitrary magic numbers to avoid accidental non-fmt arguments */
FMT_TYPE_CHAR = 0xC6ECD1, FMT_TYPE_CHAR = 0x0f5281df,
FMT_TYPE_STR = 0xC6ECD2, FMT_TYPE_STR = 0x0a5ffa9a,
FMT_TYPE_UINT = 0xC6ECD3, FMT_TYPE_UINT = 0x0746f19b,
FMT_TYPE_SINT = 0xC6ECD4, FMT_TYPE_SINT = 0x08603694,
FMT_TYPE_HEX = 0xC6ECD5, FMT_TYPE_HEX = 0x0a3d0792,
FMT_TYPE_PTR = 0xC6ECD6, FMT_TYPE_PTR = 0x0c4519e4,
FMT_TYPE_FLOAT = 0xC6ECD7, FMT_TYPE_FLOAT = 0x04814143,
FMT_TYPE_HANDLE = 0x0f112992,
FMT_TYPE_END = 0xAD32F3 FMT_TYPE_END = 0x0ecbc5ae
}; };
struct fmt_arg { struct fmt_arg {
@ -66,6 +68,9 @@ struct fmt_arg {
f64 val; f64 val;
u32 precision; u32 precision;
} f; } f;
struct {
u64 h64[2];
} handle;
} value; } value;
}; };
@ -79,6 +84,7 @@ struct fmt_arg {
#define FMT_PTR(v) (struct fmt_arg) {.type = FMT_TYPE_PTR, .value.ptr = (v)} #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(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_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) #define string_format(arena, fmt, ...) _string_format((arena), (fmt), __VA_ARGS__, FMT_END)
struct string _string_format(struct arena *arena, struct string fmt, ...); struct string _string_format(struct arena *arena, struct string fmt, ...);

View File

@ -199,6 +199,11 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
/* TODO: Remove this */ /* TODO: Remove this */
G.connect_address_str = string_copy(&G.arena, connect_address_str); 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 */ /* Sys events */
G.sys_events_mutex = sys_mutex_alloc(); G.sys_events_mutex = sys_mutex_alloc();
G.sys_events_arena = arena_alloc(GIGABYTE(64)); G.sys_events_arena = arena_alloc(GIGABYTE(64));
@ -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)) { 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)) { 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("prev: <%F>\n"), FMT_HANDLE(ent->prev)).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("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)) { 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); 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) { 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); struct string child_text = get_ent_debug_text(scratch.arena, child);
res.len += string_indent(arena, child_text, 4).len; res.len += string_indent(arena, child_text, 4).len;
child = sim_ent_from_handle(ss, child->next); child = sim_ent_from_handle(ss, child->next);
@ -1556,11 +1562,8 @@ INTERNAL void user_update(void)
struct string dbg_text = ZI; struct string dbg_text = ZI;
dbg_text.text = arena_dry_push(temp.arena, u8); dbg_text.text = arena_dry_push(temp.arena, u8);
dbg_text.len += string_format(temp.arena, LIT("ENT <%F>\n"), FMT_HANDLE(ent->handle)).len;
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 += get_ent_debug_text(temp.arena, ent).len; dbg_text.len += get_ent_debug_text(temp.arena, ent).len;
draw_text(G.ui_cmd_buffer, font, pos, dbg_text); draw_text(G.ui_cmd_buffer, font, pos, dbg_text);
arena_temp_end(temp); arena_temp_end(temp);