polyadvent

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

commit 16811635a54c0eb4f849442ce311c8d0d298ca4d
parent 1d79a744f594bc569b9bd769b35e24e8baeeb283
Author: William Casarin <jb55@jb55.com>
Date:   Mon, 19 Nov 2018 23:22:32 -0800

dynamic wip

Diffstat:
MMakefile | 2+-
Dsrc/buffer.c | 71-----------------------------------------------------------------------
Dsrc/buffer.h | 43-------------------------------------------
Msrc/entity.c | 26++++++++++++++++++--------
Msrc/entity.h | 11++++++-----
Msrc/game.h | 2+-
Msrc/geometry.c | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/geometry.h | 41+++++++++++++++++++++++++++++++++--------
Asrc/id.h | 13+++++++++++++
Msrc/main.c | 3++-
Msrc/model.c | 39++++++++++++++++++++++++++++++++-------
Msrc/model.h | 20+++++++++++++++++---
Msrc/node.c | 15++++++++++++++-
Msrc/node.h | 2++
Msrc/ply.c | 61++++++++++++++++++++++++++++++++++---------------------------
Msrc/ply.h | 2+-
Msrc/scene.c | 7++++---
Asrc/scene.h | 11+++++++++++
Msrc/skybox.c | 17++++++++++-------
Msrc/terrain.c | 20++++++++++++--------
Msrc/terrain.h | 1+
Asrc/tests.c | 35+++++++++++++++++++++++++++++++++++
Msrc/ui.c | 25++++++++++++++-----------
Asrc/vbo.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/vbo.h | 45+++++++++++++++++++++++++++++++++++++++++++++
25 files changed, 489 insertions(+), 256 deletions(-)

