started on the level geometry
authorJohn Tsiombikas <nuclear@member.fsf.org>
Wed, 15 Sep 2021 09:18:47 +0000 (12:18 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Wed, 15 Sep 2021 09:18:47 +0000 (12:18 +0300)
src/game.c
src/level.c
src/level.h
src/mesh.c
src/mesh.h

index 42a95f9..8ee1989 100644 (file)
@@ -6,8 +6,9 @@
 #include "scenefile.h"
 #include "sdr.h"
 
+static void draw_level(void);
+
 struct level lvl;
-struct scenefile scn;
 
 int win_width, win_height;
 float win_aspect;
@@ -41,11 +42,6 @@ int game_init(void)
                return -1;
        }
 
-       /* DBG */
-       if(load_scenefile(&scn, "data/dwall1.obj") == -1) {
-               return -1;
-       }
-
        return 0;
 }
 
@@ -57,8 +53,6 @@ void game_shutdown(void)
 
 void game_display(void)
 {
-       struct mesh *mesh;
-
        glClearColor(0.1, 0.1, 0.1, 1);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
@@ -68,24 +62,36 @@ void game_display(void)
        glLoadMatrixf(proj_matrix);
 
        cgm_midentity(view_matrix);
-       cgm_mpretranslate(view_matrix, 0, 1.5, -cam_dist);
+       cgm_mpretranslate(view_matrix, 0, -1.7, -cam_dist);
        cgm_mprerotate(view_matrix, cam_phi, 1, 0, 0);
        cgm_mprerotate(view_matrix, cam_theta, 0, 1, 0);
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(view_matrix);
 
+       draw_level();
+
+       game_swap_buffers();
+       assert(glGetError() == GL_NO_ERROR);
+}
+
+static void draw_level(void)
+{
+       int i, j, k;
+       struct cell *cell;
+
        glUseProgram(sdr_foo);
 
-       mesh = scn.meshlist;
-       while(mesh) {
-               draw_mesh(mesh);
-               mesh = mesh->next;
+       cell = lvl.cells;
+       for(i=0; i<lvl.height; i++) {
+               for(j=0; j<lvl.width; j++) {
+                       for(k=0; k<cell->num_mgrp; k++) {
+                               draw_meshgroup(cell->mgrp + k);
+                       }
+                       cell++;
+               }
        }
 
        glUseProgram(0);
-
-       game_swap_buffers();
-       assert(glGetError() == GL_NO_ERROR);
 }
 
 void game_reshape(int x, int y)
index 9e5fe44..70af648 100644 (file)
@@ -30,7 +30,7 @@ void destroy_level(struct level *lvl)
 int load_level(struct level *lvl, const char *fname)
 {
        struct ts_node *ts, *node, *iter;
-       int sz, cx, cy;
+       int i, j, sz, cx, cy;
        struct cell *cell;
 
        lvl->fname = strdup(fname);
@@ -75,7 +75,40 @@ int load_level(struct level *lvl, const char *fname)
                        }
                        cell = lvl->cells + cy * sz + cx;
                        cell->type = ts_get_attr_int(node, "blocked", 0) ? CELL_BLOCKED : CELL_WALK;
-                       /* TODO wall tiles and detail objects */
+
+                       /* abuse the next pointer to hang the treestore node temporarilly */
+                       cell->next = (struct cell*)node;
+               }
+       }
+
+       /* assign wall types to all occupied cells */
+       cell = lvl->cells;
+       for(i=0; i<lvl->height; i++) {
+               for(j=0; j<lvl->width; j++) {
+                       if(cell->type == CELL_SOLID) {
+                               cell++;
+                               continue;
+                       }
+
+                       /* TODO take wall choice from the level file into account */
+                       /* TODO detect corners */
+                       node = (struct ts_node*)cell->next;
+                       cell->next = 0;
+
+                       if(j <= 0 || cell[-1].type == CELL_SOLID) {
+                               cell->wall[0] = TILE_STRAIGHT;
+                       }
+                       if(i <= 0 || cell[-lvl->width].type == CELL_SOLID) {
+                               cell->wall[1] = TILE_STRAIGHT;
+                       }
+                       if(j >= lvl->width - 1 || cell[1].type == CELL_SOLID) {
+                               cell->wall[2] = TILE_STRAIGHT;
+                       }
+                       if(i >= lvl->height - 1 || cell[lvl->width].type == CELL_SOLID) {
+                               cell->wall[3] = TILE_STRAIGHT;
+                       }
+
+                       cell++;
                }
        }
 
@@ -203,3 +236,92 @@ static int load_tileset(struct level *lvl, struct ts_node *tsn)
 
        return 0;
 }
