pp refactor progress
This commit is contained in:
parent
eabefaa16d
commit
c649867ef4
261
src/pp/pp_ent.c
261
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
236
src/pp/pp_phys.c
236
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 */
|
||||
|
||||
595
src/pp/pp_sim.c
595
src/pp/pp_sim.c
File diff suppressed because it is too large
Load Diff
183
src/pp/pp_sim.h
183
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);
|
||||
|
||||
589
src/pp/pp_step.c
589
src/pp/pp_step.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user