polyadvent

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

commit a1efa0bf5f3b85e04c5819a8ec54cc8722a7e659
parent 640f12d0e6bc5ed7944d999ce5c1c131d22eb63a
Author: William Casarin <jb55@jb55.com>
Date:   Fri,  5 Jul 2019 10:40:00 -0700

wip: static resources

Diffstat:
Msrc/common.h | 1+
Msrc/entity.c | 2+-
Msrc/geometry.c | 3+--
Msrc/model.c | 35+++++++----------------------------
Msrc/model.h | 17++---------------
Msrc/node.c | 8+++++++-
Msrc/node.h | 1+
Msrc/resource.c | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/resource.h | 38++++++++++++++++++++++++++++++++++++--
Msrc/scene.c | 2+-
Msrc/skybox.c | 2+-
Mtodo.org | 10++++++++--
12 files changed, 143 insertions(+), 68 deletions(-)

diff --git a/src/common.h b/src/common.h @@ -8,6 +8,7 @@ typedef int bool; #define MAT3_ELEMS 9 #define MAT4_ELEMS 16 +#define U64HOB 0x8000000000000000 #define SLAB(f) "etc/slab/" f #define RESOURCE(f) "etc/shaders/" f diff --git a/src/entity.c b/src/entity.c @@ -21,7 +21,7 @@ struct entity *get_all_entities(u32 *count, entity_id **ids) { struct entity *init_entity(struct entity *ent, node_id *id) { node_id new_id; - init_model_id(&ent->model_id); + init_id(&ent->model_id); if (id == NULL) { init_id(&new_id); new_node(&new_id); diff --git a/src/geometry.c b/src/geometry.c @@ -5,7 +5,6 @@ #include "debug.h" #include <assert.h> - static struct resource_manager geom_manager; void @@ -174,7 +173,7 @@ void geometry_centroid(struct geometry *geom, float *dest) { void init_geometry_manager() { init_resource_manager(&geom_manager, sizeof(struct geometry), - DEF_NUM_GEOMETRY, MAX_GEOMETRY, "geometry"); + DEF_NUM_GEOMETRY, MAX_GEOMETRY, "geometry", NULL); } struct geometry *get_geometry(geometry_id *geom_id) { diff --git a/src/model.c b/src/model.c @@ -17,13 +17,6 @@ static struct resource_manager dyn_modelman; static int static_models_initialized = 0; -void init_model_id(model_id *id) -{ - /* assert((int)id->dyn_model_id.index != -1); */ - id->type = DYNAMIC_MODEL; - init_id(&id->dyn_model_id); -} - struct model *init_model(struct model *model) { init_id(&model->geom_id); model->shading = SHADING_VERT_COLOR; @@ -46,7 +39,7 @@ static inline struct model *new_uninitialized_model(struct resource_id *id) { static struct model *new_model_resource(model_id *model_id) { - struct model *model = new_uninitialized_model(&model_id->dyn_model_id); + struct model *model = new_uninitialized_model(model_id); /* debug("new model %llu\n", model_id->dyn_model_id.uuid); */ init_id(&model->geom_id); new_geometry(&model->geom_id); @@ -61,23 +54,13 @@ void init_model_manager() { struct model *new_model(model_id *id) { - id->type = DYNAMIC_MODEL; return new_model_resource(id); } + struct model *get_model(model_id *model_id) { - - switch(model_id->type) { - case DYNAMIC_MODEL: - return get_resource(&dyn_modelman, &model_id->dyn_model_id); - case STATIC_MODEL: { - struct model *model; - get_static_model(model_id->static_model_id, &model); - return model; - } - } - assert(!"unhandled case in get_model"); + return get_resource(&dyn_modelman, model_id); } @@ -106,26 +89,22 @@ static struct model *load_static_model(enum static_model m) void destroy_model(model_id *model_id) { - if (model_id->type == STATIC_MODEL) + if (is_static_resource(model_id)) return; - struct resource_id *id = &model_id->dyn_model_id; struct model *model = get_model(model_id); destroy_geometry(&model->geom_id); - destroy_resource(&dyn_modelman, id); + destroy_resource(&dyn_modelman, model_id); } + model_id get_static_model(enum static_model m, struct model **model) { - model_id model_id; - model_id.type = STATIC_MODEL; - model_id.static_model_id = m; - if (model) *model = load_static_model(m); - return model_id; + return make_static_id(m); } diff --git a/src/model.h b/src/model.h @@ -12,6 +12,8 @@ #define MAX_STATIC_MODELS 128 #define MAX_DYNAMIC_MODELS 2048 +typedef struct resource_id model_id; + enum static_model { model_tower, model_icosphere, @@ -19,21 +21,6 @@ enum static_model { NUM_STATIC_MODELS }; -enum model_type { - STATIC_MODEL, - DYNAMIC_MODEL -}; - -typedef struct model_id_t -{ - enum model_type type; - union { - struct resource_id dyn_model_id; - enum static_model static_model_id; - }; -} model_id; - - enum shading { SHADING_TERRAIN, SHADING_VERT_COLOR, diff --git a/src/node.c b/src/node.c @@ -40,7 +40,13 @@ void destroy_node(node_id *id) void init_node_manager() { - init_resource_manager(&node_manager, sizeof(struct node), 128, 0xFFFF, "node"); + struct static_resources nodes = { + .count = 0, + .capacity = N_STATIC_NODES, + }; + + init_resource_manager(&node_manager, sizeof(struct node), 128, + 0xFFFF, "node", &nodes); } struct node *node_init(struct node *node) { diff --git a/src/node.h b/src/node.h @@ -5,6 +5,7 @@ #include "resource.h" #define MAX_NODE_CHILDREN 4 +#define N_STATIC_NODES 32 enum node_flags { NODE_IGNORE_RECALC = 1 << 0 diff --git a/src/resource.c b/src/resource.c @@ -9,10 +9,21 @@ static u64 resource_uuids = 0; -static inline void *index_resource(struct resource_manager *r, int i) { - unsigned char *p = r->resources; - assert(p); - return p + (i * r->elem_size); +static inline void *index_resource_(u8 *res, u32 elem_size, int i) +{ + assert(res); + return res + (i * elem_size); +} + +static inline void *index_resource(struct resource_manager *r, int i) +{ + return index_resource_(r->resources, r->elem_size, i); +} + + +static inline void *index_static_resource(struct resource_manager *r, int i) +{ + return index_resource_(r->static_res.resources, r->elem_size, i); } void *get_all_resources(struct resource_manager *r, u32 *count, struct resource_id **ids) { @@ -39,7 +50,10 @@ void null_id(struct resource_id *id) } void init_resource_manager(struct resource_manager *r, u32 elem_size, - u32 initial_elements, u32 max_elements, const char *name) { + u32 initial_elements, u32 max_elements, + const char *name, + struct static_resources *static_res) +{ r->generation = 1; r->resource_count = 0; r->elem_size = elem_size; @@ -47,6 +61,20 @@ void init_resource_manager(struct resource_manager *r, u32 elem_size, r->current_capacity = initial_elements; r->name = name; + if (static_res) { + r->static_res = *static_res; + + if (r->static_res.resources == NULL) { + r->static_res.resources = + calloc(r->static_res.capacity, elem_size); + } + } + else { + r->static_res.count = 0; + r->static_res.capacity = 0; + r->static_res.resources = NULL; + } + assert(initial_elements != 0); r->resources = calloc(initial_elements, elem_size); @@ -97,6 +125,13 @@ static void new_id(struct resource_manager *r, struct resource_id *id) assert(id->generation); } +static void new_static_id(struct resource_manager *r, struct resource_id *id) +{ + id->index = r->static_res.count; + id->uuid = STATIC_UUID; + id->generation = 0xFFFFFFFF; +} + static void resize(struct resource_manager *r) { debug("resizing %s resources, count %d+1 > current capacity %d\n", @@ -129,14 +164,37 @@ static void resize(struct resource_manager *r) void print_id(struct resource_id *id, int nl) { + int is_static = is_static_resource(id); + + if (is_static) { + printf("sid(%llu @ %d)%s", id->uuid & ~U64HOB, id->index, nl?"\n":""); + return; + } + printf("id(u:%llu i:%d g:%d)%s", id->uuid, id->index, id->generation, nl?"\n":""); } +void *new_static_resource(struct resource_manager *r, + struct resource_id *id) +{ + assert(r->static_res.resources); + assert(id); + assert(id->index == 0xFFFFFFFF && "res_id is uninitialized"); + assert(r->static_res.count + 1 < r->static_res.capacity); + if (r->static_res.count + 1 < r->static_res.capacity) + return NULL; // we're full + + new_static_id(r, id); + + return index_static_resource(r, r->static_res.count++); +} + void *new_resource(struct resource_manager *r, struct resource_id *id) { assert(id); - assert((int)id->index == -1 && "res_id is uninitialized"); + assert(id->uuid != STATIC_UUID && "called new_resource with a static id"); + assert(id->index == 0xFFFFFFFF && "res_id is uninitialized"); struct resource_id *fresh_id; @@ -147,16 +205,25 @@ void *new_resource(struct resource_manager *r, struct resource_id *id) resize(r); fresh_id = &r->ids[r->resource_count]; - new_id(r, fresh_id); - - if (id) - *id = *fresh_id; + *id = *fresh_id; return index_resource(r, r->resource_count++); } +void *get_static_resource(struct resource_manager *r, + struct resource_id *id) +{ + assert(r->static_res.capacity > 0 && "trying to get a static " + "resource on a manager doesn't have static resources"); + + return index_static_resource(r, id->index); +} + void *get_resource(struct resource_manager *r, struct resource_id *id) { + if (id->uuid == STATIC_UUID) + return get_static_resource(r, id); + assert((int64_t)id->generation != -1 && "id intialized but not allocated (needs new_ call)"); if (id->generation == 0) { @@ -214,8 +281,3 @@ void destroy_resource(struct resource_manager *r, struct resource_id *id) { r->ids[i].index--; } } - -int is_id_allocated(struct resource_id *id) -{ - return (int)id->index != -1; -} diff --git a/src/resource.h b/src/resource.h @@ -4,6 +4,8 @@ #include "common.h" +#define STATIC_UUID 0x5A51C00000000000 + enum refresh_status { RESOURCE_DELETED, REFRESH_NOT_NEEDED, @@ -16,8 +18,15 @@ struct resource_id { u32 generation; }; +struct static_resources { + u8 *resources; + u32 count; + u32 capacity; +}; + struct resource_manager { u8 *resources; + struct static_resources static_res; struct resource_id *ids; u32 resource_count; u32 generation; @@ -25,22 +34,47 @@ struct resource_manager { u32 slots_used; u32 max_capacity; u32 current_capacity; + const char *name; }; #define ideq(a, b) ((a)->uuid == (b)->uuid) -int is_id_allocated(struct resource_id *id); void init_id(struct resource_id *id); 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 *, struct resource_id *id); void destroy_resource_manager(struct resource_manager *); void *new_resource(struct resource_manager *, struct resource_id *id); +void *new_static_resource(struct resource_manager *, struct resource_id *id); void print_id(struct resource_id *, int nl); void null_id(struct resource_id *id); +/* int is_static_resource(struct resource_id *id); */ void init_resource_manager(struct resource_manager *r, u32 elem_size, - u32 initial_elements, u32 max_elements, const char *name); + u32 initial_elements, u32 max_elements, const char *name, + struct static_resources *static_res + ); + + +static inline struct resource_id make_static_id(u32 index) +{ + return (struct resource_id){ + .uuid = STATIC_UUID, + .index = index, + .generation = -1 + }; +} + +static inline int is_static_resource(struct resource_id *id) +{ + return id->uuid == STATIC_UUID; +} + + +static inline int is_id_allocated(struct resource_id *id) +{ + return (int)id->index != -1; +} #endif /* RESOURCE_H */ diff --git a/src/scene.c b/src/scene.c @@ -55,7 +55,7 @@ void entity_test_scene(struct game *game) player->model_id = get_static_model(model_pirate_officer, NULL); model_id rock_model; - init_model_id(&rock_model); + init_id(&rock_model); /* model_id rock_model = get_static_model(model_tower, NULL); */ struct model *pmodel = new_model(&rock_model); assert(pmodel); diff --git a/src/skybox.c b/src/skybox.c @@ -39,7 +39,7 @@ void create_skybox(struct skybox *skybox, struct gpu_program *program) { int ok; node_init(&skybox->node); - init_model_id(&skybox->model_id); + init_id(&skybox->model_id); skybox->program = program; diff --git a/todo.org b/todo.org @@ -3,11 +3,17 @@ * TODO Proc Trees :procgen: * TODO [#A] Instance rendering for ground debris :perf:rendering: * TODO [#B] Load bone weights :anim: +:LOGBOOK: +CLOCK: [2019-07-05 Fri 09:28] +:END: * TODO Simple pthreads job system :jobs:threads: -* TODO Run pose :anim: -* TODO Simple animation test :anim: +* Run pose :anim: +:LOGBOOK: +CLOCK: [2019-07-05 Fri 09:28]--[2019-07-05 Fri 09:28] => 0:00 +:END: + * TODO Initial physics system :physics: * TODO Entity loading stress test :perf: