home *** CD-ROM | disk | FTP | other *** search
- /* Emacs style mode select -*- C++ -*- */
- /* ----------------------------------------------------------------------------- */
- /* */
- /* $Id:$ */
- /* */
- /* Copyright (C) 1993-1996 by id Software, Inc. */
- /* */
- /* This source is available for distribution and/or modification */
- /* only under the terms of the DOOM Source Code License as */
- /* published by id Software. All rights reserved. */
- /* */
- /* The source is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License */
- /* for more details. */
- /* */
- /* $Log:$ */
- /* */
- /* DESCRIPTION: */
- /* Rendering main loop and setup functions, */
- /* utility functions (BSP, geometry, trigonometry). */
- /* See tables.c, too. */
- /* */
- /* ----------------------------------------------------------------------------- */
-
-
- static const char rcsid[] = "$Id: r_main.c,v 1.5 1997/02/03 22:45:12 b1 Exp $";
-
-
-
- #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_video.h"
-
-
-
- /* Fineangles in the SCREENWIDTH wide window. */
- #define FIELDOFVIEW 2048
-
- int viewangleoffset;
-
- /* increment every time a check is made */
- int validcount = 1;
-
-
- lighttable_t* fixedcolormap;
- extern lighttable_t** walllights;
-
- int centerx;
- int centery;
-
- fixed_t centerxfrac;
- fixed_t centeryfrac;
- fixed_t projection;
-
- /* just for profiling purposes */
- int framecount;
-
- int sscount;
- int linecount;
- int loopcount;
-
- fixed_t viewx;
- fixed_t viewy;
- fixed_t viewz;
-
- angle_t viewangle;
-
- fixed_t viewcos;
- fixed_t viewsin;
-
- player_t* viewplayer;
-
- /* 0 = high, 1 = low */
- int detailshift;
-
- /* */
- /* 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];
-
-
- /* 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]; */
- fixed_t* finecosine = &finesine[FINEANGLES/4];
-
-
- lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
- lighttable_t* scalelightfixed[MAXLIGHTSCALE];
- lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ];
-
- /* bumped light from gun blasts */
- int extralight;
-
-
-
- void (*colfunc) (void);
- void (*basecolfunc) (void);
- void (*fuzzcolfunc) (void);
- void (*transcolfunc) (void);
- void (*spanfunc) (void);
-
-
-
- /* */
- /* 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 )
- {
- x -= viewx;
- y -= viewy;
-
- 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)];
- }
- 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 )
- {
- viewx = x1;
- viewy = 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;
-
- 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;
-
- /* use as cosine */
- dist = FixedDiv (dx, finesine[angle] );
-
- return dist;
- }
-
-
-
-
- /* */
- /* R_InitPointToAngle */
- /* */
- void R_InitPointToAngle (void)
- {
- }
-
-
- /* */
- /* R_ScaleFromGlobalAngle */
- /* Returns the texture mapping scale */
- /* for the current line (horizontal span) */
- /* at the given angle. */
- /* rw_distance must be calculated first. */
- /* */
- fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
- {
- fixed_t scale;
- int anglea;
- int angleb;
- int sinea;
- int sineb;
- fixed_t num;
- int den;
-
- anglea = ANG90 + (visangle-viewangle);
- angleb = ANG90 + (visangle-rw_normalangle);
-
- /* both 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)
- {
- }
-
-
-
- /* */
- /* 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 xtoviewangle[]: */
- /* 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;
- int j;
- int level;
- int 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 */
- /* 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;
- int setdetail;
-
-
- void
- R_SetViewSize
- ( int blocks,
- int detail )
- {
- setsizeneeded = true;
- setblocks = blocks;
- setdetail = detail;
- }
-
-
- /* */
- /* R_ExecuteSetViewSize */
- /* */
- void R_ExecuteSetViewSize (void)
- {
- fixed_t cosadj;
- fixed_t dy;
- int i;
- int j;
- int level;
- int startmap;
-
- setsizeneeded = false;
-
- if (setblocks == 11)
- {
- scaledviewwidth = SCREENWIDTH;
- viewheight = SCREENHEIGHT;
- }
- else
- {
- scaledviewwidth = setblocks*32;
- viewheight = (setblocks*168/10)&~7;
- }
-
- 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_DrawFuzzColumnLow;
- transcolfunc = R_DrawTranslatedColumnLow;
- 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;
- }
- }
- }
-
-
-
- /* */
- /* R_Init */
- /* */
- extern int detailLevel;
- extern int screenblocks;
-
-
-
- void R_Init (void)
- {
- R_InitData ();
- printf(".");
- /* printf ("\nR_InitData"); */
- R_InitPointToAngle ();
- /* printf ("\nR_InitPointToAngle"); */
- printf(".");
- R_InitTables ();
- /* viewwidth / viewheight / detailLevel are set by the defaults */
- /* printf ("\nR_InitTables"); */
- printf(".");
-
- R_SetViewSize (screenblocks, detailLevel);
-
- R_InitPlanes ();
- /* printf ("\nR_InitPlanes"); */
- printf(".");
- R_InitLightTables ();
- /* printf ("\nR_InitLightTables"); */
- printf(".");
- R_InitSkyMap ();
- /* printf ("\nR_InitSkyMap"); */
- printf(".");
- R_InitTranslationTables ();
- /* printf ("\nR_InitTranslationsTables"); */
- printf("...");
-
- 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 (!numnodes)
- 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];
- }
-
-
-
- /* */
- /* R_SetupFrame */
- /* */
- void R_SetupFrame (player_t* player)
- {
- int i;
-
- viewplayer = player;
- viewx = player->mo->x;
- viewy = player->mo->y;
- viewangle = player->mo->angle + viewangleoffset;
- extralight = player->extralight;
-
- viewz = player->viewz;
-
- viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
- viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
-
- sscount = 0;
-
- if (player->fixedcolormap)
- {
- fixedcolormap = colormaps + player->fixedcolormap*256;
-
- walllights = scalelightfixed;
-
- for (i=0 ; i<MAXLIGHTSCALE ; i++)
- scalelightfixed[i] = fixedcolormap;
- }
- else
- fixedcolormap = 0;
-
- framecount++;
- validcount++;
- }
-
-
-
- /* */
- /* R_RenderView */
- /* */
- void R_RenderPlayerView (player_t* player)
- {
- R_SetupFrame (player);
-
- /* Clear buffers. */
- R_ClearClipSegs ();
- R_ClearDrawSegs ();
- R_ClearPlanes ();
- R_ClearSprites ();
-
- /* check for new console commands. */
- NetUpdate ();
-
- /* The head node is the last node output. */
- R_RenderBSPNode (numnodes-1);
-
- /* Check for new console commands. */
- NetUpdate ();
-
- R_DrawPlanes ();
-
- /* Check for new console commands. */
- NetUpdate ();
-
- R_DrawMasked ();
-
- /* Check for new console commands. */
- NetUpdate ();
- }
-