// 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 #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 (*transc/olfunc) (void); //void (*spa/nfunc) (void); inline int finecosine(int fine) { return finesine[fine + FINEANGLES/4]; } // // 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_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_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 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 = 0; 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) { printf ("R_InitData\n"); R_InitData (); // viewwidth / viewheight / detailLevel are set by the defaults //R_SetViewSize (screenblocks, detailLevel); R_SetViewSize (10, 0); printf ("R_InitPlanes\n"); R_InitPlanes (); printf ("R_InitLightTables\n"); R_InitLightTables (); printf ("R_InitSkyMap\n"); R_InitSkyMap (); printf ("R_InitTranslationsTables\n"); R_InitTranslationTables (); 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);//finecosine[viewangle>>ANGLETOFINESHIFT]; sscount = 0; if (player->fixedcolormap) { fixedcolormap = colormaps + player->fixedcolormap*256*sizeof(lighttable_t); walllights = scalelightfixed; for (i=0 ; i