diff --git a/code/source-c/chunk.c b/code/source-c/chunk.c new file mode 100644 index 0000000..f7236bb --- /dev/null +++ b/code/source-c/chunk.c @@ -0,0 +1,45 @@ +#include + +#include +#include + +void tc_upload_chunk(tc_chunk_s *chunk) +{ + // If the chunk has no mesh, it's probably only air. + if(chunk->num_vertices == 0) + { + return; + } + + if(chunk->vao != 0) glDeleteVertexArrays(1, &chunk->vao); + if(chunk->vbo != 0) glDeleteBuffers(1, &chunk->vbo); + + glGenVertexArrays(1, &chunk->vao); + glBindVertexArray(chunk->vao); + + glGenBuffers(1, &chunk->vbo); + glBindBuffer(GL_ARRAY_BUFFER, chunk->vbo); + + 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_chunkloader_zone(tc_chunkloader_s *loader) +{ + tc_chunklist_s *list = &loader->chunklist; + for(tc_chunklist_entry_s *current = list->first; current != NULL; current = current->next) + { + tc_send_pointer_to_entity(current->entity, "draw", 0); + } + +} + diff --git a/code/source-c/chunk.h b/code/source-c/chunk.h new file mode 100644 index 0000000..6dc117f --- /dev/null +++ b/code/source-c/chunk.h @@ -0,0 +1,95 @@ + +#ifndef TC_CHUNK_H +#define TC_CHUNK_H + +#include +#include + +typedef struct tc_chunk tc_chunk_s; +typedef struct tc_chunkloader tc_chunkloader_s; + +struct tc_chunk +{ + void *pool_entry; + + tc_chunk_location_s location; + u32_t blocks[32][32][32]; + + i32_t refcounter; + + u32_t num_vertices; + f32_t *vertex_positions; + f32_t *vertex_uvs; + + u32_t vao; + u32_t vbo; + + bool_t is_renderable; +}; + + +// tc_load_chunk_at: Looks if there's a chunk already loaded at 'location' and gets it if +// there is one. If it isn't loaded, this function will return NULL. The reference counter +// will be increased. +tc_entity_s * tc_load_chunk_at (tc_chunk_location_s location); + +// tc_unload_chunk_at: Looks if there's a chunk already loaded at 'location' and decreases +// the reference counter by one, possibly free'ing the chunk and its related structures. +void tc_unload_chunk_at (tc_chunkloader_s *loader, tc_chunk_location_s location); +bool_t tc_chunk_is_loaded (tc_chunk_location_s location); +void tc_meshize_chunk (tc_chunk_s *chunk); +void tc_upload_chunk (tc_chunk_s *chunk); + + + +typedef struct tc_chunklist_entry tc_chunklist_entry_s; +typedef struct tc_chunklist tc_chunklist_s; + +struct tc_chunklist_entry +{ + tc_chunklist_entry_s *next; + tc_chunklist_entry_s *previous; + tc_entity_s *entity; +}; + +struct tc_chunklist +{ + tc_chunklist_entry_s *first; + tc_chunklist_entry_s *first_free; + + u32_t capacity; + tc_chunklist_entry_s *entries; +}; + +tc_chunklist_s tc_create_chunklist (u32_t capacity); +void tc_delete_chunklist (tc_chunklist_s list); + +// tc_chunklist_remove_item: Adds a chunk to the chunklist. +// THIS FUNCTION DOES NOT UPDATE THE REFERENCE COUNTER OF THE CHUNK! +void tc_chunklist_add_item (tc_chunklist_s *list, tc_entity_s *chunk); + +// tc_chunklist_remove_item: Removes a chunk from the chunklist. +// THIS FUNCTION DOES NOT UPDATE THE REFERENCE COUNTER OF THE CHUNK! +void tc_chunklist_remove_item (tc_chunklist_s *list, tc_entity_s *chunk); + +tc_entity_s * tc_chunklist_find_chunk_at (tc_chunklist_s *list, tc_chunk_location_s location); + + + +struct tc_chunkloader +{ + tc_chunk_location_s center; + tc_vec3i_s extent; + + tc_chunklist_s chunklist; + bool_t needs_reload; + bool_t is_rendered; +}; + +tc_chunkloader_s tc_create_chunkloader (tc_chunk_location_s location); +void tc_delete_chunkloader (tc_chunkloader_s chunkloader); + +void tc_draw_chunkloader_zone (tc_chunkloader_s *loader); + +#endif // TC_CHUNK_H + diff --git a/code/source-c/chunk_loader.c b/code/source-c/chunk_loader.c deleted file mode 100644 index 01b24ba..0000000 --- a/code/source-c/chunk_loader.c +++ /dev/null @@ -1,168 +0,0 @@ -#include "world.h" -#include "entity.h" - -#include -#include - -void tc_add_chunk_to_loader(tc_chunkloader_s *chunkloader, tc_entity_s *entity) -{ - if(chunkloader->num_chunks >= chunkloader->chunks_capacity) - { - chunkloader->chunks_capacity *= 2; - chunkloader->chunks = realloc(chunkloader->chunks, sizeof(tc_entity_s *) * chunkloader->chunks_capacity); - } - chunkloader->chunks[chunkloader->num_chunks] = entity; - ++chunkloader->num_chunks; -} - -bool tc_coord_is_within_loaders_range(tc_chunkloader_s *loader, tc_vec3i_s coord) -{ - if(coord.x < (loader->center.x - loader->extent.x / 2)) return false; - if(coord.y < (loader->center.y - loader->extent.y / 2)) return false; - if(coord.z < (loader->center.z - loader->extent.z / 2)) return false; - - if(coord.x > (loader->center.x + loader->extent.x / 2)) return false; - if(coord.y > (loader->center.y + loader->extent.y / 2)) return false; - if(coord.z > (loader->center.z + loader->extent.z / 2)) return false; - - return true; -} - -tc_chunkloader_s * tc_get_corresponding_loader(tc_world_s *world, tc_vec3i_s coord) -{ - for(uint32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index) - if(tc_coord_is_within_loaders_range(&world->loaders[loader_index], coord)) - return &world->loaders[loader_index]; - - return NULL; -} - -tc_entity_s * tc_get_chunk_of_loader(tc_chunkloader_s *loader, tc_vec3i_s coord) -{ - for(uint32_t chunk_index = 0; chunk_index < loader->num_chunks; ++chunk_index) - { - tc_chunk_s *chunk = loader->chunks[chunk_index]->specific; - if(tc_vec3i_equ(chunk->position, coord)) - return loader->chunks[chunk_index]; - } - - return NULL; -} - -tc_entity_s * tc_get_loaded_chunk(tc_world_s *world, tc_vec3i_s coord) -{ - tc_chunkloader_s *loader = tc_get_corresponding_loader(world, coord); - if(loader == NULL) return NULL; - - return tc_get_chunk_of_loader(loader, coord); -} - -tc_entity_s * tc_load_chunk_of_loader(tc_chunkloader_s *loader, tc_vec3i_s coord) -{ - tc_entity_s *entity = tc_get_chunk_of_loader(loader, coord); - - if(entity == NULL) - { - tc_entity_s *entity = tc_create_entity("chunk", loader->world); - tc_chunk_s *chunk = entity->specific; - chunk = entity->specific; - chunk->position = coord; - - loader->world->worldgen->fn_generate_chunk(loader->world->worldgen, chunk); - tc_run_hooklist(&loader->world->after_chunk_generate, chunk); - tc_upload_chunk(chunk); - - tc_add_chunk_to_loader(loader, entity); - } - return entity; -} - -void tc_reload_chunk_of_loader(tc_chunkloader_s *loader, tc_vec3i_s coord) -{ - tc_entity_s *entity = tc_get_chunk_of_loader(loader, coord); - tc_chunk_s *chunk = entity->specific; - if(chunk == NULL) return; - - tc_meshize_chunk(chunk, NULL); - tc_upload_chunk(chunk); -} - -void tc_reload_chunk(tc_world_s *world, tc_vec3i_s coord) -{ - tc_chunkloader_s *loader = tc_get_corresponding_loader(world, coord); - if(loader == NULL) return; - - tc_reload_chunk_of_loader(loader, coord); -} - -void tc_remove_chunk_from_loader(tc_chunkloader_s *loader, uint32_t index) -{ - if(loader->num_chunks != 0) - { - // This is is NOT last element - if((index+1) < loader->num_chunks) - { - loader->chunks[index] = loader->chunks[loader->num_chunks-1]; // move last chunk into gap - } - --loader->num_chunks; - } -} - -void tc_remove_unnecessary_chunks_of_loader(tc_chunkloader_s *loader) -{ - for(uint32_t chunk_index = 0; chunk_index < loader->num_chunks; ++chunk_index) - { - tc_entity_s *entity = loader->chunks[chunk_index]; - tc_chunk_s *chunk = entity->specific; - - if(!tc_coord_is_within_loaders_range(loader, chunk->position)) - { - tc_remove_chunk_from_loader(loader, chunk_index); - } - } -} - -void tc_load_all_chunks_of_chunkloader(tc_chunkloader_s *loader) -{ - for(int32_t x = 0; x < loader->extent.x; ++x) - { - for(int32_t y = 0; y < loader->extent.y; ++y) - { - for(int32_t z = 0; z < loader->extent.z; ++z) - { - tc_vec3i_s coords; - coords.x = (loader->center.x - (x - ((int32_t) loader->extent.x)))-1; - coords.y = (loader->center.y - (y - ((int32_t) loader->extent.y)))-1; - coords.z = (loader->center.z - (z - ((int32_t) loader->extent.z)))-1; - - tc_load_chunk_of_loader(loader, coords); - } - } - } -} - -void tc_reload_chunkloader_zone(tc_chunkloader_s *loader) -{ - tc_remove_unnecessary_chunks_of_loader(loader); - tc_load_all_chunks_of_chunkloader(loader); -} - -uint64_t world_update_tick = 0; - -void tc_update_world(tc_world_s *world) -{ - if((world_update_tick % 512) == 0) - { - uint32_t chunkloader_index = 0; - while(chunkloader_index < world->num_loaders) - { - if(world->loaders[chunkloader_index].needs_reload) - { - tc_reload_chunkloader_zone(&world->loaders[chunkloader_index]); - } - ++chunkloader_index; - } - } - ++world_update_tick; -} - diff --git a/code/source-c/chunk_pool.c b/code/source-c/chunk_pool.c index 702f7ca..6846e52 100644 --- a/code/source-c/chunk_pool.c +++ b/code/source-c/chunk_pool.c @@ -75,20 +75,20 @@ void tc_deallocate_chunk(tc_chunk_s *chunk) { if(chunk->vao != 0) { - glDeleteVertexArrays(1, &chunk->vertex_data); + glDeleteVertexArrays(1, &chunk->vbo); chunk->vao = 0; } - if(chunk->vertex_data != 0) + if(chunk->vbo != 0) { - glDeleteBuffers(1, &chunk->vertex_data); - chunk->vertex_data = 0; + glDeleteBuffers(1, &chunk->vbo); + chunk->vbo = 0; } - tc_chunk_pool_entry_s *entry = chunk->pool_entry; - chunk->pool_entry->next = tc_chunk_pool_g->first_free; - tc_chunk_pool_g->first_free = entry; - memset(&chunk, 0x00, sizeof(tc_chunk_s)); - chunk->pool_entry = entry; + tc_chunk_pool_entry_s *entry = chunk->pool_entry; + entry->next = tc_chunk_pool_g->first_free; + tc_chunk_pool_g->first_free = entry; + memset(chunk, 0x00, sizeof(tc_chunk_s)); + chunk->pool_entry = entry; } diff --git a/code/source-c/chunk_pool.h b/code/source-c/chunk_pool.h new file mode 100644 index 0000000..7d4cd40 --- /dev/null +++ b/code/source-c/chunk_pool.h @@ -0,0 +1,35 @@ + +#ifndef TC_CHUNK_POOL_H +#define TC_CHUNK_POOL_H + +#include +#include + +typedef struct tc_chunk_pool tc_chunk_pool_s; +typedef struct tc_chunk_pool_entry tc_chunk_pool_entry_s; + +struct tc_chunk_pool_entry +{ + tc_chunk_pool_entry_s *next; + tc_chunk_pool_entry_s *previous; + + tc_chunk_s chunk; +}; + +struct tc_chunk_pool +{ + u32_t capacity; + u32_t used_entries; + tc_chunk_pool_entry_s *entries; + tc_chunk_pool_entry_s *first_free; + + tc_chunk_pool_s *continuation; +}; + +void tc_cleanup_chunk_pool (); +void tc_init_chunk_pool (u32_t capacity); +tc_chunk_s * tc_allocate_chunk (); +void tc_deallocate_chunk (tc_chunk_s *chunk); + +#endif // TC_CHUNK_POOL_H + diff --git a/code/source-c/chunkloader.c b/code/source-c/chunkloader.c new file mode 100644 index 0000000..5e20e93 --- /dev/null +++ b/code/source-c/chunkloader.c @@ -0,0 +1,291 @@ +#include "world.h" +#include "entity.h" + +#include +#include + +tc_chunklist_s tc_create_chunklist(u32_t capacity) +{ + tc_chunklist_s list; + list.capacity = capacity; + list.entries = calloc(sizeof(tc_chunklist_entry_s), capacity); + list.first_free = list.entries; + list.first = NULL; + + return list; +} + +void tc_delete_chunklist(tc_chunklist_s list) +{ + + for(tc_chunklist_entry_s *current = list.first; current != NULL; current = current->next) + tc_chunklist_remove_item(&list, list.first->entity); + + free(list.entries); +} + +tc_chunklist_entry_s * tc_chunklist_find_first_free(tc_chunklist_s *list) +{ + for(u32_t index = 0; index < list->capacity; ++index) + if(list->entries[index].entity == NULL) return &list->entries[index]; + + return NULL; +} + +tc_chunklist_entry_s * tc_chunklist_find_corresponding_entry(tc_chunklist_s *list, tc_entity_s *chunk) +{ + for(u32_t index = 0; index < list->capacity; ++index) + { + if(list->entries[index].entity == chunk) return &list->entries[index]; + } + return NULL; +} + +bool_t tc_chunklist_contains(tc_chunklist_s *list, tc_chunk_location_s location) +{ + for(tc_chunklist_entry_s *current = list->first; current != NULL; current = current->next) + { + if(current->entity == NULL) continue; + + tc_vec3i_s chunk_coords; + chunk_coords.x = tc_get_integer_from_entity(current->entity, "grid_x"); + chunk_coords.y = tc_get_integer_from_entity(current->entity, "grid_y"); + chunk_coords.z = tc_get_integer_from_entity(current->entity, "grid_z"); + + if(tc_vec3i_equ(chunk_coords, location.grid_coords)) + { + return TRUE; + } + } + return FALSE; +} + +tc_entity_s * tc_chunklist_find_chunk_at(tc_chunklist_s *list, tc_chunk_location_s location) +{ + u32_t num_searched = 0; + for(tc_chunklist_entry_s *current = list->first; current != NULL; current = current->next) + { + ++num_searched; + + if(current->entity == NULL) continue; + + tc_vec3i_s chunk_coords; + chunk_coords.x = tc_get_integer_from_entity(current->entity, "grid_x"); + chunk_coords.y = tc_get_integer_from_entity(current->entity, "grid_y"); + chunk_coords.z = tc_get_integer_from_entity(current->entity, "grid_z"); + + if(tc_vec3i_equ(chunk_coords, location.grid_coords)) + { + return current->entity; + } + } + return NULL; +} + +void tc_chunklist_add_item(tc_chunklist_s *list, tc_entity_s *chunk) +{ + if(list->first_free == NULL) + { + puts("Chunk List overflow!"); + return; + } + + tc_chunklist_entry_s new_entry; + + new_entry.entity = chunk; + new_entry.next = list->first; + (*list->first_free) = new_entry; + list->first = list->first_free; + + // Link everything together + + if(list->first_free->next != NULL) + list->first_free->next->previous = list->first_free; + list->first_free->previous = NULL; + + // Finally assign it + list->first_free = tc_chunklist_find_first_free(list); +} + +void tc_chunklist_remove_item(tc_chunklist_s *list, tc_entity_s *chunk) +{ + tc_chunklist_entry_s *entry = tc_chunklist_find_corresponding_entry(list, chunk); + + if(list->first == entry) + list->first = entry->next; + + if(entry->previous != NULL) + entry->previous->next = entry->next; + + entry->entity = NULL; + list->first_free = entry; +} + + + +tc_chunkloader_s tc_create_chunkloader(tc_chunk_location_s location) +{ + tc_chunkloader_s loader; + loader.extent.x = UPDATE_DISTANCE * 2 + 1; + loader.extent.y = UPDATE_DISTANCE * 2 + 1; + loader.extent.z = UPDATE_DISTANCE * 2 + 1; + loader.center = location; + loader.chunklist = tc_create_chunklist(200); + loader.needs_reload = FALSE; + + return loader; +} + +void tc_delete_chunkloader(tc_chunkloader_s loader) +{ + for(tc_chunklist_entry_s *current = loader.chunklist.first; + current != NULL; current = current->next) + { + tc_chunk_s *current_chunk = current->entity->specific; + tc_unload_chunk_at(&loader, current_chunk->location); + } + tc_delete_chunklist(loader.chunklist); +} + +bool_t tc_coord_is_within_loaders_range(tc_chunkloader_s *loader, tc_vec3i_s coord) +{ + if(coord.x < (loader->center.grid_coords.x - loader->extent.x / 2)) return FALSE; + if(coord.y < (loader->center.grid_coords.y - loader->extent.y / 2)) return FALSE; + if(coord.z < (loader->center.grid_coords.z - loader->extent.z / 2)) return FALSE; + + if(coord.x > (loader->center.grid_coords.x + loader->extent.x / 2)) return FALSE; + if(coord.y > (loader->center.grid_coords.y + loader->extent.y / 2)) return FALSE; + if(coord.z > (loader->center.grid_coords.z + loader->extent.z / 2)) return FALSE; + + return TRUE; +} + +tc_chunkloader_s * tc_get_corresponding_loader(tc_chunk_location_s location) +{ + tc_vec3i_s coords = location.grid_coords; + tc_world_s *world = location.world; + + for(uint32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index) + if(tc_coord_is_within_loaders_range(&world->loaders[loader_index], coords)) + return &world->loaders[loader_index]; + + return NULL; +} + +void tc_unload_chunk_at(tc_chunkloader_s *loader, tc_chunk_location_s location) +{ + tc_entity_s *entity = tc_chunklist_find_chunk_at(&loader->chunklist, location); + if(entity == NULL) return; + + tc_chunk_s *chunk = entity->specific; + + --chunk->refcounter; + + if(chunk->refcounter < 1) + { + tc_delete_entity(entity); + tc_chunklist_remove_item(&loader->chunklist, entity); + } +} + +tc_entity_s * tc_load_chunk_at(tc_chunk_location_s location) +{ + tc_chunkloader_s *loader = tc_get_corresponding_loader(location); + if(loader == NULL) return NULL; + + tc_entity_s *entity = tc_chunklist_find_chunk_at(&loader->chunklist, location); + tc_chunk_s *chunk = entity->specific; + + ++chunk->refcounter; + return entity; +} + +void tc_unload_out_of_range_loader_chunks(tc_chunkloader_s *loader) +{ + tc_chunk_location_s location; + location.world = loader->center.world; + + for(tc_chunklist_entry_s *current = loader->chunklist.first; current != NULL; current = current->next) + { + tc_entity_s *entity = current->entity; + if(entity == NULL) + { + continue; + } + tc_chunk_s *chunk = entity->specific; + + location.grid_coords = chunk->location.grid_coords; + location.grid_coords.x = tc_get_integer_from_entity(current->entity, "grid_x"); + location.grid_coords.y = tc_get_integer_from_entity(current->entity, "grid_y"); + location.grid_coords.z = tc_get_integer_from_entity(current->entity, "grid_z"); + + if(!tc_coord_is_within_loaders_range(loader, location.grid_coords)) + { + tc_unload_chunk_at(loader, location); + tc_chunklist_remove_item(&loader->chunklist, current->entity); + } + } +} + +tc_entity_s * tc_create_chunk_for_loader_at(tc_chunkloader_s *loader, tc_vec3i_s grid_coords) +{ + tc_entity_s *entity = tc_create_entity("chunk", loader->center.world); + tc_chunk_location_s location; + location.world = loader->center.world; + location.grid_coords = grid_coords; + tc_set_integer_for_entity(entity, "grid_x", location.grid_coords.x); + tc_set_integer_for_entity(entity, "grid_y", location.grid_coords.y); + tc_set_integer_for_entity(entity, "grid_z", location.grid_coords.z); + + tc_world_s *world = loader->center.world; + + tc_send_integer_to_entity(entity, "generate", 0); + tc_run_hooklist(&world->after_chunk_generate, entity->specific); + tc_send_integer_to_entity(entity, "gl_upload", 0); + + tc_chunklist_add_item(&loader->chunklist, entity); + + return entity; +} + +void tc_load_all_chunks_of_chunkloader(tc_chunkloader_s *loader) +{ + for(int32_t x = 0; x < loader->extent.x; ++x) + for(int32_t y = 0; y < loader->extent.y; ++y) + for(int32_t z = 0; z < loader->extent.z; ++z) + { + tc_chunk_location_s location; + location.grid_coords.x = (loader->center.grid_coords.x + x - (((int32_t) loader->extent.x) / 2)+1); + location.grid_coords.y = (loader->center.grid_coords.y + y - (((int32_t) loader->extent.y) / 2)+1); + location.grid_coords.z = (loader->center.grid_coords.z + z - (((int32_t) loader->extent.z) / 2)+1); + + if(!tc_chunklist_contains(&loader->chunklist, location)) + { + tc_create_chunk_for_loader_at(loader, location.grid_coords); + } + } + +} + +void tc_reload_chunkloader_zone(tc_chunkloader_s *loader) +{ + tc_unload_out_of_range_loader_chunks(loader); + tc_load_all_chunks_of_chunkloader(loader); +} + +uint64_t world_update_tick = 0; + +void tc_update_world(tc_world_s *world) +{ + if((world_update_tick % 256) == 0) + { + uint32_t chunkloader_index = 0; + while(chunkloader_index < world->num_loaders) + { + tc_reload_chunkloader_zone(&world->loaders[chunkloader_index]); + ++chunkloader_index; + } + } + ++world_update_tick; +} + diff --git a/code/source-c/default_terrain_generator.c b/code/source-c/default_terrain_generator.c index fc39f2e..9ed67f4 100644 --- a/code/source-c/default_terrain_generator.c +++ b/code/source-c/default_terrain_generator.c @@ -1,6 +1,6 @@ #include "world.h" -bool tc_generate_default_terrain_chunk(tc_worldgen_s *gen, tc_chunk_s *chunk) +bool_t tc_generate_default_terrain_chunk(tc_worldgen_s *gen, tc_chunk_s *chunk) { tc_block_s block; block.type_identifier = 1 | TC_BLOCK_OPAQUE_BIT; @@ -11,7 +11,7 @@ bool tc_generate_default_terrain_chunk(tc_worldgen_s *gen, tc_chunk_s *chunk) tc_block_s grass; grass.type_identifier = 2 | TC_BLOCK_OPAQUE_BIT; - if(chunk->position.y > 0) return true; + if(chunk->location.grid_coords.y > 0) return true; uint32_t x_in_chunk = 0; uint32_t y_in_chunk = 0; @@ -31,7 +31,7 @@ bool tc_generate_default_terrain_chunk(tc_worldgen_s *gen, tc_chunk_s *chunk) } ++x_in_chunk; } - if(chunk->position.y == 0) + if(chunk->location.grid_coords.y == 0) { x_in_chunk = 0; while(x_in_chunk < 32) diff --git a/code/source-c/entity.c b/code/source-c/entity.c index ce60668..7edecc2 100644 --- a/code/source-c/entity.c +++ b/code/source-c/entity.c @@ -71,7 +71,7 @@ void tc_add_entity_instance_to_type(tc_entity_type_s *type, tc_entity_s *entity) if(type->num_instances >= type->instances_capacity) { type->instances_capacity *= 2; - type->instances = realloc(type->instances, type->instances_capacity); + type->instances = realloc(type->instances, sizeof(tc_entity_s *) * type->instances_capacity); } type->instances[type->num_instances] = entity; ++type->num_instances; @@ -96,28 +96,20 @@ tc_entity_s * tc_create_entity(char *type, void *userdata) return entity; } -void tc_spawn_entity(tc_entity_s *entity, tc_location_s location) -{ - entity->type->functions.fn_spawn(entity, location); -} - -void tc_teleport_entity(tc_entity_s *entity, tc_location_s location) -{ - entity->type->functions.fn_teleport(entity, location); -} - -void tc_draw_entity(tc_entity_s *entity) -{ - entity->type->functions.fn_draw(entity); -} - void tc_delete_entity(tc_entity_s *entity) { tc_entity_type_s *type = entity->type; + entity->type->functions.fn_delete(entity); + i32_t instance_index = tc_find_entity_instance_index_in_type(type, entity); + free(entity->attributes); + tc_deallocate_entity(entity); + entity->attributes = NULL; + entity->type = NULL; + if(instance_index == -1) { puts("Entity can't be found as an instance of it's type?!"); @@ -127,10 +119,6 @@ void tc_delete_entity(tc_entity_s *entity) --type->num_instances; type->instances[instance_index] = type->instances[type->num_instances]; } - - free(entity->attributes); - entity->type->functions.fn_delete(entity); - tc_deallocate_entity(entity); } @@ -143,11 +131,13 @@ tc_entity_attribute_s * tc_get_entity_attribute_with_name(tc_entity_s *entity, c tc_entity_attribute_s attribute = entity->attributes[attribute_index]; if(attribute.name == NULL) { - puts("NAAJAA"); ++attribute_index; continue; } - if(!strcmp(attribute.name, name)) return &entity->attributes[attribute_index]; + if(!strcmp(attribute.name, name)) + { + return &entity->attributes[attribute_index]; + } ++attribute_index; } return NULL; @@ -160,8 +150,9 @@ tc_entity_attribute_s * tc_allocate_entity_attribute(tc_entity_s *entity) entity->attributes_capacity *= 2; entity->attributes = realloc(entity->attributes, sizeof(tc_entity_attribute_s) * entity->attributes_capacity); } + tc_entity_attribute_s *attribute = &entity->attributes[entity->num_attributes]; ++entity->num_attributes; - return &entity->attributes[entity->num_attributes-1]; + return attribute; } tc_entity_attribute_s * tc_get_or_allocate_entity_attribute_with_name(tc_entity_s *entity, char *name) @@ -189,7 +180,8 @@ void tc_set_string_for_entity(tc_entity_s *entity, char *attr_name, char *string void tc_set_integer_for_entity(tc_entity_s *entity, char *attr_name, int64_t integer) { - tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.integer = integer; + tc_entity_attribute_s *attribute = tc_get_or_allocate_entity_attribute_with_name(entity, attr_name); + attribute->value.integer = integer; } void tc_set_float_for_entity(tc_entity_s *entity, char *attr_name, double floating) @@ -201,22 +193,56 @@ void tc_set_float_for_entity(tc_entity_s *entity, char *attr_name, double floati void * tc_get_pointer_from_entity(tc_entity_s *entity, char *attr_name) { - return tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.pointer; + tc_entity_attribute_s *attribute = + tc_get_entity_attribute_with_name(entity, attr_name); + + if(attribute == NULL) + { + return NULL; + } + + return attribute->value.pointer; } char * tc_get_string_from_entity(tc_entity_s *entity, char *attr_name) { - return tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.string; + + tc_entity_attribute_s *attribute = + tc_get_entity_attribute_with_name(entity, attr_name); + + if(attribute == NULL) + { + return NULL; + } + + return attribute->value.string; } int64_t tc_get_integer_from_entity(tc_entity_s *entity, char *attr_name) { - return tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.integer; + tc_entity_attribute_s *attribute = + tc_get_entity_attribute_with_name(entity, attr_name); + + if(attribute == NULL) + { + return 0; + } + + return attribute->value.integer; } double tc_get_float_from_entity(tc_entity_s *entity, char *attr_name) { - return tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.floating; + + tc_entity_attribute_s *attribute = + tc_get_entity_attribute_with_name(entity, attr_name); + + if(attribute == NULL) + { + return 0.0f; + } + + return attribute->value.floating; } @@ -349,7 +375,7 @@ void tc_tick_intervals() } } - +/* void tc_draw_all_entities_of_type(char *name) { tc_entity_type_s *type = tc_get_entity_type_with_name(name); @@ -365,3 +391,5 @@ void tc_draw_all_entities_of_type(char *name) ++entity_index; } } +*/ + diff --git a/code/source-c/entity.h b/code/source-c/entity.h index 3bed5a6..0b239e5 100644 --- a/code/source-c/entity.h +++ b/code/source-c/entity.h @@ -14,15 +14,15 @@ typedef struct tc_entity_pool tc_entity_pool_s; typedef struct tc_entity_pool_entry tc_entity_pool_entry_s; typedef struct tc_entity_registry tc_entity_registry_s; +typedef void (*tc_entity_create_fn) (tc_entity_s *entity, void *userdata); +typedef void (*tc_entity_delete_fn) (tc_entity_s *entity); +typedef void (*tc_entity_send_event_fn) (tc_entity_s *entity, tc_entity_event_s event); typedef struct { - void (*fn_create) (tc_entity_s *entity, void *userdata); - void (*fn_spawn) (tc_entity_s *entity, tc_location_s location); - void (*fn_teleport) (tc_entity_s *entity, tc_location_s location); - void (*fn_draw) (tc_entity_s *entity); - void (*fn_delete) (tc_entity_s *entity); - void (*fn_send_event) (tc_entity_s *entity, tc_entity_event_s event); + tc_entity_create_fn fn_create; + tc_entity_delete_fn fn_delete; + tc_entity_send_event_fn fn_send_event; } tc_fn_entity_s; @@ -70,7 +70,6 @@ struct tc_entity { tc_entity_pool_entry_s *pool_entry; - tc_location_s location; tc_entity_type_s *type; u16_t attributes_capacity; @@ -126,9 +125,6 @@ void tc_register_entity_type (tc_entity_type_ tc_entity_type_s * tc_get_entity_type_with_name (char *name); tc_entity_s * tc_create_entity (char *type, void *userdata); -void tc_spawn_entity (tc_entity_s *entity, tc_location_s location); -void tc_teleport_entity (tc_entity_s *entity, tc_location_s location); -void tc_draw_entity (tc_entity_s *entity); void tc_delete_entity (tc_entity_s *entity); void tc_set_pointer_for_entity (tc_entity_s *entity, char *attr_name, void *pointer); diff --git a/code/source-c/entity/chunk.c b/code/source-c/entity/chunk.c new file mode 100644 index 0000000..2d286de --- /dev/null +++ b/code/source-c/entity/chunk.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include + +#include +#include + +tc_entity_type_s *tc_chunk_entity_type_g = NULL; + +// entity/chunk.c: Functions for the Chunk's entity-type. + +// The userdata should be the corresponding world +void tc_create_chunk_entity(tc_entity_s *entity, void *userdata) +{ + tc_chunk_s *chunk = tc_allocate_chunk(); + tc_world_s *world = userdata; + + entity->specific = chunk; + chunk->location.world = world; + chunk->refcounter = 1; + chunk->is_renderable = TRUE; + + tc_set_integer_for_entity(entity, "grid_x", 0); + tc_set_integer_for_entity(entity, "grid_y", 0); + tc_set_integer_for_entity(entity, "grid_z", 0); + + tc_run_hooklist(&world->on_chunk_create, entity); +} + +void tc_delete_chunk_entity(tc_entity_s *entity) +{ + tc_chunk_s *chunk = entity->specific; + if(chunk->vao != 0) glDeleteVertexArrays(1, &chunk->vao); + if(chunk->vbo != 0) glDeleteBuffers(1, &chunk->vbo); + + if(chunk->vertex_positions != NULL) free(chunk->vertex_positions); + if(chunk->vertex_uvs != NULL) free(chunk->vertex_uvs); + + tc_physics_entity_s *physics_body = tc_get_pointer_from_entity(entity, "physics_body"); + tc_remove_physics_entity(physics_body); + + tc_deallocate_chunk(entity->specific); +} + +void tc_draw_chunk_entity(tc_entity_s *entity) +{ + tc_chunk_s *chunk = entity->specific; + + tc_mat4f_s model_matrix = tc_mat4f_identity(); + + tc_vec3f_s position_3f; + position_3f.x = ((float) tc_get_integer_from_entity(entity, "grid_x")) * 32.0f; + position_3f.y = ((float) tc_get_integer_from_entity(entity, "grid_y")) * 32.0f; + position_3f.z = ((float) tc_get_integer_from_entity(entity, "grid_z")) * 32.0f; + + model_matrix = + tc_mat4f_translate(model_matrix, position_3f); + + tc_shader_uniform_mat4f(&tc_game_state_g.renderer.draw_shader, "model_matrix", model_matrix); + + glBindBuffer(GL_ARRAY_BUFFER, chunk->vbo); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *) 0); + glEnableVertexAttribArray(0); + + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + (void *) (sizeof(float) * 3 * chunk->num_vertices) + ); + + glEnableVertexAttribArray(1); + + glActiveTexture(GL_TEXTURE0); + glUniform1i( + glGetUniformLocation(tc_game_state_g.renderer.draw_shader.program_id, "block_atlas"), + 0 + ); + glBindTexture(GL_TEXTURE_2D, tc_game_state_g.block_texture_atlas->gl_identifier); + + glDrawArrays(GL_TRIANGLES, 0, chunk->num_vertices); + + glBindVertexArray(0); +} + +void tc_generate_chunk_entity(tc_chunk_s *chunk) +{ + tc_world_s *world = chunk->location.world; + + tc_run_hooklist(&world->before_chunk_generate, chunk); + world->worldgen->fn_generate_chunk(world->worldgen, chunk); + tc_run_hooklist(&world->after_chunk_generate, chunk); +} + +void tc_meshize_chunk_entity(tc_chunk_s *chunk) +{ + if(chunk->vertex_positions != NULL) free(chunk->vertex_positions); + if(chunk->vertex_uvs != NULL) free(chunk->vertex_uvs); + + tc_meshize_chunk(chunk); + + +} + +void tc_receive_chunk_entity_event(tc_entity_s *entity, tc_entity_event_s event) +{ + tc_chunk_s *chunk = entity->specific; + + if(!strcmp(event.identifier, "draw")) tc_draw_chunk_entity(entity); + if(!strcmp(event.identifier, "generate")) tc_generate_chunk_entity(chunk); + if(!strcmp(event.identifier, "meshize")) tc_meshize_chunk_entity(chunk); + if(!strcmp(event.identifier, "gl_upload")) tc_upload_chunk(chunk); +} + + + +void tc_register_chunk_entity() +{ + tc_fn_entity_s chunk_functions; + chunk_functions.fn_create = &tc_create_chunk_entity; + chunk_functions.fn_delete = &tc_delete_chunk_entity; + chunk_functions.fn_send_event = &tc_receive_chunk_entity_event; + + tc_entity_type_s chunk_type; + chunk_type.internal_name = "chunk"; + chunk_type.display_name = NULL; + chunk_type.functions = chunk_functions; + chunk_type.instances_capacity = 512; + + tc_register_entity_type(chunk_type); + tc_chunk_entity_type_g = tc_get_entity_type_with_name("chunk"); +} + diff --git a/code/source-c/entity/player.c b/code/source-c/entity/player.c index 6d46ab5..f54eb10 100644 --- a/code/source-c/entity/player.c +++ b/code/source-c/entity/player.c @@ -8,24 +8,9 @@ tc_entity_type_s *tc_player_entity_type_g = NULL; void tc_fn_create_player_entity(tc_entity_s *entity) { entity->type = tc_player_entity_type_g; - entity->location = tc_zero_location(); entity->specific = NULL; } -void tc_fn_spawn_player_entity(tc_entity_s *entity, tc_location_s location) -{ - if(entity->location.world != NULL) return; - - entity->location = location; -} - -void tc_fn_teleport_player_entity(tc_entity_s *entity, tc_location_s location) -{ - tc_set_float_for_entity(tc_game_state_g.viewer, "pos_x", location.position.x); - tc_set_float_for_entity(tc_game_state_g.viewer, "pos_y", location.position.y); - tc_set_float_for_entity(tc_game_state_g.viewer, "pos_z", location.position.z); -} - void tc_fn_delete_player_entity(tc_entity_s *entity) { if(entity->specific != NULL) free(entity->specific); @@ -45,9 +30,7 @@ void tc_register_player_entity() type.internal_name = "player"; type.display_name = "Player"; type.instances_capacity = 8; - type.functions.fn_create = tc_fn_create_player_entity; - type.functions.fn_spawn = tc_fn_spawn_player_entity; - type.functions.fn_teleport = tc_fn_teleport_player_entity; + type.functions.fn_create = (tc_entity_create_fn) tc_fn_create_player_entity; type.functions.fn_delete = tc_fn_delete_player_entity; type.functions.fn_send_event = tc_fn_send_event_player_entity; diff --git a/code/source-c/entity/registration.c b/code/source-c/entity/registration.c index d6648d2..b03e28b 100644 --- a/code/source-c/entity/registration.c +++ b/code/source-c/entity/registration.c @@ -2,6 +2,7 @@ void tc_register_entities() { + tc_register_chunk_entity(); tc_register_player_entity(); } diff --git a/code/source-c/entity/registration.h b/code/source-c/entity/registration.h index 5dac8b7..f740089 100644 --- a/code/source-c/entity/registration.h +++ b/code/source-c/entity/registration.h @@ -4,6 +4,7 @@ #include "../entity.h" +void tc_register_chunk_entity (); void tc_register_player_entity (); void tc_register_entities (); diff --git a/code/source-c/initialization.c b/code/source-c/initialization.c index 55a96df..f3624c1 100644 --- a/code/source-c/initialization.c +++ b/code/source-c/initialization.c @@ -71,19 +71,16 @@ void tc_init() tc_register_entities(); tc_game_state_g.on_world_create = tc_new_hooklist(16); - tc_add_to_hooklist(&tc_game_state_g.on_world_create, tc_create_world_physics, NULL); + tc_add_to_hooklist(&tc_game_state_g.on_world_create, (tc_fn_hook) &tc_create_world_physics, NULL); tc_init_worlds(); tc_game_state_g.main_world = tc_new_world(&tc_default_terrain_generator_g); tc_game_state_g.player = tc_create_entity("player", NULL); tc_game_state_g.viewer = tc_game_state_g.player; - tc_location_s spawn_location; - spawn_location.world = tc_game_state_g.main_world; - spawn_location.position.x = 0.0f; - spawn_location.position.y = 36.0f; - spawn_location.position.z = 0.0f; - tc_teleport_entity(tc_game_state_g.player, spawn_location); + tc_set_float_for_entity(tc_game_state_g.player, "pos_x", 0.0f); + tc_set_float_for_entity(tc_game_state_g.player, "pos_y", 38.0f); + tc_set_float_for_entity(tc_game_state_g.player, "pos_z", 0.0f); tc_game_state_g.tps = 120; @@ -92,6 +89,7 @@ void tc_init() void tc_cleanup() { + tc_unload_world(tc_game_state_g.main_world); tc_cleanup_chunk_pool(); SDL_GL_DeleteContext(tc_game_state_g.renderer.gl_context); SDL_DestroyWindow(tc_game_state_g.renderer.window); diff --git a/code/source-c/main.c b/code/source-c/main.c index 042b2f0..a7a33cf 100644 --- a/code/source-c/main.c +++ b/code/source-c/main.c @@ -247,22 +247,22 @@ bool update() if(go_left) { - difference_in_perspective.x -= 0.45f; + difference_in_perspective.x -= 2.0f; } if(go_right) { - difference_in_perspective.x += 0.45f; + difference_in_perspective.x += 2.0f; } if(go_forward) { - difference_in_perspective.z += 0.4f; + difference_in_perspective.z += 2.5f; } if(go_backwards) { - difference_in_perspective.z -= 0.4f; + difference_in_perspective.z -= 2.5f; } mat4x4 position_matrix; @@ -284,9 +284,9 @@ bool update() tc_move_viewer_to(camera_position.x, camera_position.y, camera_position.z); tc_rotate_viewer_to(camera_rotation.x, camera_rotation.y, camera_rotation.z); - tc_game_state_g.main_world->spawn_loader->center.x = ((int32_t) camera_position.x) / 32 - UPDATE_DISTANCE; - tc_game_state_g.main_world->spawn_loader->center.y = ((int32_t) camera_position.y) / 32 - UPDATE_DISTANCE; - tc_game_state_g.main_world->spawn_loader->center.z = - ((int32_t) camera_position.z) / 32 - UPDATE_DISTANCE; + tc_game_state_g.main_world->spawn_loader->center.grid_coords.x = ((int32_t) camera_position.x) / 32 - UPDATE_DISTANCE; + tc_game_state_g.main_world->spawn_loader->center.grid_coords.y = ((int32_t) camera_position.y) / 32 - UPDATE_DISTANCE; + tc_game_state_g.main_world->spawn_loader->center.grid_coords.z = - ((int32_t) camera_position.z) / 32 - UPDATE_DISTANCE; tc_update_world(tc_game_state_g.main_world); diff --git a/code/source-c/meshize.c b/code/source-c/meshize.c index 607ed18..5e943b8 100644 --- a/code/source-c/meshize.c +++ b/code/source-c/meshize.c @@ -177,8 +177,11 @@ uint32_t tc_meshize_block(tc_chunk_s *chunk, return num_vertices; } -void tc_meshize_chunk(tc_chunk_s *chunk, void *userdata) +void tc_meshize_chunk(tc_chunk_s *chunk) { + if(chunk->vertex_positions != NULL) free(chunk->vertex_positions); + if(chunk->vertex_uvs != NULL) free(chunk->vertex_uvs); + chunk->num_vertices = tc_count_chunk_vertices(chunk); chunk->vertex_positions = calloc(sizeof(float), 3 * chunk->num_vertices); chunk->vertex_uvs = calloc(sizeof(float), 2 * chunk->num_vertices); diff --git a/code/source-c/physics/entity_pool.c b/code/source-c/physics/entity_pool.c new file mode 100644 index 0000000..8d6f783 --- /dev/null +++ b/code/source-c/physics/entity_pool.c @@ -0,0 +1,4 @@ +#include + + + diff --git a/code/source-c/physics/physics.c b/code/source-c/physics/physics.c index 958857b..581770e 100644 --- a/code/source-c/physics/physics.c +++ b/code/source-c/physics/physics.c @@ -97,9 +97,12 @@ void tc_free_physics_entity(tc_physics_entity_s *entity) void tc_remove_physics_entity(tc_physics_entity_s *entity) { - u32_t num_entities = entity->simulation->root->value.group.num_entities; if(entity->super == NULL) return; + tc_free_physics_entity(entity); + + // Fill up the gap created inside the entities-array. + i32_t index = 0; if((index = tc_physics_find_entity_in_group(entity->super, entity)) == -1) return; diff --git a/code/source-c/physics/raycast.c b/code/source-c/physics/raycast.c index c66d98a..3e1de0a 100644 --- a/code/source-c/physics/raycast.c +++ b/code/source-c/physics/raycast.c @@ -2,9 +2,9 @@ tc_primitive_s * tc_cast_line(tc_physics_simulation_s *simulation, tc_line_s line) { + // TODO - - + return FALSE; } diff --git a/code/source-c/shaders.c b/code/source-c/shaders.c index 4dc04a6..cb570a7 100644 --- a/code/source-c/shaders.c +++ b/code/source-c/shaders.c @@ -29,12 +29,12 @@ tc_shader_program_s tc_make_shader_program(char *vertex_path, char *fragment_pat int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); int len_vertex_source = 0; - const char *vertex_source = load_file(vertex_path, &len_vertex_source); - const char *const *vsource = &vertex_source; + char *vertex_source = load_file(vertex_path, &len_vertex_source); + const char *const *vsource = (const char *const *) &vertex_source; int len_fragment_source = 0; - const char *fragment_source = load_file(fragment_path, &len_fragment_source); - const char *const *fsource = &fragment_source; + char *fragment_source = load_file(fragment_path, &len_fragment_source); + const char *const *fsource = (const char *const *) &fragment_source; glShaderSource(vertex_shader, 1, vsource, &len_vertex_source); glShaderSource(fragment_shader, 1, fsource, &len_fragment_source); diff --git a/code/source-c/utility/location.c b/code/source-c/utility/location.c index aac35cb..fdf4a7f 100644 --- a/code/source-c/utility/location.c +++ b/code/source-c/utility/location.c @@ -2,14 +2,13 @@ #include -tc_location_s tc_zero_location() +tc_chunk_location_s tc_zero_chunk_location() { - tc_location_s location; - location.world = NULL; - location.position.x = 0.0f; - location.position.y = 0.0f; - location.position.z = 0.0f; - location.rotation = location.position; + tc_chunk_location_s location; + location.world = NULL; + location.grid_coords.x = 0; + location.grid_coords.y = 0; + location.grid_coords.z = 0; return location; } diff --git a/code/source-c/utility/location.h b/code/source-c/utility/location.h index ec3694f..3c22ba3 100644 --- a/code/source-c/utility/location.h +++ b/code/source-c/utility/location.h @@ -4,15 +4,29 @@ #include -typedef struct tc_location +typedef struct tc_entity_location { void *world; - tc_vec3f_s position; + tc_vec3f_s coords; tc_vec3f_s rotation; -} tc_location_s; +} tc_entity_location_s; -tc_location_s tc_zero_location(); +typedef struct tc_block_location +{ + void *world; + tc_vec3i_s block_coords; + +} tc_block_location_s; + +typedef struct tc_chunk_location +{ + void *world; + tc_vec3i_s grid_coords; + +} tc_chunk_location_s; + +tc_chunk_location_s tc_zero_chunk_location(); #endif // TC_LOCATION_H diff --git a/code/source-c/world.c b/code/source-c/world.c index 5e0efb7..acb98b7 100644 --- a/code/source-c/world.c +++ b/code/source-c/world.c @@ -3,78 +3,10 @@ #include +void tc_add_chunk_to_loader(tc_chunkloader_s *loader, tc_entity_s *entity); + + tc_worldgen_s tc_default_terrain_generator_g; -tc_entity_type_s *tc_chunk_entity_type_g = NULL; - -void tc_upload_chunk(tc_chunk_s *chunk) -{ - // If the chunk has no mesh, it's probably only air. - if(chunk->num_vertices == 0) - { - return; - } - - if(chunk->vao != 0) glDeleteVertexArrays(1, &chunk->vao); - if(chunk->vertex_data != 0) glDeleteBuffers(1, &chunk->vertex_data); - - 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_entity(tc_entity_s *entity) -{ - tc_chunk_s *chunk = entity->specific; - - tc_mat4f_s model_matrix = tc_mat4f_identity(); - - tc_vec3f_s position_3f; - position_3f.x = chunk->position.x * 32; - position_3f.y = chunk->position.y * 32; - position_3f.z = chunk->position.z * 32; - - model_matrix = - tc_mat4f_translate(model_matrix, position_3f); - - tc_shader_uniform_mat4f(&tc_game_state_g.renderer.draw_shader, "model_matrix", model_matrix); - - glBindBuffer(GL_ARRAY_BUFFER, chunk->vertex_data); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *) 0); - glEnableVertexAttribArray(0); - - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - (void *) (sizeof(float) * 3 * chunk->num_vertices) - ); - - glEnableVertexAttribArray(1); - - glActiveTexture(GL_TEXTURE0); - glUniform1i( - glGetUniformLocation(tc_game_state_g.renderer.draw_shader.program_id, "block_atlas"), - 0 - ); - glBindTexture(GL_TEXTURE_2D, tc_game_state_g.block_texture_atlas->gl_identifier); - - glDrawArrays(GL_TRIANGLES, 0, chunk->num_vertices); - - glBindVertexArray(0); -} - void tc_init_world_generators() { tc_default_terrain_generator_g.name = "Default Terrain Generator"; @@ -82,82 +14,9 @@ void tc_init_world_generators() } -// The userdata should be the corresponding world -void tc_create_chunk_entity(tc_entity_s *entity, void *userdata) -{ - tc_chunk_s *chunk = tc_allocate_chunk(); - tc_world_s *world = userdata; - - tc_set_string_for_entity(entity, "type", "chunk"); - tc_set_integer_for_entity(entity, "grid_x", 0); - tc_set_integer_for_entity(entity, "grid_y", 0); - tc_set_integer_for_entity(entity, "grid_z", 0); - entity->specific = chunk; - chunk->world = world; - - tc_run_hooklist(&world->on_chunk_create, entity); -} - -void tc_spawn_chunk_entity(tc_entity_s *entity, tc_location_s location) -{ - - - -} - -void tc_teleport_chunk_entity(tc_entity_s *entity, tc_location_s location) -{ - tc_chunk_s *chunk = entity->specific; - chunk->world = location.world; - chunk->position.x = location.position.x / 32; - chunk->position.y = location.position.y / 32; - chunk->position.z = location.position.z / 32; -} - -void tc_delete_chunk_entity(tc_entity_s *entity) -{ - tc_chunk_s *chunk = entity->specific; - glDeleteVertexArrays(1, &chunk->vao); - glDeleteBuffers(1, &chunk->vertex_data); - - if(chunk->vertex_positions != NULL) free(chunk->vertex_positions); - if(chunk->vertex_uvs != NULL) free(chunk->vertex_uvs); - - tc_physics_entity_s *physics_body = tc_get_pointer_from_entity(entity, "physics_body"); - tc_remove_physics_entity(physics_body); - - tc_deallocate_chunk(entity->specific); -} - -void tc_receive_chunk_entity_event(tc_entity_s *entity, tc_entity_event_s event) -{ - -} - -void tc_add_chunk_entity_type() -{ - tc_fn_entity_s chunk_functions; - chunk_functions.fn_create = &tc_create_chunk_entity; - chunk_functions.fn_spawn = &tc_spawn_chunk_entity; - chunk_functions.fn_teleport = &tc_teleport_chunk_entity; - chunk_functions.fn_draw = &tc_draw_chunk_entity; - chunk_functions.fn_delete = &tc_delete_chunk_entity; - chunk_functions.fn_send_event = &tc_receive_chunk_entity_event; - - tc_entity_type_s chunk_type; - chunk_type.internal_name = "chunk"; - chunk_type.display_name = NULL; - chunk_type.functions = chunk_functions; - chunk_type.instances_capacity = 512; - - tc_register_entity_type(chunk_type); - tc_chunk_entity_type_g = tc_get_entity_type_with_name("chunk"); -} - void tc_init_worlds() { tc_init_chunk_pool(256); - tc_add_chunk_entity_type(); tc_init_world_generators(); } @@ -173,30 +32,22 @@ void tc_set_block_in_chunk( void tc_draw_world(tc_world_s *world) { - tc_draw_all_entities_of_type("chunk"); -} -tc_chunkloader_s tc_create_chunkloader(tc_world_s *world) -{ - tc_chunkloader_s loader; - loader.extent.x = UPDATE_DISTANCE * 2 + 1; - loader.extent.y = UPDATE_DISTANCE * 2 + 1; - loader.extent.z = UPDATE_DISTANCE * 2 + 1; - loader.center.x = 0; - loader.center.y = 0; - loader.center.z = 0; - loader.chunks_capacity = 512; - loader.chunks = calloc(sizeof(tc_entity_s *), loader.chunks_capacity); - loader.num_chunks = 0; - loader.needs_reload = false; - - return loader; + for(u32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index) + { + if(world->loaders[loader_index].is_rendered) tc_draw_chunkloader_zone(&world->loaders[loader_index]); + } } tc_chunkloader_s tc_create_spawn_loader(tc_world_s *world) { - tc_chunkloader_s loader = tc_create_chunkloader(world); - loader.needs_reload = true; - loader.world = world; + tc_chunk_location_s loader_location; + loader_location.world = world; + loader_location.grid_coords.x = 0.0f; + loader_location.grid_coords.y = 0.0f; + loader_location.grid_coords.z = 0.0f; + + tc_chunkloader_s loader = tc_create_chunkloader(loader_location); + loader.is_rendered = TRUE; return loader; } @@ -204,21 +55,29 @@ tc_chunkloader_s tc_create_spawn_loader(tc_world_s *world) tc_world_s * tc_new_world(tc_worldgen_s *generator) { tc_world_s *world = calloc(sizeof(tc_world_s), 1); - world->worldgen = &tc_default_terrain_generator_g; - world->num_loaders = 1; - world->loaders = malloc(sizeof(tc_chunkloader_s) * world->num_loaders); - world->loaders[0] = tc_create_spawn_loader(world); - world->spawn_loader = &world->loaders[0]; - world->on_chunk_create = tc_new_hooklist(16); - world->on_chunk_generate = tc_new_hooklist(16); - world->after_chunk_generate = tc_new_hooklist(16); - world->on_chunk_delete = tc_new_hooklist(16); - world->on_chunk_update = tc_new_hooklist(16); + world->on_chunk_create = tc_new_hooklist(16); + world->before_chunk_generate = tc_new_hooklist(16); + world->after_chunk_generate = tc_new_hooklist(16); + world->on_chunk_delete = tc_new_hooklist(16); + world->on_chunk_update = tc_new_hooklist(16); + world->worldgen = &tc_default_terrain_generator_g; + world->num_loaders = 1; + world->loaders = malloc(sizeof(tc_chunkloader_s) * world->num_loaders); + world->loaders[0] = tc_create_spawn_loader(world); + world->spawn_loader = &world->loaders[0]; - tc_add_to_hooklist(&world->after_chunk_generate, tc_meshize_chunk, NULL); + tc_add_to_hooklist(&world->after_chunk_generate, (tc_fn_hook) tc_meshize_chunk, NULL); tc_run_hooklist(&tc_game_state_g.on_world_create, world); + tc_update_world(world); + return world; } +void tc_unload_world(tc_world_s *world) +{ + tc_delete_chunkloader(*world->spawn_loader); + free(world); +} + diff --git a/code/source-c/world.h b/code/source-c/world.h index 4dc55a3..c1eede7 100644 --- a/code/source-c/world.h +++ b/code/source-c/world.h @@ -9,23 +9,22 @@ #include #include #include +#include +#include #define UPDATE_DISTANCE 2 -typedef struct tc_worldgen tc_worldgen_s; 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 -{ +typedef struct tc_worldgen tc_worldgen_s; + +struct tc_worldgen { char *name; - bool (*fn_generate_chunk) (tc_worldgen_s *gen, tc_chunk_s *chunk); + bool_t (*fn_generate_chunk) (tc_worldgen_s *gen, tc_chunk_s *chunk); }; @@ -37,55 +36,7 @@ struct tc_block }; -struct tc_chunk -{ - tc_world_s *world; - tc_chunk_pool_entry_s *pool_entry; - - tc_vec3i_s position; - u32_t blocks[32][32][32]; - - u32_t num_vertices; - f32_t *vertex_positions; - f32_t *vertex_uvs; - - u32_t vao; - u32_t vertex_data; -}; -struct tc_chunk_pool_entry -{ - tc_chunk_pool_entry_s *next; - tc_chunk_pool_entry_s *previous; - - tc_chunk_s chunk; -}; - -struct tc_chunk_pool -{ - tc_world_s *world; - - u32_t capacity; - u32_t used_entries; - tc_chunk_pool_entry_s *entries; - tc_chunk_pool_entry_s *first_free; - - tc_chunk_pool_s *continuation; -}; - -typedef struct tc_chunkloader -{ - tc_vec3i_s center; - tc_vec3i_s extent; - - u32_t chunks_capacity; - u32_t num_chunks; - tc_entity_s **chunks; - tc_world_s *world; - - bool needs_reload; - -} tc_chunkloader_s; struct tc_world { @@ -99,7 +50,7 @@ struct tc_world tc_physics_simulation_s *physics; tc_hooklist_s on_chunk_create; - tc_hooklist_s on_chunk_generate; + tc_hooklist_s before_chunk_generate; tc_hooklist_s after_chunk_generate; tc_hooklist_s on_chunk_delete; tc_hooklist_s on_chunk_update; @@ -119,29 +70,10 @@ void tc_set_block_in_chunk( tc_block_s block ); -u32_t tc_count_chunk_vertices (tc_chunk_s *chunk); -void tc_meshize_chunk (tc_chunk_s *chunk, void *userdata); -void tc_upload_chunk (tc_chunk_s *chunk); - -bool tc_generate_default_terrain_chunk (tc_worldgen_s *gen, tc_chunk_s *chunk); - -void tc_add_chunk_to_loader (tc_chunkloader_s *chunkloader, tc_entity_s *entity); -tc_chunk_s * tc_load_chunk_at (tc_world_s *world, i32_t x, i32_t y, i32_t z); -tc_chunk_s * tc_get_loaded_chunk_at (tc_world_s *world, i32_t x, i32_t y, i32_t z); -bool tc_chunk_is_loaded (tc_world_s *world, i32_t x, i32_t y, i32_t z); - void tc_update_world (tc_world_s *world); +void tc_unload_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 -); - -void tc_cleanup_chunk_pool (); -void tc_init_chunk_pool (u32_t capacity); -tc_chunk_s * tc_allocate_chunk (); -void tc_deallocate_chunk (tc_chunk_s *chunk); +bool_t tc_generate_default_terrain_chunk (tc_worldgen_s *gen, tc_chunk_s *chunk); void tc_create_world_physics (tc_world_s *world, void *userdata); diff --git a/code/source-c/world_physics.c b/code/source-c/world_physics.c index 60a5574..8e93e48 100644 --- a/code/source-c/world_physics.c +++ b/code/source-c/world_physics.c @@ -5,7 +5,7 @@ void tc_initialize_chunk_physics(tc_entity_s *chunk_entity, void *userdata) { tc_chunk_s *chunk = chunk_entity->specific; - tc_world_s *world = chunk->world; + tc_world_s *world = chunk->location.world; tc_physics_simulation_s *simulation = world->physics; tc_physics_entity_s *chunk_body = tc_new_physics_group(simulation); @@ -44,7 +44,7 @@ void tc_initialize_chunk_physics(tc_entity_s *chunk_entity, void *userdata) void tc_create_world_physics(tc_world_s *world, void *userdata) { world->physics = tc_new_physics_simulation(); - tc_add_to_hooklist(&world->on_chunk_create, &tc_initialize_chunk_physics, NULL); - tc_add_to_hooklist(&world->on_chunk_update, &tc_initialize_chunk_physics, NULL); + tc_add_to_hooklist(&world->on_chunk_create, (tc_fn_hook) tc_initialize_chunk_physics, NULL); + tc_add_to_hooklist(&world->on_chunk_update, (tc_fn_hook) tc_initialize_chunk_physics, NULL); }