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};
126 glBegin(GL_TRIANGLES);
127 for(i=0; i<bn->num_faces; i++) {
128 if(tri->mtl != curmtl) {
130 color[0] = tri->mtl->color.x;
131 color[1] = tri->mtl->color.y;
132 color[2] = tri->mtl->color.z;
133 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
135 glBegin(GL_TRIANGLES);
139 glNormal3fv(&tri->v[j].norm.x);
140 glTexCoord2fv(&tri->v[j].tex.x);
141 glVertex3fv(&tri->v[j].pos.x);
155 void draw_level(struct level *lvl)
157 draw_level_rec(lvl->st_root);
158 draw_level_rec(lvl->dyn_root);
161 static struct material *add_material(struct level *lvl, struct material *mtl)
164 struct material *tmp;
166 for(i=0; i<lvl->num_mtls; i++) {
167 if(memcmp(lvl->mtls + i, mtl, sizeof *mtl) == 0) {
168 return lvl->mtls + i;
172 if(lvl->num_mtls >= lvl->max_mtls) {
173 newsz = lvl->max_mtls ? lvl->max_mtls * 2 : 16;
174 if(!(tmp = realloc(lvl->mtls, newsz * sizeof *lvl->mtls))) {
175 fprintf(stderr, "add_material: failed to resize materials array to %d\n", newsz);
179 lvl->max_mtls = newsz;
181 lvl->mtls[lvl->num_mtls] = *mtl;
183 return lvl->mtls + lvl->num_mtls++;
186 static int append_polygons(struct bvhnode *bnode, struct triangle *faces, int num_faces, struct material *mtl)
189 struct triangle *tri;
191 newsz = bnode->num_faces + num_faces;
192 if(!(tri = realloc(bnode->faces, newsz * sizeof *bnode->faces))) {
193 fprintf(stderr, "append_polygons: failed to resize faces array to %d\n", newsz);
197 tri += bnode->num_faces;
198 bnode->num_faces = newsz;
200 for(i=0; i<num_faces; i++) {
205 cgm_vec3 *p = &tri->v[j].pos;
206 if(p->x < bnode->aabb.vmin.x) bnode->aabb.vmin.x = p->x;
207 if(p->x > bnode->aabb.vmax.x) bnode->aabb.vmax.x = p->x;
208 if(p->y < bnode->aabb.vmin.y) bnode->aabb.vmin.y = p->y;
209 if(p->y > bnode->aabb.vmax.y) bnode->aabb.vmax.y = p->y;
210 if(p->z < bnode->aabb.vmin.z) bnode->aabb.vmin.z = p->z;
211 if(p->z > bnode->aabb.vmax.z) bnode->aabb.vmax.z = p->z;