123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861 |
- //**************************************************************************
- //**
- //** 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 <math.h>
- #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)<<detailshift;
- den = FixedMul(rw_distance,sinea);
- if (den > 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<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 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<<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,j, level, 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
- =
- = 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<<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_DrawFuzzColumn;
- transcolfunc = R_DrawTranslatedColumn;
- 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;
- }
- }
- //
- // 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<<ANGLETOFINESHIFT;
- }
- #endif
- viewangle = player->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))<<FRACBITS;
- viewy += ((M_Random()%(intensity<<2))
- -(intensity<<1))<<FRACBITS;
- }
- extralight = player->extralight;
- viewz = player->viewz;
-
- tempCentery = viewheight/2+(player->lookdir)*screenblocks/10;
- if(centery != tempCentery)
- {
- centery = tempCentery;
- centeryfrac = centery<<FRACBITS;
- for(i = 0; i < viewheight; i++)
- {
- yslope[i] = FixedDiv ((viewwidth<<detailshift)/2*FRACUNIT,
- abs(((i-centery)<<FRACBITS)+FRACUNIT/2));
- }
- }
- viewsin = finesine[tableAngle];
- viewcos = finecosine[tableAngle];
- sscount = 0;
- if(player->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
- }
|