Browse Source

Implemented per-node frustum culling based on bounding spheres.

unrollquadloop
Nico de Poel 3 years ago
parent
commit
ea2b963653
  1. 6
      frustum.c
  2. 4
      frustum.h
  3. 12
      ps1bsp.h
  4. BIN
      test.ps1bsp
  5. 5
      world.c

6
frustum.c

@ -22,7 +22,7 @@ void frustum_update(int width, int height)
// FntPrint(-1, "N = %d, W = %d, H = %d\n", near, width, height); // FntPrint(-1, "N = %d, W = %d, H = %d\n", near, width, height);
// 2 * near, shifted left for division
// 2 * ONE * near
near <<= 13; near <<= 13;
l.vx = near / width; l.vx = near / width;
@ -53,7 +53,7 @@ void frustum_update(int width, int height)
// left.vx, left.pad, right.vx, right.pad, top.vz, top.pad, bottom.vz, bottom.pad); // left.vx, left.pad, right.vx, right.pad, top.vz, top.pad, bottom.vz, bottom.pad);
} }
u_char frustum_pointInside(SVECTOR *point)
u_char frustum_pointInside(const SVECTOR *point)
{ {
if (m_dot12(left, *point) + left.pad < 0) return 0; if (m_dot12(left, *point) + left.pad < 0) return 0;
if (m_dot12(right, *point) + right.pad < 0) return 0; if (m_dot12(right, *point) + right.pad < 0) return 0;
@ -62,7 +62,7 @@ u_char frustum_pointInside(SVECTOR *point)
return 1; return 1;
} }
u_char frustum_sphereInside(SVECTOR *sphere)
u_char frustum_sphereInside(const SVECTOR *sphere)
{ {
short radius = -sphere->pad; short radius = -sphere->pad;
if (m_dot12(left, *sphere) + left.pad < radius) return 0; if (m_dot12(left, *sphere) + left.pad < radius) return 0;

4
frustum.h

@ -2,7 +2,7 @@
#define __FRUSTUM_H__ #define __FRUSTUM_H__
void frustum_update(int width, int height); void frustum_update(int width, int height);
u_char frustum_pointInside(SVECTOR *point);
u_char frustum_sphereInside(SVECTOR *sphere);
u_char frustum_pointInside(const SVECTOR *point);
u_char frustum_sphereInside(const SVECTOR *sphere);
#endif // __FRUSTUM_H__ #endif // __FRUSTUM_H__

12
ps1bsp.h

@ -119,8 +119,8 @@ typedef struct
// Used for backface culling // Used for backface culling
SVECTOR center; SVECTOR center;
// Which frame was this face last drawn on? Used to check if this face should be drawn.
u_long drawFrame;
// Run-time data
u_long drawFrame; // Which frame was this face last drawn on? Used to check if this face should be drawn.
} ps1bsp_face_t; } ps1bsp_face_t;
typedef struct typedef struct
@ -136,9 +136,7 @@ typedef struct
short children[2]; short children[2];
// TODO: add bounding box for frustum culling (or bounding sphere, might be cheaper) // TODO: add bounding box for frustum culling (or bounding sphere, might be cheaper)
u_short firstFace;
u_short numFaces;
SVECTOR boundingSphere;
} ps1bsp_node_t; } ps1bsp_node_t;
typedef struct typedef struct
@ -151,6 +149,10 @@ typedef struct
u_short firstLeafFace; u_short firstLeafFace;
u_short numLeafFaces; u_short numLeafFaces;
// Run-time data
u_short nextLeaf; // For chaining leafs in drawing order
u_short leafDepth; // At what depth the leaf's faces should be placed in the ordering table
} ps1bsp_leaf_t; } ps1bsp_leaf_t;
// Pre-parsed and encoded entity data (this runs the risk of becoming too bloated) // Pre-parsed and encoded entity data (this runs the risk of becoming too bloated)

BIN
test.ps1bsp

5
world.c

@ -3,6 +3,7 @@
#include "display.h" #include "display.h"
#include "time.h" #include "time.h"
#include "draw.h" #include "draw.h"
#include "frustum.h"
static CVECTOR colors[] = static CVECTOR colors[] =
{ {
@ -212,7 +213,11 @@ static void world_drawnode(const world_t *world, short nodeIdx, u_char *pvs)
return; return;
} }
// Perform frustum culling
const ps1bsp_node_t *node = &world->nodes[nodeIdx]; const ps1bsp_node_t *node = &world->nodes[nodeIdx];
if (!frustum_sphereInside(&node->boundingSphere))
return;
const ps1bsp_plane_t *plane = &world->planes[node->planeId]; const ps1bsp_plane_t *plane = &world->planes[node->planeId];
short dist = world_pointPlaneDist(&cam_pos, plane); short dist = world_pointPlaneDist(&cam_pos, plane);

Loading…
Cancel
Save