/* R_main.c */ #include #include "doomdef.h" #include "r_local.h" #ifdef GL_HERETIC #include "gl_struct.h" #endif /* */ int viewangleoffset; int validcount = 1; /* increment every time a check is made */ lighttable_t *fixedcolormap; extern lighttable_t **walllights; int centerx, centery; fixed_t centerxfrac, centeryfrac; fixed_t projection; int framecount; /* just for profiling purposes */ int sscount, linecount, loopcount; fixed_t viewx, viewy, viewz; angle_t viewangle; fixed_t viewcos, viewsin; player_t *viewplayer; int detailshift; /* 0 = high, 1 = low */ /* * 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; /* * 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]; int extralight; /* bumped light from gun blasts */ void (*colfunc) (void); void (*basecolfunc) (void); void (*fuzzcolfunc) (void); void (*transcolfunc) (void); void (*spanfunc) (void); /* =================== = = R_AddPointToBox = =================== */ 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 = = Returns side 0 (front) or 1 (back) =============================================================================== */ int R_PointOnSide (fixed_t x, fixed_t y, node_t *node) { fixed_t dx,dy; fixed_t left, 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 ) return 1; /* (left is negative) */ return 0; } left = FixedMul ( node->dy>>FRACBITS , dx ); right = FixedMul ( dy , node->dx>>FRACBITS ); if (right < left) return 0; /* front side */ return 1; /* back side */ } int R_PointOnSegSide (fixed_t x, fixed_t y, seg_t *line) { fixed_t lx, ly; fixed_t ldx, ldy; fixed_t dx,dy; fixed_t left, 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 ) return 1; /* (left is negative) */ return 0; } left = FixedMul ( ldy>>FRACBITS , dx ); right = FixedMul ( dy , ldx>>FRACBITS ); if (right < left) return 0; /* front side */ return 1; /* back side */ } /* =============================================================================== = = 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 is to handle * the case when x==y without additional checking. */ #define SLOPERANGE 2048 #define SLOPEBITS 11 #define DBITS (FRACBITS-SLOPEBITS) extern int tantoangle[SLOPERANGE+1]; /* get from tables.c */ /* int tantoangle[SLOPERANGE+1]; */ int SlopeDiv (unsigned num, unsigned den) { unsigned ans; if (den < 512) return SLOPERANGE; ans = (num<<3)/(den>>8); return ans <= SLOPERANGE ? ans : SLOPERANGE; } 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) return tantoangle[ SlopeDiv(y,x)]; /* octant 0 */ else return ANG90-1-tantoangle[ SlopeDiv(x,y)]; /* octant 1 */ } else { /* y<0 */ y = -y; if (x>y) return -tantoangle[SlopeDiv(y,x)]; /* octant 8 */ else return ANG270+tantoangle[ SlopeDiv(x,y)]; /* octant 7 */ } } else { /* x<0 */ x = -x; if (y>= 0) { /* y>= 0 */ if (x>y) return ANG180-1-tantoangle[ SlopeDiv(y,x)]; /* octant 3 */ else return ANG90+ tantoangle[ SlopeDiv(x,y)]; /* octant 2 */ } else { /* y<0 */ y = -y; if (x>y) return ANG180+tantoangle[ SlopeDiv(y,x)]; /* octant 4 */ else return ANG270-1-tantoangle[ SlopeDiv(x,y)]; /* octant 5 */ } } 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, dy, 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; dist = FixedDiv (dx, finesine[angle] ); /* use as cosine */ return dist; } /* ================= = = R_InitPointToAngle = ================= */ void R_InitPointToAngle (void) { /* 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 at the given angle = rw_distance must be calculated first ================ */ fixed_t R_ScaleFromGlobalAngle (angle_t visangle) { fixed_t scale; int anglea, angleb; int sinea, sineb; fixed_t num,den; #if 0 { fixed_t dist,z; fixed_t sinv, 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); /* bothe 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) { /* now getting from tables.c */ #if 0 int i; float a, 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 xtoviewangleangle[] * * 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 = = Don't really change anything here, because i might be in the middle of = a refresh. The change will take effect next refresh. = ============== */ boolean setsizeneeded; int setblocks, setdetail; void R_SetViewSize (int blocks, int detail) { setsizeneeded = true; setblocks = blocks; setdetail = detail; } /* ============== = = R_ExecuteSetViewSize = ============== */ void R_ExecuteSetViewSize (void) { fixed_t cosadj, dy; int i,j, level, startmap; #ifdef GL_HERETIC setblocks=11; #endif setsizeneeded = false; if (setblocks == 11) { scaledviewwidth = screenwidth; viewheight = screenheight; } else { /* scaledviewwidth = setblocks*32; viewheight = (setblocks*(screenheight-SBARHEIGHT)/(maxblocks-1)); */ scaledviewwidth = (setblocks*(screenwidth/10))&~7; viewheight = (setblocks*(screenheight-SBARHEIGHT+2)/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; } } /* * draw the border */ R_DrawViewBorder (); /* erase old menu stuff */ } /* ============== = = R_Init = ============== */ int detailLevel; long screenblocks; void R_Init (void) { /* printf("R_InitData "); */ R_InitData (); printf ("."); /* printf("R_InitPointToAngle\n"); */ R_InitPointToAngle (); printf ("."); /* printf("R_InitTables "); */ R_InitTables (); /* viewwidth / viewheight / detailLevel are set by the defaults */ printf ("."); R_SetViewSize (screenblocks, detailLevel); /* printf("R_InitPlanes\n"); */ R_InitPlanes (); printf ("."); /* printf("R_InitLightTables "); */ R_InitLightTables (); printf ("."); /* printf("R_InitSkyMap\n"); */ R_InitSkyMap (); printf ("."); R_InitTranslationTables(); framecount = 0; } /* ============== = = R_PointInSubsector = ============== */ subsector_t *R_PointInSubsector (fixed_t x, fixed_t y) { node_t *node; int side, nodenum; if (!numnodes) /* single subsector is a special case */ 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]; } /* //---------------------------------------------------------------------------- // // PROC R_SetupFrame // //---------------------------------------------------------------------------- */ void R_SetupFrame(player_t *player) { int i; int tableAngle; int tempCentery; /* drawbsp = 1; */ viewplayer = player; viewangle = player->mo->angle+viewangleoffset; tableAngle = viewangle>>ANGLETOFINESHIFT; if(player->chickenTics && player->chickenPeck) { /* Set chicken attack view position */ viewx = player->mo->x+player->chickenPeck*finecosine[tableAngle]; viewy = player->mo->y+player->chickenPeck*finesine[tableAngle]; } else { /* Normal view position */ viewx = player->mo->x; viewy = player->mo->y; } extralight = player->extralight; viewz = player->viewz; tempCentery = viewheight/2+(player->lookdir)*screenblocks/10; if(centery != tempCentery) { centery = tempCentery; centeryfrac = centery<fixedcolormap) { fixedcolormap = colormaps+player->fixedcolormap *256*sizeof(lighttable_t); walllights = scalelightfixed; for(i = 0; i < MAXLIGHTSCALE; i++) { scalelightfixed[i] = fixedcolormap; } } else { fixedcolormap = 0; } framecount++; validcount++; if(BorderNeedRefresh) { if(setblocks < 10) { R_DrawViewBorder(); } BorderNeedRefresh = false; BorderTopRefresh = false; /* UpdateState |= I_FULLSCRN; */ } if(BorderTopRefresh) { if(setblocks < 10) { R_DrawTopBorder(); } BorderTopRefresh = false; /* UpdateState |= I_MESSAGES; */ } #ifdef __NeXT__ RD_ClearMapWindow (); #endif #if 0 { static int frame; memset (screen, frame, screenwidth*screenheight); frame++; } #endif } /* ============== = = R_RenderView = ============== */ #ifdef GL_HERETIC extern void GL_AddExtraLines(player_t *player); #endif void R_RenderPlayerView (player_t *player) { #ifdef GL_HERETIC fn_vInitglDrawScene(); #endif R_SetupFrame (player); R_ClearClipSegs (); R_ClearDrawSegs (); R_ClearPlanes (); R_ClearSprites (); NetUpdate (); /* check for new console commands */ R_RenderBSPNode (numnodes-1); /* the head node is the last node output */ NetUpdate (); /* check for new console commands */ #ifdef GL_HERETIC if (player->lookdir) { drawseg_t *ds; for (ds=ds_p-1 ; ds >= drawsegs ; ds--) { fn_vGlAddLine(ds->curline->linedef->iLineID); } R_SetupFrame (player); viewx += FixedMul(-2048*20*abs(player->lookdir), finecosine[player->mo->angle>>ANGLETOFINESHIFT]); viewy += FixedMul(-2048*20*abs(player->lookdir), finesine[player->mo->angle>>ANGLETOFINESHIFT]); R_ClearClipSegs (); R_ClearDrawSegs (); R_ClearPlanes (); R_ClearSprites (); NetUpdate (); /* check for new console commands */ R_RenderBSPNode (numnodes-1); /* the head node is the last node output */ } #endif #ifndef GL_HERETIC R_DrawPlanes (); NetUpdate (); /* check for new console commands */ R_DrawMasked (); NetUpdate (); /* check for new console commands */ #else #ifdef WEAP_DRAWPIX if (viewangleoffset <= 1024<= -1024<