The chunk system needs to be rewritten
This commit is contained in:
parent
f12bcee579
commit
165d54ab37
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
mkdir -p dependencies/build/
|
mkdir -p dependencies/build/
|
||||||
|
|
||||||
gcc -g -o dependencies/build/glad.o \
|
gcc -g3 -o dependencies/build/glad.o \
|
||||||
-c dependencies/sources/glad/glad.c \
|
-c dependencies/sources/glad/glad.c \
|
||||||
-I dependencies/include/ -Wall
|
-I dependencies/include/ -Wall
|
||||||
|
|
||||||
gcc -g -o techneck.elf \
|
gcc -g3 -o techneck.elf \
|
||||||
code/source-c/*.c dependencies/build/glad.o \
|
code/source-c/*.c dependencies/build/glad.o \
|
||||||
-I dependencies/include -lGL -lSDL2 -lm -Wall
|
-I dependencies/include -lGL -lSDL2 -lm -Wall
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -43,9 +43,6 @@ void tc_load_textures()
|
||||||
tc_image_s *dirt =
|
tc_image_s *dirt =
|
||||||
tc_create_subimage(tc_game_state_g.block_texture_atlas, 0, 0, 8, 8);
|
tc_create_subimage(tc_game_state_g.block_texture_atlas, 0, 0, 8, 8);
|
||||||
dirt->name = "dirt";
|
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_image_s *grass =
|
||||||
tc_create_subimage(tc_game_state_g.block_texture_atlas, 8, 0, 8, 8);
|
tc_create_subimage(tc_game_state_g.block_texture_atlas, 8, 0, 8, 8);
|
||||||
grass->name = "grass";
|
grass->name = "grass";
|
||||||
|
@ -62,7 +59,8 @@ void tc_init()
|
||||||
tc_load_textures();
|
tc_load_textures();
|
||||||
tc_game_state_g.block_registry = tc_init_blocks();
|
tc_game_state_g.block_registry = tc_init_blocks();
|
||||||
tc_create_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!");
|
puts("Finished initializing!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ tc_block_s tc_new_block_at_3f(float x, float y, float z)
|
||||||
|
|
||||||
void render()
|
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);
|
glClearBufferfv(GL_COLOR, 0, color);
|
||||||
float depth = 10000000.0f;
|
float depth = 10000000.0f;
|
||||||
glClearBufferfv(GL_DEPTH, 0, &depth);
|
glClearBufferfv(GL_DEPTH, 0, &depth);
|
||||||
|
@ -129,7 +129,7 @@ void render()
|
||||||
// printf("%d\n", view_uniform_location);
|
// printf("%d\n", view_uniform_location);
|
||||||
|
|
||||||
render_block(block);
|
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);
|
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_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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
tc_init();
|
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);
|
block = tc_new_block_at_3f(0.0, 0.0, 0.0);
|
||||||
|
|
|
@ -86,36 +86,36 @@ float tc_generic_cube_uvs[72] =
|
||||||
0.0f, 0.0f,
|
0.0f, 0.0f,
|
||||||
0.0f, 1.0f,
|
0.0f, 1.0f,
|
||||||
|
|
||||||
1.0f, 0.0f,
|
|
||||||
1.0f, 1.0f,
|
|
||||||
0.0f, 1.0f,
|
0.0f, 1.0f,
|
||||||
|
1.0f, 1.0f,
|
||||||
|
1.0f, 0.0f,
|
||||||
|
|
||||||
// Right
|
// Right
|
||||||
0.0f, 1.0f,
|
|
||||||
1.0f, 1.0f,
|
|
||||||
1.0f, 0.0f,
|
|
||||||
|
|
||||||
0.0f, 1.0f,
|
0.0f, 1.0f,
|
||||||
0.0f, 0.0f,
|
0.0f, 0.0f,
|
||||||
1.0f, 0.0f,
|
1.0f, 0.0f,
|
||||||
|
|
||||||
|
1.0f, 0.0f,
|
||||||
|
1.0f, 1.0f,
|
||||||
|
0.0f, 1.0f,
|
||||||
|
|
||||||
// Top
|
// Top
|
||||||
0.0f, 0.0f,
|
0.0f, 0.0f,
|
||||||
0.0f, 1.0f,
|
0.0f, 1.0f,
|
||||||
1.0f, 0.0f,
|
1.0f, 0.0f,
|
||||||
|
|
||||||
1.0f, 1.0f,
|
|
||||||
0.0f, 1.0f,
|
0.0f, 1.0f,
|
||||||
|
1.0f, 1.0f,
|
||||||
1.0f, 0.0f,
|
1.0f, 0.0f,
|
||||||
|
|
||||||
// Bottom
|
// Bottom
|
||||||
1.0f, 1.0f,
|
|
||||||
1.0f, 0.0f,
|
|
||||||
0.0f, 1.0f,
|
0.0f, 1.0f,
|
||||||
|
|
||||||
0.0f, 0.0f,
|
0.0f, 0.0f,
|
||||||
1.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)
|
uint32_t tc_count_chunk_vertices(tc_chunk_s *chunk)
|
||||||
|
|
|
@ -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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ typedef struct
|
||||||
tc_renderer_s renderer;
|
tc_renderer_s renderer;
|
||||||
tc_asset_storage_s asset_storage;
|
tc_asset_storage_s asset_storage;
|
||||||
tc_block_registry_s block_registry;
|
tc_block_registry_s block_registry;
|
||||||
tc_world_s main_world;
|
tc_world_s *main_world;
|
||||||
|
|
||||||
tc_image_s *block_texture_atlas;
|
tc_image_s *block_texture_atlas;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,34 @@
|
||||||
|
|
||||||
tc_worldgen_s tc_default_terrain_generator_g;
|
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 model_matrix;
|
||||||
mat4x4_identity(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_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_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(
|
void tc_set_block_in_chunk(
|
||||||
tc_chunk_s *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
|
tc_block_s block
|
||||||
) {
|
) {
|
||||||
chunk->blocks[x][y][z] = block.type_identifier;
|
chunk->blocks[x][y][z] = block.type_identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void tc_draw_world(tc_world_s *world)
|
void tc_draw_world(tc_world_s *world)
|
||||||
{
|
{
|
||||||
uint32_t chunk_index = 0;
|
tc_on_each_loaded_chunk(world, tc_draw_chunk, world);
|
||||||
while(chunk_index < world->num_chunks)
|
|
||||||
{
|
|
||||||
tc_draw_chunk(world->chunks[chunk_index]);
|
|
||||||
++chunk_index;
|
|
||||||
}
|
}
|
||||||
}
|
/*
|
||||||
|
|
||||||
void tc_add_chunk(tc_world_s *world, tc_chunk_s *chunk)
|
void tc_add_chunk(tc_world_s *world, tc_chunk_s *chunk)
|
||||||
{
|
{
|
||||||
if(world->num_chunks >= world->chunks_capacity)
|
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->chunks[world->num_chunks] = chunk;
|
||||||
++world->num_chunks;
|
++world->num_chunks;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Creates & Generates a chunk and provides a pointer to it
|
void tc_setup_terrain(tc_world_s *world)
|
||||||
tc_chunk_s * tc_new_chunk(tc_world_s *world, float x, float y, float z)
|
|
||||||
{
|
{
|
||||||
tc_chunk_s *chunk = malloc(sizeof(tc_chunk_s));
|
// TODO
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
return loader;
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
}
|
||||||
chunk->num_vertices * 3 * sizeof(float),
|
|
||||||
chunk->vertex_positions
|
void tc_add_chunk_to_loader(tc_chunkloader_s *chunkloader, tc_chunk_s *chunk)
|
||||||
);
|
{
|
||||||
glBufferSubData(GL_ARRAY_BUFFER,
|
if(chunkloader->num_chunks >= chunkloader->chunks_capacity)
|
||||||
chunk->num_vertices * 3 * sizeof(float),
|
{
|
||||||
chunk->num_vertices * 2 * sizeof(float),
|
chunkloader->chunks_capacity *= 2;
|
||||||
chunk->vertex_uvs
|
chunkloader->chunks = realloc(chunkloader->chunks, sizeof(tc_chunk_s) * chunkloader->chunks_capacity);
|
||||||
);
|
}
|
||||||
|
chunkloader->chunks[chunkloader->num_chunks] = chunk;
|
||||||
glBindVertexArray(0);
|
++chunkloader->num_chunks;
|
||||||
|
}
|
||||||
tc_add_chunk(world, chunk);
|
|
||||||
|
tc_chunkloader_s tc_create_spawn_loader(tc_world_s *world)
|
||||||
return chunk;
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,9 @@ typedef struct tc_block tc_block_s;
|
||||||
typedef struct tc_chunk tc_chunk_s;
|
typedef struct tc_chunk tc_chunk_s;
|
||||||
typedef struct tc_world tc_world_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
|
struct tc_worldgen
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -31,6 +34,8 @@ struct tc_block
|
||||||
|
|
||||||
struct tc_chunk
|
struct tc_chunk
|
||||||
{
|
{
|
||||||
|
tc_chunk_pool_entry_s *superstructure;
|
||||||
|
|
||||||
tc_vec3_s position;
|
tc_vec3_s position;
|
||||||
uint32_t blocks[32][32][32];
|
uint32_t blocks[32][32][32];
|
||||||
|
|
||||||
|
@ -41,26 +46,76 @@ struct tc_chunk
|
||||||
uint32_t vao;
|
uint32_t vao;
|
||||||
uint32_t vertex_data;
|
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 chunks_capacity;
|
||||||
uint32_t num_chunks;
|
uint32_t num_chunks;
|
||||||
tc_chunk_s **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);
|
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(
|
void tc_set_block_in_chunk(
|
||||||
tc_chunk_s *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
|
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);
|
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
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue