8 static int add_mesh_faces(struct bvhnode *bnode, struct mesh *mesh);
10 int load_level(struct level *lvl, const char *fname)
14 struct ts_node *root, *node;
16 struct mesh *mesh, *tail;
18 memset(lvl, 0, sizeof *lvl);
19 if(!(lvl->st_root = calloc(1, sizeof *lvl->st_root)) ||
20 !(lvl->dyn_root = calloc(1, sizeof *lvl->dyn_root))) {
22 fprintf(stderr, "load_level: failed to allocate bvh root nodes\n");
26 cgm_vcons(&lvl->st_root->aabb.vmin, FLT_MAX, FLT_MAX, FLT_MAX);
27 cgm_vcons(&lvl->st_root->aabb.vmax, -FLT_MAX, -FLT_MAX, -FLT_MAX);
28 lvl->dyn_root->aabb = lvl->st_root->aabb;
30 dirname = alloca(strlen(fname) + 1);
31 strcpy(dirname, fname);
32 if((ptr = strrchr(dirname, '/'))) {
38 if(!(root = ts_load(fname))) {
39 fprintf(stderr, "load_level: failed to load: %s\n", fname);
42 if(strcmp(root->name, "level") != 0) {
43 fprintf(stderr, "load_level: invalid level file %s, root is not \"level\"\n", fname);
48 node = root->child_list;
50 if(strcmp(node->name, "scene") == 0) {
51 if(!(fname = ts_get_attr_str(node, "file", 0))) {
52 fprintf(stderr, "load_level: ignoring \"scene\" without a \"file\" attribute\n");
55 snprintf(path, sizeof path, "%s%s", dirname, fname);
56 printf("loading scene file: %s\n", path);
58 if(load_scenefile(&scn, path) == -1) {
61 mesh = tail = scn.meshlist;
63 add_mesh_faces(lvl->st_root, mesh);
69 tail->next = lvl->meshlist;
70 lvl->meshlist = scn.meshlist;
73 destroy_scenefile(&scn);
75 cont: node = node->next;
82 void destroy_level(struct level *lvl)
86 free_bvh_tree(lvl->st_root);
87 free_bvh_tree(lvl->dyn_root);
89 while(lvl->meshlist) {
91 lvl->meshlist = lvl->meshlist->next;
97 int ray_level(cgm_ray *ray, struct level *lvl, float tmax, struct rayhit *hit)
103 if(ray_bvhnode(ray, lvl->st_root, tmax, 0)) return 1;
104 if(ray_bvhnode(ray, lvl->dyn_root, tmax, 0)) return 1;
109 if(ray_bvhnode(ray, lvl->st_root, tmax, hit)) {
113 if(ray_bvhnode(ray, lvl->dyn_root, tmax, hit) && hit->t < hit0.t) {
125 static void draw_level_rec(struct bvhnode *bn)
128 struct triangle *tri;
129 struct material *curmtl;
130 float color[4] = {0, 0, 0, 1};
135 curmtl = bn->faces[0]->mtl;
137 glBegin(GL_TRIANGLES);
138 for(i=0; i<bn->num_faces; i++) {
140 if(tri->mtl != curmtl) {
142 color[0] = tri->mtl->color.x;
143 color[1] = tri->mtl->color.y;
144 color[2] = tri->mtl->color.z;
145 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
147 glBegin(GL_TRIANGLES);
151 glNormal3fv(&tri->v[j].norm.x);
152 glTexCoord2fv(&tri->v[j].tex.x);
153 glVertex3fv(&tri->v[j].pos.x);
159 draw_level_rec(bn->left);
160 draw_level_rec(bn->right);
163 void draw_level(struct level *lvl)
165 draw_level_rec(lvl->st_root);
166 draw_level_rec(lvl->dyn_root);
169 static int add_mesh_faces(struct bvhnode *bnode, struct mesh *mesh)
173 struct triangle *tri, **triptr;
175 newsz = bnode->num_faces + mesh->num_faces;
176 if(!(tmp = realloc(bnode->faces, newsz * sizeof *bnode->faces))) {
177 fprintf(stderr, "append_polygons: failed to resize faces array to %d\n", newsz);
181 triptr = bnode->faces + bnode->num_faces;
182 bnode->num_faces = newsz;
185 for(i=0; i<mesh->num_faces; i++) {
188 cgm_vec3 *p = &tri->v[j].pos;
189 if(p->x < bnode->aabb.vmin.x) bnode->aabb.vmin.x = p->x;
190 if(p->x > bnode->aabb.vmax.x) bnode->aabb.vmax.x = p->x;
191 if(p->y < bnode->aabb.vmin.y) bnode->aabb.vmin.y = p->y;
192 if(p->y > bnode->aabb.vmax.y) bnode->aabb.vmax.y = p->y;
193 if(p->z < bnode->aabb.vmin.z) bnode->aabb.vmin.z = p->z;
194 if(p->z > bnode->aabb.vmax.z) bnode->aabb.vmax.z = p->z;