From 165d54ab3796996e5324d948687c883f36bf686e Mon Sep 17 00:00:00 2001 From: Eric-Paul Ickhorn Date: Thu, 12 Oct 2023 18:52:05 +0200 Subject: [PATCH] The chunk system needs to be rewritten --- build.bash | 4 +- code/source-c/chunk_loading.c | 324 +++++++++++++++++++++++++++++++++ code/source-c/chunk_pool.c | 60 ++++++ code/source-c/initialization.c | 6 +- code/source-c/main.c | 12 +- code/source-c/meshize.c | 22 +-- code/source-c/noise.c | 23 +++ code/source-c/state.h | 2 +- code/source-c/world.c | 134 +++++++++----- code/source-c/world.h | 81 ++++++++- 10 files changed, 593 insertions(+), 75 deletions(-) create mode 100644 code/source-c/chunk_loading.c create mode 100644 code/source-c/chunk_pool.c create mode 100644 code/source-c/noise.c diff --git a/build.bash b/build.bash index df33d46..6d6f5d5 100644 --- a/build.bash +++ b/build.bash @@ -2,11 +2,11 @@ mkdir -p dependencies/build/ -gcc -g -o dependencies/build/glad.o \ +gcc -g3 -o dependencies/build/glad.o \ -c dependencies/sources/glad/glad.c \ -I dependencies/include/ -Wall -gcc -g -o techneck.elf \ +gcc -g3 -o techneck.elf \ code/source-c/*.c dependencies/build/glad.o \ -I dependencies/include -lGL -lSDL2 -lm -Wall diff --git a/code/source-c/chunk_loading.c b/code/source-c/chunk_loading.c new file mode 100644 index 0000000..1eb41bc --- /dev/null +++ b/code/source-c/chunk_loading.c @@ -0,0 +1,324 @@ +#include "world.h" + +#include +#include + +void tc_on_each_chunkloader(tc_world_s *world, bool (*fn_do)(tc_chunkloader_s *loader, void *userdata), void *userdata) +{ + for(uint32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index) + if(fn_do(&world->loaders[loader_index], userdata)) return; +} + +void tc_on_each_loaded_chunk(tc_world_s *world, bool (*fn_do)(tc_chunk_s *chunk, void *userdata), void *userdata) +{ + for(uint32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index) + for(uint32_t chunk_index = 0; chunk_index < world->loaders[loader_index].num_chunks; ++chunk_index) + if(fn_do(world->loaders[loader_index].chunks[chunk_index], userdata)) return; +} + +void tc_on_each_chunk_of_loader(tc_chunkloader_s *loader, bool (*fn_do)(tc_chunk_s *chunk, void *userdata), void *userdata) +{ + uint32_t chunk_index = 0; + while(chunk_index < loader->num_chunks) + { + if(fn_do(loader->chunks[chunk_index], userdata)) return; + ++chunk_index; + } +} + +// TODO: Create and use vectors + +typedef struct tc_chunk_grid_distance +{ + int32_t x; + int32_t y; + int32_t z; + +} tc_chunk_grid_distance_s; + +tc_chunk_grid_distance_s tc_chunk_distance_to( + int32_t first_x, int32_t first_y, int32_t first_z, + int32_t last_x, int32_t last_y, int32_t last_z +) { + tc_chunk_grid_distance_s distance; + distance.x = last_x - first_x; + distance.y = last_y - first_y; + distance.z = last_z - first_z; + + return distance; +} + +bool tc_chunk_coordinate_is_within_loaded_zone(tc_world_s *world, int32_t x, int32_t y, int32_t z) +{ + if((world->loading_center.x + world->load_radius) < x) return false; + if((world->loading_center.y + world->load_radius) < y) return false; + if((world->loading_center.z + world->load_radius) < z) return false; + if((world->loading_center.x - world->load_radius) > x) return false; + if((world->loading_center.y - world->load_radius) > y) return false; + if((world->loading_center.z - world->load_radius) > z) return false; + + return true; +} + +bool tc_chunk_exists(tc_world_s *world, int32_t x, int32_t y, int32_t z) +{ + uint32_t loader_index = 0; + while(loader_index < world->num_loaders) + { + tc_chunkloader_s *loader = &world->loaders[loader_index]; + + for(uint32_t chunk_index = 0; chunk_index < loader->num_chunks; ++chunk_index) + { + tc_chunk_s *chunk = loader->chunks[chunk_index]; + + if(chunk->position.x != x) continue; + if(chunk->position.y != y) continue; + if(chunk->position.z != z) continue; + + return true; + } + ++loader_index; + } + + return false; +} + +bool tc_chunk_is_loaded(tc_world_s *world, int32_t x, int32_t y, int32_t z) +{ + // TODO: Further checks + + if(!tc_chunk_coordinate_is_within_loaded_zone(world, x, y, z)) return false; + if(!tc_chunk_exists(world, x, y, z)) return false; + printf("Checked for a chunk at %d:%d:%d and found it!\n", x, y, z); + return true; +} + +bool tc_check_chunk_coordinate_equality_for_getting_a_loaded_chunk(tc_chunk_s *chunk, void *userdata) +{ + struct payload { + int32_t x; + int32_t y; + int32_t z; + tc_chunk_s *result; + } *payload = userdata; + + if(chunk->position.x != payload->x) return false; + if(chunk->position.y != payload->y) return false; + if(chunk->position.z != payload->z) return false; + payload->result = chunk; + return true; +} + +tc_chunk_s * tc_get_loaded_chunk_at(tc_world_s *world, int32_t x, int32_t y, int32_t z) +{ + struct payload { + int32_t x; + int32_t y; + int32_t z; + tc_chunk_s *result; + } payload; + + payload.x = x; + payload.y = y; + payload.z = z; + payload.result = NULL; + + tc_on_each_loaded_chunk(world, &tc_check_chunk_coordinate_equality_for_getting_a_loaded_chunk, &payload); + + return payload.result; +} + + /* + tc_chunk_s *chunk = tc_chunk_at_south_east_bottom(world); + + tc_chunk_grid_distance_s distance = tc_chunk_distance_to( + chunk->position.x, chunk->position.y, chunk->position.z, + x, y, z + ); + + while(distance.x > 0) + { + chunk = chunk->east; + --distance.x; + } + + while(distance.y > 0) + { + chunk = chunk->top; + --distance.y; + } + + while(distance.z > 0) + { + chunk = chunk->north; + --distance.z; + } + + return chunk; +void tc_reassociate_surrounding_chunks(tc_chunk_s *old_chunk, tc_chunk_s *chunk) +{ + if(old_chunk->top != NULL) old_chunk->top->bottom = chunk; + if(old_chunk->bottom != NULL) old_chunk->bottom->top = chunk; + + if(old_chunk->east != NULL) old_chunk->east->west = chunk; + if(old_chunk->west != NULL) old_chunk->west->east = chunk; + + if(old_chunk->north != NULL) old_chunk->north->south = chunk; + if(old_chunk->south != NULL) old_chunk->south->north = chunk; +} +*/ + +void tc_place_chunk_at(tc_world_s *world, tc_chunk_s *chunk, int32_t x, int32_t y, int32_t z) +{ + tc_chunk_s *old_chunk = tc_get_loaded_chunk_at(world, x, y, z); + // tc_reassociate_surrounding_chunks(old_chunk, chunk); + tc_free_chunk(world, old_chunk); +} + +tc_chunk_s * tc_create_chunk_at(tc_world_s *world, int32_t x, int32_t y, int32_t z) +{ + tc_chunk_s *chunk = tc_allocate_chunk(world); + chunk->position.x = x; + chunk->position.y = y; + chunk->position.z = z; + + world->worldgen->fn_generate_chunk(world->worldgen, chunk); + tc_upload_chunk(chunk); + tc_place_chunk_at(world, chunk, x, y, z); + + return chunk; +} + +tc_chunk_s * tc_load_chunk_at(tc_world_s *world, int32_t x, int32_t y, int32_t z) +{ + if(!tc_chunk_is_loaded(world, x, y, z)) + { + return tc_create_chunk_at(world, x, y, z); + } + return tc_get_loaded_chunk_at(world, x, y, z); +} + +// Creates & Generates a chunk and provides a pointer to it +tc_chunk_s * tc_new_chunk(tc_world_s *world, int32_t x, int32_t y, int32_t z) +{ + tc_chunk_s *chunk = tc_allocate_chunk(world); + chunk->position.x = x; + chunk->position.y = y; + chunk->position.z = z; + world->worldgen->fn_generate_chunk(world->worldgen, chunk); + + return chunk; +} +/*c_ +void tc_shift_chunks_on_axis_x(tc_world_s *world, int32_t difference) +{ + + + +} + +void tc_shift_chunks_on_axis_y(tc_world_s *world, int32_t difference) +{ + + + +} + +// Go one further west with loading +void tc_shift_loading_one_west(tc_world_s *world) +{ + tc_chunk_s *north_eastern = world->center_chunk; + while(north_eastern->east != NULL) north_eastern = north_eastern->east; + while(north_eastern->north != NULL) north_eastern = north_eastern->north; + + tc_chunk_s *north_western = world->center_chunk; + while(north_western->west != NULL) north_western = north_western->west; + while(north_western->north != NULL) north_western = north_western->north; + + tc_chunk_s *eastern_edge = north_eastern; + while((eastern_edge != NULL) && (western_edge != NULL)) + { + eastern_west = western_edge; + eastern_edge = eastern_edge->south; + western_edge = western_edge->south; + } + + // Load new row + while(north_eastern != NULL) + { + north_ + north_eastern = north_eastern->south; + } + + tc_load_chunk(); +} + +void tc_shift_chunks_on_axis_z(tc_world_s *world, int32_t difference) +{ + if(difference > 0) + { + for(; difference > 0; --difference) + tc_shift_one_west(world); + } + + if(difference < 0) + { + for(; difference < 0; ++difference) + tc_shift_one_east(world); + } +} +*/ + +tc_chunk_s * tc_reload_chunk_of_loader(tc_chunkloader_s *loader, int32_t x, int32_t y, int32_t z) +{ + + + +} + +void tc_reload_chunkloader_zone(tc_world_s *world, tc_chunkloader_s *chunkloader) +{ + int32_t last_x = chunkloader->center_x + chunkloader->width; + int32_t last_y = chunkloader->center_y + chunkloader->height; + int32_t last_z = chunkloader->center_z + chunkloader->depth; + + int32_t chunk_x = chunkloader->center_x - chunkloader->width; + while(chunk_x < last_x) + { + int32_t chunk_y = chunkloader->center_y - chunkloader->height; + while(chunk_y < last_y) + { + int32_t chunk_z = chunkloader->center_z - chunkloader->depth; + while(chunk_z < last_z) + { + tc_chunk_s *chunk = tc_get_loaded_chunk_at(world, chunk_x, chunk_y, chunk_z); + if(chunk == NULL) + { + chunk = tc_allocate_chunk(world); + chunk->position.x = chunk_x; + chunk->position.y = chunk_y; + chunk->position.z = chunk_z; + tc_add_chunk_to_loader(chunkloader, world); + } + ++chunk_z; + } + ++chunk_y; + } + ++chunk_x; + } +} + +void tc_update_world(tc_world_s *world) +{ + uint32_t chunkloader_index = 0; + while(chunkloader_index < world->num_loaders) + { + if(world->loaders[chunkloader_index].needs_reload) + { + tc_reload_chunkloader_zone(world, &world->loaders[chunkloader_index]); + } + ++chunkloader_index; + } +} + +// TODO: Set center chunk diff --git a/code/source-c/chunk_pool.c b/code/source-c/chunk_pool.c new file mode 100644 index 0000000..75abc7a --- /dev/null +++ b/code/source-c/chunk_pool.c @@ -0,0 +1,60 @@ +#include "world.h" + +#include + +void tc_reset_chunk_pool(tc_chunk_pool_s *chunk_pool) +{ + chunk_pool->used_entries = 0; + chunk_pool->first_free = chunk_pool->entries; + + uint32_t entry_index = 0; + while(entry_index < chunk_pool->capacity) + { + chunk_pool->entries[entry_index].next = &chunk_pool->entries[entry_index+1]; + chunk_pool->entries[entry_index].previous = &chunk_pool->entries[entry_index-1]; + ++entry_index; + } + + chunk_pool->entries[0].previous = NULL; + chunk_pool->entries[chunk_pool->capacity-1].next = NULL; +} + +tc_chunk_pool_s * tc_new_chunk_pool(uint32_t capacity) +{ + tc_chunk_pool_s *pool = malloc(sizeof(tc_chunk_pool_s)); + pool->capacity = capacity; + pool->entries = calloc(sizeof(tc_chunk_pool_entry_s), pool->capacity); + tc_reset_chunk_pool(pool); + + return pool; +} + +tc_chunk_pool_entry_s * tc_allocate_chunk_pool_entry(tc_chunk_pool_s *pool) +{ + if(pool->first_free == NULL) + { + pool->continuation = tc_new_chunk_pool(pool->capacity * 2); + return tc_allocate_chunk_pool_entry(pool->continuation); + } + tc_chunk_pool_entry_s *allocated = pool->first_free; + pool->first_free = allocated->next; + + return allocated; +} + +tc_chunk_s * tc_allocate_chunk(tc_world_s *world) +{ + tc_chunk_pool_entry_s *entry = tc_allocate_chunk_pool_entry(world->pool); + entry->chunk.superstructure = entry; + + return &entry->chunk; +} + +void tc_free_chunk(tc_world_s *world, tc_chunk_s *chunk) +{ + tc_chunk_pool_s *pool = world->pool; + + chunk->superstructure->next = pool->first_free; + pool->first_free = chunk->superstructure; +} + diff --git a/code/source-c/initialization.c b/code/source-c/initialization.c index 0ef411f..7195991 100644 --- a/code/source-c/initialization.c +++ b/code/source-c/initialization.c @@ -43,9 +43,6 @@ void tc_load_textures() tc_image_s *dirt = tc_create_subimage(tc_game_state_g.block_texture_atlas, 0, 0, 8, 8); dirt->name = "dirt"; - printf("POiNTA: %p!\n", dirt); - printf("Resolving from array: %p\n", tc_game_state_g.asset_storage.images); - tc_image_s *grass = tc_create_subimage(tc_game_state_g.block_texture_atlas, 8, 0, 8, 8); grass->name = "grass"; @@ -62,7 +59,8 @@ void tc_init() tc_load_textures(); tc_game_state_g.block_registry = tc_init_blocks(); tc_create_blocks(); - tc_game_state_g.main_world = tc_init_worlds(); + tc_init_worlds(); + tc_game_state_g.main_world = tc_new_world(&tc_default_terrain_generator_g); puts("Finished initializing!"); } diff --git a/code/source-c/main.c b/code/source-c/main.c index 200a81f..92ae38f 100644 --- a/code/source-c/main.c +++ b/code/source-c/main.c @@ -105,7 +105,7 @@ tc_block_s tc_new_block_at_3f(float x, float y, float z) void render() { - float color[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; + float color[4] = { 0.12f, 0.5f, 0.8f, 1.0f }; glClearBufferfv(GL_COLOR, 0, color); float depth = 10000000.0f; glClearBufferfv(GL_DEPTH, 0, &depth); @@ -129,7 +129,7 @@ void render() // printf("%d\n", view_uniform_location); render_block(block); - tc_draw_world(&tc_game_state_g.main_world); + tc_draw_world(tc_game_state_g.main_world); SDL_GL_SwapWindow(tc_game_state_g.renderer.window); } @@ -293,13 +293,19 @@ bool update() tc_camera_rotation.y += 0.1f / (3.1415 * 2); } + tc_game_state_g.main_world->loading_center.x = tc_camera_position.x / 32.0f; + tc_game_state_g.main_world->loading_center.y = tc_camera_position.y / 32.0f; + tc_game_state_g.main_world->loading_center.z = tc_camera_position.z / 32.0f; + + tc_update_world(tc_game_state_g.main_world); + return true; } int main(int argc, char **argv) { tc_init(); - tc_new_chunk(&tc_game_state_g.main_world, 1.0f, 1.0f, 1.0f); + tc_new_chunk(tc_game_state_g.main_world, 1.0f, 1.0f, 1.0f); block = tc_new_block_at_3f(0.0, 0.0, 0.0); diff --git a/code/source-c/meshize.c b/code/source-c/meshize.c index 1f16979..f547bc5 100644 --- a/code/source-c/meshize.c +++ b/code/source-c/meshize.c @@ -86,36 +86,36 @@ float tc_generic_cube_uvs[72] = 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, // Right - 0.0f, 1.0f, - 1.0f, 1.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + // Top 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, // Bottom - 1.0f, 1.0f, - 1.0f, 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f + + 1.0f, 1.0f, + 0.0f, 1.0f, + 1.0f, 0.0f }; uint32_t tc_count_chunk_vertices(tc_chunk_s *chunk) diff --git a/code/source-c/noise.c b/code/source-c/noise.c new file mode 100644 index 0000000..25e5b96 --- /dev/null +++ b/code/source-c/noise.c @@ -0,0 +1,23 @@ +#include "world.h" + +int tc_perlin_permutation[] = { + 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, + 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, + 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, + 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, + 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, + 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, + 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, + 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, + 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, + 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, + 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, + 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, + 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, + 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, + 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, + 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 +}; + + + diff --git a/code/source-c/state.h b/code/source-c/state.h index dd1aa7e..e3e0f2d 100644 --- a/code/source-c/state.h +++ b/code/source-c/state.h @@ -35,7 +35,7 @@ typedef struct tc_renderer_s renderer; tc_asset_storage_s asset_storage; tc_block_registry_s block_registry; - tc_world_s main_world; + tc_world_s *main_world; tc_image_s *block_texture_atlas; diff --git a/code/source-c/world.c b/code/source-c/world.c index 9c3447d..aed3546 100644 --- a/code/source-c/world.c +++ b/code/source-c/world.c @@ -6,7 +6,34 @@ tc_worldgen_s tc_default_terrain_generator_g; -void tc_draw_chunk(tc_chunk_s *chunk) +void tc_upload_chunk(tc_chunk_s *chunk) +{ + // If the chunk has no mesh yet + if(chunk->num_vertices == 0) + { + // Create one + tc_meshize_chunk(chunk); + } + + glGenVertexArrays(1, &chunk->vao); + glBindVertexArray(chunk->vao); + + glGenBuffers(1, &chunk->vertex_data); + glBindBuffer(GL_ARRAY_BUFFER, chunk->vertex_data); + + glBufferData(GL_ARRAY_BUFFER, chunk->num_vertices * 5 * sizeof(float), NULL, GL_STATIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, + chunk->num_vertices * 3 * sizeof(float), + chunk->vertex_positions + ); + glBufferSubData(GL_ARRAY_BUFFER, + chunk->num_vertices * 3 * sizeof(float), + chunk->num_vertices * 2 * sizeof(float), + chunk->vertex_uvs + ); + glBindVertexArray(0); +} +void tc_draw_chunk(tc_chunk_s *chunk, tc_world_s *world) { mat4x4 model_matrix; mat4x4_identity(model_matrix); @@ -46,41 +73,27 @@ void tc_init_world_generators() tc_default_terrain_generator_g.fn_generate_chunk = &tc_generate_default_terrain_chunk; } -tc_world_s tc_init_worlds() +void tc_init_worlds() { tc_init_world_generators(); - - tc_world_s world; - world.chunks_capacity = 256; - world.num_chunks = 0; - world.chunks = calloc(sizeof(tc_chunk_s *), world.chunks_capacity); - world.worldgen = &tc_default_terrain_generator_g; - - return world; } void tc_set_block_in_chunk( tc_chunk_s *chunk, - uint32_t x, uint32_t y, uint32_t z, + uint8_t x, uint8_t y, uint8_t z, tc_block_s block ) { chunk->blocks[x][y][z] = block.type_identifier; } - void tc_draw_world(tc_world_s *world) { - uint32_t chunk_index = 0; - while(chunk_index < world->num_chunks) - { - tc_draw_chunk(world->chunks[chunk_index]); - ++chunk_index; - } + tc_on_each_loaded_chunk(world, tc_draw_chunk, world); } - +/* void tc_add_chunk(tc_world_s *world, tc_chunk_s *chunk) { if(world->num_chunks >= world->chunks_capacity) @@ -91,40 +104,63 @@ void tc_add_chunk(tc_world_s *world, tc_chunk_s *chunk) world->chunks[world->num_chunks] = chunk; ++world->num_chunks; } +*/ -// Creates & Generates a chunk and provides a pointer to it -tc_chunk_s * tc_new_chunk(tc_world_s *world, float x, float y, float z) +void tc_setup_terrain(tc_world_s *world) { - tc_chunk_s *chunk = malloc(sizeof(tc_chunk_s)); - chunk->position.x = x; - chunk->position.y = y; - chunk->position.z = z; - world->worldgen->fn_generate_chunk(world->worldgen, chunk); - puts("Meshizing"); fflush(stdout); - tc_meshize_chunk(chunk); - puts("Meshized"); fflush(stdout); + // TODO - glGenVertexArrays(1, &chunk->vao); - glBindVertexArray(chunk->vao); - glGenBuffers(1, &chunk->vertex_data); - glBindBuffer(GL_ARRAY_BUFFER, chunk->vertex_data); +} +tc_chunkloader_s tc_create_chunkloader(tc_world_s *world) +{ + tc_chunkloader_s loader; + loader.width = world->load_radius * 2 + 1; + loader.height = world->load_radius * 2 + 1; + loader.depth = world->load_radius * 2 + 1; + loader.center_x = 0; + loader.center_y = 0; + loader.center_z = 0; + loader.chunks_capacity = 512; + loader.chunks = calloc(sizeof(tc_chunk_s *), loader.chunks_capacity); + loader.num_chunks = 0; + loader.needs_reload = false; - glBufferData(GL_ARRAY_BUFFER, chunk->num_vertices * 5 * sizeof(float), NULL, GL_STATIC_DRAW); - glBufferSubData(GL_ARRAY_BUFFER, 0, - chunk->num_vertices * 3 * sizeof(float), - chunk->vertex_positions - ); - glBufferSubData(GL_ARRAY_BUFFER, - chunk->num_vertices * 3 * sizeof(float), - chunk->num_vertices * 2 * sizeof(float), - chunk->vertex_uvs - ); - - glBindVertexArray(0); - - tc_add_chunk(world, chunk); - - return chunk; + return loader; +} + +void tc_add_chunk_to_loader(tc_chunkloader_s *chunkloader, tc_chunk_s *chunk) +{ + if(chunkloader->num_chunks >= chunkloader->chunks_capacity) + { + chunkloader->chunks_capacity *= 2; + chunkloader->chunks = realloc(chunkloader->chunks, sizeof(tc_chunk_s) * chunkloader->chunks_capacity); + } + chunkloader->chunks[chunkloader->num_chunks] = chunk; + ++chunkloader->num_chunks; +} + +tc_chunkloader_s tc_create_spawn_loader(tc_world_s *world) +{ + tc_chunkloader_s loader = tc_create_chunkloader(world); + loader.needs_reload = true; + + return loader; +} + +tc_world_s * tc_new_world(tc_worldgen_s *generator) +{ + tc_world_s *world = calloc(sizeof(tc_world_s), 1); + world->pool = tc_new_chunk_pool(128); + world->worldgen = &tc_default_terrain_generator_g; + // world->center_chunk = tc_new_chunk(world, 0, 0, 0); + world->load_radius = 3; + world->num_loaders = 1; + world->loaders = malloc(sizeof(tc_chunkloader_s) * world->num_loaders); + world->loaders[0] = tc_create_spawn_loader(world); + + // tc_upload_chunk(world->center_chunk); + + return world; } diff --git a/code/source-c/world.h b/code/source-c/world.h index 747252d..df93d39 100644 --- a/code/source-c/world.h +++ b/code/source-c/world.h @@ -13,6 +13,9 @@ typedef struct tc_block tc_block_s; typedef struct tc_chunk tc_chunk_s; typedef struct tc_world tc_world_s; +typedef struct tc_chunk_pool tc_chunk_pool_s; +typedef struct tc_chunk_pool_entry tc_chunk_pool_entry_s; + struct tc_worldgen { char *name; @@ -31,6 +34,8 @@ struct tc_block struct tc_chunk { + tc_chunk_pool_entry_s *superstructure; + tc_vec3_s position; uint32_t blocks[32][32][32]; @@ -41,26 +46,76 @@ struct tc_chunk uint32_t vao; uint32_t vertex_data; + tc_chunk_s *top; + tc_chunk_s *bottom; + tc_chunk_s *north; + tc_chunk_s *south; + tc_chunk_s *east; + tc_chunk_s *west; }; -struct tc_world +struct tc_chunk_pool_entry { + tc_chunk_pool_entry_s *next; + tc_chunk_pool_entry_s *previous; + + tc_chunk_s chunk; +}; + +typedef struct tc_chunkloader +{ + uint32_t center_x; + uint32_t center_y; + uint32_t center_z; + + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t chunks_capacity; uint32_t num_chunks; tc_chunk_s **chunks; - tc_worldgen_s *worldgen; + bool needs_reload; +} tc_chunkloader_s; + +struct tc_chunk_pool +{ + uint32_t capacity; + uint32_t used_entries; + tc_chunk_pool_entry_s *entries; + tc_chunk_pool_entry_s *first_free; + + tc_chunk_pool_s *continuation; }; -tc_world_s tc_init_worlds (); +struct tc_world +{ + // tc_chunk_s *center_chunk; + + tc_chunk_pool_s *pool; + tc_worldgen_s *worldgen; + + uint32_t num_loaders; + tc_chunkloader_s *loaders; + + // chunk_loading_center: The center of loading ON THE CHUNK GRID COORDINATES + tc_vec3_s loading_center; + uint32_t load_radius; +}; + +extern tc_worldgen_s tc_default_terrain_generator_g; + +void tc_init_worlds (); void tc_draw_world (tc_world_s *world); -tc_chunk_s * tc_new_chunk (tc_world_s *world, float x, float y, float z); // must be integers +tc_world_s * tc_new_world (tc_worldgen_s *generator); +tc_chunk_s * tc_new_chunk (tc_world_s *world, int32_t x, int32_t y, int32_t z); // must be integers void tc_set_block_in_chunk( tc_chunk_s *chunk, - uint32_t x, uint32_t y, uint32_t z, + uint8_t x, uint8_t y, uint8_t z, tc_block_s block ); @@ -69,5 +124,21 @@ void tc_meshize_chunk (tc_chunk_s *chunk); bool tc_generate_default_terrain_chunk (tc_worldgen_s *gen, tc_chunk_s *chunk); +tc_chunk_s * tc_load_chunk_at (tc_world_s *world, int32_t x, int32_t y, int32_t z); +tc_chunk_s * tc_get_loaded_chunk_at (tc_world_s *world, int32_t x, int32_t y, int32_t z); +bool tc_chunk_is_loaded (tc_world_s *world, int32_t x, int32_t y, int32_t z); + +void tc_update_world (tc_world_s *world); + +void tc_on_each_loaded_chunk ( + tc_world_s *world, + bool (*fn_do)(tc_chunk_s *chunk, void *userdata), + void *userdata +); + +tc_chunk_pool_s * tc_new_chunk_pool (uint32_t capacity); +tc_chunk_s * tc_allocate_chunk (tc_world_s *world); +void tc_free_chunk (tc_world_s *world, tc_chunk_s *chunk); + #endif