123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656 |
- /* Emacs style mode select -*- C++ -*-
- *-----------------------------------------------------------------------------
- *
- *
- * PrBoom: a Doom port merged with LxDoom and LSDLDoom
- * based on BOOM, a modified and improved DOOM engine
- * Copyright (C) 1999 by
- * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
- * Copyright (C) 1999-2000 by
- * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
- * Copyright 2005, 2006 by
- * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * DESCRIPTION:
- * Rendering main loop and setup functions,
- * utility functions (BSP, geometry, trigonometry).
- * See tables.c, too.
- *
- *-----------------------------------------------------------------------------*/
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #ifdef USE_SDL
- #include "SDL.h"
- #endif
- #include "doomstat.h"
- #include "d_net.h"
- #include "w_wad.h"
- #include "r_main.h"
- #include "r_things.h"
- #include "r_plane.h"
- #include "r_bsp.h"
- #include "r_draw.h"
- #include "m_bbox.h"
- #include "r_sky.h"
- #include "v_video.h"
- #include "lprintf.h"
- #include "st_stuff.h"
- #include "i_main.h"
- #include "i_system.h"
- #include "g_game.h"
- #include "r_demo.h"
- #include "r_fps.h"
- // Fineangles in the SCREENWIDTH wide window.
- #define FIELDOFVIEW 2048
- // killough: viewangleoffset is a legacy from the pre-v1.2 days, when Doom
- // had Left/Mid/Right viewing. +/-ANG90 offsets were placed here on each
- // node, by d_net.c, to set up a L/M/R session.
- int viewangleoffset;
- int validcount = 1; // increment every time a check is made
- const lighttable_t *fixedcolormap;
- int centerx, centery;
- fixed_t centerxfrac, centeryfrac;
- fixed_t viewheightfrac; //e6y: for correct clipping of things
- fixed_t projection;
- // proff 11/06/98: Added for high-res
- fixed_t projectiony;
- fixed_t viewx, viewy, viewz;
- angle_t viewangle;
- fixed_t viewcos, viewsin;
- player_t *viewplayer;
- extern lighttable_t **walllights;
- static mobj_t *oviewer;
- //
- // 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[MAX_SCREENWIDTH+1]; // killough 2/8/98
- // killough 3/20/98: Support dynamic colormaps, e.g. deep water
- // killough 4/4/98: support dynamic number of them as well
- int numcolormaps;
- const lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ];
- const lighttable_t *(*zlight)[MAXLIGHTZ];
- const lighttable_t *fullcolormap;
- const lighttable_t **colormaps;
- // killough 3/20/98, 4/4/98: end dynamic colormaps
- int extralight; // bumped light from gun blasts
- //
- // R_PointOnSide
- // Traverse BSP (sub) tree,
- // check point against partition plane.
- // Returns side 0 (front) or 1 (back).
- //
- // killough 5/2/98: reformatted
- //
- PUREFUNC int R_PointOnSide(fixed_t x, fixed_t y, const node_t *node)
- {
- if (!node->dx)
- return x <= node->x ? node->dy > 0 : node->dy < 0;
- if (!node->dy)
- return y <= node->y ? node->dx < 0 : node->dx > 0;
- x -= node->x;
- y -= node->y;
- // Try to quickly decide by looking at sign bits.
- if ((node->dy ^ node->dx ^ x ^ y) < 0)
- return (node->dy ^ x) < 0; // (left is negative)
- return FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x);
- }
- // killough 5/2/98: reformatted
- PUREFUNC int R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line)
- {
- fixed_t lx = line->v1->x;
- fixed_t ly = line->v1->y;
- fixed_t ldx = line->v2->x - lx;
- fixed_t ldy = line->v2->y - ly;
- if (!ldx)
- return x <= lx ? ldy > 0 : ldy < 0;
- if (!ldy)
- return y <= ly ? ldx < 0 : ldx > 0;
- x -= lx;
- y -= ly;
- // Try to quickly decide by looking at sign bits.
- if ((ldy ^ ldx ^ x ^ y) < 0)
- return (ldy ^ x) < 0; // (left is negative)
- return FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x);
- }
- //
- // 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 of tantoangle[]
- // is to handle the case when x==y without additional
- // checking.
- //
- // killough 5/2/98: reformatted, cleaned up
- #include <math.h>
- angle_t R_PointToAngle(fixed_t x, fixed_t y)
- {
- #if 0
- // JDC: the oldresult case only hit 10%, making it a net loss.
- // JDC: added parenthesis to force constant evaluation
- return (int)(atan2(y-viewy, x-viewx) * (ANG180/M_PI) );
- #else
- static fixed_t oldx, oldy;
- static angle_t oldresult;
- x -= viewx; y -= viewy;
- if ( /* !render_precise && */
- // e6y: here is where "slime trails" can SOMETIMES occur
- #ifdef GL_DOOM
- (V_GetMode() != VID_MODEGL) &&
- #endif
- (x < INT_MAX/4 && x > -INT_MAX/4 && y < INT_MAX/4 && y > -INT_MAX/4)
- )
- {
- // old R_PointToAngle
- return (x || y) ?
- x >= 0 ?
- y >= 0 ?
- (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
- ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
- x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
- ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
- y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
- ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
- (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
- ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
- 0;
- }
- // R_PointToAngleEx merged into R_PointToAngle
- // e6y: The precision of the code above is abysmal so use the CRT atan2 function instead!
- if (oldx != x || oldy != y)
- {
- oldx = x;
- oldy = y;
- oldresult = (int)(atan2(y, x) * ANG180/M_PI );
- }
- return oldresult;
- #endif
- }
- angle_t R_PointToAngle2(fixed_t viewx, fixed_t viewy, fixed_t x, fixed_t y)
- {
- return (y -= viewy, (x -= viewx) || y) ?
- x >= 0 ?
- y >= 0 ?
- (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
- ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
- x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
- ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
- y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
- ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
- (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
- ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
- 0;
- }
- //
- // R_InitTextureMapping
- //
- // killough 5/2/98: reformatted
- static void R_InitTextureMapping (void)
- {
- register int i,x;
- 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++)
- {
- int t;
- 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++)
- {
- for (i=0; viewangletox[i] > x; i++)
- ;
- xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
- }
- // Take out the fencepost cases from viewangletox.
- for (i=0; i<FINEANGLES/2; i++)
- if (viewangletox[i] == -1)
- viewangletox[i] = 0;
- else
- if (viewangletox[i] == viewwidth+1)
- viewangletox[i] = viewwidth;
- clipangle = xtoviewangle[0];
- }
- //
- // R_InitLightTables
- //
- #define DISTMAP 2
- static void R_InitLightTables (void)
- {
- int i;
- // killough 4/4/98: dynamic colormaps
- c_zlight = malloc(sizeof(*c_zlight) * numcolormaps);
- // Calculate the light levels to use
- // for each level / distance combination.
- for (i=0; i< LIGHTLEVELS; i++)
- {
- int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
- for (j=0; j<MAXLIGHTZ; j++)
- {
- // CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
- // brighter than normal res
- int scale = FixedDiv ((320/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
- int t, level = startmap - (scale >>= LIGHTSCALESHIFT)/DISTMAP;
- if (level < 0)
- level = 0;
- else
- if (level >= NUMCOLORMAPS)
- level = NUMCOLORMAPS-1;
- // killough 3/20/98: Initialize multiple colormaps
- level *= 256;
- for (t=0; t<numcolormaps; t++) // killough 4/4/98
- c_zlight[t][i][j] = colormaps[t] + level;
- }
- }
- }
- //
- // 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;
- void R_SetViewSize(int blocks)
- {
- setsizeneeded = true;
- setblocks = blocks;
- }
- //
- // R_ExecuteSetViewSize
- //
- void R_ExecuteSetViewSize (void)
- {
- int i;
- setsizeneeded = false;
- if (setblocks == 11)
- {
- scaledviewwidth = SCREENWIDTH;
- viewheight = SCREENHEIGHT;
- }
- // proff 09/24/98: Added for high-res
- else if (setblocks == 10)
- {
- scaledviewwidth = SCREENWIDTH;
- viewheight = SCREENHEIGHT-ST_SCALED_HEIGHT;
- }
- else
- {
- // proff 08/17/98: Changed for high-res
- scaledviewwidth = setblocks*SCREENWIDTH/10;
- viewheight = (setblocks*(SCREENHEIGHT-ST_SCALED_HEIGHT)/10) & ~7;
- }
- viewwidth = scaledviewwidth;
- viewheightfrac = viewheight<<FRACBITS;//e6y
- centery = viewheight/2;
- centerx = viewwidth/2;
- centerxfrac = centerx<<FRACBITS;
- centeryfrac = centery<<FRACBITS;
- projection = centerxfrac;
- // proff 11/06/98: Added for high-res
- projectiony = ((SCREENHEIGHT * centerx * 320) / 200) / SCREENWIDTH * FRACUNIT;
- R_InitBuffer (scaledviewwidth, viewheight);
- R_InitTextureMapping();
- // psprite scales
- // proff 08/17/98: Changed for high-res
- pspritescale = FRACUNIT*viewwidth/320;
- pspriteiscale = FRACUNIT*320/viewwidth;
- // proff 11/06/98: Added for high-res
- pspriteyscale = (((SCREENHEIGHT*viewwidth)/SCREENWIDTH) << FRACBITS) / 200;
- // thing clipping
- for (i=0 ; i<viewwidth ; i++)
- screenheightarray[i] = viewheight;
- // planes
- for (i=0 ; i<viewheight ; i++)
- { // killough 5/2/98: reformatted
- fixed_t dy = D_abs(((i-viewheight/2)<<FRACBITS)+FRACUNIT/2);
- // proff 08/17/98: Changed for high-res
- yslope[i] = FixedDiv(projectiony, dy);
- }
- for (i=0 ; i<viewwidth ; i++)
- {
- fixed_t cosadj = D_abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
- distscale[i] = FixedDiv(FRACUNIT,cosadj);
- }
- }
- //
- // R_Init
- //
- extern int screenblocks;
- void R_Init (void)
- {
- // CPhipps - R_DrawColumn isn't constant anymore, so must
- // initialise in code
- // current column draw function
- lprintf(LO_INFO, "\nR_LoadTrigTables: ");
- R_LoadTrigTables();
- lprintf(LO_INFO, "\nR_InitData: ");
- R_InitData();
- R_SetViewSize(screenblocks);
- lprintf(LO_INFO, "\nR_Init: R_InitPlanes ");
- R_InitPlanes();
- lprintf(LO_INFO, "R_InitLightTables ");
- R_InitLightTables();
- lprintf(LO_INFO, "R_InitSkyMap ");
- R_InitSkyMap();
- lprintf(LO_INFO, "R_InitTranslationsTables ");
- R_InitTranslationTables();
- lprintf(LO_INFO, "R_InitPatches ");
- R_InitPatches();
- }
- //
- // R_PointInSubsector
- //
- // killough 5/2/98: reformatted, cleaned up
- subsector_t *R_PointInSubsector(fixed_t x, fixed_t y)
- {
- int nodenum = numnodes-1;
- // special case for trivial maps (single subsector, no nodes)
- if (numnodes == 0)
- return subsectors;
- while (!(nodenum & NF_SUBSECTOR))
- nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)];
- return &subsectors[nodenum & ~NF_SUBSECTOR];
- }
- //
- // R_SetupFrame
- //
- static void R_SetupFrame (player_t *player)
- {
- int cm;
- boolean NoInterpolate = paused || (menuactive && !demoplayback);
- viewplayer = player;
- if (player->mo != oviewer || NoInterpolate)
- {
- R_ResetViewInterpolation ();
- oviewer = player->mo;
- }
- tic_vars.frac = I_GetTimeFrac ();
- if (NoInterpolate)
- tic_vars.frac = FRACUNIT;
- R_InterpolateView (player, tic_vars.frac);
- extralight = player->extralight;
- viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
- viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
- R_DoInterpolations(tic_vars.frac);
- // killough 3/20/98, 4/4/98: select colormap based on player status
- if (player->mo->subsector->sector->heightsec != -1)
- {
- const sector_t *s = player->mo->subsector->sector->heightsec + sectors;
- cm = viewz < s->floorheight ? s->bottommap : viewz > s->ceilingheight ?
- s->topmap : s->midmap;
- if (cm < 0 || cm > numcolormaps)
- cm = 0;
- }
- else
- cm = 0;
- fullcolormap = colormaps[cm];
- zlight = c_zlight[cm];
- if (player->fixedcolormap)
- {
- fixedcolormap = fullcolormap // killough 3/20/98: use fullcolormap
- + player->fixedcolormap*256*sizeof(lighttable_t);
- }
- else
- fixedcolormap = 0;
- validcount++;
- }
- int autodetect_hom = 0; // killough 2/7/98: HOM autodetection flag
- //
- // R_ShowStats
- //
- int rendered_visplanes, rendered_segs, rendered_vissprites;
- boolean rendering_stats;
- static void R_ShowStats(void)
- {
- //e6y
- #if USE_SDL
- static unsigned int FPS_SavedTick = 0, FPS_FrameCount = 0;
- unsigned int tick = SDL_GetTicks();
- FPS_FrameCount++;
- if(tick >= FPS_SavedTick + 1000)
- {
- doom_printf((V_GetMode() == VID_MODEGL)
- ?"Frame rate %d fps\nWalls %d, Flats %d, Sprites %d"
- :"Frame rate %d fps\nSegs %d, Visplanes %d, Sprites %d",
- 1000 * FPS_FrameCount / (tick - FPS_SavedTick), rendered_segs,
- rendered_visplanes, rendered_vissprites);
- FPS_SavedTick = tick;
- FPS_FrameCount = 0;
- }
- #else
- #define KEEPTIMES 10
- static int keeptime[KEEPTIMES], showtime;
- int now = I_GetTime();
- if (now - showtime > 35) {
- doom_printf((V_GetMode() == VID_MODEGL)
- ?"Frame rate %d fps\nWalls %d, Flats %d, Sprites %d"
- :"Frame rate %d fps\nSegs %d, Visplanes %d, Sprites %d",
- (35*KEEPTIMES)/(now - keeptime[0]), rendered_segs,
- rendered_visplanes, rendered_vissprites);
- showtime = now;
- }
- memmove(keeptime, keeptime+1, sizeof(keeptime[0]) * (KEEPTIMES-1));
- keeptime[KEEPTIMES-1] = now;
- #endif //e6y
- }
- //
- // R_RenderView
- //
- void R_RenderPlayerView (player_t* player)
- {
- R_SetupFrame (player);
- // Clear buffers.
- R_ClearClipSegs ();
- R_ClearDrawSegs ();
- R_ClearPlanes ();
- R_ClearSprites ();
- rendered_segs = rendered_visplanes = 0;
- if (V_GetMode() == VID_MODEGL)
- {
- #ifdef GL_DOOM
- // proff 11/99: clear buffers
- gld_InitDrawScene();
- // proff 11/99: switch to perspective mode
- gld_StartDrawScene();
- #endif
- } else {
- if (autodetect_hom)
- { // killough 2/10/98: add flashing red HOM indicators
- unsigned char color=(gametic % 20) < 9 ? 0xb0 : 0;
- V_FillRect(0, viewwindowx, viewwindowy, viewwidth, viewheight, color);
- R_DrawViewBorder();
- }
- }
- // check for new console commands.
- #ifdef HAVE_NET
- NetUpdate ();
- #endif
- // The head node is the last node output.
- R_RenderBSPNode (numnodes-1);
- R_ResetColumnBuffer();
- // Check for new console commands.
- #ifdef HAVE_NET
- NetUpdate ();
- #endif
- if (V_GetMode() != VID_MODEGL)
- R_DrawPlanes ();
- // Check for new console commands.
- #ifdef HAVE_NET
- NetUpdate ();
- #endif
- if (V_GetMode() != VID_MODEGL) {
- R_DrawMasked ();
- R_ResetColumnBuffer();
- }
- // Check for new console commands.
- #ifdef HAVE_NET
- NetUpdate ();
- #endif
- if (V_GetMode() == VID_MODEGL) {
- #ifdef GL_DOOM
- // proff 11/99: draw the scene
- gld_DrawScene(player);
- // proff 11/99: finishing off
- gld_EndDrawScene();
- #endif
- }
- if (rendering_stats) R_ShowStats();
- R_RestoreInterpolations();
- }
|