diff --git a/src/proto/pp_sim/pp_sim_core.c b/src/proto/pp_sim/pp_sim_core.c index 638ce4cd..4e33eef0 100644 --- a/src/proto/pp_sim/pp_sim_core.c +++ b/src/proto/pp_sim/pp_sim_core.c @@ -111,6 +111,92 @@ S_Ent *S_EntFromKey(S_World *world, S_Key key) return ent; } +//////////////////////////////////////////////////////////// +//~ Iteration helpers + +void S_ResetIter(Arena *arena, S_Iter *iter, S_World *world, S_Key key, S_IterKind kind) +{ + iter->kind = kind; + iter->world = world; + 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); + } +} + +S_Ent *S_NextEnt(Arena *arena, S_Iter *iter) +{ + S_Ent *result = &S_nil_ent; + S_World *world = iter->world; + b32 is_post_order = iter->kind == S_IterKind_Post; + + b32 stop = 0; + while (!stop) + { + if (iter->first_dfs) + { + S_IterDfsNode *n = iter->first_dfs; + S_Ent *ent = S_EntFromKey(iter->world, n->ent_key); + if (!n->visited) + { + /* Push children to dfs stack */ + for (S_Ent *child = S_EntFromKey(world, ent->last); !S_IsEntNil(child); child = S_EntFromKey(world, ent->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; + } + } + + return result; +} + //////////////////////////////////////////////////////////// //~ Snapshot helpers @@ -138,60 +224,6 @@ S_World *S_WorldFromSnapshot(Arena *arena, S_Snapshot *snapshot) SllStackPush(*bin, n); } - /* Sort tree */ - { - i64 ents_count = world->allocated_ents_count; - S_Ent **ents_pre = PushStructsNoZero(arena, S_Ent *, ents_count); - S_Ent **ents_post = PushStructsNoZero(arena, S_Ent *, ents_count); - { - Struct(EntNode) { EntNode *next; b32 visited; S_Ent *ent; }; - EntNode *first_dfs = 0; - i64 pre_idx = 0; - i64 post_idx = 0; - { - EntNode *n = PushStruct(scratch.arena, EntNode); - for (i64 ent_idx = 0; ent_idx < world->allocated_ents_count; ++ent_idx) - { - S_Ent *ent = &world->ents[ent_idx]; - if (S_MatchKey(ent->key, S_RootKey)) - { - n->ent = ent; - break; - } - } - SllStackPush(first_dfs, n); - } - while (first_dfs) - { - EntNode *n = first_dfs; - S_Ent *ent = n->ent; - if (!n->visited) - { - /* Push children to dfs stack */ - for (S_Ent *child = S_EntFromKey(world, ent->first); !S_IsEntNil(child); child = S_EntFromKey(world, child->prev)) - { - EntNode *child_n = PushStruct(scratch.arena, EntNode); - child_n->ent = child; - SllStackPush(first_dfs, child_n); - } - ent->pre_idx = pre_idx++; - ents_pre[ent->pre_idx] = ent; - n->visited = 1; - } - else - { - SllStackPop(first_dfs); - ent->post_idx = post_idx++; - ents_post[ent->post_idx] = ent; - } - } - Assert(pre_idx == post_idx); - world->active_ents_count = pre_idx; - world->ents_pre = ents_pre; - world->ents_post = ents_post; - } - } - EndScratch(scratch); return world; } @@ -258,6 +290,7 @@ JobDef(S_SimWorker, _, __) while (!shutdown) { ResetArena(frame_arena); + S_Iter ent_iter = ZI; ////////////////////////////// //- Begin sim frame @@ -297,6 +330,11 @@ JobDef(S_SimWorker, _, __) ////////////////////////////// //- Update entities from user control + S_ResetIter(frame_arena, &ent_iter, world, S_RootKey, S_IterKind_Post); + for (S_Ent *ent = S_NextEnt(frame_arena, &ent_iter); !S_IsEntNil(ent); ent = S_NextEnt(frame_arena, &ent_iter)) + { + } + ////////////////////////////// //- Publish sim state diff --git a/src/proto/pp_sim/pp_sim_core.h b/src/proto/pp_sim/pp_sim_core.h index 2b19743e..ab3485fd 100644 --- a/src/proto/pp_sim/pp_sim_core.h +++ b/src/proto/pp_sim/pp_sim_core.h @@ -52,10 +52,6 @@ Struct(S_Ent) //- Final data Xform final_local_to_world_xf; - - //- Per-world data - i64 pre_idx; - i64 post_idx; } extern Readonly S_nil_ent; ////////////////////////////// @@ -92,10 +88,6 @@ Struct(S_World) S_EntLookupNode **ent_bins; i64 ent_bins_count; - - S_Ent **ents_pre; - S_Ent **ents_post; - i64 active_ents_count; }; Struct(S_Snapshot) @@ -111,6 +103,30 @@ Struct(S_SnapshotNode) S_Snapshot snapshot; }; +//////////////////////////////////////////////////////////// +//~ 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_World *world; + S_IterDfsNode *first_dfs; + S_IterDfsNode *first_free_dfs; +}; + //////////////////////////////////////////////////////////// //~ Command types @@ -196,6 +212,12 @@ Vec2 S_SupportPointFromShape(S_Shape shape, Vec2 dir); S_Ent *S_EntFromKey(S_World *world, S_Key key); +//////////////////////////////////////////////////////////// +//~ Iteration helpers + +void S_ResetIter(Arena *arena, S_Iter *iter, S_World *world, S_Key key, S_IterKind kind); +S_Ent *S_NextEnt(Arena *arena, S_Iter *iter); + //////////////////////////////////////////////////////////// //~ Snapshot helpers diff --git a/src/proto/pp_vis/pp_vis_core.c b/src/proto/pp_vis/pp_vis_core.c index 9acbbdb1..c7574dd8 100644 --- a/src/proto/pp_vis/pp_vis_core.c +++ b/src/proto/pp_vis/pp_vis_core.c @@ -117,6 +117,7 @@ JobDef(V_VisWorker, _, __) while (!shutdown) { ResetArena(frame_arena); + S_Iter ent_iter = ZI; ////////////////////////////// //- Begin vis frame @@ -346,12 +347,10 @@ JobDef(V_VisWorker, _, __) //- Build render data /* Build shapes */ - for (i64 pre_idx = 0; pre_idx < world->active_ents_count; ++pre_idx) + S_ResetIter(frame_arena, &ent_iter, world, S_RootKey, S_IterKind_Pre); + for (S_Ent *ent = S_NextEnt(frame_arena, &ent_iter); !S_IsEntNil(ent); ent = S_NextEnt(frame_arena, &ent_iter)) { - S_Ent *ent = &world->ents[pre_idx]; - - // Xform xf = ent->final_to_world_xf; - Xform xf = XformIdentity; + Xform xf = ent->final_local_to_world_xf; S_Shape shape = S_MulXformShape(ent->final_local_to_world_xf, ent->local_shape); for (i32 point_idx = 0; point_idx < shape.points_count; ++point_idx) {