1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: r_main.c 1498 2020-01-05 22:13:26Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Portions Copyright (C) 1998-2012 by DooM Legacy Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 //
20 // $Log: r_main.c,v $
21 // Revision 1.29  2004/09/12 19:40:08  darkwolf95
22 // additional chex quest 1 support
23 //
24 // Revision 1.28  2004/04/18 12:40:15  hurdler
25 // Jive's request for saving screenshots
26 //
27 // Revision 1.27  2003/08/12 12:29:42  hurdler
28 // better translucent hud
29 //
30 // Revision 1.26  2003/08/11 13:50:01  hurdler
31 // go final + translucent HUD + fix spawn in net game
32 //
33 // Revision 1.25  2001/08/20 20:40:39  metzgermeister
34 //
35 // Revision 1.24  2001/08/06 23:57:09  stroggonmeth
36 // Removed portal code, improved 3D floors in hardware mode.
37 //
38 // Revision 1.23  2001/05/16 21:21:14  bpereira
39 // Revision 1.22  2001/03/30 17:12:51  bpereira
40 // Revision 1.21  2001/03/21 18:24:39  stroggonmeth
41 //
42 // Revision 1.20  2001/03/13 22:14:20  stroggonmeth
43 // Long time no commit. 3D floors, FraggleScript, portals, ect.
44 //
45 // Revision 1.19  2001/02/10 12:27:14  bpereira
46 //
47 // Revision 1.18  2001/01/25 22:15:44  bpereira
48 // added heretic support
49 //
50 // Revision 1.17  2000/11/02 17:50:09  stroggonmeth
51 // Big 3Dfloors & FraggleScript commit!!
52 //
53 // Revision 1.16  2000/10/04 16:19:24  hurdler
54 // Change all those "3dfx names" to more appropriate names
55 //
56 // Revision 1.15  2000/09/28 20:57:17  bpereira
57 // Revision 1.14  2000/09/21 16:45:06  bpereira
58 // Revision 1.13  2000/08/31 14:30:56  bpereira
59 // Revision 1.12  2000/07/01 09:23:49  bpereira
60 // Revision 1.11  2000/04/30 10:30:10  bpereira
61 // Revision 1.10  2000/04/24 20:24:38  bpereira
62 // Revision 1.9  2000/04/18 17:39:39  stroggonmeth
63 // Revision 1.8  2000/04/08 17:29:25  stroggonmeth
64 //
65 // Revision 1.7  2000/04/06 21:06:19  stroggonmeth
66 // Optimized extra_colormap code...
67 // Added #ifdefs for older water code.
68 //
69 // Revision 1.6  2000/04/04 19:28:43  stroggonmeth
70 // Global colormaps working. Added a new linedef type 272.
71 //
72 // Revision 1.5  2000/04/04 00:32:47  stroggonmeth
73 // Initial Boom compatability plus few misc changes all around.
74 //
75 // Revision 1.4  2000/03/06 15:15:54  hurdler
76 //
77 // Revision 1.3  2000/02/27 16:30:28  hurdler
78 // dead player bug fix + add allowmlook <yes|no>
79 //
80 // Revision 1.2  2000/02/27 00:42:10  hurdler
81 // Revision 1.1.1.1  2000/02/22 20:32:33  hurdler
82 // Initial import into CVS (v1.29 pr3)
83 //
84 //
85 // DESCRIPTION:
86 //      Rendering main loop and setup functions,
87 //       utility functions (BSP, geometry, trigonometry).
88 //      See tables.c, too.
89 //
90 //-----------------------------------------------------------------------------
91 
92 #include "doomincl.h"
93 #include "g_game.h"
94 #include "g_input.h"
95 #include "r_local.h"
96 #include "r_splats.h"   //faB(21jan):testing
97 #include "r_sky.h"
98 #include "st_stuff.h"
99 #include "p_local.h"
100 #include "keys.h"
101 #include "i_video.h"
102 #include "m_menu.h"
103 #include "p_local.h"
104 #include "t_func.h"
105 #include "am_map.h"
106 #include "d_main.h"
107 
108 #ifdef HWRENDER
109 #include "hardware/hw_main.h"
110 #endif
111 
112 
113 //profile stuff ---------------------------------------------------------
114 //#define TIMING
115 #ifdef TIMING
116 #include "p5prof.h"
117 long long mycount;
118 long long mytotal = 0;
119 //unsigned long  nombre = 100000;
120 #endif
121 //profile stuff ---------------------------------------------------------
122 
123 
124 // Fineangles in the SCREENWIDTH wide window.  FINE_ANG90=2048.
125 #define FINE_FIELDOFVIEW    2048
126 
127 
128 
129 int                     viewangleoffset;
130 
131 // increment every time a check is made
132 int                     validcount = 1;
133 
134 // center of perspective projection, in screen coordinates, 0=top
135 int                     centerx;
136 int                     centery;
137 int                     centerypsp;     //added:06-02-98:cf R_DrawPSprite
138 
139 // center of perspective projection, in screen coordinates << FRACBITS
140 fixed_t                 centerxfrac;
141 fixed_t                 centeryfrac;
142 
143 fixed_t                 projection;
144 //added:02-02-98:fixing the aspect ratio stuff...
145 fixed_t                 projectiony;
146 
147 // just for profiling purposes
148 int                     framecount;
149 
150 int                     sscount;
151 int                     linecount;
152 int                     loopcount;
153 
154 // fog render gobals
155 uint16_t   fog_col_length;  // post_t column or picture height
156 uint16_t   fog_tic;    // 0..0xFFF, tic per fog change
157 byte	   fog_bltic;  // 0..31, blend/blur between tics
158 tic_t      fog_nexttic;
159 uint16_t   fog_wave1 = 0x200;   // 0..0x3FF, random small scale changes
160 uint16_t   fog_wave2 = 0x200;   // 0..0x3FF, random slower
161 byte       fog_index;  // 0.. column or texture height, for slow fog effect
162 byte	   fog_init = 0;   // set 1 at fog linedef to clear previous fog blur
163 
164 // current viewer
165 // Set by R_SetupFrame
166 
167 // Normally NULL, which allows normal colormap.
168 // Set to one lighttable_t entry of colormap table.
169 // pain=>REDCOLORMAP, invulnerability=>INVERSECOLORMAP, goggles=>colormap[1]
170 // Set from current viewer
171 lighttable_t*           fixedcolormap;
172 
173 mobj_t *   viewmobj;
174 
175 sector_t * viewer_sector;
176 int      viewer_modelsec;
177 boolean  viewer_has_model;
178 boolean  viewer_underwater;  // only set when viewer_has_model
179 boolean  viewer_at_water;    // viewer straddles the water plane
180 boolean  viewer_overceiling; // only set when viewer_has_model
181 boolean  viewer_at_ceiling;  // viewer straddles the ceiling plane
182 
183 // Boom colormap, and global viewer coloring
184 lighttable_t*           view_colormap;  // full lightlevel range colormaps
185 extracolormap_t *       view_extracolormap;
186 ffloor_t *  view_fogfloor;  // viewer is in a FF_FOG floor
187 sector_t *  view_fogmodel;  // viewer is in a FF_FOG floor
188 
189 fixed_t                 viewx;
190 fixed_t                 viewy;
191 fixed_t                 viewz;  // world coord
192 
193 angle_t                 viewangle;
194 angle_t                 aimingangle;
195 
196 fixed_t                 viewcos;
197 fixed_t                 viewsin;
198 
199 player_t*               viewplayer;
200 
201 // END current viewer
202 
203 // 0 = high, 1 = low
204 int                     detailshift;
205 
206 //
207 // precalculated math tables
208 //
209 angle_t                 clipangle, clipangle_x_2;
210 
211 // The viewangle_to_x[viewangle + FINE_ANG90] lookup
212 // maps the visible view angles to screen X coordinates,
213 // flattening the arc to a flat projection plane.
214 // There will be many angles mapped to the same X.
215 int                     viewangle_to_x[FINE_ANG180];
216 
217 // The x_to_viewangleangle[] table maps a screen pixel
218 // to the lowest viewangle that maps back to x ranges
219 // from clipangle to -clipangle.
220 angle_t                 x_to_viewangle[MAXVIDWIDTH+1];
221 
222 
223 lighttable_t*           scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
224 lighttable_t*           scalelightfixed[MAXLIGHTSCALE];
225 lighttable_t*           zlight[LIGHTLEVELS][MAXLIGHTZ];
226 
227 //SoM: 3/30/2000: Hack to support extra boom colormaps.
228 int                     num_extra_colormaps = 0;
229 extracolormap_t         extra_colormaps[MAXCOLORMAPS];
230 
231 // bumped light from gun blasts
232 lightlev_t  extralight;	     // extralight seen by most draws
233 lightlev_t  extralight_fog;  // partial extralight used by FF_FOG
234 lightlev_t  extralight_cm;   // partial extralight used by colormap->fog
235 
236 consvar_t cv_chasecam       = {"chasecam","0",0,CV_OnOff};
237 
238 consvar_t cv_psprites       = {"playersprites","1",0,CV_OnOff};
239 consvar_t cv_perspcorr      = {"perspectivecrunch","0",0,CV_OnOff};
240 consvar_t cv_tiltview       = {"tiltview","0",0,CV_OnOff};
241 
242 CV_PossibleValue_t viewsize_cons_t[]={{3,"MIN"},{12,"MAX"},{0,NULL}};
243 CV_PossibleValue_t detaillevel_cons_t[]={{0,"High"},{1,"Low"},{0,NULL}};
244 
245 consvar_t cv_viewsize       = {"viewsize","10",CV_SAVE|CV_CALL,viewsize_cons_t,R_SetViewSize};      //3-12
246 consvar_t cv_detaillevel    = {"detaillevel","0",CV_SAVE|CV_CALL,detaillevel_cons_t,R_SetViewSize}; // UNUSED
247 consvar_t cv_scalestatusbar = {"scalestatusbar","0",CV_SAVE|CV_CALL,CV_YesNo,R_SetViewSize};
248 
249 CV_PossibleValue_t grtranslucenthud_cons_t[] = { {1, "MIN"}, {255, "MAX"}, {0, NULL} };
250 consvar_t cv_grtranslucenthud = {"gr_translucenthud","255",CV_SAVE|CV_CALL,grtranslucenthud_cons_t,R_SetViewSize}; //Hurdler: support translucent HUD
251 
252 CV_PossibleValue_t screenshot_type_cons_t[]={{0,"Compact"},{1,"Full"},
253 #ifdef SMIF_PC_DOS
254    {8,"PCX"},
255 #endif
256    {0,NULL}};
257 consvar_t cv_screenshot_type = { "screenshottype", "", CV_SAVE, NULL };
258 consvar_t cv_screenshot_dir = { "screenshotdir", "", CV_SAVE, NULL };
259 
260 // Boom Colormap Selection
261 CV_PossibleValue_t boom_colormap_cons_t[]={
262    {0,"Sector visible"},  // Sector colormap rules
263    {1,"Boom visible"},  // Boom colormap, visible
264    {2,"Boom normal" },  // Boom colormap rules
265    {3,"Boom detect"},    // Detect Boom features
266    {0,NULL} };
267 void BoomColormap_detect(void);
268 consvar_t cv_boom_colormap   = {"boomcolormap", "0", CV_SAVE|CV_CALL, boom_colormap_cons_t, BoomColormap_detect};
269 
270 byte EN_boom_colormap = 1;  // compatibility, user preference
BoomColormap_detect(void)271 void BoomColormap_detect(void)
272 {
273     switch( cv_boom_colormap.EV )
274     {
275      default:
276      case 0:  // sector colormap
277        EN_boom_colormap = 0;  // Legacy sector colormap
278        break;
279      case 1:  // Boom colormap
280        EN_boom_colormap = 1;  // visible colormap
281        break;
282      case 2:  // Boom visible colormap
283        EN_boom_colormap = 2;  // full boom compatibility
284        break;
285      case 3:  // Boom detect
286        EN_boom_colormap = boom_detect ? ( legacy_detect ? 1 : 2 ) : 0;
287        break;
288     }
289 }
290 
291 CV_PossibleValue_t invul_skymap_cons_t[]={
292    {0,"Vanilla"},  // Vanilla no colormap change
293    {1,"Boom"},     // Boom colormap change
294    {0,NULL} };
295 consvar_t cv_invul_skymap  = {"invul_skymap", "1", CV_SAVE, invul_skymap_cons_t};
296 
297 // matches fogwater_effect_e
298 CV_PossibleValue_t  fogwater_effect_cons_t[]={
299    {FW_colormap,"Colormap" },
300    {FW_clear,"Clear"},
301    {FW_cast,"Cast"},
302    {FW_fogfluid,"Fog Fluid"},
303    {FW_inside,"Inside"},
304    {FW_foglite,"Fog Lite"},
305    {FW_fogdust,"Fog Dust"},
306    {FW_fogsheet,"Fog Sheet"},
307    {0,NULL} };
308 consvar_t cv_water_effect = {"watereffect", "Clear", CV_SAVE|CV_CALL, fogwater_effect_cons_t, R_FW_config_update};
309 consvar_t cv_fog_effect = {"fogeffect", "Fog Dust", CV_SAVE|CV_CALL, fogwater_effect_cons_t, R_FW_config_update};
310 
311 // added 16-6-98:splitscreen
312 
313 void SplitScreen_OnChange(void);
314 
315 consvar_t cv_splitscreen = {"splitscreen","0",CV_CALL ,CV_OnOff,SplitScreen_OnChange};
316 
SplitScreen_OnChange(void)317 void SplitScreen_OnChange(void)
318 {
319     // recompute screen size
320     R_ExecuteSetViewSize();
321 
322     // change the menu
323     M_Player2_MenuEnable( cv_splitscreen.EV );
324 
325     if( !demoplayback)
326     {
327         CL_Splitscreen_Player_Manager();
328 
329         if(server && !netgame)
330             multiplayer = cv_splitscreen.EV;
331     }
332     else
333     {
334         // multiplayer demo ??
335         int i;
336         // [WDJ] Do not break splitscreen setups when a demo runs
337         if( displayplayer2_ptr )  return;  // already have a player2
338 
339         // [WDJ] This code does not guarantee that the demo will get
340         // a player2, thus all code using player2 cannot assume that
341         // displayplayer2_ptr is valid, even when cv_splitscreen.
342 
343         // find any player to be player2
344         for( i=0; i<MAXPLAYERS;i++)
345         {
346             if( playeringame[i] && i!=consoleplayer )
347             {
348                 displayplayer2 = i;
349                 displayplayer2_ptr = &players[displayplayer2];
350                 break;
351             }
352         }
353     }
354 }
355 
356 //
357 // R_PointOnSide
358 // Called by Traverse BSP (sub) tree, check point against partition plane.
359 // Returns side 0 (front) or 1 (back).
R_PointOnSide(fixed_t x,fixed_t y,node_t * node)360 int R_PointOnSide ( fixed_t x, fixed_t y, node_t* node )
361 {
362     fixed_t     dx, dy;
363     fixed_t     left, right;
364 
365     if (node->dx == 0)
366     {
367         return ((x <= node->x)? (node->dy > 0) : (node->dy < 0))? 1 : 0;
368     }
369     if (node->dy == 0)
370     {
371         return ((y <= node->y)? (node->dx < 0) : (node->dx > 0))? 1 : 0;
372     }
373 
374     dx = (x - node->x);
375     dy = (y - node->y);
376 
377     // Decide quickly by looking at sign bits.
378     // [WDJ] instead of &0x80000000, use direct sign tests which optimize
379     // better and are not type size dependent.
380     if ( (node->dy ^ node->dx ^ dx ^ dy) < 0 )
381     {
382         // (left is negative) returns back side
383         return ((node->dy ^ dx) < 0 )? 1 : 0;  // return side
384     }
385 
386     left = FixedMul ( node->dy>>FRACBITS , dx );
387     right = FixedMul ( dy , node->dx>>FRACBITS );
388 
389     // (right < left) is front side (0), otherwise back side (1).
390     return (right < left) ? 0 : 1;  // return side
391 }
392 
393 
394 // Returns side 0 (front) or 1 (back).
R_PointOnSegSide(fixed_t x,fixed_t y,seg_t * line)395 int R_PointOnSegSide ( fixed_t x, fixed_t y, seg_t* line )
396 {
397     fixed_t     dx, dy;
398     fixed_t     left, right;
399 
400     fixed_t lx = line->v1->x;
401     fixed_t ly = line->v1->y;
402 
403     fixed_t ldx = line->v2->x - lx;
404     fixed_t ldy = line->v2->y - ly;
405 
406     if (ldx == 0)
407     {
408         return ((x <= lx)? (ldy > 0) : (ldy < 0))? 1 : 0;
409     }
410     if (ldy == 0)
411     {
412         return ((y <= ly)? (ldx < 0) : (ldx > 0))? 1 : 0;
413     }
414 
415     dx = (x - lx);
416     dy = (y - ly);
417 
418     // Decide quickly by looking at sign bits.
419     // [WDJ] instead of &0x80000000, use direct sign tests which optimize
420     // better and are not type size dependent.
421     if ( (ldy ^ ldx ^ dx ^ dy) < 0 )
422     {
423         // (left is negative) returns back side
424         return ((ldy ^ dx) < 0 )? 1 : 0;  // return side
425     }
426 
427     left = FixedMul ( ldy>>FRACBITS , dx );
428     right = FixedMul ( dy , ldx>>FRACBITS );
429     // (right < left) is front side (0), otherwise back side (1).
430     return (right < left) ? 0 : 1;  // return side
431 }
432 
433 
434 // [WDJ] Generate the tan slope, suitable for tantoangle[] index.
435 // This is more accuate than the vanilla version,
436 // but would cause sync loss on demos if used everywhere.
SlopeDiv_64(fixed_t num,fixed_t den)437 int SlopeDiv_64 (fixed_t num, fixed_t den)
438 {
439     int64_t ans;
440 
441     if (den < 64)
442         return SLOPERANGE;  // max
443 
444     ans = (((int64_t)num) << 11) / den;
445     return (ans <= SLOPERANGE) ? ans : SLOPERANGE;  // max
446 }
447 
448 //
449 // R_PointToAngle
450 // To get a global angle from cartesian coordinates,
451 // the coordinates are flipped until they are in the first octant of
452 // the coordinate system, then the y (<=x) is scaled and divided by x
453 // to get a tangent (slope) value which is looked up in the
454 // tantoangle[] table.
455 
456 // Point (x2,y2) to point (x1,y1) angle.
R_PointToAngle2(fixed_t x2,fixed_t y2,fixed_t x1,fixed_t y1)457 angle_t R_PointToAngle2 ( fixed_t  x2, fixed_t  y2,
458                           fixed_t  x1, fixed_t  y1)
459 {
460     // [WDJ] This is inaccurate. Angles can be in error by 0x10000000,
461     // and not monotonic (ordering errors).
462     // Has 5 bits correct when compared to atan2().
463     angle_t ra = 0;
464     x1 -= x2;  // diff
465     y1 -= y2;
466 
467     if ( (x1 == 0) && (y1 == 0) )
468         return 0;
469 
470     if (x1>= 0)
471     {   // x >=0
472         if (y1>= 0)
473         {   // y>= 0
474             ra = (x1>y1)?
475                 // octant 0, ra = 0..ANG45
476                 tantoangle[ SlopeDiv(y1,x1)]
477              :
478                 // octant 1, ra = ANG45..ANG90
479                 ANG90-1 - tantoangle[ SlopeDiv(x1,y1)] ;
480         }
481         else
482         {   // y<0
483             y1 = -y1;
484             ra = (x1>y1)?
485                 // octant 8, ra = ANG315..0 due to angle wrap
486                 -tantoangle[ SlopeDiv(y1,x1)]
487              :
488                 // octant 7, ra = AN270..ANG315
489                 ANG270 + tantoangle[ SlopeDiv(x1,y1)] ;
490         }
491     }
492     else
493     {   // x<0
494         x1 = -x1;
495         if (y1>= 0)
496         {   // y>= 0
497             ra = (x1>y1)?
498                 // octant 3, ra = ANG135..ANG180
499                 ANG180-1 - tantoangle[ SlopeDiv(y1,x1)]
500              :
501                 // octant 2, ra = ANG90..ANG135
502                 ANG90 + tantoangle[ SlopeDiv(x1,y1)] ;
503         }
504         else
505         {   // y<0
506             y1 = -y1;
507             ra = (x1>y1)?
508                 // octant 4, ra = AN180..ANG225
509                 ANG180 + tantoangle[ SlopeDiv(y1,x1)]
510              :
511                  // octant 5, ra = ANG225..ANG270
512                 ANG270-1 - tantoangle[ SlopeDiv(x1,y1)] ;
513         }
514     }
515     return ra;
516 }
517 
518 
519 // Point of view (viewx,viewy) to point (x1,y1) angle.
R_PointToAngle(fixed_t x,fixed_t y)520 angle_t R_PointToAngle ( fixed_t x, fixed_t y)
521 {
522     // Has 13 bits correct when compared to atan2(), which is much
523     // better than the 5 correct bits of the vanilla function.
524     // Uses the more accurate SlopeDiv_64.
525     angle_t vpa = 0;
526 
527     x -= viewx;  // diff from viewpoint
528     y -= viewy;
529 
530     if ( (x == 0) && (y == 0) )
531         return 0;
532 
533     // [WDJ] Fix from PrBoom (e6y).
534     // For large x or y, resort to the slower but accurate lib function.
535     if (  x > FIXED_MAX/4 || x < -FIXED_MAX/4
536           || y > FIXED_MAX/4 || y < -FIXED_MAX/4 )
537     {
538         // PrBoom used a 1 point cache, but that is too small.
539         return (int) (atan2(y,x) * ANG180 / M_PI);
540     }
541 
542     if (x>= 0)
543     {   // x >=0
544         if (y>= 0)
545         {   // y>= 0
546             vpa = (x>y)?
547                 // octant 0, vpa = 0..ANG45
548                 tantoangle[ SlopeDiv_64(y,x)]
549              :
550                 // octant 1, vpa = ANG45..ANG90
551                 ANG90-1 - tantoangle[ SlopeDiv_64(x,y)] ;
552         }
553         else
554         {   // y<0
555             y = -y;
556             vpa = (x>y)?
557                 // octant 8, vpa = ANG315..0 due to angle wrap
558                 -tantoangle[ SlopeDiv(y,x)]
559              :
560                 // octant 7, vpa = AN270..ANG315
561                 ANG270 + tantoangle[ SlopeDiv_64(x,y)] ;
562         }
563     }
564     else
565     {   // x<0
566         x = -x;
567         if (y>= 0)
568         {   // y>= 0
569             vpa = (x>y)?
570                 // octant 3, vpa = ANG135..ANG180
571                 ANG180-1 - tantoangle[ SlopeDiv_64(y,x)]
572              :
573                 // octant 2, vpa = ANG90..ANG135
574                 ANG90 + tantoangle[ SlopeDiv_64(x,y)] ;
575         }
576         else
577         {   // y<0
578             y = -y;
579             vpa = (x>y)?
580                 // octant 4, vpa = AN180..ANG225
581                 ANG180 + tantoangle[ SlopeDiv_64(y,x)]
582              :
583                  // octant 5, vpa = ANG225..ANG270
584                 ANG270-1 - tantoangle[ SlopeDiv_64(x,y)] ;
585         }
586     }
587     return vpa;
588 }
589 
590 
R_PointToDist2(fixed_t x2,fixed_t y2,fixed_t x1,fixed_t y1)591 fixed_t R_PointToDist2 ( fixed_t x2, fixed_t y2, fixed_t x1, fixed_t y1)
592 {
593     angle_t     angle;
594     fixed_t     dist;
595 
596     fixed_t dx = abs(x1 - x2);
597     fixed_t dy = abs(y1 - y2);
598 
599     if (dy>dx)
600     {
601         // swap dx and dy
602         register fixed_t dx2 = dx;
603         dx = dy;
604         dy = dx2;
605     }
606     if(dy==0)
607        return dx;
608 
609     angle = tantoangle[ FixedDiv(dy,dx)>>DBITS ] + ANG90;
610 
611     // use as cosine
612     dist = FixedDiv (dx, sine_ANG(angle));
613     return dist;
614 }
615 
616 
617 //SoM: 3/27/2000: Little extra utility. Works in the same way as
618 //R_PointToAngle2
R_PointToDist(fixed_t x,fixed_t y)619 fixed_t R_PointToDist ( fixed_t x, fixed_t y )
620 {
621   return R_PointToDist2(viewx, viewy, x, y);
622 }
623 
624 
R_Init_PointToAngle(void)625 void R_Init_PointToAngle (void)
626 {
627     // UNUSED - now getting from tables.c
628 #if 0
629     int i;
630     long        t;
631     float       f;
632 //
633 // slope (tangent) to angle lookup
634 //
635     for (i=0 ; i<=SLOPERANGE ; i++)
636     {
637         f = atan( (float)i/SLOPERANGE )/(3.141592657*2);
638         t = 0xffffffff*f;
639         tantoangle[i] = t;
640     }
641 #endif
642 }
643 
644 
645 //
646 // R_ScaleFromGlobalAngle
647 // Returns the texture mapping scale
648 //  for the current line (horizontal span)
649 //  at the given angle.
650 // rw_distance must be calculated first.
651 //
652 //added:02-02-98:note: THIS IS USED ONLY FOR WALLS!
653 // Called from R_StoreWallRange.
R_ScaleFromGlobalAngle(angle_t visangle)654 fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
655 {
656 #if 0
657     //added:02-02-98:note: I've tried this and it displays weird...
658     fixed_t             scale;
659     fixed_t             dist;
660     fixed_t             z;
661     fixed_t             sinv, cosv;
662 
663     sinv = sine_ANG(visangle - rw_normalangle);
664     dist = FixedDiv (rw_distance, sinv);
665     cosv = cosine_ANG(viewangle - visangle);
666     z = abs(FixedMul (dist, cosv));
667     scale = FixedDiv(projection, z);
668     return scale;
669 
670 #else
671     fixed_t             scale;
672     fixed_t             num;
673     fixed_t             den;
674 
675     angle_t anglea = ANG90 + (visangle - viewangle);
676     angle_t angleb = ANG90 + (visangle - rw_normalangle);
677 
678     // both sines are always positive
679     fixed_t sinea = sine_ANG(anglea);
680     fixed_t sineb = sine_ANG(angleb);
681     //added:02-02-98:now uses projectiony instead of projection for
682     //               correct aspect ratio!
683     num = FixedMul(projectiony, sineb)<<detailshift;
684     den = FixedMul(rw_distance, sinea);
685 
686     if (den > num>>16)
687     {
688         scale = FixedDiv (num, den);
689 
690         if (scale > 64*FRACUNIT)
691             scale = 64*FRACUNIT;
692         else if (scale < 256)
693             scale = 256;
694     }
695     else
696         scale = 64*FRACUNIT;
697 
698     return scale;
699 #endif
700 }
701 
702 
703 
704 #if 0
705 void R_Init_Tables (void)
706 {
707     // UNUSED: now getting from tables.c
708     int         i;
709     float       a;
710     float       fv;
711     int         t;
712 
713     // viewangle tangent table
714     for (i=0 ; i<FINE_ANG180 ; i++)
715     {
716         a = (i-FINE_ANG90+0.5)*PI*2/FINEANGLES;
717         fv = FRACUNIT*tan (a);
718         t = fv;
719         finetangent[i] = t;
720     }
721 
722     // finesine table
723     for (i=0 ; i<5*FINEANGLES/4 ; i++)
724     {
725         // OPTIMIZE: mirror...
726         a = (i+0.5)*PI*2/FINEANGLES;
727         t = FRACUNIT*sin (a);
728         finesine[i] = t;
729     }
730 }
731 #endif
732 
733 // consvar_t cv_fov = {"fov","2048", CV_CALL | CV_NOINIT, NULL, R_ExecuteSetViewSize};
734 
735 //
736 // R_Init_TextureMapping
737 //
738 // Called by R_ExecuteSetViewSize
R_Init_TextureMapping(void)739 void R_Init_TextureMapping (void)
740 {
741     int  i;
742     int  x;
743     int  t;
744     fixed_t  focallength;
745 
746     // Use tangent table to generate viewangle_to_x:
747     //  viewangle_to_x will give the next greatest x
748     //  after the view angle.
749     //
750     // Calc focallength
751     //  so FIELDOFVIEW angles covers SCREENWIDTH.
752     focallength = FixedDiv (centerxfrac,
753                             finetangent[(FINE_FIELDOFVIEW/2) + FINE_ANG90] );
754 //                          finetangent[ cv_fov.value + FINE_ANG90] );
755 
756     for (i=0 ; i<FINE_ANG180 ; i++)
757     {
758         if (finetangent[i] > FRACUNIT*2)
759             t = -1;
760         else if (finetangent[i] < -FRACUNIT*2)
761             t = rdraw_viewwidth+1;
762         else
763         {
764             t = FixedMul (finetangent[i], focallength);
765             t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS;
766 
767             if (t < -1)
768                 t = -1;
769             else if (t>rdraw_viewwidth+1)
770                 t = rdraw_viewwidth+1;
771         }
772         viewangle_to_x[i] = t;
773     }
774 
775     // Scan viewangle_to_x[] to generate x_to_viewangle[]:
776     //  x_to_viewangle will give the smallest view angle
777     //  that maps to x.
778     for (x=0;x<=rdraw_viewwidth;x++)
779     {
780         i = 0;
781         while (viewangle_to_x[i]>x)
782             i++;
783         x_to_viewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
784     }
785 
786     // Take out the fencepost cases from viewangle_to_x.
787     for (i=0 ; i<FINE_ANG180 ; i++)
788     {
789         t = FixedMul (finetangent[i], focallength);
790         t = centerx - t;
791 
792         if (viewangle_to_x[i] == -1)
793             viewangle_to_x[i] = 0;
794         else if (viewangle_to_x[i] == rdraw_viewwidth+1)
795             viewangle_to_x[i]  = rdraw_viewwidth;
796     }
797 
798     clipangle = x_to_viewangle[0];
799     clipangle_x_2 = clipangle + clipangle;
800 }
801 
802 
803 
804 //
805 // R_Init_LightTables
806 // Only inits the zlight table,
807 //  because the scalelight table changes with view size.
808 //
809 #define DISTMAP         2
810 
811 static
R_Init_LightTables(void)812 void R_Init_LightTables (void)
813 {
814     int         i;
815     int         j;
816     int         level;
817     int         startmap;
818     int         scale;
819 
820     // Calculate the light levels to use
821     //  for each level / distance combination.
822     for (i=0 ; i< LIGHTLEVELS ; i++)
823     {
824         startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
825         for (j=0 ; j<MAXLIGHTZ ; j++)
826         {
827             //added:02-02-98:use BASEVIDWIDTH, vid.width is not set already,
828             // and it seems it needs to be calculated only once.
829             scale = FixedDiv ((BASEVIDWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
830             scale >>= LIGHTSCALESHIFT;
831             level = startmap - scale/DISTMAP;
832 
833             if (level < 0)
834                 level = 0;
835 
836             if (level >= NUMCOLORMAPS)
837                 level = NUMCOLORMAPS-1;
838 
839             zlight[i][j] = & reg_colormaps[ LIGHTTABLE( level ) ];
840         }
841     }
842 }
843 
844 
845 // R_SetViewSize
846 // Do not really change anything here,
847 //  because it might be in the middle of a refresh.
848 // The change will take effect next refresh.
849 //
850 boolean         setsizeneeded = false;
851 
852 // Called by R_Init, SCR_Recalc
853 // Called by cv_viewsize, cv_detaillevel, cv_scalestatusbar, cv_grtranslucenthud
R_SetViewSize(void)854 void R_SetViewSize (void)
855 {
856     setsizeneeded = true;
857 }
858 
859 
860 //
861 // R_ExecuteSetViewSize
862 //
863 
864 
865 // now uses screen variables cv_viewsize, cv_detaillevel
866 //
867 // Called by D_Display when setsizeneeded
868 // Called by G_DoLoadGame when setsizeneeded
869 // Called by SplitScreen_OnChange
870 // Called by cv_fov (disabled)
R_ExecuteSetViewSize(void)871 void R_ExecuteSetViewSize (void)
872 {
873     fixed_t     cosadj;
874     fixed_t     dy;
875     int         i;
876     int         j;
877     int         level;
878     int         startmap;
879 
880     int         setdetail;
881 
882     int         aspectx;  //added:02-02-98:for aspect ratio calc. below...
883 
884     setsizeneeded = false;
885     // no reduced view in splitscreen mode
886     if( cv_splitscreen.EV && (cv_viewsize.value < 11) )
887         CV_SetValue (&cv_viewsize, 11);
888 
889     // added by Hurdler
890 #ifdef HWRENDER
891     if((rendermode != render_soft) && (cv_viewsize.value < 6))
892         CV_SetValue (&cv_viewsize, 6);
893 #endif
894 
895     setdetail = cv_detaillevel.value;
896 
897     // status bar overlay at viewsize 11
898     st_overlay_on = (cv_viewsize.value==11);
899     //DarkWolf95: Support for Chex Quest
900     if (gamemode == chexquest1)
901        st_overlay_on = 0;  //don't allow overlay status bar in Chex Quest
902 
903     // clamp detail level (actually ignore it, keep it for later who knows)
904     if (setdetail)
905     {
906         setdetail = 0;
907         CONS_Printf ("lower detail mode n.a.\n");
908         CV_SetValue (&cv_detaillevel,setdetail);
909     }
910 
911     stbar_height = (EN_heretic)? H_STBAR_HEIGHT : ST_HEIGHT;
912 
913     if( cv_scalestatusbar.EV || (cv_viewsize.value>=11) )
914         stbar_height *= (rendermode == render_soft)? vid.dupy : vid.fdupy;
915 
916     //added 01-01-98: full screen view, without statusbar
917     if (cv_viewsize.value > 10)
918     {
919         rdraw_scaledviewwidth = vid.width;
920         rdraw_viewheight = vid.height;
921     }
922     else
923     {
924         //added 01-01-98: always a multiple of eight
925         rdraw_scaledviewwidth = (cv_viewsize.value*vid.width/10)&~7;
926         //added:05-02-98: make rdraw_viewheight multiple of 2 because sometimes
927         //                a line is not refreshed by R_DrawViewBorder()
928         rdraw_viewheight = (cv_viewsize.value * (vid.height - stbar_height) / 10)&~1;
929     }
930 
931     // added 16-6-98:splitscreen
932     if( cv_splitscreen.EV )
933         rdraw_viewheight >>= 1;
934 
935     detailshift = setdetail;
936     rdraw_viewwidth = rdraw_scaledviewwidth>>detailshift;
937 
938     centery = rdraw_viewheight/2;
939     centerx = rdraw_viewwidth/2;
940     centerxfrac = centerx<<FRACBITS;
941     centeryfrac = centery<<FRACBITS;
942 
943     //added:01-02-98:aspect ratio is now correct, added an 'projectiony'
944     //      since the scale is not always the same between horiz. & vert.
945     projection  = centerxfrac;
946     projectiony = (((vid.height*centerx*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width)<<FRACBITS;
947 
948     //
949     // no more low detail mode, it used to setup the right drawer routines
950     // for either detail mode here
951     //
952     // if (!detailshift) ... else ...
953 
954     R_Init_ViewBuffer (rdraw_scaledviewwidth, rdraw_viewheight);
955 
956     R_Init_TextureMapping ();
957 
958 #ifdef HWRENDER // not win32 only 19990829 by Kin
959     if( rendermode != render_soft )
960         HWR_Init_TextureMapping ();
961 #endif
962 
963     // psprite scales
964     centerypsp = rdraw_viewheight/2;  //added:06-02-98:psprite pos for freelook
965     // Doom weapons are too high for high resolutions.
966     if( EN_doom_etc )
967        centerypsp += (rdraw_viewheight/400);
968 
969     pspritescale  = (rdraw_viewwidth<<FRACBITS)/BASEVIDWIDTH;
970     pspriteiscale = (BASEVIDWIDTH<<FRACBITS)/rdraw_viewwidth;   // x axis scale
971     //added:02-02-98:now aspect ratio correct for psprites
972     pspriteyscale = (((vid.height*rdraw_viewwidth)/vid.width)<<FRACBITS)/BASEVIDHEIGHT;
973 
974     // thing clipping
975     for (i=0 ; i<rdraw_viewwidth ; i++)
976         clip_screen_bot_max[i] = rdraw_viewheight - 1;
977 
978     // setup sky scaling for old/new skies (uses pspriteyscale)
979     R_Set_Sky_Scale ();
980 
981     // planes
982     //added:02-02-98:now correct aspect ratio!
983     aspectx = (((vid.height*centerx*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width);
984 
985     if( rendermode == render_soft )
986     {
987         // this is only used for planes rendering in software mode
988         j = rdraw_viewheight*4;
989         for (i=0 ; i<j ; i++)
990         {
991             //added:10-02-98:(i-centery) became (i-centery*2) and centery*2=rdraw_viewheight
992             dy = ((i-rdraw_viewheight*2)<<FRACBITS)+FRACUNIT/2;
993             dy = abs(dy);
994             yslopetab[i] = FixedDiv (aspectx*FRACUNIT, dy);
995         }
996     }
997 
998     for (i=0 ; i<rdraw_viewwidth ; i++)
999     {
1000         cosadj = abs( cosine_ANG( x_to_viewangle[i] ));
1001         distscale[i] = FixedDiv (FRACUNIT, cosadj);
1002     }
1003 
1004     // Calculate the light levels to use
1005     //  for each level / scale combination.
1006     for (i=0 ; i< LIGHTLEVELS ; i++)
1007     {
1008         startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
1009         for (j=0 ; j<MAXLIGHTSCALE ; j++)
1010         {
1011             level = startmap - j*vid.width/(rdraw_viewwidth<<detailshift)/DISTMAP;
1012 
1013             if (level < 0)
1014                 level = 0;
1015 
1016             if (level >= NUMCOLORMAPS)
1017                 level = NUMCOLORMAPS-1;
1018 
1019             scalelight[i][j] = & reg_colormaps[ LIGHTTABLE( level ) ];
1020         }
1021     }
1022 
1023     //faB: continue to do the software setviewsize as long as we use
1024     //     the reference software view
1025 #ifdef HWRENDER // not win32 only 19990829 by Kin
1026     if( rendermode != render_soft )
1027         HWR_SetViewSize (cv_viewsize.value);
1028 #endif
1029 
1030     stbar_recalc = true;
1031     am_recalc = true;
1032 }
1033 
1034 
1035 //
1036 // R_Init
1037 //
1038 
1039 
R_Init(void)1040 void R_Init (void)
1041 {
1042 #if defined DEBUG_WINDOWED || defined PARANOIA
1043     // [WDJ] Some checks that could not be done at compile-time (enum).
1044     if( MFT_TO_SKINMAP( 1<<MFT_TRANSSHIFT ) != (&skintranstables[ 0 ]) )
1045         I_Error( "MFT_TO_SKINMAP  broken, check MFT_TRANSSHIFT\n" );
1046     if( (int)MFT_TRANSSHIFT >= (int)MFO_TRANSSHIFT )
1047         I_Error( "MFO_TRANSSHIFT - MFT_TRANSSHIFT  broken, check MFT_TRANSHIFT\n" );
1048 #endif
1049 
1050     if(dedicated)
1051         return;
1052 
1053     //added:24-01-98: screensize independent
1054     if(devparm)
1055         GenPrintf(EMSG_dev, "\nR_Load_Data");
1056     R_Load_Data ();
1057     R_Load_Corona();
1058 
1059     if(devparm)
1060         GenPrintf(EMSG_dev, "\nR_Init_PointToAngle");
1061     R_Init_PointToAngle ();
1062 
1063 #if 0
1064     if(devparm)
1065         GenPrintf(EMSG_dev, "\nR_Init_Tables");
1066     R_Init_Tables ();
1067 #endif
1068 
1069     R_Init_ViewBorder ();
1070 
1071     R_SetViewSize ();   // setsizeneeded is set true
1072 
1073     if(devparm)
1074         GenPrintf(EMSG_dev, "\nR_Init_Planes");
1075     R_Init_Planes ();
1076 
1077     //added:02-02-98: this is now done by SCR_Recalc() at the first mode set
1078     if(devparm)
1079         GenPrintf(EMSG_dev, "\nR_Init_LightTables");
1080     R_Init_LightTables ();
1081 
1082     if(devparm)
1083         GenPrintf(EMSG_dev, "\nR_Init_SkyMap");
1084     R_Init_SkyMap ();
1085 
1086     if(devparm)
1087         GenPrintf(EMSG_dev, "\nR_Init_TranslationsTables");
1088     R_Init_TranslationTables ();
1089 
1090     R_Init_DrawNodes();
1091 
1092     framecount = 0;
1093 }
1094 
1095 
1096 //
1097 // R_PointInSubsector
1098 //
R_PointInSubsector(fixed_t x,fixed_t y)1099 subsector_t* R_PointInSubsector ( fixed_t x, fixed_t y )
1100 {
1101     node_t*     node;
1102     int         side;
1103     int         nodenum;
1104 
1105     // single subsector is a special case
1106     if (!numnodes)
1107         return subsectors;
1108 
1109     nodenum = numnodes-1;
1110 
1111     while (! (nodenum & NF_SUBSECTOR) )
1112     {
1113         node = &nodes[nodenum];
1114         side = R_PointOnSide (x, y, node);
1115         nodenum = node->children[side];
1116     }
1117 
1118     return &subsectors[nodenum & ~NF_SUBSECTOR];
1119 }
1120 
1121 //
1122 // R_IsPointInSubsector, same of above but return 0 if not in subsector
1123 //
R_IsPointInSubsector(fixed_t x,fixed_t y)1124 subsector_t* R_IsPointInSubsector ( fixed_t x, fixed_t y )
1125 {
1126     node_t*     node;
1127     int         side;
1128     int         nodenum,i;
1129     subsector_t *ret;
1130 
1131     // single subsector is a special case
1132     if (!numnodes)
1133         return subsectors;
1134 
1135     nodenum = numnodes-1;
1136 
1137     while (! (nodenum & NF_SUBSECTOR) )
1138     {
1139         node = &nodes[nodenum];
1140         side = R_PointOnSide (x, y, node);
1141         nodenum = node->children[side];
1142     }
1143 
1144     ret=&subsectors[nodenum & ~NF_SUBSECTOR];
1145     for(i=0;i<ret->numlines;i++)
1146     {
1147         if(R_PointOnSegSide(x,y,&segs[ret->firstline+i]))
1148             return 0;
1149     }
1150 
1151     return ret;
1152 }
1153 
1154 
1155 //
1156 // R_SetupFrame
1157 //
1158 
1159 // WARNING : a should be unsigned but to add with 2048, it isn't !
1160 #define AIMINGTODY(a) ((tangent_ANG(a)*160)>>FRACBITS)
1161 
1162 // Setup viewx, viewy, viewz, and other view global variables.
1163 // Called by R_RenderPlayerView.
1164 // Called by HWR_RenderPlayerView.
1165 //  pind : player index, [0]=main player, [1]=splitscreen player
R_SetupFrame(byte pind,player_t * player)1166 void R_SetupFrame( byte pind, player_t* player )
1167 {
1168     int  i;
1169     int  fixedcolormap_num;
1170     int  dy=0; //added:10-02-98:
1171 
1172     viewplayer = player;
1173     extralight = player->extralight;
1174     extralight_fog = extralight >> 1;  // 1/2 for FF_FOG
1175     extralight_cm = extralight - (extralight>>2);  // 3/4 for colormap->fog
1176 
1177     // Chase camera setting must be maintained even with script camera running
1178     if( cv_chasecam.EV )
1179     {
1180         // with splitplayer, only the first player will get the chase camera
1181         if( !camera.chase )
1182              P_ResetCamera(player);  // set chase = player
1183     }
1184     else
1185         camera.chase = NULL;
1186 
1187 #ifdef FRAGGLESCRIPT
1188     // Script camera overrides chase camera
1189     if (script_camera_on)
1190     {
1191         // fragglescript camera as viewer
1192         viewmobj = script_camera.mo;
1193 #ifdef PARANOIA
1194         if (!viewmobj)
1195             I_Error("no mobj for the camera");
1196 #endif
1197         viewz = viewmobj->z;
1198         aimingangle=script_camera.aiming;
1199         viewangle = viewmobj->angle;
1200         ST_Palette0();  // Doom and Heretic
1201         fixedcolormap_num = camera.fixedcolormap;
1202     }
1203     else
1204 #endif
1205     if (camera.chase == player)  // this player has chase camera
1206     {
1207         // chase camera as viewer
1208         // use outside cam view
1209         if (!camera.mo)  // because LoadLevel removes camera
1210             P_ResetCamera(player);  // reset the camera
1211         viewmobj = camera.mo;
1212         viewz = viewmobj->z + (viewmobj->height>>1);
1213         aimingangle=camera.aiming;
1214         viewangle = viewmobj->angle;
1215 #if 1
1216         // Player cam does not see player status palette.
1217         ST_Palette0();   // Doom and Heretic
1218 #else
1219         // Player cam sees player status palette.
1220         // Can now handle splitplayer flashes.
1221         if( EN_heretic )
1222             H_PaletteFlash( player );
1223         else
1224             ST_doPaletteStuff( player );
1225 #endif
1226         fixedcolormap_num = camera.fixedcolormap;
1227     }
1228     else
1229     {
1230         // player as viewer
1231         // use the player's eyes view
1232         viewz = player->viewz;
1233 #ifdef CLIENTPREDICTION2
1234         if( demoplayback || !player->spirit)
1235         {
1236             viewmobj = player->mo;
1237             CONS_Printf("\2No spirit\n");
1238         }
1239         else
1240             viewmobj = player->spirit;
1241 #else
1242         viewmobj = player->mo;
1243 #endif
1244 
1245         // Can now handle splitplayer flashes.
1246         if( EN_heretic )
1247             H_PaletteFlash( player );
1248         else
1249             ST_doPaletteStuff( player );
1250         fixedcolormap_num = player->fixedcolormap;
1251 
1252         aimingangle=player->aiming;
1253         viewangle = viewmobj->angle+viewangleoffset;
1254 
1255         if(!demoplayback && player->playerstate!=PST_DEAD && !cl_drone)
1256         {
1257             viewangle = localangle[pind]; // WARNING : camera use this
1258             aimingangle=localaiming[pind];
1259         }
1260 
1261     }
1262 
1263 #ifdef PARANOIA
1264     if (!viewmobj)
1265          I_Error("R_Setupframe : viewmobj null (player %d)",player-players);
1266 #endif
1267     viewx = viewmobj->x;
1268     viewy = viewmobj->y;
1269 
1270     viewsin = sine_ANG(viewangle);
1271     viewcos = cosine_ANG(viewangle);
1272 
1273     // Before R_RenderBSPNode or R_DrawMasked or R_ProjectSprite
1274     // Can be camera.mo, viewplayer->mo, or fragglescript script_camera.mo
1275     viewer_sector = viewmobj->subsector->sector;
1276     viewer_modelsec = viewer_sector->modelsec;
1277     // [WDJ] modelsec used for more than water, do proper test
1278     // Use of modelsec is protected by model field, do not test for -1.
1279     viewer_has_model  = viewer_sector->model > SM_fluid;
1280     viewer_underwater = viewer_has_model && (viewz <= sectors[viewer_modelsec].floorheight);
1281     viewer_at_water = viewer_has_model && (viewz <= sectors[viewer_modelsec].floorheight + 2)
1282       && (viewz >= sectors[viewer_modelsec].floorheight - 2);
1283     viewer_overceiling = viewer_has_model && (viewz >= sectors[viewer_modelsec].ceilingheight);
1284     viewer_at_ceiling = viewer_has_model && (viewz <= sectors[viewer_modelsec].ceilingheight + 2)
1285       && (viewz >= sectors[viewer_modelsec].ceilingheight - 2);
1286 
1287     sscount = 0;
1288 
1289     fixedcolormap = NULL;  // default
1290     view_colormap = NULL;  // default
1291     view_extracolormap = NULL;
1292     view_fogmodel = NULL;
1293     view_fogfloor = NULL;
1294 
1295     // [WDJ] fog flag on colormap colors everything (but not very good fog)
1296     if( viewer_sector->extra_colormap && viewer_sector->extra_colormap->fog )
1297     {
1298         view_extracolormap = viewer_sector->extra_colormap;
1299     }
1300 
1301     // [WDJ] Because of interactions with extra colormaps, precedence must
1302     // be determined at the usage.  The Boom 282 colormap overrides all
1303     // normal colormap and extra colormap, but not fixedcolormap.
1304     // But it requires the light level calculations of an extra colormap.
1305     if( EN_boom_colormap )
1306     {
1307         // [WDJ] 4/11/2012 restore compatible Boom colormap handling
1308         if( viewer_sector->model == SM_Boom_deep_water )
1309         {
1310             sector_t * modsecp = & sectors[ viewer_modelsec ];
1311             // -1 or a valid colormap num
1312             int bcm_num = (viewz < modsecp->floorheight) ?
1313                modsecp->bottommap
1314              : (viewz > modsecp->ceilingheight)?
1315                modsecp->topmap
1316              : modsecp->midmap;
1317             // only enable view_colormap when overriding globally
1318             if(bcm_num >= 0 && bcm_num < num_extra_colormaps)
1319             {
1320                view_extracolormap = & extra_colormaps[bcm_num];
1321             }
1322         }
1323     }
1324 
1325     // Find a FF_FOG or fog extracolormap that viewer is within.
1326     // FF_FOG is a ffloor, not a model sector
1327     if( viewer_sector->ffloors )
1328     {
1329         ffloor_t * ffp;
1330         for( ffp=viewer_sector->ffloors; ffp; ffp=ffp->next )
1331         {
1332             if( ( ffp->flags & FF_FOG )
1333                 && ( ffp->model_secnum >= 0 )
1334                 && ( viewz < *(ffp->topheight) ) && ( viewz > *(ffp->bottomheight) )
1335                 )
1336             {
1337                 view_fogfloor = ffp;
1338                 view_fogmodel = & sectors[ ffp->model_secnum ];
1339                 // Fog already colors surrounding view by looking through
1340                 // fog sheets, planes, and face sheet.
1341                 // This is an extra effect enabled by colormap fog flag.
1342                 if( view_fogmodel->extra_colormap && view_fogmodel->extra_colormap->fog )
1343                 {
1344                     // fog colors all walls, floors, and things
1345                     view_extracolormap = view_fogmodel->extra_colormap;
1346                 }
1347                 else
1348                 {
1349                     // viewer fake floor without colormap overrides viewer sector colormap
1350                     view_extracolormap = NULL;
1351                 }
1352                 break;
1353             }
1354         }
1355     }
1356     if( view_fogfloor )
1357     {
1358         // partial extralight taken by fog
1359         extralight = (extralight * (256 - view_fogfloor->alpha)) >> 8;
1360     }
1361     if( view_extracolormap )
1362         view_colormap = view_extracolormap->colormap;
1363 
1364     if (fixedcolormap_num)
1365     {
1366         // the fixedcolormap overrides sector colormaps
1367         fixedcolormap =
1368             & reg_colormaps[ LIGHTTABLE( fixedcolormap_num ) ];
1369 
1370         walllights = scalelightfixed;
1371 
1372         // refresh scalelights to fixedcolormap
1373         for (i=0 ; i<MAXLIGHTSCALE ; i++)
1374             scalelightfixed[i] = fixedcolormap;
1375     }
1376 
1377     //added:06-02-98:recalc necessary stuff for mouseaiming
1378     //               slopes are already calculated for the full
1379     //               possible view (which is 4*rdraw_viewheight).
1380 
1381     if ( rendermode == render_soft )
1382     {
1383         // clip it in the case we are looking a hardware 90� full aiming
1384         // (lmps, nework and use F12...)
1385         aimingangle = G_ClipAimingPitch(aimingangle);	// limit aimingangle
1386 
1387         // [WDJ] cleaned up
1388         dy = cv_splitscreen.EV ? rdraw_viewheight*2 : rdraw_viewheight ;
1389         dy = ( dy * AIMINGTODY(aimingangle) )/ BASEVIDHEIGHT ;
1390 
1391         yslope = &yslopetab[(3*rdraw_viewheight/2) - dy];
1392     }
1393     centery = (rdraw_viewheight/2) + dy;
1394     centeryfrac = centery<<FRACBITS;
1395 
1396     // rendergametic increases by 1 to 5 each pass
1397     fog_bltic = (rendergametic>>1) & 0x001F;  // 0..31, one cycle per fog_tic
1398     fog_tic = (rendergametic>>6) & 0x0FFF;  // tic per 1.78 seconds
1399     if( (fog_nexttic - rendergametic) > 0x00FF )
1400     {  // semi-random wave, no overflow, no underflow, slightly erratic
1401        fog_nexttic = rendergametic + 5;
1402        fog_wave1 += ((int)validcount&0x007F) - 0x003F;
1403        if(fog_wave1 > 0x4000) fog_wave1 = 0x2C;  // underflow
1404        else if(fog_wave1 > 0x3FE) fog_wave1 = 0x3D2;
1405        fog_wave2 += (((int)(fog_wave1+rendergametic)&0x03FF) - 0x01FF) >> 4;
1406        if(fog_wave2 > 0x4000) fog_wave2 = 0x2C;  // underflow
1407        else if(fog_wave2 > 0x3FE) fog_wave2 = 0x3D2;
1408     }
1409 
1410     framecount++;
1411     validcount++;
1412 }
1413 
1414 #ifdef HORIZONTALDRAW
1415 
1416 #define CACHEW 32      // bytes in cache line
1417 #define CACHELINES 32  // cache lines to use
1418 
R_RotateBuffere(void)1419 void R_RotateBuffere (void)
1420 {
1421     byte    bh,bw;
1422 //    int     modulo;
1423     byte*   src,*srca,*srcr;
1424     byte*   dest,*destr;  // within screen buffer
1425     int     i,dl;
1426 
1427 
1428 #define modulo 200  //= rdraw_viewheight;
1429 
1430     // [WDJ] yhlookup screen buffer is width x height, not padded
1431     // This is not directly compatible with any screen buffer
1432     srcr  = yhlookup[0];
1433     destr = ylookup[0] + columnofs[0];  // screen[0] buffer
1434 
1435     bh = rdraw_viewwidth / CACHELINES;
1436     while (bh--)
1437     {
1438         srca = srcr;
1439         dest = destr;
1440 
1441         bw = rdraw_viewheight;
1442         while (bw--)
1443         {
1444              src  = srca++;
1445              for (i=0;i<CACHELINES/4;i++)  // fill 32 cache lines
1446              {
1447                  *dest++ = *src;
1448                  *dest++ = *(src-modulo);
1449                  *dest++ = *(src-2*modulo);
1450                  *dest++ = *(src-3*modulo);
1451                  src -= 4*modulo;
1452              }
1453              dest = (dest - CACHELINES) + vid.ybytes;
1454         }
1455         srcr  -= (CACHELINES*rdraw_viewheight);
1456         destr += CACHELINES;
1457     }
1458 }
1459 #endif
1460 
1461 
1462 
1463 // ================
1464 // R_RenderView
1465 // ================
1466 
1467 //                     FAB NOTE FOR WIN32 PORT !! I'm not finished already,
1468 // but I suspect network may have problems with the video buffer being locked
1469 // for all duration of rendering, and being released only once at the end..
1470 // I mean, there is a win16lock() or something that lasts all the rendering,
1471 // so maybe we should release screen lock before each netupdate below..?
1472 // [WDJ] Our video buffer is not locked, only driver can lock direct
1473 // buffer, and only for duration of transfer.
1474 
1475 
1476 //extern consvar_t cv_grsoftwareview; //r_glide.c
1477 extern void R_DrawFloorSplats (void);   //r_plane.c
1478 
1479 // Draw player view, render_soft.
1480 // In splitscreen the ylookup tables and viewwindowy are adjusted per player.
1481 // Global variables include:  ylookup[], viewwindowy, rdraw_viewheight
1482 //  pind : player index, [0]=main player, [1]=splitscreen player
R_RenderPlayerView(byte pind,player_t * player)1483 void R_RenderPlayerView( byte pind, player_t* player )
1484 {
1485     // rendermode == render_soft
1486     R_SetupFrame(pind, player);
1487 
1488     // Clear buffers.
1489     R_Clear_ClipSegs ();
1490     R_Clear_DrawSegs ();
1491     R_Clear_Planes (player);     //needs player for waterheight in occupied sector
1492     //R_Clear_Portals ();
1493     R_Clear_Sprites ();
1494 
1495 #ifdef FLOORSPLATS
1496     R_Clear_VisibleFloorSplats ();
1497 #endif
1498 
1499     // check for new console commands.
1500     NetUpdate ();
1501 
1502     // The head node is the last node output.
1503 
1504 //profile stuff ---------------------------------------------------------
1505 #ifdef TIMING
1506     mytotal=0;
1507     ProfZeroTimer();
1508 #endif
1509     R_RenderBSPNode (numnodes-1);
1510 #ifdef TIMING
1511     RDMSR(0x10,&mycount);
1512     mytotal += mycount;   //64bit add
1513 
1514     CONS_Printf("RenderBSPNode: 0x%d %d\n", *((int*)&mytotal+1),
1515                                              (int)mytotal );
1516 #endif
1517 //profile stuff ---------------------------------------------------------
1518 
1519 // horizontal column draw optimisation test.. deceiving.
1520 #ifdef HORIZONTALDRAW
1521 //    R_RotateBuffere ();
1522     dc_source   = yhlookup[0];
1523     dc_colormap = ylookup[0] + columnofs[0];
1524     R_RotateBufferasm ();
1525 #endif
1526 
1527     // Check for new console commands.
1528     NetUpdate ();
1529 
1530     //R_Draw_Portals ();
1531     R_Draw_Planes ();
1532 
1533     // Check for new console commands.
1534     NetUpdate ();
1535 
1536 #ifdef FLOORSPLATS
1537     //faB(21jan): testing
1538     R_DrawVisibleFloorSplats ();
1539 #endif
1540 
1541     // draw mid texture and sprite
1542     // SoM: And now 3D floors/sides!
1543     R_DrawMasked ();
1544 
1545     if( view_fogfloor
1546         && ( view_fogfloor->flags & FF_FOGFACE  ) )
1547     {
1548         lightlev_t fog_extralight = (player->extralight * view_fogfloor->alpha) >> 7;
1549         R_RenderFog( view_fogfloor, viewer_sector, fog_extralight, 0 );  // random scale
1550         if( extralight )
1551            R_RenderFog( view_fogfloor, viewer_sector, fog_extralight, 32*FRACUNIT );
1552     }
1553 
1554     // If enabled, draw the weapon psprites on top of everything
1555     // but not on side views, nor on camera views.
1556     if( cv_psprites.EV && !viewangleoffset && !script_camera_on
1557         && camera.chase != player )
1558         R_DrawPlayerSprites ();
1559 
1560     // Check for new console commands.
1561     NetUpdate ();
1562     player->mo->flags &= ~MF_NOSECTOR; // don't show self (uninit) clientprediction code
1563 }
1564 
1565 
1566 // =========================================================================
1567 //                    ENGINE COMMANDS & VARS
1568 // =========================================================================
1569 
R_Register_EngineStuff(void)1570 void R_Register_EngineStuff (void)
1571 {
1572     // Any cv_ with CV_SAVE needs to be registered, even if it is not used.
1573     // Otherwise there will be error messages when config is loaded.
1574     CV_RegisterVar (&cv_gravity);
1575     CV_RegisterVar (&cv_fog_effect);
1576     CV_RegisterVar (&cv_boom_colormap);
1577     CV_RegisterVar (&cv_invul_skymap);
1578     CV_RegisterVar (&cv_water_effect);
1579     CV_RegisterVar (&cv_sky_gen);
1580 
1581     CV_RegisterVar(&cv_screenshot_dir);
1582     CV_RegisterVar(&cv_screenshot_type);
1583 
1584     CV_RegisterVar (&cv_viewsize);
1585     CV_RegisterVar (&cv_psprites);
1586     CV_RegisterVar (&cv_splitscreen);
1587 //    CV_RegisterVar (&cv_fov);
1588     CV_RegisterVar (&cv_spritelim);
1589 
1590     // Default viewheight is changeable,
1591     // initialized to standard rdraw_viewheight
1592     CV_RegisterVar (&cv_viewheight);
1593     CV_RegisterVar (&cv_scalestatusbar);
1594     CV_RegisterVar (&cv_grtranslucenthud);
1595 
1596 //added by Hurdler
1597 #ifdef HWRENDER
1598     HWR_Register_Gr1Commands ();
1599 #endif
1600 
1601    // Enough for ded. server
1602     if( dedicated )
1603         return;
1604 
1605     CV_RegisterVar (&cv_chasecam);
1606     CV_RegisterVar (&cv_cam_dist );
1607     CV_RegisterVar (&cv_cam_height);
1608     CV_RegisterVar (&cv_cam_speed );
1609 
1610     // unfinished, not for release
1611 #ifdef PERSPCORRECT
1612     CV_RegisterVar (&cv_perspcorr);
1613 #endif
1614 
1615     // unfinished, not for release
1616 #ifdef TILTVIEW
1617     CV_RegisterVar (&cv_tiltview);
1618 #endif
1619 
1620 }
1621