implementing build_bvh_sah
[cyberay] / src / level.c
index 21a82f9..0016a70 100644 (file)
@@ -5,8 +5,7 @@
 #include "treestore.h"
 #include "mesh.h"
 
-static struct material *add_material(struct level *lvl, struct material *mtl);
-static int append_polygons(struct bvhnode *bnode, struct triangle *faces, int num_faces, struct material *mtl);
+static int add_mesh_faces(struct bvhnode *bnode, struct mesh *mesh);
 
 int load_level(struct level *lvl, const char *fname)
 {
@@ -14,8 +13,7 @@ int load_level(struct level *lvl, const char *fname)
        char path[256];
        struct ts_node *root, *node;
        struct scenefile scn;
-       struct mesh *mesh;
-       struct material *mtl;
+       struct mesh *mesh, *tail;
 
        memset(lvl, 0, sizeof *lvl);
        if(!(lvl->st_root = calloc(1, sizeof *lvl->st_root)) ||
@@ -60,13 +58,18 @@ int load_level(struct level *lvl, const char *fname)
                        if(load_scenefile(&scn, path) == -1) {
                                goto cont;
                        }
-                       mesh = scn.meshlist;
+                       mesh = tail = scn.meshlist;
                        while(mesh) {
-                               mtl = add_material(lvl, &mesh->mtl);
-                               append_polygons(lvl->st_root, mesh->faces, mesh->num_faces, mtl);
+                               add_mesh_faces(lvl->st_root, mesh);
+                               tail = mesh;
                                mesh = mesh->next;
                        }
 
+                       if(tail) {
+                               tail->next = lvl->meshlist;
+                               lvl->meshlist = scn.meshlist;
+                               scn.meshlist = 0;
+                       }
                        destroy_scenefile(&scn);
                }
 cont:  node = node->next;
@@ -78,9 +81,16 @@ cont:        node = node->next;
 
 void destroy_level(struct level *lvl)
 {
+       struct mesh *mesh;
+
        free_bvh_tree(lvl->st_root);
        free_bvh_tree(lvl->dyn_root);
-       free(lvl->mtls);
+
+       while(lvl->meshlist) {
+               mesh = lvl->meshlist;
+               lvl->meshlist = lvl->meshlist->next;
+               destroy_mesh(mesh);
+       }
 }
 
 
@@ -122,11 +132,11 @@ static void draw_level_rec(struct bvhnode *bn)
        if(!bn) return;
 
        if(bn->faces) {
-               tri = bn->faces;
-               curmtl = tri->mtl;
+               curmtl = bn->faces[0]->mtl;
 
                glBegin(GL_TRIANGLES);
                for(i=0; i<bn->num_faces; i++) {
+                       tri = bn->faces[i];
                        if(tri->mtl != curmtl) {
                                glEnd();
                                color[0] = tri->mtl->color.x;
@@ -142,7 +152,6 @@ static void draw_level_rec(struct bvhnode *bn)
                                glTexCoord2fv(&tri->v[j].tex.x);
                                glVertex3fv(&tri->v[j].pos.x);
                        }
-                       tri++;
                }
                glEnd();
        }
@@ -157,49 +166,24 @@ void draw_level(struct level *lvl)
        draw_level_rec(lvl->dyn_root);
 }
 
-static struct material *add_material(struct level *lvl, struct material *mtl)
-{
-       int i, newsz;
-       struct material *tmp;
-
-       for(i=0; i<lvl->num_mtls; i++) {
-               if(memcmp(lvl->mtls + i, mtl, sizeof *mtl) == 0) {
-                       return lvl->mtls + i;
-               }
-       }
-
-       if(lvl->num_mtls >= lvl->max_mtls) {
-               newsz = lvl->max_mtls ? lvl->max_mtls * 2 : 16;
-               if(!(tmp = realloc(lvl->mtls, newsz * sizeof *lvl->mtls))) {
-                       fprintf(stderr, "add_material: failed to resize materials array to %d\n", newsz);
-                       return 0;
-               }
-               lvl->mtls = tmp;
-               lvl->max_mtls = newsz;
-       }
-       lvl->mtls[lvl->num_mtls] = *mtl;
-
-       return lvl->mtls + lvl->num_mtls++;
-}
-
-static int append_polygons(struct bvhnode *bnode, struct triangle *faces, int num_faces, struct material *mtl)
+static int add_mesh_faces(struct bvhnode *bnode, struct mesh *mesh)
 {
        int i, j, newsz;
-       struct triangle *tri;
+       void *tmp;
+       struct triangle *tri, **triptr;
 
-       newsz = bnode->num_faces + num_faces;
-       if(!(tri = realloc(bnode->faces, newsz * sizeof *bnode->faces))) {
+       newsz = bnode->num_faces + mesh->num_faces;
+       if(!(tmp = realloc(bnode->faces, newsz * sizeof *bnode->faces))) {
                fprintf(stderr, "append_polygons: failed to resize faces array to %d\n", newsz);
                return -1;
        }
-       bnode->faces = tri;
-       tri += bnode->num_faces;
+       bnode->faces = tmp;
+       triptr = bnode->faces + bnode->num_faces;
        bnode->num_faces = newsz;
 
-       for(i=0; i<num_faces; i++) {
-               *tri = *faces++;
-               tri->mtl = mtl;
-
+       tri = mesh->faces;
+       for(i=0; i<mesh->num_faces; i++) {
+               *triptr++ = tri;
                for(j=0; j<3; j++) {
                        cgm_vec3 *p = &tri->v[j].pos;
                        if(p->x < bnode->aabb.vmin.x) bnode->aabb.vmin.x = p->x;