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->valid);
|
||||||
Assert(ss == parent->ss);
|
Assert(ss == parent->ss);
|
||||||
Entity *ent;
|
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 */
|
/* Reuse from free list */
|
||||||
ent = &ss->ents[ss->first_free_ent];
|
ent = &ss->ents[ss->first_free_ent];
|
||||||
ss->first_free_ent = ent->next_free;
|
ss->first_free_ent = ent->next_free;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Make new */
|
/* Make new */
|
||||||
ent = PushStructNoZero(ss->ents_arena, Entity);
|
ent = PushStructNoZero(ss->ents_arena, Entity);
|
||||||
++ss->num_ents_reserved;
|
++ss->num_ents_reserved;
|
||||||
@ -83,7 +86,8 @@ void ReleaseRaw(Entity *ent)
|
|||||||
Snapshot *ss = ent->ss;
|
Snapshot *ss = ent->ss;
|
||||||
/* Release children */
|
/* Release children */
|
||||||
Entity *child = EntityFromId(ss, ent->first);
|
Entity *child = EntityFromId(ss, ent->first);
|
||||||
while (child->valid) {
|
while (child->valid)
|
||||||
|
{
|
||||||
Entity *next = EntityFromId(ss, child->next);
|
Entity *next = EntityFromId(ss, child->next);
|
||||||
ReleaseRaw(child);
|
ReleaseRaw(child);
|
||||||
child = next;
|
child = next;
|
||||||
@ -103,7 +107,8 @@ void Release(Entity *ent)
|
|||||||
{
|
{
|
||||||
Snapshot *ss = ent->ss;
|
Snapshot *ss = ent->ss;
|
||||||
Entity *parent = EntityFromId(ss, ent->parent);
|
Entity *parent = EntityFromId(ss, ent->parent);
|
||||||
if (parent->valid) {
|
if (parent->valid)
|
||||||
|
{
|
||||||
Unlink(ent);
|
Unlink(ent);
|
||||||
}
|
}
|
||||||
ReleaseRaw(ent);
|
ReleaseRaw(ent);
|
||||||
@ -115,9 +120,11 @@ void ReleaseAllWithProp(Snapshot *ss, Prop prop)
|
|||||||
|
|
||||||
Entity **ents_to_release = PushDry(scratch.arena, Entity *);
|
Entity **ents_to_release = PushDry(scratch.arena, Entity *);
|
||||||
u64 ents_to_release_count = 0;
|
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];
|
Entity *ent = &ss->ents[ent_index];
|
||||||
if (ent->valid && HasProp(ent, prop)) {
|
if (ent->valid && HasProp(ent, prop))
|
||||||
|
{
|
||||||
*PushStructNoZero(scratch.arena, Entity *) = ent;
|
*PushStructNoZero(scratch.arena, Entity *) = ent;
|
||||||
++ents_to_release_count;
|
++ents_to_release_count;
|
||||||
}
|
}
|
||||||
@ -126,9 +133,11 @@ void ReleaseAllWithProp(Snapshot *ss, Prop prop)
|
|||||||
/* Release from snapshot */
|
/* Release from snapshot */
|
||||||
/* TODO: Breadth first iteration to only release parent entities (since
|
/* TODO: Breadth first iteration to only release parent entities (since
|
||||||
* child entities will be released along with parent anyway) */
|
* 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];
|
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);
|
Release(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,9 +165,12 @@ u32 IndexFromEntity(Snapshot *ss, Entity *ent)
|
|||||||
|
|
||||||
Entity *EntityFromIndex(Snapshot *ss, u32 index)
|
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];
|
return &ss->ents[index];
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return NilEntity();
|
return NilEntity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,9 +185,11 @@ void SetEntityId(Entity *ent, EntityId id)
|
|||||||
{
|
{
|
||||||
Snapshot *ss = ent->ss;
|
Snapshot *ss = ent->ss;
|
||||||
EntityId old_id = ent->id;
|
EntityId old_id = ent->id;
|
||||||
if (!EqId(old_id, id)) {
|
if (!EqId(old_id, id))
|
||||||
|
{
|
||||||
/* Release old from lookup */
|
/* Release old from lookup */
|
||||||
if (!IsNilId(old_id)) {
|
if (!IsNilId(old_id))
|
||||||
|
{
|
||||||
EntBin *bin = BinFromId(ss, old_id);
|
EntBin *bin = BinFromId(ss, old_id);
|
||||||
u32 prev_index = 0;
|
u32 prev_index = 0;
|
||||||
u32 next_index = 0;
|
u32 next_index = 0;
|
||||||
@ -183,10 +197,12 @@ void SetEntityId(Entity *ent, EntityId id)
|
|||||||
Entity *prev = NilEntity();
|
Entity *prev = NilEntity();
|
||||||
Entity *next = NilEntity();
|
Entity *next = NilEntity();
|
||||||
Entity *search = EntityFromIndex(ss, search_index);
|
Entity *search = EntityFromIndex(ss, search_index);
|
||||||
while (search->valid) {
|
while (search->valid)
|
||||||
|
{
|
||||||
next_index = search->next_in_id_bin;
|
next_index = search->next_in_id_bin;
|
||||||
next = EntityFromIndex(ss, next_index);
|
next = EntityFromIndex(ss, next_index);
|
||||||
if (EqId(search->id, old_id)) {
|
if (EqId(search->id, old_id))
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prev_index = search_index;
|
prev_index = search_index;
|
||||||
@ -198,21 +214,28 @@ void SetEntityId(Entity *ent, EntityId id)
|
|||||||
/* Old id not in bin, this should be impossible. */
|
/* Old id not in bin, this should be impossible. */
|
||||||
Assert(search->valid);
|
Assert(search->valid);
|
||||||
|
|
||||||
if (prev->valid) {
|
if (prev->valid)
|
||||||
|
{
|
||||||
prev->next_in_id_bin = next_index;
|
prev->next_in_id_bin = next_index;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
bin->first = next_index;
|
bin->first = next_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next->valid) {
|
if (next->valid)
|
||||||
|
{
|
||||||
next->prev_in_id_bin = prev_index;
|
next->prev_in_id_bin = prev_index;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
bin->last = prev_index;
|
bin->last = prev_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert new id into lookup */
|
/* Insert new id into lookup */
|
||||||
if (!IsNilId(id)) {
|
if (!IsNilId(id))
|
||||||
|
{
|
||||||
#if RtcIsEnabled
|
#if RtcIsEnabled
|
||||||
{
|
{
|
||||||
Entity *existing = EntityFromId(ss, id);
|
Entity *existing = EntityFromId(ss, id);
|
||||||
@ -224,10 +247,13 @@ void SetEntityId(Entity *ent, EntityId id)
|
|||||||
EntBin *bin = BinFromId(ss, id);
|
EntBin *bin = BinFromId(ss, id);
|
||||||
u32 ent_index = IndexFromEntity(ss, ent);
|
u32 ent_index = IndexFromEntity(ss, ent);
|
||||||
Entity *last = EntityFromIndex(ss, bin->last);
|
Entity *last = EntityFromIndex(ss, bin->last);
|
||||||
if (last->valid) {
|
if (last->valid)
|
||||||
|
{
|
||||||
last->next_in_id_bin = ent_index;
|
last->next_in_id_bin = ent_index;
|
||||||
ent->prev_in_id_bin = bin->last;
|
ent->prev_in_id_bin = bin->last;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
bin->first = ent_index;
|
bin->first = ent_index;
|
||||||
ent->prev_in_id_bin = 0;
|
ent->prev_in_id_bin = 0;
|
||||||
}
|
}
|
||||||
@ -242,10 +268,13 @@ void SetEntityId(Entity *ent, EntityId id)
|
|||||||
Entity *EntityFromId(Snapshot *ss, EntityId id)
|
Entity *EntityFromId(Snapshot *ss, EntityId id)
|
||||||
{
|
{
|
||||||
Entity *result = NilEntity();
|
Entity *result = NilEntity();
|
||||||
if (!IsNilId(id) && ss->valid) {
|
if (!IsNilId(id) && ss->valid)
|
||||||
|
{
|
||||||
EntBin *bin = BinFromId(ss, id);
|
EntBin *bin = BinFromId(ss, id);
|
||||||
for (Entity *e = EntityFromIndex(ss, bin->first); e->valid; e = EntityFromIndex(ss, e->next_in_id_bin)) {
|
for (Entity *e = EntityFromIndex(ss, bin->first); e->valid; e = EntityFromIndex(ss, e->next_in_id_bin))
|
||||||
if (EqId(e->id, id)) {
|
{
|
||||||
|
if (EqId(e->id, id))
|
||||||
|
{
|
||||||
result = e;
|
result = e;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -299,9 +328,11 @@ Entity *FirstWithProp(Snapshot *ss, Prop prop)
|
|||||||
{
|
{
|
||||||
u64 count = ss->num_ents_reserved;
|
u64 count = ss->num_ents_reserved;
|
||||||
Entity *entities = ss->ents;
|
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];
|
Entity *ent = &entities[ent_index];
|
||||||
if (ent->valid && HasProp(ent, prop)) {
|
if (ent->valid && HasProp(ent, prop))
|
||||||
|
{
|
||||||
return ent;
|
return ent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -312,17 +343,22 @@ Entity *FirstWithAllProps(Snapshot *ss, PropArray props)
|
|||||||
{
|
{
|
||||||
u64 count = ss->num_ents_reserved;
|
u64 count = ss->num_ents_reserved;
|
||||||
Entity *entities = ss->ents;
|
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];
|
Entity *ent = &entities[ent_index];
|
||||||
if (ent->valid) {
|
if (ent->valid)
|
||||||
|
{
|
||||||
b32 all = 1;
|
b32 all = 1;
|
||||||
for (u64 i = 0; i < props.count; ++i) {
|
for (u64 i = 0; i < props.count; ++i)
|
||||||
if (!HasProp(ent, props.props[i])) {
|
{
|
||||||
|
if (!HasProp(ent, props.props[i]))
|
||||||
|
{
|
||||||
all = 0;
|
all = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (all) {
|
if (all)
|
||||||
|
{
|
||||||
return ent;
|
return ent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,7 +374,8 @@ void Link(Entity *ent, Entity *parent)
|
|||||||
Snapshot *ss = ent->ss;
|
Snapshot *ss = ent->ss;
|
||||||
|
|
||||||
Entity *old_parent = EntityFromId(ss, ent->parent);
|
Entity *old_parent = EntityFromId(ss, ent->parent);
|
||||||
if (old_parent->valid) {
|
if (old_parent->valid)
|
||||||
|
{
|
||||||
/* Unlink from current parent */
|
/* Unlink from current parent */
|
||||||
Unlink(ent);
|
Unlink(ent);
|
||||||
}
|
}
|
||||||
@ -346,18 +383,24 @@ void Link(Entity *ent, Entity *parent)
|
|||||||
EntityId ent_id = ent->id;
|
EntityId ent_id = ent->id;
|
||||||
EntityId last_child_id = parent->last;
|
EntityId last_child_id = parent->last;
|
||||||
Entity *last_child = EntityFromId(ss, last_child_id);
|
Entity *last_child = EntityFromId(ss, last_child_id);
|
||||||
if (last_child->valid) {
|
if (last_child->valid)
|
||||||
|
{
|
||||||
ent->prev = last_child_id;
|
ent->prev = last_child_id;
|
||||||
last_child->next = ent_id;
|
last_child->next = ent_id;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
parent->first = ent_id;
|
parent->first = ent_id;
|
||||||
}
|
}
|
||||||
parent->last = ent_id;
|
parent->last = ent_id;
|
||||||
|
|
||||||
if (parent->is_root) {
|
if (parent->is_root)
|
||||||
|
{
|
||||||
ent->is_top = 1;
|
ent->is_top = 1;
|
||||||
ent->top = ent_id;
|
ent->top = ent_id;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ent->top = parent->top;
|
ent->top = parent->top;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,14 +418,20 @@ void Unlink(Entity *ent)
|
|||||||
Entity *next = EntityFromId(ss, ent->next);
|
Entity *next = EntityFromId(ss, ent->next);
|
||||||
|
|
||||||
/* Unlink from parent & siblings */
|
/* Unlink from parent & siblings */
|
||||||
if (prev->valid) {
|
if (prev->valid)
|
||||||
|
{
|
||||||
prev->next = next->id;
|
prev->next = next->id;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
parent->first = next->id;
|
parent->first = next->id;
|
||||||
}
|
}
|
||||||
if (next->valid) {
|
if (next->valid)
|
||||||
|
{
|
||||||
next->prev = prev->id;
|
next->prev = prev->id;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
parent->last = prev->id;
|
parent->last = prev->id;
|
||||||
}
|
}
|
||||||
ent->prev = NilEntityId;
|
ent->prev = NilEntityId;
|
||||||
@ -394,10 +443,14 @@ void Unlink(Entity *ent)
|
|||||||
|
|
||||||
void MarkChildXformsDirty(Snapshot *ss, Entity *ent)
|
void MarkChildXformsDirty(Snapshot *ss, Entity *ent)
|
||||||
{
|
{
|
||||||
for (Entity *child = EntityFromId(ss, ent->first); child->valid; child = EntityFromId(ss, child->next)) {
|
for (Entity *child = EntityFromId(ss, ent->first); child->valid; child = EntityFromId(ss, child->next))
|
||||||
if (child->_is_xform_dirty) {
|
{
|
||||||
|
if (child->_is_xform_dirty)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
child->_is_xform_dirty = 1;
|
child->_is_xform_dirty = 1;
|
||||||
MarkChildXformsDirty(ss, child);
|
MarkChildXformsDirty(ss, child);
|
||||||
}
|
}
|
||||||
@ -407,10 +460,14 @@ void MarkChildXformsDirty(Snapshot *ss, Entity *ent)
|
|||||||
Xform XformFromEntity_(Snapshot *ss, Entity *ent)
|
Xform XformFromEntity_(Snapshot *ss, Entity *ent)
|
||||||
{
|
{
|
||||||
Xform xf;
|
Xform xf;
|
||||||
if (ent->_is_xform_dirty) {
|
if (ent->_is_xform_dirty)
|
||||||
if (ent->is_top) {
|
{
|
||||||
|
if (ent->is_top)
|
||||||
|
{
|
||||||
xf = ent->_local_xform;
|
xf = ent->_local_xform;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Entity *parent = EntityFromId(ss, ent->parent);
|
Entity *parent = EntityFromId(ss, ent->parent);
|
||||||
xf = XformFromEntity_(ss, parent);
|
xf = XformFromEntity_(ss, parent);
|
||||||
xf = MulXform(xf, ent->_local_xform);
|
xf = MulXform(xf, ent->_local_xform);
|
||||||
@ -419,7 +476,9 @@ Xform XformFromEntity_(Snapshot *ss, Entity *ent)
|
|||||||
}
|
}
|
||||||
ent->_xform = xf;
|
ent->_xform = xf;
|
||||||
ent->_is_xform_dirty = 0;
|
ent->_is_xform_dirty = 0;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
xf = ent->_xform;
|
xf = ent->_xform;
|
||||||
}
|
}
|
||||||
return xf;
|
return xf;
|
||||||
@ -428,10 +487,14 @@ Xform XformFromEntity_(Snapshot *ss, Entity *ent)
|
|||||||
Xform XformFromEntity(Entity *ent)
|
Xform XformFromEntity(Entity *ent)
|
||||||
{
|
{
|
||||||
Xform xf;
|
Xform xf;
|
||||||
if (ent->_is_xform_dirty) {
|
if (ent->_is_xform_dirty)
|
||||||
if (ent->is_top) {
|
{
|
||||||
|
if (ent->is_top)
|
||||||
|
{
|
||||||
xf = ent->_local_xform;
|
xf = ent->_local_xform;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Snapshot *ss = ent->ss;
|
Snapshot *ss = ent->ss;
|
||||||
Entity *parent = EntityFromId(ss, ent->parent);
|
Entity *parent = EntityFromId(ss, ent->parent);
|
||||||
xf = XformFromEntity_(ss, parent);
|
xf = XformFromEntity_(ss, parent);
|
||||||
@ -441,7 +504,9 @@ Xform XformFromEntity(Entity *ent)
|
|||||||
}
|
}
|
||||||
ent->_xform = xf;
|
ent->_xform = xf;
|
||||||
ent->_is_xform_dirty = 0;
|
ent->_is_xform_dirty = 0;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
xf = ent->_xform;
|
xf = ent->_xform;
|
||||||
}
|
}
|
||||||
return xf;
|
return xf;
|
||||||
@ -454,12 +519,16 @@ Xform LocalXformFromEntity(Entity *ent)
|
|||||||
|
|
||||||
void SetXform(Entity *ent, Xform xf)
|
void SetXform(Entity *ent, Xform xf)
|
||||||
{
|
{
|
||||||
if (!EqXform(xf, ent->_xform)) {
|
if (!EqXform(xf, ent->_xform))
|
||||||
|
{
|
||||||
Snapshot *ss = ent->ss;
|
Snapshot *ss = ent->ss;
|
||||||
/* Update local xform */
|
/* Update local xform */
|
||||||
if (ent->is_top) {
|
if (ent->is_top)
|
||||||
|
{
|
||||||
ent->_local_xform = xf;
|
ent->_local_xform = xf;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Entity *parent = EntityFromId(ss, ent->parent);
|
Entity *parent = EntityFromId(ss, ent->parent);
|
||||||
Xform parent_global = XformFromEntity_(ss, parent);
|
Xform parent_global = XformFromEntity_(ss, parent);
|
||||||
ent->_local_xform = MulXform(InvertXform(parent_global), xf);
|
ent->_local_xform = MulXform(InvertXform(parent_global), xf);
|
||||||
@ -472,7 +541,8 @@ void SetXform(Entity *ent, Xform xf)
|
|||||||
|
|
||||||
void SetLocalXform(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->_local_xform = xf;
|
||||||
ent->_is_xform_dirty = 1;
|
ent->_is_xform_dirty = 1;
|
||||||
MarkChildXformsDirty(ent->ss, ent);
|
MarkChildXformsDirty(ent->ss, ent);
|
||||||
@ -484,21 +554,24 @@ void SetLocalXform(Entity *ent, Xform xf)
|
|||||||
|
|
||||||
void SetLinearVelocity(Entity *ent, Vec2 velocity)
|
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);
|
ent->linear_velocity = ClampVec2Len(velocity, SIM_MAX_LINEAR_VELOCITY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAngularVelocity(Entity *ent, f32 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);
|
ent->angular_velocity = ClampF32(velocity, -SIM_MAX_ANGULAR_VELOCITY, SIM_MAX_ANGULAR_VELOCITY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyLinearImpulse(Entity *ent, Vec2 impulse, Vec2 point)
|
void ApplyLinearImpulse(Entity *ent, Vec2 impulse, Vec2 point)
|
||||||
{
|
{
|
||||||
if (HasProp(ent, Prop_Dynamic)) {
|
if (HasProp(ent, Prop_Dynamic))
|
||||||
|
{
|
||||||
Xform xf = XformFromEntity(ent);
|
Xform xf = XformFromEntity(ent);
|
||||||
Vec2 center = xf.og;
|
Vec2 center = xf.og;
|
||||||
f32 scale = AbsF32(DeterminantFromXform(xf));
|
f32 scale = AbsF32(DeterminantFromXform(xf));
|
||||||
@ -513,7 +586,8 @@ void ApplyLinearImpulse(Entity *ent, Vec2 impulse, Vec2 point)
|
|||||||
|
|
||||||
void ApplyLinearImpulseToCenter(Entity *ent, Vec2 impulse)
|
void ApplyLinearImpulseToCenter(Entity *ent, Vec2 impulse)
|
||||||
{
|
{
|
||||||
if (HasProp(ent, Prop_Dynamic)) {
|
if (HasProp(ent, Prop_Dynamic))
|
||||||
|
{
|
||||||
Xform xf = XformFromEntity(ent);
|
Xform xf = XformFromEntity(ent);
|
||||||
f32 scale = AbsF32(DeterminantFromXform(xf));
|
f32 scale = AbsF32(DeterminantFromXform(xf));
|
||||||
f32 inv_mass = 1.f / (ent->mass_unscaled * scale);
|
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)
|
void ApplyForceToCenter(Entity *ent, Vec2 force)
|
||||||
{
|
{
|
||||||
if (HasProp(ent, Prop_Dynamic)) {
|
if (HasProp(ent, Prop_Dynamic))
|
||||||
|
{
|
||||||
ent->force = AddVec2(ent->force, force);
|
ent->force = AddVec2(ent->force, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyAngularImpulse(Entity *ent, f32 impulse)
|
void ApplyAngularImpulse(Entity *ent, f32 impulse)
|
||||||
{
|
{
|
||||||
if (HasProp(ent, Prop_Dynamic)) {
|
if (HasProp(ent, Prop_Dynamic))
|
||||||
|
{
|
||||||
Xform xf = XformFromEntity(ent);
|
Xform xf = XformFromEntity(ent);
|
||||||
f32 scale = AbsF32(DeterminantFromXform(xf));
|
f32 scale = AbsF32(DeterminantFromXform(xf));
|
||||||
f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale);
|
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)
|
void ApplyTorque(Entity *ent, f32 torque)
|
||||||
{
|
{
|
||||||
if (HasProp(ent, Prop_Dynamic)) {
|
if (HasProp(ent, Prop_Dynamic))
|
||||||
|
{
|
||||||
ent->torque += torque;
|
ent->torque += torque;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -576,10 +653,12 @@ void LerpEntity(Entity *e, Entity *e0, Entity *e1, f64 blend)
|
|||||||
{
|
{
|
||||||
if (IsValidAndActive(e0) && IsValidAndActive(e1)
|
if (IsValidAndActive(e0) && IsValidAndActive(e1)
|
||||||
&& EqId(e0->id, e1->id)
|
&& 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);
|
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 */
|
/* TODO: Cache parent & child xforms in sim */
|
||||||
Xform e0_xf = XformFromEntity(e0);
|
Xform e0_xf = XformFromEntity(e0);
|
||||||
Xform e1_xf = XformFromEntity(e1);
|
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)
|
void CreateMissingEntitiesFromSnapshots(Entity *local_parent, Entity *remote, EntityId remote_player)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
if (HasProp(remote, Prop_SyncSrc)) {
|
if (HasProp(remote, Prop_SyncSrc))
|
||||||
|
{
|
||||||
Snapshot *local_ss = local_parent->ss;
|
Snapshot *local_ss = local_parent->ss;
|
||||||
Snapshot *remote_ss = remote->ss;
|
Snapshot *remote_ss = remote->ss;
|
||||||
|
|
||||||
EntityId id = remote->id;
|
EntityId id = remote->id;
|
||||||
Entity *local_ent = EntityFromId(local_ss, id);
|
Entity *local_ent = EntityFromId(local_ss, id);
|
||||||
if (!local_ent->valid) {
|
if (!local_ent->valid)
|
||||||
|
{
|
||||||
local_ent = AcquireSyncDst(local_parent, id, remote_player);
|
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);
|
CreateMissingEntitiesFromSnapshots(local_ent, remote_child, remote_player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -665,7 +747,8 @@ void SyncEntity(Entity *local, Entity *remote)
|
|||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
||||||
//- Encode
|
////////////////////////////////
|
||||||
|
//~ Encode
|
||||||
|
|
||||||
void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1)
|
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;
|
u64 pos = 0;
|
||||||
e1->ss = e0->ss;
|
e1->ss = e0->ss;
|
||||||
while (pos < sizeof(*e1)) {
|
while (pos < sizeof(*e1))
|
||||||
|
{
|
||||||
u64 chunk_size = MinU64(pos + 8, sizeof(*e1)) - pos;
|
u64 chunk_size = MinU64(pos + 8, sizeof(*e1)) - pos;
|
||||||
u8 *chunk0 = (u8 *)e0 + pos;
|
u8 *chunk0 = (u8 *)e0 + pos;
|
||||||
u8 *chunk1 = (u8 *)e1 + 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;
|
u64 bits = 0;
|
||||||
CopyBytes(&bits, chunk1, chunk_size);
|
CopyBytes(&bits, chunk1, chunk_size);
|
||||||
BB_WriteUBits(bw, bits, 64);
|
BB_WriteUBits(bw, bits, 64);
|
||||||
@ -690,16 +775,19 @@ void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1)
|
|||||||
e1->ss = ss;
|
e1->ss = ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Decode
|
////////////////////////////////
|
||||||
|
//~ Decode
|
||||||
|
|
||||||
void DecodeEntity(BB_Reader *br, Entity *e)
|
void DecodeEntity(BB_Reader *br, Entity *e)
|
||||||
{
|
{
|
||||||
Snapshot *old_ss = e->ss;
|
Snapshot *old_ss = e->ss;
|
||||||
{
|
{
|
||||||
u64 pos = 0;
|
u64 pos = 0;
|
||||||
while (pos < sizeof(*e)) {
|
while (pos < sizeof(*e))
|
||||||
|
{
|
||||||
u8 *chunk = (u8 *)e + pos;
|
u8 *chunk = (u8 *)e + pos;
|
||||||
if (BB_ReadBit(br)) {
|
if (BB_ReadBit(br))
|
||||||
|
{
|
||||||
u64 chunk_size = MinU64(pos + 8, sizeof(*e)) - pos;
|
u64 chunk_size = MinU64(pos + 8, sizeof(*e)) - pos;
|
||||||
u64 bits = BB_ReadUBits(br, 64);
|
u64 bits = BB_ReadUBits(br, 64);
|
||||||
CopyBytes(chunk, &bits, chunk_size);
|
CopyBytes(chunk, &bits, chunk_size);
|
||||||
@ -713,7 +801,8 @@ void DecodeEntity(BB_Reader *br, Entity *e)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
//- Encode
|
////////////////////////////////
|
||||||
|
//~ Encode
|
||||||
|
|
||||||
void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1)
|
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.
|
/* 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. */
|
* 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;
|
u64 pos = 0;
|
||||||
e1->ss = e0->ss;
|
e1->ss = e0->ss;
|
||||||
while (pos < sizeof(*e1)) {
|
while (pos < sizeof(*e1))
|
||||||
|
{
|
||||||
u64 chunk_size = MinU64(pos + 8, sizeof(*e1)) - pos;
|
u64 chunk_size = MinU64(pos + 8, sizeof(*e1)) - pos;
|
||||||
u8 *chunk0 = (u8 *)e0 + pos;
|
u8 *chunk0 = (u8 *)e0 + pos;
|
||||||
u8 *chunk1 = (u8 *)e1 + pos;
|
u8 *chunk1 = (u8 *)e1 + pos;
|
||||||
if (EqBytes(chunk0, chunk1, chunk_size)) {
|
if (EqBytes(chunk0, chunk1, chunk_size))
|
||||||
|
{
|
||||||
BB_WriteBit(bw, 0);
|
BB_WriteBit(bw, 0);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
BB_WriteBit(bw, 1);
|
BB_WriteBit(bw, 1);
|
||||||
u64 bits = 0;
|
u64 bits = 0;
|
||||||
CopyBytes(&bits, chunk1, chunk_size);
|
CopyBytes(&bits, chunk1, chunk_size);
|
||||||
@ -744,16 +837,19 @@ void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1)
|
|||||||
e1->ss = ss;
|
e1->ss = ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Decode
|
////////////////////////////////
|
||||||
|
//~ Decode
|
||||||
|
|
||||||
void DecodeEntity(BB_Reader *br, Entity *e)
|
void DecodeEntity(BB_Reader *br, Entity *e)
|
||||||
{
|
{
|
||||||
Entity decoded = *e;
|
Entity decoded = *e;
|
||||||
{
|
{
|
||||||
u64 pos = 0;
|
u64 pos = 0;
|
||||||
while (pos < sizeof(decoded)) {
|
while (pos < sizeof(decoded))
|
||||||
|
{
|
||||||
u8 *chunk = (u8 *)&decoded + pos;
|
u8 *chunk = (u8 *)&decoded + pos;
|
||||||
if (BB_ReadBit(br)) {
|
if (BB_ReadBit(br))
|
||||||
|
{
|
||||||
u64 chunk_size = MinU64(pos + 8, sizeof(decoded)) - pos;
|
u64 chunk_size = MinU64(pos + 8, sizeof(decoded)) - pos;
|
||||||
u64 bits = BB_ReadUBits(br, 64);
|
u64 bits = BB_ReadUBits(br, 64);
|
||||||
CopyBytes(chunk, &bits, chunk_size);
|
CopyBytes(chunk, &bits, chunk_size);
|
||||||
@ -767,7 +863,8 @@ void DecodeEntity(BB_Reader *br, Entity *e)
|
|||||||
EntityId new_id = decoded.id;
|
EntityId new_id = decoded.id;
|
||||||
CopyStruct(e, &decoded);
|
CopyStruct(e, &decoded);
|
||||||
e->id = old_id;
|
e->id = old_id;
|
||||||
if (!EqId(old_id, new_id)) {
|
if (!EqId(old_id, new_id))
|
||||||
|
{
|
||||||
SetEntityId(e, new_id);
|
SetEntityId(e, new_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -558,7 +558,11 @@ void CreateMissingEntitiesFromSnapshots(Entity *local_parent, Entity *remote, En
|
|||||||
void SyncEntity(Entity *local, Entity *remote);
|
void SyncEntity(Entity *local, Entity *remote);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Encode / decode operations
|
//~ Encode
|
||||||
|
|
||||||
void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1);
|
void EncodeEntity(BB_Writer *bw, Entity *e0, Entity *e1);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Decode
|
||||||
|
|
||||||
void DecodeEntity(BB_Reader *br, Entity *e);
|
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 &&
|
result = e0 != e1 &&
|
||||||
!EqId(e0->top, e1->top) &&
|
!EqId(e0->top, e1->top) &&
|
||||||
!(HasProp(e0, Prop_Wall) && HasProp(e1, Prop_Wall));
|
!(HasProp(e0, Prop_Wall) && HasProp(e1, Prop_Wall));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration)
|
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);
|
Entity *root = EntityFromId(ss, RootEntityId);
|
||||||
u64 tick = ss->tick;
|
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];
|
Entity *check0 = &ss->ents[check0_index];
|
||||||
if (!IsValidAndActive(check0)) continue;
|
if (!IsValidAndActive(check0)) continue;
|
||||||
if (!(HasProp(check0, Prop_Solid) || HasProp(check0, Prop_Sensor))) 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);
|
SpaceIter iter = space_iter_begin_aabb(space, aabb);
|
||||||
SpaceEntry *space_entry;
|
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);
|
Entity *check1 = EntityFromId(ss, space_entry->ent);
|
||||||
if (!IsValidAndActive(check1)) continue;
|
if (!IsValidAndActive(check1)) continue;
|
||||||
if (!(HasProp(check1, Prop_Solid) || HasProp(check1, Prop_Sensor))) 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;
|
Xform e1_xf;
|
||||||
CLD_Shape e0_collider;
|
CLD_Shape e0_collider;
|
||||||
CLD_Shape e1_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;
|
e0 = check0;
|
||||||
e1 = check1;
|
e1 = check1;
|
||||||
e0_xf = check0_xf;
|
e0_xf = check0_xf;
|
||||||
e1_xf = XformFromEntity(check1);
|
e1_xf = XformFromEntity(check1);
|
||||||
e0_collider = check0_collider;
|
e0_collider = check0_collider;
|
||||||
e1_collider = check1->local_collider;
|
e1_collider = check1->local_collider;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
e0 = check1;
|
e0 = check1;
|
||||||
e1 = check0;
|
e1 = check0;
|
||||||
e0_xf = XformFromEntity(check1);
|
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);
|
EntityId constraint_id = ContactConstraintIdFromContactingIds(local_player, e0->id, e1->id);
|
||||||
Entity *constraint_ent = EntityFromId(ss, constraint_id);
|
Entity *constraint_ent = EntityFromId(ss, constraint_id);
|
||||||
|
|
||||||
if (constraint_ent->valid) {
|
if (constraint_ent->valid)
|
||||||
if (constraint_ent->contact_constraint_data.last_phys_iteration >= phys_iteration) {
|
{
|
||||||
|
if (constraint_ent->contact_constraint_data.last_phys_iteration >= phys_iteration)
|
||||||
|
{
|
||||||
/* Already processed constraint this iteration */
|
/* Already processed constraint this iteration */
|
||||||
continue;
|
continue;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
constraint_ent->contact_constraint_data.last_phys_iteration = phys_iteration;
|
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);
|
StaticAssert(countof(collision_result.points) == 2);
|
||||||
|
|
||||||
ContactConstraint *constraint = 0;
|
ContactConstraint *constraint = 0;
|
||||||
if (collision_result.num_points > 0) {
|
if (collision_result.num_points > 0)
|
||||||
|
{
|
||||||
b32 is_start = 0;
|
b32 is_start = 0;
|
||||||
if (!constraint_ent->valid) {
|
if (!constraint_ent->valid)
|
||||||
|
{
|
||||||
is_start = 1;
|
is_start = 1;
|
||||||
/* Create constraint */
|
/* Create constraint */
|
||||||
constraint_ent = AcquireLocalWithId(root, constraint_id);
|
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);
|
constraint->friction = SqrtF32(e0->friction * e1->friction);
|
||||||
|
|
||||||
/* Delete old contacts that are no longer present */
|
/* 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];
|
ContactPoint *old = &constraint->points[i];
|
||||||
u32 id = old->id;
|
u32 id = old->id;
|
||||||
b32 found = 0;
|
b32 found = 0;
|
||||||
for (u32 j = 0; j < collision_result.num_points; ++j) {
|
for (u32 j = 0; j < collision_result.num_points; ++j)
|
||||||
if (collision_result.points[j].id == id) {
|
{
|
||||||
|
if (collision_result.points[j].id == id)
|
||||||
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found)
|
||||||
|
{
|
||||||
/* Delete contact by replacing with last in array */
|
/* Delete contact by replacing with last in array */
|
||||||
*old = constraint->points[--constraint->num_points];
|
*old = constraint->points[--constraint->num_points];
|
||||||
--i;
|
--i;
|
||||||
@ -124,21 +139,25 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update / insert returned contacts */
|
/* 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];
|
CLD_CollisionPoint *res_point = &collision_result.points[i];
|
||||||
Vec2 point = res_point->point;
|
Vec2 point = res_point->point;
|
||||||
f32 sep = res_point->separation;
|
f32 sep = res_point->separation;
|
||||||
u32 id = res_point->id;
|
u32 id = res_point->id;
|
||||||
ContactPoint *contact = 0;
|
ContactPoint *contact = 0;
|
||||||
/* Match */
|
/* Match */
|
||||||
for (u32 j = 0; j < constraint->num_points; ++j) {
|
for (u32 j = 0; j < constraint->num_points; ++j)
|
||||||
|
{
|
||||||
ContactPoint *t = &constraint->points[j];
|
ContactPoint *t = &constraint->points[j];
|
||||||
if (t->id == id) {
|
if (t->id == id)
|
||||||
|
{
|
||||||
contact = t;
|
contact = t;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!contact) {
|
if (!contact)
|
||||||
|
{
|
||||||
/* Insert */
|
/* Insert */
|
||||||
contact = &constraint->points[constraint->num_points++];
|
contact = &constraint->points[constraint->num_points++];
|
||||||
ZeroStruct(contact);
|
ZeroStruct(contact);
|
||||||
@ -163,17 +182,20 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio
|
|||||||
Vec2 dir1 = e1->collision_dir;
|
Vec2 dir1 = e1->collision_dir;
|
||||||
f32 threshold = 0.5;
|
f32 threshold = 0.5;
|
||||||
b32 is_wrong_dir = 0;
|
b32 is_wrong_dir = 0;
|
||||||
if (!IsVec2Zero(dir0)) {
|
if (!IsVec2Zero(dir0))
|
||||||
|
{
|
||||||
is_wrong_dir = DotVec2(dir0, normal) <= threshold;
|
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;
|
is_wrong_dir = DotVec2(dir1, NegVec2(normal)) <= threshold;
|
||||||
}
|
}
|
||||||
constraint->wrong_dir = is_wrong_dir;
|
constraint->wrong_dir = is_wrong_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run collision callback */
|
/* Run collision callback */
|
||||||
if (collision_callback) {
|
if (collision_callback)
|
||||||
|
{
|
||||||
CollisionData data = ZI;
|
CollisionData data = ZI;
|
||||||
data.e0 = e0->id;
|
data.e0 = e0->id;
|
||||||
data.e1 = e1->id;
|
data.e1 = e1->id;
|
||||||
@ -183,7 +205,8 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio
|
|||||||
|
|
||||||
/* Calculate point */
|
/* Calculate point */
|
||||||
Vec2 midpoint = collision_result.points[0].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));
|
midpoint = AddVec2(midpoint, MulVec2(SubVec2(collision_result.points[1].point, midpoint), 0.5f));
|
||||||
}
|
}
|
||||||
data.point = midpoint;
|
data.point = midpoint;
|
||||||
@ -213,11 +236,14 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio
|
|||||||
/* Run callback twice for both e0 & e1 */
|
/* Run callback twice for both e0 & e1 */
|
||||||
b32 skip_solve0 = collision_callback(&data, sim_step_ctx);
|
b32 skip_solve0 = collision_callback(&data, sim_step_ctx);
|
||||||
b32 skip_solve1 = collision_callback(&data_inverted, 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;
|
constraint->skip_solve = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (constraint_ent->valid) {
|
}
|
||||||
|
else if (constraint_ent->valid)
|
||||||
|
{
|
||||||
constraint_ent->contact_constraint_data.num_points = 0;
|
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);
|
EntityId dbg_ent_id = CollisionDebugIdFromIds(local_player, e0->id, e1->id);
|
||||||
Entity *dbg_ent = EntityFromId(ss, dbg_ent_id);
|
Entity *dbg_ent = EntityFromId(ss, dbg_ent_id);
|
||||||
if (!dbg_ent->valid) {
|
if (!dbg_ent->valid)
|
||||||
|
{
|
||||||
/* FIXME: Entity never released */
|
/* FIXME: Entity never released */
|
||||||
dbg_ent = AcquireLocalWithId(root, dbg_ent_id);
|
dbg_ent = AcquireLocalWithId(root, dbg_ent_id);
|
||||||
EnableProp(dbg_ent, Prop_CollisionDebug);
|
EnableProp(dbg_ent, Prop_CollisionDebug);
|
||||||
@ -238,10 +265,13 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio
|
|||||||
dbg->e1 = e1->id;
|
dbg->e1 = e1->id;
|
||||||
dbg->collision_result = collision_result;
|
dbg->collision_result = collision_result;
|
||||||
|
|
||||||
if (constraint) {
|
if (constraint)
|
||||||
|
{
|
||||||
CopyBytes(dbg->points, constraint->points, sizeof(dbg->points));
|
CopyBytes(dbg->points, constraint->points, sizeof(dbg->points));
|
||||||
dbg->num_points = constraint->num_points;
|
dbg->num_points = constraint->num_points;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
dbg->num_points = 0;
|
dbg->num_points = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +296,8 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration)
|
|||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *constraint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(constraint_ent)) continue;
|
if (!ShouldSimulate(constraint_ent)) continue;
|
||||||
if (!HasProp(constraint_ent, Prop_ContactConstraint)) 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;
|
u32 num_points = constraint->num_points;
|
||||||
Entity *e0 = EntityFromId(ss, constraint->e0);
|
Entity *e0 = EntityFromId(ss, constraint->e0);
|
||||||
Entity *e1 = EntityFromId(ss, constraint->e1);
|
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 normal = constraint->normal;
|
||||||
Vec2 tangent = PerpVec2(normal);
|
Vec2 tangent = PerpVec2(normal);
|
||||||
|
|
||||||
@ -291,14 +323,16 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration)
|
|||||||
f32 inv_i1 = 0;
|
f32 inv_i1 = 0;
|
||||||
{
|
{
|
||||||
/* If not simulated locally or ent is not dynamic, pretend contact mass is infinite */
|
/* 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 scale = AbsF32(DeterminantFromXform(e0_xf));
|
||||||
f32 scaled_mass = e0->mass_unscaled * scale;
|
f32 scaled_mass = e0->mass_unscaled * scale;
|
||||||
f32 scaled_inertia = e0->inertia_unscaled * scale;
|
f32 scaled_inertia = e0->inertia_unscaled * scale;
|
||||||
inv_m0 = 1.f / scaled_mass;
|
inv_m0 = 1.f / scaled_mass;
|
||||||
inv_i0 = 1.f / scaled_inertia;
|
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 scale = AbsF32(DeterminantFromXform(e1_xf));
|
||||||
f32 scaled_mass = e1->mass_unscaled * scale;
|
f32 scaled_mass = e1->mass_unscaled * scale;
|
||||||
f32 scaled_inertia = e1->inertia_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;
|
constraint->inv_i1 = inv_i1;
|
||||||
|
|
||||||
/* Update / insert returned contacts */
|
/* 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];
|
ContactPoint *contact = &constraint->points[i];
|
||||||
Vec2 vcp0 = contact->vcp0;
|
Vec2 vcp0 = contact->vcp0;
|
||||||
Vec2 vcp1 = contact->vcp1;
|
Vec2 vcp1 = contact->vcp1;
|
||||||
@ -339,7 +374,9 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration)
|
|||||||
contact->tangent_impulse = 0;
|
contact->tangent_impulse = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Mark constraint for removal */
|
/* Mark constraint for removal */
|
||||||
constraint_ent->contact_constraint_data.num_points = 0;
|
constraint_ent->contact_constraint_data.num_points = 0;
|
||||||
DisableProp(constraint_ent, Prop_Active);
|
DisableProp(constraint_ent, Prop_Active);
|
||||||
@ -350,7 +387,8 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration)
|
|||||||
#if 0
|
#if 0
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
/* Remove collision debug ents */
|
/* 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];
|
Entity *dbg_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(dbg_ent)) continue;
|
if (!ShouldSimulate(dbg_ent)) continue;
|
||||||
if (!HasProp(dbg_ent, Prop_CollisionDebug)) continue;
|
if (!HasProp(dbg_ent, Prop_CollisionDebug)) continue;
|
||||||
@ -361,7 +399,8 @@ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration)
|
|||||||
|
|
||||||
if (!(ShouldSimulate(e0) && ShouldSimulate(e1)) ||
|
if (!(ShouldSimulate(e0) && ShouldSimulate(e1)) ||
|
||||||
!(HasProp(e0, Prop_Solid) || HasProp(e0, Prop_Sensor)) ||
|
!(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 */
|
/* Mark dbg ent for removal */
|
||||||
DisableProp(dbg_ent, Prop_Active);
|
DisableProp(dbg_ent, Prop_Active);
|
||||||
EnableProp(dbg_ent, Prop_Release);
|
EnableProp(dbg_ent, Prop_Release);
|
||||||
@ -375,7 +414,8 @@ void WarmStartContacts(PhysStepCtx *ctx)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *constraint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(constraint_ent)) continue;
|
if (!ShouldSimulate(constraint_ent)) continue;
|
||||||
if (!HasProp(constraint_ent, Prop_ContactConstraint)) continue;
|
if (!HasProp(constraint_ent, Prop_ContactConstraint)) continue;
|
||||||
@ -386,7 +426,8 @@ void WarmStartContacts(PhysStepCtx *ctx)
|
|||||||
Entity *e0 = EntityFromId(ss, constraint->e0);
|
Entity *e0 = EntityFromId(ss, constraint->e0);
|
||||||
Entity *e1 = EntityFromId(ss, constraint->e1);
|
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_m0 = constraint->inv_m0;
|
||||||
f32 inv_m1 = constraint->inv_m1;
|
f32 inv_m1 = constraint->inv_m1;
|
||||||
f32 inv_i0 = constraint->inv_i0;
|
f32 inv_i0 = constraint->inv_i0;
|
||||||
@ -401,7 +442,8 @@ void WarmStartContacts(PhysStepCtx *ctx)
|
|||||||
Vec2 normal = constraint->normal;
|
Vec2 normal = constraint->normal;
|
||||||
Vec2 tangent = PerpVec2(normal);
|
Vec2 tangent = PerpVec2(normal);
|
||||||
f32 inv_num_points = 1.f / num_points;
|
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];
|
ContactPoint *point = &constraint->points[i];
|
||||||
Vec2 vcp0 = point->vcp0;
|
Vec2 vcp0 = point->vcp0;
|
||||||
Vec2 vcp1 = point->vcp1;
|
Vec2 vcp1 = point->vcp1;
|
||||||
@ -427,7 +469,8 @@ void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *constraint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(constraint_ent)) continue;
|
if (!ShouldSimulate(constraint_ent)) continue;
|
||||||
if (!HasProp(constraint_ent, Prop_ContactConstraint)) 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;
|
f32 w1 = e1->angular_velocity;
|
||||||
|
|
||||||
u32 num_points = constraint->num_points;
|
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 e0_xf = XformFromEntity(e0);
|
||||||
Xform e1_xf = XformFromEntity(e1);
|
Xform e1_xf = XformFromEntity(e1);
|
||||||
|
|
||||||
@ -454,7 +498,8 @@ void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
|
|||||||
|
|
||||||
/* Normal impulse */
|
/* Normal impulse */
|
||||||
Vec2 normal = constraint->normal;
|
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];
|
ContactPoint *point = &constraint->points[point_index];
|
||||||
Vec2 vcp0 = point->vcp0;
|
Vec2 vcp0 = point->vcp0;
|
||||||
Vec2 vcp1 = point->vcp1;
|
Vec2 vcp1 = point->vcp1;
|
||||||
@ -468,10 +513,13 @@ void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
|
|||||||
f32 mass_scale = 1.0f;
|
f32 mass_scale = 1.0f;
|
||||||
f32 impulse_scale = 0.0f;
|
f32 impulse_scale = 0.0f;
|
||||||
|
|
||||||
if (separation > 0.0f) {
|
if (separation > 0.0f)
|
||||||
|
{
|
||||||
/* Speculative */
|
/* Speculative */
|
||||||
velocity_bias = separation / dt;
|
velocity_bias = separation / dt;
|
||||||
} else if (apply_bias) {
|
}
|
||||||
|
else if (apply_bias)
|
||||||
|
{
|
||||||
/* Soft constraint */
|
/* Soft constraint */
|
||||||
SoftSpring softness = MakeSpring(ContactSpringHz, ContactSpringDamp, dt);
|
SoftSpring softness = MakeSpring(ContactSpringHz, ContactSpringDamp, dt);
|
||||||
f32 pushout_velocity = constraint->pushout_velocity;
|
f32 pushout_velocity = constraint->pushout_velocity;
|
||||||
@ -504,7 +552,8 @@ void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
|
|||||||
|
|
||||||
/* Tangent impulse */
|
/* Tangent impulse */
|
||||||
Vec2 tangent = PerpVec2(normal);
|
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];
|
ContactPoint *point = &constraint->points[point_index];
|
||||||
Vec2 vcp0 = point->vcp0;
|
Vec2 vcp0 = point->vcp0;
|
||||||
Vec2 vcp1 = point->vcp1;
|
Vec2 vcp1 = point->vcp1;
|
||||||
@ -564,7 +613,8 @@ void PrepareMotorJoints(PhysStepCtx *ctx)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(joint_ent)) continue;
|
if (!ShouldSimulate(joint_ent)) continue;
|
||||||
if (!HasProp(joint_ent, Prop_MotorJoint)) continue;
|
if (!HasProp(joint_ent, Prop_MotorJoint)) continue;
|
||||||
@ -574,7 +624,8 @@ void PrepareMotorJoints(PhysStepCtx *ctx)
|
|||||||
Entity *e0 = EntityFromId(ss, joint->e0);
|
Entity *e0 = EntityFromId(ss, joint->e0);
|
||||||
Entity *e1 = EntityFromId(ss, joint->e1);
|
Entity *e1 = EntityFromId(ss, joint->e1);
|
||||||
|
|
||||||
if (ShouldSimulate(e0) && ShouldSimulate(e1)) {
|
if (ShouldSimulate(e0) && ShouldSimulate(e1))
|
||||||
|
{
|
||||||
Xform e0_xf = XformFromEntity(e0);
|
Xform e0_xf = XformFromEntity(e0);
|
||||||
Xform e1_xf = XformFromEntity(e1);
|
Xform e1_xf = XformFromEntity(e1);
|
||||||
|
|
||||||
@ -616,7 +667,9 @@ void PrepareMotorJoints(PhysStepCtx *ctx)
|
|||||||
joint->linear_impulse = VEC2(0, 0);
|
joint->linear_impulse = VEC2(0, 0);
|
||||||
joint->angular_impulse = 0;
|
joint->angular_impulse = 0;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Mark joint for removal */
|
/* Mark joint for removal */
|
||||||
DisableProp(joint_ent, Prop_Active);
|
DisableProp(joint_ent, Prop_Active);
|
||||||
EnableProp(joint_ent, Prop_Release);
|
EnableProp(joint_ent, Prop_Release);
|
||||||
@ -628,7 +681,8 @@ void WarmStartMotorJoints(PhysStepCtx *ctx)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(joint_ent)) continue;
|
if (!ShouldSimulate(joint_ent)) continue;
|
||||||
if (!HasProp(joint_ent, Prop_MotorJoint)) continue;
|
if (!HasProp(joint_ent, Prop_MotorJoint)) continue;
|
||||||
@ -660,7 +714,8 @@ void SolveMotorJoints(PhysStepCtx *ctx, f32 dt)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(joint_ent)) continue;
|
if (!ShouldSimulate(joint_ent)) continue;
|
||||||
if (!HasProp(joint_ent, Prop_MotorJoint)) continue;
|
if (!HasProp(joint_ent, Prop_MotorJoint)) continue;
|
||||||
@ -765,14 +820,16 @@ void PrepareMouseJoints(PhysStepCtx *ctx)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(joint_ent)) continue;
|
if (!ShouldSimulate(joint_ent)) continue;
|
||||||
if (!HasProp(joint_ent, Prop_MouseJoint)) continue;
|
if (!HasProp(joint_ent, Prop_MouseJoint)) continue;
|
||||||
|
|
||||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||||
Entity *ent = EntityFromId(ss, joint->target);
|
Entity *ent = EntityFromId(ss, joint->target);
|
||||||
if (ShouldSimulate(ent)) {
|
if (ShouldSimulate(ent))
|
||||||
|
{
|
||||||
Xform xf = XformFromEntity(ent);
|
Xform xf = XformFromEntity(ent);
|
||||||
|
|
||||||
/* TODO: Cache this */
|
/* TODO: Cache this */
|
||||||
@ -800,7 +857,9 @@ void PrepareMouseJoints(PhysStepCtx *ctx)
|
|||||||
joint->linear_impulse = VEC2(0, 0);
|
joint->linear_impulse = VEC2(0, 0);
|
||||||
joint->angular_impulse = 0;
|
joint->angular_impulse = 0;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Mark joint for removal */
|
/* Mark joint for removal */
|
||||||
DisableProp(joint_ent, Prop_Active);
|
DisableProp(joint_ent, Prop_Active);
|
||||||
EnableProp(joint_ent, Prop_Release);
|
EnableProp(joint_ent, Prop_Release);
|
||||||
@ -812,14 +871,16 @@ void WarmStartMouseJoints(PhysStepCtx *ctx)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(joint_ent)) continue;
|
if (!ShouldSimulate(joint_ent)) continue;
|
||||||
if (!HasProp(joint_ent, Prop_MouseJoint)) continue;
|
if (!HasProp(joint_ent, Prop_MouseJoint)) continue;
|
||||||
|
|
||||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||||
Entity *ent = EntityFromId(ss, joint->target);
|
Entity *ent = EntityFromId(ss, joint->target);
|
||||||
if (ShouldSimulate(ent)) {
|
if (ShouldSimulate(ent))
|
||||||
|
{
|
||||||
f32 inv_m = joint->inv_m;
|
f32 inv_m = joint->inv_m;
|
||||||
f32 inv_i = joint->inv_i;
|
f32 inv_i = joint->inv_i;
|
||||||
Xform xf = XformFromEntity(ent);
|
Xform xf = XformFromEntity(ent);
|
||||||
@ -834,14 +895,16 @@ void SolveMouseJoints(PhysStepCtx *ctx, f32 dt)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(joint_ent)) continue;
|
if (!ShouldSimulate(joint_ent)) continue;
|
||||||
if (!HasProp(joint_ent, Prop_MouseJoint)) continue;
|
if (!HasProp(joint_ent, Prop_MouseJoint)) continue;
|
||||||
|
|
||||||
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
MouseJoint *joint = &joint_ent->mouse_joint_data;
|
||||||
Entity *ent = EntityFromId(ss, joint->target);
|
Entity *ent = EntityFromId(ss, joint->target);
|
||||||
if (ShouldSimulate(ent)) {
|
if (ShouldSimulate(ent))
|
||||||
|
{
|
||||||
Vec2 v = ent->linear_velocity;
|
Vec2 v = ent->linear_velocity;
|
||||||
f32 w = ent->angular_velocity;
|
f32 w = ent->angular_velocity;
|
||||||
|
|
||||||
@ -929,7 +992,8 @@ void PrepareWeldJoints(PhysStepCtx *ctx)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(joint_ent)) continue;
|
if (!ShouldSimulate(joint_ent)) continue;
|
||||||
if (!HasProp(joint_ent, Prop_WeldJoint)) continue;
|
if (!HasProp(joint_ent, Prop_WeldJoint)) continue;
|
||||||
@ -939,7 +1003,8 @@ void PrepareWeldJoints(PhysStepCtx *ctx)
|
|||||||
WeldJoint *joint = &joint_ent->weld_joint_data;
|
WeldJoint *joint = &joint_ent->weld_joint_data;
|
||||||
Entity *e0 = EntityFromId(ss, joint->e0);
|
Entity *e0 = EntityFromId(ss, joint->e0);
|
||||||
Entity *e1 = EntityFromId(ss, joint->e1);
|
Entity *e1 = EntityFromId(ss, joint->e1);
|
||||||
if (ShouldSimulate(e0) && ShouldSimulate(e1)) {
|
if (ShouldSimulate(e0) && ShouldSimulate(e1))
|
||||||
|
{
|
||||||
Xform e0_xf = XformFromEntity(e0);
|
Xform e0_xf = XformFromEntity(e0);
|
||||||
Xform e1_xf = XformFromEntity(e1);
|
Xform e1_xf = XformFromEntity(e1);
|
||||||
|
|
||||||
@ -966,7 +1031,9 @@ void PrepareWeldJoints(PhysStepCtx *ctx)
|
|||||||
joint->angular_impulse0 = 0;
|
joint->angular_impulse0 = 0;
|
||||||
joint->angular_impulse1 = 0;
|
joint->angular_impulse1 = 0;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Mark joint for removal */
|
/* Mark joint for removal */
|
||||||
DisableProp(joint_ent, Prop_Active);
|
DisableProp(joint_ent, Prop_Active);
|
||||||
EnableProp(joint_ent, Prop_Release);
|
EnableProp(joint_ent, Prop_Release);
|
||||||
@ -978,7 +1045,8 @@ void WarmStartWeldJoints(PhysStepCtx *ctx)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(joint_ent)) continue;
|
if (!ShouldSimulate(joint_ent)) continue;
|
||||||
if (!HasProp(joint_ent, Prop_WeldJoint)) continue;
|
if (!HasProp(joint_ent, Prop_WeldJoint)) continue;
|
||||||
@ -987,7 +1055,8 @@ void WarmStartWeldJoints(PhysStepCtx *ctx)
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
Entity *e0 = EntityFromId(ss, joint->e0);
|
Entity *e0 = EntityFromId(ss, joint->e0);
|
||||||
if (ShouldSimulate(e0)) {
|
if (ShouldSimulate(e0))
|
||||||
|
{
|
||||||
f32 inv_m = joint->inv_m0;
|
f32 inv_m = joint->inv_m0;
|
||||||
f32 inv_i = joint->inv_i0;
|
f32 inv_i = joint->inv_i0;
|
||||||
Xform xf = XformFromEntity(e1);
|
Xform xf = XformFromEntity(e1);
|
||||||
@ -999,7 +1068,8 @@ void WarmStartWeldJoints(PhysStepCtx *ctx)
|
|||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
Entity *e1 = EntityFromId(ss, joint->e1);
|
Entity *e1 = EntityFromId(ss, joint->e1);
|
||||||
if (ShouldSimulate(e1)) {
|
if (ShouldSimulate(e1))
|
||||||
|
{
|
||||||
f32 inv_m = joint->inv_m1;
|
f32 inv_m = joint->inv_m1;
|
||||||
f32 inv_i = joint->inv_i1;
|
f32 inv_i = joint->inv_i1;
|
||||||
SetLinearVelocity(e1, AddVec2(e1->linear_velocity, MulVec2(joint->linear_impulse1, inv_m)));
|
SetLinearVelocity(e1, AddVec2(e1->linear_velocity, MulVec2(joint->linear_impulse1, inv_m)));
|
||||||
@ -1015,7 +1085,8 @@ void SolveWeldJoints(PhysStepCtx *ctx, f32 dt)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *joint_ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(joint_ent)) continue;
|
if (!ShouldSimulate(joint_ent)) continue;
|
||||||
if (!HasProp(joint_ent, Prop_WeldJoint)) 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;
|
WeldJoint *joint = &joint_ent->weld_joint_data;
|
||||||
Entity *e0 = EntityFromId(ss, joint->e0);
|
Entity *e0 = EntityFromId(ss, joint->e0);
|
||||||
Entity *e1 = EntityFromId(ss, joint->e1);
|
Entity *e1 = EntityFromId(ss, joint->e1);
|
||||||
if (ShouldSimulate(e0) && ShouldSimulate(e1)) {
|
if (ShouldSimulate(e0) && ShouldSimulate(e1))
|
||||||
|
{
|
||||||
Xform xf0 = XformFromEntity(e0);
|
Xform xf0 = XformFromEntity(e0);
|
||||||
Xform xf1 = XformFromEntity(e1);
|
Xform xf1 = XformFromEntity(e1);
|
||||||
|
|
||||||
@ -1094,20 +1166,23 @@ void IntegrateForces(PhysStepCtx *ctx, f32 dt)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(ent)) continue;
|
if (!ShouldSimulate(ent)) continue;
|
||||||
|
|
||||||
b32 is_dynamic = HasProp(ent, Prop_Dynamic);
|
b32 is_dynamic = HasProp(ent, Prop_Dynamic);
|
||||||
b32 is_kinematic = HasProp(ent, Prop_Kinematic);
|
b32 is_kinematic = HasProp(ent, Prop_Kinematic);
|
||||||
if (is_dynamic || is_kinematic) {
|
if (is_dynamic || is_kinematic)
|
||||||
|
{
|
||||||
Vec2 linear_velocity = ent->linear_velocity;
|
Vec2 linear_velocity = ent->linear_velocity;
|
||||||
f32 angular_velocity = ent->angular_velocity;
|
f32 angular_velocity = ent->angular_velocity;
|
||||||
f32 linear_damping_factor = MaxF32(1.0f - (ent->linear_damping * dt), 0);
|
f32 linear_damping_factor = MaxF32(1.0f - (ent->linear_damping * dt), 0);
|
||||||
f32 angular_damping_factor = MaxF32(1.0f - (ent->angular_damping * dt), 0);
|
f32 angular_damping_factor = MaxF32(1.0f - (ent->angular_damping * dt), 0);
|
||||||
|
|
||||||
/* Integrate forces */
|
/* Integrate forces */
|
||||||
if (is_dynamic) {
|
if (is_dynamic)
|
||||||
|
{
|
||||||
Xform xf = XformFromEntity(ent);
|
Xform xf = XformFromEntity(ent);
|
||||||
f32 det_abs = AbsF32(DeterminantFromXform(xf));
|
f32 det_abs = AbsF32(DeterminantFromXform(xf));
|
||||||
f32 mass = ent->mass_unscaled * det_abs;
|
f32 mass = ent->mass_unscaled * det_abs;
|
||||||
@ -1136,7 +1211,8 @@ void IntegrateVelocities(PhysStepCtx *ctx, f32 dt)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
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];
|
Entity *ent = &ss->ents[sim_ent_index];
|
||||||
if (!ShouldSimulate(ent)) continue;
|
if (!ShouldSimulate(ent)) continue;
|
||||||
if (!HasProp(ent, Prop_Dynamic) && !HasProp(ent, Prop_Kinematic)) 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;
|
Space *space = ctx->sim_step_ctx->accel->space;
|
||||||
f32 smallest_t = 1;
|
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];
|
Entity *e0 = &ss->ents[e0_index];
|
||||||
if (!ShouldSimulate(e0)) continue;
|
if (!ShouldSimulate(e0)) continue;
|
||||||
if (!(HasProp(e0, Prop_Solid) || HasProp(e0, Prop_Sensor))) 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);
|
SpaceIter iter = space_iter_begin_aabb(space, combined_aabb);
|
||||||
SpaceEntry *entry;
|
SpaceEntry *entry;
|
||||||
while ((entry = space_iter_next(&iter)) != 0) {
|
while ((entry = space_iter_next(&iter)) != 0)
|
||||||
|
{
|
||||||
Entity *e1 = EntityFromId(ss, entry->ent);
|
Entity *e1 = EntityFromId(ss, entry->ent);
|
||||||
if (!ShouldSimulate(e1)) continue;
|
if (!ShouldSimulate(e1)) continue;
|
||||||
if (!(HasProp(e1, Prop_Solid) || HasProp(e1, Prop_Sensor))) 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);
|
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);
|
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;
|
smallest_t = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1204,13 +1283,16 @@ void UpdateAabbs(PhysStepCtx *ctx)
|
|||||||
__prof;
|
__prof;
|
||||||
Snapshot *ss = ctx->sim_step_ctx->world;
|
Snapshot *ss = ctx->sim_step_ctx->world;
|
||||||
Space *space = ctx->sim_step_ctx->accel->space;
|
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];
|
Entity *ent = &ss->ents[sim_ent_index];
|
||||||
if (!IsValidAndActive(ent)) continue;
|
if (!IsValidAndActive(ent)) continue;
|
||||||
if (ent->local_collider.count > 0) {
|
if (ent->local_collider.count > 0)
|
||||||
|
{
|
||||||
Xform xf = XformFromEntity(ent);
|
Xform xf = XformFromEntity(ent);
|
||||||
SpaceEntry *space_entry = space_entry_from_handle(space, ent->space_handle);
|
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);
|
space_entry = space_entry_acquire(space, ent->id);
|
||||||
ent->space_handle = space_entry->handle;
|
ent->space_handle = space_entry->handle;
|
||||||
}
|
}
|
||||||
@ -1234,7 +1316,8 @@ void StepPhys(PhysStepCtx *ctx, f32 timestep)
|
|||||||
UpdateAabbs(ctx);
|
UpdateAabbs(ctx);
|
||||||
|
|
||||||
f32 remaining_dt = timestep;
|
f32 remaining_dt = timestep;
|
||||||
while (remaining_dt > 0) {
|
while (remaining_dt > 0)
|
||||||
|
{
|
||||||
__profn("Step part");
|
__profn("Step part");
|
||||||
++phys_iteration;
|
++phys_iteration;
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
@ -1262,7 +1345,8 @@ void StepPhys(PhysStepCtx *ctx, f32 timestep)
|
|||||||
PrepareWeldJoints(ctx);
|
PrepareWeldJoints(ctx);
|
||||||
|
|
||||||
f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS;
|
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");
|
__profn("Substep");
|
||||||
|
|
||||||
/* Warm start */
|
/* 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 */
|
Struct(EntityId)
|
||||||
#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) {
|
|
||||||
Uid uid;
|
Uid uid;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ClientHandle) {
|
Struct(ClientHandle)
|
||||||
|
{
|
||||||
u32 idx;
|
u32 idx;
|
||||||
u32 gen;
|
u32 gen;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ========================== *
|
#define SIM_CLIENT_NIL_HANDLE ((ClientHandle) { .gen = 0, .idx = 0 })
|
||||||
* Startup
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
void StartupSim(void);
|
|
||||||
|
|
||||||
/* ========================== *
|
////////////////////////////////
|
||||||
* Client store
|
//~ Client store types
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
Struct(ClientLookupBin) {
|
Struct(ClientLookupBin)
|
||||||
|
{
|
||||||
struct ClientHandle first;
|
struct ClientHandle first;
|
||||||
struct ClientHandle last;
|
struct ClientHandle last;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ClientStore) {
|
Struct(ClientStore)
|
||||||
|
{
|
||||||
b32 valid;
|
b32 valid;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
@ -57,19 +47,17 @@ Inline ClientStore *sim_client_store_nil(void)
|
|||||||
return *_g_sim_client_store_nil;
|
return *_g_sim_client_store_nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientStore *sim_client_store_acquire(void);
|
////////////////////////////////
|
||||||
void sim_client_store_release(ClientStore *store);
|
//~ Client types
|
||||||
|
|
||||||
/* ========================== *
|
Struct(SnapshotLookupBin)
|
||||||
* Client
|
{
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
Struct(SnapshotLookupBin) {
|
|
||||||
struct Snapshot *first;
|
struct Snapshot *first;
|
||||||
struct Snapshot *last;
|
struct Snapshot *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(Client) {
|
Struct(Client)
|
||||||
|
{
|
||||||
b32 valid;
|
b32 valid;
|
||||||
ClientHandle handle;
|
ClientHandle handle;
|
||||||
ClientStore *store;
|
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;
|
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);
|
/* Absolute layers */
|
||||||
void sim_client_set_channel_id(Client *client, N_ChannelId channel_id);
|
#define SIM_LAYER_FLOOR_DECALS (-300)
|
||||||
Client *sim_client_from_handle(ClientStore *store, ClientHandle handle);
|
#define SIM_LAYER_BULLETS (-200)
|
||||||
|
#define SIM_LAYER_TRACERS (-100)
|
||||||
|
#define SIM_LAYER_SHOULDERS (0)
|
||||||
|
#define SIM_LAYER_WALLS (100)
|
||||||
|
|
||||||
/* ========================== *
|
/* Relative layers */
|
||||||
* Snapshot
|
#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 = 1 << 0,
|
||||||
SIM_CONTROL_FLAG_FIRE_ALT = 1 << 1,
|
SIM_CONTROL_FLAG_FIRE_ALT = 1 << 1,
|
||||||
|
|
||||||
@ -155,22 +146,27 @@ typedef i32 ControlFlag; enum {
|
|||||||
SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 12,
|
SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 12,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ControlData) {
|
Struct(ControlData)
|
||||||
|
{
|
||||||
Vec2 move; /* Movement direction vector (speed of 0 -> 1) */
|
Vec2 move; /* Movement direction vector (speed of 0 -> 1) */
|
||||||
Vec2 focus; /* Focus direction vector (where does the controller want to look) */
|
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) */
|
Vec2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */
|
||||||
ControlFlag flags;
|
ControlFlag flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef i32 CmdKind; enum {
|
typedef i32 CmdKind; enum
|
||||||
|
{
|
||||||
SIM_CMD_KIND_INVALID,
|
SIM_CMD_KIND_INVALID,
|
||||||
|
|
||||||
SIM_CMD_KIND_CONTROL,
|
SIM_CMD_KIND_CONTROL,
|
||||||
SIM_CMD_KIND_CHAT
|
SIM_CMD_KIND_CHAT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Tile types
|
||||||
|
|
||||||
typedef i32 TileKind; enum {
|
typedef i32 TileKind; enum
|
||||||
|
{
|
||||||
SIM_TILE_KIND_NONE,
|
SIM_TILE_KIND_NONE,
|
||||||
SIM_TILE_KIND_WALL,
|
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 */
|
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;
|
b32 valid;
|
||||||
u64 tick;
|
u64 tick;
|
||||||
Client *client;
|
Client *client;
|
||||||
@ -221,17 +226,77 @@ Inline Snapshot *sim_snapshot_nil(void)
|
|||||||
return *_g_sim_snapshot_nil;
|
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);
|
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);
|
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_tick(Client *client, u64 tick);
|
||||||
Snapshot *sim_snapshot_from_closest_tick_lte(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);
|
Snapshot *sim_snapshot_from_closest_tick_gte(Client *client, u64 tick);
|
||||||
|
|
||||||
/* Tile */
|
////////////////////////////////
|
||||||
|
//~ Tile operations
|
||||||
|
|
||||||
Vec2I32 sim_world_tile_index_from_pos(Vec2 pos);
|
Vec2I32 sim_world_tile_index_from_pos(Vec2 pos);
|
||||||
Vec2 sim_pos_from_world_tile_index(Vec2I32 world_tile_index);
|
Vec2 sim_pos_from_world_tile_index(Vec2I32 world_tile_index);
|
||||||
Vec2I32 sim_local_tile_index_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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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) */
|
/* 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. */
|
/* 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;
|
Space *space;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -13,7 +13,8 @@ struct SimAccel {
|
|||||||
//~ Step ctx
|
//~ Step ctx
|
||||||
|
|
||||||
typedef struct SimStepCtx SimStepCtx;
|
typedef struct SimStepCtx SimStepCtx;
|
||||||
struct SimStepCtx {
|
struct SimStepCtx
|
||||||
|
{
|
||||||
b32 is_master;
|
b32 is_master;
|
||||||
SimAccel *accel;
|
SimAccel *accel;
|
||||||
RandState rand; /* TODO: Replace with per-sim rand for deterministic rng */
|
RandState rand; /* TODO: Replace with per-sim rand for deterministic rng */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user