diff --git a/Makefile b/Makefile @@ -12,7 +12,7 @@ LDFLAGS = -lSDL2 -lGL -lm SRC=src OBJS = $(SRC)/window.o -OBJS += $(SRC)/buffer.o +OBJS += $(SRC)/vbo.o OBJS += $(SRC)/camera.o OBJS += $(SRC)/debug.o OBJS += $(SRC)/delaunay.o diff --git a/src/buffer.c b/src/buffer.c @@ -1,71 +0,0 @@ - -#include "buffer.h" -#include "util.h" -#include <assert.h> -#include "gl.h" - -gpu_addr -make_buffer(GLenum target, const void *buffer_data, GLsizei buffer_size) { - gpu_addr buffer; - check_gl(); - glGenBuffers(1, &buffer); - check_gl(); - - glBindBuffer(target, buffer); - check_gl(); - - glBufferData(target, buffer_size, buffer_data, GL_STATIC_DRAW); - check_gl(); - - return buffer; -} - -struct vbo* -make_index_buffer(GLenum target, const void *data, GLsizei buffer_size, - struct vbo *vbo) { - vbo->components = 3; - vbo->handle = make_buffer(target, data, buffer_size); - vbo->type = GL_ELEMENT_ARRAY_BUFFER; - return vbo; -} - - -struct vbo* -make_vertex_buffer(GLenum target, const void *data, - GLsizei buffer_size, struct vbo *vbo) { - vbo->components = 3; - vbo->handle = make_buffer(target, data, buffer_size); - vbo->type = GL_ARRAY_BUFFER; - return vbo; -} - -struct vbo* -make_uv_buffer(GLenum target, const void *data, - GLsizei buffer_size, struct vbo *vbo, int components) { - vbo->components = components; - vbo->handle = make_buffer(target, data, buffer_size); - vbo->type = GL_ARRAY_BUFFER; - return vbo; -} - -void bind_ibo(struct vbo *vbo) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->handle); -} - -static void bind_vbo_internal(struct vbo *vbo, gpu_addr slot) { - glEnableVertexAttribArray(slot); - check_gl(); - glBindBuffer(vbo->type, vbo->handle); - check_gl(); - glVertexAttribPointer(slot, // attribute - vbo->components, // size - GL_FLOAT, // type - GL_FALSE, // normalized? - 0, // stride - (void*)0 // array buffer offset - ); -} - -void bind_vbo(struct vbo *vbo, gpu_addr slot) { - bind_vbo_internal(vbo, slot); -} diff --git a/src/buffer.h b/src/buffer.h @@ -1,43 +0,0 @@ -#ifndef POLYADVENT_BUFFER_H -#define POLYADVENT_BUFFER_H - -#include "gl.h" -#include "common.h" - -typedef GLuint gpu_addr; - -struct attributes { - gpu_addr position; - gpu_addr normal; - gpu_addr color; - gpu_addr tex_coord; -}; - -struct vbo { - u32 type; - int components; - gpu_addr handle; -}; - -#define NUM_VBO_SLOTS 1 - -gpu_addr make_buffer(GLenum target, const void *buffer_data, - GLsizei buffer_size); - -struct vbo * -make_vertex_buffer(GLenum target, const void *buffer_data, - GLsizei buffer_size, struct vbo *vbo); - -struct vbo * -make_index_buffer(GLenum target, const void *buffer_data, - GLsizei buffer_size, struct vbo *vbo); - -struct vbo * -make_uv_buffer(GLenum target, const void *data, - GLsizei buffer_size, struct vbo *vbo, int components); - -void bind_uv_vbo(struct vbo *vbo, gpu_addr slot); -void bind_vbo(struct vbo *vbo, gpu_addr slot); -void bind_ibo(struct vbo *vbo); - -#endif /* POLYADVENT_BUFFER_H */ diff --git a/src/entity.c b/src/entity.c @@ -27,7 +27,6 @@ struct entity *get_all_entities(u32 *count, struct entity_id **ids) { struct entity *init_entity(struct entity *ent) { node_init(&ent->node); - init_model(&ent->model); ent->casts_shadows = 1; return ent; } @@ -39,16 +38,18 @@ struct entity *get_entity_pure(struct entity_id id) { return get_entity(&pure_id); } -struct entity *get_entity(struct entity_id *id) { +struct entity *get_entity(struct entity_id *ent_id) { struct entity_id *new_id; + struct id *id = &ent_id->id; + // rollover is ok /* assert(->generation <= esys.generation); */ if (id->generation != esys.generation) { // try to find uuid in new memory layout for (u32 i = 0; i < esys.entity_count; i++) { new_id = &esys.ids[i]; - if (new_id->uuid == id->uuid) { - id->index = new_id->index; + if (new_id->id.uuid == id->uuid) { + id->index = new_id->id.index; id->generation = esys.generation; return &esys.entities[id->index]; } @@ -62,9 +63,11 @@ struct entity *get_entity(struct entity_id *id) { static inline struct entity_id new_id() { return (struct entity_id){ - .index = esys.entity_count, - .uuid = entity_uuids++, - .generation = esys.generation, + .id = (struct id) { + .index = esys.entity_count, + .uuid = entity_uuids++, + .generation = esys.generation, + } }; } @@ -88,8 +91,15 @@ struct entity *add_entity(struct entity *e, struct entity_id *id) { return new; } -void destroy_entity(struct entity *ent) { +void destroy_entities() { + for (u32 i = RESERVED_ENTITIES; i < esys.entity_count; i++) { + destroy_entity(&esys.entities[i]); + } + esys.entity_count = RESERVED_ENTITIES; +}; +void destroy_entity(struct entity *ent) { + node_detach_from_parent(&ent->node); } void destroy_entity_system() { diff --git a/src/entity.h b/src/entity.h @@ -4,6 +4,9 @@ #include "node.h" #include "model.h" +#include "id.h" + +#define RESERVED_ENTITIES 2 enum entity_flags { ENT_IS_PLAYER = 1 << 0, @@ -12,7 +15,7 @@ enum entity_flags { struct entity { struct node node; - struct model model; + struct model *model; u32 flags; float velocity[3]; float accel[3]; @@ -20,13 +23,11 @@ struct entity { }; struct entity_id { - u64 uuid; - u32 index; - u32 generation; + struct id id; }; struct entity *init_entity(struct entity *); -void delete_entities(); +void destroy_entities(); void destroy_entity(struct entity *); void init_entity_system(); struct entity *get_entity(struct entity_id *); diff --git a/src/game.h b/src/game.h @@ -2,7 +2,7 @@ #ifndef PA_GAME_H #define PA_GAME_H -#include "buffer.h" +#include "vbo.h" #include "entity.h" #include "fbo.h" #include "input.h" diff --git a/src/geometry.c b/src/geometry.c @@ -3,14 +3,18 @@ #include "util.h" #include <assert.h> +static struct geometry_manager geom_manager; + void -destroy_buffer_geometry(struct geometry *geom) { +destroy_buffer_geometry(struct geometry_id geom_id) { + struct geometry *geom = get_geometry(geom_id); + gpu_addr buffers[] = { - geom->vbos.vertex.handle, - geom->vbos.normal.handle, - geom->vbos.color.handle, - geom->vbos.index.handle, - geom->vbos.tex_coord.handle + geom->vertex.handle, + geom->normal.handle, + geom->color.handle, + geom->index.handle, + geom->tex_coord.handle }; /* void glDeleteVertexArrays(GLsizei n, const GLuint *arrays); */ /* glDisableVertexAttribArray(geom->buffer.vertex_buffer.handle); */ @@ -23,25 +27,27 @@ destroy_buffer_geometry(struct geometry *geom) { glDeleteBuffers(ARRAY_SIZE(buffers), buffers); check_gl(); + + geom->has_vbos = 0; } void bind_geometry(struct geometry *geom, struct attributes *attrs) { - bind_vbo(&geom->vbos.vertex, attrs->position); + bind_vbo(&geom->vertex, attrs->position); check_gl(); - if (geom->vbos.normal.handle && attrs->normal != 0xFFFFFFFF) { - bind_vbo(&geom->vbos.normal, attrs->normal); + if (geom->normal.handle && attrs->normal != 0xFFFFFFFF) { + bind_vbo(&geom->normal, attrs->normal); check_gl(); } - if (geom->vbos.color.handle && attrs->color != 0xFFFFFFFF) { - bind_vbo(&geom->vbos.color, attrs->color); + if (geom->color.handle && attrs->color != 0xFFFFFFFF) { + bind_vbo(&geom->color, attrs->color); check_gl(); } - if (geom->vbos.tex_coord.handle && attrs->tex_coord != 0xFFFFFFFF) { - bind_vbo(&geom->vbos.tex_coord, attrs->tex_coord); + if (geom->tex_coord.handle && attrs->tex_coord != 0xFFFFFFFF) { + bind_vbo(&geom->tex_coord, attrs->tex_coord); check_gl(); } - bind_ibo(&geom->vbos.index); + bind_ibo(&geom->index); check_gl(); } @@ -62,7 +68,7 @@ void render_geometry(struct geometry *geom, struct attributes *attrs, int type = GL_TRIANGLES; //check_for_patches(program, &type); bind_geometry(geom, attrs); - if (geom->indices) { + if (geom->num_indices) { glDrawElements(type, geom->num_indices, /* count */ GL_UNSIGNED_INT, /* type */ @@ -77,26 +83,36 @@ void render_geometry(struct geometry *geom, struct attributes *attrs, } } +void init_make_geometry(struct make_geometry *mkgeom) { + mkgeom->colors = NULL; + mkgeom->normals = NULL; + mkgeom->indices = NULL; + mkgeom->vertices = NULL; + mkgeom->tex_coords = NULL; + mkgeom->num_uv_components = 2; + mkgeom->num_verts = 0; + mkgeom->num_indices = 0; +} void init_geometry(struct geometry *geom) { - geom->colors = NULL; - geom->normals = NULL; - geom->indices = NULL; - geom->vertices = NULL; - geom->tex_coords = NULL; - geom->num_uv_components = 2; geom->has_vbos = 0; - - geom->vbos.color.handle = 0; - geom->vbos.normal.handle = 0; - geom->vbos.tex_coord.handle = 0; + init_vbo(&geom->vertex); + init_vbo(&geom->color); + init_vbo(&geom->normal); + init_vbo(&geom->tex_coord); + init_vbo(&geom->index); } void -make_buffer_geometry(struct geometry *geom) { +make_buffer_geometry_(struct make_geometry *mkgeom, struct geometry *geom) { + + // VBOs + geom->num_uv_components = mkgeom->num_uv_components; + geom->num_verts = mkgeom->num_verts; + geom->num_indices = mkgeom->num_indices; - assert(geom->vertices); + assert(mkgeom->vertices); /* assert(geom->normals); */ /* assert(geom->indices); */ /* assert(geom->num_indices >= 1); */ @@ -104,61 +120,100 @@ make_buffer_geometry(struct geometry *geom) { /* printf("making vertex buffer\n"); */ make_vertex_buffer( GL_ARRAY_BUFFER, - geom->vertices, - geom->num_verts * 3 * (int)sizeof(*geom->vertices), - &geom->vbos.vertex + mkgeom->vertices, + mkgeom->num_verts * 3 * (int)sizeof(*mkgeom->vertices), + &geom->vertex ); /* printf("making normal buffer\n"); */ // cube normals - if (geom->normals != NULL) + if (mkgeom->normals != NULL) make_vertex_buffer( GL_ARRAY_BUFFER, - geom->normals, - geom->num_verts * 3 * (int)sizeof(*geom->normals), - &geom->vbos.normal + mkgeom->normals, + mkgeom->num_verts * 3 * (int)sizeof(*mkgeom->normals), + &geom->normal ); // vertex colors - if (geom->colors != NULL) + if (mkgeom->colors != NULL) make_vertex_buffer( GL_ARRAY_BUFFER, - geom->colors, - geom->num_verts * 3 * (int)sizeof(*geom->colors), - &geom->vbos.color + mkgeom->colors, + mkgeom->num_verts * 3 * (int)sizeof(*mkgeom->colors), + &geom->color ); - if (geom->tex_coords != NULL) { + if (mkgeom->tex_coords != NULL) { assert(geom->num_uv_components); printf("%f %f %f %f\n", - geom->tex_coords[0], - geom->tex_coords[1], - geom->tex_coords[2], - geom->tex_coords[3] + mkgeom->tex_coords[0], + mkgeom->tex_coords[1], + mkgeom->tex_coords[2], + mkgeom->tex_coords[3] ); make_uv_buffer(GL_ARRAY_BUFFER, - geom->tex_coords, - geom->num_verts * geom->num_uv_components * (int)sizeof(*geom->tex_coords), - &geom->vbos.tex_coord, geom->num_uv_components); + mkgeom->tex_coords, + mkgeom->num_verts * mkgeom->num_uv_components * (int)sizeof(*mkgeom->tex_coords), + &geom->tex_coord, geom->num_uv_components); } /* printf("making index buffer\n"); */ // cube indices - if (geom->indices) + if (mkgeom->indices) make_index_buffer( GL_ELEMENT_ARRAY_BUFFER, - geom->indices, - geom->num_indices * (int)sizeof(*geom->indices), - &geom->vbos.index + mkgeom->indices, + mkgeom->num_indices * (int)sizeof(*mkgeom->indices), + &geom->index ); geom->has_vbos = 1; } +struct geometry_id +make_buffer_geometry(struct make_geometry *mkgeom) { + struct geometry_id geom_id; + struct geometry *geom = new_geometry(&geom_id); + + make_buffer_geometry_(mkgeom, geom); + return geom_id; +} + void geometry_centroid(struct geometry *geom, float *dest) { vec3_subtract(geom->max, geom->min, dest); vec3_scale(dest, 0.5, dest); }; + +void init_geometry_manager() { + geom_manager.num_geometry = 0; +} + +struct geometry *get_geometry(struct geometry_id geom_id) { + assert(geom_id.index != -1); + assert(geom_id.index < geom_manager.num_geometry); + return &geom_manager.geoms[geom_id.index]; +} + + +struct geometry *new_geometry(struct geometry_id *geom_id) { + u32 index = geom_manager.num_geometry++; + struct geometry *g = &geom_manager.geoms[index]; + init_geometry(g); + if (geom_id) + geom_id->index = index; + + return g; +} + +void init_geometry_id(struct geometry_id *id) { + id->index = -1; +} + +struct geometry *get_all_geometry(u32 *count) { + *count = geom_manager.num_geometry; + return &geom_manager.geoms[0]; +} diff --git a/src/geometry.h b/src/geometry.h @@ -3,38 +3,63 @@ #define GEOMETRY_H #include "common.h" -#include "buffer.h" +#include "vbo.h" #include "shader.h" +#include "id.h" -struct buffer_geometry { +#define MAX_GEOMETRY 64 + +// -1 is uninitialized +struct geometry_id { + struct id id; +}; + +struct geometry { struct vbo vertex; struct vbo index; struct vbo normal; struct vbo color; struct vbo tex_coord; -}; -struct geometry { - struct buffer_geometry vbos; - int has_vbos; float min[3]; float max[3]; + + int has_vbos; int num_uv_components; int num_indices; int num_verts; +}; + +struct make_geometry { float *vertices; float *normals; - u32 *indices; float *colors; + int num_verts; + + u32 *indices; + int num_indices; + float *tex_coords; + int num_uv_components; +}; + +struct geometry_manager { + struct geometry geoms[MAX_GEOMETRY]; + int num_geometry; }; void render_geometry(struct geometry *geom, struct attributes *, struct gpu_program *current_program); void bind_geometry(struct geometry *geom, struct attributes *); void init_geometry(struct geometry *geom); -void make_buffer_geometry(struct geometry *geom); +void init_make_geometry(struct make_geometry *mkgeom); +struct geometry_id make_buffer_geometry(struct make_geometry *mkgeom); void destroy_buffer_geometry(struct geometry *geom); void geometry_centroid(struct geometry *geom, float *v3); +void init_geometry_manager(); +void init_geometry_id(struct geometry_id *); +struct geometry *new_geometry(struct geometry_id *); +struct geometry *get_geometry(struct geometry_id); +struct geometry *get_all_geometry(u32 *count); #endif /* GEOMETRY_H */ diff --git a/src/id.h b/src/id.h @@ -0,0 +1,13 @@ + +#ifndef ID_H +#define ID_H + +#include "common.h" + +struct id { + u64 uuid; + u32 index; + u32 generation; +}; + +#endif /* ID_H */ diff --git a/src/main.c b/src/main.c @@ -58,7 +58,8 @@ int main(void) SDL_GL_CreateContext(window); game_init(&game, width, height); - default_scene(&game); + /* reset_scene(&game); */ + /* pbr_scene(&game); */ check_gl(); double last = hires_time_in_seconds(); diff --git a/src/model.c b/src/model.c @@ -1,26 +1,51 @@ #include "model.h" #include "ply.h" +#include <assert.h> + +#define MODELDEF(name) { .id = model_##name, .loaded = 0, .file = #name } + +static struct model_def static_models[NUM_STATIC_MODELS] = { + MODELDEF(tower), + MODELDEF(icosphere), + MODELDEF(pirateofficer), +}; + +static int static_models_initialized = 0; void init_model(struct model *model) { model->shading = SHADING_VERT_COLOR; model->texture = 0; - init_geometry(&model->geom); + init_geometry_id(&model->geom_id); } -int load_model(struct model *model, const char *name) { +static void initialize_static_models() { + for (int i = 0; i < NUM_STATIC_MODELS; i++) { + struct model_def *sm = &static_models[i]; + assert(sm->id == i); + init_model(&sm->model); + } + static_models_initialized = 1; +} + +struct model *get_model(enum static_model m) { static char path[128] = {0}; - if (model->geom.has_vbos) - return 2; + if (!static_models_initialized) + initialize_static_models(); + + struct model *model = &static_models[m].model; + + if (model->geom_id.index >= 0) + return model; int ok = 0; // Load mesh - snprintf(path, 128, "data/models/%s.ply", name); - ok = parse_ply(path, &model->geom); + snprintf(path, 128, "data/models/%s.ply", static_models[m].file); + ok = parse_ply(path, &model->geom_id); if (!ok) return 0; - return 1; + return model; } diff --git a/src/model.h b/src/model.h @@ -8,7 +8,14 @@ #include "geometry.h" #include "common.h" -#define MAX_MODELS 128 +#define MAX_STATIC_MODELS 128 + +enum static_model { + model_tower, + model_icosphere, + model_pirateofficer, + NUM_STATIC_MODELS +}; enum shading { SHADING_TERRAIN, @@ -17,14 +24,21 @@ enum shading { }; struct model { - struct geometry geom; + struct geometry_id geom_id; enum shading shading; u32 texture; }; +struct model_def { + u16 id; + int loaded; + char *file; + struct model model; +}; + void init_model(struct model *model); -int load_model(struct model *model, const char *name); +struct model *get_model(enum static_model); #endif /* MODEL_H */ diff --git a/src/node.c b/src/node.c @@ -115,7 +115,6 @@ int node_recalc(struct node *node) { return 1; } - int node_detach(struct node *node, struct node *from) { for (int i = 0; i < from->n_children; i++) { if (from->children[i] == node) { @@ -128,6 +127,20 @@ int node_detach(struct node *node, struct node *from) { return 0; } +void node_detach_from_parent(struct node *node) { + if (node->parent) + node_detach(node, node->parent); +} + +// count the total number of nodes +int node_count(struct node *node) { + int c = 1; + for (int i = 0; i < node->n_children; i++) { + c += node_count(node->children[i]); + } + return c; +} + void node_attach(struct node *node, struct node *to) { assert(to->n_children <= MAX_NODE_CHILDREN); diff --git a/src/node.h b/src/node.h @@ -27,6 +27,7 @@ struct node { int node_recalc(struct node *root); void node_attach(struct node *node, struct node *to); int node_detach(struct node *node, struct node *from); +void node_detach_from_parent(struct node *node); void node_mark_for_recalc(struct node *node); struct node *node_init(struct node *node); void node_translate(struct node *node, float *p); @@ -34,6 +35,7 @@ void node_forward(struct node *node, float *p); void node_forward_dir(struct node *node, float *orientation, float *p); void node_rotate(struct node *node, float *p); void node_scale(struct node *node, float val); +int node_count(struct node *node); float *node_world(struct node *node); #endif /* POLYADVENT_NODE_H */ diff --git a/src/ply.c b/src/ply.c @@ -105,7 +105,7 @@ static int parse_magic(const char **cursor) { } -int parse_ply(const char *filename, struct geometry *geom) { +int parse_ply(const char *filename, struct geometry_id *geom_id) { size_t len; int success = 0; int nverts = 0; @@ -118,8 +118,10 @@ int parse_ply(const char *filename, struct geometry *geom) { enum ply_state state = PLY_MAGIC; const char *data = file_contents(filename, &len); const char *p = data; + struct make_geometry mkgeom; + init_make_geometry(&mkgeom); - float vert[3], norm[3]; + float vert[3], norm[3], min[3], max[3]; int inds[3]; u8 color[3]; @@ -144,10 +146,10 @@ int parse_ply(const char *filename, struct geometry *geom) { break; } - geom->vertices = calloc(nverts * 3, sizeof(*geom->vertices)); - geom->normals = calloc(nverts * 3, sizeof(*geom->normals)); - geom->colors = calloc(nverts * 3, sizeof(*geom->colors)); - geom->indices = calloc(ninds * 3, sizeof(*geom->indices)); + mkgeom.vertices = calloc(nverts * 3, sizeof(*mkgeom.vertices)); + mkgeom.normals = calloc(nverts * 3, sizeof(*mkgeom.normals)); + mkgeom.colors = calloc(nverts * 3, sizeof(*mkgeom.colors)); + mkgeom.indices = calloc(ninds * 3, sizeof(*mkgeom.indices)); state = PLY_VERTICES; } @@ -162,25 +164,25 @@ int parse_ply(const char *filename, struct geometry *geom) { // compute bounding box as we go if (cvert == 0) { - vec3_copy(vert, geom->min); - vec3_copy(vert, geom->max); + vec3_copy(vert, min); + vec3_copy(vert, max); } else { - vec3_min(vert, geom->min, geom->min); - vec3_max(vert, geom->max, geom->max); + vec3_min(vert, min, min); + vec3_max(vert, max, max); } - geom->vertices[cvert * 3] = vert[0]; - geom->vertices[cvert * 3 + 1] = vert[1]; - geom->vertices[cvert * 3 + 2] = vert[2]; + mkgeom.vertices[cvert * 3] = vert[0]; + mkgeom.vertices[cvert * 3 + 1] = vert[1]; + mkgeom.vertices[cvert * 3 + 2] = vert[2]; - geom->normals[cvert * 3] = norm[0]; - geom->normals[cvert * 3 + 1] = norm[1]; - geom->normals[cvert * 3 + 2] = norm[2]; + mkgeom.normals[cvert * 3] = norm[0]; + mkgeom.normals[cvert * 3 + 1] = norm[1]; + mkgeom.normals[cvert * 3 + 2] = norm[2]; - geom->colors[cvert * 3] = color[0] / 255.0; - geom->colors[cvert * 3 + 1] = color[1] / 255.0; - geom->colors[cvert * 3 + 2] = color[2] / 255.0; + mkgeom.colors[cvert * 3] = color[0] / 255.0; + mkgeom.colors[cvert * 3 + 1] = color[1] / 255.0; + mkgeom.colors[cvert * 3 + 2] = color[2] / 255.0; cvert++; @@ -196,9 +198,9 @@ int parse_ply(const char *filename, struct geometry *geom) { break; } - geom->indices[cind * 3] = inds[0]; - geom->indices[cind * 3 + 1] = inds[1]; - geom->indices[cind * 3 + 2] = inds[2]; + mkgeom.indices[cind * 3] = inds[0]; + mkgeom.indices[cind * 3 + 1] = inds[1]; + mkgeom.indices[cind * 3 + 2] = inds[2]; cind++; @@ -224,14 +226,19 @@ int parse_ply(const char *filename, struct geometry *geom) { free((void*)data); if (success) { + *geom_id = make_buffer_geometry(&mkgeom); + struct geometry *geom = + get_geometry(*geom_id); + + vec3_copy(min, geom->min); + vec3_copy(max, geom->max); geom->num_indices = ninds * 3; geom->num_verts = nverts * 3; - make_buffer_geometry(geom); - free(geom->vertices); - free(geom->normals); - free(geom->colors); - free(geom->indices); + free(mkgeom.vertices); + free(mkgeom.normals); + free(mkgeom.colors); + free(mkgeom.indices); } return success; diff --git a/src/ply.h b/src/ply.h @@ -5,6 +5,6 @@ #include "geometry.h" -int parse_ply(const char *filename, struct geometry *geom); +int parse_ply(const char *filename, struct geometry_id *geom_id); #endif /* PLYPARSER_H */ diff --git a/src/scene.c b/src/scene.c @@ -7,6 +7,8 @@ void reset_scene(struct game *game) { struct entity *terrain_ent = get_terrain_entity(&game->terrain); struct entity *player_ent = get_player(&game->test_resources); + destroy_entities(); + // hide terrain and player by default terrain_ent->flags |= ENT_INVISIBLE; player_ent->flags |= ENT_INVISIBLE; @@ -24,8 +26,7 @@ void default_scene(struct game *game) { player->flags &= ~ENT_INVISIBLE; struct entity *tower = new_entity(NULL); - int ok = load_model(&tower->model, "tower"); - assert(ok); + tower->model = get_model(model_tower); tower->node.label = "tower"; node_attach(&tower->node, &player->node); node_translate(&tower->node, V3(0.0, 50.0, 0.0)); @@ -39,5 +40,5 @@ void default_scene(struct game *game) { } void pbr_scene(struct game *game) { - + struct model *sphere = get_model(model_icosphere); } diff --git a/src/scene.h b/src/scene.h @@ -0,0 +1,11 @@ + +#ifndef SCENE_H +#define SCENE_H + +#include "game.h" + +void default_scene(struct game *); +void reset_scene(struct game *); +void pbr_scene(struct game *); + +#endif /* SCENE_H */ diff --git a/src/skybox.c b/src/skybox.c @@ -36,7 +36,6 @@ static u32 skybox_indices[] = { void create_skybox(struct skybox *skybox, struct gpu_program *program) { struct shader vertex, frag; struct shader *shaders[] = {&vertex, &frag}; - struct geometry *geom = &skybox->model.geom; int ok; node_init(&skybox->node); @@ -44,15 +43,19 @@ void create_skybox(struct skybox *skybox, struct gpu_program *program) { skybox->program = program; - geom->vertices = skybox_vertices; - geom->indices = skybox_indices; + struct make_geometry mkgeom; + init_make_geometry(&mkgeom); + + mkgeom.vertices = skybox_vertices; + mkgeom.indices = skybox_indices; /* geom->tex_coords = skybox_uvs; */ /* geom->num_uv_components = 3; */ - geom->num_verts = ARRAY_SIZE(skybox_vertices); - geom->num_indices = ARRAY_SIZE(skybox_indices); + mkgeom.num_verts = ARRAY_SIZE(skybox_vertices); + mkgeom.num_indices = ARRAY_SIZE(skybox_indices); - make_buffer_geometry(&skybox->model.geom); + skybox->model.geom_id = + make_buffer_geometry(&mkgeom); static const char *faces[6] = { CUBEMAP("hw_sahara/sahara_rt_flip.tga"), @@ -109,7 +112,7 @@ void render_skybox(struct skybox *skybox, mat4 *camera) { glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->model.texture); check_gl(); - render_geometry(&skybox->model.geom, &skybox->attrs, skybox->program); + render_geometry(get_geometry(skybox->model.geom_id), &skybox->attrs, skybox->program); check_gl(); glDepthMask(GL_TRUE); diff --git a/src/terrain.c b/src/terrain.c @@ -56,7 +56,8 @@ void init_terrain(struct terrain *terrain, float size) { ent = new_entity(&terrain->entity_id); assert(terrain->entity_id.uuid == 0); - ent->model.shading = SHADING_TERRAIN; + terrain->model.shading = SHADING_TERRAIN; + ent->model = &terrain->model; ent->node.label = "terrain_node"; ent->casts_shadows = 0; @@ -205,13 +206,16 @@ void create_terrain(struct terrain *terrain, float scale) { struct entity *ent = get_entity(&terrain->entity_id); assert(ent); - ent->model.geom.num_verts = num_verts; - ent->model.geom.vertices = (float*)del_verts; - ent->model.geom.normals = (float*)del_norms; - ent->model.geom.indices = (u32*)del_indices; - ent->model.geom.num_indices = num_verts; + struct make_geometry mkgeom; + init_make_geometry(&mkgeom); + mkgeom.num_verts = num_verts; + mkgeom.vertices = (float*)del_verts; + mkgeom.normals = (float*)del_norms; + mkgeom.indices = (u32*)del_indices; + mkgeom.num_indices = num_verts; - make_buffer_geometry(&ent->model.geom); + terrain->model.geom_id = + make_buffer_geometry(&mkgeom); delaunay2d_release(del); tri_delaunay2d_release(tri); @@ -227,5 +231,5 @@ void create_terrain(struct terrain *terrain, float scale) { void destroy_terrain(struct terrain *terrain) { struct entity *ent = get_entity(&terrain->entity_id); assert(ent); - destroy_buffer_geometry(&ent->model.geom); + destroy_buffer_geometry(get_geometry(terrain->model.geom_id)); } diff --git a/src/terrain.h b/src/terrain.h @@ -24,6 +24,7 @@ struct terrain { struct entity_id entity_id; struct perlin_settings settings; struct point *samples; + struct model model; double (*fn)(struct terrain *, double, double); int n_samples; double size; diff --git a/src/tests.c b/src/tests.c @@ -0,0 +1,35 @@ + +#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/ui.c b/src/ui.c @@ -1,7 +1,7 @@ #include "ui.h" #include "mat4.h" -#include "buffer.h" +#include "vbo.h" #include "geometry.h" #include "util.h" #include "common.h" @@ -34,18 +34,21 @@ static GLfloat quad_uvs[] = }; -static void create_quad(struct geometry *geom) +static struct geometry_id create_quad() { - init_geometry(geom); - geom->indices = quad_indices; - geom->vertices = quad_vertices; - geom->colors = quad_normals; - geom->tex_coords = quad_uvs; - geom->num_indices = ARRAY_SIZE(quad_indices); - geom->num_verts = ARRAY_SIZE(quad_vertices); - geom->num_uv_components = 2; - make_buffer_geometry(geom); + struct make_geometry mkgeom = { + .indices = quad_indices, + .vertices = quad_vertices, + .normals = quad_normals, + .tex_coords = quad_uvs, + .num_indices = ARRAY_SIZE(quad_indices), + .num_verts = ARRAY_SIZE(quad_vertices), + .num_uv_components = 2 + }; + struct geometry_id id = make_buffer_geometry(&mkgeom); check_gl(); + + return id; } void render_ui(struct ui *ui, float *view) { diff --git a/src/vbo.c b/src/vbo.c @@ -0,0 +1,78 @@ + +#include "vbo.h" +#include "util.h" +#include <assert.h> +#include "gl.h" + +gpu_addr +make_buffer(GLenum target, const void *buffer_data, GLsizei buffer_size) { + gpu_addr buffer; + check_gl(); + glGenBuffers(1, &buffer); + check_gl(); + + glBindBuffer(target, buffer); + check_gl(); + + glBufferData(target, buffer_size, buffer_data, GL_STATIC_DRAW); + check_gl(); + + return buffer; +} + +struct vbo* +make_index_buffer(GLenum target, const void *data, GLsizei buffer_size, + struct vbo *vbo) { + vbo->components = 3; + vbo->handle = make_buffer(target, data, buffer_size); + vbo->type = GL_ELEMENT_ARRAY_BUFFER; + return vbo; +} + + +struct vbo* +make_vertex_buffer(GLenum target, const void *data, + GLsizei buffer_size, struct vbo *vbo) { + vbo->components = 3; + vbo->handle = make_buffer(target, data, buffer_size); + vbo->type = GL_ARRAY_BUFFER; + return vbo; +} + +struct vbo* +make_uv_buffer(GLenum target, const void *data, + GLsizei buffer_size, struct vbo *vbo, int components) { + vbo->components = components; + vbo->handle = make_buffer(target, data, buffer_size); + vbo->type = GL_ARRAY_BUFFER; + return vbo; +} + +void bind_ibo(struct vbo *vbo) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->handle); +} + +struct vbo* init_vbo(struct vbo *vbo) { + vbo->type = 0; + vbo->handle = 0; + vbo->components = 0; + return vbo; +} + +static void bind_vbo_internal(struct vbo *vbo, gpu_addr slot) { + glEnableVertexAttribArray(slot); + check_gl(); + glBindBuffer(vbo->type, vbo->handle); + check_gl(); + glVertexAttribPointer(slot, // attribute + vbo->components, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); +} + +void bind_vbo(struct vbo *vbo, gpu_addr slot) { + bind_vbo_internal(vbo, slot); +} diff --git a/src/vbo.h b/src/vbo.h @@ -0,0 +1,45 @@ +#ifndef POLYADVENT_BUFFER_H +#define POLYADVENT_BUFFER_H + +#include "gl.h" +#include "common.h" + +typedef GLuint gpu_addr; + +struct attributes { + gpu_addr position; + gpu_addr normal; + gpu_addr color; + gpu_addr tex_coord; +}; + +struct vbo { + u32 type; + int components; + gpu_addr handle; +}; + +#define NUM_VBO_SLOTS 1 + +gpu_addr make_buffer(GLenum target, const void *buffer_data, + GLsizei buffer_size); + +struct vbo *init_vbo(struct vbo *); + +struct vbo * +make_vertex_buffer(GLenum target, const void *buffer_data, + GLsizei buffer_size, struct vbo *vbo); + +struct vbo * +make_index_buffer(GLenum target, const void *buffer_data, + GLsizei buffer_size, struct vbo *vbo); + +struct vbo * +make_uv_buffer(GLenum target, const void *data, + GLsizei buffer_size, struct vbo *vbo, int components); + +void bind_uv_vbo(struct vbo *vbo, gpu_addr slot); +void bind_vbo(struct vbo *vbo, gpu_addr slot); +void bind_ibo(struct vbo *vbo); + +#endif /* POLYADVENT_BUFFER_H */