Browse Source

Faces can now carry their own per-vertex lighting data, instead of sharing all vertex data with adjacent faces.

tess_experiment
Nico de Poel 3 years ago
parent
commit
3167f1474e
  1. 15
      ps1bsp.h
  2. BIN
      test.ps1bsp
  3. 16
      world.c
  4. 2
      world.h

15
ps1bsp.h

@ -22,7 +22,7 @@ Probable rendering process:
typedef struct
{
unsigned short numVertices;
unsigned short numFaceVertIndices;
unsigned short numFaceVertices;
unsigned short numFaces;
} ps1bsp_header_t;
@ -51,19 +51,16 @@ typedef struct
unsigned char b : 5;
} ps1bsp_vertex_t;
// Instead of edges as in the original BSP format, we store triangles for easy consumption by the PS1
// Note: it may actually be more efficient to render quads for faces with 4+ vertices
typedef struct
{
unsigned short vertex0;
unsigned short vertex1;
unsigned short vertex2;
} ps1bsp_triangle_t;
unsigned short index;
unsigned char light;
} ps1bsp_facevertex_t;
typedef struct
{
unsigned short firstVertexIndex;
unsigned short numVertices;
unsigned short firstFaceVertex;
unsigned short numFaceVertices;
} ps1bsp_face_t;
// Pre-parsed and encoded entity data (this runs the risk of becoming too bloated)

BIN
test.ps1bsp

16
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->faceVertIndices = (unsigned short*)bytes;
bytes += sizeof(unsigned short) * world->header->numFaceVertIndices;
world->faceVertices = (ps1bsp_facevertex_t*)bytes;
bytes += sizeof(ps1bsp_facevertex_t) * world->header->numFaceVertices;
world->faces = (ps1bsp_face_t*)bytes;
bytes += sizeof(ps1bsp_face_t) * world->header->numFaces;
@ -52,19 +52,19 @@ void world_draw(const world_t *world)
const CVECTOR *col = &colors[faceIdx % numColors];
char *scratch = scratchpad;
SVECTOR *vecs = (SVECTOR*)mem_scratch(&scratch, sizeof(SVECTOR) * face->numVertices);
SVECTOR *vecs = (SVECTOR*)mem_scratch(&scratch, sizeof(SVECTOR) * face->numFaceVertices);
// 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)
ps1bsp_facevertex_t *faceVertex = &world->faceVertices[face->firstFaceVertex];
for (int vertIdx = 0; vertIdx < face->numFaceVertices; ++vertIdx, ++faceVertex)
{
const ps1bsp_vertex_t *vert = &world->vertices[*faceVertIndex];
const ps1bsp_vertex_t *vert = &world->vertices[faceVertex->index];
vecs[vertIdx] = *((SVECTOR*)vert);
vecs[vertIdx].pad = vert->baseLight;
}
// Draw the face as a triangle fan
for (int vertIdx = 1; vertIdx < face->numVertices - 1; ++vertIdx)
for (int vertIdx = 1; vertIdx < face->numFaceVertices - 1; ++vertIdx)
{
const SVECTOR *v0 = &vecs[0];
const SVECTOR *v1 = &vecs[vertIdx];
@ -74,7 +74,7 @@ void world_draw(const world_t *world)
gte_ldv3(v0, v1, v2);
gte_rtpt(); // Rotation, translation, perspective projection
// Normal clipping for backface culling
// Normal clipping for backface culling (TODO: should be necessary only once per face, using plane normal & camera direction)
gte_nclip();
gte_stopz(&p);
if (p < 0)

2
world.h

@ -7,7 +7,7 @@ typedef struct
{
ps1bsp_header_t *header;
ps1bsp_vertex_t *vertices;
unsigned short *faceVertIndices;
ps1bsp_facevertex_t *faceVertices;
ps1bsp_face_t *faces;
} world_t;

Loading…
Cancel
Save