+
+struct tile *find_level_tile(struct level *lvl, const char *tname)
+{
+       struct tile *tile = lvl->tiles;
+       while(tile) {
+               if(strcmp(tile->name, tname) == 0) {
+                       return tile;
+               }
+               tile = tile->next;
+       }
+       return 0;
+}
+
+int gen_cell_geom(struct level *lvl, struct cell *cell)
+{
+       int i;
+       struct meshgroup *wallgeom;
+       struct tile *tstr;
+       struct mesh *mesh, *tmesh;
+       float xform[16];
+
+       printf("foo!\n");
+
+       if(!(tstr = find_level_tile(lvl, "straight"))) {
+               return -1;
+       }
+
+       if(!(wallgeom = malloc(sizeof *wallgeom))) {
+               return -1;
+       }
+       init_meshgroup(wallgeom);
+
+       for(i=0; i<4; i++) {
+               if(cell->wall[i] == TILE_STRAIGHT) {    /* TODO: support other wall types */
+                       cgm_mrotation_y(xform, i * M_PI / 2.0f);
+
+                       tmesh = tstr->scn.meshlist;
+                       while(tmesh) {
+                               if(!(mesh = malloc(sizeof *mesh))) {
+                                       return -1;
+                               }
+
+                               /* create a copy of the tile mesh */
+                               if(copy_mesh(mesh, tmesh) == -1) {
+                                       free(mesh);
+                                       return -1;
+                               }
+                               if(i) xform_mesh(mesh, xform);  /* rotate it to match the wall angle */
+
+                               /* add it to the level meshlist */
+                               mesh->next = lvl->meshlist;
+                               lvl->meshlist = mesh;
+
+                               /* add it to the meshgroup */
+                               if(add_meshgroup_mesh(wallgeom, mesh) == -1) {
+                                       destroy_mesh(mesh);
+                                       free(mesh);
+                                       return -1;
+                               }
+
+                               tmesh = tmesh->next;
+                       }
+               }
+       }
+
+       /* TODO: append to other existing meshgroups for detail objects */
+       cell->mgrp = wallgeom;
+       cell->num_mgrp = 1;
+
+       return 0;
+}
+
+int gen_level_geom(struct level *lvl)
+{
+       int i, j;
+       struct cell *cell;
+
+       for(i=0; i<lvl->height; i++) {
+               for(j=0; j<lvl->width; j++) {
+                       cell = lvl->cells + i * lvl->width + j;
+                       if(cell->type != CELL_SOLID) {
+                               if(gen_cell_geom(lvl, cell) == -1) {
+                                       return -1;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
index 6a57dc2..53eb9c1 100644 (file)
@@ -4,6 +4,7 @@
 #include "scenefile.h"
 
 enum {
+       TILE_EMPTY,
        TILE_STRAIGHT,
        TILE_CORNER,
        TILE_DOOR
@@ -27,7 +28,10 @@ struct cell {
        int wall[4];
        int floor, ceil;
 
-       struct meshgroup mgrp;
+       struct meshgroup *mgrp;
+       int num_mgrp;
+
+       struct cell *next;
 };
 
 struct level {
@@ -37,6 +41,11 @@ struct level {
        struct cell *cells;
 
        struct tile *tiles;
+
+       /* meshes owned by the level, constructed during geometry generation or
+        * loaded, excluding meshes in tiles scenefiles
+        */
+       struct mesh *meshlist;
 };
 
 
@@ -46,6 +55,9 @@ void destroy_level(struct level *lvl);
 int load_level(struct level *lvl, const char *fname);
 int save_level(struct level *lvl, const char *fname);
 
+struct tile *find_level_tile(struct level *lvl, const char *tname);
+
+int gen_cell_geom(struct level *lvl, struct cell *cell);
 int gen_level_geom(struct level *lvl);
 
 #endif /* LEVEL_H_ */
index 538f7c9..dbafcbd 100644 (file)
@@ -39,6 +39,34 @@ void clear_mesh(struct mesh *m)
        m->bbvalid = m->vbovalid = 0;
 }
 
+int copy_mesh(struct mesh *dest, struct mesh *src)
+{
+       init_mesh(dest);
+
+       if(src->max_verts && !(dest->varr = malloc(src->max_verts * sizeof *dest->varr))) {
+               return -1;
+       }
+       if(src->max_idx && !(dest->iarr = malloc(src->max_idx * sizeof *dest->iarr))) {
+               free(dest->varr);
+               dest->varr = 0;
+               return -1;
+       }
+
+       dest->num_verts = src->num_verts;
+       dest->max_verts = src->max_verts;
+       if(dest->varr) {
+               memcpy(dest->varr, src->varr, src->num_verts * sizeof *dest->varr);
+       }
+
+       dest->num_idx = src->num_idx;
+       dest->max_idx = src->max_idx;
+       if(dest->iarr) {
+               memcpy(dest->iarr, src->iarr, src->num_idx * sizeof *dest->iarr);
+       }
+
+       return 0;
+}
+
 void init_meshgroup(struct meshgroup *mg)
 {
        memset(mg, 0, sizeof *mg);
@@ -333,3 +361,17 @@ static int update_meshgroup_vbo(struct meshgroup *mg)
        free(iarr);
        return 0;
 }
+
+void xform_mesh(struct mesh *mesh, float *mat)
+{
+       int i;
+
+       mesh->vbovalid = 0;
+       mesh->bbvalid = 0;
+
+       for(i=0; i<mesh->num_verts; i++) {
+               cgm_vmul_v3m4(&mesh->varr[i].pos, mat);
+               cgm_vmul_v3m3(&mesh->varr[i].norm, mat);
+               cgm_vmul_v3m3(&mesh->varr[i].tang, mat);
+       }
+}
index b0a0a4b..1f94a8e 100644 (file)
@@ -56,6 +56,7 @@ struct mesh {
 };
 
 struct meshgroup {
+       /* doesn't own the meshes */
        struct mesh **meshes;
        int num_meshes, max_meshes;
 
@@ -70,6 +71,7 @@ struct meshgroup {
 void init_mesh(struct mesh *m);
 void destroy_mesh(struct mesh *m);
 void clear_mesh(struct mesh *m);
+int copy_mesh(struct mesh *dest, struct mesh *src);
 
 void init_meshgroup(struct meshgroup *mg);
 void destroy_meshgroup(struct meshgroup *mg);
@@ -86,4 +88,6 @@ int add_meshgroup_mesh(struct meshgroup *mg, struct mesh *m);
 void draw_mesh(struct mesh *m);
 void draw_meshgroup(struct meshgroup *mg);
 
+void xform_mesh(struct mesh *mesh, float *mat);
+
 #endif /* MESH_H_ */