From c649867ef4fe68d1145111eff683ee65a6f8f218 Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 5 Aug 2025 16:50:47 -0500 Subject: [PATCH] pp refactor progress --- src/pp/pp_ent.c | 261 ++++++++++++++------- src/pp/pp_ent.h | 6 +- src/pp/pp_phys.c | 236 +++++++++++++------ src/pp/pp_sim.c | 595 +++++++++++++++++++++++++++++------------------ src/pp/pp_sim.h | 183 ++++++++++----- src/pp/pp_step.c | 589 +++++++++++++++++++++++++++++++--------------- src/pp/pp_step.h | 7 +- 7 files changed, 1240 insertions(+), 637 deletions(-) diff --git a/src/pp/pp_ent.c b/src/pp/pp_ent.c index dd0d0acc..8d828b08 100644 --- a/src/pp/pp_ent.c +++ b/src/pp/pp_ent.c @@ -7,11 +7,14 @@ Entity *AcquireRaw(Snapshot *ss, Entity *parent, EntityId id) Assert(ss->valid); Assert(ss == parent->ss); Entity *ent; - if (ss->first_free_ent > 0 && ss->first_free_ent < ss->num_ents_reserved) { + if (ss->first_free_ent > 0 && ss->first_free_ent < ss->num_ents_reserved) + { /* Reuse from free list */ ent = &ss->ents[ss->first_free_ent]; ss->first_free_ent = ent->next_free; - } else { + } + else + { /* Make new */ ent = PushStructNoZero(ss->ents_arena, Entity); ++ss->num_ents_reserved; @@ -83,7 +86,8 @@ void ReleaseRaw(Entity *ent) Snapshot *ss = ent->ss; /* Release children */ Entity *child = EntityFromId(ss, ent->first); - while (child->valid) { + while (child->valid) + { Entity *next = EntityFromId(ss, child->next); ReleaseRaw(child); child = next; @@ -103,7 +107,8 @@ void Release(Entity *ent) { Snapshot *ss = ent->ss; Entity *parent = EntityFromId(ss, ent->parent); - if (parent->valid) { + if (parent->valid) + { Unlink(ent); } ReleaseRaw(ent); @@ -115,9 +120,11 @@ void ReleaseAllWithProp(Snapshot *ss, Prop prop) Entity **ents_to_release = PushDry(scratch.arena, Entity *); u64 ents_to_release_count = 0; - for (u64 ent_index = 0; ent_index < ss->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < ss->num_ents_reserved; ++ent_index) + { Entity *ent = &ss->ents[ent_index]; - if (ent->valid && HasProp(ent, prop)) { + if (ent->valid && HasProp(ent, prop)) + { *PushStructNoZero(scratch.arena, Entity *) = ent; ++ents_to_release_count; } @@ -126,9 +133,11 @@ void ReleaseAllWithProp(Snapshot *ss, Prop prop) /* Release from snapshot */ /* TODO: Breadth first iteration to only release parent entities (since * child entities will be released along with parent anyway) */ - for (u64 i = 0; i < ents_to_release_count; ++i) { + for (u64 i = 0; i < ents_to_release_count; ++i) + { Entity *ent = ents_to_release[i]; - if (ent->valid && !ent->is_root && !HasProp(ent, Prop_Cmd) && !HasProp(ent, Prop_Player)) { + if (ent->valid && !ent->is_root && !HasProp(ent, Prop_Cmd) && !HasProp(ent, Prop_Player)) + { Release(ent); } } @@ -156,9 +165,12 @@ u32 IndexFromEntity(Snapshot *ss, Entity *ent) Entity *EntityFromIndex(Snapshot *ss, u32 index) { - if (index > 0 && index < ss->num_ents_reserved) { + if (index > 0 && index < ss->num_ents_reserved) + { return &ss->ents[index]; - } else { + } + else + { return NilEntity(); } } @@ -173,9 +185,11 @@ void SetEntityId(Entity *ent, EntityId id) { Snapshot *ss = ent->ss; EntityId old_id = ent->id; - if (!EqId(old_id, id)) { + if (!EqId(old_id, id)) + { /* Release old from lookup */ - if (!IsNilId(old_id)) { + if (!IsNilId(old_id)) + { EntBin *bin = BinFromId(ss, old_id); u32 prev_index = 0; u32 next_index = 0; @@ -183,10 +197,12 @@ void SetEntityId(Entity *ent, EntityId id) Entity *prev = NilEntity(); Entity *next = NilEntity(); Entity *search = EntityFromIndex(ss, search_index); - while (search->valid) { + while (search->valid) + { next_index = search->next_in_id_bin; next = EntityFromIndex(ss, next_index); - if (EqId(search->id, old_id)) { + if (EqId(search->id, old_id)) + { break; } prev_index = search_index; @@ -198,21 +214,28 @@ void SetEntityId(Entity *ent, EntityId id) /* Old id not in bin, this should be impossible. */ Assert(search->valid); - if (prev->valid) { + if (prev->valid) + { prev->next_in_id_bin = next_index; - } else { + } + else + { bin->first = next_index; } - if (next->valid) { + if (next->valid) + { next->prev_in_id_bin = prev_index; - } else { + } + else + { bin->last = prev_index; } } /* Insert new id into lookup */ - if (!IsNilId(id)) { + if (!IsNilId(id)) + { #if RtcIsEnabled { Entity *existing = EntityFromId(ss, id); @@ -224,10 +247,13 @@ void SetEntityId(Entity *ent, EntityId id) EntBin *bin = BinFromId(ss, id); u32 ent_index = IndexFromEntity(ss, ent); Entity *last = EntityFromIndex(ss, bin->last); - if (last->valid) { + if (last->valid) + { last->next_in_id_bin = ent_index; ent->prev_in_id_bin = bin->last; - } else { + } + else + { bin->first = ent_index; ent->prev_in_id_bin = 0; } @@ -242,10 +268,13 @@ void SetEntityId(Entity *ent, EntityId id) Entity *EntityFromId(Snapshot *ss, EntityId id) { Entity *result = NilEntity(); - if (!IsNilId(id) && ss->valid) { + if (!IsNilId(id) && ss->valid) + { EntBin *bin = BinFromId(ss, id); - for (Entity *e = EntityFromIndex(ss, bin->first); e->valid; e = EntityFromIndex(ss, e->next_in_id_bin)) { - if (EqId(e->id, id)) { + for (Entity *e = EntityFromIndex(ss, bin->first); e->valid; e = EntityFromIndex(ss, e->next_in_id_bin)) + { + if (EqId(e->id, id)) + { result = e; break; } @@ -299,9 +328,11 @@ Entity *FirstWithProp(Snapshot *ss, Prop prop) { u64 count = ss->num_ents_reserved; Entity *entities = ss->ents; - for (u64 ent_index = 0; ent_index < count; ++ent_index) { + for (u64 ent_index = 0; ent_index < count; ++ent_index) + { Entity *ent = &entities[ent_index]; - if (ent->valid && HasProp(ent, prop)) { + if (ent->valid && HasProp(ent, prop)) + { return ent; } } @@ -312,17 +343,22 @@ Entity *FirstWithAllProps(Snapshot *ss, PropArray props) { u64 count = ss->num_ents_reserved; Entity *entities = ss->ents; - for (u64 ent_index = 0; ent_index < count; ++ent_index) { + for (u64 ent_index = 0; ent_index < count; ++ent_index) + { Entity *ent = &entities[ent_index]; - if (ent->valid) { + if (ent->valid) + { b32 all = 1; - for (u64 i = 0; i < props.count; ++i) { - if (!HasProp(ent, props.props[i])) { + for (u64 i = 0; i < props.count; ++i) + { + if (!HasProp(ent, props.props[i])) + { all = 0; break; } } - if (all) { + if (all) + { return ent; } } @@ -338,7 +374,8 @@ void Link(Entity *ent, Entity *parent) Snapshot *ss = ent->ss; Entity *old_parent = EntityFromId(ss, ent->parent); - if (old_parent->valid) { + if (old_parent->valid) + { /* Unlink from current parent */ Unlink(ent); } @@ -346,18 +383,24 @@ void Link(Entity *ent, Entity *parent) EntityId ent_id = ent->id; EntityId last_child_id = parent->last; Entity *last_child = EntityFromId(ss, last_child_id); - if (last_child->valid) { + if (last_child->valid) + { ent->prev = last_child_id; last_child->next = ent_id; - } else { + } + else + { parent->first = ent_id; } parent->last = ent_id; - if (parent->is_root) { + if (parent->is_root) + { ent->is_top = 1; ent->top = ent_id; - } else { + } + else + { ent->top = parent->top; } @@ -375,14 +418,20 @@ void Unlink(Entity *ent) Entity *next = EntityFromId(ss, ent->next); /* Unlink from parent & siblings */ - if (prev->valid) { + if (prev->valid) + { prev->next = next->id; - } else { + } + else + { parent->first = next->id; } - if (next->valid) { + if (next->valid) + { next->prev = prev->id; - } else { + } + else + { parent->last = prev->id; } ent->prev = NilEntityId; @@ -394,10 +443,14 @@ void Unlink(Entity *ent) void MarkChildXformsDirty(Snapshot *ss, Entity *ent) { - for (Entity *child = EntityFromId(ss, ent->first); child->valid; child = EntityFromId(ss, child->next)) { - if (child->_is_xform_dirty) { + for (Entity *child = EntityFromId(ss, ent->first); child->valid; child = EntityFromId(ss, child->next)) + { + if (child->_is_xform_dirty) + { break; - } else { + } + else + { child->_is_xform_dirty = 1; MarkChildXformsDirty(ss, child); } @@ -407,10 +460,14 @@ void MarkChildXformsDirty(Snapshot *ss, Entity *ent) Xform XformFromEntity_(Snapshot *ss, Entity *ent) { Xform xf; - if (ent->_is_xform_dirty) { - if (ent->is_top) { + if (ent->_is_xform_dirty) + { + if (ent->is_top) + { xf = ent->_local_xform; - } else { + } + else + { Entity *parent = EntityFromId(ss, ent->parent); xf = XformFromEntity_(ss, parent); xf = MulXform(xf, ent->_local_xform); @@ -419,7 +476,9 @@ Xform XformFromEntity_(Snapshot *ss, Entity *ent) } ent->_xform = xf; ent->_is_xform_dirty = 0; - } else { + } + else + { xf = ent->_xform; } return xf; @@ -428,10 +487,14 @@ Xform XformFromEntity_(Snapshot *ss, Entity *ent) Xform XformFromEntity(Entity *ent) { Xform xf; - if (ent->_is_xform_dirty) { - if (ent->is_top) { + if (ent->_is_xform_dirty) + { + if (ent->is_top) + { xf = ent->_local_xform; - } else { + } + else + { Snapshot *ss = ent->ss; Entity *parent = EntityFromId(ss, ent->parent); xf = XformFromEntity_(ss, parent); @@ -441,7 +504,9 @@ Xform XformFromEntity(Entity *ent) } ent->_xform = xf; ent->_is_xform_dirty = 0; - } else { + } + else + { xf = ent->_xform; } return xf; @@ -454,12 +519,16 @@ Xform LocalXformFromEntity(Entity *ent) void SetXform(Entity *ent, Xform xf) { - if (!EqXform(xf, ent->_xform)) { + if (!EqXform(xf, ent->_xform)) + { Snapshot *ss = ent->ss; /* Update local xform */ - if (ent->is_top) { + if (ent->is_top) + { ent->_local_xform = xf; - } else { + } + else + { Entity *parent = EntityFromId(ss, ent->parent); Xform parent_global = XformFromEntity_(ss, parent); ent->_local_xform = MulXform(InvertXform(parent_global), xf); @@ -472,7 +541,8 @@ void SetXform(Entity *ent, Xform xf) void SetLocalXform(Entity *ent, Xform xf) { - if (!EqXform(xf, ent->_local_xform)) { + if (!EqXform(xf, ent->_local_xform)) + { ent->_local_xform = xf; ent->_is_xform_dirty = 1; MarkChildXformsDirty(ent->ss, ent); @@ -484,21 +554,24 @@ void SetLocalXform(Entity *ent, Xform xf) void SetLinearVelocity(Entity *ent, Vec2 velocity) { - if (HasProp(ent, Prop_Kinematic) || HasProp(ent, Prop_Dynamic)) { + if (HasProp(ent, Prop_Kinematic) || HasProp(ent, Prop_Dynamic)) + { ent->linear_velocity = ClampVec2Len(velocity, SIM_MAX_LINEAR_VELOCITY); } } void SetAngularVelocity(Entity *ent, f32 velocity) { - if (HasProp(ent, Prop_Kinematic) || HasProp(ent, Prop_Dynamic)) { + if (HasProp(ent, Prop_Kinematic) || HasProp(ent, Prop_Dynamic)) + { ent->angular_velocity = ClampF32(velocity, -SIM_MAX_ANGULAR_VELOCITY, SIM_MAX_ANGULAR_VELOCITY); } } void ApplyLinearImpulse(Entity *ent, Vec2 impulse, Vec2 point) { - if (HasProp(ent, Prop_Dynamic)) { + if (HasProp(ent, Prop_Dynamic)) + { Xform xf = XformFromEntity(ent); Vec2 center = xf.og; f32 scale = AbsF32(DeterminantFromXform(xf)); @@ -513,7 +586,8 @@ void ApplyLinearImpulse(Entity *ent, Vec2 impulse, Vec2 point) void ApplyLinearImpulseToCenter(Entity *ent, Vec2 impulse) { - if (HasProp(ent, Prop_Dynamic)) { + if (HasProp(ent, Prop_Dynamic)) + { Xform xf = XformFromEntity(ent); f32 scale = AbsF32(DeterminantFromXform(xf)); f32 inv_mass = 1.f / (ent->mass_unscaled * scale); @@ -524,14 +598,16 @@ void ApplyLinearImpulseToCenter(Entity *ent, Vec2 impulse) void ApplyForceToCenter(Entity *ent, Vec2 force) { - if (HasProp(ent, Prop_Dynamic)) { + if (HasProp(ent, Prop_Dynamic)) + { ent->force = AddVec2(ent->force, force); } } void ApplyAngularImpulse(Entity *ent, f32 impulse) { - if (HasProp(ent, Prop_Dynamic)) { + if (HasProp(ent, Prop_Dynamic)) + { Xform xf = XformFromEntity(ent); f32 scale = AbsF32(DeterminantFromXform(xf)); f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale); @@ -541,7 +617,8 @@ void ApplyAngularImpulse(Entity *ent, f32 impulse) void ApplyTorque(Entity *ent, f32 torque) { - if (HasProp(ent, Prop_Dynamic)) { + if (HasProp(ent, Prop_Dynamic)) + { ent->torque += torque; } } @@ -576,10 +653,12 @@ void LerpEntity(Entity *e, Entity *e0, Entity *e1, f64 blend) { if (IsValidAndActive(e0) && IsValidAndActive(e1) && EqId(e0->id, e1->id) - && e0->continuity_gen == e1->continuity_gen) { + && e0->continuity_gen == e1->continuity_gen) + { e->_local_xform = LerpXform(e0->_local_xform, e1->_local_xform, blend); - if (e->is_top) { + if (e->is_top) + { /* TODO: Cache parent & child xforms in sim */ Xform e0_xf = XformFromEntity(e0); Xform e1_xf = XformFromEntity(e1); @@ -615,16 +694,19 @@ void LerpEntity(Entity *e, Entity *e0, Entity *e1, f64 blend) void CreateMissingEntitiesFromSnapshots(Entity *local_parent, Entity *remote, EntityId remote_player) { __prof; - if (HasProp(remote, Prop_SyncSrc)) { + if (HasProp(remote, Prop_SyncSrc)) + { Snapshot *local_ss = local_parent->ss; Snapshot *remote_ss = remote->ss; EntityId id = remote->id; Entity *local_ent = EntityFromId(local_ss, id); - if (!local_ent->valid) { + if (!local_ent->valid) + { local_ent = AcquireSyncDst(local_parent, id, remote_player); } - for (Entity *remote_child = EntityFromId(remote_ss, remote->first); remote_child->valid; remote_child = EntityFromId(remote_ss, remote_child->next)) { + for (Entity *remote_child = EntityFromId(remote_ss, remote->first); remote_child->valid; remote_child = EntityFromId(remote_ss, remote_child->next)) + { CreateMissingEntitiesFromSnapshots(local_ent, remote_child, remote_player); } } @@ -665,7 +747,8 @@ void SyncEntity(Entity *local, Entity *remote) #if 1 -//- Encode +//////////////////////////////// +//~ Encode void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1) { @@ -676,11 +759,13 @@ void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1) u64 pos = 0; e1->ss = e0->ss; - while (pos < sizeof(*e1)) { + while (pos < sizeof(*e1)) + { u64 chunk_size = MinU64(pos + 8, sizeof(*e1)) - pos; u8 *chunk0 = (u8 *)e0 + pos; u8 *chunk1 = (u8 *)e1 + pos; - if (BB_WriteBit(bw, !EqBytes(chunk0, chunk1, chunk_size))) { + if (BB_WriteBit(bw, !EqBytes(chunk0, chunk1, chunk_size))) + { u64 bits = 0; CopyBytes(&bits, chunk1, chunk_size); BB_WriteUBits(bw, bits, 64); @@ -690,16 +775,19 @@ void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1) e1->ss = ss; } -//- Decode +//////////////////////////////// +//~ Decode void DecodeEntity(BB_Reader *br, Entity *e) { Snapshot *old_ss = e->ss; { u64 pos = 0; - while (pos < sizeof(*e)) { + while (pos < sizeof(*e)) + { u8 *chunk = (u8 *)e + pos; - if (BB_ReadBit(br)) { + if (BB_ReadBit(br)) + { u64 chunk_size = MinU64(pos + 8, sizeof(*e)) - pos; u64 bits = BB_ReadUBits(br, 64); CopyBytes(chunk, &bits, chunk_size); @@ -713,7 +801,8 @@ void DecodeEntity(BB_Reader *br, Entity *e) #else -//- Encode +//////////////////////////////// +//~ Encode void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1) { @@ -723,17 +812,21 @@ void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1) /* FIXME: Things like xforms need to be retreived manually rather than memcopied. * This will also be true for things like ent handles once uids are implemented. */ - /* TODO: Granular delta encoding */ + /* TODO: Granular delta encoding */ u64 pos = 0; e1->ss = e0->ss; - while (pos < sizeof(*e1)) { + while (pos < sizeof(*e1)) + { u64 chunk_size = MinU64(pos + 8, sizeof(*e1)) - pos; u8 *chunk0 = (u8 *)e0 + pos; u8 *chunk1 = (u8 *)e1 + pos; - if (EqBytes(chunk0, chunk1, chunk_size)) { + if (EqBytes(chunk0, chunk1, chunk_size)) + { BB_WriteBit(bw, 0); - } else { + } + else + { BB_WriteBit(bw, 1); u64 bits = 0; CopyBytes(&bits, chunk1, chunk_size); @@ -744,16 +837,19 @@ void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1) e1->ss = ss; } -//- Decode +//////////////////////////////// +//~ Decode void DecodeEntity(BB_Reader *br, Entity *e) { Entity decoded = *e; { u64 pos = 0; - while (pos < sizeof(decoded)) { + while (pos < sizeof(decoded)) + { u8 *chunk = (u8 *)&decoded + pos; - if (BB_ReadBit(br)) { + if (BB_ReadBit(br)) + { u64 chunk_size = MinU64(pos + 8, sizeof(decoded)) - pos; u64 bits = BB_ReadUBits(br, 64); CopyBytes(chunk, &bits, chunk_size); @@ -767,7 +863,8 @@ void DecodeEntity(BB_Reader *br, Entity *e) EntityId new_id = decoded.id; CopyStruct(e, &decoded); e->id = old_id; - if (!EqId(old_id, new_id)) { + if (!EqId(old_id, new_id)) + { SetEntityId(e, new_id); } } diff --git a/src/pp/pp_ent.h b/src/pp/pp_ent.h index c1389e61..9846cf33 100644 --- a/src/pp/pp_ent.h +++ b/src/pp/pp_ent.h @@ -558,7 +558,11 @@ void CreateMissingEntitiesFromSnapshots(Entity *local_parent, Entity *remote, En void SyncEntity(Entity *local, Entity *remote); //////////////////////////////// -//~ Encode / decode operations +//~ Encode void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1); + +//////////////////////////////// +//~ Decode + void DecodeEntity(BB_Reader *br, Entity *e); diff --git a/src/pp/pp_phys.c b/src/pp/pp_phys.c index b0b7a158..158443a0 100644 --- a/src/pp/pp_phys.c +++ b/src/pp/pp_phys.c @@ -7,7 +7,7 @@ b32 CanEntitiesContact(Entity *e0, Entity *e1) result = e0 != e1 && !EqId(e0->top, e1->top) && !(HasProp(e0, Prop_Wall) && HasProp(e1, Prop_Wall)); - return result; + return result; } void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration) @@ -22,7 +22,8 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio Entity *root = EntityFromId(ss, RootEntityId); u64 tick = ss->tick; - for (u64 check0_index = 0; check0_index < ss->num_ents_reserved; ++check0_index) { + for (u64 check0_index = 0; check0_index < ss->num_ents_reserved; ++check0_index) + { Entity *check0 = &ss->ents[check0_index]; if (!IsValidAndActive(check0)) continue; if (!(HasProp(check0, Prop_Solid) || HasProp(check0, Prop_Sensor))) continue; @@ -34,7 +35,8 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio SpaceIter iter = space_iter_begin_aabb(space, aabb); SpaceEntry *space_entry; - while ((space_entry = space_iter_next(&iter)) != 0) { + while ((space_entry = space_iter_next(&iter)) != 0) + { Entity *check1 = EntityFromId(ss, space_entry->ent); if (!IsValidAndActive(check1)) continue; if (!(HasProp(check1, Prop_Solid) || HasProp(check1, Prop_Sensor))) continue; @@ -48,14 +50,17 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio Xform e1_xf; CLD_Shape e0_collider; CLD_Shape e1_collider; - if (check0->id.uid.hi < check1->id.uid.hi) { + if (check0->id.uid.hi < check1->id.uid.hi) + { e0 = check0; e1 = check1; e0_xf = check0_xf; e1_xf = XformFromEntity(check1); e0_collider = check0_collider; e1_collider = check1->local_collider; - } else { + } + else + { e0 = check1; e1 = check0; e0_xf = XformFromEntity(check1); @@ -67,11 +72,15 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio EntityId constraint_id = ContactConstraintIdFromContactingIds(local_player, e0->id, e1->id); Entity *constraint_ent = EntityFromId(ss, constraint_id); - if (constraint_ent->valid) { - if (constraint_ent->contact_constraint_data.last_phys_iteration >= phys_iteration) { + if (constraint_ent->valid) + { + if (constraint_ent->contact_constraint_data.last_phys_iteration >= phys_iteration) + { /* Already processed constraint this iteration */ continue; - } else { + } + else + { constraint_ent->contact_constraint_data.last_phys_iteration = phys_iteration; } } @@ -84,9 +93,11 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio StaticAssert(countof(collision_result.points) == 2); ContactConstraint *constraint = 0; - if (collision_result.num_points > 0) { + if (collision_result.num_points > 0) + { b32 is_start = 0; - if (!constraint_ent->valid) { + if (!constraint_ent->valid) + { is_start = 1; /* Create constraint */ constraint_ent = AcquireLocalWithId(root, constraint_id); @@ -106,17 +117,21 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio constraint->friction = SqrtF32(e0->friction * e1->friction); /* Delete old contacts that are no longer present */ - for (u32 i = 0; i < constraint->num_points; ++i) { + for (u32 i = 0; i < constraint->num_points; ++i) + { ContactPoint *old = &constraint->points[i]; u32 id = old->id; b32 found = 0; - for (u32 j = 0; j < collision_result.num_points; ++j) { - if (collision_result.points[j].id == id) { + for (u32 j = 0; j < collision_result.num_points; ++j) + { + if (collision_result.points[j].id == id) + { found = 1; break; } } - if (!found) { + if (!found) + { /* Delete contact by replacing with last in array */ *old = constraint->points[--constraint->num_points]; --i; @@ -124,21 +139,25 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio } /* Update / insert returned contacts */ - for (u32 i = 0; i < collision_result.num_points; ++i) { + for (u32 i = 0; i < collision_result.num_points; ++i) + { CLD_CollisionPoint *res_point = &collision_result.points[i]; Vec2 point = res_point->point; f32 sep = res_point->separation; u32 id = res_point->id; ContactPoint *contact = 0; /* Match */ - for (u32 j = 0; j < constraint->num_points; ++j) { + for (u32 j = 0; j < constraint->num_points; ++j) + { ContactPoint *t = &constraint->points[j]; - if (t->id == id) { + if (t->id == id) + { contact = t; break; } } - if (!contact) { + if (!contact) + { /* Insert */ contact = &constraint->points[constraint->num_points++]; ZeroStruct(contact); @@ -163,17 +182,20 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio Vec2 dir1 = e1->collision_dir; f32 threshold = 0.5; b32 is_wrong_dir = 0; - if (!IsVec2Zero(dir0)) { + if (!IsVec2Zero(dir0)) + { is_wrong_dir = DotVec2(dir0, normal) <= threshold; } - if (!IsVec2Zero(dir1) && !is_wrong_dir) { + if (!IsVec2Zero(dir1) && !is_wrong_dir) + { is_wrong_dir = DotVec2(dir1, NegVec2(normal)) <= threshold; } constraint->wrong_dir = is_wrong_dir; } /* Run collision callback */ - if (collision_callback) { + if (collision_callback) + { CollisionData data = ZI; data.e0 = e0->id; data.e1 = e1->id; @@ -183,7 +205,8 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio /* Calculate point */ Vec2 midpoint = collision_result.points[0].point; - if (collision_result.num_points > 1) { + if (collision_result.num_points > 1) + { midpoint = AddVec2(midpoint, MulVec2(SubVec2(collision_result.points[1].point, midpoint), 0.5f)); } data.point = midpoint; @@ -213,11 +236,14 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio /* Run callback twice for both e0 & e1 */ b32 skip_solve0 = collision_callback(&data, sim_step_ctx); b32 skip_solve1 = collision_callback(&data_inverted, sim_step_ctx); - if (skip_solve0 || skip_solve1) { + if (skip_solve0 || skip_solve1) + { constraint->skip_solve = 1; } } - } else if (constraint_ent->valid) { + } + else if (constraint_ent->valid) + { constraint_ent->contact_constraint_data.num_points = 0; } @@ -226,7 +252,8 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio { EntityId dbg_ent_id = CollisionDebugIdFromIds(local_player, e0->id, e1->id); Entity *dbg_ent = EntityFromId(ss, dbg_ent_id); - if (!dbg_ent->valid) { + if (!dbg_ent->valid) + { /* FIXME: Entity never released */ dbg_ent = AcquireLocalWithId(root, dbg_ent_id); EnableProp(dbg_ent, Prop_CollisionDebug); @@ -238,10 +265,13 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio dbg->e1 = e1->id; dbg->collision_result = collision_result; - if (constraint) { + if (constraint) + { CopyBytes(dbg->points, constraint->points, sizeof(dbg->points)); dbg->num_points = constraint->num_points; - } else { + } + else + { dbg->num_points = 0; } @@ -266,7 +296,8 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration) __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *constraint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(constraint_ent)) continue; if (!HasProp(constraint_ent, Prop_ContactConstraint)) continue; @@ -276,7 +307,8 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration) u32 num_points = constraint->num_points; Entity *e0 = EntityFromId(ss, constraint->e0); Entity *e1 = EntityFromId(ss, constraint->e1); - if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && IsValidAndActive(e0) && IsValidAndActive(e1)) { + if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && IsValidAndActive(e0) && IsValidAndActive(e1)) + { Vec2 normal = constraint->normal; Vec2 tangent = PerpVec2(normal); @@ -291,14 +323,16 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration) f32 inv_i1 = 0; { /* If not simulated locally or ent is not dynamic, pretend contact mass is infinite */ - if (ShouldSimulate(e0) && HasProp(e0, Prop_Dynamic)) { + if (ShouldSimulate(e0) && HasProp(e0, Prop_Dynamic)) + { f32 scale = AbsF32(DeterminantFromXform(e0_xf)); f32 scaled_mass = e0->mass_unscaled * scale; f32 scaled_inertia = e0->inertia_unscaled * scale; inv_m0 = 1.f / scaled_mass; inv_i0 = 1.f / scaled_inertia; } - if (ShouldSimulate(e1) && HasProp(e1, Prop_Dynamic)) { + if (ShouldSimulate(e1) && HasProp(e1, Prop_Dynamic)) + { f32 scale = AbsF32(DeterminantFromXform(e1_xf)); f32 scaled_mass = e1->mass_unscaled * scale; f32 scaled_inertia = e1->inertia_unscaled * scale; @@ -313,7 +347,8 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration) constraint->inv_i1 = inv_i1; /* Update / insert returned contacts */ - for (u32 i = 0; i < num_points; ++i) { + for (u32 i = 0; i < num_points; ++i) + { ContactPoint *contact = &constraint->points[i]; Vec2 vcp0 = contact->vcp0; Vec2 vcp1 = contact->vcp1; @@ -339,7 +374,9 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration) contact->tangent_impulse = 0; #endif } - } else { + } + else + { /* Mark constraint for removal */ constraint_ent->contact_constraint_data.num_points = 0; DisableProp(constraint_ent, Prop_Active); @@ -350,7 +387,8 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration) #if 0 #if COLLIDER_DEBUG /* Remove collision debug ents */ - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *dbg_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(dbg_ent)) continue; if (!HasProp(dbg_ent, Prop_CollisionDebug)) continue; @@ -361,7 +399,8 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration) if (!(ShouldSimulate(e0) && ShouldSimulate(e1)) || !(HasProp(e0, Prop_Solid) || HasProp(e0, Prop_Sensor)) || - !(HasProp(e1, Prop_Solid) || HasProp(e1, Prop_Sensor))) { + !(HasProp(e1, Prop_Solid) || HasProp(e1, Prop_Sensor))) + { /* Mark dbg ent for removal */ DisableProp(dbg_ent, Prop_Active); EnableProp(dbg_ent, Prop_Release); @@ -375,7 +414,8 @@ void WarmStartContacts(PhysStepCtx *ctx) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *constraint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(constraint_ent)) continue; if (!HasProp(constraint_ent, Prop_ContactConstraint)) continue; @@ -386,7 +426,8 @@ void WarmStartContacts(PhysStepCtx *ctx) Entity *e0 = EntityFromId(ss, constraint->e0); Entity *e1 = EntityFromId(ss, constraint->e1); - if (num_points > 0 && IsValidAndActive(e0) && IsValidAndActive(e1) && !constraint->skip_solve && !constraint->wrong_dir) { + if (num_points > 0 && IsValidAndActive(e0) && IsValidAndActive(e1) && !constraint->skip_solve && !constraint->wrong_dir) + { f32 inv_m0 = constraint->inv_m0; f32 inv_m1 = constraint->inv_m1; f32 inv_i0 = constraint->inv_i0; @@ -401,7 +442,8 @@ void WarmStartContacts(PhysStepCtx *ctx) Vec2 normal = constraint->normal; Vec2 tangent = PerpVec2(normal); f32 inv_num_points = 1.f / num_points; - for (u32 i = 0; i < num_points; ++i) { + for (u32 i = 0; i < num_points; ++i) + { ContactPoint *point = &constraint->points[i]; Vec2 vcp0 = point->vcp0; Vec2 vcp1 = point->vcp1; @@ -427,7 +469,8 @@ void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *constraint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(constraint_ent)) continue; if (!HasProp(constraint_ent, Prop_ContactConstraint)) continue; @@ -443,7 +486,8 @@ void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias) f32 w1 = e1->angular_velocity; u32 num_points = constraint->num_points; - if (num_points > 0 && IsValidAndActive(e0) && IsValidAndActive(e1) && !constraint->skip_solve && !constraint->wrong_dir) { + if (num_points > 0 && IsValidAndActive(e0) && IsValidAndActive(e1) && !constraint->skip_solve && !constraint->wrong_dir) + { Xform e0_xf = XformFromEntity(e0); Xform e1_xf = XformFromEntity(e1); @@ -454,7 +498,8 @@ void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias) /* Normal impulse */ Vec2 normal = constraint->normal; - for (u32 point_index = 0; point_index < num_points; ++point_index) { + for (u32 point_index = 0; point_index < num_points; ++point_index) + { ContactPoint *point = &constraint->points[point_index]; Vec2 vcp0 = point->vcp0; Vec2 vcp1 = point->vcp1; @@ -468,10 +513,13 @@ void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias) f32 mass_scale = 1.0f; f32 impulse_scale = 0.0f; - if (separation > 0.0f) { + if (separation > 0.0f) + { /* Speculative */ velocity_bias = separation / dt; - } else if (apply_bias) { + } + else if (apply_bias) + { /* Soft constraint */ SoftSpring softness = MakeSpring(ContactSpringHz, ContactSpringDamp, dt); f32 pushout_velocity = constraint->pushout_velocity; @@ -504,7 +552,8 @@ void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias) /* Tangent impulse */ Vec2 tangent = PerpVec2(normal); - for (u32 point_index = 0; point_index < num_points; ++point_index) { + for (u32 point_index = 0; point_index < num_points; ++point_index) + { ContactPoint *point = &constraint->points[point_index]; Vec2 vcp0 = point->vcp0; Vec2 vcp1 = point->vcp1; @@ -564,7 +613,8 @@ void PrepareMotorJoints(PhysStepCtx *ctx) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *joint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(joint_ent)) continue; if (!HasProp(joint_ent, Prop_MotorJoint)) continue; @@ -574,7 +624,8 @@ void PrepareMotorJoints(PhysStepCtx *ctx) Entity *e0 = EntityFromId(ss, joint->e0); Entity *e1 = EntityFromId(ss, joint->e1); - if (ShouldSimulate(e0) && ShouldSimulate(e1)) { + if (ShouldSimulate(e0) && ShouldSimulate(e1)) + { Xform e0_xf = XformFromEntity(e0); Xform e1_xf = XformFromEntity(e1); @@ -616,7 +667,9 @@ void PrepareMotorJoints(PhysStepCtx *ctx) joint->linear_impulse = VEC2(0, 0); joint->angular_impulse = 0; #endif - } else { + } + else + { /* Mark joint for removal */ DisableProp(joint_ent, Prop_Active); EnableProp(joint_ent, Prop_Release); @@ -628,7 +681,8 @@ void WarmStartMotorJoints(PhysStepCtx *ctx) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *joint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(joint_ent)) continue; if (!HasProp(joint_ent, Prop_MotorJoint)) continue; @@ -660,7 +714,8 @@ void SolveMotorJoints(PhysStepCtx *ctx, f32 dt) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *joint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(joint_ent)) continue; if (!HasProp(joint_ent, Prop_MotorJoint)) continue; @@ -765,14 +820,16 @@ void PrepareMouseJoints(PhysStepCtx *ctx) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *joint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(joint_ent)) continue; if (!HasProp(joint_ent, Prop_MouseJoint)) continue; MouseJoint *joint = &joint_ent->mouse_joint_data; Entity *ent = EntityFromId(ss, joint->target); - if (ShouldSimulate(ent)) { + if (ShouldSimulate(ent)) + { Xform xf = XformFromEntity(ent); /* TODO: Cache this */ @@ -800,7 +857,9 @@ void PrepareMouseJoints(PhysStepCtx *ctx) joint->linear_impulse = VEC2(0, 0); joint->angular_impulse = 0; #endif - } else { + } + else + { /* Mark joint for removal */ DisableProp(joint_ent, Prop_Active); EnableProp(joint_ent, Prop_Release); @@ -812,14 +871,16 @@ void WarmStartMouseJoints(PhysStepCtx *ctx) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *joint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(joint_ent)) continue; if (!HasProp(joint_ent, Prop_MouseJoint)) continue; MouseJoint *joint = &joint_ent->mouse_joint_data; Entity *ent = EntityFromId(ss, joint->target); - if (ShouldSimulate(ent)) { + if (ShouldSimulate(ent)) + { f32 inv_m = joint->inv_m; f32 inv_i = joint->inv_i; Xform xf = XformFromEntity(ent); @@ -834,14 +895,16 @@ void SolveMouseJoints(PhysStepCtx *ctx, f32 dt) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *joint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(joint_ent)) continue; if (!HasProp(joint_ent, Prop_MouseJoint)) continue; MouseJoint *joint = &joint_ent->mouse_joint_data; Entity *ent = EntityFromId(ss, joint->target); - if (ShouldSimulate(ent)) { + if (ShouldSimulate(ent)) + { Vec2 v = ent->linear_velocity; f32 w = ent->angular_velocity; @@ -929,7 +992,8 @@ void PrepareWeldJoints(PhysStepCtx *ctx) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *joint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(joint_ent)) continue; if (!HasProp(joint_ent, Prop_WeldJoint)) continue; @@ -939,7 +1003,8 @@ void PrepareWeldJoints(PhysStepCtx *ctx) WeldJoint *joint = &joint_ent->weld_joint_data; Entity *e0 = EntityFromId(ss, joint->e0); Entity *e1 = EntityFromId(ss, joint->e1); - if (ShouldSimulate(e0) && ShouldSimulate(e1)) { + if (ShouldSimulate(e0) && ShouldSimulate(e1)) + { Xform e0_xf = XformFromEntity(e0); Xform e1_xf = XformFromEntity(e1); @@ -966,7 +1031,9 @@ void PrepareWeldJoints(PhysStepCtx *ctx) joint->angular_impulse0 = 0; joint->angular_impulse1 = 0; #endif - } else { + } + else + { /* Mark joint for removal */ DisableProp(joint_ent, Prop_Active); EnableProp(joint_ent, Prop_Release); @@ -978,7 +1045,8 @@ void WarmStartWeldJoints(PhysStepCtx *ctx) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *joint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(joint_ent)) continue; if (!HasProp(joint_ent, Prop_WeldJoint)) continue; @@ -987,7 +1055,8 @@ void WarmStartWeldJoints(PhysStepCtx *ctx) #if 0 Entity *e0 = EntityFromId(ss, joint->e0); - if (ShouldSimulate(e0)) { + if (ShouldSimulate(e0)) + { f32 inv_m = joint->inv_m0; f32 inv_i = joint->inv_i0; Xform xf = XformFromEntity(e1); @@ -999,7 +1068,8 @@ void WarmStartWeldJoints(PhysStepCtx *ctx) #if 1 Entity *e1 = EntityFromId(ss, joint->e1); - if (ShouldSimulate(e1)) { + if (ShouldSimulate(e1)) + { f32 inv_m = joint->inv_m1; f32 inv_i = joint->inv_i1; SetLinearVelocity(e1, AddVec2(e1->linear_velocity, MulVec2(joint->linear_impulse1, inv_m))); @@ -1015,7 +1085,8 @@ void SolveWeldJoints(PhysStepCtx *ctx, f32 dt) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *joint_ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(joint_ent)) continue; if (!HasProp(joint_ent, Prop_WeldJoint)) continue; @@ -1023,7 +1094,8 @@ void SolveWeldJoints(PhysStepCtx *ctx, f32 dt) WeldJoint *joint = &joint_ent->weld_joint_data; Entity *e0 = EntityFromId(ss, joint->e0); Entity *e1 = EntityFromId(ss, joint->e1); - if (ShouldSimulate(e0) && ShouldSimulate(e1)) { + if (ShouldSimulate(e0) && ShouldSimulate(e1)) + { Xform xf0 = XformFromEntity(e0); Xform xf1 = XformFromEntity(e1); @@ -1094,20 +1166,23 @@ void IntegrateForces(PhysStepCtx *ctx, f32 dt) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(ent)) continue; b32 is_dynamic = HasProp(ent, Prop_Dynamic); b32 is_kinematic = HasProp(ent, Prop_Kinematic); - if (is_dynamic || is_kinematic) { + if (is_dynamic || is_kinematic) + { Vec2 linear_velocity = ent->linear_velocity; f32 angular_velocity = ent->angular_velocity; f32 linear_damping_factor = MaxF32(1.0f - (ent->linear_damping * dt), 0); f32 angular_damping_factor = MaxF32(1.0f - (ent->angular_damping * dt), 0); /* Integrate forces */ - if (is_dynamic) { + if (is_dynamic) + { Xform xf = XformFromEntity(ent); f32 det_abs = AbsF32(DeterminantFromXform(xf)); f32 mass = ent->mass_unscaled * det_abs; @@ -1136,7 +1211,8 @@ void IntegrateVelocities(PhysStepCtx *ctx, f32 dt) { __prof; Snapshot *ss = ctx->sim_step_ctx->world; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *ent = &ss->ents[sim_ent_index]; if (!ShouldSimulate(ent)) continue; if (!HasProp(ent, Prop_Dynamic) && !HasProp(ent, Prop_Kinematic)) continue; @@ -1156,7 +1232,8 @@ f32 DetermineEarliestToi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_i Space *space = ctx->sim_step_ctx->accel->space; f32 smallest_t = 1; - for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) { + for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) + { Entity *e0 = &ss->ents[e0_index]; if (!ShouldSimulate(e0)) continue; if (!(HasProp(e0, Prop_Solid) || HasProp(e0, Prop_Sensor))) continue; @@ -1174,7 +1251,8 @@ f32 DetermineEarliestToi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_i SpaceIter iter = space_iter_begin_aabb(space, combined_aabb); SpaceEntry *entry; - while ((entry = space_iter_next(&iter)) != 0) { + while ((entry = space_iter_next(&iter)) != 0) + { Entity *e1 = EntityFromId(ss, entry->ent); if (!ShouldSimulate(e1)) continue; if (!(HasProp(e1, Prop_Solid) || HasProp(e1, Prop_Sensor))) continue; @@ -1186,7 +1264,8 @@ f32 DetermineEarliestToi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_i Xform e1_xf_t1 = GetDerivedEntityXform(e1, step_dt); f32 t = CLD_TimeOfImpact(&e0_collider, &e1_collider, e0_xf_t0, e1_xf_t0, e0_xf_t1, e1_xf_t1, tolerance, max_iterations); - if (t != 0 && t < smallest_t) { + if (t != 0 && t < smallest_t) + { smallest_t = t; } } @@ -1204,13 +1283,16 @@ void UpdateAabbs(PhysStepCtx *ctx) __prof; Snapshot *ss = ctx->sim_step_ctx->world; Space *space = ctx->sim_step_ctx->accel->space; - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *ent = &ss->ents[sim_ent_index]; if (!IsValidAndActive(ent)) continue; - if (ent->local_collider.count > 0) { + if (ent->local_collider.count > 0) + { Xform xf = XformFromEntity(ent); SpaceEntry *space_entry = space_entry_from_handle(space, ent->space_handle); - if (!space_entry->valid) { + if (!space_entry->valid) + { space_entry = space_entry_acquire(space, ent->id); ent->space_handle = space_entry->handle; } @@ -1234,7 +1316,8 @@ void StepPhys(PhysStepCtx *ctx, f32 timestep) UpdateAabbs(ctx); f32 remaining_dt = timestep; - while (remaining_dt > 0) { + while (remaining_dt > 0) + { __profn("Step part"); ++phys_iteration; TempArena scratch = BeginScratchNoConflict(); @@ -1262,7 +1345,8 @@ void StepPhys(PhysStepCtx *ctx, f32 timestep) PrepareWeldJoints(ctx); f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS; - for (u32 i = 0; i < SIM_PHYSICS_SUBSTEPS; ++i) { + for (u32 i = 0; i < SIM_PHYSICS_SUBSTEPS; ++i) + { __profn("Substep"); /* Warm start */ diff --git a/src/pp/pp_sim.c b/src/pp/pp_sim.c index c3440d72..55825d65 100644 --- a/src/pp/pp_sim.c +++ b/src/pp/pp_sim.c @@ -24,74 +24,55 @@ * is used when working in contexts where id is irrelevant. */ -#define CLIENT_LOOKUP_BINS 127 -#define TICK_LOOKUP_BINS 127 -#define ID_LOOKUP_BINS 4096 + //////////////////////////////// + //~ Startup -/* ========================== * - * Startup - * ========================== */ - -Global struct { - Arena *nil_arena; - ClientStore *nil_client_store; - Client *nil_client; - Snapshot *nil_snapshot; - Entity *nil_ent; -} G = ZI, DebugAlias(G, G_sim); - -/* Accessed via `sim_client_store_nil()` */ -Readonly ClientStore **_g_sim_client_store_nil = &G.nil_client_store; - -/* Accessed via `sim_client_nil()` */ -Readonly Client **_g_sim_client_nil = &G.nil_client; - -/* Accessed via `sim_snapshot_nil()` */ -Readonly Snapshot **_g_sim_snapshot_nil = &G.nil_snapshot; - -/* Accessed via `NilEntity()` */ -Readonly Entity **_g_sim_ent_nil = &G.nil_ent; +SharedSimCtx shared_sim_ctx = ZI; +Readonly ClientStore **_g_sim_client_store_nil = &shared_sim_ctx.nil_client_store; +Readonly Client **_g_sim_client_nil = &shared_sim_ctx.nil_client; +Readonly Snapshot **_g_sim_snapshot_nil = &shared_sim_ctx.nil_snapshot; +Readonly Entity **_g_sim_ent_nil = &shared_sim_ctx.nil_ent; void StartupSim(void) { __prof; - G.nil_arena = AcquireArena(Gibi(1)); + SharedSimCtx *g = &shared_sim_ctx; + g->nil_arena = AcquireArena(Gibi(1)); /* Nil client store */ - G.nil_client_store = PushStruct(G.nil_arena, ClientStore); - G.nil_client_store->valid = 0; + g->nil_client_store = PushStruct(g->nil_arena, ClientStore); + g->nil_client_store->valid = 0; /* Nil client */ - G.nil_client = PushStruct(G.nil_arena, Client); - G.nil_client->valid = 0; - G.nil_client->store = sim_client_store_nil(); + g->nil_client = PushStruct(g->nil_arena, Client); + g->nil_client->valid = 0; + g->nil_client->store = sim_client_store_nil(); /* Nil snapshot */ - G.nil_snapshot = PushStruct(G.nil_arena, Snapshot); - G.nil_snapshot->valid = 0; - G.nil_snapshot->client = sim_client_nil(); + g->nil_snapshot = PushStruct(g->nil_arena, Snapshot); + g->nil_snapshot->valid = 0; + g->nil_snapshot->client = sim_client_nil(); /* Nil ent */ - G.nil_ent = PushStruct(G.nil_arena, Entity); - G.nil_ent->ss = sim_snapshot_nil(); - G.nil_ent->valid = 0; - G.nil_ent->id = NilEntityId; - G.nil_ent->_local_xform = XformIdentity; - G.nil_ent->_xform = XformIdentity; - G.nil_ent->_is_xform_dirty = 0; - G.nil_ent->friction = 0.5f; - G.nil_ent->mass_unscaled = 1; - G.nil_ent->inertia_unscaled = 1; - G.nil_ent->sprite_local_xform = XformIdentity; - G.nil_ent->sprite_tint = ColorWhite; + g->nil_ent = PushStruct(g->nil_arena, Entity); + g->nil_ent->ss = sim_snapshot_nil(); + g->nil_ent->valid = 0; + g->nil_ent->id = NilEntityId; + g->nil_ent->_local_xform = XformIdentity; + g->nil_ent->_xform = XformIdentity; + g->nil_ent->_is_xform_dirty = 0; + g->nil_ent->friction = 0.5f; + g->nil_ent->mass_unscaled = 1; + g->nil_ent->inertia_unscaled = 1; + g->nil_ent->sprite_local_xform = XformIdentity; + g->nil_ent->sprite_tint = ColorWhite; /* Lock nil arena */ - SetArenaReadonly(G.nil_arena); + SetArenaReadonly(g->nil_arena); } -/* ========================== * - * Client store alloc - * ========================== */ +//////////////////////////////// +//~ Acquire client store ClientStore *sim_client_store_acquire(void) { @@ -113,9 +94,11 @@ ClientStore *sim_client_store_acquire(void) void sim_client_store_release(ClientStore *store) { __prof; - for (u64 i = 0; i < store->num_clients_reserved; ++i) { + for (u64 i = 0; i < store->num_clients_reserved; ++i) + { Client *client = &store->clients[i]; - if (client->valid) { + if (client->valid) + { sim_client_release(client); } } @@ -123,20 +106,22 @@ void sim_client_store_release(ClientStore *store) ReleaseArena(store->arena); } -/* ========================== * - * Client alloc - * ========================== */ +//////////////////////////////// +//~ Acquire client Client *sim_client_acquire(ClientStore *store) { ClientHandle handle = ZI; Client *client = sim_client_from_handle(store, store->first_free_client); - if (client->valid) { + if (client->valid) + { store->first_free_client = client->next_free; handle = client->handle; ++handle.gen; - } else { + } + else + { client = PushStructNoZero(store->clients_arena, Client); handle.gen = 1; handle.idx = store->num_clients_reserved; @@ -158,10 +143,12 @@ Client *sim_client_acquire(ClientStore *store) void sim_client_release(Client *client) { /* Release internal snapshot memory */ - for (u64 i = 0; i < client->num_snapshot_lookup_bins; ++i) { + for (u64 i = 0; i < client->num_snapshot_lookup_bins; ++i) + { SnapshotLookupBin *bin = &client->snapshot_lookup_bins[i]; Snapshot *ss = bin->first; - while (ss) { + while (ss) + { Snapshot *next = ss->next_in_bin; ReleaseArena(ss->ents_arena); ReleaseArena(ss->arena); @@ -182,11 +169,10 @@ void sim_client_release(Client *client) ReleaseArena(client->snapshots_arena); } -/* ========================== * - * Client lookup - * ========================== */ +//////////////////////////////// +//~ Client lookup -internal u64 hash_from_channel_id(N_ChannelId channel_id) +u64 client_channel_hash_hash_from_channel_id(N_ChannelId channel_id) { return HashFnv64(Fnv64Basis, StringFromStruct(&channel_id)); } @@ -197,37 +183,48 @@ void sim_client_set_channel_id(Client *client, N_ChannelId channel_id) N_ChannelId old_channel_id = client->channel_id; /* Remove old channel id from channel lookup */ - if (!N_IsChannelIdNil(old_channel_id)) { + if (!N_IsChannelIdNil(old_channel_id)) + { u64 bin_index = client->channel_hash % store->num_client_lookup_bins; ClientLookupBin *bin = &store->client_lookup_bins[bin_index]; Client *prev = sim_client_from_handle(store, client->prev_in_bin); Client *next = sim_client_from_handle(store, client->next_in_bin); - if (prev->valid) { + if (prev->valid) + { prev->next_in_bin = next->handle; - } else { + } + else + { bin->first = next->handle; } - if (next->valid) { + if (next->valid) + { next->prev_in_bin = prev->handle; - } else { + } + else + { bin->last = prev->handle; } } /* Insert into channel lookup */ /* TODO: Enforce no duplicates */ - u64 channel_hash = hash_from_channel_id(channel_id); + u64 channel_hash = client_channel_hash_hash_from_channel_id(channel_id); client->channel_id = channel_id; client->channel_hash = channel_hash; - if (!N_IsChannelIdNil(channel_id)) { + if (!N_IsChannelIdNil(channel_id)) + { u64 bin_index = channel_hash % store->num_client_lookup_bins; ClientLookupBin *bin = &store->client_lookup_bins[bin_index]; { Client *prev_in_bin = sim_client_from_handle(store, bin->last); - if (prev_in_bin->valid) { + if (prev_in_bin->valid) + { prev_in_bin->next_in_bin = client->handle; client->prev_in_bin = prev_in_bin->handle; - } else { + } + else + { bin->first = client->handle; } bin->last = client->handle; @@ -238,11 +235,13 @@ void sim_client_set_channel_id(Client *client, N_ChannelId channel_id) Client *sim_client_from_channel_id(ClientStore *store, N_ChannelId channel_id) { Client *result = sim_client_nil(); - u64 channel_hash = hash_from_channel_id(channel_id); + u64 channel_hash = client_channel_hash_hash_from_channel_id(channel_id); u64 bin_index = channel_hash % store->num_client_lookup_bins; ClientLookupBin *bin = &store->client_lookup_bins[bin_index]; - for (Client *client = sim_client_from_handle(store, bin->first); client->valid; client = sim_client_from_handle(store, client->next_in_bin)) { - if (client->channel_hash == channel_hash) { + for (Client *client = sim_client_from_handle(store, bin->first); client->valid; client = sim_client_from_handle(store, client->next_in_bin)) + { + if (client->channel_hash == channel_hash) + { result = client; break; } @@ -252,23 +251,25 @@ Client *sim_client_from_channel_id(ClientStore *store, N_ChannelId channel_id) Client *sim_client_from_handle(ClientStore *store, ClientHandle handle) { - if (handle.gen != 0 && handle.idx < store->num_clients_reserved) { + if (handle.gen != 0 && handle.idx < store->num_clients_reserved) + { Client *client = &store->clients[handle.idx]; - if (client->handle.gen == handle.gen) { + if (client->handle.gen == handle.gen) + { return client; } } return sim_client_nil(); } -/* ========================== * - * Snapshot alloc - * ========================== */ +//////////////////////////////// +//~ Acquire snapshot /* Produces a new snapshot at `tick` with data copied from `src` snapshot. */ Snapshot *sim_snapshot_acquire(Client *client, Snapshot *src, u64 tick) { - if (tick == 0) { + if (tick == 0) + { return sim_snapshot_nil(); } @@ -278,12 +279,15 @@ Snapshot *sim_snapshot_acquire(Client *client, Snapshot *src, u64 tick) Arena *ents_arena = 0; { ss = client->first_free_snapshot; - if (ss) { + if (ss) + { /* Re-use existing snasphot arenas */ client->first_free_snapshot = ss->next_free; ents_arena = ss->ents_arena; arena = ss->arena; - } else { + } + else + { /* Arenas allocated here will be released with client */ arena = AcquireArena(Gibi(1)); ents_arena = AcquireArena(Gibi(1)); @@ -312,11 +316,15 @@ Snapshot *sim_snapshot_acquire(Client *client, Snapshot *src, u64 tick) /* Copy id lookup bins */ ss->num_id_bins = src->num_id_bins > 0 ? src->num_id_bins : ID_LOOKUP_BINS; ss->id_bins = PushStructsNoZero(ss->arena, EntBin, ss->num_id_bins); - if (src->num_id_bins > 0) { - for (u64 i = 0; i < src->num_id_bins; ++i) { + if (src->num_id_bins > 0) + { + for (u64 i = 0; i < src->num_id_bins; ++i) + { ss->id_bins[i] = src->id_bins[i]; } - } else { + } + else + { ZeroBytes(ss->id_bins, sizeof(*ss->id_bins) * ss->num_id_bins); } @@ -325,7 +333,8 @@ Snapshot *sim_snapshot_acquire(Client *client, Snapshot *src, u64 tick) ss->num_ents_allocated = src->num_ents_allocated; ss->num_ents_reserved = src->num_ents_reserved; ss->ents = PushStructsNoZero(ss->ents_arena, Entity, ss->num_ents_reserved); - if (ss->num_ents_reserved == 0) { + if (ss->num_ents_reserved == 0) + { /* Copying from nil snapshot, need to create blank & root entity */ /* Push blank ent at index 0 (because index 0 is never valid anyway since it maps to NilEntity()) */ @@ -348,8 +357,11 @@ Snapshot *sim_snapshot_acquire(Client *client, Snapshot *src, u64 tick) ++ss->num_ents_allocated; ++ss->num_ents_reserved; } - } else { - for (u64 i = 0; i < ss->num_ents_reserved; ++i) { + } + else + { + for (u64 i = 0; i < ss->num_ents_reserved; ++i) + { Entity *dst_ent = &ss->ents[i]; Entity *src_ent = &src->ents[i]; *dst_ent = *src_ent; @@ -360,7 +372,8 @@ Snapshot *sim_snapshot_acquire(Client *client, Snapshot *src, u64 tick) /* Release duplicate tick if it exists */ { Snapshot *existing = sim_snapshot_from_tick(client, tick); - if (existing->valid) { + if (existing->valid) + { sim_snapshot_release(existing); } } @@ -368,28 +381,39 @@ Snapshot *sim_snapshot_acquire(Client *client, Snapshot *src, u64 tick) /* Linear search to insert snapshot in tick order */ { Snapshot *prev = sim_snapshot_from_tick(client, client->last_tick); - while (prev->valid) { - if (prev->tick < tick) { + while (prev->valid) + { + if (prev->tick < tick) + { break; } prev = sim_snapshot_from_tick(client, prev->prev_tick); } - if (prev->valid) { + if (prev->valid) + { Snapshot *next = sim_snapshot_from_tick(client, prev->next_tick); - if (next->valid) { + if (next->valid) + { next->prev_tick = tick; - } else { + } + else + { client->last_tick = tick; } ss->next_tick = prev->next_tick; ss->prev_tick = prev->tick; prev->next_tick = ss->tick; - } else { + } + else + { Snapshot *first = sim_snapshot_from_tick(client, client->first_tick); - if (first->valid) { + if (first->valid) + { ss->next_tick = first->tick; first->prev_tick = tick; - } else { + } + else + { client->last_tick = tick; } ss->next_tick = client->first_tick; @@ -401,10 +425,13 @@ Snapshot *sim_snapshot_acquire(Client *client, Snapshot *src, u64 tick) { u64 bin_index = tick % client->num_snapshot_lookup_bins; SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index]; - if (bin->last) { + if (bin->last) + { bin->last->next_in_bin = ss; ss->prev_in_bin = bin->last; - } else { + } + else + { bin->first = ss; } bin->last = ss; @@ -423,14 +450,20 @@ void sim_snapshot_release(Snapshot *ss) SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index]; Snapshot *prev = ss->prev_in_bin; Snapshot *next = ss->next_in_bin; - if (prev) { + if (prev) + { prev->next_in_bin = next; - } else { + } + else + { bin->first = next; } - if (next) { + if (next) + { next->prev_in_bin = prev; - } else { + } + else + { bin->last = prev; } } @@ -439,14 +472,20 @@ void sim_snapshot_release(Snapshot *ss) { Snapshot *prev = sim_snapshot_from_tick(client, ss->prev_tick); Snapshot *next = sim_snapshot_from_tick(client, ss->next_tick); - if (prev->valid) { + if (prev->valid) + { prev->next_tick = next->tick; - } else { + } + else + { client->first_tick = next->tick; } - if (next->valid) { + if (next->valid) + { next->prev_tick = prev->tick; - } else { + } + else + { client->last_tick = prev->tick; } } @@ -460,20 +499,26 @@ void sim_snapshot_release(Snapshot *ss) /* Release all snapshots for client with tick in range [start, end] */ void sim_snapshot_release_ticks_in_range(Client *client, u64 start, u64 end) { - if (start > end) { + if (start > end) + { u64 swp = start; start = end; end = swp; } Snapshot *ss = sim_snapshot_from_tick(client, client->first_tick); - while (ss->valid) { + while (ss->valid) + { u64 tick = ss->tick; u64 next_tick = ss->next_tick; - if (tick >= start) { - if (tick <= end) { + if (tick >= start) + { + if (tick <= end) + { sim_snapshot_release(ss); - } else { + } + else + { break; } } @@ -481,18 +526,20 @@ void sim_snapshot_release_ticks_in_range(Client *client, u64 start, u64 end) } } -/* ========================== * - * Snapshot lookup - * ========================== */ +//////////////////////////////// +//~ Snapshot lookup Snapshot *sim_snapshot_from_tick(Client *client, u64 tick) { Snapshot *ss = sim_snapshot_nil(); - if (tick > 0) { + if (tick > 0) + { u64 bin_index = tick % client->num_snapshot_lookup_bins; SnapshotLookupBin *bin = &client->snapshot_lookup_bins[bin_index]; - for (Snapshot *search = bin->first; search; search = search->next_in_bin) { - if (search->tick == tick) { + for (Snapshot *search = bin->first; search; search = search->next_in_bin) + { + if (search->tick == tick) + { ss = search; break; } @@ -505,11 +552,14 @@ Snapshot *sim_snapshot_from_tick(Client *client, u64 tick) Snapshot *sim_snapshot_from_closest_tick_lte(Client *client, u64 tick) { Snapshot *ss = sim_snapshot_from_tick(client, tick); - if (!ss->valid) { + if (!ss->valid) + { /* Degenerate to linear search */ ss = sim_snapshot_from_tick(client, client->last_tick); - while (ss->valid) { - if (ss->tick <= tick) { + while (ss->valid) + { + if (ss->tick <= tick) + { break; } ss = sim_snapshot_from_tick(client, ss->prev_tick); @@ -522,11 +572,14 @@ Snapshot *sim_snapshot_from_closest_tick_lte(Client *client, u64 tick) Snapshot *sim_snapshot_from_closest_tick_gte(Client *client, u64 tick) { Snapshot *ss = sim_snapshot_from_tick(client, tick); - if (!ss->valid) { + if (!ss->valid) + { /* Degenerate to linear search */ ss = sim_snapshot_from_tick(client, client->first_tick); - while (ss->valid) { - if (ss->tick >= tick) { + while (ss->valid) + { + if (ss->tick >= tick) + { break; } ss = sim_snapshot_from_tick(client, ss->next_tick); @@ -535,9 +588,8 @@ Snapshot *sim_snapshot_from_closest_tick_gte(Client *client, u64 tick) return ss; } -/* ========================== * - * Tile - * ========================== */ +//////////////////////////////// +//~ Tile Vec2I32 sim_world_tile_index_from_pos(Vec2 pos) { @@ -594,7 +646,8 @@ void sim_snapshot_set_tile(Snapshot *ss, Vec2I32 world_tile_index, TileKind tile EntityId chunk_id = TileChunkIdFromIndex(chunk_index); Entity *chunk_ent = EntityFromId(ss, chunk_id); - if (!chunk_ent->valid) { + if (!chunk_ent->valid) + { Entity *root = EntityFromId(ss, RootEntityId); chunk_ent = AcquireSyncSrcWithId(root, chunk_id); EnableProp(chunk_ent, Prop_TileChunk); @@ -605,9 +658,8 @@ void sim_snapshot_set_tile(Snapshot *ss, Vec2I32 world_tile_index, TileKind tile chunk_ent->tile_chunk_tiles[local_index.x + (local_index.y * SIM_TILES_PER_CHUNK_SQRT)] = tile_kind; } -/* ========================== * - * Snapshot lerp - * ========================== */ +//////////////////////////////// +//~ Snapshot lerp Snapshot *sim_snapshot_acquire_from_lerp(Client *client, Snapshot *ss0, Snapshot *ss1, f64 blend) { @@ -618,23 +670,30 @@ Snapshot *sim_snapshot_acquire_from_lerp(Client *client, Snapshot *ss0, Snapshot Snapshot *ss; b32 should_blend = 1; - if (ss0->continuity_gen == ss1->continuity_gen && 0 < blend && blend < 1) { + if (ss0->continuity_gen == ss1->continuity_gen && 0 < blend && blend < 1) + { ss = sim_snapshot_acquire(client, ss0, ss0->tick); - } else if (RoundF64ToI64(blend) <= 0) { + } + else if (RoundF64ToI64(blend) <= 0) + { ss = sim_snapshot_acquire(client, ss0, ss0->tick); should_blend = 0; - } else { + } + else + { ss = sim_snapshot_acquire(client, ss1, ss1->tick); should_blend = 0; } - if (!ss0->valid || !ss1->valid) { + if (!ss0->valid || !ss1->valid) + { /* New snapshot allocation caused one of the src snapshots original to release. * ss0 & ss1 should be from a separate client than the allocating one. */ Assert(0); } - if (should_blend) { + if (should_blend) + { /* Blend time */ ss->sim_dt_ns = LerpI64(ss0->sim_dt_ns, ss1->sim_dt_ns, blend); ss->sim_time_ns = LerpI64(ss0->sim_time_ns, ss1->sim_time_ns, blend); @@ -643,7 +702,8 @@ Snapshot *sim_snapshot_acquire_from_lerp(Client *client, Snapshot *ss0, Snapshot { __profn("Lerp snapshot entities"); u64 num_entities = MinU64(ss0->num_ents_reserved, ss1->num_ents_reserved); - for (u64 i = 0; i < num_entities; ++i) { + for (u64 i = 0; i < num_entities; ++i) + { Entity *e = &ss->ents[i]; Entity *e0 = &ss0->ents[i]; Entity *e1 = &ss1->ents[i]; @@ -655,9 +715,8 @@ Snapshot *sim_snapshot_acquire_from_lerp(Client *client, Snapshot *ss0, Snapshot return ss; } -/* ========================== * - * Snapshot sync - * ========================== */ +//////////////////////////////// +//~ Snapshot sync /* Syncs entity data between snapshots */ void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntityId remote_player, u32 sync_flags) @@ -673,24 +732,32 @@ void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntityId re Entity *remote_root = EntityFromId(remote_ss, RootEntityId); /* Create new ents from remote */ - for (Entity *remote_top = EntityFromId(remote_ss, remote_root->first); remote_top->valid; remote_top = EntityFromId(remote_ss, remote_top->next)) { + for (Entity *remote_top = EntityFromId(remote_ss, remote_root->first); remote_top->valid; remote_top = EntityFromId(remote_ss, remote_top->next)) + { CreateMissingEntitiesFromSnapshots(local_root, remote_top, remote_player); } /* Sync ents with remote, skipping index 0 (nil) & index 1 (root) */ - for (u64 i = 2; i < local_ss->num_ents_reserved; ++i) { + for (u64 i = 2; i < local_ss->num_ents_reserved; ++i) + { Entity *local_ent = &local_ss->ents[i]; - if (local_ent->valid && HasProp(local_ent, Prop_SyncDst)) { + if (local_ent->valid && HasProp(local_ent, Prop_SyncDst)) + { b32 should_sync = EqId(local_ent->owner, remote_player) || IsNilId(remote_player); - if ((sync_flags & SIM_SYNC_FLAG_NOSYNC_PREDICTABLES) && EqId(local_ent->predictor, local_ss->local_player)) { + if ((sync_flags & SIM_SYNC_FLAG_NOSYNC_PREDICTABLES) && EqId(local_ent->predictor, local_ss->local_player)) + { should_sync = 0; } - if (should_sync) { + if (should_sync) + { Entity *remote_ent = EntityFromId(remote_ss, local_ent->id); - if (remote_ent->valid) { + if (remote_ent->valid) + { /* Copy all ent data from remote */ SyncEntity(local_ent, remote_ent); - } else { + } + else + { /* Remote ent is no longer valid / networked, release it */ EnableProp(local_ent, Prop_Release); DisableProp(local_ent, Prop_SyncDst); @@ -715,9 +782,8 @@ void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntityId re #if 1 -/* ========================== * - * Snapshot encode - * ========================== */ +//////////////////////////////// +//~ Snapshot encode void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1) { @@ -736,10 +802,12 @@ void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapsho /* Id bins */ /* TODO: Don't encode these */ BB_WriteDebugMarker(bw, Lit("SNAPSHOT BINS")); - for (u64 i = 0; i < ss1->num_id_bins; ++i) { + for (u64 i = 0; i < ss1->num_id_bins; ++i) + { u32 old_first = 0; u32 old_last = 0; - if (i < ss0->num_id_bins) { + if (i < ss0->num_id_bins) + { EntBin *old_bin = &ss0->id_bins[i]; old_first = old_bin->first; old_last = old_bin->last; @@ -747,13 +815,16 @@ void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapsho EntBin *bin = &ss1->id_bins[i]; b32 first_diff = bin->first != old_first; b32 last_diff = bin->last != old_last; - if (first_diff || last_diff) { + if (first_diff || last_diff) + { BB_WriteBit(bw, 1); BB_WriteUV(bw, i); - if (BB_WriteBit(bw, first_diff)) { + if (BB_WriteBit(bw, first_diff)) + { BB_WriteUV(bw, bin->first); } - if (BB_WriteBit(bw, last_diff)) { + if (BB_WriteBit(bw, last_diff)) + { BB_WriteUV(bw, bin->last); } } @@ -762,19 +833,23 @@ void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapsho /* Ents */ BB_WriteDebugMarker(bw, Lit("SNAPSHOT NUM ENTS")); - if (BB_WriteBit(bw, ss1->num_ents_allocated != ss0->num_ents_allocated)) { + if (BB_WriteBit(bw, ss1->num_ents_allocated != ss0->num_ents_allocated)) + { BB_WriteUV(bw, ss1->num_ents_allocated); } - if (BB_WriteBit(bw, ss1->num_ents_reserved != ss0->num_ents_reserved)) { + if (BB_WriteBit(bw, ss1->num_ents_reserved != ss0->num_ents_reserved)) + { BB_WriteUV(bw, ss1->num_ents_reserved); } BB_WriteDebugMarker(bw, Lit("SNAPSHOT ENTS")); BB_WriteDebugMarker(bw, StringFromStruct(&ss1->num_ents_reserved)); - for (u64 i = 1; i < ss1->num_ents_reserved; ++i) { + for (u64 i = 1; i < ss1->num_ents_reserved; ++i) + { Entity *e0 = NilEntity(); - if (i < ss0->num_ents_reserved) { + if (i < ss0->num_ents_reserved) + { e0 = &ss0->ents[i]; } Entity *e1 = &ss1->ents[i]; @@ -784,9 +859,8 @@ void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapsho BB_WriteDebugMarker(bw, Lit("SNAPSHOT END")); } -/* ========================== * - * Snapshot decode - * ========================== */ +//////////////////////////////// +//~ Snapshot decode void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) { @@ -800,24 +874,30 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) ss->continuity_gen = BB_ReadUV(br); ss->phys_iteration = BB_ReadUV(br); - ss->local_player = (EntityId) { .uid = BB_ReadUid(br) }; + ss->local_player = (EntityId){ .uid = BB_ReadUid(br) }; /* Id bins */ /* TODO: Don't decode these, determine them implicitly from decoded ents */ BB_ReadDebugMarker(br, Lit("SNAPSHOT BINS")); { b32 bin_changed = BB_ReadBit(br); - while (bin_changed) { + while (bin_changed) + { u32 bin_index = BB_ReadUV(br); - if (bin_index < ss->num_id_bins) { + if (bin_index < ss->num_id_bins) + { EntBin *bin = &ss->id_bins[bin_index]; - if (BB_ReadBit(br)) { + if (BB_ReadBit(br)) + { bin->first = BB_ReadUV(br); } - if (BB_ReadBit(br)) { + if (BB_ReadBit(br)) + { bin->last = BB_ReadUV(br); } - } else { + } + else + { /* Invalid bin index */ Assert(0); } @@ -828,22 +908,28 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) /* Ents */ BB_ReadDebugMarker(br, Lit("SNAPSHOT NUM ENTS")); - if (BB_ReadBit(br)) { + if (BB_ReadBit(br)) + { ss->num_ents_allocated = BB_ReadUV(br); } b32 num_ents_reserved_changed = BB_ReadBit(br); - if (num_ents_reserved_changed) { + if (num_ents_reserved_changed) + { u64 old_num_ents_reserved = ss->num_ents_reserved; ss->num_ents_reserved = BB_ReadUV(br); i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved; - if (reserve_diff > 0) { + if (reserve_diff > 0) + { PushStructsNoZero(ss->ents_arena, Entity, reserve_diff); - for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) { + for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) + { Entity *e = &ss->ents[i]; *e = *NilEntity(); e->ss = ss; } - } else if (reserve_diff < 0) { + } + else if (reserve_diff < 0) + { /* TODO: Handle this */ /* NOTE: Should be impossible for snasphot reserve count to decrease at the moment */ Assert(0); @@ -852,7 +938,8 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) BB_ReadDebugMarker(br, Lit("SNAPSHOT ENTS")); BB_ReadDebugMarker(br, StringFromStruct(&ss->num_ents_reserved)); - for (u64 i = 1; i < ss->num_ents_reserved; ++i) { + for (u64 i = 1; i < ss->num_ents_reserved; ++i) + { Entity *e = &ss->ents[i]; e->ss = ss; DecodeEntity(br, e); @@ -864,9 +951,8 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) #else -/* ========================== * - * Snapshot encode - * ========================== */ +//////////////////////////////// +//~ Snapshot encode void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1) { @@ -884,53 +970,67 @@ void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapsho - if (ss1->num_ents_allocated == ss0->num_ents_allocated) { + if (ss1->num_ents_allocated == ss0->num_ents_allocated) + { BB_WriteBit(bw, 0); - } else { + } + else + { BB_WriteBit(bw, 1); BB_WriteUV(bw, ss1->num_ents_allocated); } - if (ss1->num_ents_reserved == ss0->num_ents_reserved) { + if (ss1->num_ents_reserved == ss0->num_ents_reserved) + { BB_WriteBit(bw, 0); - } else { + } + else + { BB_WriteBit(bw, 1); BB_WriteUV(bw, ss1->num_ents_reserved); } BB_AlignWriter(bw); - for (u64 i = 0; i < ss1->num_ents_reserved; ++i) { + for (u64 i = 0; i < ss1->num_ents_reserved; ++i) + { Entity *e0 = NilEntity(); - if (i < ss0->num_ents_reserved) { + if (i < ss0->num_ents_reserved) + { e0 = &ss0->ents[i]; } - if (e0->valid != e1->valid) { + if (e0->valid != e1->valid) + { BB_WriteBit(1); BB_WriteBit(e1->valid); - if (e1->valid) { + if (e1->valid) + { BB_WriteUid(bw, e1->id.uid); } - } else { + } + else + { BB_WriteBit(0); } - if (e1->valid) { + if (e1->valid) + { Entity *e1 = &ss1->ents[i]; EncodeEntity(bw, e0, e1); } } } -/* ========================== * - * Snapshot decode - * ========================== */ +//////////////////////////////// +//~ Snapshot decode -struct sim_ent_decode_node { +struct sim_ent_decode_node +{ String tmp_encoded; }; -struct sim_ent_decode_queue { +struct sim_ent_decode_queue +{ struct sim_ent_decode_node *first; struct sim_ent_decode_node *last; }; @@ -946,20 +1046,24 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) ss->continuity_gen = BB_ReadUV(br); ss->phys_iteration = BB_ReadUV(br); - ss->local_player = (EntityId) { .uid = BB_ReadUid(br) }; + ss->local_player = (EntityId){ .uid = BB_ReadUid(br) }; #if 1 - if (BB_ReadBit(br)) { + if (BB_ReadBit(br)) + { ss->num_ents_allocated = BB_ReadUV(br); } - if (BB_ReadBit(br)) { + if (BB_ReadBit(br)) + { u64 old_num_ents_reserved = ss->num_ents_reserved; ss->num_ents_reserved = BB_ReadUV(br); i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved; - if (reserve_diff > 0) { + if (reserve_diff > 0) + { PushStructsNoZero(ss->ents_arena, Entity, reserve_diff); - for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) { + for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) + { Entity *e = &ss->ents[i]; *e = *NilEntity(); e->ss = ss; @@ -970,7 +1074,8 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) /* Build decode queue */ struct sim_ent_decode_queue queue; b32 should_read_ent = BB_ReadBit(br); - while (should_read_ent) { + while (should_read_ent) + { /* TODO: Delta decode index based on last read index */ u32 index = BB_ReadUV(br); b32 allocation_changed = BB_ReadBit(br); @@ -978,33 +1083,43 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) u32 alloc_parent_index = ZI; EntityId alloc_ent_id = ZI; - if (allocation_changed) { + if (allocation_changed) + { released = BB_ReadBit(br); - if (released) { + if (released) + { Entity *e = sim_ent_from_index(ss, e); Assert(e->valid); /* An entity that we don't have allocated should never have been marked for release */ - if (e->valid) { + if (e->valid) + { EnableProp(e, Prop_Release); } - } else { + } + else + { alloc_parent_index = BB_ReadUV(); alloc_ent_id = sim_ent_id_from_uid(BB_ReadUid(br)); } } - if (!released) { + if (!released) + { u64 num_ent_bits = BB_ReadUV(br); BB_Reader ent_br = br_from_seek_bits(br, num_ent_bits); - if (BB_NumBitsRemaining(&ent_br) > 0) { + if (BB_NumBitsRemaining(&ent_br) > 0) + { struct sim_ent_decode_node *n = PushStruct(scratch.arena, struct sim_ent_decode_node); n->is_new = allocation_changed && !released; n->index = index; n->alloc_parent_ndex = alloc_parent_index; n->alloc_ent_id = alloc_ent_id; n->br = ent_br; - if (queue.last) { + if (queue.last) + { queue.last->next = n; - } else { + } + else + { queue.first = n; } queue.last = n; @@ -1015,18 +1130,23 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) } /* Acquire new ents from decode queue */ - for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) { - if (n->is_new) { + for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) + { + if (n->is_new) + { u32 index = n->index; Entity *parent = sim_ent_from_index(ss, n->alloc_parent_index); Assert(!sim_ent_from_index(ss, index)->valid && !EntityFromId(ss, alloc_ent_id)->valid); /* An entity that we have allocated already should never be marked for allocation */ Assert(parent->valid); /* Parent for new entity allocation should always be valid */ - if (parent->valid && index < ss->num_ents_reserved) { + if (parent->valid && index < ss->num_ents_reserved) + { Entity *ent = &ss->ents[index]; ent->valid = 1; SetEntityId(ent, n->alloc_ent_id); Link(parent, ent); - } else { + } + else + { /* Received an invalid entity allocation */ Assert(0); } @@ -1034,29 +1154,37 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) } /* Decode ent data from decode queue */ - for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) { + for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) + { BB_Reader ent_br = n->br; u32 index = n->index; Entity *e = sim_ent_from_index(ss, index); - if (e->valid) { + if (e->valid) + { DecodeEntity(&ent_br, e); - } else { + } + else + { /* Received delta for unallocated ent */ Assert(0); } } #else /* Ents */ - if (BB_ReadBit(br)) { + if (BB_ReadBit(br)) + { ss->num_ents_allocated = BB_ReadUV(br); } - if (BB_ReadBit(br)) { + if (BB_ReadBit(br)) + { u64 old_num_ents_reserved = ss->num_ents_reserved; ss->num_ents_reserved = BB_ReadUV(br); i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved; - if (reserve_diff > 0) { + if (reserve_diff > 0) + { PushStructsNoZero(ss->ents_arena, Entity, reserve_diff); - for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) { + for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) + { Entity *e = &ss->ents[i]; *e = *NilEntity(); e->ss = ss; @@ -1064,34 +1192,45 @@ void sim_snapshot_decode(BB_Reader *br, Snapshot *ss) } } - for (u64 i = 0; i < ss->num_ents_reserved; ++i) { + for (u64 i = 0; i < ss->num_ents_reserved; ++i) + { b32 allocation_changed = BB_ReadBit(br); - if (allocation_changed) { - if (BB_ReadBit(br)) { + if (allocation_changed) + { + if (BB_ReadBit(br)) + { struct sim_ent_decode_node *n = PushStruct(scratch.arena, struct sim_ent_decode_node) - } else { + } + else + { EnableProp(e, Prop_Release); } } } - for (u64 i = 0; i < ss->num_ents_reserved; ++i) { + for (u64 i = 0; i < ss->num_ents_reserved; ++i) + { Entity *e = &ss->ents[i]; e->ss = ss; b32 valid_changed = BB_ReadBit(br); b32 allocated = 1; - if (valid_changed) { + if (valid_changed) + { allocated = BB_ReadBit(br); } - if (!allocated) { + if (!allocated) + { /* Why is an already released ent being marked as released? */ Assert(e->valid); - if (e->valid) { + if (e->valid) + { EnableProp(e, Prop_Release); } - } else { + } + else + { DecodeEntity(br, e); } } diff --git a/src/pp/pp_sim.h b/src/pp/pp_sim.h index 575afae2..0c1091f9 100644 --- a/src/pp/pp_sim.h +++ b/src/pp/pp_sim.h @@ -1,41 +1,31 @@ -#define SIM_CLIENT_NIL_HANDLE ((ClientHandle) { .gen = 0, .idx = 0 }) +//////////////////////////////// +//~ Id types -/* Absolute layers */ -#define SIM_LAYER_FLOOR_DECALS (-300) -#define SIM_LAYER_BULLETS (-200) -#define SIM_LAYER_TRACERS (-100) -#define SIM_LAYER_SHOULDERS (0) -#define SIM_LAYER_WALLS (100) - -/* Relative layers */ -#define SIM_LAYER_RELATIVE_DEFAULT (0) -#define SIM_LAYER_RELATIVE_WEAPON (1) - -Struct(EntityId) { +Struct(EntityId) +{ Uid uid; }; -Struct(ClientHandle) { +Struct(ClientHandle) +{ u32 idx; u32 gen; }; -/* ========================== * - * Startup - * ========================== */ +#define SIM_CLIENT_NIL_HANDLE ((ClientHandle) { .gen = 0, .idx = 0 }) -void StartupSim(void); -/* ========================== * - * Client store - * ========================== */ +//////////////////////////////// +//~ Client store types -Struct(ClientLookupBin) { +Struct(ClientLookupBin) +{ struct ClientHandle first; struct ClientHandle last; }; -Struct(ClientStore) { +Struct(ClientStore) +{ b32 valid; Arena *arena; @@ -57,19 +47,17 @@ Inline ClientStore *sim_client_store_nil(void) return *_g_sim_client_store_nil; } -ClientStore *sim_client_store_acquire(void); -void sim_client_store_release(ClientStore *store); +//////////////////////////////// +//~ Client types -/* ========================== * - * Client - * ========================== */ - -Struct(SnapshotLookupBin) { +Struct(SnapshotLookupBin) +{ struct Snapshot *first; struct Snapshot *last; }; -Struct(Client) { +Struct(Client) +{ b32 valid; ClientHandle handle; ClientStore *store; @@ -122,22 +110,25 @@ Inline b32 sim_client_handle_eq(ClientHandle a, ClientHandle b) return a.gen == b.gen && a.idx == b.idx; } -Client *sim_client_acquire(ClientStore *store); -void sim_client_release(Client *client); +//////////////////////////////// +//~ Layer types -Client *sim_client_from_channel_id(ClientStore *store, N_ChannelId channel_id); -void sim_client_set_channel_id(Client *client, N_ChannelId channel_id); -Client *sim_client_from_handle(ClientStore *store, ClientHandle handle); +/* Absolute layers */ +#define SIM_LAYER_FLOOR_DECALS (-300) +#define SIM_LAYER_BULLETS (-200) +#define SIM_LAYER_TRACERS (-100) +#define SIM_LAYER_SHOULDERS (0) +#define SIM_LAYER_WALLS (100) -/* ========================== * - * Snapshot - * ========================== */ +/* Relative layers */ +#define SIM_LAYER_RELATIVE_DEFAULT (0) +#define SIM_LAYER_RELATIVE_WEAPON (1) -typedef i32 SyncFlag; enum { - SIM_SYNC_FLAG_NOSYNC_PREDICTABLES = 1 << 0 -}; +//////////////////////////////// +//~ Control types -typedef i32 ControlFlag; enum { +typedef i32 ControlFlag; enum +{ SIM_CONTROL_FLAG_FIRE = 1 << 0, SIM_CONTROL_FLAG_FIRE_ALT = 1 << 1, @@ -155,22 +146,27 @@ typedef i32 ControlFlag; enum { SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 12, }; -Struct(ControlData) { +Struct(ControlData) +{ Vec2 move; /* Movement direction vector (speed of 0 -> 1) */ Vec2 focus; /* Focus direction vector (where does the controller want to look) */ Vec2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */ ControlFlag flags; }; -typedef i32 CmdKind; enum { +typedef i32 CmdKind; enum +{ SIM_CMD_KIND_INVALID, SIM_CMD_KIND_CONTROL, SIM_CMD_KIND_CHAT }; +//////////////////////////////// +//~ Tile types -typedef i32 TileKind; enum { +typedef i32 TileKind; enum +{ SIM_TILE_KIND_NONE, SIM_TILE_KIND_WALL, @@ -178,7 +174,16 @@ typedef i32 TileKind; enum { }; StaticAssert(NUM_SIM_TILE_KINDS < 256); /* Tile kind must fit in 8 bits */ -Struct(Snapshot) { +//////////////////////////////// +//~ Snapshot types + +typedef i32 SyncFlag; enum +{ + SIM_SYNC_FLAG_NOSYNC_PREDICTABLES = 1 << 0 +}; + +Struct(Snapshot) +{ b32 valid; u64 tick; Client *client; @@ -221,17 +226,77 @@ Inline Snapshot *sim_snapshot_nil(void) return *_g_sim_snapshot_nil; } -/* Acquire */ +//////////////////////////////// +//~ Shared state + +#define CLIENT_LOOKUP_BINS 127 +#define TICK_LOOKUP_BINS 127 +#define ID_LOOKUP_BINS 4096 + + +Struct(SharedSimCtx) +{ + Arena *nil_arena; + ClientStore *nil_client_store; + Client *nil_client; + Snapshot *nil_snapshot; + struct Entity *nil_ent; +}; + +extern SharedSimCtx shared_sim_ctx; + +/* Accessed via `sim_client_store_nil()` */ +extern Readonly ClientStore **_g_sim_client_store_nil; + +/* Accessed via `sim_client_nil()` */ +extern Readonly Client **_g_sim_client_nil; + +/* Accessed via `sim_snapshot_nil()` */ +extern Readonly Snapshot **_g_sim_snapshot_nil; +extern Readonly struct Entity **_g_sim_ent_nil; + +//////////////////////////////// +//~ Startup + +void StartupSim(void); + +//////////////////////////////// +//~ Client store acquire operations + +ClientStore *sim_client_store_acquire(void); +void sim_client_store_release(ClientStore *store); + +//////////////////////////////// +//~ Client acquire operations + +Client *sim_client_acquire(ClientStore *store); +void sim_client_release(Client *client); + +//////////////////////////////// +//~ Client lookup operations + +u64 client_channel_hash_hash_from_channel_id(N_ChannelId channel_id); +void sim_client_set_channel_id(Client *client, N_ChannelId channel_id); +Client *sim_client_from_channel_id(ClientStore *store, N_ChannelId channel_id); +Client *sim_client_from_handle(ClientStore *store, ClientHandle handle); + +//////////////////////////////// +//~ Snapshot acquire operations + Snapshot *sim_snapshot_acquire(Client *client, Snapshot *src, u64 tick); -void sim_snapshot_release(Snapshot *sim_snapshot); +void sim_snapshot_release(Snapshot *ss); void sim_snapshot_release_ticks_in_range(Client *client, u64 start, u64 end); -/* Lookup */ +//////////////////////////////// +//~ Snapshot lookup operations + Snapshot *sim_snapshot_from_tick(Client *client, u64 tick); Snapshot *sim_snapshot_from_closest_tick_lte(Client *client, u64 tick); Snapshot *sim_snapshot_from_closest_tick_gte(Client *client, u64 tick); -/* Tile */ +//////////////////////////////// +//~ Tile operations + Vec2I32 sim_world_tile_index_from_pos(Vec2 pos); Vec2 sim_pos_from_world_tile_index(Vec2I32 world_tile_index); Vec2I32 sim_local_tile_index_from_world_tile_index(Vec2I32 world_tile_index); @@ -239,12 +304,22 @@ Vec2I32 sim_world_tile_index_from_local_tile_index(Vec2I32 tile_chunk_index, Vec Vec2I32 sim_tile_chunk_index_from_world_tile_index(Vec2I32 world_tile_index); void sim_snapshot_set_tile(Snapshot *ss, Vec2I32 world_tile_index, TileKind tile_kind); -/* Lerp */ +//////////////////////////////// +//~ Snapshot lerp operations + Snapshot *sim_snapshot_acquire_from_lerp(Client *client, Snapshot *ss0, Snapshot *ss1, f64 blend); -/* Sync */ +//////////////////////////////// +//~ Snapshot sync operations + void sim_snapshot_sync_ents(Snapshot *local_ss, Snapshot *remote_ss, EntityId remote_player, u32 sync_flags); -/* Encode / decode */ +//////////////////////////////// +//~ Snapshot encode operations + void sim_snapshot_encode(BB_Writer *bw, Client *receiver, Snapshot *ss0, Snapshot *ss1); + +//////////////////////////////// +//~ Snapshot decode operations + void sim_snapshot_decode(BB_Reader *br, Snapshot *ss); diff --git a/src/pp/pp_step.c b/src/pp/pp_step.c index c197aa1d..e4896018 100644 --- a/src/pp/pp_step.c +++ b/src/pp/pp_step.c @@ -18,9 +18,11 @@ void ResetSimAccel(Snapshot *ss, SimAccel *accel) space_reset(accel->space); /* Reset ent space handles */ - for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { + for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) + { Entity *ent = &ss->ents[sim_ent_index]; - if (ent->valid) { + if (ent->valid) + { ZeroStruct(&ent->space_handle); } } @@ -167,7 +169,8 @@ Entity *SpawnTestEmployee(Entity *parent) } /* Player weapon */ - if (employee->valid) { + if (employee->valid) + { LAX SpawnTestSmg; LAX SpawnTestLauncher; LAX SpawnTestChucker; @@ -185,7 +188,8 @@ Entity *SpawnTestEmployee(Entity *parent) Entity *SpawnTestCamera(Entity *parent, Entity *follow) { Entity *camera_ent = NilEntity(); - if (follow->valid) { + if (follow->valid) + { camera_ent = AcquireSyncSrc(parent); SetXform(camera_ent, XformIdentity); @@ -398,9 +402,11 @@ void SpawnTestTile(Snapshot *world, Vec2 world_pos) void ClearLevelTest(SimStepCtx *ctx) { Snapshot *world = ctx->world; - for (u64 j = 0; j < world->num_ents_reserved; ++j) { + for (u64 j = 0; j < world->num_ents_reserved; ++j) + { Entity *ent = &world->ents[j]; - if (ent->valid) { + if (ent->valid) + { EnableProp(ent, Prop_Release); } } @@ -447,14 +453,18 @@ void GenerateTestWalls(Snapshot *world) u64 sorted_tile_chunks_count = 0; { x_sorted_tile_chunks = PushDry(scratch.arena, Entity *); - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ent->valid) continue; - if (HasProp(ent, Prop_TileChunk)) { + if (HasProp(ent, Prop_TileChunk)) + { /* Append chunk to array */ *PushStructNoZero(scratch.arena, Entity *) = ent; ++sorted_tile_chunks_count; - } else if (HasProp(ent, Prop_Wall)) { + } + else if (HasProp(ent, Prop_Wall)) + { /* Release existing wall */ EnableProp(ent, Prop_Release); } @@ -468,7 +478,8 @@ void GenerateTestWalls(Snapshot *world) Mergesort(y_sorted_tile_chunks, sorted_tile_chunks_count, sizeof(*y_sorted_tile_chunks), SortTileYCmp, 0); } - struct wall_node { + struct wall_node + { Vec2I32 start; Vec2I32 end; i32 wall_dir; /* = 0 up, 1 = right, 2 = down, 3 = left */ @@ -483,7 +494,8 @@ void GenerateTestWalls(Snapshot *world) struct wall_node *first_wall = 0; /* Generate horizontal wall nodes */ - for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) { + for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) + { Entity *chunk = x_sorted_tile_chunks[sorted_index]; Vec2I32 chunk_index = chunk->tile_chunk_index; Entity *top_chunk = TileChunkFromChunkIndex(world, VEC2I32(chunk_index.x, chunk_index.y - 1)); @@ -491,55 +503,72 @@ void GenerateTestWalls(Snapshot *world) /* If there's no chunk below this one, then do an extra iteration (since walls are created at the top of each tile) */ i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + !bottom_chunk->valid; i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + 1; - for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) { + for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) + { i32 wall_start = -1; i32 wall_end = -1; i32 wall_dir = -1; - for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) { + for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) + { i32 desired_wall_dir = -1; TileKind tile = SIM_TILE_KIND_NONE; - if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) { + if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) + { tile = TileKindFromChunk(chunk, VEC2I32(tile_x, tile_y)); } - if (tile_x < SIM_TILES_PER_CHUNK_SQRT) { + if (tile_x < SIM_TILES_PER_CHUNK_SQRT) + { TileKind top_tile = SIM_TILE_KIND_NONE; - if (tile_y == 0) { - if (top_chunk->valid) { + if (tile_y == 0) + { + if (top_chunk->valid) + { Vec2I32 top_tile_local_index = VEC2I32(tile_x, SIM_TILES_PER_CHUNK_SQRT - 1); top_tile = TileKindFromChunk(top_chunk, top_tile_local_index); } - } else { + } + else + { top_tile = TileKindFromChunk(chunk, VEC2I32(tile_x, tile_y - 1)); } - if (tile == SIM_TILE_KIND_WALL) { + if (tile == SIM_TILE_KIND_WALL) + { /* Process wall tile */ - if (top_tile != SIM_TILE_KIND_WALL) { + if (top_tile != SIM_TILE_KIND_WALL) + { desired_wall_dir = 0; } - } else { + } + else + { /* Process non-wall tile */ - if (top_tile == SIM_TILE_KIND_WALL) { + if (top_tile == SIM_TILE_KIND_WALL) + { desired_wall_dir = 2; } } } /* Stop wall */ - if (wall_dir >= 0 && desired_wall_dir != wall_dir) { + if (wall_dir >= 0 && desired_wall_dir != wall_dir) + { Vec2I32 start = sim_world_tile_index_from_local_tile_index(chunk_index, VEC2I32(wall_start, tile_y)); Vec2I32 end = sim_world_tile_index_from_local_tile_index(chunk_index, VEC2I32(wall_end, tile_y)); struct wall_node *node = 0; - if (wall_start == 0) { + if (wall_start == 0) + { u64 start_hash = RandU64FromSeed(*(u64 *)&start); start_hash = RandU64FromSeeds(start_hash, wall_dir); DictEntry *entry = DictEntryFromHash(horizontal_ends_dict, start_hash); - if (entry) { + if (entry) + { /* Existing wall exists accross chunk boundary */ node = (struct wall_node *)entry->value; RemoveDictEntry(horizontal_ends_dict, entry); } } - if (!node) { + if (!node) + { node = PushStruct(scratch.arena, struct wall_node); node->start = start; node->next = first_wall; @@ -547,7 +576,8 @@ void GenerateTestWalls(Snapshot *world) first_wall = node; } node->end = end; - if (wall_end == SIM_TILES_PER_CHUNK_SQRT) { + if (wall_end == SIM_TILES_PER_CHUNK_SQRT) + { u64 end_hash = RandU64FromSeed(*(u64 *)&end); end_hash = RandU64FromSeeds(end_hash, wall_dir); SetDictValue(scratch.arena, horizontal_ends_dict, end_hash, (u64)node); @@ -558,8 +588,10 @@ void GenerateTestWalls(Snapshot *world) } /* Start / extend wall */ - if (desired_wall_dir >= 0) { - if (wall_dir != desired_wall_dir) { + if (desired_wall_dir >= 0) + { + if (wall_dir != desired_wall_dir) + { /* Start wall */ wall_start = tile_x; } @@ -572,7 +604,8 @@ void GenerateTestWalls(Snapshot *world) } /* Generate vertical wall nodes */ - for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) { + for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) + { Entity *chunk = y_sorted_tile_chunks[sorted_index]; Vec2I32 chunk_index = chunk->tile_chunk_index; Entity *left_chunk = TileChunkFromChunkIndex(world, VEC2I32(chunk_index.x - 1, chunk_index.y)); @@ -580,56 +613,73 @@ void GenerateTestWalls(Snapshot *world) /* If there's no chunk to the right of this one, then do an extra iteration (since walls are created on the left of each tile) */ i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + 1; i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + !right_chunk->valid; - for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) { + for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) + { i32 wall_start = -1; i32 wall_end = -1; i32 wall_dir = -1; - for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) { + for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) + { i32 desired_wall_dir = -1; TileKind tile = SIM_TILE_KIND_NONE; - if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) { + if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) + { tile = TileKindFromChunk(chunk, VEC2I32(tile_x, tile_y)); } - if (tile_y < SIM_TILES_PER_CHUNK_SQRT) { + if (tile_y < SIM_TILES_PER_CHUNK_SQRT) + { TileKind left_tile = SIM_TILE_KIND_NONE; - if (tile_x == 0) { - if (left_chunk->valid) { + if (tile_x == 0) + { + if (left_chunk->valid) + { Vec2I32 left_tile_local_index = VEC2I32(SIM_TILES_PER_CHUNK_SQRT - 1, tile_y); left_tile = TileKindFromChunk(left_chunk, left_tile_local_index); } - } else { + } + else + { left_tile = TileKindFromChunk(chunk, VEC2I32(tile_x - 1, tile_y)); } - if (tile == SIM_TILE_KIND_WALL) { + if (tile == SIM_TILE_KIND_WALL) + { /* Process wall tile */ - if (left_tile != SIM_TILE_KIND_WALL) { + if (left_tile != SIM_TILE_KIND_WALL) + { desired_wall_dir = 3; } - } else { + } + else + { /* Process non-wall tile */ - if (left_tile == SIM_TILE_KIND_WALL) { + if (left_tile == SIM_TILE_KIND_WALL) + { desired_wall_dir = 1; } } } /* Stop wall */ - if (wall_dir >= 0 && desired_wall_dir != wall_dir) { + if (wall_dir >= 0 && desired_wall_dir != wall_dir) + { Vec2I32 start = sim_world_tile_index_from_local_tile_index(chunk_index, VEC2I32(tile_x, wall_start)); Vec2I32 end = sim_world_tile_index_from_local_tile_index(chunk_index, VEC2I32(tile_x, wall_end)); struct wall_node *node = 0; - if (wall_start == 0) { + if (wall_start == 0) + { u64 start_hash = RandU64FromSeed(*(u64 *)&start); start_hash = RandU64FromSeeds(start_hash, wall_dir); DictEntry *entry = DictEntryFromHash(vertical_ends_dict, start_hash); - if (entry) { + if (entry) + { /* Existing wall exists accross chunk boundary */ node = (struct wall_node *)entry->value; RemoveDictEntry(vertical_ends_dict, entry); } } - if (!node) { + if (!node) + { node = PushStruct(scratch.arena, struct wall_node); node->start = start; node->next = first_wall; @@ -637,7 +687,8 @@ void GenerateTestWalls(Snapshot *world) first_wall = node; } node->end = end; - if (wall_end == SIM_TILES_PER_CHUNK_SQRT) { + if (wall_end == SIM_TILES_PER_CHUNK_SQRT) + { u64 end_hash = RandU64FromSeed(*(u64 *)&end); end_hash = RandU64FromSeeds(end_hash, wall_dir); SetDictValue(scratch.arena, vertical_ends_dict, end_hash, (u64)node); @@ -648,8 +699,10 @@ void GenerateTestWalls(Snapshot *world) } /* Start / extend wall */ - if (desired_wall_dir >= 0) { - if (wall_dir != desired_wall_dir) { + if (desired_wall_dir >= 0) + { + if (wall_dir != desired_wall_dir) + { /* Start wall */ wall_start = tile_y; } @@ -662,7 +715,8 @@ void GenerateTestWalls(Snapshot *world) } /* Create wall entities */ - for (struct wall_node *node = first_wall; node; node = node->next) { + for (struct wall_node *node = first_wall; node; node = node->next) + { Entity *wall_ent = AcquireSyncSrc(root); EnableProp(wall_ent, Prop_Wall); @@ -697,9 +751,11 @@ CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx) Entity *root = EntityFromId(world, RootEntityId); b32 skip_solve = 0; - if (ShouldSimulate(e0) && ShouldSimulate(e1)) { + if (ShouldSimulate(e0) && ShouldSimulate(e1)) + { /* Bullet impact */ - if (HasProp(e0, Prop_Bullet)) { + if (HasProp(e0, Prop_Bullet)) + { Vec2 normal = data->normal; /* Impact normal */ Vec2 vrel = data->vrel; /* Impact velocity */ @@ -708,12 +764,14 @@ CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx) Entity *src = EntityFromId(world, bullet->bullet_src); /* Process collision if bullet already spent or * target share same top level parent */ - if (!bullet->bullet_has_hit && !EqId(src->top, target->top) && HasProp(target, Prop_Solid)) { + if (!bullet->bullet_has_hit && !EqId(src->top, target->top) && HasProp(target, Prop_Solid)) + { Vec2 point = data->point; /* Update tracer */ Entity *tracer = EntityFromId(world, bullet->bullet_tracer); - if (ShouldSimulate(tracer)) { + if (ShouldSimulate(tracer)) + { Xform xf = XformFromEntity(tracer); xf.og = point; SetXform(tracer, xf); @@ -750,7 +808,8 @@ CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx) } /* Create explosion */ - if (bullet->bullet_explosion_strength > 0) { + if (bullet->bullet_explosion_strength > 0) + { SpawnTestExplosion(root, point, bullet->bullet_explosion_strength, bullet->bullet_explosion_radius); } @@ -761,7 +820,8 @@ CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx) } /* Explosion blast collision */ - if (HasProp(e0, Prop_Explosion)) { + if (HasProp(e0, Prop_Explosion)) + { Entity *exp = e0; Entity *victim = e1; @@ -776,12 +836,14 @@ CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx) Vec2 point = closest_points.p1; f32 distance = Vec2Len(dir); #if 0 - if (closest_points.colliding) { + if (closest_points.colliding) + { dir = NegVec2(dir); //distance = 0; } #else - if (DotVec2(data->normal, dir) < 0) { + if (DotVec2(data->normal, dir) < 0) + { dir = NegVec2(dir); point = xf.og; distance = 0; @@ -791,7 +853,8 @@ CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx) /* TODO: Blast obstruction */ f32 radius = exp->explosion_radius; f32 strength_center = exp->explosion_strength; - if (distance < radius) { + if (distance < radius) + { const f32 falloff_curve = 3; /* Cubic falloff */ f32 strength_factor = PowF32(1 - distance/radius, falloff_curve); Vec2 impulse = Vec2WithLen(dir, strength_center * strength_factor); @@ -800,8 +863,10 @@ CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx) } /* Chucker zone */ - if (HasProp(e0, Prop_ChuckerZone)) { - if (!EqId(e0->top, e1->top) && HasProp(e1, Prop_Solid)) { + if (HasProp(e0, Prop_ChuckerZone)) + { + if (!EqId(e0->top, e1->top) && HasProp(e1, Prop_Solid)) + { e0->chucker_zone_ent = e1->id; e0->chucker_zone_ent_tick = world->tick; } @@ -845,13 +910,16 @@ void StepSim(SimStepCtx *ctx) { /* FIXME: Ensure only cmds are synced to master player */ - for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) { + for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) + { Client *client = &client_store->clients[client_index]; - if (client->valid && client != master_client && client != world_client && client != publish_client) { + if (client->valid && client != master_client && client != world_client && client != publish_client) + { Entity *player = EntityFromId(world, client->player_id); /* Create player if necessary */ - if (is_master && !player->valid) { + if (is_master && !player->valid) + { /* FIXME: Player never released upon disconnect */ player = AcquireSyncSrc(root); player->player_client_handle = client->handle; @@ -859,7 +927,8 @@ void StepSim(SimStepCtx *ctx) player->predictor = player->id; Activate(player, world->tick); client->player_id = player->id; - if (client == user_input_client) { + if (client == user_input_client) + { user_input_client->player_id = player->id; world_client->player_id = player->id; world->local_player = player->id; @@ -870,16 +939,19 @@ void StepSim(SimStepCtx *ctx) } /* Update rtt */ - if (is_master && player->valid) { + if (is_master && player->valid) + { player->player_last_rtt_ns = client->last_rtt_ns; player->player_average_rtt_seconds -= player->player_average_rtt_seconds / 200; player->player_average_rtt_seconds += SecondsFromNs(client->last_rtt_ns) / 200; } /* Sync ents from client */ - if (player->valid) { + if (player->valid) + { Snapshot *src_ss = sim_snapshot_from_tick(client, world->tick); - if (src_ss->valid) { + if (src_ss->valid) + { sim_snapshot_sync_ents(world, src_ss, player->id, 0); } } @@ -887,28 +959,36 @@ void StepSim(SimStepCtx *ctx) } /* Mark all incoming ents as sync dsts */ - for (u64 i = 0; i < world->num_ents_reserved; ++i) { + for (u64 i = 0; i < world->num_ents_reserved; ++i) + { Entity *ent = &world->ents[i]; - if (ent->valid && HasProp(ent, Prop_SyncSrc) && !EqId(ent->owner, world_client->player_id)) { + if (ent->valid && HasProp(ent, Prop_SyncSrc) && !EqId(ent->owner, world_client->player_id)) + { DisableProp(ent, Prop_SyncSrc); EnableProp(ent, Prop_SyncDst); } } /* Mark incoming cmds with correct client */ - for (u64 i = 0; i < world->num_ents_reserved; ++i) { + for (u64 i = 0; i < world->num_ents_reserved; ++i) + { Entity *ent = &world->ents[i]; - if (ent->valid && HasProp(ent, Prop_Cmd) && HasProp(ent, Prop_SyncDst)) { + if (ent->valid && HasProp(ent, Prop_Cmd) && HasProp(ent, Prop_SyncDst)) + { ent->cmd_player = ent->owner; } } /* Mark any locally created CMDs as sync sources */ - if (!is_master) { - for (u64 i = 0; i < world->num_ents_reserved; ++i) { + if (!is_master) + { + for (u64 i = 0; i < world->num_ents_reserved; ++i) + { Entity *ent = &world->ents[i]; - if (IsValidAndActive(ent) && HasProp(ent, Prop_Cmd)) { - if (!IsNilId(ent->cmd_player) && EqId(ent->cmd_player, world->local_player)) { + if (IsValidAndActive(ent) && HasProp(ent, Prop_Cmd)) + { + if (!IsNilId(ent->cmd_player) && EqId(ent->cmd_player, world->local_player)) + { EnableProp(ent, Prop_SyncSrc); } } @@ -925,14 +1005,17 @@ void StepSim(SimStepCtx *ctx) //- Activate entities - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ent->valid) continue; if (HasProp(ent, Prop_SyncDst) && !IsOwner(ent) && !ShouldPredict(ent)) continue; - if (!HasProp(ent, Prop_Active)) { + if (!HasProp(ent, Prop_Active)) + { u64 atick = ent->activation_tick; - if (atick != 0 || world->tick >= atick) { + if (atick != 0 || world->tick >= atick) + { Activate(ent, world->tick); } } @@ -941,21 +1024,26 @@ void StepSim(SimStepCtx *ctx) //- Process player cmds - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *cmd_ent = &world->ents[ent_index]; if (!is_master && !ShouldSimulate(cmd_ent)) continue; - if (HasProp(cmd_ent, Prop_Cmd)) { + if (HasProp(cmd_ent, Prop_Cmd)) + { Entity *player = EntityFromId(world, cmd_ent->cmd_player); - if (ShouldSimulate(player)) { + if (ShouldSimulate(player)) + { b32 persist_cmd = 0; - if (!is_master && !EqId(player->id, world->local_player)) { + if (!is_master && !EqId(player->id, world->local_player)) + { /* We are not the master and the command is not our own, skip processing */ continue; } CmdKind kind = cmd_ent->cmd_kind; - switch (kind) { + switch (kind) + { case SIM_CMD_KIND_CONTROL: { /* Player's will send control cmds a lot, so keep it around to prevent re-creating it each time */ @@ -974,82 +1062,105 @@ void StepSim(SimStepCtx *ctx) player->player_dbg_drag_stop = 0; /* Cap movement vector magnitude */ - if (Vec2LenSq(control->move) > 1) { + if (Vec2LenSq(control->move) > 1) + { control->move = NormVec2(control->move); } /* Debug cmds */ - if (ctx->is_master) { - if (flags & SIM_CONTROL_FLAG_DRAG) { - if (!(old_control.flags & SIM_CONTROL_FLAG_DRAG)) { + if (ctx->is_master) + { + if (flags & SIM_CONTROL_FLAG_DRAG) + { + if (!(old_control.flags & SIM_CONTROL_FLAG_DRAG)) + { player->player_dbg_drag_start = 1; } - } else { - if (old_control.flags & SIM_CONTROL_FLAG_DRAG) { + } + else + { + if (old_control.flags & SIM_CONTROL_FLAG_DRAG) + { player->player_dbg_drag_stop = 1; } } - if (flags & SIM_CONTROL_FLAG_DELETE) { + if (flags & SIM_CONTROL_FLAG_DELETE) + { Entity *ent = EntityFromId(world, player->player_hovered_ent); - if (ent->valid) { + if (ent->valid) + { EnableProp(ent, Prop_Release); } } - if (flags & SIM_CONTROL_FLAG_CLEAR_ALL) { + if (flags & SIM_CONTROL_FLAG_CLEAR_ALL) + { ClearLevelTest(ctx); } - if (flags & SIM_CONTROL_FLAG_SPAWN1_TEST) { + if (flags & SIM_CONTROL_FLAG_SPAWN1_TEST) + { P_LogDebugF("Spawn test 1"); u32 count = 1; f32 spread = 0; - for (u32 j = 0; j < count; ++j) { + for (u32 j = 0; j < count; ++j) + { Vec2 pos = player->player_cursor_pos; pos.y += (((f32)j / (f32)count) - 0.5) * spread; SpawnTestEntities1(root, pos); } } - if (flags & SIM_CONTROL_FLAG_SPAWN2_TEST) { + if (flags & SIM_CONTROL_FLAG_SPAWN2_TEST) + { P_LogDebugF("Spawn test 2"); u32 count = 1; f32 spread = 0; - for (u32 j = 0; j < count; ++j) { + for (u32 j = 0; j < count; ++j) + { Vec2 pos = player->player_cursor_pos; pos.y += (((f32)j / (f32)count) - 0.5) * spread; SpawnTestEntities2(root, pos); } } - if (flags & SIM_CONTROL_FLAG_SPAWN3_TEST) { + if (flags & SIM_CONTROL_FLAG_SPAWN3_TEST) + { P_LogDebugF("Spawn test 3"); u32 count = 1; f32 spread = 0; - for (u32 j = 0; j < count; ++j) { + for (u32 j = 0; j < count; ++j) + { Vec2 pos = player->player_cursor_pos; pos.y += (((f32)j / (f32)count) - 0.5) * spread; SpawnTestEntities3(root, pos); } } - if (flags & SIM_CONTROL_FLAG_SPAWN4_TEST) { + if (flags & SIM_CONTROL_FLAG_SPAWN4_TEST) + { P_LogDebugF("Spawn test 4"); u32 count = 1; f32 spread = 0; - for (u32 j = 0; j < count; ++j) { + for (u32 j = 0; j < count; ++j) + { Vec2 pos = player->player_cursor_pos; pos.y += (((f32)j / (f32)count) - 0.5) * spread; SpawnTestEntities4(root, pos); } } - if (flags & SIM_CONTROL_FLAG_WALLS_TEST) { + if (flags & SIM_CONTROL_FLAG_WALLS_TEST) + { GenerateTestWalls(world); } - if (flags & SIM_CONTROL_FLAG_EXPLODE_TEST) { + if (flags & SIM_CONTROL_FLAG_EXPLODE_TEST) + { P_LogDebugF("Explosion test"); SpawnTestExplosion(root, player->player_cursor_pos, 100, 2); } } - if (flags & SIM_CONTROL_FLAG_TILE_TEST) { + if (flags & SIM_CONTROL_FLAG_TILE_TEST) + { SpawnTestTile(world, player->player_cursor_pos); - } else if (old_control.flags & SIM_CONTROL_FLAG_TILE_TEST) { + } + else if (old_control.flags & SIM_CONTROL_FLAG_TILE_TEST) + { GenerateTestWalls(world); } } @@ -1060,7 +1171,8 @@ void StepSim(SimStepCtx *ctx) { struct sim_data_key msg_key = cmd_ent->cmd_chat_msg; String msg = sim_data_from_key(sim_data_store, msg_key); - if (msg.len > 0) { + if (msg.len > 0) + { Entity *chat_ent = AcquireSyncSrc(root); EnableProp(chat_ent, Prop_CHAT); chat_ent->chat_player = player->id; @@ -1077,7 +1189,8 @@ void StepSim(SimStepCtx *ctx) } /* Release cmd */ - if (!persist_cmd) { + if (!persist_cmd) + { EnableProp(cmd_ent, Prop_Release); } } @@ -1087,13 +1200,16 @@ void StepSim(SimStepCtx *ctx) //- Update entity control from player control - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; - if (HasProp(ent, Prop_Controlled)) { + if (HasProp(ent, Prop_Controlled)) + { Entity *player = EntityFromId(world, ent->controlling_player); - if (player->valid) { + if (player->valid) + { ent->control = player->player_control; } } @@ -1102,14 +1218,18 @@ void StepSim(SimStepCtx *ctx) //- Create employees - if (is_master) { - for (u64 i = 0; i < world->num_ents_reserved; ++i) { + if (is_master) + { + for (u64 i = 0; i < world->num_ents_reserved; ++i) + { Entity *ent = &world->ents[i]; if (!ShouldSimulate(ent)) continue; - if (HasProp(ent, Prop_Player)) { + if (HasProp(ent, Prop_Player)) + { /* FIXME: Ents never released when client disconnects */ Entity *control_ent = EntityFromId(world, ent->player_control_ent); - if (!control_ent->valid) { + if (!control_ent->valid) + { control_ent = SpawnTestEmployee(root); control_ent->predictor = ent->id; EnableProp(control_ent, Prop_Controlled); @@ -1117,13 +1237,15 @@ void StepSim(SimStepCtx *ctx) control_ent->controlling_player = ent->id; } Entity *camera_ent = EntityFromId(world, ent->player_camera_ent); - if (!camera_ent->valid) { + if (!camera_ent->valid) + { camera_ent = SpawnTestCamera(root, control_ent); camera_ent->predictor = ent->id; ent->player_camera_ent = camera_ent->id; } Entity *camera_follow = EntityFromId(world, camera_ent->camera_follow); - if (!camera_follow->valid) { + if (!camera_follow->valid) + { camera_ent->camera_follow = control_ent->id; } } @@ -1133,7 +1255,8 @@ void StepSim(SimStepCtx *ctx) //- Update entities from sprite - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; if (S_IsTagNil(ent->sprite)) continue; @@ -1143,22 +1266,27 @@ void StepSim(SimStepCtx *ctx) /* Update animation */ { S_Span span = S_SpanFromName(sheet, ent->sprite_span_name); - if (ent->animation_last_frame_change_time_ns == 0) { + if (ent->animation_last_frame_change_time_ns == 0) + { ent->animation_last_frame_change_time_ns = SecondsFromNs(world->sim_time_ns); } f64 time_in_frame = SecondsFromNs(world->sim_time_ns - ent->animation_last_frame_change_time_ns); u64 frame_index = ent->animation_frame; - if (frame_index < span.start || frame_index > span.end) { + if (frame_index < span.start || frame_index > span.end) + { frame_index = span.start; } - if (span.end > span.start) { + if (span.end > span.start) + { S_Frame frame = S_FrameFromIndex(sheet, frame_index); - while (time_in_frame > frame.duration) { + while (time_in_frame > frame.duration) + { time_in_frame -= frame.duration; ++frame_index; - if (frame_index > span.end) { + if (frame_index > span.end) + { /* Loop animation */ frame_index = span.start; } @@ -1188,7 +1316,8 @@ void StepSim(SimStepCtx *ctx) #endif /* Update collider from sprite */ - if (ent->sprite_collider_slice.len > 0) { + if (ent->sprite_collider_slice.len > 0) + { Xform cxf = ent->sprite_local_xform; S_Slice slice = S_SliceFromNameIndex(sheet, ent->sprite_collider_slice, ent->animation_frame); @@ -1197,7 +1326,8 @@ void StepSim(SimStepCtx *ctx) /* Test collider */ #if 0 - if (HasProp(ent, Prop_Test)) { + if (HasProp(ent, Prop_Test)) + { //if ((1)) { #if 0 ent->local_collider.points[0] = VEC2(0, 0); @@ -1234,7 +1364,8 @@ void StepSim(SimStepCtx *ctx) //- Update attachments - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; if (!HasProp(ent, Prop_Attached)) continue; @@ -1258,26 +1389,33 @@ void StepSim(SimStepCtx *ctx) //- Process ent control - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; - if (HasProp(ent, Prop_Controlled)) { + if (HasProp(ent, Prop_Controlled)) + { ControlData *control = &ent->control; ControlFlag flags = control->flags; - if (flags & SIM_CONTROL_FLAG_FIRE) { + if (flags & SIM_CONTROL_FLAG_FIRE) + { Entity *equipped = EntityFromId(world, ent->equipped); - if (equipped->valid) { + if (equipped->valid) + { ++equipped->num_primary_triggers; } } - if (flags & SIM_CONTROL_FLAG_FIRE_ALT) { + if (flags & SIM_CONTROL_FLAG_FIRE_ALT) + { Entity *equipped = EntityFromId(world, ent->equipped); - if (equipped->valid) { + if (equipped->valid) + { ++equipped->num_secondary_triggers; } } - if (flags & SIM_CONTROL_FLAG_TELEPORT_TEST) { + if (flags & SIM_CONTROL_FLAG_TELEPORT_TEST) + { TeleportTest(ent, control->dbg_cursor); } } @@ -1286,7 +1424,8 @@ void StepSim(SimStepCtx *ctx) //- Process triggered entities - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; @@ -1295,26 +1434,36 @@ void StepSim(SimStepCtx *ctx) ent->num_primary_triggers = 0; ent->num_secondary_triggers = 0; - if (primary_triggered) { + if (primary_triggered) + { i64 world_time_ns = world->sim_time_ns; - if ((world_time_ns - ent->last_primary_fire_ns >= NsFromSeconds(ent->primary_fire_delay)) || ent->last_primary_fire_ns == 0) { + if ((world_time_ns - ent->last_primary_fire_ns >= NsFromSeconds(ent->primary_fire_delay)) || ent->last_primary_fire_ns == 0) + { ent->last_primary_fire_ns = world_time_ns; - } else { + } + else + { primary_triggered = 0; } } - if (secondary_triggered) { + if (secondary_triggered) + { i64 world_time_ns = world->sim_time_ns; - if ((world_time_ns - ent->last_secondary_fire_ns >= NsFromSeconds(ent->secondary_fire_delay)) || ent->last_secondary_fire_ns == 0) { + if ((world_time_ns - ent->last_secondary_fire_ns >= NsFromSeconds(ent->secondary_fire_delay)) || ent->last_secondary_fire_ns == 0) + { ent->last_secondary_fire_ns = world_time_ns; - } else { + } + else + { secondary_triggered = 0; } } /* Fire smg */ - if (HasProp(ent, Prop_Smg)) { - if (primary_triggered) { + if (HasProp(ent, Prop_Smg)) + { + if (primary_triggered) + { S_Tag sprite = ent->sprite; u32 animation_frame = ent->animation_frame; S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, sprite); @@ -1337,14 +1486,14 @@ void StepSim(SimStepCtx *ctx) bullet->bullet_knockback = 10; bullet->layer = SIM_LAYER_BULLETS; - #if 1 +#if 1 /* Point collider */ bullet->local_collider.points[0] = VEC2(0, 0); bullet->local_collider.count = 1; - #else +#else bullet->sprite = S_TagFromPath(Lit("sprite/bullet.ase")); bullet->sprite_collider_slice = Lit("shape"); - #endif +#endif } /* Spawn tracer */ @@ -1360,8 +1509,10 @@ void StepSim(SimStepCtx *ctx) } /* Fire launcher */ - if (HasProp(ent, Prop_Launcher)) { - if (primary_triggered) { + if (HasProp(ent, Prop_Launcher)) + { + if (primary_triggered) + { S_Tag sprite = ent->sprite; u32 animation_frame = ent->animation_frame; S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, sprite); @@ -1406,15 +1557,20 @@ void StepSim(SimStepCtx *ctx) } /* Fire chucker */ - if (HasProp(ent, Prop_Chucker)) { - if (primary_triggered) { + if (HasProp(ent, Prop_Chucker)) + { + if (primary_triggered) + { } - if (secondary_triggered) { + if (secondary_triggered) + { Entity *zone = EntityFromId(world, ent->chucker_zone); Entity *target = EntityFromId(world, zone->chucker_zone_ent); Entity *old_joint_ent = EntityFromId(world, ent->chucker_joint); - if (IsValidAndActive(target) && zone->chucker_zone_ent_tick == world->tick - 1) { - if (!EqId(old_joint_ent->weld_joint_data.e1, target->id)) { + if (IsValidAndActive(target) && zone->chucker_zone_ent_tick == world->tick - 1) + { + if (!EqId(old_joint_ent->weld_joint_data.e1, target->id)) + { Entity *joint_ent = AcquireSyncSrc(root); EnableProp(joint_ent, Prop_Active); @@ -1435,7 +1591,8 @@ void StepSim(SimStepCtx *ctx) ent->chucker_joint = joint_ent->id; } } - if (old_joint_ent->valid) { + if (old_joint_ent->valid) + { EnableProp(old_joint_ent, Prop_Release); DisableProp(old_joint_ent, Prop_Active); } @@ -1446,13 +1603,16 @@ void StepSim(SimStepCtx *ctx) //- Create & update motor joints from control move - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; - if (HasProp(ent, Prop_Controlled)) { + if (HasProp(ent, Prop_Controlled)) + { Entity *joint_ent = EntityFromId(world, ent->move_joint); - if (is_master && !IsValidAndActive(joint_ent)) { + if (is_master && !IsValidAndActive(joint_ent)) + { joint_ent = AcquireSyncSrc(root); joint_ent->predictor = ent->predictor; joint_ent->mass_unscaled = F32Infinity; @@ -1471,7 +1631,8 @@ void StepSim(SimStepCtx *ctx) joint_ent->motor_joint_data = MotorJointFromDef(def); } - if (ShouldSimulate(joint_ent)) { + if (ShouldSimulate(joint_ent)) + { SetXform(joint_ent, XformIdentity); /* Reset joint ent position */ SetLinearVelocity(joint_ent, MulVec2(ClampVec2Len(ent->control.move, 1), ent->control_force_max_speed)); } @@ -1482,17 +1643,20 @@ void StepSim(SimStepCtx *ctx) //- Create & update motor joints from control focus (aim) #if SIM_PLAYER_AIM - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; - if (HasProp(ent, Prop_Controlled)) { + if (HasProp(ent, Prop_Controlled)) + { Xform xf = XformFromEntity(ent); Xform sprite_xf = MulXform(xf, ent->sprite_local_xform); /* Retrieve / create aim joint */ Entity *joint_ent = EntityFromId(world, ent->aim_joint); - if (is_master && !IsValidAndActive(joint_ent)) { + if (is_master && !IsValidAndActive(joint_ent)) + { joint_ent = AcquireSyncSrc(root); joint_ent->predictor = ent->predictor; joint_ent->mass_unscaled = F32Infinity; @@ -1510,7 +1674,8 @@ void StepSim(SimStepCtx *ctx) joint_ent->motor_joint_data = MotorJointFromDef(def); } - if (ShouldSimulate(joint_ent)) { + if (ShouldSimulate(joint_ent)) + { /* Set correction rate dynamically since motor velocity is only set for one frame */ joint_ent->motor_joint_data.correction_rate = 10 * sim_dt; @@ -1532,7 +1697,8 @@ void StepSim(SimStepCtx *ctx) Vec2 hold_dir = MulXformBasisV2(sprite_xf, sprite_hold_dir); Vec2 hold_pos = MulXformV2(sprite_xf, sprite_hold_pos); - if (EqVec2(hold_pos, ent_pos)) { + if (EqVec2(hold_pos, ent_pos)) + { /* If hold pos is same as origin (E.G if pivot is being used as hold pos), then move hold pos forward a tad to avoid issue */ sprite_hold_pos = AddVec2(sprite_hold_pos, VEC2(0, -1)); hold_pos = MulXformV2(sprite_xf, sprite_hold_pos); @@ -1559,11 +1725,13 @@ void StepSim(SimStepCtx *ctx) } f32 new_vel = 0; - if (!IsF32Nan(new_angle)) { + if (!IsF32Nan(new_angle)) + { const f32 angle_error_allowed = 0.001f; Xform joint_xf = XformFromEntity(joint_ent); f32 diff = UnwindAngleF32(new_angle - RotationFromXform(joint_xf)); - if (AbsF32(diff) > angle_error_allowed) { + if (AbsF32(diff) > angle_error_allowed) + { /* Instantly snap joint ent to new angle */ new_vel = diff / sim_dt; } @@ -1579,7 +1747,8 @@ void StepSim(SimStepCtx *ctx) //- Create motor joints from ground friction (gravity) #if 1 - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; if (!HasProp(ent, Prop_Dynamic)) continue; @@ -1592,8 +1761,10 @@ void StepSim(SimStepCtx *ctx) def.correction_rate = 0; def.max_force = ent->linear_ground_friction; def.max_torque = ent->angular_ground_friction; - if (joint_ent->motor_joint_data.max_force != def.max_force || joint_ent->motor_joint_data.max_torque != def.max_torque) { - if (is_master && !IsValidAndActive(joint_ent)) { + if (joint_ent->motor_joint_data.max_force != def.max_force || joint_ent->motor_joint_data.max_torque != def.max_torque) + { + if (is_master && !IsValidAndActive(joint_ent)) + { joint_ent = AcquireSyncSrc(root); joint_ent->predictor = ent->predictor; EnableProp(joint_ent, Prop_MotorJoint); @@ -1608,8 +1779,10 @@ void StepSim(SimStepCtx *ctx) //- Create mouse joints from client debug drag - if (is_master) { - for (u64 i = 0; i < world->num_ents_reserved; ++i) { + if (is_master) + { + for (u64 i = 0; i < world->num_ents_reserved; ++i) + { Entity *player = &world->ents[i]; if (!ShouldSimulate(player)) continue; if (!HasProp(player, Prop_Player)) continue; @@ -1621,14 +1794,19 @@ void StepSim(SimStepCtx *ctx) Entity *joint_ent = EntityFromId(world, player->player_dbg_drag_joint_ent); Entity *target_ent = EntityFromId(world, joint_ent->mouse_joint_data.target); - if (stop_dragging) { + if (stop_dragging) + { target_ent = NilEntity(); - } else if (start_dragging) { + } + else if (start_dragging) + { target_ent = EntityFromId(world, player->player_hovered_ent); } - if (ShouldSimulate(target_ent)) { - if (!IsValidAndActive(joint_ent)) { + if (ShouldSimulate(target_ent)) + { + if (!IsValidAndActive(joint_ent)) + { /* FIXME: Joint ent may never release */ joint_ent = AcquireLocal(root); joint_ent->mass_unscaled = F32Infinity; @@ -1641,9 +1819,12 @@ void StepSim(SimStepCtx *ctx) MouseJointDesc def = CreateMouseJointDef(); def.target = target_ent->id; - if (EqId(joint_ent->mouse_joint_data.target, target_ent->id)) { + if (EqId(joint_ent->mouse_joint_data.target, target_ent->id)) + { def.point_local_start = joint_ent->mouse_joint_data.point_local_start; - } else { + } + else + { def.point_local_start = InvertXformMulV2(xf, cursor); } def.point_end = cursor; @@ -1653,7 +1834,9 @@ void StepSim(SimStepCtx *ctx) def.angular_spring_hz = 1; def.angular_spring_damp = 0.1f; joint_ent->mouse_joint_data = MouseJointFromDef(def); - } else if (IsValidAndActive(joint_ent)) { + } + else if (IsValidAndActive(joint_ent)) + { joint_ent->mouse_joint_data.target = target_ent->id; } } @@ -1672,7 +1855,8 @@ void StepSim(SimStepCtx *ctx) //- Update explosions - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; if (!HasProp(ent, Prop_Explosion)) continue; @@ -1684,7 +1868,8 @@ void StepSim(SimStepCtx *ctx) //- Update tracers - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; if (!HasProp(ent, Prop_Tracer)) continue; @@ -1695,7 +1880,8 @@ void StepSim(SimStepCtx *ctx) Vec2 gradient_start = AddVec2(ent->tracer_gradient_start, tick_velocity); Vec2 gradient_end = AddVec2(ent->tracer_gradient_end, tick_velocity); - if (DotVec2(tick_velocity, SubVec2(gradient_start, end)) > 0) { + if (DotVec2(tick_velocity, SubVec2(gradient_start, end)) > 0) + { /* Tracer has disappeared */ EnableProp(ent, Prop_Release); } @@ -1707,12 +1893,14 @@ void StepSim(SimStepCtx *ctx) //- Initialize bullet kinematics from sources - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; if (!HasProp(ent, Prop_Bullet)) continue; - if (ent->activation_tick == world->tick) { + if (ent->activation_tick == world->tick) + { Entity *src = EntityFromId(world, ent->bullet_src); Xform src_xf = XformFromEntity(src); @@ -1741,7 +1929,8 @@ void StepSim(SimStepCtx *ctx) /* Initialize tracer */ Entity *tracer = EntityFromId(world, ent->bullet_tracer); - if (ShouldSimulate(tracer)) { + if (ShouldSimulate(tracer)) + { SetXform(tracer, xf); EnableProp(tracer, Prop_Kinematic); SetLinearVelocity(tracer, ent->linear_velocity); @@ -1765,7 +1954,8 @@ void StepSim(SimStepCtx *ctx) //- Update cameras - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; if (!HasProp(ent, Prop_Camera)) continue; @@ -1780,7 +1970,8 @@ void StepSim(SimStepCtx *ctx) { Xform quad_xf = MulXform(XformFromEntity(ent), ent->camera_quad_xform); Vec2 camera_size = ScaleFromXform(quad_xf); - if (!IsVec2Zero(camera_size)) { + if (!IsVec2Zero(camera_size)) + { aspect_ratio = camera_size.x / camera_size.y; } } @@ -1792,10 +1983,13 @@ void StepSim(SimStepCtx *ctx) ent->camera_xform_target.og = camera_focus_pos; /* Lerp camera */ - if (ent->camera_applied_lerp_continuity_gen_plus_one == ent->camera_lerp_continuity_gen + 1) { + if (ent->camera_applied_lerp_continuity_gen_plus_one == ent->camera_lerp_continuity_gen + 1) + { f32 t = 1 - PowF32(2.f, -20.f * (f32)sim_dt); xf = LerpXform(xf, ent->camera_xform_target, t); - } else { + } + else + { /* Skip lerp */ xf = ent->camera_xform_target; } @@ -1806,7 +2000,8 @@ void StepSim(SimStepCtx *ctx) { /* TODO: Update based on distance to quake */ ent->shake = 0; - for (u64 quake_ent_index = 0; quake_ent_index < world->num_ents_reserved; ++quake_ent_index) { + for (u64 quake_ent_index = 0; quake_ent_index < world->num_ents_reserved; ++quake_ent_index) + { Entity *quake = &world->ents[quake_ent_index]; if (!ShouldSimulate(quake)) continue; if (!HasProp(quake, Prop_Quake)) continue; @@ -1820,13 +2015,15 @@ void StepSim(SimStepCtx *ctx) //- Update quakes - for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) + { Entity *ent = &world->ents[ent_index]; if (!ShouldSimulate(ent)) continue; if (!HasProp(ent, Prop_Quake)) continue; ent->quake_intensity = MaxF32(0, ent->quake_intensity - (ent->quake_fade * sim_dt)); - if (ent->quake_intensity <= 0) { + if (ent->quake_intensity <= 0) + { EnableProp(ent, Prop_Release); } } @@ -1841,14 +2038,17 @@ void StepSim(SimStepCtx *ctx) u64 stack_count = 1; *stack = root; - while (stack_count > 0) { + while (stack_count > 0) + { Entity *parent; PopStruct(temp.arena, Entity *, &parent); --stack_count; i32 parent_layer = parent->final_layer; - for (Entity *child = EntityFromId(world, parent->first); child->valid; child = EntityFromId(world, child->next)) { - if (ShouldSimulate(child)) { + for (Entity *child = EntityFromId(world, parent->first); child->valid; child = EntityFromId(world, child->next)) + { + if (ShouldSimulate(child)) + { child->final_layer = parent_layer + child->layer; *PushStructNoZero(temp.arena, Entity *) = child; ++stack_count; @@ -1867,7 +2067,8 @@ void StepSim(SimStepCtx *ctx) //- Sync to publish client - if (publish_client->valid && world->tick > publish_client->last_tick) { + if (publish_client->valid && world->tick > publish_client->last_tick) + { Snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, publish_client->last_tick); Snapshot *pub_world = sim_snapshot_acquire(publish_client, prev_pub_world, world->tick); @@ -1875,9 +2076,11 @@ void StepSim(SimStepCtx *ctx) sim_snapshot_sync_ents(pub_world, world, world_client->player_id, 0); /* Mark all synced ents as both sync dsts & sync srcs */ - for (u64 ent_index = 2; ent_index < pub_world->num_ents_reserved; ++ent_index) { + for (u64 ent_index = 2; ent_index < pub_world->num_ents_reserved; ++ent_index) + { Entity *ent = &pub_world->ents[ent_index]; - if (ent->valid) { + if (ent->valid) + { EnableProp(ent, Prop_SyncDst); EnableProp(ent, Prop_SyncSrc); } diff --git a/src/pp/pp_step.h b/src/pp/pp_step.h index 8f84a47d..8b4a00c2 100644 --- a/src/pp/pp_step.h +++ b/src/pp/pp_step.h @@ -4,8 +4,8 @@ /* Structure used to accelerate up entity lookup (rebuilt every step) */ /* TODO: Remove this and do something better. Just a hack to de-couple old sim ctx from step. */ -typedef struct SimAccel SimAccel; -struct SimAccel { +Struct(SimAccel) +{ Space *space; }; @@ -13,7 +13,8 @@ struct SimAccel { //~ Step ctx typedef struct SimStepCtx SimStepCtx; -struct SimStepCtx { +struct SimStepCtx +{ b32 is_master; SimAccel *accel; RandState rand; /* TODO: Replace with per-sim rand for deterministic rng */