@ -194,6 +194,66 @@ static void world_drawFaces(const world_t *world, const ps1bsp_face_t *firstFace
}
}
/ / Simplified BSP subtree traversal specifically for sorting faces of brush models .
/ / This skips the frustum culling and PVS culling stages , as this will have already been done on the leafs containing the model .
static ps1bsp_face_t * world_sortModelFaces ( const world_t * world , const ps1bsp_model_t * model , u_long frameNum , ps1bsp_face_t * * lastFace )
{
short * nodeStack = ( short * ) ( scratchpad + 256 ) ;
u_char stackPtr = 0 ;
/ / Push the start node onto the stack
nodeStack [ stackPtr + + ] = model - > nodeId0 ;
ps1bsp_face_t * firstFace = NULL ;
while ( stackPtr > 0 )
{
/ / Pop a node off the stack
short nodeIdx = nodeStack [ - - stackPtr ] ;
if ( nodeIdx < 0 ) / / Leaf node
{
u_short leafIdx = ~ nodeIdx ;
if ( leafIdx = = 0 ) / / Leaf 0 should not be drawn
continue ;
const ps1bsp_leaf_t * leaf = & world - > leaves [ leafIdx ] ;
const u_short * leafFaces = & world - > leafFaces [ leaf - > firstLeafFace ] ;
for ( u_short leafFaceIdx = 0 ; leafFaceIdx < leaf - > numLeafFaces ; + + leafFaceIdx )
{
ps1bsp_face_t * face = & world - > faces [ leafFaces [ leafFaceIdx ] ] ;
/ / Make sure we draw each face only once per frame
if ( face - > drawFrame = = frameNum )
continue ;
face - > drawFrame = frameNum ;
/ / Cull faces that are facing away from the camera
if ( ! world_cull_backface ( world , face ) )
continue ;
if ( ! firstFace )
* lastFace = face ;
face - > nextFace = firstFace ;
firstFace = face ;
}
continue ;
}
const ps1bsp_node_t * node = & world - > nodes [ nodeIdx ] ;
const ps1bsp_plane_t * plane = & world - > planes [ node - > planeId ] ;
short dist = world_pointPlaneDist ( & cam_pos , plane ) ; / / TODO : add / subtract model origin from camera to sort faces in model space
/ / Traverse the subtree in back - to - front order
char order = dist < 0 ;
nodeStack [ stackPtr + + ] = node - > children [ order ] ;
nodeStack [ stackPtr + + ] = node - > children [ order ^ 1 ] ;
}
return firstFace ;
}
static ps1bsp_face_t * world_sortFaces ( const world_t * world , const ps1bsp_leaf_t * firstLeaf )
{
ps1bsp_face_t * firstFace = NULL ;
@ -233,24 +293,17 @@ static ps1bsp_face_t *world_sortFaces(const world_t *world, const ps1bsp_leaf_t
firstFace = face ;
}
/ / Draw models in this leaf
/ / Sort faces for the models in this leaf
for ( const ps1bsp_model_t * model = leaf - > models ; model ! = NULL ; model = model - > nextModel )
{
/ / Hmmm . . . either just draw all the faces in this model , or do the whole BSP sorting thing
/ / Guess we could call sortLeafs from here
/ / If we don ' t , things like tech doors which are concave might render improperly
ps1bsp_face_t * face = & world - > faces [ model - > firstFace ] ;
for ( u_short faceIdx = 0 ; faceIdx < model - > numFaces ; + + faceIdx , + + face )
/ / This successfully sorts the faces within a single model .
/ / However , several models occupying the same leaf will still clip through each other
/ / and since we ' re looking at only a single leaf per model , large brush models will often have neighbouring leafs drawing over them .
ps1bsp_face_t * lastFace ;
ps1bsp_face_t * face = world_sortModelFaces ( world , model , frameNum , & lastFace ) ;
if ( face ! = NULL )
{
if ( face - > drawFrame = = frameNum )
continue ;
face - > drawFrame = frameNum ;
if ( ! world_cull_backface ( world , face ) )
continue ;
face - > nextFace = firstFace ;
lastFace - > nextFace = firstFace ;
firstFace = face ;
}
}