sort tile chunks by x & y separately to fix bug
This commit is contained in:
parent
d9f841dad6
commit
92bb82cdb4
293
src/sim_step.c
293
src/sim_step.c
@ -374,16 +374,29 @@ INTERNAL void test_spawn_tile(struct sim_snapshot *world, struct v2 world_pos)
|
||||
|
||||
|
||||
|
||||
INTERNAL SORT_COMPARE_FUNC_DEF(tile_chunk_sort, arg_a, arg_b, udata)
|
||||
INTERNAL SORT_COMPARE_FUNC_DEF(tile_chunk_sort_x, arg_a, arg_b, udata)
|
||||
{
|
||||
(UNUSED)udata;
|
||||
struct sim_ent *a = *(struct sim_ent **)arg_a;
|
||||
struct sim_ent *b = *(struct sim_ent **)arg_b;
|
||||
struct v2i32 index_a = a->tile_chunk_index;
|
||||
struct v2i32 index_b = b->tile_chunk_index;
|
||||
i32 a_x = a->tile_chunk_index.x;
|
||||
i32 b_x = b->tile_chunk_index.x;
|
||||
|
||||
i32 res = 0;
|
||||
res = 2 * ((index_a.y < index_b.y) - (index_a.y > index_b.y)) + ((index_a.x < index_b.x) - (index_a.x > index_b.x));
|
||||
res = (a_x < b_x) - (a_x > b_x);
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERNAL SORT_COMPARE_FUNC_DEF(tile_chunk_sort_y, arg_a, arg_b, udata)
|
||||
{
|
||||
(UNUSED)udata;
|
||||
struct sim_ent *a = *(struct sim_ent **)arg_a;
|
||||
struct sim_ent *b = *(struct sim_ent **)arg_b;
|
||||
i32 a_y = a->tile_chunk_index.y;
|
||||
i32 b_y = b->tile_chunk_index.y;
|
||||
|
||||
i32 res = 0;
|
||||
res = (a_y < b_y) - (a_y > b_y);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -403,10 +416,10 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
||||
}
|
||||
|
||||
/* Sort tile chunks */
|
||||
/* NOTE: We sort tile chunks from top-left to bottom-right so that cross
|
||||
/* NOTE: We sort tile chunks from left-right and top-bottom so that cross
|
||||
* chunk tile checks only have to happen in one direction (because we
|
||||
* know the left & top chunks have already been processed) */
|
||||
struct sim_ent **sorted_tile_chunks = arena_dry_push(scratch.arena, struct sim_ent *);
|
||||
struct sim_ent **x_sorted_tile_chunks = arena_dry_push(scratch.arena, struct sim_ent *);
|
||||
u64 sorted_tile_chunks_count = 0;
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
@ -416,7 +429,11 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
||||
++sorted_tile_chunks_count;
|
||||
}
|
||||
}
|
||||
merge_sort(sorted_tile_chunks, sorted_tile_chunks_count, sizeof(*sorted_tile_chunks), tile_chunk_sort, NULL);
|
||||
struct sim_ent **y_sorted_tile_chunks = arena_push_array_no_zero(scratch.arena, struct sim_ent *, sorted_tile_chunks_count);
|
||||
MEMCPY(y_sorted_tile_chunks, x_sorted_tile_chunks, sizeof(*x_sorted_tile_chunks) * sorted_tile_chunks_count);
|
||||
|
||||
merge_sort(x_sorted_tile_chunks, sorted_tile_chunks_count, sizeof(*x_sorted_tile_chunks), tile_chunk_sort_x, NULL);
|
||||
merge_sort(y_sorted_tile_chunks, sorted_tile_chunks_count, sizeof(*y_sorted_tile_chunks), tile_chunk_sort_y, NULL);
|
||||
|
||||
struct wall_node {
|
||||
struct v2i32 start;
|
||||
@ -433,150 +450,150 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
||||
|
||||
/* Generate horizontal wall nodes */
|
||||
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
||||
struct sim_ent *chunk = sorted_tile_chunks[sorted_index];
|
||||
struct sim_ent *chunk = x_sorted_tile_chunks[sorted_index];
|
||||
struct v2i32 chunk_index = chunk->tile_chunk_index;
|
||||
/* Generate horizontal wall nodes */
|
||||
{
|
||||
struct sim_ent *top_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x, chunk_index.y - 1));
|
||||
struct sim_ent *bottom_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x, chunk_index.y + 1));
|
||||
/* If there's no chunk below this one, then do an extra iteration (since walls are created at the top of each tile) */
|
||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + !bottom_chunk->valid;
|
||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||
for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
|
||||
i32 wall_start = -1;
|
||||
i32 wall_end = -1;
|
||||
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
|
||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
||||
}
|
||||
b32 should_have_top_wall = false;
|
||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
enum sim_tile_kind top_tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_y == 0) {
|
||||
if (top_chunk->valid) {
|
||||
struct v2i32 top_tile_local_index = V2I32(tile_x, SIM_TILES_PER_CHUNK_SQRT - 1);
|
||||
top_tile = sim_get_chunk_tile(top_chunk, top_tile_local_index);
|
||||
}
|
||||
} else {
|
||||
top_tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y - 1));
|
||||
struct sim_ent *top_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x, chunk_index.y - 1));
|
||||
struct sim_ent *bottom_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x, chunk_index.y + 1));
|
||||
/* If there's no chunk below this one, then do an extra iteration (since walls are created at the top of each tile) */
|
||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + !bottom_chunk->valid;
|
||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||
for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
|
||||
i32 wall_start = -1;
|
||||
i32 wall_end = -1;
|
||||
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
|
||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
||||
}
|
||||
b32 should_have_top_wall = false;
|
||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
enum sim_tile_kind top_tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_y == 0) {
|
||||
if (top_chunk->valid) {
|
||||
struct v2i32 top_tile_local_index = V2I32(tile_x, SIM_TILES_PER_CHUNK_SQRT - 1);
|
||||
top_tile = sim_get_chunk_tile(top_chunk, top_tile_local_index);
|
||||
}
|
||||
if (tile == SIM_TILE_KIND_WALL) {
|
||||
/* Process wall tile */
|
||||
should_have_top_wall = top_tile != SIM_TILE_KIND_WALL;
|
||||
} else {
|
||||
/* Process non-wall tile */
|
||||
should_have_top_wall = top_tile == SIM_TILE_KIND_WALL;
|
||||
} else {
|
||||
top_tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y - 1));
|
||||
}
|
||||
if (tile == SIM_TILE_KIND_WALL) {
|
||||
/* Process wall tile */
|
||||
should_have_top_wall = top_tile != SIM_TILE_KIND_WALL;
|
||||
} else {
|
||||
/* Process non-wall tile */
|
||||
should_have_top_wall = top_tile == SIM_TILE_KIND_WALL;
|
||||
}
|
||||
}
|
||||
if (should_have_top_wall) {
|
||||
if (wall_start < 0) {
|
||||
/* Start wall */
|
||||
wall_start = tile_x;
|
||||
}
|
||||
/* Extend wall */
|
||||
wall_end = tile_x + 1;
|
||||
} else if (wall_end >= 0) {
|
||||
/* Stop wall */
|
||||
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_start, tile_y));
|
||||
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_end, tile_y));
|
||||
struct wall_node *node = NULL;
|
||||
if (wall_start == 0) {
|
||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
||||
struct dict_entry *entry = dict_get_entry(&horizontal_ends_dict, start_hash);
|
||||
if (entry) {
|
||||
/* Existing wall exists accross chunk boundary */
|
||||
node = (struct wall_node *)entry->value;
|
||||
dict_remove_entry(&horizontal_ends_dict, entry);
|
||||
}
|
||||
}
|
||||
if (should_have_top_wall) {
|
||||
if (wall_start < 0) {
|
||||
/* Start wall */
|
||||
wall_start = tile_x;
|
||||
}
|
||||
/* Extend wall */
|
||||
wall_end = tile_x + 1;
|
||||
} else if (wall_end >= 0) {
|
||||
/* Stop wall */
|
||||
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_start, tile_y));
|
||||
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_end, tile_y));
|
||||
struct wall_node *node = NULL;
|
||||
if (wall_start == 0) {
|
||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
||||
struct dict_entry *entry = dict_get_entry(&horizontal_ends_dict, start_hash);
|
||||
if (entry) {
|
||||
/* Existing wall exists accross chunk boundary */
|
||||
node = (struct wall_node *)entry->value;
|
||||
dict_remove_entry(&horizontal_ends_dict, entry);
|
||||
}
|
||||
}
|
||||
if (!node) {
|
||||
node = arena_push(scratch.arena, struct wall_node);
|
||||
node->start = start;
|
||||
node->next = first_wall;
|
||||
first_wall = node;
|
||||
}
|
||||
node->end = end;
|
||||
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
||||
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
||||
dict_set(scratch.arena, &horizontal_ends_dict, end_hash, node);
|
||||
}
|
||||
wall_start = -1;
|
||||
wall_end = -1;
|
||||
if (!node) {
|
||||
node = arena_push(scratch.arena, struct wall_node);
|
||||
node->start = start;
|
||||
node->next = first_wall;
|
||||
first_wall = node;
|
||||
}
|
||||
node->end = end;
|
||||
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
||||
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
||||
dict_set(scratch.arena, &horizontal_ends_dict, end_hash, node);
|
||||
}
|
||||
wall_start = -1;
|
||||
wall_end = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Generate vertical wall nodes */
|
||||
{
|
||||
struct sim_ent *left_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x - 1, chunk_index.y));
|
||||
struct sim_ent *right_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x + 1, chunk_index.y));
|
||||
/* If there's no chunk to the right of this one, then do an extra iteration (since walls are created on the left of each tile) */
|
||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + !right_chunk->valid;
|
||||
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
|
||||
i32 wall_start = -1;
|
||||
i32 wall_end = -1;
|
||||
for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
|
||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
||||
}
|
||||
}
|
||||
|
||||
b32 should_have_left_wall = false;
|
||||
if (tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
enum sim_tile_kind left_tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_x == 0) {
|
||||
if (left_chunk->valid) {
|
||||
struct v2i32 left_tile_local_index = V2I32(SIM_TILES_PER_CHUNK_SQRT - 1, tile_y);
|
||||
left_tile = sim_get_chunk_tile(left_chunk, left_tile_local_index);
|
||||
}
|
||||
} else {
|
||||
left_tile = sim_get_chunk_tile(chunk, V2I32(tile_x - 1, tile_y));
|
||||
/* Generate vertical wall nodes */
|
||||
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
||||
struct sim_ent *chunk = y_sorted_tile_chunks[sorted_index];
|
||||
struct v2i32 chunk_index = chunk->tile_chunk_index;
|
||||
struct sim_ent *left_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x - 1, chunk_index.y));
|
||||
struct sim_ent *right_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x + 1, chunk_index.y));
|
||||
/* If there's no chunk to the right of this one, then do an extra iteration (since walls are created on the left of each tile) */
|
||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + !right_chunk->valid;
|
||||
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
|
||||
i32 wall_start = -1;
|
||||
i32 wall_end = -1;
|
||||
for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
|
||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
||||
}
|
||||
|
||||
b32 should_have_left_wall = false;
|
||||
if (tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||
enum sim_tile_kind left_tile = SIM_TILE_KIND_NONE;
|
||||
if (tile_x == 0) {
|
||||
if (left_chunk->valid) {
|
||||
struct v2i32 left_tile_local_index = V2I32(SIM_TILES_PER_CHUNK_SQRT - 1, tile_y);
|
||||
left_tile = sim_get_chunk_tile(left_chunk, left_tile_local_index);
|
||||
}
|
||||
if (tile == SIM_TILE_KIND_WALL) {
|
||||
/* Process wall tile */
|
||||
should_have_left_wall = left_tile != SIM_TILE_KIND_WALL;
|
||||
} else {
|
||||
/* Process non-wall tile */
|
||||
should_have_left_wall = left_tile == SIM_TILE_KIND_WALL;
|
||||
} else {
|
||||
left_tile = sim_get_chunk_tile(chunk, V2I32(tile_x - 1, tile_y));
|
||||
}
|
||||
if (tile == SIM_TILE_KIND_WALL) {
|
||||
/* Process wall tile */
|
||||
should_have_left_wall = left_tile != SIM_TILE_KIND_WALL;
|
||||
} else {
|
||||
/* Process non-wall tile */
|
||||
should_have_left_wall = left_tile == SIM_TILE_KIND_WALL;
|
||||
}
|
||||
}
|
||||
if (should_have_left_wall) {
|
||||
if (wall_start < 0) {
|
||||
/* Start wall */
|
||||
wall_start = tile_y;
|
||||
}
|
||||
/* Extend wall */
|
||||
wall_end = tile_y + 1;
|
||||
} else if (wall_end >= 0) {
|
||||
/* Stop wall */
|
||||
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_start));
|
||||
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_end));
|
||||
struct wall_node *node = NULL;
|
||||
if (wall_start == 0) {
|
||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
||||
struct dict_entry *entry = dict_get_entry(&vertical_ends_dict, start_hash);
|
||||
if (entry) {
|
||||
/* Existing wall exists accross chunk boundary */
|
||||
node = (struct wall_node *)entry->value;
|
||||
dict_remove_entry(&vertical_ends_dict, entry);
|
||||
}
|
||||
}
|
||||
if (should_have_left_wall) {
|
||||
if (wall_start < 0) {
|
||||
/* Start wall */
|
||||
wall_start = tile_y;
|
||||
}
|
||||
/* Extend wall */
|
||||
wall_end = tile_y + 1;
|
||||
} else if (wall_end >= 0) {
|
||||
/* Stop wall */
|
||||
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_start));
|
||||
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_end));
|
||||
struct wall_node *node = NULL;
|
||||
if (wall_start == 0) {
|
||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
||||
struct dict_entry *entry = dict_get_entry(&vertical_ends_dict, start_hash);
|
||||
if (entry) {
|
||||
/* Existing wall exists accross chunk boundary */
|
||||
node = (struct wall_node *)entry->value;
|
||||
dict_remove_entry(&vertical_ends_dict, entry);
|
||||
}
|
||||
}
|
||||
if (!node) {
|
||||
node = arena_push(scratch.arena, struct wall_node);
|
||||
node->start = start;
|
||||
node->next = first_wall;
|
||||
first_wall = node;
|
||||
}
|
||||
node->end = end;
|
||||
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
||||
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
||||
dict_set(scratch.arena, &vertical_ends_dict, end_hash, node);
|
||||
}
|
||||
wall_start = -1;
|
||||
wall_end = -1;
|
||||
if (!node) {
|
||||
node = arena_push(scratch.arena, struct wall_node);
|
||||
node->start = start;
|
||||
node->next = first_wall;
|
||||
first_wall = node;
|
||||
}
|
||||
node->end = end;
|
||||
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
||||
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
||||
dict_set(scratch.arena, &vertical_ends_dict, end_hash, node);
|
||||
}
|
||||
wall_start = -1;
|
||||
wall_end = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1861,9 +1861,6 @@ INTERNAL void user_update(void)
|
||||
|
||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Video memory usage: %F MiB"), FMT_FLOAT((f64)gstat_get(GSTAT_VRAM_USAGE) / 1024 / 1024)));
|
||||
pos.y += spacing;
|
||||
|
||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Video memory budget: %F GiB"), FMT_FLOAT((f64)gstat_get(GSTAT_VRAM_BUDGET) / 1024 / 1024 / 1024)));
|
||||
pos.y += spacing;
|
||||
pos.y += spacing;
|
||||
|
||||
#if 0
|
||||
|
||||
Loading…
Reference in New Issue
Block a user