1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 * Rendering main loop and setup functions,
29 * utility functions (BSP, geometry, trigonometry).
32 *-----------------------------------------------------------------------------*/
45 //#include "lprintf.h"
47 #include "rockmacros.h"
49 // Fineangles in the SCREENWIDTH wide window.
50 #define FIELDOFVIEW 2048
52 // killough: viewangleoffset is a legacy from the pre-v1.2 days, when Doom
53 // had Left/Mid/Right viewing. +/-ANG90 offsets were placed here on each
54 // node, by d_net.c, to set up a L/M/R session.
58 int validcount
= 1; // increment every time a check is made
59 lighttable_t
*fixedcolormap
;
60 int centerx IBSS_ATTR
;
61 int centery IBSS_ATTR
;
62 fixed_t centerxfrac
, centeryfrac
;
64 // proff 11/06/98: Added for high-res
66 fixed_t viewx
, viewy
, viewz
;
68 fixed_t viewcos
, viewsin
;
70 extern lighttable_t
**walllights
;
73 // precalculated math tables
78 // The viewangletox[viewangle + FINEANGLES/4] lookup
79 // maps the visible view angles to screen X coordinates,
80 // flattening the arc to a flat projection plane.
81 // There will be many angles mapped to the same X.
85 // The xtoviewangleangle[] table maps a screen pixel
86 // to the lowest viewangle that maps back to x ranges
87 // from clipangle to -clipangle.
89 angle_t xtoviewangle
[MAX_SCREENWIDTH
+1]; // killough 2/8/98
91 // killough 3/20/98: Support dynamic colormaps, e.g. deep water
92 // killough 4/4/98: support dynamic number of them as well
95 lighttable_t
*(*c_scalelight
)[LIGHTLEVELS
][MAXLIGHTSCALE
];
96 lighttable_t
*(*c_zlight
)[LIGHTLEVELS
][MAXLIGHTZ
];
97 lighttable_t
*(*scalelight
)[MAXLIGHTSCALE
];
98 lighttable_t
*(*zlight
)[MAXLIGHTZ
];
99 lighttable_t
*fullcolormap
;
100 lighttable_t
**colormaps
;
102 // killough 3/20/98, 4/4/98: end dynamic colormaps
104 int extralight
; // bumped light from gun blasts
106 void (*colfunc
)(void);
110 // Traverse BSP (sub) tree,
111 // check point against partition plane.
112 // Returns side 0 (front) or 1 (back).
114 // killough 5/2/98: reformatted
117 int R_PointOnSide(fixed_t x
, fixed_t y
, const node_t
*node
)
120 return x
<= node
->x
? node
->dy
> 0 : node
->dy
< 0;
123 return y
<= node
->y
? node
->dx
< 0 : node
->dx
> 0;
128 // Try to quickly decide by looking at sign bits.
129 if ((node
->dy
^ node
->dx
^ x
^ y
) < 0)
130 return (node
->dy
^ x
) < 0; // (left is negative)
131 return FixedMul(y
, node
->dx
>>FRACBITS
) >= FixedMul(node
->dy
>>FRACBITS
, x
);
134 // killough 5/2/98: reformatted
136 int R_PointOnSegSide(fixed_t x
, fixed_t y
, const seg_t
*line
)
138 fixed_t lx
= line
->v1
->x
;
139 fixed_t ly
= line
->v1
->y
;
140 fixed_t ldx
= line
->v2
->x
- lx
;
141 fixed_t ldy
= line
->v2
->y
- ly
;
144 return x
<= lx
? ldy
> 0 : ldy
< 0;
147 return y
<= ly
? ldx
< 0 : ldx
> 0;
152 // Try to quickly decide by looking at sign bits.
153 if ((ldy
^ ldx
^ x
^ y
) < 0)
154 return (ldy
^ x
) < 0; // (left is negative)
155 return FixedMul(y
, ldx
>>FRACBITS
) >= FixedMul(ldy
>>FRACBITS
, x
);
160 // To get a global angle from cartesian coordinates,
161 // the coordinates are flipped until they are in
162 // the first octant of the coordinate system, then
163 // the y (<=x) is scaled and divided by x to get a
164 // tangent (slope) value which is looked up in the
165 // tantoangle[] table. The +1 size of tantoangle[]
166 // is to handle the case when x==y without additional
169 // killough 5/2/98: reformatted, cleaned up
171 angle_t
R_PointToAngle(fixed_t x
, fixed_t y
)
173 return (y
-= viewy
, (x
-= viewx
) || y
) ?
176 (x
> y
) ? tantoangle
[SlopeDiv(y
,x
)] : // octant 0
177 ANG90
-1-tantoangle
[SlopeDiv(x
,y
)] : // octant 1
178 x
> (y
= -y
) ? 0-tantoangle
[SlopeDiv(y
,x
)] : // octant 8
179 ANG270
+tantoangle
[SlopeDiv(x
,y
)] : // octant 7
180 y
>= 0 ? (x
= -x
) > y
? ANG180
-1-tantoangle
[SlopeDiv(y
,x
)] : // octant 3
181 ANG90
+ tantoangle
[SlopeDiv(x
,y
)] : // octant 2
182 (x
= -x
) > (y
= -y
) ? ANG180
+tantoangle
[ SlopeDiv(y
,x
)] : // octant 4
183 ANG270
-1-tantoangle
[SlopeDiv(x
,y
)] : // octant 5
187 angle_t
R_PointToAngle2(fixed_t viewx
, fixed_t viewy
, fixed_t x
, fixed_t y
)
189 return (y
-= viewy
, (x
-= viewx
) || y
) ?
192 (x
> y
) ? tantoangle
[SlopeDiv(y
,x
)] : // octant 0
193 ANG90
-1-tantoangle
[SlopeDiv(x
,y
)] : // octant 1
194 x
> (y
= -y
) ? 0-tantoangle
[SlopeDiv(y
,x
)] : // octant 8
195 ANG270
+tantoangle
[SlopeDiv(x
,y
)] : // octant 7
196 y
>= 0 ? (x
= -x
) > y
? ANG180
-1-tantoangle
[SlopeDiv(y
,x
)] : // octant 3
197 ANG90
+ tantoangle
[SlopeDiv(x
,y
)] : // octant 2
198 (x
= -x
) > (y
= -y
) ? ANG180
+tantoangle
[ SlopeDiv(y
,x
)] : // octant 4
199 ANG270
-1-tantoangle
[SlopeDiv(x
,y
)] : // octant 5
204 // R_InitTextureMapping
206 // killough 5/2/98: reformatted
208 static void R_InitTextureMapping (void)
213 // Use tangent table to generate viewangletox:
214 // viewangletox will give the next greatest x
215 // after the view angle.
218 // so FIELDOFVIEW angles covers SCREENWIDTH.
220 if(viewangletox
==NULL
)
221 viewangletox
=malloc(sizeof(int)*FINEANGLES
/2);
223 focallength
= FixedDiv(centerxfrac
, finetangent
[FINEANGLES
/4+FIELDOFVIEW
/2]);
225 for (i
=0 ; i
<FINEANGLES
/2 ; i
++)
228 if (finetangent
[i
] > FRACUNIT
*2)
231 if (finetangent
[i
] < -FRACUNIT
*2)
235 t
= FixedMul(finetangent
[i
], focallength
);
236 t
= (centerxfrac
- t
+ FRACUNIT
-1) >> FRACBITS
;
246 // Scan viewangletox[] to generate xtoviewangle[]:
247 // xtoviewangle will give the smallest view angle
250 for (x
=0; x
<=viewwidth
; x
++)
252 for (i
=0; viewangletox
[i
] > x
; i
++)
254 xtoviewangle
[x
] = (i
<<ANGLETOFINESHIFT
)-ANG90
;
257 // Take out the fencepost cases from viewangletox.
258 for (i
=0; i
<FINEANGLES
/2; i
++)
259 if (viewangletox
[i
] == -1)
262 if (viewangletox
[i
] == viewwidth
+1)
263 viewangletox
[i
] = viewwidth
;
265 clipangle
= xtoviewangle
[0];
270 // Only inits the zlight table,
271 // because the scalelight table changes with view size.
276 void R_InitLightTables (void)
280 // killough 4/4/98: dynamic colormaps
281 c_zlight
= malloc(sizeof(*c_zlight
) * numcolormaps
);
282 c_scalelight
= malloc(sizeof(*c_scalelight
) * numcolormaps
);
284 // Calculate the light levels to use
285 // for each level / distance combination.
286 for (i
=0; i
< LIGHTLEVELS
; i
++)
288 int j
, startmap
= ((LIGHTLEVELS
-1-i
)*2)*NUMCOLORMAPS
/LIGHTLEVELS
;
289 for (j
=0; j
<MAXLIGHTZ
; j
++)
291 // CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
292 // brighter than normal res
293 int scale
= FixedDiv ((320/2*FRACUNIT
), (j
+1)<<LIGHTZSHIFT
);
294 int t
, level
= startmap
- (scale
>>= LIGHTSCALESHIFT
)/DISTMAP
;
299 if (level
>= NUMCOLORMAPS
)
300 level
= NUMCOLORMAPS
-1;
302 // killough 3/20/98: Initialize multiple colormaps
304 for (t
=0; t
<numcolormaps
; t
++) // killough 4/4/98
305 c_zlight
[t
][i
][j
] = colormaps
[t
] + level
;
312 // Do not really change anything here,
313 // because it might be in the middle of a refresh.
314 // The change will take effect next refresh.
317 boolean setsizeneeded
;
320 void R_SetViewSize(int blocks
)
322 setsizeneeded
= true;
327 // R_ExecuteSetViewSize
330 void R_ExecuteSetViewSize (void)
334 setsizeneeded
= false;
338 scaledviewwidth
= SCREENWIDTH
;
339 viewheight
= SCREENHEIGHT
;
341 // proff 09/24/98: Added for high-res
342 else if (setblocks
== 10)
344 scaledviewwidth
= SCREENWIDTH
;
345 viewheight
= SCREENHEIGHT
-ST_SCALED_HEIGHT
;
349 // proff 08/17/98: Changed for high-res
350 scaledviewwidth
= setblocks
*SCREENWIDTH
/10;
351 viewheight
= (setblocks
*(SCREENHEIGHT
-ST_SCALED_HEIGHT
)/10) & ~7;
354 viewwidth
= scaledviewwidth
;
356 centery
= viewheight
/2;
357 centerx
= viewwidth
/2;
358 centerxfrac
= centerx
<<FRACBITS
;
359 centeryfrac
= centery
<<FRACBITS
;
360 projection
= centerxfrac
;
361 // proff 11/06/98: Added for high-res
362 projectiony
= ((SCREENHEIGHT
* centerx
* 320) / 200) / SCREENWIDTH
* FRACUNIT
;
364 R_InitBuffer (scaledviewwidth
, viewheight
);
366 R_InitTextureMapping();
369 // proff 08/17/98: Changed for high-res
370 pspritescale
= FRACUNIT
*viewwidth
/320;
371 pspriteiscale
= FRACUNIT
*320/viewwidth
;
372 // proff 11/06/98: Added for high-res
373 pspriteyscale
= (((SCREENHEIGHT
*viewwidth
)/SCREENWIDTH
) << FRACBITS
) / 200;
376 for (i
=0 ; i
<viewwidth
; i
++)
377 screenheightarray
[i
] = viewheight
;
380 for (i
=0 ; i
<viewheight
; i
++)
381 { // killough 5/2/98: reformatted
382 fixed_t dy
= D_abs(((i
-viewheight
/2)<<FRACBITS
)+FRACUNIT
/2);
383 // proff 08/17/98: Changed for high-res
384 yslope
[i
] = FixedDiv(projectiony
, dy
);
387 for (i
=0 ; i
<viewwidth
; i
++)
389 fixed_t cosadj
= D_abs(finecosine
[xtoviewangle
[i
]>>ANGLETOFINESHIFT
]);
390 distscale
[i
] = FixedDiv(FRACUNIT
,cosadj
);
393 // Calculate the light levels to use
394 // for each level / scale combination.
395 for (i
=0; i
<LIGHTLEVELS
; i
++)
397 int j
, startmap
= ((LIGHTLEVELS
-1-i
)*2)*NUMCOLORMAPS
/LIGHTLEVELS
;
398 for (j
=0 ; j
<MAXLIGHTSCALE
; j
++)
400 int t
, level
= startmap
- j
*320/viewwidth
/DISTMAP
;
405 if (level
>= NUMCOLORMAPS
)
406 level
= NUMCOLORMAPS
-1;
408 // killough 3/20/98: initialize multiple colormaps
411 for (t
=0; t
<numcolormaps
; t
++) // killough 4/4/98
412 c_scalelight
[t
][i
][j
] = colormaps
[t
] + level
;
421 extern int screenblocks
;
425 // CPhipps - R_DrawColumn isn't constant anymore, so must
426 // initialise in code
427 colfunc
= R_DrawColumn
; // current column draw function
428 // if (SCREENWIDTH<320)
429 // I_Error("R_Init: Screenwidth(%d) < 320",SCREENWIDTH);
432 printf("\nR_LoadTrigTables: ");
436 printf("\nR_InitData: ");
438 R_SetViewSize(screenblocks
);
439 printf("\nR_Init: R_InitPlanes ");
441 printf("R_InitLightTables ");
443 printf("R_InitSkyMap ");
445 printf("R_InitTranslationsTables ");
446 R_InitTranslationTables();
450 // R_PointInSubsector
452 // killough 5/2/98: reformatted, cleaned up
454 subsector_t
*R_PointInSubsector(fixed_t x
, fixed_t y
)
456 int nodenum
= numnodes
-1;
457 while (!(nodenum
& NF_SUBSECTOR
))
458 nodenum
= nodes
[nodenum
].children
[R_PointOnSide(x
, y
, nodes
+nodenum
)];
459 return &subsectors
[nodenum
& ~NF_SUBSECTOR
];
466 void R_SetupFrame (player_t
*player
)
471 viewx
= player
->mo
->x
;
472 viewy
= player
->mo
->y
;
473 viewangle
= player
->mo
->angle
+ viewangleoffset
;
474 extralight
= player
->extralight
;
476 viewz
= player
->viewz
;
478 viewsin
= finesine
[viewangle
>>ANGLETOFINESHIFT
];
479 viewcos
= finecosine
[viewangle
>>ANGLETOFINESHIFT
];
481 // killough 3/20/98, 4/4/98: select colormap based on player status
483 if (player
->mo
->subsector
->sector
->heightsec
!= -1)
485 const sector_t
*s
= player
->mo
->subsector
->sector
->heightsec
+ sectors
;
486 cm
= viewz
< s
->floorheight
? s
->bottommap
: viewz
> s
->ceilingheight
?
487 s
->topmap
: s
->midmap
;
488 if (cm
< 0 || cm
> numcolormaps
)
494 fullcolormap
= colormaps
[cm
];
495 zlight
= c_zlight
[cm
];
496 scalelight
= c_scalelight
[cm
];
498 if (player
->fixedcolormap
)
500 // killough 3/20/98: localize scalelightfixed (readability/optimization)
501 static lighttable_t
*scalelightfixed
[MAXLIGHTSCALE
];
503 fixedcolormap
= fullcolormap
// killough 3/20/98: use fullcolormap
504 + player
->fixedcolormap
*256*sizeof(lighttable_t
);
506 walllights
= scalelightfixed
;
508 for (i
=0 ; i
<MAXLIGHTSCALE
; i
++)
509 scalelightfixed
[i
] = fixedcolormap
;
520 void R_RenderPlayerView (player_t
* player
)
522 R_SetupFrame (player
);
530 // check for new console commands.
533 // The head node is the last node output.
534 R_RenderBSPNode (numnodes
-1);
536 // Check for new console commands.
541 // Check for new console commands.
546 // Check for new console commands.