mirror of
https://github.com/jndean/IPUDOOM.git
synced 2026-06-24 21:58:50 +00:00
764 lines
15 KiB
C
764 lines
15 KiB
C
//
|
|
// Copyright(C) 1993-1996 Id Software, Inc.
|
|
// Copyright(C) 2005-2014 Simon Howard
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// DESCRIPTION:
|
|
// Rendering main loop and setup functions,
|
|
// utility functions (BSP, geometry, trigonometry).
|
|
// See tables.c, too.
|
|
//
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "d_loop.h"
|
|
#include "d_player.h"
|
|
#include "doomdata.h"
|
|
#include "doomtype.h"
|
|
#include "i_video.h"
|
|
#include "m_bbox.h"
|
|
#include "m_fixed.h"
|
|
#include "m_menu.h"
|
|
#include "p_mobj.h"
|
|
#include "r_bsp.h"
|
|
#include "r_data.h"
|
|
#include "r_defs.h"
|
|
#include "r_draw.h"
|
|
#include "r_main.h"
|
|
#include "r_plane.h"
|
|
#include "r_sky.h"
|
|
#include "r_state.h"
|
|
#include "r_things.h"
|
|
#include "tables.h"
|
|
|
|
#include "ipu_host.h"
|
|
#include "doomstat.h" // TMP< REMOVEME
|
|
|
|
// Fineangles in the SCREENWIDTH wide window.
|
|
#define FIELDOFVIEW 2048
|
|
|
|
int viewangleoffset;
|
|
|
|
// increment every time a check is made
|
|
int validcount = 1;
|
|
|
|
lighttable_t *fixedcolormap;
|
|
extern lighttable_t **walllights;
|
|
|
|
int centerx;
|
|
int centery;
|
|
|
|
fixed_t centerxfrac;
|
|
fixed_t centeryfrac;
|
|
fixed_t projection;
|
|
|
|
// just for profiling purposes
|
|
int framecount;
|
|
|
|
int sscount;
|
|
int linecount;
|
|
int loopcount;
|
|
|
|
fixed_t viewx;
|
|
fixed_t viewy;
|
|
fixed_t viewz;
|
|
|
|
angle_t viewangle;
|
|
|
|
fixed_t viewcos;
|
|
fixed_t viewsin;
|
|
|
|
player_t *viewplayer;
|
|
|
|
// 0 = high, 1 = low
|
|
int detailshift;
|
|
|
|
//
|
|
// precalculated math tables
|
|
//
|
|
angle_t clipangle;
|
|
|
|
// The viewangletox[viewangle + FINEANGLES/4] lookup
|
|
// maps the visible view angles to screen X coordinates,
|
|
// flattening the arc to a flat projection plane.
|
|
// There will be many angles mapped to the same X.
|
|
int viewangletox[FINEANGLES / 2];
|
|
|
|
// The xtoviewangleangle[] table maps a screen pixel
|
|
// to the lowest viewangle that maps back to x ranges
|
|
// from clipangle to -clipangle.
|
|
angle_t xtoviewangle[SCREENWIDTH + 1];
|
|
|
|
lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
|
|
lighttable_t *scalelightfixed[MAXLIGHTSCALE];
|
|
lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
|
|
|
|
// bumped light from gun blasts
|
|
int extralight;
|
|
|
|
int renderIPUonly; // JOSEF
|
|
|
|
void (*colfunc)(void);
|
|
void (*basecolfunc)(void);
|
|
void (*fuzzcolfunc)(void);
|
|
void (*transcolfunc)(void);
|
|
void (*spanfunc)(void);
|
|
|
|
//
|
|
// R_AddPointToBox
|
|
// Expand a given bbox
|
|
// so that it encloses a given point.
|
|
//
|
|
void R_AddPointToBox(int x, int y, fixed_t *box) {
|
|
if (x < box[BOXLEFT])
|
|
box[BOXLEFT] = x;
|
|
if (x > box[BOXRIGHT])
|
|
box[BOXRIGHT] = x;
|
|
if (y < box[BOXBOTTOM])
|
|
box[BOXBOTTOM] = y;
|
|
if (y > box[BOXTOP])
|
|
box[BOXTOP] = y;
|
|
}
|
|
|
|
//
|
|
// R_PointOnSide
|
|
// Traverse BSP (sub) tree,
|
|
// check point against partition plane.
|
|
// Returns side 0 (front) or 1 (back).
|
|
//
|
|
int R_PointOnSide(fixed_t x, fixed_t y, node_t *node) {
|
|
fixed_t dx;
|
|
fixed_t dy;
|
|
fixed_t left;
|
|
fixed_t right;
|
|
|
|
if (!node->dx) {
|
|
if (x <= node->x)
|
|
return node->dy > 0;
|
|
|
|
return node->dy < 0;
|
|
}
|
|
if (!node->dy) {
|
|
if (y <= node->y)
|
|
return node->dx < 0;
|
|
|
|
return node->dx > 0;
|
|
}
|
|
|
|
dx = (x - node->x);
|
|
dy = (y - node->y);
|
|
|
|
// Try to quickly decide by looking at sign bits.
|
|
if ((node->dy ^ node->dx ^ dx ^ dy) & 0x80000000) {
|
|
if ((node->dy ^ dx) & 0x80000000) {
|
|
// (left is negative)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
left = FixedMul(node->dy >> FRACBITS, dx);
|
|
right = FixedMul(dy, node->dx >> FRACBITS);
|
|
|
|
if (right < left) {
|
|
// front side
|
|
return 0;
|
|
}
|
|
// back side
|
|
return 1;
|
|
}
|
|
|
|
int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line) {
|
|
fixed_t lx;
|
|
fixed_t ly;
|
|
fixed_t ldx;
|
|
fixed_t ldy;
|
|
fixed_t dx;
|
|
fixed_t dy;
|
|
fixed_t left;
|
|
fixed_t right;
|
|
|
|
lx = line->v1->x;
|
|
ly = line->v1->y;
|
|
|
|
ldx = line->v2->x - lx;
|
|
ldy = line->v2->y - ly;
|
|
|
|
if (!ldx) {
|
|
if (x <= lx)
|
|
return ldy > 0;
|
|
|
|
return ldy < 0;
|
|
}
|
|
if (!ldy) {
|
|
if (y <= ly)
|
|
return ldx < 0;
|
|
|
|
return ldx > 0;
|
|
}
|
|
|
|
dx = (x - lx);
|
|
dy = (y - ly);
|
|
|
|
// Try to quickly decide by looking at sign bits.
|
|
if ((ldy ^ ldx ^ dx ^ dy) & 0x80000000) {
|
|
if ((ldy ^ dx) & 0x80000000) {
|
|
// (left is negative)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
left = FixedMul(ldy >> FRACBITS, dx);
|
|
right = FixedMul(dy, ldx >> FRACBITS);
|
|
|
|
if (right < left) {
|
|
// front side
|
|
return 0;
|
|
}
|
|
// back side
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// R_PointToAngle
|
|
// To get a global angle from cartesian coordinates,
|
|
// the coordinates are flipped until they are in
|
|
// the first octant of the coordinate system, then
|
|
// the y (<=x) is scaled and divided by x to get a
|
|
// tangent (slope) value which is looked up in the
|
|
// tantoangle[] table.
|
|
|
|
//
|
|
|
|
angle_t R_PointToAngle(fixed_t x, fixed_t y) {
|
|
x -= viewx;
|
|
y -= viewy;
|
|
|
|
if ((!x) && (!y))
|
|
return 0;
|
|
|
|
if (x >= 0) {
|
|
// x >=0
|
|
if (y >= 0) {
|
|
// y>= 0
|
|
|
|
if (x > y) {
|
|
// octant 0
|
|
return tantoangle[SlopeDiv(y, x)];
|
|
} else {
|
|
// octant 1
|
|
return ANG90 - 1 - tantoangle[SlopeDiv(x, y)];
|
|
}
|
|
} else {
|
|
// y<0
|
|
y = -y;
|
|
|
|
if (x > y) {
|
|
// octant 8
|
|
return -tantoangle[SlopeDiv(y, x)];
|
|
} else {
|
|
// octant 7
|
|
return ANG270 + tantoangle[SlopeDiv(x, y)];
|
|
}
|
|
}
|
|
} else {
|
|
// x<0
|
|
x = -x;
|
|
|
|
if (y >= 0) {
|
|
// y>= 0
|
|
if (x > y) {
|
|
// octant 3
|
|
return ANG180 - 1 - tantoangle[SlopeDiv(y, x)];
|
|
} else {
|
|
// octant 2
|
|
return ANG90 + tantoangle[SlopeDiv(x, y)];
|
|
}
|
|
} else {
|
|
// y<0
|
|
y = -y;
|
|
|
|
if (x > y) {
|
|
// octant 4
|
|
return ANG180 + tantoangle[SlopeDiv(y, x)];
|
|
} else {
|
|
// octant 5
|
|
return ANG270 - 1 - tantoangle[SlopeDiv(x, y)];
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) {
|
|
viewx = x1;
|
|
viewy = y1;
|
|
|
|
return R_PointToAngle(x2, y2);
|
|
}
|
|
|
|
fixed_t R_PointToDist(fixed_t x, fixed_t y) {
|
|
int angle;
|
|
fixed_t dx;
|
|
fixed_t dy;
|
|
fixed_t temp;
|
|
fixed_t dist;
|
|
fixed_t frac;
|
|
|
|
dx = abs(x - viewx);
|
|
dy = abs(y - viewy);
|
|
|
|
if (dy > dx) {
|
|
temp = dx;
|
|
dx = dy;
|
|
dy = temp;
|
|
}
|
|
|
|
// Fix crashes in udm1.wad
|
|
|
|
if (dx != 0) {
|
|
frac = FixedDiv(dy, dx);
|
|
} else {
|
|
frac = 0;
|
|
}
|
|
|
|
angle = (tantoangle[frac >> DBITS] + ANG90) >> ANGLETOFINESHIFT;
|
|
|
|
// use as cosine
|
|
dist = FixedDiv(dx, finesine[angle]);
|
|
|
|
return dist;
|
|
}
|
|
|
|
//
|
|
// R_InitPointToAngle
|
|
//
|
|
void R_InitPointToAngle(void) {
|
|
// UNUSED - now getting from tables.c
|
|
#if 0
|
|
int i;
|
|
long t;
|
|
float f;
|
|
//
|
|
// slope (tangent) to angle lookup
|
|
//
|
|
for (i=0 ; i<=SLOPERANGE ; i++)
|
|
{
|
|
f = atan( (float)i/SLOPERANGE )/(3.141592657*2);
|
|
t = 0xffffffff*f;
|
|
tantoangle[i] = t;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// R_ScaleFromGlobalAngle
|
|
// Returns the texture mapping scale
|
|
// for the current line (horizontal span)
|
|
// at the given angle.
|
|
// rw_distance must be calculated first.
|
|
//
|
|
fixed_t R_ScaleFromGlobalAngle(angle_t visangle) {
|
|
fixed_t scale;
|
|
angle_t anglea;
|
|
angle_t angleb;
|
|
int sinea;
|
|
int sineb;
|
|
fixed_t num;
|
|
int den;
|
|
|
|
// UNUSED
|
|
#if 0
|
|
{
|
|
fixed_t dist;
|
|
fixed_t z;
|
|
fixed_t sinv;
|
|
fixed_t cosv;
|
|
|
|
sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT];
|
|
dist = FixedDiv (rw_distance, sinv);
|
|
cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT];
|
|
z = abs(FixedMul (dist, cosv));
|
|
scale = FixedDiv(projection, z);
|
|
return scale;
|
|
}
|
|
#endif
|
|
|
|
anglea = ANG90 + (visangle - viewangle);
|
|
angleb = ANG90 + (visangle - rw_normalangle);
|
|
|
|
// both sines are allways positive
|
|
sinea = finesine[anglea >> ANGLETOFINESHIFT];
|
|
sineb = finesine[angleb >> ANGLETOFINESHIFT];
|
|
num = FixedMul(projection, sineb) << detailshift;
|
|
den = FixedMul(rw_distance, sinea);
|
|
|
|
if (den > num >> FRACBITS) {
|
|
scale = FixedDiv(num, den);
|
|
|
|
if (scale > 64 * FRACUNIT)
|
|
scale = 64 * FRACUNIT;
|
|
else if (scale < 256)
|
|
scale = 256;
|
|
} else
|
|
scale = 64 * FRACUNIT;
|
|
|
|
return scale;
|
|
}
|
|
|
|
//
|
|
// R_InitTables
|
|
//
|
|
void R_InitTables(void) {
|
|
// UNUSED: now getting from tables.c
|
|
#if 0
|
|
int i;
|
|
float a;
|
|
float fv;
|
|
int t;
|
|
|
|
// viewangle tangent table
|
|
for (i=0 ; i<FINEANGLES/2 ; i++)
|
|
{
|
|
a = (i-FINEANGLES/4+0.5)*PI*2/FINEANGLES;
|
|
fv = FRACUNIT*tan (a);
|
|
t = fv;
|
|
finetangent[i] = t;
|
|
}
|
|
|
|
// finesine table
|
|
for (i=0 ; i<5*FINEANGLES/4 ; i++)
|
|
{
|
|
// OPTIMIZE: mirror...
|
|
a = (i+0.5)*PI*2/FINEANGLES;
|
|
t = FRACUNIT*sin (a);
|
|
finesine[i] = t;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// R_InitTextureMapping
|
|
//
|
|
void R_InitTextureMapping(void) {
|
|
int i;
|
|
int x;
|
|
int t;
|
|
fixed_t focallength;
|
|
|
|
// Use tangent table to generate viewangletox:
|
|
// viewangletox will give the next greatest x
|
|
// after the view angle.
|
|
//
|
|
// Calc focallength
|
|
// so FIELDOFVIEW angles covers SCREENWIDTH.
|
|
focallength =
|
|
FixedDiv(centerxfrac, finetangent[FINEANGLES / 4 + FIELDOFVIEW / 2]);
|
|
|
|
for (i = 0; i < FINEANGLES / 2; i++) {
|
|
if (finetangent[i] > FRACUNIT * 2)
|
|
t = -1;
|
|
else if (finetangent[i] < -FRACUNIT * 2)
|
|
t = viewwidth + 1;
|
|
else {
|
|
t = FixedMul(finetangent[i], focallength);
|
|
t = (centerxfrac - t + FRACUNIT - 1) >> FRACBITS;
|
|
|
|
if (t < -1)
|
|
t = -1;
|
|
else if (t > viewwidth + 1)
|
|
t = viewwidth + 1;
|
|
}
|
|
viewangletox[i] = t;
|
|
}
|
|
|
|
// Scan viewangletox[] to generate xtoviewangle[]:
|
|
// xtoviewangle will give the smallest view angle
|
|
// that maps to x.
|
|
for (x = 0; x <= viewwidth; x++) {
|
|
i = 0;
|
|
while (viewangletox[i] > x)
|
|
i++;
|
|
xtoviewangle[x] = (i << ANGLETOFINESHIFT) - ANG90;
|
|
}
|
|
|
|
// Take out the fencepost cases from viewangletox.
|
|
for (i = 0; i < FINEANGLES / 2; i++) {
|
|
t = FixedMul(finetangent[i], focallength);
|
|
t = centerx - t;
|
|
|
|
if (viewangletox[i] == -1)
|
|
viewangletox[i] = 0;
|
|
else if (viewangletox[i] == viewwidth + 1)
|
|
viewangletox[i] = viewwidth;
|
|
}
|
|
|
|
clipangle = xtoviewangle[0];
|
|
}
|
|
|
|
//
|
|
// R_InitLightTables
|
|
// Only inits the zlight table,
|
|
// because the scalelight table changes with view size.
|
|
//
|
|
#define DISTMAP 2
|
|
|
|
void R_InitLightTables(void) {
|
|
int i;
|
|
int j;
|
|
int level;
|
|
int startmap;
|
|
int scale;
|
|
|
|
// Calculate the light levels to use
|
|
// for each level / distance combination.
|
|
for (i = 0; i < LIGHTLEVELS; i++) {
|
|
startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS;
|
|
for (j = 0; j < MAXLIGHTZ; j++) {
|
|
scale = FixedDiv((SCREENWIDTH / 2 * FRACUNIT), (j + 1) << LIGHTZSHIFT);
|
|
scale >>= LIGHTSCALESHIFT;
|
|
level = startmap - scale / DISTMAP;
|
|
|
|
if (level < 0)
|
|
level = 0;
|
|
|
|
if (level >= NUMCOLORMAPS)
|
|
level = NUMCOLORMAPS - 1;
|
|
|
|
zlight[i][j] = colormaps + level * 256;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// R_SetViewSize
|
|
// Do not really change anything here,
|
|
// because it might be in the middle of a refresh.
|
|
// The change will take effect next refresh.
|
|
//
|
|
boolean setsizeneeded;
|
|
int setblocks;
|
|
int setdetail;
|
|
|
|
void R_SetViewSize(int blocks, int detail) {
|
|
setsizeneeded = true;
|
|
setblocks = blocks;
|
|
setdetail = detail;
|
|
}
|
|
|
|
//
|
|
// R_ExecuteSetViewSize
|
|
//
|
|
void R_ExecuteSetViewSize(void) {
|
|
|
|
IPU_R_ExecuteSetViewSize();
|
|
|
|
fixed_t cosadj;
|
|
fixed_t dy;
|
|
int i;
|
|
int j;
|
|
int level;
|
|
int startmap;
|
|
|
|
setsizeneeded = false;
|
|
|
|
if (setblocks == 11) {
|
|
scaledviewwidth = SCREENWIDTH;
|
|
viewheight = SCREENHEIGHT;
|
|
} else {
|
|
scaledviewwidth = setblocks * 32;
|
|
viewheight = (setblocks * 168 / 10) & ~7;
|
|
}
|
|
|
|
detailshift = setdetail;
|
|
viewwidth = scaledviewwidth >> detailshift;
|
|
|
|
centery = viewheight / 2;
|
|
centerx = viewwidth / 2;
|
|
centerxfrac = centerx << FRACBITS;
|
|
centeryfrac = centery << FRACBITS;
|
|
projection = centerxfrac;
|
|
|
|
if (!detailshift) {
|
|
colfunc = basecolfunc = R_DrawColumn;
|
|
fuzzcolfunc = R_DrawFuzzColumn;
|
|
transcolfunc = R_DrawTranslatedColumn;
|
|
spanfunc = R_DrawSpan;
|
|
} else {
|
|
colfunc = basecolfunc = R_DrawColumnLow;
|
|
fuzzcolfunc = R_DrawFuzzColumnLow;
|
|
transcolfunc = R_DrawTranslatedColumnLow;
|
|
spanfunc = R_DrawSpanLow;
|
|
}
|
|
|
|
R_InitBuffer(scaledviewwidth, viewheight);
|
|
|
|
R_InitTextureMapping();
|
|
|
|
// psprite scales
|
|
pspritescale = FRACUNIT * viewwidth / SCREENWIDTH;
|
|
pspriteiscale = FRACUNIT * SCREENWIDTH / viewwidth;
|
|
|
|
// thing clipping
|
|
for (i = 0; i < viewwidth; i++)
|
|
screenheightarray[i] = viewheight;
|
|
|
|
// planes
|
|
for (i = 0; i < viewheight; i++) {
|
|
dy = ((i - viewheight / 2) << FRACBITS) + FRACUNIT / 2;
|
|
dy = abs(dy);
|
|
yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, dy);
|
|
}
|
|
|
|
for (i = 0; i < viewwidth; i++) {
|
|
cosadj = abs(finecosine[xtoviewangle[i] >> ANGLETOFINESHIFT]);
|
|
distscale[i] = FixedDiv(FRACUNIT, cosadj);
|
|
}
|
|
|
|
// Calculate the light levels to use
|
|
// for each level / scale combination.
|
|
for (i = 0; i < LIGHTLEVELS; i++) {
|
|
startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS;
|
|
for (j = 0; j < MAXLIGHTSCALE; j++) {
|
|
level = startmap - j * SCREENWIDTH / (viewwidth << detailshift) / DISTMAP;
|
|
|
|
if (level < 0)
|
|
level = 0;
|
|
|
|
if (level >= NUMCOLORMAPS)
|
|
level = NUMCOLORMAPS - 1;
|
|
|
|
scalelight[i][j] = colormaps + level * 256;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// R_Init
|
|
//
|
|
|
|
void R_Init(void) {
|
|
|
|
R_InitData();
|
|
printf(".");
|
|
R_InitPointToAngle();
|
|
printf(".");
|
|
R_InitTables();
|
|
// viewwidth / viewheight / detailLevel are set by the defaults
|
|
printf(".");
|
|
|
|
R_SetViewSize(screenblocks, detailLevel);
|
|
R_InitPlanes();
|
|
printf(".");
|
|
R_InitLightTables();
|
|
printf(".");
|
|
R_InitSkyMap();
|
|
R_InitTranslationTables();
|
|
printf(".");
|
|
|
|
framecount = 0;
|
|
|
|
IPU_R_Init();
|
|
}
|
|
|
|
//
|
|
// R_PointInSubsector
|
|
//
|
|
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) {
|
|
node_t *node;
|
|
int side;
|
|
int nodenum;
|
|
|
|
// single subsector is a special case
|
|
if (!numnodes)
|
|
return subsectors;
|
|
|
|
nodenum = numnodes - 1;
|
|
|
|
while (!(nodenum & NF_SUBSECTOR)) {
|
|
node = &nodes[nodenum];
|
|
side = R_PointOnSide(x, y, node);
|
|
nodenum = node->children[side];
|
|
}
|
|
|
|
return &subsectors[nodenum & ~NF_SUBSECTOR];
|
|
}
|
|
|
|
//
|
|
// R_SetupFrame
|
|
//
|
|
void R_SetupFrame(player_t *player) {
|
|
int i;
|
|
|
|
viewplayer = player;
|
|
viewx = player->mo->x;
|
|
viewy = player->mo->y;
|
|
viewangle = player->mo->angle + viewangleoffset;
|
|
extralight = player->extralight;
|
|
|
|
viewz = player->viewz;
|
|
|
|
viewsin = finesine[viewangle >> ANGLETOFINESHIFT];
|
|
viewcos = finecosine[viewangle >> ANGLETOFINESHIFT];
|
|
|
|
sscount = 0;
|
|
|
|
if (player->fixedcolormap) {
|
|
fixedcolormap = colormaps + player->fixedcolormap * 256;
|
|
|
|
walllights = scalelightfixed;
|
|
|
|
for (i = 0; i < MAXLIGHTSCALE; i++)
|
|
scalelightfixed[i] = fixedcolormap;
|
|
} else
|
|
fixedcolormap = 0;
|
|
|
|
framecount++;
|
|
validcount++;
|
|
}
|
|
|
|
//
|
|
// R_RenderView
|
|
//
|
|
void R_RenderPlayerView(player_t *player) {
|
|
R_SetupFrame(player);
|
|
|
|
// Clear buffers.
|
|
R_ClearClipSegs();
|
|
R_ClearDrawSegs();
|
|
R_ClearPlanes();
|
|
R_ClearSprites();
|
|
|
|
// check for new console commands.
|
|
NetUpdate();
|
|
|
|
// The head node is the last node output.
|
|
R_RenderBSPNode(numnodes - 1);
|
|
|
|
// Check for new console commands.
|
|
NetUpdate();
|
|
|
|
// R_DrawPlanes();
|
|
|
|
// Check for new console commands.
|
|
// NetUpdate();
|
|
|
|
IPU_R_RenderPlayerView();
|
|
|
|
if (!renderIPUonly) R_DrawMasked();
|
|
|
|
// Check for new console commands.
|
|
NetUpdate();
|
|
}
|