8 static struct material *add_material(struct level *lvl, struct material *mtl);
9 static int append_polygons(struct bvhnode *bnode, struct triangle *faces, int num_faces, struct material *mtl);
11 int load_level(struct level *lvl, const char *fname)
15 struct ts_node *root, *node;
20 memset(lvl, 0, sizeof *lvl);
21 if(!(lvl->st_root = calloc(1, sizeof *lvl->st_root)) ||
22 !(lvl->dyn_root = calloc(1, sizeof *lvl->dyn_root))) {
24 fprintf(stderr, "load_level: failed to allocate bvh root nodes\n");
28 cgm_vcons(&lvl->st_root->aabb.vmin, FLT_MAX, FLT_MAX, FLT_MAX);
29 cgm_vcons(&lvl->st_root->aabb.vmax, -FLT_MAX, -FLT_MAX, -FLT_MAX);
30 lvl->dyn_root->aabb = lvl->st_root->aabb;
32 dirname = alloca(strlen(fname) + 1);
33 strcpy(dirname, fname);
34 if((ptr = strrchr(dirname, '/'))) {
40 if(!(root = ts_load(fname))) {
41 fprintf(stderr, "load_level: failed to load: %s\n", fname);
44 if(strcmp(root->name, "level") != 0) {
45 fprintf(stderr, "load_level: invalid level file %s, root is not \"level\"\n", fname);
50 node = root->child_list;
52 if(strcmp(node->name, "scene") == 0) {
53 if(!(fname = ts_get_attr_str(node, "file", 0))) {
54 fprintf(stderr, "load_level: ignoring \"scene\" without a \"file\" attribute\n");
57 snprintf(path, sizeof path, "%s%s", dirname, fname);
58 printf("loading scene file: %s\n", path);
60 if(load_scenefile(&scn, path) == -1) {
65 mtl = add_material(lvl, &mesh->mtl);
66 append_polygons(lvl->st_root, mesh->faces, mesh->num_faces, mtl);
70 destroy_scenefile(&scn);
72 cont: node = node->next;
79 void destroy_level(struct level *lvl)
81 free_bvh_tree(lvl->st_root);
82 free_bvh_tree(lvl->dyn_root);
87 int ray_level(cgm_ray *ray, struct level *lvl, float tmax, struct rayhit *hit)
92 static void draw_level_rec(struct bvhnode *bn)
96 struct material *curmtl;
97 float color[4] = {0, 0, 0, 1};
103 glBegin(GL_TRIANGLES);
104 for(i=0; i<bn->num_faces; i++) {
105 if(tri->mtl != curmtl) {
107 color[0] = tri->mtl->color.x;
108 color[1] = tri->mtl->color.y;
109 color[2] = tri->mtl->color.z;
110 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
112 glBegin(GL_TRIANGLES);
116 glNormal3fv(&tri->v[j].norm.x);
117 glTexCoord2fv(&tri->v[j].tex.x);
118 glVertex3fv(&tri->v[j].pos.x);
132 void draw_level(struct level *lvl)
134 draw_level_rec(lvl->st_root);
135 draw_level_rec(lvl->dyn_root);
138 static struct material *add_material(struct level *lvl, struct material *mtl)
141 struct material *tmp;
143 for(i=0; i<lvl->num_mtls; i++) {
144 if(memcmp(lvl->mtls + i, mtl, sizeof *mtl) == 0) {
145 return lvl->mtls + i;
149 if(lvl->num_mtls >= lvl->max_mtls) {
150 newsz = lvl->max_mtls ? lvl->max_mtls * 2 : 16;
151 if(!(tmp = realloc(lvl->mtls, newsz * sizeof *lvl->mtls))) {
152 fprintf(stderr, "add_material: failed to resize materials array to %d\n", newsz);
156 lvl->max_mtls = newsz;
158 lvl->mtls[lvl->num_mtls] = *mtl;
160 return lvl->mtls + lvl->num_mtls++;
163 static int append_polygons(struct bvhnode *bnode, struct triangle *faces, int num_faces, struct material *mtl)
166 struct triangle *tri;
168 newsz = bnode->num_faces + num_faces;
169 if(!(tri = realloc(bnode->faces, newsz * sizeof *bnode->faces))) {
170 fprintf(stderr, "append_polygons: failed to resize faces array to %d\n", newsz);
174 tri += bnode->num_faces;
175 bnode->num_faces = newsz;
177 for(i=0; i<num_faces; i++) {
182 cgm_vec3 *p = &tri->v[j].pos;
183 if(p->x < bnode->aabb.vmin.x) bnode->aabb.vmin.x = p->x;
184 if(p->x > bnode->aabb.vmax.x) bnode->aabb.vmax.x = p->x;
185 if(p->y < bnode->aabb.vmin.y) bnode->aabb.vmin.y = p->y;
186 if(p->y > bnode->aabb.vmax.y) bnode->aabb.vmax.y = p->y;
187 if(p->z < bnode->aabb.vmin.z) bnode->aabb.vmin.z = p->z;
188 if(p->z > bnode->aabb.vmax.z) bnode->aabb.vmax.z = p->z;