#ifndef __PS1BSP_H__ #define __PS1BSP_H__ #ifdef __cplusplus extern "C" { #endif /* Probable rendering process: - Determine visible leaves based on PVS and frustum culling, the usual. - Chain together faces/polygons to be drawn. Possibly grouped by texture ID? Texture chaining might improve performance by making better use of texture cache, but we'll still be separating polygons based on depth anyway, so the advantage is questionable. Texture chaining should probably be the last optimization we try. - Tessellate polygons close to the camera by recursively cutting edges in two, up to X times based on camera distance/screen size. Possibly GTE can aid with averaging coordinates? => look at GPF/GPL (general purpose interpolation) - Collect all vertices that need to be transformed, put them through GTE, update lighting values if needed, and cache the results. (It may not be worth it to collect and precalculate vertices, as keeping track of all the administration also comes at a considerable cost.) - Draw all the (tessellated) polygons using the precalculated vertex positions. Use GTE to calculate average depth and order polygons. Note: we may not have to calculate average depth for BSP polygons, as the leafs already provide an ordering, and leafs are convex so there is no need to sort the polygons within. We do however need some kind of depth value per leaf to insert alias models at the correct positions in the ordering table. */ typedef struct { unsigned int offset; unsigned int size; } ps1bsp_dentry_t; typedef struct { u_short version; ps1bsp_dentry_t textures; ps1bsp_dentry_t vertices; ps1bsp_dentry_t polygons; ps1bsp_dentry_t polyVertices; ps1bsp_dentry_t faces; ps1bsp_dentry_t faceVertices; ps1bsp_dentry_t planes; ps1bsp_dentry_t nodes; ps1bsp_dentry_t leaves; ps1bsp_dentry_t leafFaces; ps1bsp_dentry_t visData; } ps1bsp_header_t; typedef struct { unsigned char w, h; // These may be necessary for scaling UVs, especially since we use a mix of mip0 and mip1 textures unsigned char uoffs, voffs; // Texture coordinate offset within the texture page unsigned short tpage; // Texture page in PS1 VRAM (precalculated when generating the texture atlas) unsigned short nextframe; // If non-zero, the texture is animated and this points to the next texture in the sequence } ps1bsp_texture_t; // This matches the SVECTOR data type; we can use the extra padding to store some more data. typedef struct { short x, y, z; short pad; } ps1bsp_vertex_t; // Texture UV and lighting data for a vertex on a particular polygon. // TODO: break up into poly vertex (index + uv) and surface vertex (index + light) shared between polygons. Will reduce this struct size to 4 bytes and eliminate duplicate light values. typedef struct { unsigned short index; unsigned short light; // Can be made into u_char if we need to store more data; currently u_short for 32-bit alignment purposes unsigned short u, v; // Can be made into u_char if we need to store more data; currently u_short for 32-bit alignment purposes } ps1bsp_polyvertex_t; // Faces are broken up into one or more polygons, each of which can be drawn as a quad/triangle strip with a single texture. // This ahead-of-time tesselation is done to deal with the fact that the PS1 can't do texture wrapping, meaning tiling textures have to be broken up into separate polygons. typedef struct { unsigned short firstPolyVertex; unsigned short numPolyVertices; } ps1bsp_polygon_t; typedef struct { unsigned short index; // Sampled texture color * light, for untextured gouraud shaded drawing at range unsigned char a : 1; unsigned char r : 5; unsigned char g : 5; unsigned char b : 5; } ps1bsp_facevertex_t; #define SURF_DRAWSKY 0x2 #define SURF_DRAWLIQUID 0x4 #define SURF_DRAWWATER 0x8 // High quality: Face -> polygons -> polygon vertex indices (index + UV + light) -> vertices // Low quality: Face -> face vertex indices (index + color) -> vertices typedef struct ps1bsp_face_s { unsigned short planeId; unsigned char side; // Used for high-quality tesselated textured drawing unsigned short firstPolygon; unsigned char numPolygons; unsigned char totalQuads; // Used for low-quality untextured vertex colored drawing unsigned short firstFaceVertex; unsigned char numFaceVertices; unsigned char textureId; unsigned char flags; // Used for backface culling SVECTOR center; // Run-time data const struct ps1bsp_face_s* nextFace; // For chaining faces in drawing order u_long drawFrame; // Which frame was this face last drawn on? Used to check if this face should be drawn. } ps1bsp_face_t; typedef struct { SVECTOR normal; short dist; short type; } ps1bsp_plane_t; typedef struct { int planeId; short children[2]; SVECTOR boundingSphere; } ps1bsp_node_t; typedef struct ps1bsp_leaf_s { short type; int vislist; SVECTOR mins, maxs; u_short firstLeafFace; u_short numLeafFaces; // Run-time data const struct ps1bsp_leaf_s* nextLeaf; // For chaining leafs in drawing order } ps1bsp_leaf_t; // Pre-parsed and encoded entity data (this runs the risk of becoming too bloated) typedef struct { unsigned short classtype; // Hash of the original classname short angle[3]; // Can store both mangle (all axes) and just angle (Z-axis rotation only) int origin[3]; // In 12-bit fixed point coordinates unsigned int spawnflags; unsigned short messageId; // Index into a pool of pre-defined messages } ps1bsp_entity_t; typedef struct { unsigned short length; char message[1]; } ps1bsp_message_t; #ifdef __cplusplus } #endif #endif // __PS1BSP_H__