working wall collisions

This commit is contained in:
jacob 2026-02-09 17:16:09 -06:00
parent bf56bd7155
commit 09490d8c47
2 changed files with 191 additions and 622 deletions

View File

@ -1364,25 +1364,59 @@ P_Space P_SpaceFromFrame(Arena *arena, P_Frame *frame)
}
}
//- Debug draw walls
//- Push walls to space
for (GenWall *wall = first_wall; wall; wall = wall->next)
{
i64 wall_idx = 0;
for (GenWall *wall = first_wall; wall; wall = wall->next)
Vec2 p0 = VEC2(wall->start.x / P_TilesPerMeter - P_WorldPitch / 2, wall->start.y / P_TilesPerMeter - P_WorldPitch / 2);
Vec2 p1 = VEC2(wall->end.x / P_TilesPerMeter - P_WorldPitch / 2, wall->end.y / P_TilesPerMeter - P_WorldPitch / 2);
// P_Shape shape = P_ShapeFromDesc(.count = 2, .points = { p0, p1 });
P_Shape shape = P_ShapeFromDesc(.count = 2, .points = { p0, p1 }, .radius = 0.01 );
Rng2 aabb = P_BoundingBoxFromShape(shape);
aabb = AddRng2Vec2(aabb, VEC2(P_WorldPitch / 2.0, P_WorldPitch / 2.0));
aabb.p0 = FloorVec2(aabb.p0);
aabb.p1 = CeilVec2(aabb.p1);
aabb.p1.x = MaxF32(aabb.p1.x, aabb.p0.x + 1);
aabb.p1.y = MaxF32(aabb.p1.y, aabb.p0.y + 1);
aabb = IntersectRng2(aabb, space_aabb);
u64 id = P_WallShapeIDBasis ^ MixU64s(
((u64)wall->start.x << 0) | ((u64)wall->start.y << 32),
((u64)wall->end.x << 0) | ((u64)wall->end.y << 32)
);
for (i32 y = aabb.p0.y; y < aabb.p1.y; ++y)
{
Vec2 p0 = VEC2(wall->start.x / P_TilesPerMeter - P_WorldPitch / 2, wall->start.y / P_TilesPerMeter - P_WorldPitch / 2);
Vec2 p1 = VEC2(wall->end.x / P_TilesPerMeter - P_WorldPitch / 2, wall->end.y / P_TilesPerMeter - P_WorldPitch / 2);
u64 color_seed0 = MixU64(wall_idx + 1);
u64 color_seed1 = MixU64(color_seed0);
u64 color_seed2 = MixU64(color_seed1);
Vec4 color = Color_White;
color.r = Norm24(color_seed0) * 0.75 + 0.25;
color.g = Norm24(color_seed1) * 0.75 + 0.25;
color.b = Norm24(color_seed2) * 0.75 + 0.25;
P_DebugDrawLine(p0, p1, color);
++wall_idx;
for (i32 x = aabb.p0.x; x < aabb.p1.x; ++x)
{
i64 cell_idx = y * P_WorldPitch + x;
P_SpaceCell *cell = &space.cells[cell_idx];
P_SpaceEntry *entry = PushStruct(arena, P_SpaceEntry);
SllStackPush(cell->first, entry);
entry->shape = shape;
entry->shape_id = id;
}
}
++wall_idx;
// P_DebugDrawShape(shape, Color_Cyan);
}
//- Debug draw walls
// {
// i64 wall_idx = 0;
// for (GenWall *wall = first_wall; wall; wall = wall->next)
// {
// Vec2 p0 = VEC2(wall->start.x / P_TilesPerMeter - P_WorldPitch / 2, wall->start.y / P_TilesPerMeter - P_WorldPitch / 2);
// Vec2 p1 = VEC2(wall->end.x / P_TilesPerMeter - P_WorldPitch / 2, wall->end.y / P_TilesPerMeter - P_WorldPitch / 2);
// u64 color_seed0 = MixU64(wall_idx + 1);
// u64 color_seed1 = MixU64(color_seed0);
// u64 color_seed2 = MixU64(color_seed1);
// Vec4 color = Color_White;
// color.r = Norm24(color_seed0) * 0.75 + 0.25;
// color.g = Norm24(color_seed1) * 0.75 + 0.25;
// color.b = Norm24(color_seed2) * 0.75 + 0.25;
// P_DebugDrawLine(p0, p1, color);
// ++wall_idx;
// }
// ++wall_idx;
// }
}
@ -2047,175 +2081,172 @@ void P_StepFrame(P_Frame *frame)
// TODO: Not like this
if (!is_predicting)
for (P_Ent *ent0 = P_FirstEnt(frame); !P_IsEntNil(ent0); ent0 = P_NextEnt(ent0))
{
for (P_Ent *ent0 = P_FirstEnt(frame); !P_IsEntNil(ent0); ent0 = P_NextEnt(ent0))
if (ent0->is_guy)
{
if (ent0->is_guy)
P_Shape shape0 = P_WorldShapeFromEnt(ent0);
Rng2 aabb0 = P_BoundingBoxFromShape(shape0);
Rng2 query_rect = Zi;
query_rect.p0 = FloorVec2(aabb0.p0);
query_rect.p1 = CeilVec2(aabb0.p1);
query_rect.p1.x = MaxF32(query_rect.p1.x, query_rect.p0.x + 1);
query_rect.p1.y = MaxF32(query_rect.p1.y, query_rect.p0.y + 1);
for (i32 query_y = query_rect.p0.y; query_y < query_rect.p1.y; ++query_y)
{
P_Shape shape0 = P_WorldShapeFromEnt(ent0);
Rng2 aabb0 = P_BoundingBoxFromShape(shape0);
Rng2 query_rect = Zi;
query_rect.p0 = FloorVec2(aabb0.p0);
query_rect.p1 = CeilVec2(aabb0.p1);
query_rect.p1.x = MaxF32(query_rect.p1.x, query_rect.p0.x + 1);
query_rect.p1.y = MaxF32(query_rect.p1.y, query_rect.p0.y + 1);
for (i32 query_y = query_rect.p0.y; query_y < query_rect.p1.y; ++query_y)
for (i32 query_x = query_rect.p0.x; query_x < query_rect.p1.x; ++query_x)
{
for (i32 query_x = query_rect.p0.x; query_x < query_rect.p1.x; ++query_x)
P_SpaceCell cell = P_SpaceCellFromPos(&space, VEC2(query_x, query_y));
for (P_SpaceEntry *space_entry = cell.first; space_entry; space_entry = space_entry->next)
{
P_SpaceCell cell = P_SpaceCellFromPos(&space, VEC2(query_x, query_y));
for (P_SpaceEntry *space_entry = cell.first; space_entry; space_entry = space_entry->next)
Rng2 aabb1 = P_BoundingBoxFromShape(space_entry->shape);
P_Ent *ent1 = P_EntFromKey(frame, (P_EntKey) { .v = space_entry->shape_id });
if (!P_MatchEntKey(ent0->key, ent1->key) && IsIntersectingRng2(aabb0, aabb1))
{
Rng2 aabb1 = P_BoundingBoxFromShape(space_entry->shape);
P_Ent *ent1 = P_EntFromKey(frame, (P_EntKey) { .v = space_entry->shape_id });
if (!P_MatchEntKey(ent0->key, ent1->key) && IsIntersectingRng2(aabb0, aabb1))
P_Shape shape1 = space_entry->shape;
b32 is_static_collision = P_IsEntNil(ent1);
b32 is_guy_on_guy_collision = ent0->is_guy && ent1->is_guy;
if (is_static_collision || is_guy_on_guy_collision)
{
P_Shape shape1 = space_entry->shape;
b32 is_static_collision = P_IsEntNil(ent1);
b32 is_guy_on_guy_collision = ent0->is_guy && ent1->is_guy;
if (is_static_collision || is_guy_on_guy_collision)
P_ConstraintKey constraint_key = Zi;
{
P_ConstraintKey constraint_key = Zi;
// Deterministic shape ID order for consistent constraint lookup
u64 shape_id0 = ent0->key.v;
u64 shape_id1 = space_entry->shape_id;
if (shape_id0 > shape_id1)
{
// Deterministic shape ID order for consistent constraint lookup
u64 shape_id0 = ent0->key.v;
u64 shape_id1 = space_entry->shape_id;
if (shape_id0 > shape_id1)
{
u64 tmp = shape_id0;
shape_id0 = shape_id1;
shape_id1 = tmp;
}
constraint_key = P_ConstraintKeyFromU64s(shape_id0, shape_id1);
u64 tmp = shape_id0;
shape_id0 = shape_id1;
shape_id1 = tmp;
}
P_Constraint *constraint = P_ConstraintFromKey(frame, constraint_key);
if (constraint->last_touched_tick < frame->tick)
constraint_key = P_ConstraintKeyFromU64s(shape_id0, shape_id1);
}
P_Constraint *constraint = P_ConstraintFromKey(frame, constraint_key);
if (constraint->last_touched_tick < frame->tick)
{
P_CollisionResult collision = P_CollisionResultFromShapes(shape0, shape1);
if (collision.collision_points_count > 0)
{
P_CollisionResult collision = P_CollisionResultFromShapes(shape0, shape1);
if (collision.collision_points_count > 0)
if (P_IsConstraintNil(constraint))
{
if (P_IsConstraintNil(constraint))
{
constraint = P_PushConstraint(frame, constraint_key);
}
constraint->last_touched_tick = frame->tick;
constraint->normal = collision.collision_normal;
// constraint->friction = SqrtF32(ent0->friction * ent1->friction);
constraint->friction = 0;
constraint = P_PushConstraint(frame, constraint_key);
}
constraint->last_touched_tick = frame->tick;
constraint->normal = collision.collision_normal;
// constraint->friction = SqrtF32(ent0->friction * ent1->friction);
constraint->friction = 0;
if (is_static_collision)
{
constraint->flags |= P_ConstraintFlag_Solid;
}
else if (is_guy_on_guy_collision)
{
constraint->flags |= P_ConstraintFlag_Gentle;
// constraint->flags |= P_ConstraintFlag_NoWarmStart;
}
if (is_static_collision)
{
constraint->flags |= P_ConstraintFlag_Solid;
}
else if (is_guy_on_guy_collision)
{
constraint->flags |= P_ConstraintFlag_Gentle;
// constraint->flags |= P_ConstraintFlag_NoWarmStart;
}
// TODO: Real masses
f32 inv_m0 = 10;
f32 inv_m1 = 10;
f32 inv_i0 = 0;
f32 inv_i1 = 0;
// TODO: Real masses
f32 inv_m0 = 10;
f32 inv_m1 = 10;
f32 inv_i0 = 0;
f32 inv_i1 = 0;
// Treat statics / non-predicted ents as infinite-mass
if (!ent0->is_guy || (is_predicting && !P_MatchEntKey(ent0->key, local_guy->key)))
// Treat statics / non-predicted ents as infinite-mass
if (!ent0->is_guy || (is_predicting && !P_MatchEntKey(ent0->key, local_guy->key)))
{
inv_m0 = 0;
inv_i0 = 0;
}
if (!ent1->is_guy || (is_predicting && !P_MatchEntKey(ent1->key, local_guy->key)))
{
inv_m1 = 0;
inv_i1 = 0;
}
constraint->ent0 = ent0->key;
constraint->ent1 = ent1->key;
constraint->static_center0 = shape0.center_of_mass;
constraint->static_center1 = shape1.center_of_mass;
constraint->inv_m0 = inv_m0;
constraint->inv_m1 = inv_m1;
constraint->inv_i0 = inv_i0;
constraint->inv_i1 = inv_i1;
// Delete old contacts that are no longer present
for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
{
P_ContactPoint *contact = &constraint->points[contact_point_idx];
u32 id = contact->id;
b32 match = 0;
for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
{
inv_m0 = 0;
inv_i0 = 0;
}
if (!ent1->is_guy || (is_predicting && !P_MatchEntKey(ent1->key, local_guy->key)))
{
inv_m1 = 0;
inv_i1 = 0;
}
constraint->ent0 = ent0->key;
constraint->ent1 = ent1->key;
constraint->static_center0 = shape0.center_of_mass;
constraint->static_center1 = shape1.center_of_mass;
constraint->inv_m0 = inv_m0;
constraint->inv_m1 = inv_m1;
constraint->inv_i0 = inv_i0;
constraint->inv_i1 = inv_i1;
// Delete old contacts that are no longer present
for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
{
P_ContactPoint *contact = &constraint->points[contact_point_idx];
u32 id = contact->id;
b32 match = 0;
for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
if (collision.collision_points[collision_point_idx].id == id)
{
if (collision.collision_points[collision_point_idx].id == id)
match = 1;
break;
}
}
if (!match)
{
// Delete contact by replacing with last in array
*contact = constraint->points[constraint->points_count - 1];
constraint->points_count -= 1;
contact_point_idx -= 1;
}
}
// Create / update contacts from collision
for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
{
P_CollisionPoint collision_point = collision.collision_points[collision_point_idx];
u32 id = collision_point.id;
P_ContactPoint *contact = 0;
{
for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
{
P_ContactPoint *tmp = &constraint->points[contact_point_idx];
if (tmp->id == id)
{
match = 1;
contact = tmp;
break;
}
}
if (!match)
if (!contact)
{
// Delete contact by replacing with last in array
*contact = constraint->points[constraint->points_count - 1];
constraint->points_count -= 1;
contact_point_idx -= 1;
contact = &constraint->points[constraint->points_count];
constraint->points_count += 1;
ZeroStruct(contact);
}
}
contact->id = id;
// Create / update contacts from collision
for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
{
P_CollisionPoint collision_point = collision.collision_points[collision_point_idx];
Vec2 vcp0 = SubVec2(collision_point.p, shape0.center_of_mass);
Vec2 vcp1 = SubVec2(collision_point.p, shape1.center_of_mass);
u32 id = collision_point.id;
P_ContactPoint *contact = 0;
{
for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
{
P_ContactPoint *tmp = &constraint->points[contact_point_idx];
if (tmp->id == id)
{
contact = tmp;
break;
}
}
if (!contact)
{
contact = &constraint->points[constraint->points_count];
constraint->points_count += 1;
ZeroStruct(contact);
}
}
contact->id = id;
contact->vcp0 = vcp0;
contact->vcp1 = vcp1;
contact->starting_separation = collision_point.separation;
Vec2 vcp0 = SubVec2(collision_point.p, shape0.center_of_mass);
Vec2 vcp1 = SubVec2(collision_point.p, shape1.center_of_mass);
contact->vcp0 = vcp0;
contact->vcp1 = vcp1;
contact->starting_separation = collision_point.separation;
// Debug draw
// {
// // P_Ent *ent0 = P_EntFromKey(frame, constraint->ent0);
// // P_Ent *ent1 = P_EntFromKey(frame, constraint->ent1);
// Vec2 normal = constraint->normal;
// Vec2 center0 = Zi;
// Vec2 center1 = Zi;
// if (!P_IsEntNil(ent0)) center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
// if (!P_IsEntNil(ent1)) center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
// Vec2 p0 = AddVec2(center0, vcp0);
// Vec2 p1 = AddVec2(center1, vcp1);
// P_DebugDrawPoint(p0, Color_Cyan);
// P_DebugDrawLine(p0, AddVec2(p0, normal), Color_White);
// }
}
// Debug draw
// {
// // P_Ent *ent0 = P_EntFromKey(frame, constraint->ent0);
// // P_Ent *ent1 = P_EntFromKey(frame, constraint->ent1);
// Vec2 normal = constraint->normal;
// Vec2 center0 = Zi;
// Vec2 center1 = Zi;
// if (!P_IsEntNil(ent0)) center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
// if (!P_IsEntNil(ent1)) center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
// Vec2 p0 = AddVec2(center0, vcp0);
// Vec2 p1 = AddVec2(center1, vcp1);
// P_DebugDrawPoint(p0, Color_Cyan);
// P_DebugDrawLine(p0, AddVec2(p0, normal), Color_White);
// }
}
}
}
@ -2223,469 +2254,10 @@ void P_StepFrame(P_Frame *frame)
}
}
}
// for (P_Ent *ent1 = P_FirstEnt(frame); !P_IsEntNil(ent1); ent1 = P_NextEnt(ent1))
// {
// if (ent1->is_guy && ent1->key.v > ent0->key.v)
// {
// P_Shape shape1 = P_WorldShapeFromEnt(ent1);
// // TODO: World query
// P_CollisionResult collision = P_CollisionResultFromShapes(shape0, shape1);
// if (collision.collision_points_count > 0)
// {
// P_ConstraintKey constraint_key = P_ConstraintKeyFromU64s(ent0->key.v, ent1->key.v);
// P_Constraint *constraint = P_ConstraintFromKey(frame, constraint_key);
// if (constraint->last_touched_tick < frame->tick)
// {
// if (P_IsConstraintNil(constraint))
// {
// constraint = P_PushConstraint(frame, constraint_key);
// }
// constraint->flags = P_ConstraintFlag_Gentle | P_ConstraintFlag_NoWarmStart;
// constraint->last_touched_tick = frame->tick;
// constraint->normal = collision.collision_normal;
// // constraint->friction = SqrtF32(ent0->friction * ent1->friction);
// constraint->friction = 0;
// // TODO: Real masses
// f32 inv_m0 = 10;
// f32 inv_m1 = 10;
// f32 inv_i0 = 0;
// f32 inv_i1 = 0;
// // Treat non-predicted guys as infinite-mass
// if (is_predicting && ent0 != local_guy)
// {
// inv_m0 = 0;
// }
// if (is_predicting && ent1 != local_guy)
// {
// inv_m1 = 0;
// }
// constraint->ent0 = ent0->key;
// constraint->ent1 = ent1->key;
// // constraint->static_center1 = shape1.center_of_mass;
// constraint->inv_m0 = inv_m0;
// constraint->inv_m1 = inv_m1;
// constraint->inv_i0 = inv_i0;
// constraint->inv_i1 = inv_i1;
// // Delete old contacts that are no longer present
// for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
// {
// P_ContactPoint *contact = &constraint->points[contact_point_idx];
// u32 id = contact->id;
// b32 match = 0;
// for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
// {
// if (collision.collision_points[collision_point_idx].id == id)
// {
// match = 1;
// break;
// }
// }
// if (!match)
// {
// // Delete contact by replacing with last in array
// *contact = constraint->points[constraint->points_count - 1];
// constraint->points_count -= 1;
// contact_point_idx -= 1;
// }
// }
// // Create / update contacts from collision
// for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
// {
// P_CollisionPoint collision_point = collision.collision_points[collision_point_idx];
// u32 id = collision_point.id;
// P_ContactPoint *contact = 0;
// {
// for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
// {
// P_ContactPoint *tmp = &constraint->points[contact_point_idx];
// if (tmp->id == id)
// {
// contact = tmp;
// break;
// }
// }
// if (!contact)
// {
// contact = &constraint->points[constraint->points_count];
// constraint->points_count += 1;
// ZeroStruct(contact);
// }
// }
// contact->id = id;
// Vec2 vcp0 = SubVec2(collision_point.p, shape0.center_of_mass);
// Vec2 vcp1 = SubVec2(collision_point.p, shape1.center_of_mass);
// contact->vcp0 = vcp0;
// contact->vcp1 = vcp1;
// contact->starting_separation = collision_point.separation;
// // Debug draw
// // {
// // // P_Ent *ent0 = P_EntFromKey(frame, constraint->ent0);
// // // P_Ent *ent1 = P_EntFromKey(frame, constraint->ent1);
// // Vec2 normal = constraint->normal;
// // Vec2 center0 = Zi;
// // Vec2 center1 = Zi;
// // if (!P_IsEntNil(ent0)) center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
// // if (!P_IsEntNil(ent1)) center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
// // Vec2 p0 = AddVec2(center0, vcp0);
// // Vec2 p1 = AddVec2(center1, vcp1);
// // P_DebugDrawPoint(p0, Color_Cyan);
// // P_DebugDrawLine(p0, AddVec2(p0, normal), Color_White);
// // }
// }
// }
// }
// }
// }
}
}
}
//////////////////////////////
//- Generate solid constraints
// TODO: Not like this
// for (P_Ent *ent0 = P_FirstEnt(frame); !P_IsEntNil(ent0); ent0 = P_NextEnt(ent0))
// {
// if (ent0->is_guy)
// {
// P_Shape shape0 = P_WorldShapeFromEnt(ent0);
// Rng2 aabb = P_BoundingBoxFromShape(shape0);
// P_Query query = P_QueryFromRect(scratch.arena, aabb, P_QueryFlag_IncludeWalls);
// for (P_QueryItem *item = query.first; item; item = item->next)
// {
// P_Shape shape1 = item->shape;
// // TODO: World query
// P_CollisionResult collision = P_CollisionResultFromShapes(shape0, shape1);
// if (collision.collision_points_count > 0)
// {
// P_Constraint *constraint = P_ConstraintFromKey(world_frame, constraint_key);
// if (P_IsConstraintNil(constraint))
// {
// constraint = P_PushConstraint(world_frame, constraint_key);
// }
// if (constraint->last_touched_tick < frame->tick)
// {
// constraint->last_touched_Tick = frame->tick;
// constraint->flags = P_ConstraintFlag_Solid;
// constraint->last_touched_tick = frame->tick;
// constraint->normal = collision.collision_normal;
// // constraint->friction = SqrtF32(ent0->friction * ent1->friction);
// constraint->friction = 0;
// // TODO: Real masses
// f32 inv_m0 = 10;
// f32 inv_m1 = 10;
// f32 inv_i0 = 0;
// f32 inv_i1 = 0;
// // Treat non-predicted guys as infinite-mass
// if (is_predicting && ent0 != local_guy)
// {
// inv_m0 = 0;
// }
// if (is_predicting && ent1 != local_guy)
// {
// inv_m1 = 0;
// }
// constraint->ent0 = ent0->key;
// constraint->ent1 = ent1->key;
// // constraint->static_center1 = shape1.center_of_mass;
// constraint->inv_m0 = inv_m0;
// constraint->inv_m1 = inv_m1;
// constraint->inv_i0 = inv_i0;
// constraint->inv_i1 = inv_i1;
// // Delete old contacts that are no longer present
// for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
// {
// P_ContactPoint *contact = &constraint->points[contact_point_idx];
// u32 id = contact->id;
// b32 match = 0;
// for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
// {
// if (collision.collision_points[collision_point_idx].id == id)
// {
// match = 1;
// break;
// }
// }
// if (!match)
// {
// // Delete contact by replacing with last in array
// *contact = constraint->points[constraint->points_count - 1];
// constraint->points_count -= 1;
// contact_point_idx -= 1;
// }
// }
// // Create / update contacts from collision
// for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
// {
// P_CollisionPoint collision_point = collision.collision_points[collision_point_idx];
// u32 id = collision_point.id;
// P_ContactPoint *contact = 0;
// {
// for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
// {
// P_ContactPoint *tmp = &constraint->points[contact_point_idx];
// if (tmp->id == id)
// {
// contact = tmp;
// break;
// }
// }
// if (!contact)
// {
// contact = &constraint->points[constraint->points_count];
// constraint->points_count += 1;
// ZeroStruct(contact);
// }
// }
// contact->id = id;
// Vec2 vcp0 = SubVec2(collision_point.p, shape0.center_of_mass);
// Vec2 vcp1 = SubVec2(collision_point.p, shape1.center_of_mass);
// contact->vcp0 = vcp0;
// contact->vcp1 = vcp1;
// contact->starting_separation = collision_point.separation;
// // Debug draw
// // {
// // // P_Ent *ent0 = P_EntFromKey(frame, constraint->ent0);
// // // P_Ent *ent1 = P_EntFromKey(frame, constraint->ent1);
// // Vec2 normal = constraint->normal;
// // Vec2 center0 = Zi;
// // Vec2 center1 = Zi;
// // if (!P_IsEntNil(ent0)) center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
// // if (!P_IsEntNil(ent1)) center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
// // Vec2 p0 = AddVec2(center0, vcp0);
// // Vec2 p1 = AddVec2(center1, vcp1);
// // P_DebugDrawPoint(p0, Color_Cyan);
// // P_DebugDrawLine(p0, AddVec2(p0, normal), Color_White);
// // }
// }
// }
// }
// }
// }
// }
// //////////////////////////////
// //- Generate solid constraints
// // TODO: Not like this
// for (P_Ent *ent0 = P_FirstEnt(frame); !P_IsEntNil(ent0); ent0 = P_NextEnt(ent0))
// {
// if (ent0->is_guy)
// {
// P_Shape shape0 = P_WorldShapeFromEnt(ent0);
// for (P_Ent *ent1 = P_FirstEnt(frame); !P_IsEntNil(ent1); ent1 = P_NextEnt(ent1))
// {
// if (ent1->is_guy && ent1->key.v > ent0->key.v)
// {
// P_Shape shape1 = P_WorldShapeFromEnt(ent1);
// // TODO: World query
// P_CollisionResult collision = P_CollisionResultFromShapes(shape0, shape1);
// if (collision.collision_points_count > 0)
// {
// // FIXME: Key lookup
// P_Constraint *constraint = 0;
// {
// b32 match = 0;
// for (i64 constraint_idx = 0; constraint_idx < frame->constraints_count; ++constraint_idx)
// {
// constraint = &frame->constraints[constraint_idx];
// if (P_MatchEntKey(constraint->ent0, ent0->key) && P_MatchEntKey(constraint->ent1, ent1->key))
// {
// match = 1;
// break;
// }
// }
// if (!match)
// {
// if (frame->constraints_count < frame->constraints_cap)
// {
// constraint = &frame->constraints[frame->constraints_count];
// frame->constraints_count += 1;
// ZeroStruct(constraint);
// }
// }
// }
// if (constraint)
// {
// constraint->flags = P_ConstraintFlag_Solid;
// constraint->last_touched_tick = frame->tick;
// constraint->normal = collision.collision_normal;
// // constraint->friction = SqrtF32(ent0->friction * ent1->friction);
// constraint->friction = 0;
// // TODO: Real masses
// f32 inv_m0 = 10;
// f32 inv_m1 = 10;
// f32 inv_i0 = 0;
// f32 inv_i1 = 0;
// // Treat non-predicted guys as infinite-mass
// if (is_predicting && ent0 != local_guy)
// {
// inv_m0 = 0;
// }
// if (is_predicting && ent1 != local_guy)
// {
// inv_m1 = 0;
// }
// constraint->ent0 = ent0->key;
// constraint->ent1 = ent1->key;
// // constraint->static_center1 = shape1.center_of_mass;
// constraint->inv_m0 = inv_m0;
// constraint->inv_m1 = inv_m1;
// constraint->inv_i0 = inv_i0;
// constraint->inv_i1 = inv_i1;
// // Delete old contacts that are no longer present
// for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
// {
// P_ContactPoint *contact = &constraint->points[contact_point_idx];
// u32 id = contact->id;
// b32 match = 0;
// for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
// {
// if (collision.collision_points[collision_point_idx].id == id)
// {
// match = 1;
// break;
// }
// }
// if (!match)
// {
// // Delete contact by replacing with last in array
// *contact = constraint->points[constraint->points_count - 1];
// constraint->points_count -= 1;
// contact_point_idx -= 1;
// }
// }
// // Create / update contacts from collision
// for (i32 collision_point_idx = 0; collision_point_idx < collision.collision_points_count; ++collision_point_idx)
// {
// P_CollisionPoint collision_point = collision.collision_points[collision_point_idx];
// u32 id = collision_point.id;
// P_ContactPoint *contact = 0;
// {
// for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx)
// {
// P_ContactPoint *tmp = &constraint->points[contact_point_idx];
// if (tmp->id == id)
// {
// contact = tmp;
// break;
// }
// }
// if (!contact)
// {
// contact = &constraint->points[constraint->points_count];
// constraint->points_count += 1;
// ZeroStruct(contact);
// }
// }
// contact->id = id;
// Vec2 vcp0 = SubVec2(collision_point.p, shape0.center_of_mass);
// Vec2 vcp1 = SubVec2(collision_point.p, shape1.center_of_mass);
// contact->vcp0 = vcp0;
// contact->vcp1 = vcp1;
// contact->starting_separation = collision_point.separation;
// // Debug draw
// // {
// // // P_Ent *ent0 = P_EntFromKey(frame, constraint->ent0);
// // // P_Ent *ent1 = P_EntFromKey(frame, constraint->ent1);
// // Vec2 normal = constraint->normal;
// // Vec2 center0 = Zi;
// // Vec2 center1 = Zi;
// // if (!P_IsEntNil(ent0)) center0 = P_WorldShapeFromEnt(ent0).center_of_mass;
// // if (!P_IsEntNil(ent1)) center1 = P_WorldShapeFromEnt(ent1).center_of_mass;
// // Vec2 p0 = AddVec2(center0, vcp0);
// // Vec2 p1 = AddVec2(center1, vcp1);
// // P_DebugDrawPoint(p0, Color_Cyan);
// // P_DebugDrawLine(p0, AddVec2(p0, normal), Color_White);
// // }
// }
// }
// }
// }
// }
// }
// }
//////////////////////////////
//- Prune constraints
@ -2697,12 +2269,7 @@ void P_StepFrame(P_Frame *frame)
b32 prune = 1;
if (constraint->last_touched_tick == frame->tick)
{
P_Ent *ent0 = P_EntFromKey(frame, constraint->ent0);
P_Ent *ent1 = P_EntFromKey(frame, constraint->ent1);
if (!P_IsEntNil(ent0) && !P_IsEntNil(ent1))
{
prune = 0;
}
prune = 0;
}
if (prune)
{

View File

@ -6,6 +6,8 @@
#define P_NilEntKey ((P_EntKey) { 0 })
#define P_NilConstraintKey ((P_EntKey) { 0 })
#define P_WallShapeIDBasis 0x40d501b4cf6d4f0cull
Struct(P_EntKey)
{
u64 v;