Browse Source

Added initial frustum calculation based on screen parameters and view matrix.

unrollquadloop
Nico de Poel 3 years ago
parent
commit
0f450cf6b1
  1. 4
      display.c
  2. 56
      frustum.c
  3. 7
      frustum.h
  4. 5
      qmath.h
  5. 12
      world.c

4
display.c

@ -1,5 +1,6 @@
#include "common.h"
#include "display.h"
#include "frustum.h"
#include <inline_c.h>
@ -177,6 +178,9 @@ void display_start()
// Compose view and projection matrices to obtain a combined view-projection matrix
CompMatrixLV(&proj_matrix, &view_matrix, &vp_matrix);
int screenheight = (GetVideoMode() == MODE_NTSC) ? SCREENHEIGHT_NTSC : SCREENHEIGHT_PAL;
frustum_update(&view_matrix, (SCREENWIDTH << 12) / aspect_scale.vx, (screenheight << 12) / aspect_scale.vy);
}
void display_finish()

56
frustum.c

@ -0,0 +1,56 @@
#include "common.h"
#include "frustum.h"
#include "display.h"
#include <inline_c.h>
static SVECTOR left, right, top, bottom;
static INLINE void frustum_buildPlane(MATRIX *view_matrix, VECTOR *normal, SVECTOR *outPlane)
{
ApplyMatrixLV(view_matrix, normal, normal);
VectorNormalS(normal, outPlane);
outPlane->pad = m_dot12(cam_pos, *outPlane);
}
void frustum_update(MATRIX *view_matrix, int width, int height)
{
VECTOR l, r, t, b;
int near;
gte_ReadGeomScreen(&near);
//FntPrint(-1, "N = %d, W = %d, H = %d\n", near, width, height);
// 2 * near, shifted left for division
near <<= 13;
l.vx = near / width;
l.vy = ONE;
l.vz = 0;
b.vx = 0;
b.vy = ONE;
b.vz = near / height;
r.vx = -l.vx;
r.vy = ONE;
r.vz = 0;
t.vx = 0;
t.vy = ONE;
t.vz = -b.vz;
frustum_buildPlane(view_matrix, &l, &left);
frustum_buildPlane(view_matrix, &r, &right);
frustum_buildPlane(view_matrix, &t, &top);
frustum_buildPlane(view_matrix, &b, &bottom);
// FntPrint(-1, "l = %d %d, r = %d %d, t = %d %d, b = %d %d\n",
// left.vx, left.pad, right.vx, right.pad, top.vz, top.pad, bottom.vz, bottom.pad);
}
u_char frustum_checkSphere(SVECTOR *sphere)
{
return 1;
}

7
frustum.h

@ -0,0 +1,7 @@
#ifndef __FRUSTUM_H__
#define __FRUSTUM_H__
void frustum_update(MATRIX *view_matrix, int width, int height);
u_char frustum_checkSphere(SVECTOR *sphere);
#endif // __FRUSTUM_H__

5
qmath.h

@ -3,10 +3,7 @@
MATRIX *RotMatrixQ(SVECTOR *r, MATRIX *m);
INLINE int m_dot12s(const SVECTOR a, const SVECTOR b)
{
return (((int)a.vx * b.vx) >> 12) + (((int)a.vy * b.vy) >> 12) + (((int)a.vz * b.vz) >> 12);
}
#define m_dot12(a, b) ((((int)(a).vx * (b).vx) >> 12) + (((int)(a).vy * (b).vy) >> 12) + (((int)(a).vz * (b).vz) >> 12))
// TODO: worth a benchmark: is it faster to copy these vectors and use them from the stack, or to do six pointer dereferences?
INLINE int m_pointPlaneDist2(const VECTOR point2, const SVECTOR normal12, int dist2)

12
world.c

@ -66,7 +66,7 @@ static INLINE short world_planeDot(const SVECTOR *dir, const ps1bsp_plane_t *pla
if (plane->type < 3)
return ((short*)dir)[plane->type];
return (short)m_dot12s(*dir, plane->normal);
return (short)m_dot12(*dir, plane->normal);
}
static INLINE char world_cull_backface(const world_t *world, const ps1bsp_face_t *face, short *dot)
@ -78,8 +78,10 @@ static INLINE char world_cull_backface(const world_t *world, const ps1bsp_face_t
cam_vec.vy = face->center.vy - cam_pos.vy;
cam_vec.vz = face->center.vz - cam_pos.vz;
// Check if the face is behind the camera
short camDot = m_dot12s(cam_vec, cam_dir);
// Check if the face is behind the camera
// TODO: this may cull faces close to the camera, use VectorNormalS to normalize and check for angles < -60 degrees
// TODO: or, just check against all corners of the face...
short camDot = m_dot12(cam_vec, cam_dir);
if (camDot < 0)
return 1;
@ -199,6 +201,7 @@ static void world_drawnode(const world_t *world, short nodeIdx, u_char *pvs)
ps1bsp_face_t *face = &world->faces[*leafFace];
// Check if we've already drawn this face on the current frame
// NOTE: this can cause sorting issues when rendering front-to-back with leaf-based depth
if (face->drawFrame == frameNum)
continue;
@ -214,6 +217,7 @@ static void world_drawnode(const world_t *world, short nodeIdx, u_char *pvs)
short dist = world_pointPlaneDist(&cam_pos, plane);
// Draw child nodes in front-to-back order; adding faces to the OT will reverse the drawing order
// PLAN: traverse back-to-front to determine leaf order & depth, then draw faces front-to-back with primbuf checks
char order = dist < 0;
world_drawnode(world, node->children[order], pvs);
world_drawnode(world, node->children[order ^ 1], pvs);
@ -282,8 +286,6 @@ static u_short world_leafAtPoint(const world_t *world, const VECTOR *point)
void world_draw(const world_t *world)
{
int p;
// The world doesn't move, so we just set the camera view-projection matrix
gte_SetRotMatrix(&vp_matrix);
gte_SetTransMatrix(&vp_matrix);

Loading…
Cancel
Save