diff --git a/ps1bsp.h b/ps1bsp.h index 5d40b3f..eead86a 100755 --- a/ps1bsp.h +++ b/ps1bsp.h @@ -33,7 +33,7 @@ typedef struct ps1bsp_dentry_t faceVertices; ps1bsp_dentry_t planes; ps1bsp_dentry_t nodes; - ps1bsp_dentry_t leafs; + ps1bsp_dentry_t leaves; ps1bsp_dentry_t leafFaces; } ps1bsp_header_t; @@ -72,17 +72,19 @@ typedef struct { unsigned short firstFaceVertex; unsigned char numFaceVertices; + + u_long drawFrame; // Which frame was this face last drawn on? Used to check if this face should be drawn. } ps1bsp_face_t; typedef struct { SVECTOR normal; - u_short dist; + short dist; } ps1bsp_plane_t; typedef struct { - u_int planeId; + int planeId; u_short front; u_short back; // TODO: add bounding box for frustum culling diff --git a/test.ps1bsp b/test.ps1bsp index 59a3a9e..3673abf 100755 Binary files a/test.ps1bsp and b/test.ps1bsp differ diff --git a/world.c b/world.c index 080c179..bc93d52 100644 --- a/world.c +++ b/world.c @@ -1,6 +1,7 @@ #include "common.h" #include "world.h" #include "display.h" +#include "time.h" #include @@ -35,6 +36,18 @@ void world_load(const u_long *data, world_t *world) world->faceVertices = (ps1bsp_facevertex_t*)(bytes + header->faceVertices.offset); world->numFaceVertices = header->faceVertices.size / sizeof(ps1bsp_facevertex_t); + + world->planes = (ps1bsp_plane_t*)(bytes + header->planes.offset); + world->numPlanes = header->planes.size / sizeof(ps1bsp_plane_t); + + world->nodes = (ps1bsp_node_t*)(bytes + header->nodes.offset); + world->numNodes = header->nodes.size / sizeof(ps1bsp_node_t); + + world->leaves = (ps1bsp_leaf_t*)(bytes + header->leaves.offset); + world->numLeaves = header->leaves.size / sizeof(ps1bsp_leaf_t); + + world->leafFaces = (u_short*)(bytes + header->leafFaces.offset); + world->numLeafFaces = header->leafFaces.size / sizeof(u_short); } static INLINE void drawface_triangle_fan(const ps1bsp_face_t *face, SVECTOR *vecs) @@ -209,6 +222,27 @@ static INLINE void drawface_quad_strip(const ps1bsp_face_t *face, SVECTOR *vecs) } } +static void world_drawface(const world_t *world, const ps1bsp_face_t *face, char *scratchptr) +{ + const CVECTOR *col = &colors[(u_long)face % numColors]; + + SVECTOR *vecs = (SVECTOR*)mem_scratch(&scratchptr, sizeof(SVECTOR) * face->numFaceVertices); + + // Copy this face's vertices into scratch RAM for fast reuse + ps1bsp_facevertex_t *faceVertex = &world->faceVertices[face->firstFaceVertex]; + for (int vertIdx = 0; vertIdx < face->numFaceVertices; ++vertIdx, ++faceVertex) + { + const ps1bsp_vertex_t *vert = &world->vertices[faceVertex->index]; + vecs[vertIdx] = *((SVECTOR*)vert); + vecs[vertIdx].pad = vert->baseLight; + } + + if (face->numFaceVertices == 3) + drawface_triangle_fan(face, vecs); + else + drawface_quad_strip(face, vecs); +} + void world_draw(const world_t *world) { int p; @@ -217,26 +251,22 @@ void world_draw(const world_t *world) gte_SetRotMatrix(&vp_matrix); gte_SetTransMatrix(&vp_matrix); - for (int faceIdx = 0; faceIdx < world->numFaces; ++faceIdx) + u_long frameNum = time_getFrameNumber(); + + const ps1bsp_leaf_t *leaf = &world->leaves[0]; + for (u_short leafIdx = 0; leafIdx < world->numLeaves; ++leafIdx, ++leaf) { - const ps1bsp_face_t *face = &world->faces[faceIdx]; - const CVECTOR *col = &colors[faceIdx % numColors]; + u_short *leafFace = &world->leafFaces[leaf->firstLeafFace]; + for (u_short leafFaceIdx = 0; leafFaceIdx < leaf->numLeafFaces; ++leafFaceIdx, ++leafFace) + { + ps1bsp_face_t *face = &world->faces[*leafFace]; - char *scratch = scratchpad; - SVECTOR *vecs = (SVECTOR*)mem_scratch(&scratch, sizeof(SVECTOR) * face->numFaceVertices); + // Check if we've already drawn this face + if (face->drawFrame == frameNum) + continue; - // Copy this face's vertices into scratch RAM for fast reuse - ps1bsp_facevertex_t *faceVertex = &world->faceVertices[face->firstFaceVertex]; - for (int vertIdx = 0; vertIdx < face->numFaceVertices; ++vertIdx, ++faceVertex) - { - const ps1bsp_vertex_t *vert = &world->vertices[faceVertex->index]; - vecs[vertIdx] = *((SVECTOR*)vert); - vecs[vertIdx].pad = vert->baseLight; + world_drawface(world, face, scratchpad); + face->drawFrame = frameNum; } - - if (face->numFaceVertices == 3) - drawface_triangle_strip(face, vecs); - else - drawface_quad_strip(face, vecs); } } diff --git a/world.h b/world.h index 08b1e45..d9bbabd 100644 --- a/world.h +++ b/world.h @@ -13,6 +13,18 @@ typedef struct u_short numFaceVertices; ps1bsp_facevertex_t *faceVertices; + + u_short numPlanes; + ps1bsp_plane_t *planes; + + u_short numNodes; + ps1bsp_node_t *nodes; + + u_short numLeaves; + ps1bsp_leaf_t *leaves; + + u_short numLeafFaces; + u_short *leafFaces; } world_t; void world_load(const u_long *data, world_t *world);