The chunk system needs to be rewritten

This commit is contained in:
Eric-Paul Ickhorn 2023-10-12 18:52:05 +02:00
parent f12bcee579
commit 165d54ab37
10 changed files with 593 additions and 75 deletions

View File

@ -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

View File

@ -0,0 +1,324 @@
#include "world.h"
#include <stdlib.h>
#include <stdio.h>
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

View File

@ -0,0 +1,60 @@
#include "world.h"
#include <stdlib.h>
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;
}

View File

@ -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!");
}

View File

@ -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);

View File

@ -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)

23
code/source-c/noise.c Normal file
View File

@ -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
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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