Some medium-sized refactor
This commit is contained in:
parent
163457c5b8
commit
fb0aa65d00
|
@ -0,0 +1,45 @@
|
||||||
|
#include <chunk.h>
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
|
||||||
|
#ifndef TC_CHUNK_H
|
||||||
|
#define TC_CHUNK_H
|
||||||
|
|
||||||
|
#include <utility/location.h>
|
||||||
|
#include <entity.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -1,168 +0,0 @@
|
||||||
#include "world.h"
|
|
||||||
#include "entity.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -75,20 +75,20 @@ void tc_deallocate_chunk(tc_chunk_s *chunk)
|
||||||
{
|
{
|
||||||
if(chunk->vao != 0)
|
if(chunk->vao != 0)
|
||||||
{
|
{
|
||||||
glDeleteVertexArrays(1, &chunk->vertex_data);
|
glDeleteVertexArrays(1, &chunk->vbo);
|
||||||
chunk->vao = 0;
|
chunk->vao = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(chunk->vertex_data != 0)
|
if(chunk->vbo != 0)
|
||||||
{
|
{
|
||||||
glDeleteBuffers(1, &chunk->vertex_data);
|
glDeleteBuffers(1, &chunk->vbo);
|
||||||
chunk->vertex_data = 0;
|
chunk->vbo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tc_chunk_pool_entry_s *entry = chunk->pool_entry;
|
tc_chunk_pool_entry_s *entry = chunk->pool_entry;
|
||||||
chunk->pool_entry->next = tc_chunk_pool_g->first_free;
|
entry->next = tc_chunk_pool_g->first_free;
|
||||||
tc_chunk_pool_g->first_free = entry;
|
tc_chunk_pool_g->first_free = entry;
|
||||||
memset(&chunk, 0x00, sizeof(tc_chunk_s));
|
memset(chunk, 0x00, sizeof(tc_chunk_s));
|
||||||
chunk->pool_entry = entry;
|
chunk->pool_entry = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
#ifndef TC_CHUNK_POOL_H
|
||||||
|
#define TC_CHUNK_POOL_H
|
||||||
|
|
||||||
|
#include <utility/utility.h>
|
||||||
|
#include <chunk.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -0,0 +1,291 @@
|
||||||
|
#include "world.h"
|
||||||
|
#include "entity.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "world.h"
|
#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;
|
tc_block_s block;
|
||||||
block.type_identifier = 1 | TC_BLOCK_OPAQUE_BIT;
|
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;
|
tc_block_s grass;
|
||||||
grass.type_identifier = 2 | TC_BLOCK_OPAQUE_BIT;
|
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 x_in_chunk = 0;
|
||||||
uint32_t y_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;
|
++x_in_chunk;
|
||||||
}
|
}
|
||||||
if(chunk->position.y == 0)
|
if(chunk->location.grid_coords.y == 0)
|
||||||
{
|
{
|
||||||
x_in_chunk = 0;
|
x_in_chunk = 0;
|
||||||
while(x_in_chunk < 32)
|
while(x_in_chunk < 32)
|
||||||
|
|
|
@ -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)
|
if(type->num_instances >= type->instances_capacity)
|
||||||
{
|
{
|
||||||
type->instances_capacity *= 2;
|
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->instances[type->num_instances] = entity;
|
||||||
++type->num_instances;
|
++type->num_instances;
|
||||||
|
@ -96,28 +96,20 @@ tc_entity_s * tc_create_entity(char *type, void *userdata)
|
||||||
return entity;
|
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)
|
void tc_delete_entity(tc_entity_s *entity)
|
||||||
{
|
{
|
||||||
tc_entity_type_s *type = entity->type;
|
tc_entity_type_s *type = entity->type;
|
||||||
|
|
||||||
|
entity->type->functions.fn_delete(entity);
|
||||||
|
|
||||||
i32_t instance_index =
|
i32_t instance_index =
|
||||||
tc_find_entity_instance_index_in_type(type, entity);
|
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)
|
if(instance_index == -1)
|
||||||
{
|
{
|
||||||
puts("Entity can't be found as an instance of it's type?!");
|
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->num_instances;
|
||||||
type->instances[instance_index] = type->instances[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];
|
tc_entity_attribute_s attribute = entity->attributes[attribute_index];
|
||||||
if(attribute.name == NULL)
|
if(attribute.name == NULL)
|
||||||
{
|
{
|
||||||
puts("NAAJAA");
|
|
||||||
++attribute_index;
|
++attribute_index;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(!strcmp(attribute.name, name)) return &entity->attributes[attribute_index];
|
if(!strcmp(attribute.name, name))
|
||||||
|
{
|
||||||
|
return &entity->attributes[attribute_index];
|
||||||
|
}
|
||||||
++attribute_index;
|
++attribute_index;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -160,8 +150,9 @@ tc_entity_attribute_s * tc_allocate_entity_attribute(tc_entity_s *entity)
|
||||||
entity->attributes_capacity *= 2;
|
entity->attributes_capacity *= 2;
|
||||||
entity->attributes = realloc(entity->attributes, sizeof(tc_entity_attribute_s) * entity->attributes_capacity);
|
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;
|
++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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
void tc_draw_all_entities_of_type(char *name)
|
||||||
{
|
{
|
||||||
tc_entity_type_s *type = tc_get_entity_type_with_name(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;
|
++entity_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
|
@ -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_pool_entry tc_entity_pool_entry_s;
|
||||||
typedef struct tc_entity_registry tc_entity_registry_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
|
typedef struct
|
||||||
{
|
{
|
||||||
void (*fn_create) (tc_entity_s *entity, void *userdata);
|
tc_entity_create_fn fn_create;
|
||||||
void (*fn_spawn) (tc_entity_s *entity, tc_location_s location);
|
tc_entity_delete_fn fn_delete;
|
||||||
void (*fn_teleport) (tc_entity_s *entity, tc_location_s location);
|
tc_entity_send_event_fn fn_send_event;
|
||||||
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_fn_entity_s;
|
} tc_fn_entity_s;
|
||||||
|
|
||||||
|
@ -70,7 +70,6 @@ struct tc_entity
|
||||||
{
|
{
|
||||||
tc_entity_pool_entry_s *pool_entry;
|
tc_entity_pool_entry_s *pool_entry;
|
||||||
|
|
||||||
tc_location_s location;
|
|
||||||
tc_entity_type_s *type;
|
tc_entity_type_s *type;
|
||||||
|
|
||||||
u16_t attributes_capacity;
|
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_type_s * tc_get_entity_type_with_name (char *name);
|
||||||
|
|
||||||
tc_entity_s * tc_create_entity (char *type, void *userdata);
|
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_delete_entity (tc_entity_s *entity);
|
||||||
|
|
||||||
void tc_set_pointer_for_entity (tc_entity_s *entity, char *attr_name, void *pointer);
|
void tc_set_pointer_for_entity (tc_entity_s *entity, char *attr_name, void *pointer);
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
#include <entity/registration.h>
|
||||||
|
#include <chunk_pool.h>
|
||||||
|
#include <chunk.h>
|
||||||
|
#include <world.h>
|
||||||
|
#include <state.h>
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
|
@ -8,24 +8,9 @@ tc_entity_type_s *tc_player_entity_type_g = NULL;
|
||||||
void tc_fn_create_player_entity(tc_entity_s *entity)
|
void tc_fn_create_player_entity(tc_entity_s *entity)
|
||||||
{
|
{
|
||||||
entity->type = tc_player_entity_type_g;
|
entity->type = tc_player_entity_type_g;
|
||||||
entity->location = tc_zero_location();
|
|
||||||
entity->specific = NULL;
|
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)
|
void tc_fn_delete_player_entity(tc_entity_s *entity)
|
||||||
{
|
{
|
||||||
if(entity->specific != NULL) free(entity->specific);
|
if(entity->specific != NULL) free(entity->specific);
|
||||||
|
@ -45,9 +30,7 @@ void tc_register_player_entity()
|
||||||
type.internal_name = "player";
|
type.internal_name = "player";
|
||||||
type.display_name = "Player";
|
type.display_name = "Player";
|
||||||
type.instances_capacity = 8;
|
type.instances_capacity = 8;
|
||||||
type.functions.fn_create = tc_fn_create_player_entity;
|
type.functions.fn_create = (tc_entity_create_fn) 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_delete = tc_fn_delete_player_entity;
|
type.functions.fn_delete = tc_fn_delete_player_entity;
|
||||||
type.functions.fn_send_event = tc_fn_send_event_player_entity;
|
type.functions.fn_send_event = tc_fn_send_event_player_entity;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
void tc_register_entities()
|
void tc_register_entities()
|
||||||
{
|
{
|
||||||
|
tc_register_chunk_entity();
|
||||||
tc_register_player_entity();
|
tc_register_player_entity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "../entity.h"
|
#include "../entity.h"
|
||||||
|
|
||||||
|
void tc_register_chunk_entity ();
|
||||||
void tc_register_player_entity ();
|
void tc_register_player_entity ();
|
||||||
void tc_register_entities ();
|
void tc_register_entities ();
|
||||||
|
|
||||||
|
|
|
@ -71,19 +71,16 @@ void tc_init()
|
||||||
tc_register_entities();
|
tc_register_entities();
|
||||||
|
|
||||||
tc_game_state_g.on_world_create = tc_new_hooklist(16);
|
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_init_worlds();
|
||||||
tc_game_state_g.main_world = tc_new_world(&tc_default_terrain_generator_g);
|
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.player = tc_create_entity("player", NULL);
|
||||||
tc_game_state_g.viewer = tc_game_state_g.player;
|
tc_game_state_g.viewer = tc_game_state_g.player;
|
||||||
|
|
||||||
tc_location_s spawn_location;
|
tc_set_float_for_entity(tc_game_state_g.player, "pos_x", 0.0f);
|
||||||
spawn_location.world = tc_game_state_g.main_world;
|
tc_set_float_for_entity(tc_game_state_g.player, "pos_y", 38.0f);
|
||||||
spawn_location.position.x = 0.0f;
|
tc_set_float_for_entity(tc_game_state_g.player, "pos_z", 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_game_state_g.tps = 120;
|
tc_game_state_g.tps = 120;
|
||||||
|
|
||||||
|
@ -92,6 +89,7 @@ void tc_init()
|
||||||
|
|
||||||
void tc_cleanup()
|
void tc_cleanup()
|
||||||
{
|
{
|
||||||
|
tc_unload_world(tc_game_state_g.main_world);
|
||||||
tc_cleanup_chunk_pool();
|
tc_cleanup_chunk_pool();
|
||||||
SDL_GL_DeleteContext(tc_game_state_g.renderer.gl_context);
|
SDL_GL_DeleteContext(tc_game_state_g.renderer.gl_context);
|
||||||
SDL_DestroyWindow(tc_game_state_g.renderer.window);
|
SDL_DestroyWindow(tc_game_state_g.renderer.window);
|
||||||
|
|
|
@ -247,22 +247,22 @@ bool update()
|
||||||
|
|
||||||
if(go_left)
|
if(go_left)
|
||||||
{
|
{
|
||||||
difference_in_perspective.x -= 0.45f;
|
difference_in_perspective.x -= 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(go_right)
|
if(go_right)
|
||||||
{
|
{
|
||||||
difference_in_perspective.x += 0.45f;
|
difference_in_perspective.x += 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(go_forward)
|
if(go_forward)
|
||||||
{
|
{
|
||||||
difference_in_perspective.z += 0.4f;
|
difference_in_perspective.z += 2.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(go_backwards)
|
if(go_backwards)
|
||||||
{
|
{
|
||||||
difference_in_perspective.z -= 0.4f;
|
difference_in_perspective.z -= 2.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4x4 position_matrix;
|
mat4x4 position_matrix;
|
||||||
|
@ -284,9 +284,9 @@ bool update()
|
||||||
tc_move_viewer_to(camera_position.x, camera_position.y, camera_position.z);
|
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_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.grid_coords.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.grid_coords.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.z = - ((int32_t) camera_position.z) / 32 - UPDATE_DISTANCE;
|
||||||
|
|
||||||
tc_update_world(tc_game_state_g.main_world);
|
tc_update_world(tc_game_state_g.main_world);
|
||||||
|
|
||||||
|
|
|
@ -177,8 +177,11 @@ uint32_t tc_meshize_block(tc_chunk_s *chunk,
|
||||||
return num_vertices;
|
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->num_vertices = tc_count_chunk_vertices(chunk);
|
||||||
chunk->vertex_positions = calloc(sizeof(float), 3 * chunk->num_vertices);
|
chunk->vertex_positions = calloc(sizeof(float), 3 * chunk->num_vertices);
|
||||||
chunk->vertex_uvs = calloc(sizeof(float), 2 * chunk->num_vertices);
|
chunk->vertex_uvs = calloc(sizeof(float), 2 * chunk->num_vertices);
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include <physics/simulation.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -97,9 +97,12 @@ void tc_free_physics_entity(tc_physics_entity_s *entity)
|
||||||
|
|
||||||
void tc_remove_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;
|
if(entity->super == NULL) return;
|
||||||
|
|
||||||
|
tc_free_physics_entity(entity);
|
||||||
|
|
||||||
|
// Fill up the gap created inside the entities-array.
|
||||||
|
|
||||||
i32_t index = 0;
|
i32_t index = 0;
|
||||||
if((index = tc_physics_find_entity_in_group(entity->super, entity)) == -1) return;
|
if((index = tc_physics_find_entity_in_group(entity->super, entity)) == -1) return;
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
tc_primitive_s * tc_cast_line(tc_physics_simulation_s *simulation, tc_line_s line)
|
tc_primitive_s * tc_cast_line(tc_physics_simulation_s *simulation, tc_line_s line)
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
int len_vertex_source = 0;
|
int len_vertex_source = 0;
|
||||||
const char *vertex_source = load_file(vertex_path, &len_vertex_source);
|
char *vertex_source = load_file(vertex_path, &len_vertex_source);
|
||||||
const char *const *vsource = &vertex_source;
|
const char *const *vsource = (const char *const *) &vertex_source;
|
||||||
|
|
||||||
int len_fragment_source = 0;
|
int len_fragment_source = 0;
|
||||||
const char *fragment_source = load_file(fragment_path, &len_fragment_source);
|
char *fragment_source = load_file(fragment_path, &len_fragment_source);
|
||||||
const char *const *fsource = &fragment_source;
|
const char *const *fsource = (const char *const *) &fragment_source;
|
||||||
|
|
||||||
glShaderSource(vertex_shader, 1, vsource, &len_vertex_source);
|
glShaderSource(vertex_shader, 1, vsource, &len_vertex_source);
|
||||||
glShaderSource(fragment_shader, 1, fsource, &len_fragment_source);
|
glShaderSource(fragment_shader, 1, fsource, &len_fragment_source);
|
||||||
|
|
|
@ -2,14 +2,13 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
tc_location_s tc_zero_location()
|
tc_chunk_location_s tc_zero_chunk_location()
|
||||||
{
|
{
|
||||||
tc_location_s location;
|
tc_chunk_location_s location;
|
||||||
location.world = NULL;
|
location.world = NULL;
|
||||||
location.position.x = 0.0f;
|
location.grid_coords.x = 0;
|
||||||
location.position.y = 0.0f;
|
location.grid_coords.y = 0;
|
||||||
location.position.z = 0.0f;
|
location.grid_coords.z = 0;
|
||||||
location.rotation = location.position;
|
|
||||||
|
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,29 @@
|
||||||
|
|
||||||
#include <utility/math.h>
|
#include <utility/math.h>
|
||||||
|
|
||||||
typedef struct tc_location
|
typedef struct tc_entity_location
|
||||||
{
|
{
|
||||||
void *world;
|
void *world;
|
||||||
tc_vec3f_s position;
|
tc_vec3f_s coords;
|
||||||
tc_vec3f_s rotation;
|
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
|
#endif // TC_LOCATION_H
|
||||||
|
|
||||||
|
|
|
@ -3,78 +3,10 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void tc_add_chunk_to_loader(tc_chunkloader_s *loader, tc_entity_s *entity);
|
||||||
|
|
||||||
|
|
||||||
tc_worldgen_s tc_default_terrain_generator_g;
|
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()
|
void tc_init_world_generators()
|
||||||
{
|
{
|
||||||
tc_default_terrain_generator_g.name = "Default Terrain Generator";
|
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()
|
void tc_init_worlds()
|
||||||
{
|
{
|
||||||
tc_init_chunk_pool(256);
|
tc_init_chunk_pool(256);
|
||||||
tc_add_chunk_entity_type();
|
|
||||||
tc_init_world_generators();
|
tc_init_world_generators();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,30 +32,22 @@ void tc_set_block_in_chunk(
|
||||||
|
|
||||||
void tc_draw_world(tc_world_s *world)
|
void tc_draw_world(tc_world_s *world)
|
||||||
{
|
{
|
||||||
tc_draw_all_entities_of_type("chunk");
|
for(u32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index)
|
||||||
}
|
|
||||||
tc_chunkloader_s tc_create_chunkloader(tc_world_s *world)
|
|
||||||
{
|
{
|
||||||
tc_chunkloader_s loader;
|
if(world->loaders[loader_index].is_rendered) tc_draw_chunkloader_zone(&world->loaders[loader_index]);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tc_chunkloader_s tc_create_spawn_loader(tc_world_s *world)
|
tc_chunkloader_s tc_create_spawn_loader(tc_world_s *world)
|
||||||
{
|
{
|
||||||
tc_chunkloader_s loader = tc_create_chunkloader(world);
|
tc_chunk_location_s loader_location;
|
||||||
loader.needs_reload = true;
|
loader_location.world = world;
|
||||||
loader.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;
|
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 * tc_new_world(tc_worldgen_s *generator)
|
||||||
{
|
{
|
||||||
tc_world_s *world = calloc(sizeof(tc_world_s), 1);
|
tc_world_s *world = calloc(sizeof(tc_world_s), 1);
|
||||||
|
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->worldgen = &tc_default_terrain_generator_g;
|
||||||
world->num_loaders = 1;
|
world->num_loaders = 1;
|
||||||
world->loaders = malloc(sizeof(tc_chunkloader_s) * world->num_loaders);
|
world->loaders = malloc(sizeof(tc_chunkloader_s) * world->num_loaders);
|
||||||
world->loaders[0] = tc_create_spawn_loader(world);
|
world->loaders[0] = tc_create_spawn_loader(world);
|
||||||
world->spawn_loader = &world->loaders[0];
|
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);
|
|
||||||
|
|
||||||
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_run_hooklist(&tc_game_state_g.on_world_create, world);
|
||||||
|
|
||||||
|
tc_update_world(world);
|
||||||
|
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tc_unload_world(tc_world_s *world)
|
||||||
|
{
|
||||||
|
tc_delete_chunkloader(*world->spawn_loader);
|
||||||
|
free(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,23 +9,22 @@
|
||||||
#include <physics/simulation.h>
|
#include <physics/simulation.h>
|
||||||
#include <utility/math.h>
|
#include <utility/math.h>
|
||||||
#include <entity.h>
|
#include <entity.h>
|
||||||
|
#include <chunk.h>
|
||||||
|
#include <chunk_pool.h>
|
||||||
|
|
||||||
|
|
||||||
#define UPDATE_DISTANCE 2
|
#define UPDATE_DISTANCE 2
|
||||||
|
|
||||||
|
|
||||||
typedef struct tc_worldgen tc_worldgen_s;
|
|
||||||
typedef struct tc_block tc_block_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_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;
|
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
|
struct tc_world
|
||||||
{
|
{
|
||||||
|
@ -99,7 +50,7 @@ struct tc_world
|
||||||
tc_physics_simulation_s *physics;
|
tc_physics_simulation_s *physics;
|
||||||
|
|
||||||
tc_hooklist_s on_chunk_create;
|
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 after_chunk_generate;
|
||||||
tc_hooklist_s on_chunk_delete;
|
tc_hooklist_s on_chunk_delete;
|
||||||
tc_hooklist_s on_chunk_update;
|
tc_hooklist_s on_chunk_update;
|
||||||
|
@ -119,29 +70,10 @@ void tc_set_block_in_chunk(
|
||||||
tc_block_s block
|
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_update_world (tc_world_s *world);
|
||||||
|
void tc_unload_world (tc_world_s *world);
|
||||||
|
|
||||||
void tc_on_each_loaded_chunk (
|
bool_t tc_generate_default_terrain_chunk (tc_worldgen_s *gen, tc_chunk_s *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);
|
|
||||||
|
|
||||||
void tc_create_world_physics (tc_world_s *world, void *userdata);
|
void tc_create_world_physics (tc_world_s *world, void *userdata);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
void tc_initialize_chunk_physics(tc_entity_s *chunk_entity, void *userdata)
|
void tc_initialize_chunk_physics(tc_entity_s *chunk_entity, void *userdata)
|
||||||
{
|
{
|
||||||
tc_chunk_s *chunk = chunk_entity->specific;
|
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_simulation_s *simulation = world->physics;
|
||||||
|
|
||||||
tc_physics_entity_s *chunk_body = tc_new_physics_group(simulation);
|
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)
|
void tc_create_world_physics(tc_world_s *world, void *userdata)
|
||||||
{
|
{
|
||||||
world->physics = tc_new_physics_simulation();
|
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_create, (tc_fn_hook) 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_update, (tc_fn_hook) tc_initialize_chunk_physics, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue