|
|
|
@ -202,39 +202,54 @@ static ps1bsp_face_t *world_sortFaces(const world_t *world, const ps1bsp_leaf_t |
|
|
|
return firstFace; |
|
|
|
} |
|
|
|
|
|
|
|
static void world_sortLeafs(const world_t *world, short nodeIdx, u_char *pvs, ps1bsp_leaf_t **firstLeaf) |
|
|
|
static ps1bsp_leaf_t *world_sortLeafs(const world_t *world, short startNode, u_char *pvs) |
|
|
|
{ |
|
|
|
if (nodeIdx < 0) // Leaf node |
|
|
|
short *nodeStack = (short*)(scratchpad + 256); // Place the node stack in fast RAM after the PVS data |
|
|
|
u_char stackPtr = 0; |
|
|
|
|
|
|
|
// Push the start node onto the stack |
|
|
|
nodeStack[stackPtr++] = startNode; |
|
|
|
|
|
|
|
ps1bsp_leaf_t *firstLeaf = NULL; |
|
|
|
while (stackPtr > 0) |
|
|
|
{ |
|
|
|
u_short leafIdx = ~nodeIdx; |
|
|
|
if (leafIdx == 0) // Leaf 0 should not be drawn |
|
|
|
return; |
|
|
|
|
|
|
|
// PVS culling |
|
|
|
u_short test = leafIdx - 1; |
|
|
|
if ((pvs[test >> 3] & (1 << (test & 0x7))) == 0) |
|
|
|
return; |
|
|
|
|
|
|
|
// Add the leaf to the sorted linked list |
|
|
|
// Since we're traversing the BSP tree front-to-back, adding each leaf at the start sorts the list in back-to-front order |
|
|
|
ps1bsp_leaf_t *leaf = (ps1bsp_leaf_t*)&world->leaves[leafIdx]; |
|
|
|
leaf->nextLeaf = *firstLeaf; |
|
|
|
*firstLeaf = leaf; |
|
|
|
return; |
|
|
|
} |
|
|
|
// Pop a node off the stack |
|
|
|
short nodeIdx = nodeStack[--stackPtr]; |
|
|
|
|
|
|
|
// Perform frustum culling |
|
|
|
const ps1bsp_node_t *node = &world->nodes[nodeIdx]; |
|
|
|
if (!frustum_sphereInside(&node->boundingSphere)) |
|
|
|
return; |
|
|
|
if (nodeIdx < 0) // Leaf node |
|
|
|
{ |
|
|
|
u_short leafIdx = ~nodeIdx; |
|
|
|
if (leafIdx == 0) // Leaf 0 should not be drawn |
|
|
|
continue; |
|
|
|
|
|
|
|
const ps1bsp_plane_t *plane = &world->planes[node->planeId]; |
|
|
|
short dist = world_pointPlaneDist(&cam_pos, plane); |
|
|
|
|
|
|
|
// Traverse the BSP tree in front-to-back order |
|
|
|
char order = dist < 0; |
|
|
|
world_sortLeafs(world, node->children[order], pvs, firstLeaf); |
|
|
|
world_sortLeafs(world, node->children[order ^ 1], pvs, firstLeaf); |
|
|
|
// PVS culling |
|
|
|
u_short test = leafIdx - 1; |
|
|
|
if ((pvs[test >> 3] & (1 << (test & 0x7))) == 0) |
|
|
|
continue; |
|
|
|
|
|
|
|
// Add the leaf to the sorted linked list |
|
|
|
// Since we're traversing the BSP tree front-to-back, adding each leaf at the start sorts the list in back-to-front order |
|
|
|
ps1bsp_leaf_t *leaf = (ps1bsp_leaf_t*)&world->leaves[leafIdx]; |
|
|
|
leaf->nextLeaf = firstLeaf; |
|
|
|
firstLeaf = leaf; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// Perform frustum culling |
|
|
|
const ps1bsp_node_t *node = &world->nodes[nodeIdx]; |
|
|
|
if (!frustum_sphereInside(&node->boundingSphere)) |
|
|
|
continue; |
|
|
|
|
|
|
|
const ps1bsp_plane_t *plane = &world->planes[node->planeId]; |
|
|
|
short dist = world_pointPlaneDist(&cam_pos, plane); |
|
|
|
|
|
|
|
// Traverse the BSP tree in front-to-back order |
|
|
|
char order = dist < 0; |
|
|
|
nodeStack[stackPtr++] = node->children[order ^ 1]; |
|
|
|
nodeStack[stackPtr++] = node->children[order]; |
|
|
|
} |
|
|
|
|
|
|
|
return firstLeaf; |
|
|
|
} |
|
|
|
|
|
|
|
// Decompress PVS data for the given leaf ID and store it in RAM at the given buffer pointer location. |
|
|
|
@ -315,8 +330,7 @@ void world_draw(const world_t *world) |
|
|
|
else |
|
|
|
world_drawface = &world_drawface_lit; |
|
|
|
|
|
|
|
ps1bsp_leaf_t *firstLeaf = NULL; |
|
|
|
world_sortLeafs(world, 0, pvs, &firstLeaf); |
|
|
|
ps1bsp_leaf_t *firstLeaf = world_sortLeafs(world, 0, pvs); |
|
|
|
ps1bsp_face_t *firstFace = world_sortFaces(world, firstLeaf); |
|
|
|
world_drawFaces(world, firstFace); |
|
|
|
} |