polyadvent

A game engine from scratch in C
git clone git://jb55.com/polyadvent
Log | Files | Refs | README

commit d46337ec1b2bf722e315d6534df25dfab11d9d02
parent ecca662a2c4afb0c5be1b7befd9c277a42a247e8
Author: William Casarin <jb55@jb55.com>
Date:   Tue, 20 Nov 2018 00:34:46 -0800

more progress

Diffstat:
Msrc/entity.c | 76++++++++++++++++------------------------------------------------------------
Msrc/entity.h | 3++-
Msrc/geometry.c | 10+++++-----
Msrc/node.c | 1+
Msrc/ply.c | 5++---
Msrc/resource.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/resource.h | 12++++++++++--
Msrc/skybox.c | 5++---
Msrc/terrain.c | 2+-
Msrc/ui.c | 6++----
10 files changed, 131 insertions(+), 81 deletions(-)

diff --git a/src/entity.c b/src/entity.c @@ -9,10 +9,8 @@ static struct resource_manager esys; -static u64 entity_uuids = 0; - struct entity *get_all_entities(u32 *count, entity_id_t **ids) { - return (struct entity*)get_all_resources(count, ids); + return get_all_resources(&esys, count, ids); } struct entity *init_entity(struct entity *ent) { @@ -21,74 +19,35 @@ struct entity *init_entity(struct entity *ent) { return ent; } -struct entity *get_entity_pure(struct entity_id id) { - struct entity_id pure_id; - pure_id = id; - - return get_entity(&pure_id); -} - -struct entity *get_entity(struct entity_id *ent_id) { - struct entity_id *new_id; - struct id *id = &ent_id->id; - - // rollover is ok - /* assert(->generation <= esys.generation); */ - if (id->generation != esys.generation) { - // try to find uuid in new memory layout - for (u32 i = 0; i < esys.entity_count; i++) { - new_id = &esys.ids[i]; - if (new_id->id.uuid == id->uuid) { - id->index = new_id->id.index; - id->generation = esys.generation; - return &esys.entities[id->index]; - } - } - - // entity was deleted - return NULL; - } - return &esys.entities[id->index]; -} - -static inline struct entity_id new_id() { - return (struct entity_id){ - .id = (struct id) { - .index = esys.resource_count, - .uuid = entity_uuids++, - .generation = esys.generation, - } - }; +struct entity *get_entity(entity_id_t *ent_id) { + return get_resource(&esys, ent_id); } -static inline struct entity *new_uninitialized_entity(struct entity_id *id) { - struct entity_id fresh_id; - fresh_id = new_id(); - - if (id) - *id = fresh_id; - - return &esys.entities[esys.entity_count++]; +static inline struct entity *new_uninitialized_entity(entity_id_t *id) { + return new_resource(&esys, id); } -struct entity *new_entity(struct entity_id *id) { +struct entity *new_entity(entity_id_t *id) { return init_entity(new_uninitialized_entity(id)); } -struct entity *add_entity(struct entity *e, struct entity_id *id) { +struct entity *add_entity(struct entity *e, entity_id_t *id) { struct entity *new = new_uninitialized_entity(id); *new = *e; return new; } void destroy_entities() { - for (u32 i = RESERVED_ENTITIES; i < esys.entity_count; i++) { - destroy_entity(&esys.entities[i]); + entity_id_t *ids; + u32 count; + get_all_resources(&esys, &count, &ids); + for (u32 i = RESERVED_ENTITIES; i < count; i++) { + destroy_entity(&ids[i]); } - esys.entity_count = RESERVED_ENTITIES; }; -void destroy_entity(entity_id_t id) { +void destroy_entity(entity_id_t *id) { + struct entity *ent = get_entity(id); node_detach_from_parent(&ent->node); destroy_resource(&esys, id); } @@ -98,11 +57,8 @@ void destroy_entity_system() { } void init_entity_system() { - esys.generation = 0; - esys.entities = calloc(DEF_NUM_ENTITIES, sizeof(*esys.entities)); - - esys.ids = - calloc(DEF_NUM_ENTITIES, sizeof(*esys.ids)); + init_resource_manager(&esys, sizeof(struct entity), DEF_NUM_ENTITIES, + MAX_ENTITIES); } diff --git a/src/entity.h b/src/entity.h @@ -7,6 +7,7 @@ #include "id.h" #define RESERVED_ENTITIES 2 +#define MAX_ENTITIES 2048 enum entity_flags { ENT_IS_PLAYER = 1 << 0, @@ -26,7 +27,7 @@ typedef struct resource_id entity_id_t; struct entity *init_entity(struct entity *); void destroy_entities(); -void destroy_entity(struct entity *); +void destroy_entity(entity_id_t *); void init_entity_system(); struct entity *get_entity(entity_id_t *); struct entity *get_all_entities(u32 *count, entity_id_t **ids); diff --git a/src/geometry.c b/src/geometry.c @@ -189,14 +189,14 @@ void init_geometry_manager() { geom_manager.num_geometry = 0; } -struct geometry *get_geometry(struct geometry_id geom_id) { - assert(geom_id.index != -1); - assert(geom_id.index < geom_manager.num_geometry); - return &geom_manager.geoms[geom_id.index]; +struct geometry *get_geometry(geometry_id_t *geom_id) { + assert(geom_id->index != -1); + assert(geom_id->index < geom_manager.num_geometry); + return &geom_manager.geoms[geom_id->index]; } -struct geometry *new_geometry(struct geometry_id *geom_id) { +struct geometry *new_geometry(geometry_id_t *geom_id) { u32 index = geom_manager.num_geometry++; struct geometry *g = &geom_manager.geoms[index]; init_geometry(g); diff --git a/src/node.c b/src/node.c @@ -120,6 +120,7 @@ int node_detach(struct node *node, struct node *from) { if (from->children[i] == node) { memmove(from->children[i], from->children[i+1], from->n_children - i - 1); + assert(!"fixme, this should be times the size of *children"); from->n_children--; return 1; } diff --git a/src/ply.c b/src/ply.c @@ -226,9 +226,8 @@ int parse_ply(const char *filename, geometry_id_t *geom_id) { free((void*)data); if (success) { - *geom_id = make_buffer_geometry(&mkgeom); - struct geometry *geom = - get_geometry(*geom_id); + make_buffer_geometry(&mkgeom, geom_id); + struct geometry *geom = get_geometry(geom_id); vec3_copy(min, geom->min); vec3_copy(max, geom->max); diff --git a/src/resource.c b/src/resource.c @@ -1,5 +1,13 @@ #include "resource.h" +#include <stdlib.h> +#include <string.h> + +static u64 resource_uuids = 0; + +static inline void *index_resource(struct resource_manager *r, int i) { + return &r->resources[i * r->elem_size]; +} void *get_all_resources(struct resource_manager *r, u32 *count, struct resource_id **ids) { if (count != 0) @@ -9,6 +17,86 @@ void *get_all_resources(struct resource_manager *r, u32 *count, struct resource_ return r->resources; } -void destroy_resource(struct resource_manager *r) { - +void init_resource_manager(struct resource_manager *r, u32 elem_size, + u32 initial_elements, u32 max_elements) { + r->generation = 1; + r->resource_count = 0; + r->elem_size = elem_size; + r->max_elements = max_elements; + + r->resources = calloc(initial_elements, elem_size); + r->ids = calloc(initial_elements, sizeof(*r->ids)); +} + +void destroy_resource_manager(struct resource_manager *r) { + free(r->ids); + free(r->resources); +} + +static int refresh_id(struct resource_manager *r, struct resource_id *id, + struct resource_id *new) +{ + // rollover is ok + /* assert(->generation <= esys.generation); */ + if (id->generation != r->generation) { + // try to find uuid in new memory layout + for (u32 i = 0; i < r->resource_count; i++) { + struct resource_id *new_id = &r->ids[i]; + if (new_id->uuid == id->uuid) { + new->index = new_id->index; + new->generation = r->generation; + return 1; + } + } + + // entity was deleted + return 0; + } + + // doesn't need refreshed + return 2; +} + +int is_resource_destroyed(struct resource_id *id) { + return id->generation == 0; +} + +void destroy_resource(struct resource_manager *r, struct resource_id *id) { + if (is_resource_destroyed(id)) + return; + + int res = refresh_id(r, id, id); + // entity already deleted + if (res == 0) { + id->generation = 0; + return; + } + // generation 0 means destroyed + id->generation = 0; + + memmove(index_resource(r, id->index), + index_resource(r, id->index+1), r->resource_count -) +} + +struct resource_id new_id(struct resource_manager *r) { + return (struct resource_id){ + .index = r->resource_count, + .uuid = resource_uuids++, + .generation = r->generation, + }; +} + +void *new_resource(struct resource_manager *r, struct resource_id *id) { + struct resource_id fresh_id = new_id(r); + + if (id) + *id = fresh_id; + + return index_resource(r, r->resource_count++); +} + +void *get_resource(struct resource_manager *r, struct resource_id *id) { + refresh_id(r, id, id); + + return index_resource(r, id->index); } diff --git a/src/resource.h b/src/resource.h @@ -11,14 +11,22 @@ struct resource_id { }; struct resource_manager { - void *resources; + u8 *resources; struct resource_id *ids; u32 resource_count; u32 generation; + u32 elem_size; + u32 max_elements; }; +void *get_resource(struct resource_manager *r, struct resource_id *id); void *get_all_resources(struct resource_manager *, u32 *count, struct resource_id **ids); -void destroy_resource(struct resource_manager *); +void destroy_resource(struct resource_manager *, struct resource_id *id); void destroy_resource_manager(struct resource_manager *); +struct resource_id new_id(struct resource_manager *); +void *new_resource(struct resource_manager *, struct resource_id *id); + +void init_resource_manager(struct resource_manager *r, u32 elem_size, + u32 initial_elements, u32 max_elements); #endif /* RESOURCE_H */ diff --git a/src/skybox.c b/src/skybox.c @@ -54,8 +54,7 @@ void create_skybox(struct skybox *skybox, struct gpu_program *program) { mkgeom.num_verts = ARRAY_SIZE(skybox_vertices); mkgeom.num_indices = ARRAY_SIZE(skybox_indices); - skybox->model.geom_id = - make_buffer_geometry(&mkgeom); + make_buffer_geometry(&mkgeom, &skybox->model.geom_id); static const char *faces[6] = { CUBEMAP("hw_sahara/sahara_rt_flip.tga"), @@ -112,7 +111,7 @@ void render_skybox(struct skybox *skybox, mat4 *camera) { glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->model.texture); check_gl(); - render_geometry(get_geometry(skybox->model.geom_id), &skybox->attrs, skybox->program); + render_geometry(get_geometry(&skybox->model.geom_id), &skybox->attrs, skybox->program); check_gl(); glDepthMask(GL_TRUE); diff --git a/src/terrain.c b/src/terrain.c @@ -230,5 +230,5 @@ void create_terrain(struct terrain *terrain, float scale) { void destroy_terrain(struct terrain *terrain) { struct entity *ent = get_entity(&terrain->entity_id); assert(ent); - destroy_buffer_geometry(get_geometry(terrain->model.geom_id)); + destroy_buffer_geometry(&terrain->model.geom_id); } diff --git a/src/ui.c b/src/ui.c @@ -34,7 +34,7 @@ static GLfloat quad_uvs[] = }; -static geometry_id_t create_quad() +static void create_quad(geometry_id_t *id) { struct make_geometry mkgeom = { .indices = quad_indices, @@ -45,10 +45,8 @@ static geometry_id_t create_quad() .num_verts = ARRAY_SIZE(quad_vertices), .num_uv_components = 2 }; - geometry_id_t id = make_buffer_geometry(&mkgeom); + make_buffer_geometry(&mkgeom, id); check_gl(); - - return id; } void render_ui(struct ui *ui, float *view) {