]> icculus.org git repositories - theoddone33/hhexen.git/blob - base/r_main.c
Initial revision
[theoddone33/hhexen.git] / base / r_main.c
1
2 //**************************************************************************
3 //**
4 //** r_main.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile$
7 //** $Revision$
8 //** $Date$
9 //** $Author$
10 //**
11 //**************************************************************************
12
13 #include <math.h>
14 #include "h2def.h"
15 #include "r_local.h"
16 #ifdef RENDER3D
17 #include "ogl_def.h"
18 #endif
19
20 #ifdef RENDER3D
21 extern void R_RenderMap();
22 extern void R_DrawPlayerSprites();
23 #endif
24
25 int                     viewangleoffset;
26
27
28 int                     validcount = 1;         // increment every time a check is made
29
30 lighttable_t    *fixedcolormap;
31 extern  lighttable_t    **walllights;
32
33 int                             centerx, centery;
34 fixed_t                 centerxfrac, centeryfrac;
35 fixed_t                 projection;
36
37 int                             framecount;             // just for profiling purposes
38
39 int             sscount, linecount, loopcount;
40
41 fixed_t         viewx, viewy, viewz;
42 angle_t         viewangle;
43 fixed_t         viewcos, viewsin;
44 player_t        *viewplayer;
45
46 #ifdef RENDER3D
47 float       viewpitch;          // player->lookdir, global version
48 #endif
49
50 int                             detailshift;            // 0 = high, 1 = low
51
52 //
53 // precalculated math tables
54 //
55 angle_t         clipangle;
56
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];
61
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];
65
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];
69
70 // fixed_t              finesine[5*FINEANGLES/4];
71 fixed_t         *finecosine = &finesine[FINEANGLES/4];
72
73
74 lighttable_t    *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
75 lighttable_t    *scalelightfixed[MAXLIGHTSCALE];
76 lighttable_t    *zlight[LIGHTLEVELS][MAXLIGHTZ];
77
78 int                     extralight;                     // bumped light from gun blasts
79
80 void            (*colfunc) (void);
81 void            (*basecolfunc) (void);
82 void            (*fuzzcolfunc) (void);
83 void            (*transcolfunc) (void);
84 void            (*spanfunc) (void);
85
86 /*
87 ===================
88 =
89 = R_AddPointToBox
90 =
91 ===================
92 */
93
94 /*
95 void R_AddPointToBox (int x, int y, fixed_t *box)
96 {
97         if (x< box[BOXLEFT])
98                 box[BOXLEFT] = x;
99         if (x> box[BOXRIGHT])
100                 box[BOXRIGHT] = x;
101         if (y< box[BOXBOTTOM])
102                 box[BOXBOTTOM] = y;
103         if (y> box[BOXTOP])
104                 box[BOXTOP] = y;
105 }
106 */
107
108
109 /*
110 ===============================================================================
111 =
112 = R_PointOnSide
113 =
114 = Returns side 0 (front) or 1 (back)
115 ===============================================================================
116 */
117
118 int     R_PointOnSide (fixed_t x, fixed_t y, node_t *node)
119 {
120         fixed_t dx,dy;
121         fixed_t left, right;
122
123         if (!node->dx)
124         {
125                 if (x <= node->x)
126                         return node->dy > 0;
127                 return node->dy < 0;
128         }
129         if (!node->dy)
130         {
131                 if (y <= node->y)
132                         return node->dx < 0;
133                 return node->dx > 0;
134         }
135
136         dx = (x - node->x);
137         dy = (y - node->y);
138
139 // try to quickly decide by looking at sign bits
140         if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 )
141         {
142                 if  ( (node->dy ^ dx) & 0x80000000 )
143                         return 1;       // (left is negative)
144                 return 0;
145         }
146
147         left = FixedMul ( node->dy>>FRACBITS , dx );
148         right = FixedMul ( dy , node->dx>>FRACBITS );
149
150         if (right < left)
151                 return 0;               // front side
152         return 1;                       // back side
153 }
154
155
156 int     R_PointOnSegSide (fixed_t x, fixed_t y, seg_t *line)
157 {
158         fixed_t lx, ly;
159         fixed_t ldx, ldy;
160         fixed_t dx,dy;
161         fixed_t left, right;
162
163         lx = line->v1->x;
164         ly = line->v1->y;
165
166         ldx = line->v2->x - lx;
167         ldy = line->v2->y - ly;
168
169         if (!ldx)
170         {
171                 if (x <= lx)
172                         return ldy > 0;
173                 return ldy < 0;
174         }
175         if (!ldy)
176         {
177                 if (y <= ly)
178                         return ldx < 0;
179                 return ldx > 0;
180         }
181
182         dx = (x - lx);
183         dy = (y - ly);
184
185 // try to quickly decide by looking at sign bits
186         if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 )
187         {
188                 if  ( (ldy ^ dx) & 0x80000000 )
189                         return 1;       // (left is negative)
190                 return 0;
191         }
192
193         left = FixedMul ( ldy>>FRACBITS , dx );
194         right = FixedMul ( dy , ldx>>FRACBITS );
195
196         if (right < left)
197                 return 0;               // front side
198         return 1;                       // back side
199 }
200
201
202 /*
203 ===============================================================================
204 =
205 = R_PointToAngle
206 =
207 ===============================================================================
208 */
209
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
216 #define SLOPEBITS       11
217 #define DBITS           (FRACBITS-SLOPEBITS)
218
219
220 extern  int     tantoangle[SLOPERANGE+1];               // get from tables.c
221
222 // int  tantoangle[SLOPERANGE+1];
223
224 int SlopeDiv (unsigned num, unsigned den)
225 {
226         unsigned ans;
227         if (den < 512)
228                 return SLOPERANGE;
229         ans = (num<<3)/(den>>8);
230         return ans <= SLOPERANGE ? ans : SLOPERANGE;
231 }
232
233 angle_t R_PointToAngle (fixed_t x, fixed_t y)
234 {
235         x -= viewx;
236         y -= viewy;
237         if ( (!x) && (!y) )
238                 return 0;
239         if (x>= 0)
240         {       // x >=0
241                 if (y>= 0)
242                 {       // y>= 0
243                         if (x>y)
244                                 return tantoangle[ SlopeDiv(y,x)];     // octant 0
245                         else
246                                 return ANG90-1-tantoangle[ SlopeDiv(x,y)];  // octant 1
247                 }
248                 else
249                 {       // y<0
250                         y = -y;
251                         if (x>y)
252                                 return -tantoangle[SlopeDiv(y,x)];  // octant 8
253                         else
254                                 return ANG270+tantoangle[ SlopeDiv(x,y)];  // octant 7
255                 }
256         }
257         else
258         {       // x<0
259                 x = -x;
260                 if (y>= 0)
261                 {       // y>= 0
262                         if (x>y)
263                                 return ANG180-1-tantoangle[ SlopeDiv(y,x)]; // octant 3
264                         else
265                                 return ANG90+ tantoangle[ SlopeDiv(x,y)];  // octant 2
266                 }
267                 else
268                 {       // y<0
269                         y = -y;
270                         if (x>y)
271                                 return ANG180+tantoangle[ SlopeDiv(y,x)];  // octant 4
272                         else
273                                 return ANG270-1-tantoangle[ SlopeDiv(x,y)];  // octant 5
274                 }
275         }
276
277         return 0;
278 }
279
280
281 angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
282 {
283         viewx = x1;
284         viewy = y1;
285         return R_PointToAngle (x2, y2);
286 }
287
288
289 fixed_t R_PointToDist (fixed_t x, fixed_t y)
290 {
291         int             angle;
292         fixed_t dx, dy, temp;
293         fixed_t dist;
294
295         dx = abs(x - viewx);
296         dy = abs(y - viewy);
297
298         if (dy>dx)
299         {
300                 temp = dx;
301                 dx = dy;
302                 dy = temp;
303         }
304
305         angle = (tantoangle[ FixedDiv(dy,dx)>>DBITS ]+ANG90) >> ANGLETOFINESHIFT;
306
307         dist = FixedDiv (dx, finesine[angle] ); // use as cosine
308
309         return dist;
310 }
311
312
313
314 /*
315 =================
316 =
317 = R_InitPointToAngle
318 =
319 =================
320 */
321
322 void R_InitPointToAngle (void)
323 {
324 // now getting from tables.c
325 #if 0
326         int     i;
327         long    t;
328         float   f;
329 //
330 // slope (tangent) to angle lookup
331 //
332         for (i=0 ; i<=SLOPERANGE ; i++)
333         {
334                 f = atan( (float)i/SLOPERANGE )/(3.141592657*2);
335                 t = 0xffffffff*f;
336                 tantoangle[i] = t;
337         }
338 #endif
339 }
340
341 //=============================================================================
342
343 /*
344 ================
345 =
346 = R_ScaleFromGlobalAngle
347 =
348 = Returns the texture mapping scale for the current line at the given angle
349 = rw_distance must be calculated first
350 ================
351 */
352
353 fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
354 {
355         fixed_t         scale;
356         int                     anglea, angleb;
357         int                     sinea, sineb;
358         fixed_t         num,den;
359
360 #if 0
361 {
362         fixed_t         dist,z;
363         fixed_t         sinv, cosv;
364
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);
370         return scale;
371 }
372 #endif
373
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);
381         if (den > num>>16)
382         {
383                 scale = FixedDiv (num, den);
384                 if (scale > 64*FRACUNIT)
385                         scale = 64*FRACUNIT;
386                 else if (scale < 256)
387                         scale = 256;
388         }
389         else
390                 scale = 64*FRACUNIT;
391
392         return scale;
393 }
394
395
396
397 /*
398 =================
399 =
400 = R_InitTables
401 =
402 =================
403 */
404
405 void R_InitTables (void)
406 {
407 // now getting from tables.c
408 #if 0
409         int             i;
410         float           a, fv;
411         int                     t;
412
413 //
414 // viewangle tangent table
415 //
416         for (i=0 ; i<FINEANGLES/2 ; i++)
417         {
418                 a = (i-FINEANGLES/4+0.5)*PI*2/FINEANGLES;
419                 fv = FRACUNIT*tan (a);
420                 t = fv;
421                 finetangent[i] = t;
422         }
423
424 //
425 // finesine table
426 //
427         for (i=0 ; i<5*FINEANGLES/4 ; i++)
428         {
429 // OPTIMIZE: mirror...
430                 a = (i+0.5)*PI*2/FINEANGLES;
431                 t = FRACUNIT*sin (a);
432                 finesine[i] = t;
433         }
434 #endif
435
436 }
437
438
439 /*
440 =================
441 =
442 = R_InitTextureMapping
443 =
444 =================
445 */
446
447 void R_InitTextureMapping (void)
448 {
449         int                     i;
450         int                     x;
451         int                     t;
452         fixed_t         focallength;
453
454
455 //
456 // use tangent table to generate viewangletox
457 // viewangletox will give the next greatest x after the view angle
458 //
459         // calc focallength so FIELDOFVIEW angles covers SCREENWIDTH
460         focallength = FixedDiv (centerxfrac
461         , finetangent[FINEANGLES/4+FIELDOFVIEW/2] );
462
463         for (i=0 ; i<FINEANGLES/2 ; i++)
464         {
465                 if (finetangent[i] > FRACUNIT*2)
466                         t = -1;
467                 else if (finetangent[i] < -FRACUNIT*2)
468                         t = viewwidth+1;
469                 else
470                 {
471                         t = FixedMul (finetangent[i], focallength);
472                         t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS;
473                         if (t < -1)
474                                 t = -1;
475                         else if (t>viewwidth+1)
476                                 t = viewwidth+1;
477                 }
478                 viewangletox[i] = t;
479         }
480
481 //
482 // scan viewangletox[] to generate xtoviewangleangle[]
483 //
484 // xtoviewangle will give the smallest view angle that maps to x
485         for (x=0;x<=viewwidth;x++)
486         {
487                 i = 0;
488                 while (viewangletox[i]>x)
489                         i++;
490                 xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
491         }
492
493 //
494 // take out the fencepost cases from viewangletox
495 //
496         for (i=0 ; i<FINEANGLES/2 ; i++)
497         {
498                 t = FixedMul (finetangent[i], focallength);
499                 t = centerx - t;
500                 if (viewangletox[i] == -1)
501                         viewangletox[i] = 0;
502                 else if (viewangletox[i] == viewwidth+1)
503                         viewangletox[i]  = viewwidth;
504         }
505
506         clipangle = xtoviewangle[0];
507 }
508
509 //=============================================================================
510
511 /*
512 ====================
513 =
514 = R_InitLightTables
515 =
516 = Only inits the zlight table, because the scalelight table changes
517 = with view size
518 =
519 ====================
520 */
521
522 #define         DISTMAP 2
523
524 void R_InitLightTables (void)
525 {
526         int             i,j, level, startmap;
527         int             scale;
528
529 //
530 // Calculate the light levels to use for each level / distance combination
531 //
532         for (i=0 ; i< LIGHTLEVELS ; i++)
533         {
534                 startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
535                 for (j=0 ; j<MAXLIGHTZ ; j++)
536                 {
537                         scale = FixedDiv ((SCREENWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
538                         scale >>= LIGHTSCALESHIFT;
539                         level = startmap - scale/DISTMAP;
540                         if (level < 0)
541                                 level = 0;
542                         if (level >= NUMCOLORMAPS)
543                                 level = NUMCOLORMAPS-1;
544                         zlight[i][j] = colormaps + level*256;
545                 }
546         }
547 }
548
549
550 /*
551 ==============
552 =
553 = R_SetViewSize
554 =
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.
557 =
558 ==============
559 */
560
561 boolean setsizeneeded;
562 int             setblocks, setdetail;
563
564 void R_SetViewSize (int blocks, int detail)
565 {
566         setsizeneeded = true;
567         setblocks = blocks;
568         setdetail = detail;
569 }
570
571 /*
572 ==============
573 =
574 = R_ExecuteSetViewSize
575 =
576 ==============
577 */
578
579 void R_ExecuteSetViewSize (void)
580 {
581         fixed_t cosadj, dy;
582         int             i,j, level, startmap;
583
584         setsizeneeded = false;
585
586         if (setblocks == 11)
587         {
588                 scaledviewwidth = SCREENWIDTH;
589                 viewheight = SCREENHEIGHT;
590         }
591         else
592         {
593                 scaledviewwidth = setblocks*32;
594 #ifdef RENDER3D
595         viewheight = (setblocks*(200-SBARHEIGHT*sbarscale/20)/10);
596 #else
597                 viewheight = (setblocks*161/10);
598 #endif
599         }
600
601         detailshift = setdetail;
602         viewwidth = scaledviewwidth>>detailshift;
603
604         centery = viewheight/2;
605         centerx = viewwidth/2;
606         centerxfrac = centerx<<FRACBITS;
607         centeryfrac = centery<<FRACBITS;
608         projection = centerxfrac;
609
610 #ifndef RENDER3D
611         if (!detailshift)
612         {
613                 colfunc = basecolfunc = R_DrawColumn;
614                 fuzzcolfunc = R_DrawFuzzColumn;
615                 transcolfunc = R_DrawTranslatedColumn;
616                 spanfunc = R_DrawSpan;
617         }
618         else
619         {
620                 colfunc = basecolfunc = R_DrawColumnLow;
621                 fuzzcolfunc = R_DrawFuzzColumn;
622                 transcolfunc = R_DrawTranslatedColumn;
623                 spanfunc = R_DrawSpanLow;
624         }
625 #endif
626
627         R_InitBuffer (scaledviewwidth, viewheight);
628
629         R_InitTextureMapping ();
630
631 //
632 // psprite scales
633 //
634         pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
635         pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
636
637 //
638 // thing clipping
639 //
640         for (i=0 ; i<viewwidth ; i++)
641                 screenheightarray[i] = viewheight;
642
643 //
644 // planes
645 //
646         for (i=0 ; i<viewheight ; i++)
647         {
648                 dy = ((i-viewheight/2)<<FRACBITS)+FRACUNIT/2;
649                 dy = abs(dy);
650                 yslope[i] = FixedDiv ( (viewwidth<<detailshift)/2*FRACUNIT, dy);
651         }
652
653         for (i=0 ; i<viewwidth ; i++)
654         {
655                 cosadj = abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
656                 distscale[i] = FixedDiv (FRACUNIT,cosadj);
657         }
658
659 //
660 // Calculate the light levels to use for each level / scale combination
661 //
662         for (i=0 ; i< LIGHTLEVELS ; i++)
663         {
664                 startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
665                 for (j=0 ; j<MAXLIGHTSCALE ; j++)
666                 {
667                         level = startmap - j*SCREENWIDTH/(viewwidth<<detailshift)/DISTMAP;
668                         if (level < 0)
669                                 level = 0;
670                         if (level >= NUMCOLORMAPS)
671                                 level = NUMCOLORMAPS-1;
672                         scalelight[i][j] = colormaps + level*256;
673                 }
674         }
675
676 //
677 // draw the border
678 //
679         R_DrawViewBorder ();    // erase old menu stuff
680 }
681
682
683 /*
684 ==============
685 =
686 = R_Init
687 =
688 ==============
689 */
690
691 int detailLevel;
692 int screenblocks;
693
694 void R_Init(void)
695 {
696         R_InitData();
697         R_InitPointToAngle();
698         R_InitTables();
699         // viewwidth / viewheight / detailLevel are set by the defaults
700         R_SetViewSize(screenblocks, detailLevel);
701         R_InitPlanes();
702         R_InitLightTables();
703         R_InitSkyMap();
704 #ifndef RENDER3D
705         R_InitTranslationTables();
706 #else
707     OGL_InitData();
708 #endif
709         framecount = 0;
710 }
711
712 /*
713 ==============
714 =
715 = R_PointInSubsector
716 =
717 ==============
718 */
719
720 subsector_t *R_PointInSubsector (fixed_t x, fixed_t y)
721 {
722         node_t  *node;
723         int             side, nodenum;
724
725         if (!numnodes)                          // single subsector is a special case
726                 return subsectors;
727
728         nodenum = numnodes-1;
729
730         while (! (nodenum & NF_SUBSECTOR) )
731         {
732                 node = &nodes[nodenum];
733                 side = R_PointOnSide (x, y, node);
734                 nodenum = node->children[side];
735         }
736
737         return &subsectors[nodenum & ~NF_SUBSECTOR];
738
739 }
740
741 //----------------------------------------------------------------------------
742 //
743 // PROC R_SetupFrame
744 //
745 //----------------------------------------------------------------------------
746
747 void R_SetupFrame(player_t *player)
748 {
749         int i;
750         int tableAngle;
751         int tempCentery;
752         int intensity;
753
754         //drawbsp = 1;
755         viewplayer = player; 
756         viewangle = player->mo->angle+viewangleoffset;
757 #ifdef RENDER3D
758     viewpitch = player->lookdir;
759 #endif
760         tableAngle = viewangle>>ANGLETOFINESHIFT;
761         viewx = player->mo->x;
762         viewy = player->mo->y;
763
764         if(localQuakeHappening[displayplayer] && !paused)
765         {
766                 intensity = localQuakeHappening[displayplayer];
767                 viewx += ((M_Random() % (intensity<<2))
768                                         -(intensity<<1))<<FRACBITS;
769                 viewy += ((M_Random()%(intensity<<2))
770                                         -(intensity<<1))<<FRACBITS;
771         }
772
773         extralight = player->extralight;
774         viewz = player->viewz;
775         
776 #ifdef RENDER3D
777         tempCentery = viewheight/2;
778 #else
779         tempCentery = viewheight/2+(player->lookdir)*screenblocks/10;
780 #endif
781         if(centery != tempCentery)
782         {
783                 centery = tempCentery;
784                 centeryfrac = centery<<FRACBITS;
785                 for(i = 0; i < viewheight; i++)
786                 {
787                         yslope[i] = FixedDiv ((viewwidth<<detailshift)/2*FRACUNIT,
788                                 abs(((i-centery)<<FRACBITS)+FRACUNIT/2));
789                 }
790         }
791         viewsin = finesine[tableAngle];
792         viewcos = finecosine[tableAngle];
793         sscount = 0;
794         if(player->fixedcolormap)
795         {
796                 fixedcolormap = colormaps+player->fixedcolormap
797                         *256*sizeof(lighttable_t);
798                 walllights = scalelightfixed;
799                 for(i = 0; i < MAXLIGHTSCALE; i++)
800                 {
801                         scalelightfixed[i] = fixedcolormap;
802                 }
803         }
804         else
805         {
806                 fixedcolormap = 0;
807         }
808         framecount++;
809         validcount++;
810         if(BorderNeedRefresh)
811         {
812 #ifdef RENDER3D
813         R_DrawViewBorder();
814 #else
815                 if(setblocks < 10)
816                 {
817                         R_DrawViewBorder();
818                 }
819 #endif
820                 BorderNeedRefresh = false;
821                 BorderTopRefresh = false;
822                 UpdateState |= I_FULLSCRN;
823         }
824         if(BorderTopRefresh)
825         {
826                 if(setblocks < 10)
827                 {
828                         R_DrawTopBorder();
829                 }
830                 BorderTopRefresh = false;
831                 UpdateState |= I_MESSAGES;
832         }
833
834 #ifdef __NeXT__
835         RD_ClearMapWindow ();
836 #endif
837
838 #if 0
839 {
840 static int frame;
841 memset (screen, frame, SCREENWIDTH*SCREENHEIGHT);
842 frame++;
843 }
844 #endif
845 }
846
847 /*
848 ==============
849 =
850 = R_RenderView
851 =
852 ==============
853 */
854
855 void R_RenderPlayerView (player_t *player)
856 {
857         R_SetupFrame (player);
858
859 #ifndef RENDER3D
860         R_ClearClipSegs ();
861         R_ClearDrawSegs ();
862         R_ClearPlanes ();
863 #endif
864
865         R_ClearSprites ();
866         NetUpdate ();                                   // check for new console commands
867
868 #ifdef RENDER3D
869     OGL_SwitchTo3DState();
870 #endif
871
872         // Make displayed player invisible locally
873         if (localQuakeHappening[displayplayer] && gamestate == GS_LEVEL)
874         {
875                 players[displayplayer].mo->flags2 |= MF2_DONTDRAW;
876 #ifdef RENDER3D
877         R_RenderMap();
878 #else
879                 R_RenderBSPNode (numnodes-1);   // head node is the last node output
880 #endif
881                 players[displayplayer].mo->flags2 &= ~MF2_DONTDRAW;
882         }
883         else
884         {
885 #ifdef RENDER3D
886         R_RenderMap();
887 #else
888                 R_RenderBSPNode (numnodes-1);   // head node is the last node output
889 #endif
890         }
891
892         NetUpdate ();                                   // check for new console commands
893
894 #ifndef RENDER3D
895         R_DrawPlanes ();
896         NetUpdate ();                                   // check for new console commands
897 #endif
898
899         R_DrawMasked ();
900         NetUpdate ();                                   // check for new console commands
901
902 #ifdef RENDER3D
903     OGL_Restore2DState(1);
904  
905     // Draw psprites.
906     if( viewangleoffset <= 1024<<ANGLETOFINESHIFT || viewangleoffset >=
907         -1024<<ANGLETOFINESHIFT )
908     {   // don't draw on side views
909         R_DrawPlayerSprites();
910     }
911  
912     OGL_Restore2DState(2);
913 #endif
914 }