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)
93 if(ray_bvhnode(ray, lvl->st_root, tmax, 0)) return 1;
94 if(ray_bvhnode(ray, lvl->dyn_root, tmax, 0)) return 1;
99 if(ray_bvhnode(ray, lvl->st_root, tmax, hit)) {
103 if(ray_bvhnode(ray, lvl->dyn_root, tmax, hit) && hit->t < hit0.t) {
115 static void draw_level_rec(struct bvhnode *bn)
118 struct triangle *tri;
119 struct material *curmtl;
120 float color[4] = {0, 0, 0, 1};
128 glBegin(GL_TRIANGLES);
129 for(i=0; i<bn->num_faces; i++) {
130 if(tri->mtl != curmtl) {
132 color[0] = tri->mtl->color.x;
133 color[1] = tri->mtl->color.y;
134 color[2] = tri->mtl->color.z;
135 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
137 glBegin(GL_TRIANGLES);
141 glNormal3fv(&tri->v[j].norm.x);
142 glTexCoord2fv(&tri->v[j].tex.x);
143 glVertex3fv(&tri->v[j].pos.x);
150 draw_level_rec(bn->left);
151 draw_level_rec(bn->right);
154 void draw_level(struct level *lvl)
156 draw_level_rec(lvl->st_root);
157 draw_level_rec(lvl->dyn_root);
160 static struct material *add_material(struct level *lvl, struct material *mtl)
163 struct material *tmp;
165 for(i=0; i<lvl->num_mtls; i++) {
166 if(memcmp(lvl->mtls + i, mtl, sizeof *mtl) == 0) {
167 return lvl->mtls + i;
171 if(lvl->num_mtls >= lvl->max_mtls) {
172 newsz = lvl->max_mtls ? lvl->max_mtls * 2 : 16;
173 if(!(tmp = realloc(lvl->mtls, newsz * sizeof *lvl->mtls))) {
174 fprintf(stderr, "add_material: failed to resize materials array to %d\n", newsz);
178 lvl->max_mtls = newsz;
180 lvl->mtls[lvl->num_mtls] = *mtl;
182 return lvl->mtls + lvl->num_mtls++;
185 static int append_polygons(struct bvhnode *bnode, struct triangle *faces, int num_faces, struct material *mtl)
188 struct triangle *tri;
190 newsz = bnode->num_faces + num_faces;
191 if(!(tri = realloc(bnode->faces, newsz * sizeof *bnode->faces))) {
192 fprintf(stderr, "append_polygons: failed to resize faces array to %d\n", newsz);
196 tri += bnode->num_faces;
197 bnode->num_faces = newsz;
199 for(i=0; i<num_faces; i++) {
204 cgm_vec3 *p = &tri->v[j].pos;
205 if(p->x < bnode->aabb.vmin.x) bnode->aabb.vmin.x = p->x;
206 if(p->x > bnode->aabb.vmax.x) bnode->aabb.vmax.x = p->x;
207 if(p->y < bnode->aabb.vmin.y) bnode->aabb.vmin.y = p->y;
208 if(p->y > bnode->aabb.vmax.y) bnode->aabb.vmax.y = p->y;
209 if(p->z < bnode->aabb.vmin.z) bnode->aabb.vmin.z = p->z;
210 if(p->z > bnode->aabb.vmax.z) bnode->aabb.vmax.z = p->z;