#include "common.h" #include "world.h" #include "display.h" #include static CVECTOR colors[] = { { 255, 0, 0 }, { 0, 255, 0 }, { 0, 0, 255 }, { 255, 255, 0 }, { 255, 0, 255 }, { 0, 255, 255 }, { 128, 255, 0 }, { 255, 128, 0 }, { 128, 0, 255 }, { 255, 0, 128 }, { 0, 128, 255 }, { 0, 255, 128 }, }; static const int numColors = sizeof(colors) / sizeof(CVECTOR); void world_load(const u_long *data, world_t *world) { const char *bytes = (const char*)data; world->header = (ps1bsp_header_t*)bytes; bytes += sizeof(ps1bsp_header_t); world->vertices = (ps1bsp_vertex_t*)bytes; bytes += sizeof(ps1bsp_vertex_t) * world->header->numVertices; 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; } void world_draw(const world_t *world) { int p; // The world doesn't move, so we just set the camera view-projection matrix gte_SetRotMatrix(&vp_matrix); gte_SetTransMatrix(&vp_matrix); for (int faceIdx = 0; faceIdx < world->header->numFaces; ++faceIdx) { const ps1bsp_face_t *face = &world->faces[faceIdx]; const CVECTOR *col = &colors[faceIdx % numColors]; 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) { 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 gte_nclip(); gte_stopz(&p); if (p < 0) continue; // Average Z for depth sorting and culling gte_avsz3(); gte_stotz(&p); unsigned short depth = p >> 2; if (depth <= 0 || depth >= OTLEN) continue; // Draw a flat-shaded untextured colored triangle POLY_F3 *poly = (POLY_F3*)mem_prim(sizeof(POLY_F3)); if (poly == NULL) break; setPolyF3(poly); gte_stsxy3_f3(poly); poly->r0 = col->r; poly->g0 = col->g; poly->b0 = col->b; addPrim(curOT + depth, poly); } } }