1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
20 // Rendering main loop and setup functions,
21 // utility functions (BSP, geometry, trigonometry).
24 //-----------------------------------------------------------------------------
27 static const char rcsid[] = "$Id: r_main.c,v 1.5 1997/02/03 22:45:12 b1 Exp $";
42 // Fineangles in the SCREENWIDTH wide window.
43 #define FIELDOFVIEW 2048
49 // increment every time a check is made
53 lighttable_t* fixedcolormap;
54 extern lighttable_t** walllights;
63 // just for profiling purposes
85 // precalculated math tables
89 // The viewangletox[viewangle + FINEANGLES/4] lookup
90 // maps the visible view angles to screen X coordinates,
91 // flattening the arc to a flat projection plane.
92 // There will be many angles mapped to the same X.
93 int viewangletox[FINEANGLES/2];
95 // The xtoviewangleangle[] table maps a screen pixel
96 // to the lowest viewangle that maps back to x ranges
97 // from clipangle to -clipangle.
98 angle_t xtoviewangle[SCREENWIDTH+1];
102 // The finetangentgent[angle+FINEANGLES/4] table
103 // holds the fixed_t tangent values for view angles,
104 // ranging from MININT to 0 to MAXINT.
105 // fixed_t finetangent[FINEANGLES/2];
107 // fixed_t finesine[5*FINEANGLES/4];
108 fixed_t* finecosine = &finesine[FINEANGLES/4];
111 lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
112 lighttable_t* scalelightfixed[MAXLIGHTSCALE];
113 lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ];
115 // bumped light from gun blasts
120 void (*colfunc) (void);
121 void (*basecolfunc) (void);
122 void (*fuzzcolfunc) (void);
123 void (*transcolfunc) (void);
124 void (*spanfunc) (void);
130 // Expand a given bbox
131 // so that it encloses a given point.
141 if (x> box[BOXRIGHT])
143 if (y< box[BOXBOTTOM])
152 // Traverse BSP (sub) tree,
153 // check point against partition plane.
154 // Returns side 0 (front) or 1 (back).
185 // Try to quickly decide by looking at sign bits.
186 if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 )
188 if ( (node->dy ^ dx) & 0x80000000 )
190 // (left is negative)
196 left = FixedMul ( node->dy>>FRACBITS , dx );
197 right = FixedMul ( dy , node->dx>>FRACBITS );
227 ldx = line->v2->x - lx;
228 ldy = line->v2->y - ly;
248 // Try to quickly decide by looking at sign bits.
249 if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 )
251 if ( (ldy ^ dx) & 0x80000000 )
253 // (left is negative)
259 left = FixedMul ( ldy>>FRACBITS , dx );
260 right = FixedMul ( dy , ldx>>FRACBITS );
274 // To get a global angle from cartesian coordinates,
275 // the coordinates are flipped until they are in
276 // the first octant of the coordinate system, then
277 // the y (<=x) is scaled and divided by x to get a
278 // tangent (slope) value which is looked up in the
279 // tantoangle[] table.
307 return tantoangle[ SlopeDiv(y,x)];
312 return ANG90-1-tantoangle[ SlopeDiv(x,y)];
323 return -tantoangle[SlopeDiv(y,x)];
328 return ANG270+tantoangle[ SlopeDiv(x,y)];
343 return ANG180-1-tantoangle[ SlopeDiv(y,x)];
348 return ANG90+ tantoangle[ SlopeDiv(x,y)];
359 return ANG180+tantoangle[ SlopeDiv(y,x)];
364 return ANG270-1-tantoangle[ SlopeDiv(x,y)];
381 return R_PointToAngle (x2, y2);
406 angle = (tantoangle[ FixedDiv(dy,dx)>>DBITS ]+ANG90) >> ANGLETOFINESHIFT;
409 dist = FixedDiv (dx, finesine[angle] );
416 // R_ScaleFromGlobalAngle
417 // Returns the texture mapping scale
418 // for the current line (horizontal span)
419 // at the given angle.
420 // rw_distance must be calculated first.
422 fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
432 anglea = ANG90 + (visangle-viewangle);
433 angleb = ANG90 + (visangle-rw_normalangle);
435 // both sines are allways positive
436 sinea = finesine[anglea>>ANGLETOFINESHIFT];
437 sineb = finesine[angleb>>ANGLETOFINESHIFT];
438 num = FixedMul(projection,sineb)<<detailshift;
439 den = FixedMul(rw_distance,sinea);
443 scale = FixedDiv (num, den);
445 if (scale > 64*FRACUNIT)
447 else if (scale < 256)
458 // R_InitTextureMapping
460 void R_InitTextureMapping (void)
467 // Use tangent table to generate viewangletox:
468 // viewangletox will give the next greatest x
469 // after the view angle.
472 // so FIELDOFVIEW angles covers SCREENWIDTH.
473 focallength = FixedDiv (centerxfrac,
474 finetangent[FINEANGLES/4+FIELDOFVIEW/2] );
476 for (i=0 ; i<FINEANGLES/2 ; i++)
478 if (finetangent[i] > FRACUNIT*2)
480 else if (finetangent[i] < -FRACUNIT*2)
484 t = FixedMul (finetangent[i], focallength);
485 t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS;
489 else if (t>viewwidth+1)
495 // Scan viewangletox[] to generate xtoviewangle[]:
496 // xtoviewangle will give the smallest view angle
498 for (x=0;x<=viewwidth;x++)
501 while (viewangletox[i]>x)
503 xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
506 // Take out the fencepost cases from viewangletox.
507 for (i=0 ; i<FINEANGLES/2 ; i++)
509 if (viewangletox[i] == -1)
511 else if (viewangletox[i] == viewwidth+1)
512 viewangletox[i] = viewwidth;
515 clipangle = xtoviewangle[0];
522 // Only inits the zlight table,
523 // because the scalelight table changes with view size.
527 void R_InitLightTables (void)
535 // Calculate the light levels to use
536 // for each level / distance combination.
537 for (i=0 ; i< LIGHTLEVELS ; i++)
539 startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
540 for (j=0 ; j<MAXLIGHTZ ; j++)
542 scale = FixedDiv ((SCREENWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
543 scale >>= LIGHTSCALESHIFT;
544 level = startmap - scale/DISTMAP;
549 if (level >= NUMCOLORMAPS)
550 level = NUMCOLORMAPS-1;
552 zlight[i][j] = colormaps + level*256;
561 // Do not really change anything here,
562 // because it might be in the middle of a refresh.
563 // The change will take effect next refresh.
565 boolean setsizeneeded;
575 setsizeneeded = true;
582 // R_ExecuteSetViewSize
584 void R_ExecuteSetViewSize (void)
593 setsizeneeded = false;
597 scaledviewwidth = SCREENWIDTH;
598 viewheight = SCREENHEIGHT;
602 scaledviewwidth = setblocks*32;
603 viewheight = (setblocks*168/10)&~7;
606 detailshift = setdetail;
607 viewwidth = scaledviewwidth>>detailshift;
609 centery = viewheight/2;
610 centerx = viewwidth/2;
611 centerxfrac = centerx<<FRACBITS;
612 centeryfrac = centery<<FRACBITS;
613 projection = centerxfrac;
617 colfunc = basecolfunc = R_DrawColumn;
618 fuzzcolfunc = R_DrawFuzzColumn;
619 transcolfunc = R_DrawTranslatedColumn;
620 spanfunc = R_DrawSpan;
624 colfunc = basecolfunc = R_DrawColumnLow;
625 fuzzcolfunc = R_DrawFuzzColumn;
626 transcolfunc = R_DrawTranslatedColumn;
627 spanfunc = R_DrawSpanLow;
630 R_InitBuffer (scaledviewwidth, viewheight);
632 R_InitTextureMapping ();
635 pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
636 pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
639 for (i=0 ; i<viewwidth ; i++)
640 screenheightarray[i] = viewheight;
643 for (i=0 ; i<viewheight ; i++)
645 dy = ((i-viewheight/2)<<FRACBITS)+FRACUNIT/2;
647 yslope[i] = FixedDiv ( (viewwidth<<detailshift)/2*FRACUNIT, dy);
650 for (i=0 ; i<viewwidth ; i++)
652 cosadj = abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
653 distscale[i] = FixedDiv (FRACUNIT,cosadj);
656 // Calculate the light levels to use
657 // for each level / scale combination.
658 for (i=0 ; i< LIGHTLEVELS ; i++)
660 startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
661 for (j=0 ; j<MAXLIGHTSCALE ; j++)
663 level = startmap - j*SCREENWIDTH/(viewwidth<<detailshift)/DISTMAP;
668 if (level >= NUMCOLORMAPS)
669 level = NUMCOLORMAPS-1;
671 scalelight[i][j] = colormaps + level*256;
681 extern int detailLevel;
682 extern int screenblocks;
689 printf ("\nR_InitData");
691 R_SetViewSize (screenblocks, detailLevel);
693 printf ("\nR_InitPlanes");
694 R_InitLightTables ();
695 printf ("\nR_InitLightTables");
697 printf ("\nR_InitSkyMap");
698 R_InitTranslationTables ();
699 printf ("\nR_InitTranslationsTables");
706 // R_PointInSubsector
717 // single subsector is a special case
721 nodenum = numnodes-1;
723 while (! (nodenum & NF_SUBSECTOR) )
725 node = &nodes[nodenum];
726 side = R_PointOnSide (x, y, node);
727 nodenum = node->children[side];
730 return &subsectors[nodenum & ~NF_SUBSECTOR];
738 void R_SetupFrame (player_t* player)
743 viewx = player->mo->x;
744 viewy = player->mo->y;
745 viewangle = player->mo->angle + viewangleoffset;
746 extralight = player->extralight;
748 viewz = player->viewz;
750 viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
751 viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
755 if (player->fixedcolormap)
759 + player->fixedcolormap*256*sizeof(lighttable_t);
761 walllights = scalelightfixed;
763 for (i=0 ; i<MAXLIGHTSCALE ; i++)
764 scalelightfixed[i] = fixedcolormap;
778 void R_RenderPlayerView (player_t* player)
780 R_SetupFrame (player);
788 // check for new console commands.
791 // The head node is the last node output.
792 R_RenderBSPNode (numnodes-1);
794 // Check for new console commands.
799 // Check for new console commands.
804 // Check for new console commands.