@ -69,10 +69,8 @@ static INLINE short world_planeDot(const SVECTOR *dir, const ps1bsp_plane_t *pla
return ( short ) m_dot12s ( * dir , plane - > normal ) ;
}
static void world_draw face( const world_t * world , const ps1bsp_face_t * face )
static INLINE char world_cull_back face( const world_t * world , const ps1bsp_face_t * face , short * dot )
{
/ / TODO : do an early primitive buffer check here , so we can skip backface culling & vertex copying if it ' s already full
/ / Backface culling using the face ' s plane and center point
/ / This eliminates the need for normal clipping per polygon
SVECTOR cam_vec ;
@ -81,65 +79,79 @@ static void world_drawface(const world_t *world, const ps1bsp_face_t *face)
cam_vec . vz = face - > center . vz - cam_pos . vz ;
const ps1bsp_plane_t * plane = & world - > planes [ face - > planeId ] ;
/ / NOTE : this value could be REALLY useful for determining the tessellation subdivisions . It has camera distance * and * angle in it .
/ / Just include the face size / area for an approximate screen size . Maybe also separate x / y / z for angle - dependent tessellation .
short dot = world_planeDot ( & cam_vec , plane ) ;
if ( ( dot > = 0 ) ^ face - > side )
* dot = world_planeDot ( & cam_vec , plane ) ;
return ( ( * dot > = 0 ) ^ face - > side ) ;
}
static void world_drawface_lit ( const world_t * world , const ps1bsp_face_t * face )
{
/ / TODO : early primitive buffer check
short dot ;
if ( world_cull_backface ( world , face , & dot ) )
return ;
if ( ! enableTexturing )
/ / Draw untextured , vertex colored polygons
SVECTOR * verts = ( SVECTOR * ) ( scratchpad + 256 ) ;
const ps1bsp_polygon_t * poly = & world - > polygons [ face - > firstPolygon ] ;
for ( u_char polyIdx = 0 ; polyIdx < face - > numPolygons ; + + polyIdx , + + poly )
{
/ / Draw untextured , vertex colored polygons
SVECTOR * verts = ( SVECTOR * ) ( scratchpad + 256 ) ;
const ps1bsp_polygon_t * poly = & world - > polygons [ face - > firstPolygon ] ;
for ( u_char polyIdx = 0 ; polyIdx < face - > numPolygons ; + + polyIdx , + + poly )
ps1bsp_polyvertex_t * polyVertex = & world - > polyVertices [ poly - > firstPolyVertex ] ;
SVECTOR * curVert = verts ;
for ( u_char vertIdx = 0 ; vertIdx < poly - > numPolyVertices ; + + vertIdx , + + polyVertex , + + curVert )
{
ps1bsp_polyvertex_t * polyVertex = & world - > polyVertices [ poly - > firstPolyVertex ] ;
SVECTOR * curVert = verts ;
for ( u_char vertIdx = 0 ; vertIdx < poly - > numPolyVertices ; + + vertIdx , + + polyVertex , + + curVert )
{
const ps1bsp_vertex_t * vert = & world - > vertices [ polyVertex - > index ] ;
* curVert = * ( ( SVECTOR * ) vert ) ;
curVert - > pad = polyVertex - > light ;
}
if ( poly - > numPolyVertices = = 3 )
draw_triangle_fan ( verts , 3 ) ;
else
draw_quad_strip ( verts , poly - > numPolyVertices ) ;
const ps1bsp_vertex_t * vert = & world - > vertices [ polyVertex - > index ] ;
* curVert = * ( ( SVECTOR * ) vert ) ;
curVert - > pad = polyVertex - > light ;
}
if ( poly - > numPolyVertices = = 3 )
draw_trianglefan_lit ( verts , 3 ) ;
else
draw_quadstrip_lit ( verts , poly - > numPolyVertices ) ;
}
else
}
static void world_drawface_textured ( const world_t * world , const ps1bsp_face_t * face )
{
/ / NOTE : this value could be REALLY useful for determining the tessellation subdivisions . It has camera distance * and * angle in it .
/ / Just include the face size / area for an approximate screen size . Maybe also separate x / y / z for angle - dependent tessellation .
short dot ;
if ( world_cull_backface ( world , face , & dot ) )
return ;
/ / TODO : do an early primitive buffer check here , so we can skip vertex copying if it ' s already full
/ / When doing tessellation , we need the above dot product to decide how many polys to draw , so we can only safely check the primbuffer size here
/ / Though since we ' re drawing front - to - back and tessellation will only happen close to the camera , I suppose we could get away with just checking for non - tessellated polycounts
/ / Draw textured , vertex colored polygons
STVECTOR * verts = ( STVECTOR * ) ( scratchpad + 256 ) ;
ps1bsp_texture_t * faceTexture = & world - > textures [ face - > textureId ] ;
const ps1bsp_polygon_t * poly = & world - > polygons [ face - > firstPolygon ] ;
for ( u_char polyIdx = 0 ; polyIdx < face - > numPolygons ; + + polyIdx , + + poly )
{
/ / Draw textured , vertex colored polygons
STVECTOR * verts = ( STVECTOR * ) ( scratchpad + 256 ) ;
ps1bsp_texture_t * faceTexture = & world - > textures [ face - > textureId ] ;
const ps1bsp_polygon_t * poly = & world - > polygons [ face - > firstPolygon ] ;
for ( u_char polyIdx = 0 ; polyIdx < face - > numPolygons ; + + polyIdx , + + poly )
ps1bsp_polyvertex_t * polyVertex = & world - > polyVertices [ poly - > firstPolyVertex ] ;
STVECTOR * curVert = verts ;
for ( u_char vertIdx = 0 ; vertIdx < poly - > numPolyVertices ; + + vertIdx , + + polyVertex , + + curVert )
{
ps1bsp_polyvertex_t * polyVertex = & world - > polyVertices [ poly - > firstPolyVertex ] ;
STVECTOR * curVert = verts ;
for ( u_char vertIdx = 0 ; vertIdx < poly - > numPolyVertices ; + + vertIdx , + + polyVertex , + + curVert )
{
const ps1bsp_vertex_t * vert = & world - > vertices [ polyVertex - > index ] ;
* ( ( SVECTOR * ) curVert ) = * ( ( SVECTOR * ) vert ) ;
curVert - > u = ( u_short ) polyVertex - > u ;
curVert - > v = ( u_short ) polyVertex - > v ;
curVert - > pad = polyVertex - > light ;
}
if ( face - > flags & SURF_DRAWWATER )
draw_quad_strip_water ( verts , poly - > numPolyVertices , faceTexture - > tpage ) ;
else
draw_quad_strip_tex ( verts , poly - > numPolyVertices , faceTexture - > tpage ) ;
const ps1bsp_vertex_t * vert = & world - > vertices [ polyVertex - > index ] ;
* ( ( SVECTOR * ) curVert ) = * ( ( SVECTOR * ) vert ) ;
curVert - > u = ( u_short ) polyVertex - > u ;
curVert - > v = ( u_short ) polyVertex - > v ;
curVert - > pad = polyVertex - > light ;
}
if ( face - > flags & SURF_DRAWWATER )
draw_quadstrip_water ( verts , poly - > numPolyVertices , faceTexture - > tpage ) ;
else
draw_quadstrip_textured ( verts , poly - > numPolyVertices , faceTexture - > tpage ) ;
}
}
static void ( * world_drawface ) ( const world_t * , const ps1bsp_face_t * ) = & world_drawface_textured ;
static void world_drawnode ( const world_t * world , short nodeIdx , u_char * pvs )
{
u_long frameNum = time_getFrameNumber ( ) ;
if ( nodeIdx < 0 ) / / Leaf node
{
/ / Check if this leaf is visible from the current camera position
@ -147,6 +159,7 @@ static void world_drawnode(const world_t *world, short nodeIdx, u_char *pvs)
if ( ( pvs [ test > > 3 ] & ( 1 < < ( test & 0x7 ) ) ) = = 0 )
return ;
u_long frameNum = time_getFrameNumber ( ) ;
const ps1bsp_leaf_t * leaf = & world - > leaves [ ~ nodeIdx ] ;
const u_short * leafFace = & world - > leafFaces [ leaf - > firstLeafFace ] ;
@ -250,5 +263,10 @@ void world_draw(const world_t *world)
u_char * pvs = world_loadVisData ( world , cam_leaf , & pvsbuf ) ;
/ / u_char * pvs = world_noVisData ( world , & pvsbuf ) ;
if ( enableTexturing )
world_drawface = & world_drawface_textured ;
else
world_drawface = & world_drawface_lit ;
world_drawnode ( world , 0 , pvs ) ;
}