pp refactor

This commit is contained in:
jacob 2025-08-05 17:08:51 -05:00
parent 03d4386cdc
commit a39c649dc3
5 changed files with 248 additions and 172 deletions

View File

@ -33,9 +33,9 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio
CLD_Shape check0_collider = check0->local_collider; CLD_Shape check0_collider = check0->local_collider;
Aabb aabb = CLD_AabbFromShape(&check0_collider, check0_xf); Aabb aabb = CLD_AabbFromShape(&check0_collider, check0_xf);
SpaceIter iter = space_iter_begin_aabb(space, aabb); SpaceIter iter = BeginSpaceIterAabb(space, aabb);
SpaceEntry *space_entry; SpaceEntry *space_entry;
while ((space_entry = space_iter_next(&iter)) != 0) while ((space_entry = NextSpaceIterAabb(&iter)) != 0)
{ {
Entity *check1 = EntityFromId(ss, space_entry->ent); Entity *check1 = EntityFromId(ss, space_entry->ent);
if (!IsValidAndActive(check1)) continue; if (!IsValidAndActive(check1)) continue;
@ -287,7 +287,7 @@ void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteratio
} }
#endif #endif
} }
space_iter_end(&iter); EndSpaceIter(&iter);
} }
} }
@ -1249,9 +1249,9 @@ f32 DetermineEarliestToi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_i
Aabb aabb_t1 = CLD_AabbFromShape(&e0_collider, e0_xf_t1); Aabb aabb_t1 = CLD_AabbFromShape(&e0_collider, e0_xf_t1);
Aabb combined_aabb = CLD_CombineAabb(aabb_t0, aabb_t1); Aabb combined_aabb = CLD_CombineAabb(aabb_t0, aabb_t1);
SpaceIter iter = space_iter_begin_aabb(space, combined_aabb); SpaceIter iter = BeginSpaceIterAabb(space, combined_aabb);
SpaceEntry *entry; SpaceEntry *entry;
while ((entry = space_iter_next(&iter)) != 0) while ((entry = NextSpaceIterAabb(&iter)) != 0)
{ {
Entity *e1 = EntityFromId(ss, entry->ent); Entity *e1 = EntityFromId(ss, entry->ent);
if (!ShouldSimulate(e1)) continue; if (!ShouldSimulate(e1)) continue;
@ -1269,7 +1269,7 @@ f32 DetermineEarliestToi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_i
smallest_t = t; smallest_t = t;
} }
} }
space_iter_end(&iter); EndSpaceIter(&iter);
} }
return smallest_t; return smallest_t;
@ -1290,14 +1290,14 @@ void UpdateAabbs(PhysStepCtx *ctx)
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 = SpaceEntryFromHandle(space, ent->space_handle);
if (!space_entry->valid) if (!space_entry->valid)
{ {
space_entry = space_entry_acquire(space, ent->id); space_entry = AcquireSpaceEntry(space, ent->id);
ent->space_handle = space_entry->handle; ent->space_handle = space_entry->handle;
} }
Aabb aabb = CLD_AabbFromShape(&ent->local_collider, xf); Aabb aabb = CLD_AabbFromShape(&ent->local_collider, xf);
space_entry_update_aabb(space_entry, aabb); UpdateSpaceEntryAabb(space_entry, aabb);
} }
} }
} }

View File

