polyadvent

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

commit 33051a9b86fb62ab292f5dff5cce17c5268dea9c
parent 089461edd69dcef733ef1c09c9c14a339bbff5a2
Author: William Casarin <jb55@jb55.com>
Date:   Fri,  5 Jul 2019 16:45:53 -0700

I dont care anymore

Diffstat:
Msrc/animation.c | 63++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/animation.h | 2++
Msrc/game.c | 9+++++----
Msrc/geometry.c | 7++++++-
Msrc/geometry.h | 8++++++++
Msrc/input.c | 6+++---
Msrc/main.c | 4++--
Msrc/model.c | 15+++++++++++++--
Msrc/node.c | 3+++
Msrc/ply.c | 3+--
Msrc/ply.h | 2+-
Msrc/render.c | 12++++++++++++
Msrc/resource.c | 2++
Msrc/resource.h | 5-----
Msrc/scene.c | 6+++++-
Msrc/util.h | 1+
Mtest/test_animation.c | 9++++++++-
Mtest/test_resource.c | 33+++++++++++++++++++++++++++++++++
Mtest/test_scene.c | 6+++---
Mtodo.org | 2+-
20 files changed, 165 insertions(+), 33 deletions(-)

diff --git a/src/animation.c b/src/animation.c @@ -3,14 +3,17 @@ #include "xml.h" #include "util.h" #include "node.h" +#include "debug.h" #include "animation.h" enum dae_state { PARSING_START, PARSING_NODE, + PARSING_FLOAT_ARRAY, PARSING_POSE, PARSING_JOINT, PARSING_JOINT_MATRIX, + PARSING_WEIGHTS, }; struct dae_data { @@ -19,6 +22,8 @@ struct dae_data { FILE *dae_file; struct pose *poses; int *nposes; + float *weights; + int nweights; char current_name[JOINT_LABEL_SIZE]; }; @@ -68,10 +73,16 @@ static void dae_tag_start(struct xmlparser *x, const char *t, size_t tl) { struct dae_data *data = (struct dae_data*)x->user_data; + debug("state %d tag_start %.*s\n", data->state, (int)tl, t); + if (streq(t, "node")) { data->state = PARSING_NODE; data->node_level++; } + else if (streq(t, "float_array")) { + debug("-> PARSING_FLOAT_ARRAY\n"); + data->state = PARSING_FLOAT_ARRAY; + } else if (data->state == PARSING_JOINT && streq(t, "matrix")) data->state = PARSING_JOINT_MATRIX; else @@ -100,11 +111,12 @@ static void dae_tagbody(struct xmlparser *x, const char *d, size_t dl) { static int count = 0; struct dae_data *data = (struct dae_data*)x->user_data; + struct pose *pose; if (data->state == PARSING_JOINT_MATRIX) { assert(*data->nposes); - struct pose *pose = &data->poses[*data->nposes - 1]; + pose = &data->poses[*data->nposes - 1]; assert(pose); struct joint *joint = &pose->joints[pose->njoints]; @@ -122,6 +134,32 @@ static void dae_tagbody(struct xmlparser *x, const char *d, size_t dl) pose->njoints++; data->state = PARSING_POSE; } + else if (data->state == PARSING_WEIGHTS) { + pose = &data->poses[*data->nposes]; + assert(data->nweights > 0); + data->weights = calloc(data->nweights, sizeof(float)); + + const char *p = d; + float val; + int i; + + for (i = 0; i < data->nweights; i++) { + sscanf(p, "%f", &val); + data->weights[i] = val; + + while (p < d+dl) { + if (*(p++) == ' ') + break; + } + } + + assert(data->nweights == i); + + pose->nweights = data->nweights; + pose->weights = data->weights; + + data->state = PARSING_POSE; + } } static int dae_getc(struct xmlparser *x) @@ -137,21 +175,30 @@ void dae_attr(struct xmlparser *x, const char *t, size_t tl, if (data->state == PARSING_NODE && streq(a, "id") - && streq(v, "Armature")) - { + && streq(v, "Armature")) { + struct pose *pose = &data->poses[(*data->nposes)++]; data->state = PARSING_POSE; init_pose(pose); } + else if (data->state == PARSING_FLOAT_ARRAY + && streq(a, "id") + && contains(v, "skin-weights-array")) { + debug("PARSING_SOURCE -> PARSING_WEIGHTS_START\n"); + data->state = PARSING_WEIGHTS; + } + else if (data->state == PARSING_WEIGHTS + && streq(a, "count")) { + data->nweights = atoi(v); + } else if (data->state == PARSING_NODE - && streq(a, "name")) - { + && streq(a, "name")) { strncpy(data->current_name, v, sizeof(data->current_name)); } else if (data->state == PARSING_NODE && streq(a, "type") - && streq(v, "JOINT")) - { + && streq(v, "JOINT")) { + data->state = PARSING_JOINT; } } @@ -190,6 +237,8 @@ void load_poses(const char *filename, struct pose *poses, int *nposes) .state = PARSING_START, .poses = poses, .nposes = nposes, + .nweights = -1, + .weights = NULL }; data.dae_file = fopen("data/models/pirate-officer.dae", "rb"); diff --git a/src/animation.h b/src/animation.h @@ -21,6 +21,8 @@ struct joint struct pose { struct joint joints[MAX_JOINTS]; + float *weights; + int nweights; int njoints; }; diff --git a/src/game.c b/src/game.c @@ -86,9 +86,9 @@ void game_init(struct game *game, int width, int height) { init_sdl(&game->window, width, height); init_gl(&game->test_resources, width, height); init_entity_system(); + init_geometry_manager(); init_model_manager(); init_node_manager(); - init_geometry_manager(); init_user_settings(&game->user_settings); check_gl(); @@ -175,13 +175,14 @@ void game_init(struct game *game, int width, int height) { player = &static_entities()[entity_player]; struct node *pnode = &static_nodes()[node_player]; assert(pnode); + res->player_id = make_static_id(entity_player); assert(res->player_id.index == entity_player); /* player->model_id = get_static_model(model_pirate_officer, NULL); */ - struct model *pmodel = new_model(&player->model_id); assert(pmodel); - struct geometry *geom = get_geometry(&pmodel->geom_id); assert(geom); + struct model *pmodel; + player->model_id = get_static_model(model_pirate_officer, &pmodel); + print_id(&player->model_id, true); - proc_sphere(geom); pmodel->shading = SHADING_VERT_COLOR; node_set_label(pnode, "player"); diff --git a/src/geometry.c b/src/geometry.c @@ -6,7 +6,7 @@ #include "static_resources.h" #include <assert.h> -static struct resource_manager geom_manager; +struct resource_manager geom_manager; void destroy_buffer_geometry(geometry_id *geom_id) { @@ -172,10 +172,15 @@ void geometry_centroid(struct geometry *geom, float *dest) { vec3_scale(dest, 0.5, dest); }; + void init_geometry_manager() { init_resource_manager(&geom_manager, sizeof(struct geometry), DEF_NUM_GEOMETRY, MAX_GEOMETRY, "geometry", NUM_STATIC_MODELS); + + for (int i = 0; i < NUM_STATIC_MODELS; i++) { + init_geometry(&static_geometry()[i]); + } } struct geometry *get_geometry(geometry_id *geom_id) { diff --git a/src/geometry.h b/src/geometry.h @@ -59,5 +59,13 @@ struct geometry *new_geometry(geometry_id *); struct geometry *get_geometry(geometry_id *); struct geometry *get_all_geometry(u32 *count, geometry_id **ids); void destroy_geometry(geometry_id *geom_id); +struct resource_manager *get_geometry_manager(); + +extern struct resource_manager geom_manager; + +static inline struct geometry *static_geometry() +{ + return (struct geometry *)geom_manager.resources; +} #endif /* GEOMETRY_H */ diff --git a/src/input.c b/src/input.c @@ -82,9 +82,9 @@ void process_events(struct input *input, u64 current_frame) { } - if (input->resized_width) - printf("checking resize %d %d\n", input->resized_width, - input->resized_height); + /* if (input->resized_width) */ + /* printf("checking resize %d %d\n", input->resized_width, */ + /* input->resized_height); */ } diff --git a/src/main.c b/src/main.c @@ -68,8 +68,8 @@ int main(void) game.frame++; process_events(&game.input, game.frame); if (game.input.resized_height) { - printf("handling resize %d %d\n", game.input.resized_width, - game.input.resized_height); + /* printf("handling resize %d %d\n", game.input.resized_width, */ + /* game.input.resized_height); */ handle_resize(&game, game.input.resized_width, game.input.resized_height); } //default_config.camera = game.test_resources.camera_node->mat; diff --git a/src/model.c b/src/model.c @@ -76,15 +76,26 @@ static struct model *load_static_model(enum static_model m) static char path[128] = {0}; struct model *model = &static_models()[m]; + struct geometry *geom = &static_geometry()[m]; + init_geometry(geom); + model->geom_id = make_static_id(m); - if (is_id_allocated(&model->geom_id) && get_geometry(&model->geom_id)) + if (get_geometry(&model->geom_id)->has_vbos) { + debug("model %s already loaded\n", static_model_defs[m].file); return model; + } int ok = 0; // Load mesh + debug("loading %s model with geom_id ", static_model_defs[m].file); + + print_id(&model->geom_id, true); + assert(m < NUM_STATIC_MODELS); snprintf(path, 128, "data/models/%s.ply", static_model_defs[m].file); - ok = parse_ply(path, &model->geom_id); + ok = parse_ply(path, geom); + if (m == model_pirate_officer) + printf("num_verts: %d\n", geom->num_verts); if (!ok) return 0; diff --git a/src/node.c b/src/node.c @@ -43,6 +43,9 @@ void init_node_manager() { init_resource_manager(&node_manager, sizeof(struct node), 128, 0xFFFF, "node", N_STATIC_NODES); + + for (int i = 0; i < N_STATIC_NODES; i++) + node_init(&static_nodes()[i]); } struct node *node_init(struct node *node) { diff --git a/src/ply.c b/src/ply.c @@ -101,7 +101,7 @@ static int parse_magic(const char **cursor) { } -int parse_ply(const char *filename, geometry_id *geom_id) { +int parse_ply(const char *filename, struct geometry *geom) { size_t len; int success = 0; int nverts = 0; @@ -222,7 +222,6 @@ int parse_ply(const char *filename, geometry_id *geom_id) { free((void*)data); if (success) { - struct geometry *geom = new_geometry(geom_id); assert(geom); mkgeom.num_indices = ninds * 3; diff --git a/src/ply.h b/src/ply.h @@ -5,6 +5,6 @@ #include "geometry.h" -int parse_ply(const char *filename, geometry_id *geom_id); +int parse_ply(const char *filename, struct geometry *geom); #endif /* PLYPARSER_H */ diff --git a/src/render.c b/src/render.c @@ -10,6 +10,7 @@ #include "vbo.h" #include "shader.h" #include "geometry.h" +#include "static_resources.h" #include "debug.h" #include "render.h" #include "skybox.h" @@ -342,6 +343,17 @@ void render (struct game *game, struct render_config *config) { if (node == NULL) return; + if (i == 1) { + debug("rendering %s\n", node->label); + print_id(&entity->model_id, true); + struct model *model = get_model(&entity->model_id); + struct geometry *geom = get_geometry(&model->geom_id); + print_id(&model->geom_id, true); + + printf("num_verts: %d\n", geom->num_verts); + } + + mat4_multiply(view_proj, node->mat, mvp); mat4_copy(node->mat, model_view); mat4_multiply(config->depth_vp, model_view, depth_mvp); diff --git a/src/resource.c b/src/resource.c @@ -164,6 +164,7 @@ void *new_resource(struct resource_manager *r, struct resource_id *id) assert(id); assert(id->uuid != STATIC_UUID && "called new_resource with a static id"); assert(id->index == 0xFFFFFFFF && "res_id is uninitialized"); + assert(id->index >= r->static_elems); struct resource_id *fresh_id; @@ -240,6 +241,7 @@ void destroy_resource(struct resource_manager *r, struct resource_id *id) { r->name, id->uuid, id->index, r->resource_count); r->resource_count--; + assert(r->resource_count >= r->static_elems); r->generation++; assert((int)r->resource_count - (int)id->index >= 0); diff --git a/src/resource.h b/src/resource.h @@ -66,9 +66,4 @@ static inline int is_static_resource(struct resource_id *id) } -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 @@ -52,7 +52,6 @@ void entity_test_scene(struct game *game) { struct entity *player = get_player(&game->test_resources); struct terrain *terrain = &game->terrain; - player->model_id = get_static_model(model_pirate_officer, NULL); model_id rock_model; init_id(&rock_model); @@ -60,6 +59,10 @@ void entity_test_scene(struct game *game) /* model_id rock_model = get_static_model(model_tower, NULL); */ struct model *pmodel = new_model(&rock_model); assert(pmodel); struct geometry *geom = get_geometry(&pmodel->geom_id); assert(geom); + printf("rock geom "); + print_id(&pmodel->geom_id, 1); + printf("rock model "); + print_id(&rock_model, 1); proc_sphere(geom); for (int i = 0; i < terrain->size*0.2; i++) { @@ -75,6 +78,7 @@ void entity_test_scene(struct game *game) node_scale(node, pow(15.0, rand_0to1())); node_rotate(node, V3(rand_0to1(),rand_0to1(),rand_0to1())); node_translate(node, V3(x, y, z)); + node_set_label(node, "rock"); node_recalc(node); } diff --git a/src/util.h b/src/util.h @@ -30,6 +30,7 @@ #define min(a,b) (a < b ? a : b) #define max(a,b) (a > b ? a : b) #define streq(a,b) (strcmp(a,b) == 0) +#define contains(a,b) (strstr(a,b) != NULL) #define memeq(a,b,n1,n2) (memcmp(a,b,min(n1, n2)) == 0) #define approxeq(a, b) (fabs(a-b) < EPSILON) diff --git a/test/test_animation.c b/test/test_animation.c @@ -1,6 +1,7 @@ #include "animation.h" #include "util.h" +#include "debug.h" #include <assert.h> #include <stdio.h> @@ -21,8 +22,14 @@ int main(int argc, char *argv[]) load_poses("data/models/pirate-officer.dae", poses, &nposes); assert(nposes == 1); - pose = &poses[0]; + + debug("pose->nweights %d\n", pose->nweights); + assert(pose->nweights == 389); + assert(approxeq(pose->weights[0], 0.05213558)); + debug("pose last weight %f\n", pose->weights[388]); + assert(approxeq(pose->weights[388], 0.01394611)); + assert(pose->njoints == 11); joint = &pose->joints[0]; diff --git a/test/test_resource.c b/test/test_resource.c @@ -3,6 +3,7 @@ #include "entity.h" #include "model.h" #include "util.h" +#include "procmesh.h" #include "debug.h" #include <assert.h> @@ -138,6 +139,37 @@ static void test_entity_system() destroy_entity_system(); } +void test_geometry() +{ + printf("test_geometry\n"); + init_geometry_manager(); + init_model_manager(); + + struct model *model; + model_id player_model_id = + get_static_model(model_pirate_officer, &model); + + struct geometry *geom = get_geometry(&model->geom_id); + assert(geom); + + assert(geom->num_verts == 2676); + + model_id rock_model; + init_id(&rock_model); + struct model *pmodel = new_model(&rock_model); assert(pmodel); + struct geometry *pgeom = get_geometry(&pmodel->geom_id); assert(geom); + proc_sphere(pgeom); + + model_id player_model_id2 = make_static_id(model_pirate_officer); + + assert(ideq(&player_model_id, &player_model_id2)); + + pmodel = get_model(&player_model_id2); + pgeom = get_geometry(&pmodel->geom_id); + + assert(geom->num_verts == 2676); +} + void test_dynamic_model_manager() { printf("test_dynamic_model_manager\n"); @@ -146,6 +178,7 @@ void test_dynamic_model_manager() int main(int argc, char *argv[]) { + test_geometry(); test_int_resource_manager(); test_compact(); test_dynamic_model_manager(); diff --git a/test/test_scene.c b/test/test_scene.c @@ -25,9 +25,10 @@ void delete_every_other_entity() if (i % 2 == 0) { struct entity *ent = get_entity(&ids[i]); assert(ent); - struct model *pmodel = get_model(&ent->model_id); assert(pmodel); + struct model *pmodel = get_model(&ent->model_id); - destroy_model(&ent->model_id); + if (pmodel) + destroy_model(&ent->model_id); destroy_entity(&ids[i]); } } @@ -69,7 +70,6 @@ int scene_tests(struct game *game) { /* assert(ent_count == 102); */ delete_every_other_entity(); - assert(ent_count == 502); return 1; } diff --git a/todo.org b/todo.org @@ -4,7 +4,7 @@ * TODO [#A] Instance rendering for ground debris :perf:rendering: * TODO [#B] Load bone weights :anim: :LOGBOOK: -CLOCK: [2019-07-05 Fri 09:28] +CLOCK: [2019-07-05 Fri 15:46] :END: * TODO Simple pthreads job system :jobs:threads: