From 0df2cb80cf03d7259746834220d209b306a8c503 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Thu, 4 Sep 2008 23:15:36 +0000 Subject: Add GPLed Heretic/Hexen source. Subversion-branch: /branches/raven-branch Subversion-revision: 1195 --- src/hexen/r_main.c | 860 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 860 insertions(+) create mode 100644 src/hexen/r_main.c (limited to 'src/hexen/r_main.c') diff --git a/src/hexen/r_main.c b/src/hexen/r_main.c new file mode 100644 index 00000000..0f308748 --- /dev/null +++ b/src/hexen/r_main.c @@ -0,0 +1,860 @@ + +//************************************************************************** +//** +//** r_main.c : Heretic 2 : Raven Software, Corp. +//** +//** $RCSfile: r_main.c,v $ +//** $Revision: 1.16 $ +//** $Date: 96/01/06 18:37:41 $ +//** $Author: bgokey $ +//** +//************************************************************************** + +#include +#include "h2def.h" +#include "r_local.h" + +int viewangleoffset; + +#ifdef __WATCOMC__ +int newViewAngleOff; +#endif + +int validcount = 1; // increment every time a check is made + +lighttable_t *fixedcolormap; +extern lighttable_t **walllights; + +int centerx, centery; +fixed_t centerxfrac, centeryfrac; +fixed_t projection; + +int framecount; // just for profiling purposes + +int sscount, linecount, loopcount; + +fixed_t viewx, viewy, viewz; +angle_t viewangle; +fixed_t viewcos, viewsin; +player_t *viewplayer; + +int detailshift; // 0 = high, 1 = low + +// +// 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]; + +// the finetangentgent[angle+FINEANGLES/4] table holds the fixed_t tangent +// values for view angles, ranging from MININT to 0 to MAXINT. +// fixed_t finetangent[FINEANGLES/2]; + +// fixed_t finesine[5*FINEANGLES/4]; +fixed_t *finecosine = &finesine[FINEANGLES/4]; + + +lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; +lighttable_t *scalelightfixed[MAXLIGHTSCALE]; +lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; + +int extralight; // bumped light from gun blasts + +void (*colfunc) (void); +void (*basecolfunc) (void); +void (*fuzzcolfunc) (void); +void (*transcolfunc) (void); +void (*spanfunc) (void); + +/* +=================== += += R_AddPointToBox += +=================== +*/ + +/* +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 += += Returns side 0 (front) or 1 (back) +=============================================================================== +*/ + +int R_PointOnSide (fixed_t x, fixed_t y, node_t *node) +{ + fixed_t dx,dy; + fixed_t left, 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 ) + return 1; // (left is negative) + return 0; + } + + left = FixedMul ( node->dy>>FRACBITS , dx ); + right = FixedMul ( dy , node->dx>>FRACBITS ); + + if (right < left) + return 0; // front side + return 1; // back side +} + + +int R_PointOnSegSide (fixed_t x, fixed_t y, seg_t *line) +{ + fixed_t lx, ly; + fixed_t ldx, ldy; + fixed_t dx,dy; + fixed_t left, 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 ) + return 1; // (left is negative) + return 0; + } + + left = FixedMul ( ldy>>FRACBITS , dx ); + right = FixedMul ( dy , ldx>>FRACBITS ); + + if (right < left) + return 0; // front side + return 1; // back side +} + + +/* +=============================================================================== += += 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. The +1 size is to handle +// the case when x==y without additional checking. +#define SLOPERANGE 2048 +#define SLOPEBITS 11 +#define DBITS (FRACBITS-SLOPEBITS) + + +extern int tantoangle[SLOPERANGE+1]; // get from tables.c + +// int tantoangle[SLOPERANGE+1]; + +int SlopeDiv (unsigned num, unsigned den) +{ + unsigned ans; + if (den < 512) + return SLOPERANGE; + ans = (num<<3)/(den>>8); + return ans <= SLOPERANGE ? ans : SLOPERANGE; +} + +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) + return tantoangle[ SlopeDiv(y,x)]; // octant 0 + else + return ANG90-1-tantoangle[ SlopeDiv(x,y)]; // octant 1 + } + else + { // y<0 + y = -y; + if (x>y) + return -tantoangle[SlopeDiv(y,x)]; // octant 8 + else + return ANG270+tantoangle[ SlopeDiv(x,y)]; // octant 7 + } + } + else + { // x<0 + x = -x; + if (y>= 0) + { // y>= 0 + if (x>y) + return ANG180-1-tantoangle[ SlopeDiv(y,x)]; // octant 3 + else + return ANG90+ tantoangle[ SlopeDiv(x,y)]; // octant 2 + } + else + { // y<0 + y = -y; + if (x>y) + return ANG180+tantoangle[ SlopeDiv(y,x)]; // octant 4 + else + return ANG270-1-tantoangle[ SlopeDiv(x,y)]; // octant 5 + } + } + + 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, dy, temp; + fixed_t dist; + + dx = abs(x - viewx); + dy = abs(y - viewy); + + if (dy>dx) + { + temp = dx; + dx = dy; + dy = temp; + } + + angle = (tantoangle[ FixedDiv(dy,dx)>>DBITS ]+ANG90) >> ANGLETOFINESHIFT; + + dist = FixedDiv (dx, finesine[angle] ); // use as cosine + + return dist; +} + + + +/* +================= += += R_InitPointToAngle += +================= +*/ + +void R_InitPointToAngle (void) +{ +// 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 at the given angle += rw_distance must be calculated first +================ +*/ + +fixed_t R_ScaleFromGlobalAngle (angle_t visangle) +{ + fixed_t scale; + int anglea, angleb; + int sinea, sineb; + fixed_t num,den; + +#if 0 +{ + fixed_t dist,z; + fixed_t sinv, 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); +// bothe sines are allways positive + sinea = finesine[anglea>>ANGLETOFINESHIFT]; + sineb = finesine[angleb>>ANGLETOFINESHIFT]; + num = FixedMul(projection,sineb)< num>>16) + { + 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) +{ +// now getting from tables.c +#if 0 + int i; + float a, fv; + int t; + +// +// viewangle tangent table +// + for (i=0 ; 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 xtoviewangleangle[] +// +// 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<>= LIGHTSCALESHIFT; + level = startmap - scale/DISTMAP; + if (level < 0) + level = 0; + if (level >= NUMCOLORMAPS) + level = NUMCOLORMAPS-1; + zlight[i][j] = colormaps + level*256; + } + } +} + + +/* +============== += += R_SetViewSize += += Don't really change anything here, because i might be in the middle of += a refresh. The change will take effect next refresh. += +============== +*/ + +boolean setsizeneeded; +int setblocks, setdetail; + +void R_SetViewSize (int blocks, int detail) +{ + setsizeneeded = true; + setblocks = blocks; + setdetail = detail; +} + +/* +============== += += R_ExecuteSetViewSize += +============== +*/ + +void R_ExecuteSetViewSize (void) +{ + fixed_t cosadj, dy; + int i,j, level, startmap; + + setsizeneeded = false; + + if (setblocks == 11) + { + scaledviewwidth = SCREENWIDTH; + viewheight = SCREENHEIGHT; + } + else + { + scaledviewwidth = setblocks*32; + viewheight = (setblocks*161/10); + } + + detailshift = setdetail; + viewwidth = scaledviewwidth>>detailshift; + + centery = viewheight/2; + centerx = viewwidth/2; + centerxfrac = centerx<>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= NUMCOLORMAPS) + level = NUMCOLORMAPS-1; + scalelight[i][j] = colormaps + level*256; + } + } + +// +// draw the border +// + R_DrawViewBorder (); // erase old menu stuff +} + + +/* +============== += += R_Init += +============== +*/ + +int detailLevel; +int screenblocks; + +void R_Init(void) +{ + R_InitData(); + R_InitPointToAngle(); + R_InitTables(); + // viewwidth / viewheight / detailLevel are set by the defaults + R_SetViewSize(screenblocks, detailLevel); + R_InitPlanes(); + R_InitLightTables(); + R_InitSkyMap(); + R_InitTranslationTables(); + framecount = 0; +} + +/* +============== += += R_PointInSubsector += +============== +*/ + +subsector_t *R_PointInSubsector (fixed_t x, fixed_t y) +{ + node_t *node; + int side, nodenum; + + if (!numnodes) // single subsector is a special case + 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]; + +} + +//---------------------------------------------------------------------------- +// +// PROC R_SetupFrame +// +//---------------------------------------------------------------------------- + +void R_SetupFrame(player_t *player) +{ + int i; + int tableAngle; + int tempCentery; + int intensity; + + //drawbsp = 1; + viewplayer = player; +#ifdef __WATCOMC__ + if(newViewAngleOff) + { + viewangleoffset = newViewAngleOff<mo->angle+viewangleoffset; + tableAngle = viewangle>>ANGLETOFINESHIFT; + viewx = player->mo->x; + viewy = player->mo->y; + + if(localQuakeHappening[displayplayer] && !paused) + { + intensity = localQuakeHappening[displayplayer]; + viewx += ((M_Random() % (intensity<<2)) + -(intensity<<1))<extralight; + viewz = player->viewz; + + tempCentery = viewheight/2+(player->lookdir)*screenblocks/10; + if(centery != tempCentery) + { + centery = tempCentery; + centeryfrac = centery<fixedcolormap) + { + fixedcolormap = colormaps+player->fixedcolormap + *256*sizeof(lighttable_t); + walllights = scalelightfixed; + for(i = 0; i < MAXLIGHTSCALE; i++) + { + scalelightfixed[i] = fixedcolormap; + } + } + else + { + fixedcolormap = 0; + } + framecount++; + validcount++; + if(BorderNeedRefresh) + { + if(setblocks < 10) + { + R_DrawViewBorder(); + } + BorderNeedRefresh = false; + BorderTopRefresh = false; + UpdateState |= I_FULLSCRN; + } + if(BorderTopRefresh) + { + if(setblocks < 10) + { + R_DrawTopBorder(); + } + BorderTopRefresh = false; + UpdateState |= I_MESSAGES; + } + +#ifdef __NeXT__ + RD_ClearMapWindow (); +#endif +#ifdef __WATCOMC__ + destview = destscreen+(viewwindowx>>2)+viewwindowy*80; +#endif + +#if 0 +{ +static int frame; +memset (screen, frame, SCREENWIDTH*SCREENHEIGHT); +frame++; +} +#endif +} + +/* +============== += += R_RenderView += +============== +*/ + +void R_RenderPlayerView (player_t *player) +{ + R_SetupFrame (player); + R_ClearClipSegs (); + R_ClearDrawSegs (); + R_ClearPlanes (); + R_ClearSprites (); + NetUpdate (); // check for new console commands + + // Make displayed player invisible locally + if (localQuakeHappening[displayplayer] && gamestate == GS_LEVEL) + { + players[displayplayer].mo->flags2 |= MF2_DONTDRAW; + R_RenderBSPNode (numnodes-1); // head node is the last node output + players[displayplayer].mo->flags2 &= ~MF2_DONTDRAW; + } + else + { + R_RenderBSPNode (numnodes-1); // head node is the last node output + } + + NetUpdate (); // check for new console commands + R_DrawPlanes (); + NetUpdate (); // check for new console commands + R_DrawMasked (); + NetUpdate (); // check for new console commands +} -- cgit v1.2.3