polyadvent

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

commit 4ab2c240025aef85491b3f4d7a2864ce32db9d10
parent cca2a76abe04ffd902c46d000ffc2b087e5285f7
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 30 Jun 2019 19:51:25 -0700

dyn model wip

Diffstat:
MMakefile | 1+
MTODOs.org | 10++++------
Msrc/entity.h | 2+-
Msrc/game.c | 55+++++++++----------------------------------------------
Msrc/model.c | 47+++++++++++++++++++++++++++++++++++++++++++----
Msrc/model.h | 26+++++++++++++++++++++-----
Asrc/procmesh.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/procmesh.h | 9+++++++++
Msrc/render.c | 6++++--
Msrc/scene.c | 2+-
Msrc/terrain.c | 9+++++----
Msrc/terrain.h | 2+-
Msrc/update.c | 11++++++++---
13 files changed, 160 insertions(+), 73 deletions(-)

diff --git a/Makefile b/Makefile @@ -49,6 +49,7 @@ OBJS += $(SRC)/vec3.o OBJS += $(SRC)/scene.o OBJS += $(SRC)/resource.o OBJS += $(SRC)/quickhull.o +OBJS += $(SRC)/procmesh.o TESTS = test/test_animation TESTS += test/test_resource diff --git a/TODOs.org b/TODOs.org @@ -18,15 +18,12 @@ CLOSED: [2019-06-22 Sat 12:52] ** DONE Load poses in engine CLOSED: [2019-06-22 Sat 12:52] -** TODO factor node properties - -perhaps there's a more minimal subset of node that would be useful to -both joints and entities? - -** TODO use nodes for joints +** DONE use nodes for joints +CLOSED: [2019-06-30 Sun 17:26] It will just be easier for interpolation + ** TODO Load bone weights ** TODO Run pose ** TODO Simple animation test @@ -40,6 +37,7 @@ It will just be easier for interpolation ** TODO Entity loading stress test + * Procedural ** TODO Trees diff --git a/src/entity.h b/src/entity.h @@ -16,7 +16,7 @@ enum entity_flags { struct entity { node_id node_id; - struct model *model; + model_id model_id; u32 flags; float velocity[3]; float accel[3]; diff --git a/src/game.c b/src/game.c @@ -12,6 +12,7 @@ #include "stb_image.h" #include "skybox.h" #include "quickhull.h" +#include "procmesh.h" #include "util.h" #include <assert.h> @@ -54,51 +55,6 @@ static void init_user_settings(struct user_settings *settings) { } -static void qh_mesh_to_geom(qh_mesh_t *qh, struct make_geometry *geom) { - assert(!geom->vertices); - assert(!geom->indices); - float *new_normals = malloc(sizeof(float) * 3 * qh->nvertices); - - geom->vertices = (float*)qh->vertices; - geom->normals = (float*)qh->normals; - geom->indices = qh->indices; - geom->num_verts = qh->nvertices; - geom->num_indices = qh->nindices; - - for (u32 i = 0; i < qh->nnormals; i++) { - int ndv = i * 9; - - qh_vertex_t *n = &qh->normals[i]; - for (int j = 0; j < 9; j++) { - new_normals[ndv+j] = n->v[j%3]; - } - } - - geom->normals = new_normals; -} - - -void proc_sphere(struct make_geometry *mkgeom, geometry_id *geom_id) { - const int n = 50; - qh_vertex_t *vertices = malloc(n*sizeof(qh_vertex_t)); - const float radius = 2.0; - - - for (int i = 0; i < n; ++i) { - float a0 = (rand_0to1() * TAU); - float a1 = (rand_0to1() * TAU); - vertices[i].z = sin(a0) * radius; - vertices[i].x = cos(a1) * cos(a0) * rand_0to1() * radius; - vertices[i].y = sin(a1) * cos(a0) * rand_0to1() * radius; - } - - qh_mesh_t mesh = qh_quickhull3d(vertices, n); - qh_mesh_to_geom(&mesh, mkgeom); - make_buffer_geometry(mkgeom, geom_id); - - qh_free_mesh(mesh); -} - void game_init(struct game *game, int width, int height) { init_gl(&game->test_resources, width, height); @@ -190,7 +146,14 @@ void game_init(struct game *game, int width, int height) { struct node *pnode = get_node(&player->node_id); assert(pnode); assert(res->player_id.index == 1); - player->model = get_model(model_pirate_officer); + /* player->model_id = get_static_model(model_pirate_officer, NULL); */ + + struct model *pmodel = new_model(&player->model_id); assert(pmodel); + + proc_sphere(geom); + + ok = load_model(&player->model, "pirate-officer"); + assert(ok); node_set_label(pnode, "player"); node_attach(&player->node_id, &res->root_id); diff --git a/src/model.c b/src/model.c @@ -32,22 +32,47 @@ static void initialize_static_models() { static_models_initialized = 1; } -static inline struct model *new_uninitialized_model(model_id *id) { +static inline struct model *new_uninitialized_model(struct resource_id *id) { return new_resource(&dyn_modelman, id); } +static struct model *new_model_resource(model_id *model_id) +{ + struct model *model = new_uninitialized_model(&model_id->dyn_model_id); + new_geometry(&model->geom_id); + return model; +} + void init_model_manager() { init_resource_manager(&dyn_modelman, sizeof(struct model), DEF_DYNAMIC_MODELS, MAX_DYNAMIC_MODELS); } -struct model *new_dynamic_model(model_id *id) +struct model *new_model(model_id *id) +{ + id->type = DYNAMIC_MODEL; + return new_model_resource(id); +} + +struct model *get_model(model_id *model_id) { - return init_model(new_uninitialized_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"); } -struct model *get_model(enum static_model m) { + +static struct model *load_static_model(enum static_model m) +{ static char path[128] = {0}; if (!static_models_initialized) @@ -68,3 +93,17 @@ struct model *get_model(enum static_model m) { return model; } + +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; +} + + diff --git a/src/model.h b/src/model.h @@ -12,8 +12,6 @@ #define MAX_STATIC_MODELS 128 #define MAX_DYNAMIC_MODELS 2048 -typedef struct resource_id model_id; - enum static_model { model_tower, model_icosphere, @@ -21,6 +19,21 @@ 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, @@ -28,7 +41,8 @@ enum shading { }; struct model { - geometry_id geom_id; + /* geometry_id geom_id; */ + struct geometry geom; enum shading shading; u32 texture; }; @@ -43,8 +57,10 @@ struct model_def { void init_model_manager(); struct model *init_model(struct model *model); -struct model *get_model(enum static_model); +struct model *get_model(model_id *); +struct model *new_model(model_id *); +struct model *new_static_model(model_id *); -struct model *new_dynamic_model(model_id *); +model_id get_static_model(enum static_model, struct model**); #endif /* MODEL_H */ diff --git a/src/procmesh.c b/src/procmesh.c @@ -0,0 +1,53 @@ + +#include "quickhull.h" +#include "geometry.h" +#include "util.h" + + +static void qh_mesh_to_geom(qh_mesh_t *qh, struct make_geometry *geom) { + assert(!geom->vertices); + assert(!geom->indices); + float *new_normals = malloc(sizeof(float) * 3 * qh->nvertices); + + geom->vertices = (float*)qh->vertices; + geom->normals = (float*)qh->normals; + geom->indices = qh->indices; + geom->num_verts = qh->nvertices; + geom->num_indices = qh->nindices; + + for (u32 i = 0; i < qh->nnormals; i++) { + int ndv = i * 9; + + qh_vertex_t *n = &qh->normals[i]; + for (int j = 0; j < 9; j++) { + new_normals[ndv+j] = n->v[j%3]; + } + } + + geom->normals = new_normals; +} + + +void proc_sphere(geometry_id *geom_id) { + struct make_geometry mkgeom; + const int n = 50; + qh_vertex_t *vertices = malloc(n*sizeof(qh_vertex_t)); + const float radius = 2.0; + + + for (int i = 0; i < n; ++i) { + float a0 = (rand_0to1() * TAU); + float a1 = (rand_0to1() * TAU); + vertices[i].z = sin(a0) * radius; + vertices[i].x = cos(a1) * cos(a0) * rand_0to1() * radius; + vertices[i].y = sin(a1) * cos(a0) * rand_0to1() * radius; + } + + qh_mesh_t mesh = qh_quickhull3d(vertices, n); + qh_mesh_to_geom(&mesh, &mkgeom); + make_buffer_geometry(&mkgeom, geom_id); + + free(mkgeom.normals); + qh_free_mesh(mesh); +} + diff --git a/src/procmesh.h b/src/procmesh.h @@ -0,0 +1,9 @@ + +#ifndef PROCMESH_H +#define PROCMESH_H + +#include "geometry.h" + +void proc_sphere(struct make_geometry *mkgeom, geometry_id *geom_id); + +#endif /* PROCMESH_H */ diff --git a/src/render.c b/src/render.c @@ -354,8 +354,10 @@ void render (struct game *game, struct render_config *config) { recalc_normals(res->uniforms.normal_matrix, model_view, normal_matrix); check_gl(); - - struct geometry *geo = get_geometry(&entity->model->geom_id); + struct model *model = get_model(&entity->model_id); + assert(model); + struct geometry *geo = get_geometry(&model->geom_id); + assert(geo); render_geometry(geo, res->vertex_attrs, current_program); check_gl(); } diff --git a/src/scene.c b/src/scene.c @@ -30,7 +30,7 @@ void default_scene(struct game *game) { struct node *pnode = get_node(&player->node_id); assert(tnode); - tower->model = get_model(model_tower); + tower->model_id = get_static_model_id(model_tower); node_set_label(tnode, "tower"); node_attach(&tower->node_id, &player->node_id); node_translate(tnode, V3(0.0, 50.0, 0.0)); diff --git a/src/terrain.c b/src/terrain.c @@ -53,14 +53,15 @@ void reset_terrain(struct terrain *terrain, float size) { void init_terrain(struct terrain *terrain, float size) { init_id(&terrain->entity_id); - struct entity *ent = new_entity(&terrain->entity_id); - struct node *node = get_node(&ent->node_id); + struct entity *ent = new_entity(&terrain->entity_id); assert(ent); + struct node *node = get_node(&ent->node_id); assert(node); + struct model *model = get_model(&terrain->model_id); assert(model); assert(node); assert(terrain->entity_id.index == 0); - terrain->model.shading = SHADING_TERRAIN; - ent->model = &terrain->model; + model->shading = SHADING_TERRAIN; + ent->model_id = terrain->model_id; node_set_label(node, "terrain"); ent->casts_shadows = 0; diff --git a/src/terrain.h b/src/terrain.h @@ -24,7 +24,7 @@ struct terrain { entity_id entity_id; struct perlin_settings settings; struct point *samples; - struct model model; + model_id model_id; double (*fn)(struct terrain *, double, double); int n_samples; double size; diff --git a/src/update.c b/src/update.c @@ -187,7 +187,8 @@ static int try_reload_shaders(struct resources *res) { #endif void resize_fbos(struct entity *player, struct fbo *shadow_buffer, - float *m4_ortho, int width, int height) { + float *m4_ortho, int width, int height) +{ if (shadow_buffer->handle) { // TODO: remove once delete_fbo deletes attachments glDeleteTextures(1, &shadow_buffer->attachments[1]); @@ -197,7 +198,10 @@ void resize_fbos(struct entity *player, struct fbo *shadow_buffer, // TODO: compute better bounds based const float factor = 4.5; - struct geometry *geom = get_geometry(&player->model->geom_id); + + struct model *model = get_model(&player->model_id); assert(model); + struct geometry *geom = get_geometry(&model->geom_id); assert(geom); + float left = geom->min[0] - factor; float right = geom->max[0] + factor; float bottom = geom->min[1] - factor; @@ -292,7 +296,8 @@ void orbit_update_from_mouse(struct orbit *camera, struct input *input, float target[3]; struct node *target_node = get_node(&player->node_id); struct node *cam_node = get_node(&camera->node_id); - struct geometry *player_geom = get_geometry(&player->model->geom_id); + struct model *pmodel = get_model(&player->model_id); assert(pmodel); + struct geometry *player_geom = get_geometry(model->geom_id); assert(target_node); assert(cam_node);