diff --git a/n64e1m1.ps1bsp b/n64e1m1.ps1bsp index 1136465..46578cc 100755 Binary files a/n64e1m1.ps1bsp and b/n64e1m1.ps1bsp differ diff --git a/n64e2m2.ps1bsp b/n64e2m2.ps1bsp index a6be510..82e6a56 100755 Binary files a/n64e2m2.ps1bsp and b/n64e2m2.ps1bsp differ diff --git a/n64start.ps1bsp b/n64start.ps1bsp index 4691da5..cfebcfb 100755 Binary files a/n64start.ps1bsp and b/n64start.ps1bsp differ diff --git a/ps1bsp.h b/ps1bsp.h index 5a0ebf1..0889884 100755 --- a/ps1bsp.h +++ b/ps1bsp.h @@ -106,10 +106,14 @@ typedef struct ps1bsp_face_s unsigned short planeId; unsigned char side; + // TODO: not sure if we should make separate lists for triangles and non-triangle polygons here + // Could potentially improve drawing performance but at the cost of more memory use per face + // Used for high-quality tesselated textured drawing unsigned short firstPolygon; unsigned char numPolygons; - unsigned char totalQuads; + + unsigned char totalPrimitives; // Used for early primitive buffer checks // Used for low-quality untextured vertex colored drawing unsigned short firstFaceVertex; @@ -120,6 +124,7 @@ typedef struct ps1bsp_face_s // Used for backface culling SVECTOR center; + unsigned short bounds[4]; // Run-time data const struct ps1bsp_face_s* nextFace; // For chaining faces in drawing order diff --git a/world.c b/world.c index 3bc1da8..53e9a95 100644 --- a/world.c +++ b/world.c @@ -85,7 +85,21 @@ static INLINE short world_cull_backface(const world_t *world, const ps1bsp_face_ // UPDATE: tessellation does solve this, to an extent. However we must also make sure not to discard faces partially inside the frustum, and force tessellation on those. int camDot = m_dot12(&cam_vec, &cam_dir); if (camDot < 0) + { + // Check if the face may be partially inside the frustum. If so, we draw it with a high amount of tessellation. + for (int i = 0; i < 4; ++i) + { + const ps1bsp_vertex_t *vert = &world->vertices[face->bounds[i]]; + if (frustum_pointInside((SVECTOR*)vert)) + { + // TODO: use a simplified formula with only face area to determine tessellation LOD + return 1; + } + } + + // Face really isn't visible return 0; + } // Flip angle for faces that are on the opposite side of their plane char flip = 2 * face->side - 1; @@ -191,7 +205,7 @@ static void world_drawFaces(const world_t *world, const ps1bsp_face_t *firstFace for (const ps1bsp_face_t *face = firstFace; face != NULL; face = face->nextFace) { // Early primitive buffer check - if (!mem_checkprim(sizeof(POLY_GT4), face->totalQuads)) + if (!mem_checkprim(sizeof(POLY_GT4), face->totalPrimitives)) break; world_drawface(world, face, curOT);