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