From 66a2cc66d7504c9b64e1c461e62ad2a9d964fa95 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sat, 23 Jul 2005 16:19:41 +0000 Subject: Initial revision Subversion-branch: /trunk/chocolate-doom Subversion-revision: 4 --- src/r_main.c | 901 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 901 insertions(+) create mode 100644 src/r_main.c (limited to 'src/r_main.c') diff --git a/src/r_main.c b/src/r_main.c new file mode 100644 index 00000000..0253bca2 --- /dev/null +++ b/src/r_main.c @@ -0,0 +1,901 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// $Id: r_main.c 4 2005-07-23 16:19:41Z fraggle $ +// +// 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$ +// Revision 1.1 2005/07/23 16:19:58 fraggle +// Initial revision +// +// +// DESCRIPTION: +// Rendering main loop and setup functions, +// utility functions (BSP, geometry, trigonometry). +// See tables.c, too. +// +//----------------------------------------------------------------------------- + + +static const char rcsid[] = "$Id: r_main.c 4 2005-07-23 16:19:41Z fraggle $"; + + + +#include +#include + + +#include "doomdef.h" +#include "d_net.h" + +#include "m_bbox.h" + +#include "r_local.h" +#include "r_sky.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) +{ + // 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. +// 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; + + // UNUSED +#if 0 +{ + fixed_t dist; + fixed_t z; + fixed_t sinv; + fixed_t 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); + + // both sines are allways positive + sinea = finesine[anglea>>ANGLETOFINESHIFT]; + sineb = finesine[angleb>>ANGLETOFINESHIFT]; + num = FixedMul(projection,sineb)< 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; + + // viewangle tangent table + 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++) + { + i = 0; + while (viewangletox[i]>x) + i++; + xtoviewangle[x] = (i<>= 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<>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= 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 ("\nR_InitData"); + R_InitPointToAngle (); + printf ("\nR_InitPointToAngle"); + R_InitTables (); + // viewwidth / viewheight / detailLevel are set by the defaults + printf ("\nR_InitTables"); + + R_SetViewSize (screenblocks, detailLevel); + R_InitPlanes (); + printf ("\nR_InitPlanes"); + R_InitLightTables (); + printf ("\nR_InitLightTables"); + R_InitSkyMap (); + printf ("\nR_InitSkyMap"); + R_InitTranslationTables (); + printf ("\nR_InitTranslationsTables"); + + 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*sizeof(lighttable_t); + + walllights = scalelightfixed; + + for (i=0 ; i