123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code 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 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code 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.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "Precompiled.h"
- #include "globaldata.h"
- #include <stdlib.h>
- #include <math.h>
- #include "doomdef.h"
- #include "d_net.h"
- #include "m_bbox.h"
- #include "r_local.h"
- #include "r_sky.h"
- #include "i_system.h"
- // Fineangles in the SCREENWIDTH wide window.
- // increment every time a check is made
- // just for profiling purposes
- // 0 = high, 1 = low
- //
- // precalculated math tables
- //
- // The ::g->viewangletox[::g->viewangle + FINEANGLES/4] lookup
- // maps the visible view angles to screen X coordinates,
- // flattening the arc to a flat ::g->projection plane.
- // There will be many angles mapped to the same X.
- // The xtoviewangleangle[] table maps a screen pixel
- // to the lowest ::g->viewangle that maps back to x ranges
- // from ::g->clipangle to -::g->clipangle.
- // UNUSED.
- // 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];
- const fixed_t* finecosine = &finesine[FINEANGLES/4];
- // bumped light from gun blasts
- void (*colfunc) (lighttable_t * dc_colormap,
- byte * dc_source);
- void (*basecolfunc) (lighttable_t * dc_colormap,
- byte * dc_source);
- void (*fuzzcolfunc) (lighttable_t * dc_colormap,
- byte * dc_source);
- void (*transcolfunc) (lighttable_t * dc_colormap,
- byte * dc_source);
- void (*spanfunc) (fixed_t xfrac,
- fixed_t yfrac,
- fixed_t ds_y,
- int ds_x1,
- int ds_x2,
- fixed_t ds_xstep,
- fixed_t ds_ystep,
- lighttable_t * ds_colormap,
- byte * ds_source);
- //
- // 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 )
- {
- extern fixed_t GetViewX(); extern fixed_t GetViewY();
- x -= GetViewX();
- y -= GetViewY();
- 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)]; // // ALANHACK UNSIGNED
- }
- 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 )
- {
- extern void SetViewX( fixed_t ); extern void SetViewY( fixed_t );
- SetViewX( x1 );
- SetViewY( 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;
- extern fixed_t GetViewX(); extern fixed_t GetViewY();
- dx = abs(x - GetViewX());
- dy = abs(y - GetViewY());
- if (dy>dx)
- {
- temp = dx;
- dx = dy;
- dy = temp;
- }
- angle = (tantoangle[ FixedDiv(dy,dx)>>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.
- // ::g->rw_distance must be calculated first.
- //
- fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
- {
- fixed_t scale;
- //int anglea;
- //int angleb;
- 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-::g->rw_normalangle)>>ANGLETOFINESHIFT];
- dist = FixedDiv (::g->rw_distance, sinv);
- cosv = finecosine[(::g->viewangle-visangle)>>ANGLETOFINESHIFT];
- z = abs(FixedMul (dist, cosv));
- scale = FixedDiv(::g->projection, z);
- return scale;
- }
- #endif
- extern angle_t GetViewAngle();
- anglea = ANG90 + (visangle-GetViewAngle());
- angleb = ANG90 + (visangle-::g->rw_normalangle);
- // both sines are allways positive
- sinea = finesine[anglea>>ANGLETOFINESHIFT];
- sineb = finesine[angleb>>ANGLETOFINESHIFT];
- num = FixedMul(::g->projection,sineb) << ::g->detailshift;
- den = FixedMul(::g->rw_distance,sinea);
- // DHM - Nerve :: If the den is pretty much 0, don't try the divide
- if (den>>8 > 0 && 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)
- {
- // UNUSED: now getting from tables.c
- #if 0
- int i;
- float a;
- float fv;
- int t;
- // ::g->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:
- // ::g->viewangletox will give the next greatest x
- // after the view angle.
- //
- // Calc focallength
- // so FIELDOFVIEW angles covers SCREENWIDTH.
- focallength = FixedDiv (::g->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 = ::g->viewwidth+1;
- else
- {
- t = FixedMul (finetangent[i], focallength);
- t = (::g->centerxfrac - t+FRACUNIT-1)>>FRACBITS;
- if (t < -1)
- t = -1;
- else if (t>::g->viewwidth+1)
- t = ::g->viewwidth+1;
- }
- ::g->viewangletox[i] = t;
- }
- // Scan ::g->viewangletox[] to generate ::g->xtoviewangle[]:
- // ::g->xtoviewangle will give the smallest view angle
- // that maps to x.
- for (x=0;x<=::g->viewwidth;x++)
- {
- i = 0;
- while (::g->viewangletox[i]>x)
- i++;
- ::g->xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
- }
- // Take out the fencepost cases from ::g->viewangletox.
- for (i=0 ; i<FINEANGLES/2 ; i++)
- {
- t = FixedMul (finetangent[i], focallength);
- t = ::g->centerx - t;
- if (::g->viewangletox[i] == -1)
- ::g->viewangletox[i] = 0;
- else if (::g->viewangletox[i] == ::g->viewwidth+1)
- ::g->viewangletox[i] = ::g->viewwidth;
- }
- ::g->clipangle = ::g->xtoviewangle[0];
- }
- //
- // R_InitLightTables
- // Only inits the ::g->zlight table,
- // because the ::g->scalelight table changes with view size.
- //
- void R_InitLightTables (void)
- {
- int i;
- int j;
- int level;
- int nocollide_startmap;
- int scale;
- // Calculate the light levels to use
- // for each level / distance combination.
- for (i=0 ; i< LIGHTLEVELS ; i++)
- {
- nocollide_startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
- for (j=0 ; j<MAXLIGHTZ ; j++)
- {
- scale = FixedDiv ((SCREENWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
- scale >>= LIGHTSCALESHIFT;
- level = nocollide_startmap - scale/DISTMAP;
- if (level < 0)
- level = 0;
- if (level >= NUMCOLORMAPS)
- level = NUMCOLORMAPS-1;
- ::g->zlight[i][j] = ::g->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.
- //
- void
- R_SetViewSize
- ( int blocks,
- int detail )
- {
- ::g->setsizeneeded = true;
- ::g->setblocks = blocks;
- ::g->setdetail = detail;
- }
- //
- // R_ExecuteSetViewSize
- //
- void R_ExecuteSetViewSize (void)
- {
- fixed_t cosadj;
- fixed_t dy;
- int i;
- int j;
- int level;
- int nocollide_startmap;
- ::g->setsizeneeded = false;
- if (::g->setblocks == 11)
- {
- ::g->scaledviewwidth = ORIGINAL_WIDTH;
- ::g->viewheight = ORIGINAL_HEIGHT;
- }
- else
- {
- ::g->scaledviewwidth = ::g->setblocks*32;
- ::g->viewheight = (::g->setblocks*168/10)&~7;
- }
- // SMF - temp
- ::g->scaledviewwidth *= GLOBAL_IMAGE_SCALER;
- ::g->viewheight *= GLOBAL_IMAGE_SCALER;
- ::g->detailshift = ::g->setdetail;
- ::g->viewwidth = ::g->scaledviewwidth>>::g->detailshift;
- ::g->centery = ::g->viewheight/2;
- ::g->centerx = ::g->viewwidth/2;
- ::g->centerxfrac = ::g->centerx<<FRACBITS;
- ::g->centeryfrac = ::g->centery<<FRACBITS;
- ::g->projection = ::g->centerxfrac;
- if (!::g->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 (::g->scaledviewwidth, ::g->viewheight);
- R_InitTextureMapping ();
- // psprite scales
- ::g->pspritescale = FRACUNIT*::g->viewwidth/ORIGINAL_WIDTH;
- ::g->pspriteiscale = FRACUNIT*ORIGINAL_WIDTH/::g->viewwidth;
- // thing clipping
- for (i=0 ; i < ::g->viewwidth ; i++)
- ::g->screenheightarray[i] = ::g->viewheight;
- // planes
- for (i=0 ; i < ::g->viewheight ; i++)
- {
- dy = ((i-::g->viewheight/2)<<FRACBITS)+FRACUNIT/2;
- dy = abs(dy);
- ::g->yslope[i] = FixedDiv ( (::g->viewwidth << ::g->detailshift)/2*FRACUNIT, dy);
- }
- for (i=0 ; i < ::g->viewwidth ; i++)
- {
- cosadj = abs(finecosine[::g->xtoviewangle[i]>>ANGLETOFINESHIFT]);
- ::g->distscale[i] = FixedDiv (FRACUNIT,cosadj);
- }
- // Calculate the light levels to use
- // for each level / scale combination.
- for (i=0 ; i< LIGHTLEVELS ; i++)
- {
- nocollide_startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
- for (j=0 ; j<MAXLIGHTSCALE ; j++)
- {
- level = nocollide_startmap - j*SCREENWIDTH/(::g->viewwidth << ::g->detailshift)/DISTMAP;
- if (level < 0)
- level = 0;
- if (level >= NUMCOLORMAPS)
- level = NUMCOLORMAPS-1;
- ::g->scalelight[i][j] = ::g->colormaps + level*256;
- }
- }
- }
- //
- // R_Init
- //
- void R_Init (void)
- {
- R_InitData ();
- I_Printf ("\nR_InitData");
- R_InitPointToAngle ();
- I_Printf ("\nR_InitPointToAngle");
- R_InitTables ();
- // ::g->viewwidth / ::g->viewheight / ::g->detailLevel are set by the defaults
- I_Printf ("\nR_InitTables");
- R_SetViewSize (::g->screenblocks, ::g->detailLevel);
- R_InitPlanes ();
- I_Printf ("\nR_InitPlanes");
- R_InitLightTables ();
- I_Printf ("\nR_InitLightTables");
- R_InitSkyMap ();
- I_Printf ("\nR_InitSkyMap");
- R_InitTranslationTables ();
- I_Printf ("\nR_InitTranslationsTables");
- ::g->framecount = 0;
- }
- //
- // 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 (!::g->numnodes)
- return ::g->subsectors;
- nodenum = ::g->numnodes-1;
- while (! (nodenum & NF_SUBSECTOR) )
- {
- node = &::g->nodes[nodenum];
- side = R_PointOnSide (x, y, node);
- nodenum = node->children[side];
- }
- return &::g->subsectors[nodenum & ~NF_SUBSECTOR];
- }
- //
- // R_SetupFrame
- //
- void R_SetupFrame (player_t* player)
- {
- int i;
- ::g->viewplayer = player;
- extern void SetViewX( fixed_t ); extern void SetViewY( fixed_t ); extern void SetViewAngle( angle_t );
- SetViewX( player->mo->x );
- SetViewY( player->mo->y );
- SetViewAngle( player->mo->angle + ::g->viewangleoffset );
- ::g->extralight = player->extralight;
- ::g->viewz = player->viewz;
- extern angle_t GetViewAngle();
- ::g->viewsin = finesine[GetViewAngle()>>ANGLETOFINESHIFT];
- ::g->viewcos = finecosine[GetViewAngle()>>ANGLETOFINESHIFT];
- ::g->sscount = 0;
- if (player->fixedcolormap)
- {
- ::g->fixedcolormap =
- ::g->colormaps
- + player->fixedcolormap*256*sizeof(lighttable_t);
- ::g->walllights = ::g->scalelightfixed;
- for (i=0 ; i<MAXLIGHTSCALE ; i++)
- ::g->scalelightfixed[i] = ::g->fixedcolormap;
- }
- else
- ::g->fixedcolormap = 0;
- ::g->framecount++;
- ::g->validcount++;
- }
- //
- // R_RenderView
- //
- void R_RenderPlayerView (player_t* player)
- {
- if ( player->mo == NULL ) {
- return;
- }
- R_SetupFrame (player);
- // Clear buffers.
- R_ClearClipSegs ();
- R_ClearDrawSegs ();
- R_ClearPlanes ();
- R_ClearSprites ();
- // check for new console commands.
- NetUpdate ( NULL );
- // The head node is the last node output.
- R_RenderBSPNode (::g->numnodes-1);
- // Check for new console commands.
- NetUpdate ( NULL );
- R_DrawPlanes ();
- // Check for new console commands.
- NetUpdate ( NULL );
- R_DrawMasked ();
- // Check for new console commands.
- NetUpdate ( NULL );
- }
|