polyadvent

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

commit d9e8b3450400c825afa81b631de1a66a79a443ef
parent 89c556a73924eb70abe9537d3b75b0b9792b5fe0
Author: William Casarin <jb55@jb55.com>
Date:   Tue,  2 Jul 2019 15:21:50 -0700

resource fixes

Diffstat:
Msrc/animation.c | 2+-
Msrc/entity.c | 2+-
Msrc/game.c | 2++
Msrc/geometry.c | 20++++++++++++++++++--
Msrc/geometry.h | 1+
Msrc/main.c | 2+-
Msrc/model.c | 16+++++++++++++++-
Msrc/model.h | 1+
Msrc/node.c | 7++++---
Msrc/procmesh.c | 15++++++++++++++-
Msrc/resource.c | 37++++++++++++++++++++++++-------------
Msrc/resource.h | 5+++--
Msrc/scene.c | 61++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/scene.h | 1+
Msrc/terrain.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/terrain.h | 1+
Msrc/update.c | 55+++----------------------------------------------------
Msrc/vbo.h | 1+
Mtest/test_resource.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mtest/test_scene.c | 30++++++++++++++++++++++++++++++
20 files changed, 288 insertions(+), 102 deletions(-)

diff --git a/src/animation.c b/src/animation.c @@ -116,7 +116,7 @@ static void dae_tagbody(struct xmlparser *x, const char *d, size_t dl) assert(&joint->node_id == &pose->joints[pose->njoints].node_id); parse_joint(d, pose->njoints, joint); - print_id(&joint->node_id); + print_id(&joint->node_id, 1); node_set_label(node, data->current_name); joint->children_ids[0] = data->node_level; pose->njoints++; diff --git a/src/entity.c b/src/entity.c @@ -108,7 +108,7 @@ void destroy_entity_system() { void init_entity_system() { init_resource_manager(&esys, sizeof(struct entity), DEF_NUM_ENTITIES, - MAX_ENTITIES); + MAX_ENTITIES, "entity"); } diff --git a/src/game.c b/src/game.c @@ -134,6 +134,8 @@ void game_init(struct game *game, int width, int height) { init_terrain(terrain, size); create_terrain(terrain, size); + update_terrain(terrain); + /* get_entity(&terrain->entity_id)->flags |= ENT_INVISIBLE; */ create_skybox(&res->skybox, &res->programs[SKYBOX_PROGRAM]); diff --git a/src/geometry.c b/src/geometry.c @@ -174,7 +174,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); + DEF_NUM_GEOMETRY, MAX_GEOMETRY, "geometry"); } struct geometry *get_geometry(geometry_id *geom_id) { @@ -183,9 +183,25 @@ struct geometry *get_geometry(geometry_id *geom_id) { struct geometry *new_geometry(geometry_id *geom_id) { - return new_resource(&geom_manager, geom_id); + struct geometry *geom = new_resource(&geom_manager, geom_id); + /* debug("new geometry %llu\n", geom_id->uuid); */ + return geom; } struct geometry *get_all_geometry(u32 *count, geometry_id **ids) { return get_all_resources(&geom_manager, count, ids); } + +void destroy_geometry(geometry_id *geom_id) +{ + struct geometry *geom = get_geometry(geom_id); assert(geom); + struct vbo *vbo; + + for (int i = 0; i < n_vertex_attrs; i++) { + vbo = &geom->vbos[i]; + if (vbo->handle) + glDeleteBuffers(1, &vbo->handle); + } + + destroy_resource(&geom_manager, geom_id); +} diff --git a/src/geometry.h b/src/geometry.h @@ -58,5 +58,6 @@ void init_geometry_id(geometry_id *); 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); #endif /* GEOMETRY_H */ diff --git a/src/main.c b/src/main.c @@ -40,7 +40,7 @@ int main(void) int height = 480; game_init(&game, width, height); /* reset_scene(&game); */ - /* pbr_scene(&game); */ + entity_test_scene(&game); check_gl(); double last = hires_time_in_seconds(); diff --git a/src/model.c b/src/model.c @@ -2,6 +2,7 @@ #include "model.h" #include "ply.h" #include "resource.h" +#include "debug.h" #include <assert.h> #define MODELDEF(name) { .id = model_##name, .loaded = 0, .file = #name } @@ -46,6 +47,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); + /* debug("new model %llu\n", model_id->dyn_model_id.uuid); */ init_id(&model->geom_id); new_geometry(&model->geom_id); return model; @@ -53,7 +55,7 @@ static struct model *new_model_resource(model_id *model_id) void init_model_manager() { init_resource_manager(&dyn_modelman, sizeof(struct model), - DEF_DYNAMIC_MODELS, MAX_DYNAMIC_MODELS); + DEF_DYNAMIC_MODELS, MAX_DYNAMIC_MODELS, "model"); } @@ -102,6 +104,18 @@ static struct model *load_static_model(enum static_model m) return model; } +void destroy_model(model_id *model_id) +{ + if (model_id->type == STATIC_MODEL) + 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); +} + model_id get_static_model(enum static_model m, struct model **model) { model_id model_id; diff --git a/src/model.h b/src/model.h @@ -62,6 +62,7 @@ struct model *get_model(model_id *); struct model *get_model_geom(model_id *, struct geometry **); struct model *new_model(model_id *); struct model *new_static_model(model_id *); +void destroy_model(model_id *); model_id get_static_model(enum static_model, struct model**); diff --git a/src/node.c b/src/node.c @@ -19,6 +19,7 @@ struct node *new_node(node_id *id) { struct node *n = node_init(new_uninitialized_node(id)); assert((int64_t)id->uuid != -1); + /* debug("new node %llu\n", id->uuid); */ return n; } @@ -39,7 +40,7 @@ void destroy_node(node_id *id) void init_node_manager() { - init_resource_manager(&node_manager, sizeof(struct node), 128, 0xFFFF); + init_resource_manager(&node_manager, sizeof(struct node), 128, 0xFFFF, "node"); } struct node *node_init(struct node *node) { @@ -107,7 +108,7 @@ int node_needs_recalc(struct node *node) } vec3 *node_world(struct node *node) { - node_recalc(node); + return &node->mat[M_X]; } @@ -175,7 +176,7 @@ int node_detach(struct node *node, struct node *from) { if (child && child == node) { destroy_node(child_id); memmove(&from->children_ids[i], &from->children_ids[i+1], - sizeof(*from->children_ids) * from->n_children - 1); + sizeof(*from->children_ids) * (from->n_children - i - 1)); // TODO: test node_detach from->n_children--; return 1; diff --git a/src/procmesh.c b/src/procmesh.c @@ -35,7 +35,7 @@ void proc_sphere(struct geometry *geom) { const int n = 50; qh_vertex_t *vertices = malloc(n*sizeof(qh_vertex_t)); const float radius = 2.0; - + float *colors; for (int i = 0; i < n; ++i) { float a0 = (rand_0to1() * TAU); @@ -43,13 +43,26 @@ void proc_sphere(struct geometry *geom) { 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); + + assert(mesh.nvertices); + colors = malloc(mesh.nvertices * 3 * sizeof(*colors)); + assert(colors); + for (u32 i = 0; i < mesh.nvertices; i++) { + for (int j = 0; j < 3; j++) + colors[i*3+j] = 0.5; + } + mkgeom.colors = colors; + qh_mesh_to_geom(&mesh, &mkgeom); + make_buffer_geometry(&mkgeom, geom); free(vertices); + free(colors); free(mkgeom.normals); qh_free_mesh(mesh); } diff --git a/src/resource.c b/src/resource.c @@ -39,17 +39,18 @@ void null_id(struct resource_id *id) } void init_resource_manager(struct resource_manager *r, u32 elem_size, - u32 initial_elements, u32 max_elements) { + u32 initial_elements, u32 max_elements, const char *name) { r->generation = 1; r->resource_count = 0; r->elem_size = elem_size; r->max_capacity = max_elements; r->current_capacity = initial_elements; + r->name = name; assert(initial_elements != 0); r->resources = calloc(initial_elements, elem_size); - r->ids = calloc(initial_elements, sizeof(*r->ids)); + r->ids = calloc(initial_elements, sizeof(struct resource_id)); } void destroy_resource_manager(struct resource_manager *r) { @@ -63,7 +64,8 @@ static int refresh_id(struct resource_manager *r, struct resource_id *id, // rollover is ok /* assert(->generation <= esys.generation); */ if (id->generation != r->generation) { - /* debug("id gen %d != res gen %d, refreshing\n", id->generation, r->generation); */ + /* debug("id %llu gen %d != res gen %d, refreshing\n", */ + /* id->uuid, id->generation, r->generation); */ // try to find uuid in new memory layout for (u32 i = 0; i < r->resource_count; i++) { struct resource_id *newer_id = &r->ids[i]; @@ -97,6 +99,8 @@ static void new_id(struct resource_manager *r, struct resource_id *id) static void resize(struct resource_manager *r) { + debug("resizing %s resources, count %d+1 > current capacity %d\n", + r->name, r->resource_count, r->current_capacity); void *new_mem; u32 new_size = r->resource_count * 1.5; if (new_size >= r->max_capacity) @@ -121,14 +125,12 @@ static void resize(struct resource_manager *r) } r->current_capacity = new_size; r->ids = new_mem; - - // 2 to avoid issues with compact generation incrementing - r->generation += 2; } -void print_id(struct resource_id *id) +void print_id(struct resource_id *id, int nl) { - printf("res_id(uuid:%llu ind:%d gen:%d)\n", id->uuid, id->index, id->generation); + printf("id(u:%llu i:%d g:%d)%s", + id->uuid, id->index, id->generation, nl?"\n":""); } void *new_resource(struct resource_manager *r, struct resource_id *id) @@ -158,14 +160,14 @@ void *get_resource(struct resource_manager *r, struct resource_id *id) { assert((int64_t)id->generation != -1 && "id intialized but not allocated (needs new_ call)"); if (id->generation == 0) { - //unusual("getting already deleted resource %llu\n", id->uuid); + /* unusual("getting already deleted resource %llu\n", id->uuid); */ return NULL; } enum refresh_status res = refresh_id(r, id, id); if (res == RESOURCE_DELETED) { - unusual("getting deleted resource %llu\n", id->uuid); + unusual("getting deleted %s resource %llu\n", r->name, id->uuid); return NULL; } @@ -190,18 +192,27 @@ void destroy_resource(struct resource_manager *r, struct resource_id *id) { return; } - /* debug("destroying resource %llu\n", id->uuid); */ + debug("destroying %s resource %llu ind %d res_count %d\n", + r->name, id->uuid, id->index, r->resource_count); r->resource_count--; r->generation++; + assert((int)r->resource_count - (int)id->index >= 0); + + // TODO: we're copying OOB here memmove(index_resource(r, id->index), index_resource(r, id->index+1), - r->elem_size * r->resource_count); + r->elem_size * (r->resource_count - id->index)); memmove(&r->ids[id->index], &r->ids[id->index+1], - sizeof(*r->ids) * r->resource_count); + sizeof(struct resource_id) * (r->resource_count - id->index)); + + + for (u32 i = id->index; i < r->resource_count; i++) { + r->ids[i].index--; + } } int is_id_allocated(struct resource_id *id) diff --git a/src/resource.h b/src/resource.h @@ -25,6 +25,7 @@ struct resource_manager { u32 slots_used; u32 max_capacity; u32 current_capacity; + const char *name; }; #define ideq(a, b) ((a)->uuid == (b)->uuid) @@ -36,10 +37,10 @@ void *get_all_resources(struct resource_manager *, u32 *count, struct resource_i 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 print_id(struct resource_id *); +void print_id(struct resource_id *, int nl); void null_id(struct resource_id *id); void init_resource_manager(struct resource_manager *r, u32 elem_size, - u32 initial_elements, u32 max_elements); + u32 initial_elements, u32 max_elements, const char *name); #endif /* RESOURCE_H */ diff --git a/src/scene.c b/src/scene.c @@ -1,6 +1,10 @@ + #include "game.h" #include "model.h" +#include "procmesh.h" +#include "debug.h" +#include "vec3.h" #include <assert.h> void reset_scene(struct game *game) { @@ -43,12 +47,63 @@ void default_scene(struct game *game) { } -void pbr_scene(struct game *game) { +static void delete_every_other_entity() +{ + u32 count; + entity_id *ids; + + for (u32 i = RESERVED_ENTITIES; i < 1000; i++) { + get_all_entities(&count, &ids); + + if (i >= count) + return; + + if (i % 2 == 0) { + struct entity *ent = get_entity(&ids[i]); assert(ent); + struct model *pmodel = get_model(&ent->model_id); assert(pmodel); + + destroy_model(&ent->model_id); + destroy_entity(&ids[i]); + } + } +} + + + +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); + + for (int i = 0; i < 500; i++) { + struct entity *ent = new_entity(NULL); + struct node *node = get_node(&ent->node_id); + + struct model *pmodel = new_model(&ent->model_id); assert(pmodel); + struct geometry *geom = get_geometry(&pmodel->geom_id); assert(geom); + + proc_sphere(geom); + pmodel->shading = SHADING_VERT_COLOR; + + double x = rand_0to1() * terrain->size; + double y = rand_0to1() * terrain->size; + double z = terrain->fn(terrain, x, y); + + node_scale(node, 10.0); + node_translate(node, V3(x, y, z)); + + node_recalc(node); + } + +} + +void pbr_scene(struct game *game) +{ struct entity *ent = new_entity(NULL); struct node *node = get_node(&ent->node_id); assert(node); + struct entity *player = get_player(&game->test_resources); 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/scene.h b/src/scene.h @@ -6,6 +6,7 @@ void default_scene(struct game *); void reset_scene(struct game *); +void entity_test_scene(struct game *); void pbr_scene(struct game *); #endif /* SCENE_H */ diff --git a/src/terrain.c b/src/terrain.c @@ -2,6 +2,7 @@ #include "terrain.h" #include "util.h" #include "delaunay.h" +#include "debug.h" #include "vec3.h" #include "perlin.h" #include "poisson.h" @@ -241,3 +242,53 @@ void destroy_terrain(struct terrain *terrain) { struct model *model = get_model(&ent->model_id); assert(model); destroy_buffer_geometry(&model->geom_id); } + + +void update_terrain(struct terrain *terrain) { + static int first = 1; + static float last_scale = -1.0; + + struct entity *ent = get_entity(&terrain->entity_id); + assert(ent); + struct perlin_settings *ts = &terrain->settings; + struct node *tnode = get_node(&ent->node_id); + assert(tnode); + + debug("updating terrain\n"); + + if (first) { + reset_terrain(terrain, terrain->size); + /* tnode->pos[0] = rand_0to1() * terrain->size; */ + /* tnode->pos[1] = rand_0to1() * terrain->size; */ + first = 0; + } + + ts->ox = tnode->pos[0]; + ts->oy = tnode->pos[1]; + + double scale = tnode->pos[2] * 0.0015; + if (scale == 0) scale = 1.0; + + printf("terrain %f %f %f\n", tnode->pos[0], tnode->pos[1], tnode->pos[2]); + + /* ts.o1s = fabs(sin(1/n) * 0.25); */ + /* ts.o1 = fabs(cos(n*0.2) * 0.5); */ + /* ts.o2s = fabs(cos(n+2) * 0.5); */ + /* ts.o2 = fabs(sin(n*0.02) * 2); */ + ts->freq = scale * 0.05; + ts->amplitude = 50.0; + + /* if (terrain->fn) */ + /* destroy_terrain(terrain); */ + + /* const double pdist = min(5.0, max(1.1, 1.0/scale*1.4)); */ + + /* printf("pdist %f\n", pdist); */ + + if (last_scale == -1.0 || fabs(scale - last_scale) > 0.00001) { + gen_terrain_samples(terrain, scale); + } + + last_scale = scale; + create_terrain(terrain, scale); +} diff --git a/src/terrain.h b/src/terrain.h @@ -32,6 +32,7 @@ struct terrain { double old_noisy_boi(struct terrain *, double x, double y); +void update_terrain(struct terrain *terrain); void gen_terrain_samples(struct terrain *terrain, float scale); void init_terrain(struct terrain *terrain, float size); void reset_terrain(struct terrain *terrain, float size); diff --git a/src/update.c b/src/update.c @@ -88,55 +88,6 @@ static void remap_samples(struct point *points, int n_samples, } } -void update_terrain(struct terrain *terrain) { - static int first = 1; - static float last_scale = -1.0; - - struct entity *ent = get_entity(&terrain->entity_id); - assert(ent); - struct perlin_settings *ts = &terrain->settings; - struct node *tnode = get_node(&ent->node_id); - assert(tnode); - - debug("updating terrain\n"); - - if (first) { - reset_terrain(terrain, terrain->size); - tnode->pos[0] = rand_0to1() * terrain->size; - tnode->pos[1] = rand_0to1() * terrain->size; - first = 0; - } - - ts->ox = tnode->pos[0]; - ts->oy = tnode->pos[1]; - - double scale = tnode->pos[2] * 0.0015; - if (scale == 0) scale = 1.0; - - printf("terrain %f %f %f\n", tnode->pos[0], tnode->pos[1], tnode->pos[2]); - - /* ts.o1s = fabs(sin(1/n) * 0.25); */ - /* ts.o1 = fabs(cos(n*0.2) * 0.5); */ - /* ts.o2s = fabs(cos(n+2) * 0.5); */ - /* ts.o2 = fabs(sin(n*0.02) * 2); */ - ts->freq = scale * 0.05; - ts->amplitude = 50.0; - - /* if (terrain->fn) */ - /* destroy_terrain(terrain); */ - - /* const double pdist = min(5.0, max(1.1, 1.0/scale*1.4)); */ - - /* printf("pdist %f\n", pdist); */ - - if (last_scale == -1.0 || fabs(scale - last_scale) > 0.00001) { - gen_terrain_samples(terrain, scale); - } - - last_scale = scale; - create_terrain(terrain, scale); -} - static void player_terrain_collision(struct terrain *terrain, struct entity *player) { // player movement static vec3 last_pos[3] = {0}; @@ -382,7 +333,7 @@ static void player_update(struct game *game, struct entity *player) { void update (struct game *game) { static int toggle_fog = 0; - static int first = 1; + static int needs_terrain_update = 0; struct resources *res = &game->test_resources; struct terrain *terrain = &game->terrain; struct node *root = get_node(&game->test_resources.root_id); @@ -400,9 +351,9 @@ void update (struct game *game) { gravity(game); - if (first) { + if (needs_terrain_update) { update_terrain(terrain); - first = 0; + needs_terrain_update = 0; } /* spherical_dir(game->test_resources.camera.coords, camera_dir); */ diff --git a/src/vbo.h b/src/vbo.h @@ -69,5 +69,6 @@ make_int_vertex_buffer(struct vbo *vbo, const int *data, void bind_uv_vbo(struct vbo *vbo, gpu_addr slot); void bind_vbo(struct vbo *vbo, gpu_addr slot, GLenum type); +void free_vbo(struct vbo *vbo); #endif /* POLYADVENT_BUFFER_H */ diff --git a/test/test_resource.c b/test/test_resource.c @@ -6,43 +6,79 @@ #include "debug.h" #include <assert.h> -void test_compact() +static void print_int_resources(struct resource_manager *m) +{ + int *ints = (int*)m->resources; + + for (u32 i = 0; i < m->resource_count; i++) { + printf("%d ", ints[i]); + } + + printf("\n"); +} + + +static void print_ids(struct resource_manager *m) +{ + for (u32 i = 0; i < m->resource_count; i++) { + print_id(&m->ids[i], 0); + printf(" "); + } + printf("\n"); +} + + +static void test_compact() { printf("test_compact\n"); struct resource_manager r; - struct resource_id ids[3], first_id; + struct resource_id ids[20]; int *p; + u32 i; - init_resource_manager(&r, sizeof(int), 2, 4); + init_resource_manager(&r, sizeof(int), 2, 6, "int"); - for (int i = 0; i < (int)ARRAY_SIZE(ids); i++) + for (i = 0; i < (int)ARRAY_SIZE(ids); i++) init_id(&ids[i]); - init_id(&first_id); + i = 0; - p = new_resource(&r, &first_id); - assert(r.resource_count == 1); - *p = 11; + p = new_resource(&r, &ids[i++]); + assert(r.resource_count == 1); *p = 0; - p = new_resource(&r, &ids[0]); - *p = 22; + p = new_resource(&r, &ids[i++]); *p = 1; assert(r.resource_count == 2); - destroy_resource(&r, &first_id); - assert(r.resource_count == 1); - assert(get_resource(&r, &first_id) == NULL); - assert(*(int*)get_resource(&r, &ids[0]) == 22); + p = new_resource(&r, &ids[i++]); *p = 2; + p = new_resource(&r, &ids[i++]); + *p = 3; - new_resource(&r, &ids[1]); - assert(r.resource_count == 2); - assert(r.current_capacity == 2); - new_resource(&r, &ids[2]); + print_int_resources(&r); + print_ids(&r); + + assert(r.resource_count == 4); + destroy_resource(&r, &ids[1]); assert(r.resource_count == 3); - assert(r.current_capacity >= 3); + print_int_resources(&r); + print_ids(&r); + + assert(*(int*)get_resource(&r, &ids[0]) == 0); + assert( get_resource(&r, &ids[1]) == NULL); + print_id(&ids[1], 1); + debug("%d\n",*(int*)get_resource(&r, &ids[2]) ); + assert(*(int*)get_resource(&r, &ids[2]) == 2); + + new_resource(&r, &ids[i++]); + assert(r.resource_count == 4); + assert(r.current_capacity >= 4); + + new_resource(&r, &ids[i++]); + assert(r.resource_count == 5); + assert(r.current_capacity >= 5); } -void test_int_resource_manager() +static void test_int_resource_manager() { printf("test_int_resource_manager\n"); struct resource_manager r @@ -50,7 +86,7 @@ void test_int_resource_manager() struct resource_id id, first_id; int *p; // 2 item case - init_resource_manager(&r, sizeof(int), 1, 2); + init_resource_manager(&r, sizeof(int), 1, 2, "int"); init_id(&id); init_id(&first_id); @@ -74,7 +110,7 @@ void test_int_resource_manager() destroy_resource_manager(&r); } -void test_entity_system() +static void test_entity_system() { printf("test_entity_system\n"); u32 count; diff --git a/test/test_scene.c b/test/test_scene.c @@ -12,6 +12,28 @@ #define t_assert(cond, msg) assert(cond && msg); +void delete_every_other_entity() +{ + u32 count; + entity_id *ids; + + for (u32 i = RESERVED_ENTITIES; i < 1000; i++) { + get_all_entities(&count, &ids); + + if (i >= count) + return; + + if (i % 2 == 0) { + struct entity *ent = get_entity(&ids[i]); assert(ent); + struct model *pmodel = get_model(&ent->model_id); assert(pmodel); + + destroy_model(&ent->model_id); + destroy_entity(&ids[i]); + } + } +} + + int scene_tests(struct game *game) { struct node *root = get_node(&game->test_resources.root_id); assert(root); @@ -41,6 +63,14 @@ int scene_tests(struct game *game) { t_assert(node_count(root) == initial_node_count, "scene: node count doesn't match initial after reset_scene"); + entity_test_scene(game); + + get_all_entities(&ent_count, NULL); + /* assert(ent_count == 102); */ + + delete_every_other_entity(); + assert(ent_count == 502); + return 1; }