diff --git a/ps1bsp.h b/ps1bsp.h index e795033..3ebaa19 100755 --- a/ps1bsp.h +++ b/ps1bsp.h @@ -22,7 +22,7 @@ Probable rendering process: typedef struct { unsigned short numVertices; - unsigned short numTriangles; + unsigned short numFaceVertIndices; unsigned short numFaces; } ps1bsp_header_t; @@ -62,11 +62,8 @@ typedef struct typedef struct { - unsigned short firstTriangleId; // TODO: could also just do first-index, num-indices here. No real need for a triangle_t struct. - unsigned short numTriangles; - - unsigned short firstQuadId; // For if/when we decide to add quads to the mix - unsigned short numQuads; + unsigned short firstVertexIndex; + unsigned short numVertices; } ps1bsp_face_t; // Pre-parsed and encoded entity data (this runs the risk of becoming too bloated) diff --git a/test.ps1bsp b/test.ps1bsp index 9497db6..809f689 100755 Binary files a/test.ps1bsp and b/test.ps1bsp differ diff --git a/world.c b/world.c index 2d1c3cb..f33bb3a 100644 --- a/world.c +++ b/world.c @@ -31,8 +31,8 @@ void world_load(const u_long *data, world_t *world) world->vertices = (ps1bsp_vertex_t*)bytes; bytes += sizeof(ps1bsp_vertex_t) * world->header->numVertices; - world->triangles = (ps1bsp_triangle_t*)bytes; - bytes += sizeof(ps1bsp_triangle_t) * world->header->numTriangles; + world->faceVertIndices = (unsigned short*)bytes; + bytes += sizeof(unsigned short) * world->header->numFaceVertIndices; world->faces = (ps1bsp_face_t*)bytes; bytes += sizeof(ps1bsp_face_t) * world->header->numFaces; @@ -46,35 +46,26 @@ void world_draw(const world_t *world) gte_SetRotMatrix(&vp_matrix); gte_SetTransMatrix(&vp_matrix); - char *scratch = scratchpad; - SVECTOR *vecs = (SVECTOR*)mem_scratch(&scratch, sizeof(SVECTOR) * 3); - for (int faceIdx = 0; faceIdx < world->header->numFaces; ++faceIdx) { const ps1bsp_face_t *face = &world->faces[faceIdx]; const CVECTOR *col = &colors[faceIdx % numColors]; - const ps1bsp_triangle_t *tri = &world->triangles[face->firstTriangleId]; - for (int triangleIdx = 0; triangleIdx < face->numTriangles; ++triangleIdx, ++tri) + char *scratch = scratchpad; + SVECTOR *vecs = (SVECTOR*)mem_scratch(&scratch, sizeof(SVECTOR) * face->numVertices); + + // Copy this face's vertices into scratch RAM for fast reuse + unsigned short *faceVertIndex = &world->faceVertIndices[face->firstVertexIndex]; + for (int vertIdx = 0; vertIdx < face->numVertices; ++vertIdx, ++faceVertIndex) { - // Naively draw the triangle with GTE, nothing special or optimized about this - const ps1bsp_vertex_t *v0 = &world->vertices[tri->vertex0]; - const ps1bsp_vertex_t *v1 = &world->vertices[tri->vertex1]; - const ps1bsp_vertex_t *v2 = &world->vertices[tri->vertex2]; - - vecs[0].vx = v0->x; vecs[0].vy = v0->y; vecs[0].vz = v0->z; - vecs[1].vx = v1->x; vecs[1].vy = v1->y; vecs[1].vz = v1->z; - vecs[2].vx = v2->x; vecs[2].vy = v2->y; vecs[2].vz = v2->z; - gte_ldv3c(vecs); - - // This method *should* work but it doesn't on real hardware, for some reason. - // Perhaps the PS1 doesn't like loading data from random far-off memory locations directly into GTE registers? - // We probably want to use the scratchpad memory to prepare the vertex data for the GTE anyway. - // SVECTOR *v0 = (SVECTOR*)&world->vertices[tri->vertex0]; - // SVECTOR *v1 = (SVECTOR*)&world->vertices[tri->vertex1]; - // SVECTOR *v2 = (SVECTOR*)&world->vertices[tri->vertex2]; - // gte_ldv3(v0, v1, v2); + vecs[vertIdx] = *((SVECTOR*)&world->vertices[*faceVertIndex]); + } + // Draw the face as a triangle fan + for (int vertIdx = 1; vertIdx < face->numVertices - 1; ++vertIdx) + { + // Naively draw the triangle with GTE, nothing special or optimized about this + gte_ldv3(&vecs[0], &vecs[vertIdx], &vecs[vertIdx + 1]); gte_rtpt(); // Rotation, translation, perspective projection // Normal clipping for backface culling diff --git a/world.h b/world.h index af210cd..354df56 100644 --- a/world.h +++ b/world.h @@ -7,7 +7,7 @@ typedef struct { ps1bsp_header_t *header; ps1bsp_vertex_t *vertices; - ps1bsp_triangle_t *triangles; + unsigned short *faceVertIndices; ps1bsp_face_t *faces; } world_t;