#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;
return -1;
}
- /* DBG */
- if(load_scenefile(&scn, "data/dwall1.obj") == -1) {
- return -1;
- }
-
return 0;
}
void game_display(void)
{
- struct mesh *mesh;
-
glClearColor(0.1, 0.1, 0.1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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)
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);
}
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++;
}
}
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;
+}
#include "scenefile.h"
enum {
+ TILE_EMPTY,
TILE_STRAIGHT,
TILE_CORNER,
TILE_DOOR
int wall[4];
int floor, ceil;
- struct meshgroup mgrp;
+ struct meshgroup *mgrp;
+ int num_mgrp;
+
+ struct cell *next;
};
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;
};
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_ */
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);
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);
+ }
+}
};
struct meshgroup {
+ /* doesn't own the meshes */
struct mesh **meshes;
int num_meshes, max_meshes;
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);
void draw_mesh(struct mesh *m);
void draw_meshgroup(struct meshgroup *mg);
+void xform_mesh(struct mesh *mesh, float *mat);
+
#endif /* MESH_H_ */