2 //**************************************************************************
4 //** r_main.c : Heretic 2 : Raven Software, Corp.
11 //**************************************************************************
21 extern void R_RenderMap();
22 extern void R_DrawPlayerSprites();
28 int validcount = 1; // increment every time a check is made
30 lighttable_t *fixedcolormap;
31 extern lighttable_t **walllights;
34 fixed_t centerxfrac, centeryfrac;
37 int framecount; // just for profiling purposes
39 int sscount, linecount, loopcount;
41 fixed_t viewx, viewy, viewz;
43 fixed_t viewcos, viewsin;
47 float viewpitch; // player->lookdir, global version
50 int detailshift; // 0 = high, 1 = low
53 // precalculated math tables
57 // The viewangletox[viewangle + FINEANGLES/4] lookup maps the visible view
58 // angles to screen X coordinates, flattening the arc to a flat projection
59 // plane. There will be many angles mapped to the same X.
60 int viewangletox[FINEANGLES/2];
62 // The xtoviewangleangle[] table maps a screen pixel to the lowest viewangle
63 // that maps back to x ranges from clipangle to -clipangle
64 angle_t xtoviewangle[SCREENWIDTH+1];
66 // the finetangentgent[angle+FINEANGLES/4] table holds the fixed_t tangent
67 // values for view angles, ranging from MININT to 0 to MAXINT.
68 // fixed_t finetangent[FINEANGLES/2];
70 // fixed_t finesine[5*FINEANGLES/4];
71 fixed_t *finecosine = &finesine[FINEANGLES/4];
74 lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
75 lighttable_t *scalelightfixed[MAXLIGHTSCALE];
76 lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
78 int extralight; // bumped light from gun blasts
80 void (*colfunc) (void);
81 void (*basecolfunc) (void);
82 void (*fuzzcolfunc) (void);
83 void (*transcolfunc) (void);
84 void (*spanfunc) (void);
95 void R_AddPointToBox (int x, int y, fixed_t *box)
101 if (y< box[BOXBOTTOM])
110 ===============================================================================
114 = Returns side 0 (front) or 1 (back)
115 ===============================================================================
118 int R_PointOnSide (fixed_t x, fixed_t y, node_t *node)
139 // try to quickly decide by looking at sign bits
140 if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 )
142 if ( (node->dy ^ dx) & 0x80000000 )
143 return 1; // (left is negative)
147 left = FixedMul ( node->dy>>FRACBITS , dx );
148 right = FixedMul ( dy , node->dx>>FRACBITS );
151 return 0; // front side
152 return 1; // back side
156 int R_PointOnSegSide (fixed_t x, fixed_t y, seg_t *line)
166 ldx = line->v2->x - lx;
167 ldy = line->v2->y - ly;
185 // try to quickly decide by looking at sign bits
186 if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 )
188 if ( (ldy ^ dx) & 0x80000000 )
189 return 1; // (left is negative)
193 left = FixedMul ( ldy>>FRACBITS , dx );
194 right = FixedMul ( dy , ldx>>FRACBITS );
197 return 0; // front side
198 return 1; // back side
203 ===============================================================================
207 ===============================================================================
210 // to get a global angle from cartesian coordinates, the coordinates are
211 // flipped until they are in the first octant of the coordinate system, then
212 // the y (<=x) is scaled and divided by x to get a tangent (slope) value
213 // which is looked up in the tantoangle[] table. The +1 size is to handle
214 // the case when x==y without additional checking.
215 #define SLOPERANGE 2048
217 #define DBITS (FRACBITS-SLOPEBITS)
220 extern int tantoangle[SLOPERANGE+1]; // get from tables.c
222 // int tantoangle[SLOPERANGE+1];
224 int SlopeDiv (unsigned num, unsigned den)
229 ans = (num<<3)/(den>>8);
230 return ans <= SLOPERANGE ? ans : SLOPERANGE;
233 angle_t R_PointToAngle (fixed_t x, fixed_t y)
244 return tantoangle[ SlopeDiv(y,x)]; // octant 0
246 return ANG90-1-tantoangle[ SlopeDiv(x,y)]; // octant 1
252 return -tantoangle[SlopeDiv(y,x)]; // octant 8
254 return ANG270+tantoangle[ SlopeDiv(x,y)]; // octant 7
263 return ANG180-1-tantoangle[ SlopeDiv(y,x)]; // octant 3
265 return ANG90+ tantoangle[ SlopeDiv(x,y)]; // octant 2
271 return ANG180+tantoangle[ SlopeDiv(y,x)]; // octant 4
273 return ANG270-1-tantoangle[ SlopeDiv(x,y)]; // octant 5
281 angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
285 return R_PointToAngle (x2, y2);
289 fixed_t R_PointToDist (fixed_t x, fixed_t y)
292 fixed_t dx, dy, temp;
305 angle = (tantoangle[ FixedDiv(dy,dx)>>DBITS ]+ANG90) >> ANGLETOFINESHIFT;
307 dist = FixedDiv (dx, finesine[angle] ); // use as cosine
322 void R_InitPointToAngle (void)
324 // now getting from tables.c
330 // slope (tangent) to angle lookup
332 for (i=0 ; i<=SLOPERANGE ; i++)
334 f = atan( (float)i/SLOPERANGE )/(3.141592657*2);
341 //=============================================================================
346 = R_ScaleFromGlobalAngle
348 = Returns the texture mapping scale for the current line at the given angle
349 = rw_distance must be calculated first
353 fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
365 sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT];
366 dist = FixedDiv (rw_distance, sinv);
367 cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT];
368 z = abs(FixedMul (dist, cosv));
369 scale = FixedDiv(projection, z);
374 anglea = ANG90 + (visangle-viewangle);
375 angleb = ANG90 + (visangle-rw_normalangle);
376 // bothe sines are allways positive
377 sinea = finesine[anglea>>ANGLETOFINESHIFT];
378 sineb = finesine[angleb>>ANGLETOFINESHIFT];
379 num = FixedMul(projection,sineb)<<detailshift;
380 den = FixedMul(rw_distance,sinea);
383 scale = FixedDiv (num, den);
384 if (scale > 64*FRACUNIT)
386 else if (scale < 256)
405 void R_InitTables (void)
407 // now getting from tables.c
414 // viewangle tangent table
416 for (i=0 ; i<FINEANGLES/2 ; i++)
418 a = (i-FINEANGLES/4+0.5)*PI*2/FINEANGLES;
419 fv = FRACUNIT*tan (a);
427 for (i=0 ; i<5*FINEANGLES/4 ; i++)
429 // OPTIMIZE: mirror...
430 a = (i+0.5)*PI*2/FINEANGLES;
431 t = FRACUNIT*sin (a);
442 = R_InitTextureMapping
447 void R_InitTextureMapping (void)
456 // use tangent table to generate viewangletox
457 // viewangletox will give the next greatest x after the view angle
459 // calc focallength so FIELDOFVIEW angles covers SCREENWIDTH
460 focallength = FixedDiv (centerxfrac
461 , finetangent[FINEANGLES/4+FIELDOFVIEW/2] );
463 for (i=0 ; i<FINEANGLES/2 ; i++)
465 if (finetangent[i] > FRACUNIT*2)
467 else if (finetangent[i] < -FRACUNIT*2)
471 t = FixedMul (finetangent[i], focallength);
472 t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS;
475 else if (t>viewwidth+1)
482 // scan viewangletox[] to generate xtoviewangleangle[]
484 // xtoviewangle will give the smallest view angle that maps to x
485 for (x=0;x<=viewwidth;x++)
488 while (viewangletox[i]>x)
490 xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
494 // take out the fencepost cases from viewangletox
496 for (i=0 ; i<FINEANGLES/2 ; i++)
498 t = FixedMul (finetangent[i], focallength);
500 if (viewangletox[i] == -1)
502 else if (viewangletox[i] == viewwidth+1)
503 viewangletox[i] = viewwidth;
506 clipangle = xtoviewangle[0];
509 //=============================================================================
516 = Only inits the zlight table, because the scalelight table changes
524 void R_InitLightTables (void)
526 int i,j, level, startmap;
530 // Calculate the light levels to use for each level / distance combination
532 for (i=0 ; i< LIGHTLEVELS ; i++)
534 startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
535 for (j=0 ; j<MAXLIGHTZ ; j++)
537 scale = FixedDiv ((SCREENWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
538 scale >>= LIGHTSCALESHIFT;
539 level = startmap - scale/DISTMAP;
542 if (level >= NUMCOLORMAPS)
543 level = NUMCOLORMAPS-1;
544 zlight[i][j] = colormaps + level*256;
555 = Don't really change anything here, because i might be in the middle of
556 = a refresh. The change will take effect next refresh.
561 boolean setsizeneeded;
562 int setblocks, setdetail;
564 void R_SetViewSize (int blocks, int detail)
566 setsizeneeded = true;
574 = R_ExecuteSetViewSize
579 void R_ExecuteSetViewSize (void)
582 int i,j, level, startmap;
584 setsizeneeded = false;
588 scaledviewwidth = SCREENWIDTH;
589 viewheight = SCREENHEIGHT;
593 scaledviewwidth = setblocks*32;
595 viewheight = (setblocks*(200-SBARHEIGHT*sbarscale/20)/10);
597 viewheight = (setblocks*161/10);
601 detailshift = setdetail;
602 viewwidth = scaledviewwidth>>detailshift;
604 centery = viewheight/2;
605 centerx = viewwidth/2;
606 centerxfrac = centerx<<FRACBITS;
607 centeryfrac = centery<<FRACBITS;
608 projection = centerxfrac;
613 colfunc = basecolfunc = R_DrawColumn;
614 fuzzcolfunc = R_DrawFuzzColumn;
615 transcolfunc = R_DrawTranslatedColumn;
616 spanfunc = R_DrawSpan;
620 colfunc = basecolfunc = R_DrawColumnLow;
621 fuzzcolfunc = R_DrawFuzzColumn;
622 transcolfunc = R_DrawTranslatedColumn;
623 spanfunc = R_DrawSpanLow;
627 R_InitBuffer (scaledviewwidth, viewheight);
629 R_InitTextureMapping ();
634 pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
635 pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
640 for (i=0 ; i<viewwidth ; i++)
641 screenheightarray[i] = viewheight;
646 for (i=0 ; i<viewheight ; i++)
648 dy = ((i-viewheight/2)<<FRACBITS)+FRACUNIT/2;
650 yslope[i] = FixedDiv ( (viewwidth<<detailshift)/2*FRACUNIT, dy);
653 for (i=0 ; i<viewwidth ; i++)
655 cosadj = abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
656 distscale[i] = FixedDiv (FRACUNIT,cosadj);
660 // Calculate the light levels to use for each level / scale combination
662 for (i=0 ; i< LIGHTLEVELS ; i++)
664 startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
665 for (j=0 ; j<MAXLIGHTSCALE ; j++)
667 level = startmap - j*SCREENWIDTH/(viewwidth<<detailshift)/DISTMAP;
670 if (level >= NUMCOLORMAPS)
671 level = NUMCOLORMAPS-1;
672 scalelight[i][j] = colormaps + level*256;
679 R_DrawViewBorder (); // erase old menu stuff
697 R_InitPointToAngle();
699 // viewwidth / viewheight / detailLevel are set by the defaults
700 R_SetViewSize(screenblocks, detailLevel);
705 R_InitTranslationTables();
720 subsector_t *R_PointInSubsector (fixed_t x, fixed_t y)
725 if (!numnodes) // single subsector is a special case
728 nodenum = numnodes-1;
730 while (! (nodenum & NF_SUBSECTOR) )
732 node = &nodes[nodenum];
733 side = R_PointOnSide (x, y, node);
734 nodenum = node->children[side];
737 return &subsectors[nodenum & ~NF_SUBSECTOR];
741 //----------------------------------------------------------------------------
745 //----------------------------------------------------------------------------
747 void R_SetupFrame(player_t *player)
756 viewangle = player->mo->angle+viewangleoffset;
758 viewpitch = player->lookdir;
760 tableAngle = viewangle>>ANGLETOFINESHIFT;
761 viewx = player->mo->x;
762 viewy = player->mo->y;
764 if(localQuakeHappening[displayplayer] && !paused)
766 intensity = localQuakeHappening[displayplayer];
767 viewx += ((M_Random() % (intensity<<2))
768 -(intensity<<1))<<FRACBITS;
769 viewy += ((M_Random()%(intensity<<2))
770 -(intensity<<1))<<FRACBITS;
773 extralight = player->extralight;
774 viewz = player->viewz;
777 tempCentery = viewheight/2;
779 tempCentery = viewheight/2+(player->lookdir)*screenblocks/10;
781 if(centery != tempCentery)
783 centery = tempCentery;
784 centeryfrac = centery<<FRACBITS;
785 for(i = 0; i < viewheight; i++)
787 yslope[i] = FixedDiv ((viewwidth<<detailshift)/2*FRACUNIT,
788 abs(((i-centery)<<FRACBITS)+FRACUNIT/2));
791 viewsin = finesine[tableAngle];
792 viewcos = finecosine[tableAngle];
794 if(player->fixedcolormap)
796 fixedcolormap = colormaps+player->fixedcolormap
797 *256*sizeof(lighttable_t);
798 walllights = scalelightfixed;
799 for(i = 0; i < MAXLIGHTSCALE; i++)
801 scalelightfixed[i] = fixedcolormap;
810 if(BorderNeedRefresh)
820 BorderNeedRefresh = false;
821 BorderTopRefresh = false;
822 UpdateState |= I_FULLSCRN;
830 BorderTopRefresh = false;
831 UpdateState |= I_MESSAGES;
835 RD_ClearMapWindow ();
841 memset (screen, frame, SCREENWIDTH*SCREENHEIGHT);
855 void R_RenderPlayerView (player_t *player)
857 R_SetupFrame (player);
866 NetUpdate (); // check for new console commands
869 OGL_SwitchTo3DState();
872 // Make displayed player invisible locally
873 if (localQuakeHappening[displayplayer] && gamestate == GS_LEVEL)
875 players[displayplayer].mo->flags2 |= MF2_DONTDRAW;
879 R_RenderBSPNode (numnodes-1); // head node is the last node output
881 players[displayplayer].mo->flags2 &= ~MF2_DONTDRAW;
888 R_RenderBSPNode (numnodes-1); // head node is the last node output
892 NetUpdate (); // check for new console commands
896 NetUpdate (); // check for new console commands
900 NetUpdate (); // check for new console commands
903 OGL_Restore2DState(1);
906 if( viewangleoffset <= 1024<<ANGLETOFINESHIFT || viewangleoffset >=
907 -1024<<ANGLETOFINESHIFT )
908 { // don't draw on side views
909 R_DrawPlayerSprites();
912 OGL_Restore2DState(2);