/* 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 * * 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. * *-----------------------------------------------------------------------------*/ #include "doomstat.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 "i_system.h" //#include "lprintf.h" #include "st_stuff.h" #include "rockmacros.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 lighttable_t *fixedcolormap; int centerx IBSS_ATTR; int centery IBSS_ATTR; fixed_t centerxfrac, centeryfrac; 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; // // 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=0; // 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; lighttable_t *(*c_scalelight)[LIGHTLEVELS][MAXLIGHTSCALE]; lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ]; lighttable_t *(*scalelight)[MAXLIGHTSCALE]; lighttable_t *(*zlight)[MAXLIGHTZ]; lighttable_t *fullcolormap; lighttable_t **colormaps; // killough 3/20/98, 4/4/98: end dynamic colormaps int extralight; // bumped light from gun blasts void (*colfunc)(void); // // R_PointOnSide // Traverse BSP (sub) tree, // check point against partition plane. // Returns side 0 (front) or 1 (back). // // killough 5/2/98: reformatted // 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 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 angle_t R_PointToAngle(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; } 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. if(viewangletox==NULL) viewangletox=malloc(sizeof(int)*FINEANGLES/2); focallength = FixedDiv(centerxfrac, finetangent[FINEANGLES/4+FIELDOFVIEW/2]); 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 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<>= 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>ANGLETOFINESHIFT]); distscale[i] = FixedDiv(FRACUNIT,cosadj); } // Calculate the light levels to use // for each level / scale combination. for (i=0; i= NUMCOLORMAPS) level = NUMCOLORMAPS-1; // killough 3/20/98: initialize multiple colormaps level *= 256; for (t=0; tmo->x; viewy = player->mo->y; viewangle = player->mo->angle + viewangleoffset; extralight = player->extralight; viewz = player->viewz; viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; // 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]; scalelight = c_scalelight[cm]; if (player->fixedcolormap) { // killough 3/20/98: localize scalelightfixed (readability/optimization) static lighttable_t *scalelightfixed[MAXLIGHTSCALE]; fixedcolormap = fullcolormap // killough 3/20/98: use fullcolormap + player->fixedcolormap*256*sizeof(lighttable_t); walllights = scalelightfixed; for (i=0 ; i