@ -1,21 +1,16 @@
/* FIXME: Default space entry & cell pointers to nil */ /* FIXME: Default space entry & cell pointers to nil */
/* Offset in bytes from start of space struct to start of entry array (assume adjacently allocated) */ Readonly SpaceEntry _g_space_entry_nil = ZI;
#define SPACE_ENTRIES_OFFSET (sizeof(Space) + (sizeof(Space) % alignof(SpaceEntry))) Readonly SpaceCell _g_space_cell_nil = ZI;
Readonly Space _g_space_nil = ZI;
/* Accessed via NilEntity() */ ////////////////////////////////
Readonly SpaceEntry _g_space_entry_nil = { .valid = 0 }; //~ Space
Readonly SpaceCell _g_space_cell_nil = { .valid = 0 };
Readonly Space _g_space_nil = { .valid = 0 };
/* ========================== *
* Space alloc
* ========================== */
/* NOTE: /* NOTE:
* The number of bins determines how often tiles will collide in the spatial hash. * The number of bins determines how often tiles will collide in the spatial hash.
* For example, at `num_bins_sqrt` = 256 (65536 bins), tiles <1, 1>, <1, 257>, and <257, 257> will collide. */ * For example, at `num_bins_sqrt` = 256 (65536 bins), tiles <1, 1>, <1, 257>, and <257, 257> will collide. */
Space *space_acquire(f32 cell_size, u32 num_bins_sqrt) Space *AcquireSpace(f32 cell_size, u32 num_bins_sqrt)
{ {
Space *space; Space *space;
{ {
@ -36,13 +31,13 @@ Space *space_acquire(f32 cell_size, u32 num_bins_sqrt)
return space; return space;
} }
void space_release(Space *space) void ReleaseSpace(Space *space)
{ {
ReleaseArena(space->cell_arena); ReleaseArena(space->cell_arena);
ReleaseArena(space->entry_arena); ReleaseArena(space->entry_arena);
} }
void space_reset(Space *space) void ResetSpace(Space *space)
{ {
PopTo(space->entry_arena, (u64)space->entries - (u64)ArenaBase(space->entry_arena)); PopTo(space->entry_arena, (u64)space->entries - (u64)ArenaBase(space->entry_arena));
ResetArena(space->cell_arena); ResetArena(space->cell_arena);
@ -53,23 +48,25 @@ void space_reset(Space *space)
space->first_free_entry = 0; space->first_free_entry = 0;
} }
Space *space_from_entry(SpaceEntry *entry) Space *SpaceFromEntry(SpaceEntry *entry)
{ {
if (entry->valid) { if (entry->valid)
{
u64 first_entry_addr = (u64)(entry - entry->handle.idx); u64 first_entry_addr = (u64)(entry - entry->handle.idx);
Space *space = (Space *)(first_entry_addr - SPACE_ENTRIES_OFFSET); Space *space = (Space *)(first_entry_addr - SpaceEntriesOffset);
Assert(space->entries == (SpaceEntry *)first_entry_addr); Assert(space->entries == (SpaceEntry *)first_entry_addr);
return space; return space;
} else { }
return space_nil(); else
{
return NilSpace();
} }
} }
/* ========================== * ////////////////////////////////
* Cell //~ Cell
* ========================== */
internal Vec2I32 world_to_cell_coords(f32 cell_size, Vec2 world_pos) Vec2I32 SpaceCellCoordsFromWorldCoords(f32 cell_size, Vec2 world_pos)
{ {
f32 x = world_pos.x; f32 x = world_pos.x;
f32 y = world_pos.y; f32 y = world_pos.y;
@ -78,7 +75,7 @@ internal Vec2I32 world_to_cell_coords(f32 cell_size, Vec2 world_pos)
return VEC2I32((i32)x, (i32)y); return VEC2I32((i32)x, (i32)y);
} }
internal i32 cell_coords_to_bin_index(Space *space, Vec2I32 cell_pos) i32 SpaceBinIndexFromCellCoords(Space *space, Vec2I32 cell_pos)
{ {
i32 num_bins_sqrt = space->num_bins_sqrt; i32 num_bins_sqrt = space->num_bins_sqrt;
@ -100,13 +97,15 @@ internal i32 cell_coords_to_bin_index(Space *space, Vec2I32 cell_pos)
return bin_index; return bin_index;
} }
SpaceCell *space_get_cell(Space *space, Vec2I32 cell_pos) SpaceCell *SpaceCellFromCellPos(Space *space, Vec2I32 cell_pos)
{ {
i32 bin_index = cell_coords_to_bin_index(space, cell_pos); i32 bin_index = SpaceBinIndexFromCellCoords(space, cell_pos);
SpaceCellBin *bin = &space->bins[bin_index]; SpaceCellBin *bin = &space->bins[bin_index];
SpaceCell *result = space_cell_nil(); SpaceCell *result = NilSpaceCell();
for (SpaceCell *n = bin->first_cell; n; n = n->next_in_bin) { for (SpaceCell *n = bin->first_cell; n; n = n->next_in_bin)
if (EqVec2I32(n->pos, cell_pos)) { {
if (EqVec2I32(n->pos, cell_pos))
{
result = n; result = n;
break; break;
} }
@ -114,34 +113,43 @@ SpaceCell *space_get_cell(Space *space, Vec2I32 cell_pos)
return result; return result;
} }
internal void space_cell_node_alloc(Vec2I32 cell_pos, SpaceEntry *entry) void AcquireSpaceCellNode(Vec2I32 cell_pos, SpaceEntry *entry)
{ {
Space *space = space_from_entry(entry); Space *space = SpaceFromEntry(entry);
i32 bin_index = cell_coords_to_bin_index(space, cell_pos); i32 bin_index = SpaceBinIndexFromCellCoords(space, cell_pos);
SpaceCellBin *bin = &space->bins[bin_index]; SpaceCellBin *bin = &space->bins[bin_index];
/* Find existing cell */ /* Find existing cell */
SpaceCell *cell = 0; SpaceCell *cell = 0;
for (SpaceCell *n = bin->first_cell; n; n = n->next_in_bin) { for (SpaceCell *n = bin->first_cell; n; n = n->next_in_bin)
if (EqVec2I32(n->pos, cell_pos)) { {
if (EqVec2I32(n->pos, cell_pos))
{
cell = n; cell = n;
break; break;
} }
} }
/* Acquire new cell if necessary */ /* Acquire new cell if necessary */
if (!cell) { if (!cell)
if (space->first_free_cell) { {
if (space->first_free_cell)
{
cell = space->first_free_cell; cell = space->first_free_cell;
space->first_free_cell = cell->next_free; space->first_free_cell = cell->next_free;
} else { }
else
{
cell = PushStructNoZero(space->cell_arena, SpaceCell); cell = PushStructNoZero(space->cell_arena, SpaceCell);
} }
ZeroStruct(cell); ZeroStruct(cell);
if (bin->last_cell) { if (bin->last_cell)
{
bin->last_cell->next_in_bin = cell; bin->last_cell->next_in_bin = cell;
cell->prev_in_bin = bin->last_cell; cell->prev_in_bin = bin->last_cell;
} else { }
else
{
bin->first_cell = cell; bin->first_cell = cell;
} }
bin->last_cell = cell; bin->last_cell = cell;
@ -153,10 +161,13 @@ internal void space_cell_node_alloc(Vec2I32 cell_pos, SpaceEntry *entry)
/* Acquire node */ /* Acquire node */
SpaceCellNode *node; SpaceCellNode *node;
{ {
if (space->first_free_cell_node) { if (space->first_free_cell_node)
{
node = space->first_free_cell_node; node = space->first_free_cell_node;
space->first_free_cell_node = node->next_free; space->first_free_cell_node = node->next_free;
} else { }
else
{
node = PushStructNoZero(space->cell_arena, SpaceCellNode); node = PushStructNoZero(space->cell_arena, SpaceCellNode);
} }
ZeroStruct(node); ZeroStruct(node);
@ -164,44 +175,56 @@ internal void space_cell_node_alloc(Vec2I32 cell_pos, SpaceEntry *entry)
/* Insert into cell list */ /* Insert into cell list */
node->cell = cell; node->cell = cell;
if (cell->last_node) { if (cell->last_node)
{
cell->last_node->next_in_cell = node; cell->last_node->next_in_cell = node;
node->prev_in_cell = cell->last_node; node->prev_in_cell = cell->last_node;
} else { }
else
{
cell->first_node = node; cell->first_node = node;
} }
cell->last_node = node; cell->last_node = node;
/* Insert into entry list */ /* Insert into entry list */
node->entry = entry; node->entry = entry;
if (entry->last_node) { if (entry->last_node)
{
entry->last_node->next_in_entry = node; entry->last_node->next_in_entry = node;
node->prev_in_entry = entry->last_node; node->prev_in_entry = entry->last_node;
} else { }
else
{
entry->first_node = node; entry->first_node = node;
} }
entry->last_node = node; entry->last_node = node;
} }
internal void space_cell_node_release(SpaceCellNode *n) void ReleaseSpaceCellNode(SpaceCellNode *n)
{ {
SpaceCell *cell = n->cell; SpaceCell *cell = n->cell;
SpaceEntry *entry = n->entry; SpaceEntry *entry = n->entry;
Space *space = space_from_entry(entry); Space *space = SpaceFromEntry(entry);
SpaceCellBin *bin = cell->bin; SpaceCellBin *bin = cell->bin;
/* Remove from entry list */ /* Remove from entry list */
{ {
SpaceCellNode *prev = n->prev_in_entry; SpaceCellNode *prev = n->prev_in_entry;
SpaceCellNode *next = n->next_in_entry; SpaceCellNode *next = n->next_in_entry;
if (prev) { if (prev)
{
prev->next_in_entry = next; prev->next_in_entry = next;
} else { }
else
{
entry->first_node = next; entry->first_node = next;
} }
if (next) { if (next)
{
next->prev_in_entry = prev; next->prev_in_entry = prev;
} else { }
else
{
entry->last_node = prev; entry->last_node = prev;
} }
} }
@ -210,31 +233,44 @@ internal void space_cell_node_release(SpaceCellNode *n)
{ {
SpaceCellNode *prev = n->prev_in_cell; SpaceCellNode *prev = n->prev_in_cell;
SpaceCellNode *next = n->next_in_cell; SpaceCellNode *next = n->next_in_cell;
if (prev) { if (prev)
{
prev->next_in_cell = next; prev->next_in_cell = next;
} else { }
else
{
cell->first_node = next; cell->first_node = next;
} }
if (next) { if (next)
{
next->prev_in_cell = prev; next->prev_in_cell = prev;
} else { }
else
{
cell->last_node = prev; cell->last_node = prev;
} }
} }
/* If cell is now empty, release it */ /* If cell is now empty, release it */
if (!cell->first_node && !cell->last_node) { if (!cell->first_node && !cell->last_node)
{
/* Remove from bin */ /* Remove from bin */
SpaceCell *prev = cell->prev_in_bin; SpaceCell *prev = cell->prev_in_bin;
SpaceCell *next = cell->next_in_bin; SpaceCell *next = cell->next_in_bin;
if (prev) { if (prev)
{
prev->next_in_bin = next; prev->next_in_bin = next;
} else { }
else
{
bin->first_cell = next; bin->first_cell = next;
} }
if (next) { if (next)
{
next->prev_in_bin = prev; next->prev_in_bin = prev;
} else { }
else
{
bin->last_cell = prev; bin->last_cell = prev;
} }
cell->valid = 0; cell->valid = 0;
@ -249,17 +285,18 @@ internal void space_cell_node_release(SpaceCellNode *n)
space->first_free_cell_node = n; space->first_free_cell_node = n;
} }
/* ========================== * ////////////////////////////////
* Entry //~ Entry
* ========================== */
SpaceEntry *space_entry_from_handle(Space *space, SpaceEntryHandle handle) SpaceEntry *SpaceEntryFromHandle(Space *space, SpaceEntryHandle handle)
{ {
SpaceEntry *entry = space_entry_nil(); SpaceEntry *entry = NilSpaceEntry();
if (handle.gen > 0 && handle.idx < space->num_entries_reserved) { if (handle.gen > 0 && handle.idx < space->num_entries_reserved)
{
SpaceEntry *tmp = &space->entries[handle.idx]; SpaceEntry *tmp = &space->entries[handle.idx];
if (tmp->handle.gen == handle.gen) { if (tmp->handle.gen == handle.gen)
{
entry = tmp; entry = tmp;
} }
} }
@ -267,15 +304,18 @@ SpaceEntry *space_entry_from_handle(Space *space, SpaceEntryHandle handle)
return entry; return entry;
} }
SpaceEntry *space_entry_acquire(Space *space, EntityId ent) SpaceEntry *AcquireSpaceEntry(Space *space, EntityId ent)
{ {
SpaceEntry *entry = 0; SpaceEntry *entry = 0;
SpaceEntryHandle handle = ZI; SpaceEntryHandle handle = ZI;
if (space->first_free_entry) { if (space->first_free_entry)
{
entry = space->first_free_entry; entry = space->first_free_entry;
space->first_free_entry = entry->next_free; space->first_free_entry = entry->next_free;
handle = entry->handle; handle = entry->handle;
} else { }
else
{
entry = PushStructNoZero(space->entry_arena, SpaceEntry); entry = PushStructNoZero(space->entry_arena, SpaceEntry);
handle.idx = space->num_entries_reserved; handle.idx = space->num_entries_reserved;
handle.gen = 1; handle.gen = 1;
@ -288,61 +328,70 @@ SpaceEntry *space_entry_acquire(Space *space, EntityId ent)
return entry; return entry;
} }
void space_entry_release(SpaceEntry *entry) void ReleaseSpaceEntry(SpaceEntry *entry)
{ {
/* Release nodes */ /* Release nodes */
SpaceCellNode *n = entry->first_node; SpaceCellNode *n = entry->first_node;
while (n) { while (n)
{
SpaceCellNode *next = n->next_in_entry; SpaceCellNode *next = n->next_in_entry;
/* TODO: More efficient batch release that doesn't care about maintaining entry list */ /* TODO: More efficient batch release that doesn't care about maintaining entry list */
space_cell_node_release(n); ReleaseSpaceCellNode(n);
n = next; n = next;
} }
Space *space = space_from_entry(entry); Space *space = SpaceFromEntry(entry);
entry->next_free = space->first_free_entry; entry->next_free = space->first_free_entry;
entry->valid = 0; entry->valid = 0;
++entry->handle.gen; ++entry->handle.gen;
space->first_free_entry = entry; space->first_free_entry = entry;
} }
void space_entry_update_aabb(SpaceEntry *entry, Aabb new_aabb) void UpdateSpaceEntryAabb(SpaceEntry *entry, Aabb new_aabb)
{ {
Space *space = space_from_entry(entry); Space *space = SpaceFromEntry(entry);
f32 cell_size = space->cell_size; f32 cell_size = space->cell_size;
Vec2I32 old_cell_p0 = VEC2I32(0, 0); Vec2I32 old_cell_p0 = VEC2I32(0, 0);
Vec2I32 old_cell_p1 = VEC2I32(0, 0); Vec2I32 old_cell_p1 = VEC2I32(0, 0);
if (entry->first_node) { if (entry->first_node)
{
Aabb old_aabb = entry->aabb; Aabb old_aabb = entry->aabb;
old_cell_p0 = world_to_cell_coords(cell_size, old_aabb.p0); old_cell_p0 = SpaceCellCoordsFromWorldCoords(cell_size, old_aabb.p0);
old_cell_p1 = world_to_cell_coords(cell_size, old_aabb.p1); old_cell_p1 = SpaceCellCoordsFromWorldCoords(cell_size, old_aabb.p1);
} }
Vec2I32 new_cell_p0 = world_to_cell_coords(cell_size, new_aabb.p0); Vec2I32 new_cell_p0 = SpaceCellCoordsFromWorldCoords(cell_size, new_aabb.p0);
Vec2I32 new_cell_p1 = world_to_cell_coords(cell_size, new_aabb.p1); Vec2I32 new_cell_p1 = SpaceCellCoordsFromWorldCoords(cell_size, new_aabb.p1);
/* Release outdated nodes */ /* Release outdated nodes */
SpaceCellNode *n = entry->first_node; SpaceCellNode *n = entry->first_node;
while (n) { while (n)
{
SpaceCell *cell = n->cell; SpaceCell *cell = n->cell;
Vec2I32 cell_pos = cell->pos; Vec2I32 cell_pos = cell->pos;
if (cell_pos.x < new_cell_p0.x || cell_pos.x > new_cell_p1.x || cell_pos.y < new_cell_p0.y || cell_pos.y > new_cell_p1.y) { if (cell_pos.x < new_cell_p0.x || cell_pos.x > new_cell_p1.x || cell_pos.y < new_cell_p0.y || cell_pos.y > new_cell_p1.y)
{
/* Cell is outside of new AABB */ /* Cell is outside of new AABB */
SpaceCellNode *next = n->next_in_entry; SpaceCellNode *next = n->next_in_entry;
space_cell_node_release(n); ReleaseSpaceCellNode(n);
n = next; n = next;
} else { }
else
{
n = n->next_in_entry; n = n->next_in_entry;
} }
} }
/* Insert new nodes */ /* Insert new nodes */
for (i32 y = new_cell_p0.y; y <= new_cell_p1.y; ++y) { for (i32 y = new_cell_p0.y; y <= new_cell_p1.y; ++y)
for (i32 x = new_cell_p0.x; x <= new_cell_p1.x; ++x) { {
if (x != 0 && y != 0 && (x < old_cell_p0.x || x > old_cell_p1.x || y < old_cell_p0.y || y > old_cell_p1.y)) { for (i32 x = new_cell_p0.x; x <= new_cell_p1.x; ++x)
{
if (x != 0 && y != 0 && (x < old_cell_p0.x || x > old_cell_p1.x || y < old_cell_p0.y || y > old_cell_p1.y))
{
/* Cell is outside of old AABB */ /* Cell is outside of old AABB */
space_cell_node_alloc(VEC2I32(x, y), entry); AcquireSpaceCellNode(VEC2I32(x, y), entry);
} }
} }
} }
@ -350,19 +399,19 @@ void space_entry_update_aabb(SpaceEntry *entry, Aabb new_aabb)
entry->aabb = new_aabb; entry->aabb = new_aabb;
} }
/* ========================== * ////////////////////////////////
* Iter //~ Iter
* ========================== */
SpaceIter space_iter_begin_aabb(Space *space, Aabb aabb) SpaceIter BeginSpaceIterAabb(Space *space, Aabb aabb)
{ {
SpaceIter iter = ZI; SpaceIter iter = ZI;
f32 cell_size = space->cell_size; f32 cell_size = space->cell_size;
iter.space = space; iter.space = space;
iter.cell_start = world_to_cell_coords(cell_size, aabb.p0); iter.cell_start = SpaceCellCoordsFromWorldCoords(cell_size, aabb.p0);
iter.cell_end = world_to_cell_coords(cell_size, aabb.p1); iter.cell_end = SpaceCellCoordsFromWorldCoords(cell_size, aabb.p1);
if (iter.cell_start.x > iter.cell_end.x || iter.cell_start.y > iter.cell_end.y) { if (iter.cell_start.x > iter.cell_end.x || iter.cell_start.y > iter.cell_end.y)
{
/* Swap cell_start & cell_end */ /* Swap cell_start & cell_end */
Vec2I32 tmp = iter.cell_start; Vec2I32 tmp = iter.cell_start;
iter.cell_start = iter.cell_end; iter.cell_start = iter.cell_end;
@ -377,7 +426,7 @@ SpaceIter space_iter_begin_aabb(Space *space, Aabb aabb)
return iter; return iter;
} }
SpaceEntry *space_iter_next(SpaceIter *iter) SpaceEntry *NextSpaceIterAabb(SpaceIter *iter)
{ {
Space *space = iter->space; Space *space = iter->space;
Aabb iter_aabb = iter->aabb; Aabb iter_aabb = iter->aabb;
@ -387,36 +436,49 @@ SpaceEntry *space_iter_next(SpaceIter *iter)
i32 span = cell_end.x - cell_start.x; i32 span = cell_end.x - cell_start.x;
SpaceCellNode *next_node = 0; SpaceCellNode *next_node = 0;
if (cell_cur.x >= cell_start.x && cell_cur.x <= cell_end.x && cell_cur.y >= cell_start.y && cell_cur.y <= cell_end.y) { if (cell_cur.x >= cell_start.x && cell_cur.x <= cell_end.x && cell_cur.y >= cell_start.y && cell_cur.y <= cell_end.y)
{
/* Started */ /* Started */
Assert(iter->prev != 0); Assert(iter->prev != 0);
next_node = iter->prev->next_in_cell; next_node = iter->prev->next_in_cell;
} else if (cell_cur.x > cell_end.x || cell_cur.y > cell_end.y) { }
else if (cell_cur.x > cell_end.x || cell_cur.y > cell_end.y)
{
/* Ended */ /* Ended */
return 0; return 0;
} }
for (;;) { for (;;)
if (next_node) { {
if (next_node)
{
SpaceEntry *entry = next_node->entry; SpaceEntry *entry = next_node->entry;
Aabb entry_aabb = entry->aabb; Aabb entry_aabb = entry->aabb;
if (CLD_TestAabb(entry_aabb, iter_aabb)) { if (CLD_TestAabb(entry_aabb, iter_aabb))
{
break; break;
} else { }
else
{
next_node = next_node->next_in_cell; next_node = next_node->next_in_cell;
} }
} else { }
else
{
/* Reached end of cell, find next cell */ /* Reached end of cell, find next cell */
b32 nextx = (cell_cur.x + 1) <= cell_end.x; b32 nextx = (cell_cur.x + 1) <= cell_end.x;
b32 nexty = (nextx == 0) && ((cell_cur.y + 1) <= cell_end.y); b32 nexty = (nextx == 0) && ((cell_cur.y + 1) <= cell_end.y);
if (nextx || nexty) { if (nextx || nexty)
{
cell_cur.x += nextx - (span * nexty); cell_cur.x += nextx - (span * nexty);
cell_cur.y += nexty; cell_cur.y += nexty;
cell_cur.x += (cell_cur.x == 0); cell_cur.x += (cell_cur.x == 0);
cell_cur.y += (cell_cur.y == 0); cell_cur.y += (cell_cur.y == 0);
SpaceCell *cell = space_get_cell(space, cell_cur); SpaceCell *cell = SpaceCellFromCellPos(space, cell_cur);
next_node = cell->first_node; next_node = cell->first_node;
} else { }
else
{
/* Reached end of iter */ /* Reached end of iter */
cell_cur.x += 1; cell_cur.x += 1;
cell_cur.y += 1; cell_cur.y += 1;

View File

@ -1,17 +1,19 @@
typedef struct SpaceEntryHandle SpaceEntryHandle; ////////////////////////////////
struct SpaceEntryHandle { //~ Space entry types
Struct(SpaceEntryHandle)
{
u64 idx; u64 idx;
u64 gen; u64 gen;
}; };
typedef struct SpaceCellNode SpaceCellNode; Struct(SpaceEntry)
typedef struct SpaceEntry SpaceEntry; {
struct SpaceEntry {
b32 valid; b32 valid;
SpaceEntryHandle handle; SpaceEntryHandle handle;
SpaceCellNode *first_node; struct SpaceCellNode *first_node;
SpaceCellNode *last_node; struct SpaceCellNode *last_node;
Aabb aabb; Aabb aabb;
EntityId ent; EntityId ent;
@ -19,13 +21,15 @@ struct SpaceEntry {
SpaceEntry *next_free; SpaceEntry *next_free;
}; };
////////////////////////////////
//~ Space cell types
/* Links a cell to a entry. /* Links a cell to a entry.
* Acts as both a node in the list of entries contained by the cell, and a node in the list of cells containing the entry. */ * Acts as both a node in the list of entries contained by the cell, and a node in the list of cells containing the entry. */
typedef struct SpaceCell SpaceCell; Struct(SpaceCellNode)
typedef struct SpaceCellNode SpaceCellNode; {
struct SpaceCellNode {
SpaceEntry *entry; SpaceEntry *entry;
SpaceCell *cell; struct SpaceCell *cell;
/* For list of all entries contained by cell */ /* For list of all entries contained by cell */
SpaceCellNode *prev_in_cell; SpaceCellNode *prev_in_cell;
@ -38,30 +42,32 @@ struct SpaceCellNode {
SpaceCellNode *next_free; SpaceCellNode *next_free;
}; };
typedef struct SpaceCellBin SpaceCellBin; Struct(SpaceCell)
typedef struct SpaceCell SpaceCell; {
struct SpaceCell {
b32 valid; b32 valid;
Vec2I32 pos; Vec2I32 pos;
SpaceCellNode *first_node; SpaceCellNode *first_node;
SpaceCellNode *last_node; SpaceCellNode *last_node;
SpaceCellBin *bin; struct SpaceCellBin *bin;
SpaceCell *prev_in_bin; SpaceCell *prev_in_bin;
SpaceCell *next_in_bin; SpaceCell *next_in_bin;
SpaceCell *next_free; SpaceCell *next_free;
}; };
typedef struct SpaceCellBin SpaceCellBin; Struct(SpaceCellBin)
struct SpaceCellBin { {
SpaceCell *first_cell; SpaceCell *first_cell;
SpaceCell *last_cell; SpaceCell *last_cell;
}; };
typedef struct Space Space; ////////////////////////////////
struct Space { //~ Space types
Struct(Space)
{
b32 valid; b32 valid;
f32 cell_size; f32 cell_size;
@ -78,8 +84,8 @@ struct Space {
SpaceEntry *first_free_entry; SpaceEntry *first_free_entry;
}; };
typedef struct SpaceIter SpaceIter; Struct(SpaceIter)
struct SpaceIter { {
Aabb aabb; Aabb aabb;
Space *space; Space *space;
Vec2I32 cell_start; Vec2I32 cell_start;
@ -88,57 +94,66 @@ struct SpaceIter {
SpaceCellNode *prev; SpaceCellNode *prev;
}; };
/* ========================== * ////////////////////////////////
* Nil //~ Nil types
* ========================== */
Inline SpaceEntry *space_entry_nil(void) /* Offset in bytes from start of space struct to start of entry array (assume adjacently allocated) */
#define SpaceEntriesOffset (sizeof(Space) + (sizeof(Space) % alignof(SpaceEntry)))
/* Accessed via NilEntity() */
extern Readonly SpaceEntry _g_space_entry_nil;
extern Readonly SpaceCell _g_space_cell_nil;
extern Readonly Space _g_space_nil;
////////////////////////////////
//~ Nil helpers
Inline SpaceEntry *NilSpaceEntry(void)
{ {
extern Readonly SpaceEntry _g_space_entry_nil; extern Readonly SpaceEntry _g_space_entry_nil;
return &_g_space_entry_nil; return &_g_space_entry_nil;
} }
Inline SpaceCell *space_cell_nil(void) Inline SpaceCell *NilSpaceCell(void)
{ {
extern Readonly SpaceCell _g_space_cell_nil; extern Readonly SpaceCell _g_space_cell_nil;
return &_g_space_cell_nil; return &_g_space_cell_nil;
} }
Inline Space *space_nil(void) Inline Space *NilSpace(void)
{ {
extern Readonly Space _g_space_nil; extern Readonly Space _g_space_nil;
return &_g_space_nil; return &_g_space_nil;
} }
/* ========================== * ////////////////////////////////
* Space //~ Space
* ========================== */
Space *space_acquire(f32 cell_size, u32 num_bins_sqrt); Space *AcquireSpace(f32 cell_size, u32 num_bins_sqrt);
void space_release(Space *space); void ReleaseSpace(Space *space);
void space_reset(Space *space); void ResetSpace(Space *space);
Space *SpaceFromEntry(SpaceEntry *entry);
Space *space_from_entry(SpaceEntry *entry); ////////////////////////////////
//~ Cell
/* ========================== * Vec2I32 SpaceCellCoordsFromWorldCoords(f32 cell_size, Vec2 world_pos);
* Cell i32 SpaceBinIndexFromCellCoords(Space *space, Vec2I32 cell_pos);
* ========================== */ SpaceCell *SpaceCellFromCellPos(Space *space, Vec2I32 cell_pos);
void AcquireSpaceCellNode(Vec2I32 cell_pos, SpaceEntry *entry);
void ReleaseSpaceCellNode(SpaceCellNode *n);
SpaceCell *space_get_cell(Space *space, Vec2I32 cell_pos); ////////////////////////////////
//~ Entry
/* ========================== * SpaceEntry *SpaceEntryFromHandle(Space *space, SpaceEntryHandle handle);
* Entry SpaceEntry *AcquireSpaceEntry(Space *space, EntityId ent);
* ========================== */ void ReleaseSpaceEntry(SpaceEntry *entry);
void UpdateSpaceEntryAabb(SpaceEntry *entry, Aabb new_aabb);
SpaceEntry *space_entry_from_handle(Space *space, SpaceEntryHandle handle); ////////////////////////////////
SpaceEntry *space_entry_acquire(Space *space, EntityId entity); //~ Iter
void space_entry_release(SpaceEntry *entry);
void space_entry_update_aabb(SpaceEntry *entry, Aabb new_aabb);
/* ========================== * SpaceIter BeginSpaceIterAabb(Space *space, Aabb aabb);
* Iter SpaceEntry *NextSpaceIterAabb(SpaceIter *iter);
* ========================== */ #define EndSpaceIter(i)
SpaceIter space_iter_begin_aabb(Space *space, Aabb aabb);
SpaceEntry *space_iter_next(SpaceIter *iter);
#define space_iter_end(i)

View File

@ -4,18 +4,18 @@
SimAccel AcquireSimAccel(void) SimAccel AcquireSimAccel(void)
{ {
SimAccel accel = ZI; SimAccel accel = ZI;
accel.space = space_acquire(SPACE_CELL_SIZE, SPACE_CELL_BINS_SQRT); accel.space = AcquireSpace(SPACE_CELL_SIZE, SPACE_CELL_BINS_SQRT);
return accel; return accel;
} }
void ReleaseSimAccel(SimAccel *accel) void ReleaseSimAccel(SimAccel *accel)
{ {
space_release(accel->space); ReleaseSpace(accel->space);
} }
void ResetSimAccel(Snapshot *ss, SimAccel *accel) void ResetSimAccel(Snapshot *ss, SimAccel *accel)
{ {
space_reset(accel->space); ResetSpace(accel->space);
/* Reset ent space handles */ /* Reset ent space handles */
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)

View File

@ -12,8 +12,7 @@ Struct(SimAccel)
//////////////////////////////// ////////////////////////////////
//~ Step ctx //~ Step ctx
typedef struct SimStepCtx SimStepCtx; Struct(SimStepCtx)
struct SimStepCtx
{ {
b32 is_master; b32 is_master;
SimAccel *accel; SimAccel *accel;