tile -> wall generation
This commit is contained in:
parent
b7f2c3d185
commit
bf56bd7155
@ -765,6 +765,11 @@ Rng2 IntersectRng2(Rng2 a, Rng2 b)
|
||||
return result;
|
||||
}
|
||||
|
||||
b32 IsIntersectingRng2(Rng2 a, Rng2 b)
|
||||
{
|
||||
return !IsRng2Empty(IntersectRng2(a, b));
|
||||
}
|
||||
|
||||
Rng2 AddRng2Vec2(Rng2 r, Vec2 v)
|
||||
{
|
||||
Rng2 result = Zi;
|
||||
@ -833,6 +838,11 @@ Rng2I32 IntersectRng2I32(Rng2I32 a, Rng2I32 b)
|
||||
return result;
|
||||
}
|
||||
|
||||
b32 IsIntersectingRng2I32(Rng2I32 a, Rng2I32 b)
|
||||
{
|
||||
return !IsRng2I32Empty(IntersectRng2I32(a, b));
|
||||
}
|
||||
|
||||
Rng2I32 AddRng2I32Vec2I32(Rng2I32 r, Vec2I32 v)
|
||||
{
|
||||
Rng2I32 result = Zi;
|
||||
|
||||
@ -439,6 +439,7 @@ Vec2 CenterFromRng2(Rng2 r);
|
||||
Vec2 NormRng2(Rng2 r, Vec2 v);
|
||||
Rng2 UnionRng2(Rng2 a, Rng2 b);
|
||||
Rng2 IntersectRng2(Rng2 a, Rng2 b);
|
||||
b32 IsIntersectingRng2(Rng2 a, Rng2 b);
|
||||
Rng2 AddRng2Vec2(Rng2 r, Vec2 v);
|
||||
Rng2 MulRng2Vec2(Rng2 a, Vec2 v);
|
||||
Rng2 DivRng2Vec2(Rng2 a, Vec2 v);
|
||||
@ -449,6 +450,7 @@ Vec2I32 DimsFromRng2I32(Rng2I32 r);
|
||||
Vec2I32 CenterFromRng2I32(Rng2I32 r);
|
||||
Rng2I32 UnionRng2I32(Rng2I32 a, Rng2I32 b);
|
||||
Rng2I32 IntersectRng2I32(Rng2I32 a, Rng2I32 b);
|
||||
b32 IsIntersectingRng2I32(Rng2I32 a, Rng2I32 b);
|
||||
Rng2I32 AddRng2I32Vec2I32(Rng2I32 r, Vec2I32 v);
|
||||
Rng2I32 MulRng2I32Vec2I32(Rng2I32 a, Vec2I32 v);
|
||||
Rng2I32 DivRng2I32Vec2I32(Rng2I32 a, Vec2I32 v);
|
||||
|
||||
621
src/pp/pp.c
621
src/pp/pp.c
@ -1193,6 +1193,215 @@ P_Constraint *P_NextConstraint(P_Constraint *c)
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Space
|
||||
|
||||
P_Space P_SpaceFromFrame(Arena *arena, P_Frame *frame)
|
||||
{
|
||||
P_Space space = Zi;
|
||||
TempArena scratch = BeginScratch(arena);
|
||||
P_World *world = frame->world;
|
||||
i64 cells_count = P_WorldPitch * P_WorldPitch;
|
||||
space.cells = PushStructs(arena, P_SpaceCell, cells_count);
|
||||
|
||||
Rng2 space_aabb = RNG2(
|
||||
VEC2(0, 0),
|
||||
VEC2(P_WorldPitch, P_WorldPitch)
|
||||
);
|
||||
|
||||
//- Insert entity shapes
|
||||
for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||
{
|
||||
b32 should_insert = ent->is_guy;
|
||||
if (should_insert)
|
||||
{
|
||||
P_Shape shape = P_WorldShapeFromEnt(ent);
|
||||
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);
|
||||
if (!IsRng2Empty(aabb))
|
||||
{
|
||||
for (i32 y = aabb.p0.y; y < aabb.p1.y; ++y)
|
||||
{
|
||||
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 = ent->key.v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- Generate wall shapes from tiles
|
||||
// TODO: Cache walls in separate space
|
||||
{
|
||||
Enum(WallDir)
|
||||
{
|
||||
WallDir_None,
|
||||
WallDir_Up,
|
||||
WallDir_Right,
|
||||
WallDir_Down,
|
||||
WallDir_Left,
|
||||
};
|
||||
|
||||
Struct(GenWall)
|
||||
{
|
||||
GenWall *next;
|
||||
WallDir dir;
|
||||
Vec2I32 start;
|
||||
Vec2I32 end;
|
||||
};
|
||||
|
||||
i64 walls_count = 0;
|
||||
GenWall *first_wall = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// FIXME: Iterate to pitch + 1
|
||||
|
||||
|
||||
|
||||
//- Generate horizontal walls
|
||||
for (i32 tile_y = 0; tile_y < P_TilesPitch + 1; ++tile_y)
|
||||
{
|
||||
i32 wall_start = -1;
|
||||
WallDir prev_wall_dir = WallDir_None;
|
||||
for (i32 tile_x = 0; tile_x < P_TilesPitch + 1; ++tile_x)
|
||||
{
|
||||
P_TileKind tile = P_TileKind_Empty;
|
||||
P_TileKind tile_t = P_TileKind_Empty;
|
||||
if (tile_x >= 0 && tile_x < P_TilesPitch)
|
||||
{
|
||||
if (tile_y >= 0 && tile_y < P_TilesPitch)
|
||||
{
|
||||
tile = world->tiles[tile_y * (i32)P_TilesPitch + tile_x];
|
||||
}
|
||||
if ((tile_y - 1) >= 0 && (tile_y - 1) < P_TilesPitch)
|
||||
{
|
||||
tile_t = world->tiles[(tile_y - 1) * (i32)P_TilesPitch + tile_x];
|
||||
}
|
||||
}
|
||||
WallDir dir = WallDir_None;
|
||||
if (tile == P_TileKind_Wall && tile_t != P_TileKind_Wall)
|
||||
{
|
||||
dir = WallDir_Up;
|
||||
}
|
||||
else if (tile != P_TileKind_Wall && tile_t == P_TileKind_Wall)
|
||||
{
|
||||
dir = WallDir_Down;
|
||||
}
|
||||
if (dir != prev_wall_dir)
|
||||
{
|
||||
if (prev_wall_dir != WallDir_None)
|
||||
{
|
||||
GenWall *wall = PushStruct(scratch.arena, GenWall);
|
||||
++walls_count;
|
||||
SllStackPush(first_wall, wall);
|
||||
wall->dir = prev_wall_dir;
|
||||
wall->start = VEC2I32(wall_start, tile_y);
|
||||
wall->end = VEC2I32(tile_x, tile_y);
|
||||
}
|
||||
wall_start = tile_x;
|
||||
}
|
||||
prev_wall_dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
//- Generate vertical walls
|
||||
for (i32 tile_x = 0; tile_x < P_TilesPitch + 1; ++tile_x)
|
||||
{
|
||||
i32 wall_start = -1;
|
||||
WallDir prev_wall_dir = WallDir_None;
|
||||
for (i32 tile_y = 0; tile_y < P_TilesPitch + 1; ++tile_y)
|
||||
{
|
||||
P_TileKind tile = P_TileKind_Empty;
|
||||
P_TileKind tile_l = P_TileKind_Empty;
|
||||
if (tile_y >= 0 && tile_y < P_TilesPitch)
|
||||
{
|
||||
if (tile_x >= 0 && tile_x < P_TilesPitch)
|
||||
{
|
||||
tile = world->tiles[tile_y * (i32)P_TilesPitch + tile_x];
|
||||
}
|
||||
if ((tile_x - 1) >= 0 && (tile_x - 1) < P_TilesPitch)
|
||||
{
|
||||
tile_l = world->tiles[tile_y * (i32)P_TilesPitch + (tile_x - 1)];
|
||||
}
|
||||
}
|
||||
WallDir dir = WallDir_None;
|
||||
if (tile == P_TileKind_Wall && tile_l != P_TileKind_Wall)
|
||||
{
|
||||
dir = WallDir_Left;
|
||||
}
|
||||
else if (tile != P_TileKind_Wall && tile_l == P_TileKind_Wall)
|
||||
{
|
||||
dir = WallDir_Right;
|
||||
}
|
||||
if (dir != prev_wall_dir)
|
||||
{
|
||||
if (prev_wall_dir != WallDir_None)
|
||||
{
|
||||
GenWall *wall = PushStruct(scratch.arena, GenWall);
|
||||
++walls_count;
|
||||
SllStackPush(first_wall, wall);
|
||||
wall->dir = prev_wall_dir;
|
||||
wall->start = VEC2I32(tile_x, wall_start);
|
||||
wall->end = VEC2I32(tile_x, tile_y);
|
||||
}
|
||||
wall_start = tile_y;
|
||||
}
|
||||
prev_wall_dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
//- 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EndScratch(scratch);
|
||||
return space;
|
||||
}
|
||||
|
||||
P_SpaceCell P_SpaceCellFromPos(P_Space *space, Vec2 pos)
|
||||
{
|
||||
P_SpaceCell result = Zi;
|
||||
pos = AddVec2(pos, VEC2(P_WorldPitch / 2.0, P_WorldPitch / 2.0));
|
||||
if (pos.x >= 0 && pos.x < P_WorldPitch && pos.y >= 0 && pos.y < P_WorldPitch)
|
||||
{
|
||||
i64 cell_idx = FloorF32(pos.y) * P_WorldPitch + FloorF32(pos.x);
|
||||
result = space->cells[cell_idx];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ List helpers
|
||||
|
||||
@ -1561,7 +1770,6 @@ P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick)
|
||||
else
|
||||
{
|
||||
dst = PushStructNoZero(world->frames_arena, P_Constraint);
|
||||
LogDebugF("RAAAAAAH");
|
||||
}
|
||||
*dst = *src;
|
||||
P_ConstraintBin *bin = &frame->constraint_bins[src->key.v % frame->constraint_bins_count];
|
||||
@ -1817,11 +2025,8 @@ void P_StepFrame(P_Frame *frame)
|
||||
f32 solid_pushout_velocity = TweakFloat("Contact spring pushout", 3, 0, 50);
|
||||
|
||||
// Gentle params
|
||||
f32 gentle_pushout_factor = TweakFloat("Gentle pushout factor", 10, 0, 50);
|
||||
|
||||
|
||||
|
||||
|
||||
// f32 gentle_pushout_factor = TweakFloat("Gentle pushout factor", 10, 0, 50);
|
||||
f32 gentle_pushout_factor = TweakFloat("Gentle pushout factor", 0.1, 0, 50);
|
||||
|
||||
|
||||
|
||||
@ -1829,14 +2034,19 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Generate guy-on-guy constraints
|
||||
//- Build pre-solve space
|
||||
|
||||
P_Space space = P_SpaceFromFrame(scratch.arena, frame);
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Generate guy constraints
|
||||
|
||||
|
||||
|
||||
// TODO: Not like this
|
||||
|
||||
|
||||
|
||||
if (!is_predicting)
|
||||
{
|
||||
for (P_Ent *ent0 = P_FirstEnt(frame); !P_IsEntNil(ent0); ent0 = P_NextEnt(ent0))
|
||||
@ -1844,131 +2054,304 @@ void P_StepFrame(P_Frame *frame)
|
||||
if (ent0->is_guy)
|
||||
{
|
||||
P_Shape shape0 = P_WorldShapeFromEnt(ent0);
|
||||
for (P_Ent *ent1 = P_FirstEnt(frame); !P_IsEntNil(ent1); ent1 = P_NextEnt(ent1))
|
||||
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)
|
||||
{
|
||||
if (ent1->is_guy && ent1->key.v > ent0->key.v)
|
||||
for (i32 query_x = query_rect.p0.x; query_x < query_rect.p1.x; ++query_x)
|
||||
{
|
||||
P_Shape shape1 = P_WorldShapeFromEnt(ent1);
|
||||
|
||||
// TODO: World query
|
||||
P_CollisionResult collision = P_CollisionResultFromShapes(shape0, shape1);
|
||||
if (collision.collision_points_count > 0)
|
||||
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_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)
|
||||
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))
|
||||
{
|
||||
if (P_IsConstraintNil(constraint))
|
||||
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)
|
||||
{
|
||||
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)
|
||||
P_ConstraintKey constraint_key = Zi;
|
||||
{
|
||||
if (collision.collision_points[collision_point_idx].id == id)
|
||||
// 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)
|
||||
{
|
||||
match = 1;
|
||||
break;
|
||||
u64 tmp = shape_id0;
|
||||
shape_id0 = shape_id1;
|
||||
shape_id1 = tmp;
|
||||
}
|
||||
constraint_key = P_ConstraintKeyFromU64s(shape_id0, shape_id1);
|
||||
}
|
||||
if (!match)
|
||||
P_Constraint *constraint = P_ConstraintFromKey(frame, constraint_key);
|
||||
if (constraint->last_touched_tick < frame->tick)
|
||||
{
|
||||
// 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_CollisionResult collision = P_CollisionResultFromShapes(shape0, shape1);
|
||||
if (collision.collision_points_count > 0)
|
||||
{
|
||||
P_ContactPoint *tmp = &constraint->points[contact_point_idx];
|
||||
if (tmp->id == id)
|
||||
if (P_IsConstraintNil(constraint))
|
||||
{
|
||||
contact = tmp;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
// 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)))
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
// }
|
||||
}
|
||||
}
|
||||
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);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 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);
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1992,7 +2375,9 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
|
||||
|
||||
// // TODO: Not like this
|
||||
// TODO: Not like this
|
||||
|
||||
|
||||
|
||||
// for (P_Ent *ent0 = P_FirstEnt(frame); !P_IsEntNil(ent0); ent0 = P_NextEnt(ent0))
|
||||
// {
|
||||
@ -2001,9 +2386,9 @@ void P_StepFrame(P_Frame *frame)
|
||||
// P_Shape shape0 = P_WorldShapeFromEnt(ent0);
|
||||
// Rng2 aabb = P_BoundingBoxFromShape(shape0);
|
||||
|
||||
// P_Query collisions = P_QueryFromRect(scratch.arena, aabb, P_QueryFlag_IncludeWalls);
|
||||
// P_Query query = P_QueryFromRect(scratch.arena, aabb, P_QueryFlag_IncludeWalls);
|
||||
|
||||
// for (P_QueryItem *item = collisions.first; item; item = item->next)
|
||||
// for (P_QueryItem *item = query.first; item; item = item->next)
|
||||
// {
|
||||
// P_Shape shape1 = item->shape;
|
||||
|
||||
@ -2427,6 +2812,8 @@ void P_StepFrame(P_Frame *frame)
|
||||
//////////////////////////////
|
||||
//- Solve constraints
|
||||
|
||||
// TODO: Solve wall constraints last
|
||||
|
||||
for (P_Constraint *constraint = P_FirstConstraint(frame); !P_IsConstraintNil(constraint); constraint = P_NextConstraint(constraint))
|
||||
{
|
||||
P_Ent *ent0 = P_EntFromKey(frame, constraint->ent0);
|
||||
|
||||
26
src/pp/pp.h
26
src/pp/pp.h
@ -247,6 +247,26 @@ Struct(P_ConstraintBin)
|
||||
P_Constraint *last;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Space types
|
||||
|
||||
Struct(P_SpaceEntry)
|
||||
{
|
||||
P_SpaceEntry *next;
|
||||
P_Shape shape;
|
||||
u64 shape_id;
|
||||
};
|
||||
|
||||
Struct(P_SpaceCell)
|
||||
{
|
||||
P_SpaceEntry *first;
|
||||
};
|
||||
|
||||
Struct(P_Space)
|
||||
{
|
||||
P_SpaceCell *cells;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ World types
|
||||
|
||||
@ -577,6 +597,12 @@ P_Ent *P_NextEnt(P_Ent *e);
|
||||
P_Constraint *P_FirstConstraint(P_Frame *frame);
|
||||
P_Constraint *P_NextConstraint(P_Constraint *c);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Space
|
||||
|
||||
P_Space P_SpaceFromFrame(Arena *arena, P_Frame *frame);
|
||||
P_SpaceCell P_SpaceCellFromPos(P_Space *space, Vec2 pos);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ List helpers
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
||||
while (!shutdown)
|
||||
{
|
||||
shutdown = Atomic32Fetch(&S.shutdown);
|
||||
P_tl.debug_draw_enabled = TweakBool("Simulation debug draw", 0);
|
||||
P_tl.debug_draw_enabled = TweakBool("Simulation debug draw", 1);
|
||||
ResetArena(frame_arena);
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
@ -126,8 +126,6 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
|
||||
//////////////////////////////
|
||||
//- Particle emitter shader
|
||||
|
||||
// TODO: Initialize particles in per-particle-sim-thread rather than sequentially in emitter thread
|
||||
|
||||
ComputeShader(V_EmitParticlesCS, 64)
|
||||
{
|
||||
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
|
||||
@ -138,9 +136,9 @@ ComputeShader(V_EmitParticlesCS, 64)
|
||||
if (emitter_idx < frame.emitters_count)
|
||||
{
|
||||
V_Emitter emitter = emitters[emitter_idx];
|
||||
for (u32 i = 0; i < emitter.count; ++i)
|
||||
for (u32 emitter_particle_idx = 0; emitter_particle_idx < emitter.count; ++emitter_particle_idx)
|
||||
{
|
||||
u32 particle_seq = emitter.first_particle_seq + i;
|
||||
u32 particle_seq = emitter.first_particle_seq + emitter_particle_idx;
|
||||
u32 particle_idx = particle_seq % (u32)V_ParticlesCap;
|
||||
particles[particle_idx].exists = 1;
|
||||
particles[particle_idx].emitter_init_num = emitter_idx + 1;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user