pp refactor progress

This commit is contained in:
jacob 2025-08-05 16:50:47 -05:00
parent eabefaa16d
commit c649867ef4
7 changed files with 1240 additions and 637 deletions

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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 */