From de86e12ba099e85ae3dae779226fff61a641e58d Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 9 Feb 2026 18:03:48 -0600 Subject: [PATCH] generate walls space separately during bake rather than every frame --- src/pp/pp.c | 574 +++++++++++++++++++++++++++------------------------- src/pp/pp.h | 10 +- 2 files changed, 306 insertions(+), 278 deletions(-) diff --git a/src/pp/pp.c b/src/pp/pp.c index 99377df0..9c09aca3 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -1196,7 +1196,7 @@ P_Constraint *P_NextConstraint(P_Constraint *c) //////////////////////////////////////////////////////////// //~ Space -P_Space P_SpaceFromFrame(Arena *arena, P_Frame *frame) +P_Space P_SpaceFromEnts(Arena *arena, P_Frame *frame) { P_Space space = Zi; TempArena scratch = BeginScratch(arena); @@ -1241,163 +1241,168 @@ P_Space P_SpaceFromFrame(Arena *arena, P_Frame *frame) } } - //- Generate wall shapes from tiles - // TODO: Cache walls in separate space + EndScratch(scratch); + return space; +} + +P_Space P_SpaceFromWalls(Arena *arena, P_Frame *frame) +{ + P_Space space = Zi; + TempArena scratch = BeginScratch(arena); + P_World *world = frame->world; + space.dims = VEC2I32(P_WorldPitch, P_WorldPitch); + 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) + ); + + Enum(WallDir) { - Enum(WallDir) - { - WallDir_None, - WallDir_Up, - WallDir_Right, - WallDir_Down, - WallDir_Left, - }; + WallDir_None, + WallDir_Up, + WallDir_Right, + WallDir_Down, + WallDir_Left, + }; - Struct(GenWall) - { - GenWall *next; - WallDir dir; - Vec2I32 start; - Vec2I32 end; - }; + Struct(GenWall) + { + GenWall *next; + WallDir dir; + Vec2I32 start; + Vec2I32 end; + }; - i64 walls_count = 0; - GenWall *first_wall = 0; + 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 + //- 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) { - 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_t = P_TileKind_Empty; + if (tile_x >= 0 && tile_x < P_TilesPitch) { - 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)]; - } + tile = world->tiles[tile_y * (i32)P_TilesPitch + tile_x]; } - WallDir dir = WallDir_None; - if (tile == P_TileKind_Wall && tile_l != P_TileKind_Wall) + if ((tile_y - 1) >= 0 && (tile_y - 1) < P_TilesPitch) { - dir = WallDir_Left; + tile_t = world->tiles[(tile_y - 1) * (i32)P_TilesPitch + tile_x]; } - 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; } - } - - //- Push walls to space - 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 }, .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) + WallDir dir = WallDir_None; + if (tile == P_TileKind_Wall && tile_t != P_TileKind_Wall) { - 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; - entry->dir.x = (wall->dir == WallDir_Right) + ((wall->dir == WallDir_Left) * -1); - entry->dir.y = (wall->dir == WallDir_Down) + ((wall->dir == WallDir_Up) * -1); - } + 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; + } + } + + //- Push walls to space + 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 }, .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) + { + 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; + entry->dir.x = (wall->dir == WallDir_Right) + ((wall->dir == WallDir_Left) * -1); + entry->dir.y = (wall->dir == WallDir_Down) + ((wall->dir == WallDir_Up) * -1); + } + } + } EndScratch(scratch); return space; @@ -1407,7 +1412,7 @@ 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) + if (pos.x >= 0 && pos.x < space->dims.x && pos.y >= 0 && pos.y < space->dims.y) { i64 cell_idx = FloorF32(pos.y) * P_WorldPitch + FloorF32(pos.x); result = space->cells[cell_idx]; @@ -1562,7 +1567,7 @@ P_World *P_AcquireWorld(void) world->arena = arena; } world->frames_arena = AcquireArena(Gibi(64)); - world->statics_arena = AcquireArena(Gibi(64)); + world->bake_arena = AcquireArena(Gibi(64)); world->first_frame = &P_NilFrame; world->last_frame = &P_NilFrame; @@ -2044,13 +2049,23 @@ void P_StepFrame(P_Frame *frame) + ////////////////////////////// + //- Bake world + { + u64 desired_bake_hash = world->tiles_hash; + if (desired_bake_hash != world->baked_hash) + { + ResetArena(world->bake_arena); + world->walls_space = P_SpaceFromWalls(world->bake_arena, frame); + world->baked_hash = desired_bake_hash; + } + } ////////////////////////////// - //- Build pre-solve space - - P_Space space = P_SpaceFromFrame(scratch.arena, frame); + //- Build pre-solve ents space + P_Space ents_space = P_SpaceFromEnts(scratch.arena, frame); ////////////////////////////// @@ -2077,165 +2092,172 @@ void P_StepFrame(P_Frame *frame) { 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 cells[] = { + P_SpaceCellFromPos(&ents_space, VEC2(query_x, query_y)), + P_SpaceCellFromPos(&world->walls_space, VEC2(query_x, query_y)), + }; + for (i64 cell_idx = 0; cell_idx < countof(cells); ++cell_idx) { - 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_SpaceCell cell = cells[cell_idx]; + for (P_SpaceEntry *space_entry = cell.first; space_entry; space_entry = space_entry->next) { - 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) + 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_ConstraintKey constraint_key = Zi; + 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) { - // 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) + P_ConstraintKey constraint_key = Zi; { - u64 tmp = shape_id0; - shape_id0 = shape_id1; - shape_id1 = tmp; + // 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); } - 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); - - b32 skip_collision = 0; - skip_collision = skip_collision || collision.collision_points_count <= 0; - if (!skip_collision && !IsVec2Zero(space_entry->dir)) + P_Constraint *constraint = P_ConstraintFromKey(frame, constraint_key); + if (constraint->last_touched_tick < frame->tick) { - // Skip collision if normal violates one-way direction - f32 threshold = 0.5; - skip_collision = DotVec2(space_entry->dir, collision.collision_normal) >= threshold; - } + P_CollisionResult collision = P_CollisionResultFromShapes(shape0, shape1); - if (!skip_collision) - { - if (P_IsConstraintNil(constraint)) + b32 skip_collision = 0; + skip_collision = skip_collision || collision.collision_points_count <= 0; + if (!skip_collision && !IsVec2Zero(space_entry->dir)) { - 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; + // Skip collision if normal violates one-way direction + f32 threshold = 0.5; + skip_collision = DotVec2(space_entry->dir, collision.collision_normal) >= threshold; } - // 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))) + if (!skip_collision) { - 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 (P_IsConstraintNil(constraint)) { - if (collision.collision_points[collision_point_idx].id == id) - { - match = 1; - break; - } + constraint = P_PushConstraint(frame, constraint_key); } - if (!match) + 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) { - // Delete contact by replacing with last in array - *contact = constraint->points[constraint->points_count - 1]; - constraint->points_count -= 1; - contact_point_idx -= 1; + constraint->flags |= P_ConstraintFlag_Solid; } - } - - // 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; + else if (is_guy_on_guy_collision) { - for (i32 contact_point_idx = 0; contact_point_idx < constraint->points_count; ++contact_point_idx) + 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) { - P_ContactPoint *tmp = &constraint->points[contact_point_idx]; - if (tmp->id == id) + if (collision.collision_points[collision_point_idx].id == id) { - contact = tmp; + match = 1; break; } } - if (!contact) + if (!match) { - contact = &constraint->points[constraint->points_count]; - constraint->points_count += 1; - ZeroStruct(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->id = id; - Vec2 vcp0 = SubVec2(collision_point.p, shape0.center_of_mass); - Vec2 vcp1 = SubVec2(collision_point.p, shape1.center_of_mass); + // 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]; - contact->vcp0 = vcp0; - contact->vcp1 = vcp1; - contact->starting_separation = collision_point.separation; + 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; - // 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); - // } + 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); + // } + } } } } diff --git a/src/pp/pp.h b/src/pp/pp.h index 309ac0f7..b3149396 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -267,6 +267,7 @@ Struct(P_SpaceCell) Struct(P_Space) { + Vec2I32 dims; P_SpaceCell *cells; }; @@ -330,7 +331,6 @@ Struct(P_World) { Arena *arena; Arena *frames_arena; - Arena *statics_arena; u64 seed; RandState rand; @@ -344,6 +344,11 @@ Struct(P_World) i64 frame_bins_count; P_FrameBin *frame_bins; + //- Baked data + Arena *bake_arena; + P_Space walls_space; + u64 baked_hash; + u64 tiles_hash; u8 *tiles; }; @@ -603,7 +608,8 @@ P_Constraint *P_NextConstraint(P_Constraint *c); //////////////////////////////////////////////////////////// //~ Space -P_Space P_SpaceFromFrame(Arena *arena, P_Frame *frame); +P_Space P_SpaceFromEnts(Arena *arena, P_Frame *frame); +P_Space P_SpaceFromWalls(Arena *arena, P_Frame *frame); P_SpaceCell P_SpaceCellFromPos(P_Space *space, Vec2 pos); ////////////////////////////////////////////////////////////