Browse Source

Sort faces for brush models into the overall faces list.

This works well to draw models correctly by themselves, but when placed in the world they may still have clipping issues with other models and/or neighboring leafs.
master
Nico de Poel 3 years ago
parent
commit
9474739c26
  1. 83
      world.c

83
world.c

@ -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;
}
}

Loading…
Cancel
Save