polyadvent

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

commit ce45bea5987910e2a98470df559a5bab51c9cb7b
parent 153122c760c01517bb4eb8dc7793d11a2f3d38f7
Author: William Casarin <jb55@jb55.com>
Date:   Tue,  2 Jul 2019 11:44:30 -0700

scene tests working

Diffstat:
M.gitignore | 1+
MMakefile | 2++
Msrc/entity.c | 29+++++++++++++++++++++++++----
Msrc/entity.h | 12+++++++++++-
Msrc/game.c | 28++++++++++++++++++++++++++++
Msrc/game.h | 3+++
Msrc/main.c | 25++-----------------------
Msrc/node.c | 6++++++
Msrc/procmesh.c | 1+
Msrc/resource.c | 9+++++++--
Msrc/scene.c | 14++++++++++----
Msrc/terrain.c | 2+-
Dsrc/tests.c | 35-----------------------------------
Msrc/util.h | 3+++
Msrc/vbo.c | 2+-
Atest/test_scene.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16 files changed, 157 insertions(+), 71 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -5,3 +5,4 @@ polyadvent *.d /test/test_animation /test/test_resource +/test/test_scene diff --git a/Makefile b/Makefile @@ -53,6 +53,7 @@ OBJS += $(SRC)/procmesh.o TESTS = test/test_animation TESTS += test/test_resource +TESTS += test/test_scene SRCS=$(OBJS:.o=.c) @@ -77,6 +78,7 @@ test/%: test/%.o $(OBJS) check: $(TESTS) ./test/test_animation ./test/test_resource + ./test/test_scene $(BIN): src/main.o $(OBJS) $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ diff --git a/src/entity.c b/src/entity.c @@ -3,6 +3,7 @@ #include "node.h" #include "model.h" #include "resource.h" +#include "debug.h" #include <assert.h> #define DEF_NUM_ENTITIES 1024 @@ -25,6 +26,7 @@ struct entity *init_entity(struct entity *ent, node_id *id) { init_id(&new_id); new_node(&new_id); ent->node_id = new_id; + /* debug("init_entity with new node_id %llu\n", new_id.uuid); */ } else { ent->node_id = *id; @@ -41,12 +43,20 @@ static inline struct entity *new_uninitialized_entity(entity_id *id) { return new_resource(&esys, id); } -struct entity *new_entity(entity_id *id) { +struct entity *new_entity_(entity_id *id) { return new_entity_with_node(id, NULL); } -struct entity *new_entity_with_node(entity_id *id, node_id *node) { +struct entity *new_entity_with_node(entity_id *id, node_id *node) +{ + entity_id new_id; + + if (id == NULL) { + id = &new_id; + init_id(&new_id); + } + return init_entity(new_uninitialized_entity(id), node); } @@ -65,7 +75,8 @@ void destroy_entities() { } }; -void destroy_entity(entity_id *id) { +void destroy_entity(entity_id *id) +{ struct entity *ent = get_entity(id); assert(ent); if (ent == NULL) @@ -76,11 +87,21 @@ void destroy_entity(entity_id *id) { if (node == NULL) return; + if (id->index < RESERVED_ENTITIES) { + unusual("trying to destroy reserved entity with node %s\n", node->label); + return; + } + node_detach_from_parent(node); - destroy_resource(&esys, &ent->node_id); destroy_resource(&esys, id); } +const char *entity_label(struct entity *ent) +{ + struct node *node = get_node(&ent->node_id); assert(node); + return node->label; +} + void destroy_entity_system() { destroy_resource_manager(&esys); } diff --git a/src/entity.h b/src/entity.h @@ -5,6 +5,8 @@ #include "node.h" #include "model.h" #include "id.h" +#include "util.h" +#include <assert.h> #define RESERVED_ENTITIES 2 #define MAX_ENTITIES 2048 @@ -31,9 +33,17 @@ struct resource_manager *_internal_get_entity_system(); void destroy_entity(entity_id *); void init_entity_system(); struct entity *get_entity(entity_id *); +const char *entity_label(struct entity *); struct entity *get_all_entities(u32 *count, entity_id **ids); -struct entity *new_entity(entity_id *); +struct entity *new_entity_(entity_id *); struct entity *new_entity_with_node(entity_id *, node_id *); void destroy_entity_system(); +static inline struct entity *new_entity(entity_id *id) +{ + if (id) + assert((int)id->index == -1 && "error: " __FILE__ ":" STRIZE(__LINE__) " missing init_id or already initialized"); + return new_entity_(id); +} + #endif /* ENTITY_H */ diff --git a/src/game.c b/src/game.c @@ -55,8 +55,35 @@ static void init_user_settings(struct user_settings *settings) { } +static void init_sdl(SDL_Window **window, int width, int height) +{ + SDL_Init( SDL_INIT_VIDEO ); + + /* SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); + + *window = SDL_CreateWindow("SDL2/OpenGL Demo", 0, 0, width, height, + SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); + + SDL_GL_CreateContext(*window); +} + +void quit_game(struct game *game) +{ + game->quit = 1; +} 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_model_manager(); @@ -84,6 +111,7 @@ void game_init(struct game *game, int width, int height) { mat4 *light_dir = res->light_dir; int ok = 0; + game->quit = 0; game->frame = 0; const double size = 10000.0; diff --git a/src/game.h b/src/game.h @@ -84,8 +84,10 @@ struct user_settings { }; struct game { + SDL_Window *window; int counter; int seed; + int quit; float dt; u64 frame; struct user_settings user_settings; @@ -98,6 +100,7 @@ struct game { struct entity *get_player(struct resources *); struct entity *get_terrain_entity(struct terrain *); void game_init(struct game *game, int width, int height); +void quit_game(struct game *game); void should_update(struct game *game); int was_key_pressed_this_frame(struct game *game, int scancode); int is_free_camera(struct game *game); diff --git a/src/main.c b/src/main.c @@ -38,27 +38,6 @@ int main(void) /* SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); */ int width = 640; int height = 480; - - SDL_Init( SDL_INIT_VIDEO ); - - /* SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); */ - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); - - - SDL_Window *window = SDL_CreateWindow( - "SDL2/OpenGL Demo", 0, 0, width, height, - SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); - - SDL_GL_CreateContext(window); game_init(&game, width, height); /* reset_scene(&game); */ /* pbr_scene(&game); */ @@ -85,7 +64,7 @@ int main(void) }; - while (1) { + while (!game.quit) { game.frame++; process_events(&game.input, game.frame); if (game.input.resized_height) { @@ -116,7 +95,7 @@ int main(void) render(&game, &default_config); /* Swap front and back buffers */ - SDL_GL_SwapWindow(window); + SDL_GL_SwapWindow(game.window); } /* free(slab_buffer); */ diff --git a/src/node.c b/src/node.c @@ -2,6 +2,7 @@ #include "node.h" #include "mat_util.h" +#include "debug.h" #include <string.h> #include <stdio.h> #include <assert.h> @@ -28,6 +29,11 @@ struct node *get_node(node_id *id) void destroy_node(node_id *id) { +#ifdef DEBUG + struct node *node = get_node(id); + debug("destroying node %llu %s\n", id->uuid, node->label); +#endif + destroy_resource(&node_manager, id); } diff --git a/src/procmesh.c b/src/procmesh.c @@ -49,6 +49,7 @@ void proc_sphere(struct geometry *geom) { qh_mesh_to_geom(&mesh, &mkgeom); make_buffer_geometry(&mkgeom, geom); + free(vertices); free(mkgeom.normals); qh_free_mesh(mesh); } diff --git a/src/resource.c b/src/resource.c @@ -134,7 +134,7 @@ void print_id(struct resource_id *id) void *new_resource(struct resource_manager *r, struct resource_id *id) { assert(id); - assert((int)id->index == -1 && "res_id already initialized or uninitialized"); + assert((int)id->index == -1 && "res_id is uninitialized"); struct resource_id *fresh_id; @@ -174,8 +174,10 @@ void *get_resource(struct resource_manager *r, struct resource_id *id) { void destroy_resource(struct resource_manager *r, struct resource_id *id) { - if (is_resource_destroyed(id)) + if (is_resource_destroyed(id)) { + unusual("trying to destroy resource %llu which was already destroyed\n", id->uuid); return; + } enum refresh_status res = refresh_id(r, id, id); // entity already deleted @@ -183,10 +185,13 @@ void destroy_resource(struct resource_manager *r, struct resource_id *id) { /* id->uuid, id->generation, id->index); */ if (res == RESOURCE_DELETED) { + unusual("trying to destroy resource %llu which was already destroyed (2)\n", id->uuid); id->generation = 0; return; } + /* debug("destroying resource %llu\n", id->uuid); */ + r->resource_count--; r->generation++; diff --git a/src/scene.c b/src/scene.c @@ -36,13 +36,19 @@ void default_scene(struct game *game) { node_translate(tnode, V3(0.0, 50.0, 0.0)); node_recalc(tnode); float z = terrain->fn(terrain, tnode->mat[M_X], tnode->mat[M_Y]); - node_detach(tnode, pnode); + /* node_detach(tnode, pnode); */ tnode->mat[M_Z] = z; // END ENTITIES } -/* void pbr_scene(struct game *game) { */ -/* struct model *sphere = get_static_model(model_icosphere, NULL); */ -/* } */ +void pbr_scene(struct game *game) { + struct entity *ent = new_entity(NULL); + struct node *node = get_node(&ent->node_id); assert(node); + + ent->model_id = get_static_model(model_icosphere, NULL); + node_set_label(node, "sphere"); + node_attach(&game->test_resources.root_id, &ent->node_id); + +} diff --git a/src/terrain.c b/src/terrain.c @@ -54,7 +54,7 @@ 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); assert(ent); + struct entity *ent = new_entity(&terrain->entity_id); struct node *node = get_node(&ent->node_id); assert(node); struct model *model = new_model(&ent->model_id); assert(model); /* struct model *model = init_model(&ent->model_id); assert(model); */ diff --git a/src/tests.c b/src/tests.c @@ -1,35 +0,0 @@ - -#include "scene.h" -#include "entity.h" - - -/* #define t_assert(cond, msg) if (cond) { printf(msg); } */ -#define t_assert(cond, msg) assert(cond); - -int scene_tests(struct game *game) { - struct node *root = &game->test_resources.root; - u32 ent_count; - int initial_node_count = node_count(root); - reset_scene(game); - t_assert(node_count(root) == initial_node_count, - "scene: node count doesn't match initial after reset_scene"); - - get_all_entities(&ent_count, NULL); - t_assert(ent_count == RESERVED_ENTITIES, - "scene: entity count isn't reset after reset_scene"); - - default_scene(game); - get_all_entities(&ent_count, NULL); - - t_assert(ent_count > RESERVED_ENTITIES, - "scene: entity count isn't larger after loading default scene"); - - reset_scene(game); - t_assert(ent_count == RESERVED_ENTITIES, - "scene: entity count isn't reset after reset_scene"); - - t_assert(node_count(root) == initial_node_count, - "scene: node count doesn't match initial after reset_scene"); - - return 1; -} diff --git a/src/util.h b/src/util.h @@ -16,6 +16,9 @@ } \ } +#define STRIZE_DETAIL(x) #x +#define STRIZE(x) STRIZE_DETAIL(x) + #define UP_VEC V3(0.0, 0.0, 1.0) #define PI 3.14159265 #define TAU 6.2831853 diff --git a/src/vbo.c b/src/vbo.c @@ -16,7 +16,7 @@ make_buffer(GLenum target, const void *buffer_data, GLsizei buffer_size) { check_gl(); assert(buffer_size > 0); - debug("buffer data %d\n", buffer_size); + /* debug("buffer data %d\n", buffer_size); */ glBufferData(target, buffer_size, buffer_data, GL_STATIC_DRAW); check_gl(); diff --git a/test/test_scene.c b/test/test_scene.c @@ -0,0 +1,56 @@ + +#include "scene.h" +#include "entity.h" +#include "game.h" +#include "debug.h" +#include <assert.h> + +#include <unistd.h> + + +/* #define t_assert(cond, msg) if (cond) { printf(msg); } */ +#define t_assert(cond, msg) assert(cond && msg); + + +int scene_tests(struct game *game) { + struct node *root = get_node(&game->test_resources.root_id); + assert(root); + + u32 ent_count; + int initial_node_count = node_count(root); + reset_scene(game); + t_assert(node_count(root) == initial_node_count, + "scene: node count doesn't match initial after reset_scene"); + + get_all_entities(&ent_count, NULL); + t_assert(ent_count == RESERVED_ENTITIES, + "scene: entity count isn't reset after reset_scene"); + + + default_scene(game); + get_all_entities(&ent_count, NULL); + + t_assert(ent_count > RESERVED_ENTITIES, + "scene: entity count isn't larger after loading default scene"); + + reset_scene(game); + get_all_entities(&ent_count, NULL); + t_assert(ent_count == RESERVED_ENTITIES, + "scene: entity count isn't reset after reset_scene"); + + t_assert(node_count(root) == initial_node_count, + "scene: node count doesn't match initial after reset_scene"); + + return 1; +} + + +int main(int argc, char *argv[]) +{ + struct game game; + int res = chdir("/home/jb55/src/c/polyadvent"); + assert(res == 0); + game_init(&game, 1024, 768); + scene_tests(&game); + return 0; +}