|
|
|
@ -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 |
|
|
|
|