From af3687f3e5fea22607e452d28f2666f5352284ec Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 16 Dec 2025 16:37:35 -0600 Subject: [PATCH] remove entity tree --- src/pp/pp_sim/pp_sim_core.c | 219 +++++------------------------------- src/pp/pp_sim/pp_sim_core.h | 52 ++------- src/pp/pp_vis/pp_vis_core.c | 69 ++++++------ 3 files changed, 68 insertions(+), 272 deletions(-) diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 2c1b55ca..80598448 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -1,9 +1,7 @@ S_SharedState S_shared_state = ZI; Readonly S_Ent S_nil_ent = { - .local_xf = CompXformIdentity, - .world_xf = CompXformIdentity, - .tint = { 0.5, 0.5, 0.5, 1 }, + .xf = CompXformIdentity }; //////////////////////////////////////////////////////////// @@ -168,86 +166,29 @@ S_Ent *S_EntFromKey(S_Lookup *lookup, S_Key key) //////////////////////////////////////////////////////////// //~ Iteration helpers -S_Ent *S_FirstEntEx(Arena *arena, S_Iter *iter, S_Lookup *lookup, S_Key key, S_IterKind kind) +S_Ent *S_FirstEnt(S_Iter *iter, S_World *world) { - iter->kind = kind; - iter->lookup = lookup; - for (S_IterDfsNode *n = iter->first_dfs; n; n = n->next) - { - n->next = iter->first_free_dfs; - iter->first_free_dfs = n; - } - iter->first_dfs = 0; - { - S_IterDfsNode *n = iter->first_free_dfs; - if (n) - { - SllStackPop(iter->first_free_dfs); - ZeroStruct(n); - } - else - { - n = PushStruct(arena, S_IterDfsNode); - } - n->ent_key = key; - SllStackPush(iter->first_dfs, n); - } - return S_NextEnt(arena, iter); + ZeroStruct(iter); + iter->world = world; + return S_NextEnt(iter); } -S_Ent *S_NextEnt(Arena *arena, S_Iter *iter) +S_Ent *S_NextEnt(S_Iter *iter) { + S_World *world = iter->world; S_Ent *result = &S_nil_ent; - S_Lookup *lookup = iter->lookup; - b32 is_post_order = iter->kind == S_IterKind_Post; - b32 stop = 0; - while (!stop) + i64 ent_idx = iter->cur_idx; + for (; ent_idx < world->ents_count; ++ent_idx) { - if (iter->first_dfs) + S_Ent *ent = &world->ents[ent_idx]; + if (ent->active) { - S_IterDfsNode *n = iter->first_dfs; - S_Ent *ent = S_EntFromKey(iter->lookup, n->ent_key); - if (!n->visited) - { - /* Push children to dfs stack */ - for (S_Ent *child = S_EntFromKey(lookup, ent->last); !S_IsEntNil(child); child = S_EntFromKey(lookup, child->prev)) - { - S_IterDfsNode *child_n = iter->first_free_dfs; - if (child_n) - { - SllStackPop(iter->first_free_dfs); - ZeroStruct(child_n); - } - else - { - child_n = PushStruct(arena, S_IterDfsNode); - } - child_n->ent_key = child->key; - SllStackPush(iter->first_dfs, child_n); - } - n->visited = 1; - if (!is_post_order) - { - result = ent; - stop = 1; - } - } - else - { - SllStackPop(iter->first_dfs); - if (is_post_order) - { - result = ent; - stop = 1; - } - } - } - else - { - stop = 1; + result = ent; + break; } } + iter->cur_idx = ent_idx + 1; return result; } @@ -323,17 +264,6 @@ void S_TickForever(WaveLaneCtx *lane) f64 sim_dt = SecondsFromNs(sim_dt_ns); world->tick += 1; - ////////////////////////////// - //- Create root ent - - if (world->tick == 1) - { - S_Ent *root_ent = PushStruct(ents_arena, S_Ent); - *root_ent = S_nil_ent; - root_ent->key = S_RootKey; - root_ent->active = 1; - ++world->ents_count; - } lookup = S_LookupFromWorld(frame_arena, world); ////////////////////////////// @@ -362,12 +292,8 @@ void S_TickForever(WaveLaneCtx *lane) for (S_EntListNode *src_n = cmd.ents.first; src_n; src_n = src_n->next) { S_Ent *src = &src_n->ent; - if (S_IsKeyNil(src->parent)) - { - src->parent = S_RootKey; - } S_Key key = src->key; - if (!S_MatchKey(key, S_RootKey) && !S_IsKeyNil(key)) + if (!S_IsKeyNil(key)) { S_Ent *dst = S_EntFromKey(&lookup, key); if (S_IsEntNil(dst)) @@ -396,84 +322,6 @@ void S_TickForever(WaveLaneCtx *lane) } lookup = S_LookupFromWorld(frame_arena, world); - ////////////////////////////// - //- Build entity tree - - { - /* Reset tree links */ - for (i64 ent_idx = 0; ent_idx < world->ents_count; ++ent_idx) - { - S_Ent *ent = &world->ents[ent_idx]; - if (ent->active) - { - ent->first = S_NilKey; - ent->last = S_NilKey; - ent->next = S_NilKey; - ent->prev = S_NilKey; - ent->count = 0; - } - } - - { - /* Sort ents by key before tree-build (for deterministic child order in parents) */ - S_Ent **sorted_ents = 0; - { - sorted_ents = PushStructsNoZero(frame_arena, S_Ent *, world->ents_count); - for (i64 ent_idx = 0; ent_idx < world->ents_count; ++ent_idx) - { - sorted_ents[ent_idx] = &world->ents[ent_idx]; - } - Mergesort(sorted_ents, world->ents_count, sizeof(*sorted_ents), S_SortEntsByKeyCmp, 0); - } - - /* Build tree */ - for (i64 ent_idx = 0; ent_idx < world->ents_count; ++ent_idx) - { - S_Ent *ent = sorted_ents[ent_idx]; - if (ent->active) - { - S_Key key = ent->key; - S_Ent *parent = S_EntFromKey(&lookup, ent->parent); - if (parent->active) - { - S_Ent *prev = S_EntFromKey(&lookup, parent->last); - if (S_IsEntNil(prev)) - { - parent->first = key; - } - else - { - prev->next = key; - } - ent->prev = prev->key; - parent->last = key; - ++parent->count; - } - } - } - } - - /* Prune dangling ents */ - /* NOTE: If only the top level of a multi-level ent tree is - * dangling, the children may be marked inactive one level per tick - * since iteration is linear over the array. */ - for (i64 ent_idx = 0; ent_idx < world->ents_count; ++ent_idx) - { - S_Ent *ent = &world->ents[ent_idx]; - if (ent->active && !S_MatchKey(ent->key, S_RootKey)) - { - S_Ent *parent = S_EntFromKey(&lookup, ent->parent); - if (!parent->active) - { - ent->active = 0; - ent->next_free_ent_num = first_free_ent_num; - first_free_ent_num = ent_idx + 1; - } - } - } - } - lookup = S_LookupFromWorld(frame_arena, world); - ////////////////////////////// //- Update ent controls @@ -494,30 +342,26 @@ void S_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Apply control forces - for (S_Ent *ent = S_FirstEnt(frame_arena, &iter, &lookup); ent->active; ent = S_NextEnt(frame_arena, &iter)) + for (S_Ent *ent = S_FirstEnt(&iter, world); ent->active; ent = S_NextEnt(&iter)) { - Xform xf = ent->local_xf; + if (!IsVec2Zero(ent->move)) + { + DEBUGBREAKABLE; + } + + Xform xf = ent->xf; if (!IsVec2Zero(ent->look)) { xf = XformWithWorldRotation(xf, AngleFromVec2(ent->look)); } xf.og = AddVec2(xf.og, MulVec2(ent->move, ent->move_speed)); - ent->local_xf = xf; - } - - ////////////////////////////// - //- Compute pre-solve world transforms - - for (S_Ent *ent = S_FirstEnt(frame_arena, &iter, &lookup); ent->active; ent = S_NextEnt(frame_arena, &iter)) - { - ent->old_world_xf = ent->world_xf; - ent->world_xf = MulXform(S_EntFromKey(&lookup, ent->parent)->world_xf, ent->local_xf); + ent->xf = xf; } ////////////////////////////// //- Solve followers - for (S_Ent *ent = S_FirstEnt(frame_arena, &iter, &lookup); ent->active; ent = S_NextEnt(frame_arena, &iter)) + for (S_Ent *ent = S_FirstEnt(&iter, world); ent->active; ent = S_NextEnt(&iter)) { S_Ent *follow = S_EntFromKey(&lookup, ent->follow); if (follow->active) @@ -527,24 +371,15 @@ void S_TickForever(WaveLaneCtx *lane) look_ratio.y = 0.25; look_ratio.x = look_ratio.y / (16.0 / 9.0); - Vec2 target = MulXformV2(follow->world_xf, follow->local_shape.centroid); + Vec2 target = MulXformV2(follow->xf, follow->local_shape.centroid); target = AddVec2(target, MulVec2Vec2(follow->look, look_ratio)); - Xform xf = ent->local_xf; - // xf.og = AddVec2(xf.og, SubVec2(follow->world_xf.og, follow->old_world_xf.og)); + Xform xf = ent->xf; xf.og = LerpVec2(xf.og, target, follow_speed); - ent->local_xf = xf; + ent->xf = xf; } } - ////////////////////////////// - //- Compute post-solve world transforms - - for (S_Ent *ent = S_FirstEnt(frame_arena, &iter, &lookup); ent->active; ent = S_NextEnt(frame_arena, &iter)) - { - ent->world_xf = MulXform(S_EntFromKey(&lookup, ent->parent)->world_xf, ent->local_xf); - } - ////////////////////////////// //- Publish sim state diff --git a/src/pp/pp_sim/pp_sim_core.h b/src/pp/pp_sim/pp_sim_core.h index 409276da..d7328288 100644 --- a/src/pp/pp_sim/pp_sim_core.h +++ b/src/pp/pp_sim/pp_sim_core.h @@ -2,7 +2,6 @@ //~ Key types #define S_NilKey ((S_Key) { 0 }) -#define S_RootKey ((S_Key) { .v.hi = 0xaaaaaaaaaaaaaaaa, .v.lo = 0xaaaaaaaaaaaaaaaa }) Struct(S_Key) { @@ -38,16 +37,6 @@ Struct(S_Shape) Struct(S_Ent) { - ////////////////////////////// - //- Tree links - - S_Key parent; - S_Key first; - S_Key last; - S_Key next; - S_Key prev; - u64 count; - ////////////////////////////// //- Persistent data @@ -57,29 +46,18 @@ Struct(S_Ent) ////////////////////////////// //- Build data - Xform local_xf; - - Vec4 tint; + Xform xf; + S_Shape local_shape; S_Key follow; S_Key camera; - S_Shape local_shape; - f32 move_speed; Vec2 move; Vec2 look; - ////////////////////////////// - //- Pre-solve data - - Xform old_world_xf; - - ////////////////////////////// - //- Post-solve data - - Xform world_xf; + b32 has_weapon; ////////////////////////////// //- Internal sim data @@ -151,25 +129,10 @@ Struct(S_SnapshotNode) //////////////////////////////////////////////////////////// //~ Iterator types -Enum(S_IterKind) -{ - S_IterKind_Pre, - S_IterKind_Post, -}; - -Struct(S_IterDfsNode) -{ - S_IterDfsNode *next; - b32 visited; - S_Key ent_key; -}; - Struct(S_Iter) { - S_IterKind kind; - S_Lookup *lookup; - S_IterDfsNode *first_dfs; - S_IterDfsNode *first_free_dfs; + S_World *world; + i64 cur_idx; }; //////////////////////////////////////////////////////////// @@ -278,9 +241,8 @@ S_Ent *S_EntFromKey(S_Lookup *lookup, S_Key key); //////////////////////////////////////////////////////////// //~ Iteration helpers -#define S_FirstEnt(arena, iter, lookup) S_FirstEntEx((arena), (iter), (lookup), S_RootKey, S_IterKind_Pre) -S_Ent *S_FirstEntEx(Arena *arena, S_Iter *iter, S_Lookup *lookup, S_Key key, S_IterKind kind); -S_Ent *S_NextEnt(Arena *arena, S_Iter *iter); +S_Ent *S_FirstEnt(S_Iter *iter, S_World *world); +S_Ent *S_NextEnt(S_Iter *iter); //////////////////////////////////////////////////////////// //~ Snapshot helpers diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 2c3aaf63..30a71bd0 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -152,7 +152,7 @@ void V_TickForever(WaveLaneCtx *lane) S_Key child_key = S_RandKey(); S_Key camera_key = S_RandKey(); - i32 count = 3; + i32 count = 2; for (u64 i = 0; i < count; ++i) { S_EntListNode *n = PushStruct(frame->arena, S_EntListNode); @@ -165,7 +165,6 @@ void V_TickForever(WaveLaneCtx *lane) /* Test player */ case 0: { - ent->tint = Color_Red; ent->key = V.player_key; ent->camera = camera_key; ent->move_speed = 0.1; @@ -177,32 +176,12 @@ void V_TickForever(WaveLaneCtx *lane) ); } // ent->local_xf = XformFromPos(VEC2(200, 200)); - ent->local_xf = XformFromPos(VEC2(0, 0)); - } break; - - /* Test child */ - case 1: - { - f32 width = 0.1; - f32 height = 1; - - ent->tint = Color_Cyan; - ent->key = child_key; - ent->parent = V.player_key; - { - ent->local_shape = S_ShapeFromDesc( - .count = 4, - .points = { - VEC2(-width / 2, -height), VEC2(width / 2, -height), - VEC2(width / 2, 0), VEC2(-width / 2, 0), - } - ); - } - ent->local_xf = XformFromTrs(TRS(.t = { 0, 0 }, .r = Tau / 4)); + ent->xf = XformFromPos(VEC2(0, 0)); + ent->has_weapon = 1; } break; /* Test camera */ - case 2: + case 1: { ent->key = camera_key; ent->follow = V.player_key; @@ -286,7 +265,7 @@ void V_TickForever(WaveLaneCtx *lane) { S_Ent *player = S_EntFromKey(&V.lookup, V.player_key); S_Ent *camera = S_EntFromKey(&V.lookup, player->camera); - camera_pos = MulXformV2(camera->world_xf, camera->local_shape.centroid); + camera_pos = MulXformV2(camera->xf, camera->local_shape.centroid); } ////////////////////////////// @@ -531,7 +510,7 @@ void V_TickForever(WaveLaneCtx *lane) Vec2 look = ZI; { S_Ent *player = S_EntFromKey(&V.lookup, V.player_key); - Vec2 center = MulXformV2(player->world_xf, player->local_shape.centroid); + Vec2 center = MulXformV2(player->xf, player->local_shape.centroid); look = SubVec2(world_cursor, center); } cmd->target = V.player_key; @@ -572,19 +551,39 @@ void V_TickForever(WaveLaneCtx *lane) //- Build render data /* Build shape buffers */ - for (S_Ent *ent = S_FirstEnt(frame->arena, &iter, &V.lookup); ent->active; ent = S_NextEnt(frame->arena, &iter)) + for (S_Ent *ent = S_FirstEnt(&iter, V.world); ent->active; ent = S_NextEnt(&iter)) { - Xform ent_to_world_xf = ent->world_xf; + Xform ent_to_world_xf = ent->xf; Xform ent_to_draw_xf = MulXform(world_to_draw_xf, ent_to_world_xf); - /* Draw shape */ - b32 is_visible = ent->tint.w != 0; + b32 is_visible = 1; if (is_visible) { - Vec4 color = ent->tint; - i32 detail = 32; - S_Shape shape = S_MulXformShape(ent_to_draw_xf, ent->local_shape); - V_DrawShape(frame->dverts_arena, frame->dvert_idxs_arena, shape, LinearFromSrgb(color), detail, V_DrawFlag_Line); + /* Draw shape */ + { + Vec4 color = Color_Purple; + i32 detail = 32; + S_Shape shape = S_MulXformShape(ent_to_draw_xf, ent->local_shape); + V_DrawShape(frame->dverts_arena, frame->dvert_idxs_arena, shape, LinearFromSrgb(color), detail, V_DrawFlag_Line); + } + /* Draw weapon */ + if (ent->has_weapon) + { + Vec4 color = Color_Cyan; + f32 width = 0.1; + f32 height = 1; + S_Shape local_shape = S_ShapeFromDesc( + .count = 4, + .points = { + VEC2(-width / 2, -height), VEC2(width / 2, -height), + VEC2(width / 2, 0), VEC2(-width / 2, 0), + } + ); + Xform local_xf = XformFromTrs(TRS(.t = { 0, 0 }, .r = Tau / 4)); + Xform xf = MulXform(ent_to_draw_xf, local_xf); + S_Shape shape = S_MulXformShape(xf, local_shape); + V_DrawShape(frame->dverts_arena, frame->dvert_idxs_arena, shape, LinearFromSrgb(color), 10, V_DrawFlag_Line); + } } }