summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/r_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/r_main.c')
-rw-r--r--apps/plugins/doom/r_main.c531
1 files changed, 531 insertions, 0 deletions
diff --git a/apps/plugins/doom/r_main.c b/apps/plugins/doom/r_main.c
new file mode 100644
index 0000000000..f79097a969
--- /dev/null
+++ b/apps/plugins/doom/r_main.c
@@ -0,0 +1,531 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
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
11 *
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.
16 *
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.
21 *
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
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Rendering main loop and setup functions,
29 * utility functions (BSP, geometry, trigonometry).
30 * See tables.c, too.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "w_wad.h"
36#include "r_main.h"
37#include "r_things.h"
38#include "r_plane.h"
39#include "r_bsp.h"
40#include "r_draw.h"
41#include "m_bbox.h"
42#include "r_sky.h"
43#include "v_video.h"
44#include "i_system.h"
45//#include "lprintf.h"
46#include "st_stuff.h"
47#include "rockmacros.h"
48
49// Fineangles in the SCREENWIDTH wide window.
50#define FIELDOFVIEW 2048
51
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.
55
56int viewangleoffset;
57
58int validcount = 1; // increment every time a check is made
59lighttable_t *fixedcolormap;
60int centerx IBSS_ATTR;
61int centery IBSS_ATTR;
62fixed_t centerxfrac, centeryfrac;
63fixed_t projection;
64fixed_t viewx, viewy, viewz;
65angle_t viewangle;
66fixed_t viewcos, viewsin;
67player_t *viewplayer;
68extern lighttable_t **walllights;
69
70//
71// precalculated math tables
72//
73
74angle_t clipangle;
75
76// The viewangletox[viewangle + FINEANGLES/4] lookup
77// maps the visible view angles to screen X coordinates,
78// flattening the arc to a flat projection plane.
79// There will be many angles mapped to the same X.
80
81int viewangletox[FINEANGLES/2];
82
83// The xtoviewangleangle[] table maps a screen pixel
84// to the lowest viewangle that maps back to x ranges
85// from clipangle to -clipangle.
86
87angle_t xtoviewangle[SCREENWIDTH+1]; // killough 2/8/98
88
89// killough 3/20/98: Support dynamic colormaps, e.g. deep water
90// killough 4/4/98: support dynamic number of them as well
91
92int numcolormaps;
93lighttable_t *(*c_scalelight)[LIGHTLEVELS][MAXLIGHTSCALE];
94lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ];
95lighttable_t *(*scalelight)[MAXLIGHTSCALE];
96lighttable_t *(*zlight)[MAXLIGHTZ];
97lighttable_t *fullcolormap;
98lighttable_t **colormaps;
99
100// killough 3/20/98, 4/4/98: end dynamic colormaps
101
102int extralight; // bumped light from gun blasts
103
104void (*colfunc)(void);
105
106//
107// R_PointOnSide
108// Traverse BSP (sub) tree,
109// check point against partition plane.
110// Returns side 0 (front) or 1 (back).
111//
112// killough 5/2/98: reformatted
113//
114
115int R_PointOnSide(fixed_t x, fixed_t y, const node_t *node)
116{
117 if (!node->dx)
118 return x <= node->x ? node->dy > 0 : node->dy < 0;
119
120 if (!node->dy)
121 return y <= node->y ? node->dx < 0 : node->dx > 0;
122
123 x -= node->x;
124 y -= node->y;
125
126 // Try to quickly decide by looking at sign bits.
127 if ((node->dy ^ node->dx ^ x ^ y) < 0)
128 return (node->dy ^ x) < 0; // (left is negative)
129 return FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x);
130}
131
132// killough 5/2/98: reformatted
133
134int R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line)
135{
136 fixed_t lx = line->v1->x;
137 fixed_t ly = line->v1->y;
138 fixed_t ldx = line->v2->x - lx;
139 fixed_t ldy = line->v2->y - ly;
140
141 if (!ldx)
142 return x <= lx ? ldy > 0 : ldy < 0;
143
144 if (!ldy)
145 return y <= ly ? ldx < 0 : ldx > 0;
146
147 x -= lx;
148 y -= ly;
149
150 // Try to quickly decide by looking at sign bits.
151 if ((ldy ^ ldx ^ x ^ y) < 0)
152 return (ldy ^ x) < 0; // (left is negative)
153 return FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x);
154}
155
156//
157// R_PointToAngle
158// To get a global angle from cartesian coordinates,
159// the coordinates are flipped until they are in
160// the first octant of the coordinate system, then
161// the y (<=x) is scaled and divided by x to get a
162// tangent (slope) value which is looked up in the
163// tantoangle[] table. The +1 size of tantoangle[]
164// is to handle the case when x==y without additional
165// checking.
166//
167// killough 5/2/98: reformatted, cleaned up
168
169angle_t R_PointToAngle(fixed_t x, fixed_t y)
170{
171 return (y -= viewy, (x -= viewx) || y) ?
172 x >= 0 ?
173 y >= 0 ?
174 (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
175 ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
176 x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
177 ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
178 y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
179 ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
180 (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
181 ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
182 0;
183}
184
185angle_t R_PointToAngle2(fixed_t viewx, fixed_t viewy, fixed_t x, fixed_t y)
186{
187 return (y -= viewy, (x -= viewx) || y) ?
188 x >= 0 ?
189 y >= 0 ?
190 (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
191 ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
192 x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
193 ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
194 y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
195 ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
196 (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
197 ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
198 0;
199}
200
201//
202// R_InitTextureMapping
203//
204// killough 5/2/98: reformatted
205
206static void R_InitTextureMapping (void)
207{
208 register int i,x;
209 fixed_t focallength;
210
211 // Use tangent table to generate viewangletox:
212 // viewangletox will give the next greatest x
213 // after the view angle.
214 //
215 // Calc focallength
216 // so FIELDOFVIEW angles covers SCREENWIDTH.
217
218 focallength = FixedDiv(centerxfrac, finetangent[FINEANGLES/4+FIELDOFVIEW/2]);
219
220 for (i=0 ; i<FINEANGLES/2 ; i++)
221 {
222 int t;
223 if (finetangent[i] > FRACUNIT*2)
224 t = -1;
225 else
226 if (finetangent[i] < -FRACUNIT*2)
227 t = viewwidth+1;
228 else
229 {
230 t = FixedMul(finetangent[i], focallength);
231 t = (centerxfrac - t + FRACUNIT-1) >> FRACBITS;
232 if (t < -1)
233 t = -1;
234 else
235 if (t > viewwidth+1)
236 t = viewwidth+1;
237 }
238 viewangletox[i] = t;
239 }
240
241 // Scan viewangletox[] to generate xtoviewangle[]:
242 // xtoviewangle will give the smallest view angle
243 // that maps to x.
244
245 for (x=0; x<=viewwidth; x++)
246 {
247 for (i=0; viewangletox[i] > x; i++)
248 ;
249 xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
250 }
251
252 // Take out the fencepost cases from viewangletox.
253 for (i=0; i<FINEANGLES/2; i++)
254 if (viewangletox[i] == -1)
255 viewangletox[i] = 0;
256 else
257 if (viewangletox[i] == viewwidth+1)
258 viewangletox[i] = viewwidth;
259
260 clipangle = xtoviewangle[0];
261}
262
263//
264// R_InitLightTables
265// Only inits the zlight table,
266// because the scalelight table changes with view size.
267//
268
269#define DISTMAP 2
270
271void R_InitLightTables (void)
272{
273 int i;
274
275 // killough 4/4/98: dynamic colormaps
276 c_zlight = malloc(sizeof(*c_zlight) * numcolormaps);
277 c_scalelight = malloc(sizeof(*c_scalelight) * numcolormaps);
278
279 // Calculate the light levels to use
280 // for each level / distance combination.
281 for (i=0; i< LIGHTLEVELS; i++)
282 {
283 int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
284 for (j=0; j<MAXLIGHTZ; j++)
285 {
286 // CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
287 // brighter than normal res
288 int scale = FixedDiv ((320/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
289 int t, level = startmap - (scale >>= LIGHTSCALESHIFT)/DISTMAP;
290
291 if (level < 0)
292 level = 0;
293 else
294 if (level >= NUMCOLORMAPS)
295 level = NUMCOLORMAPS-1;
296
297 // killough 3/20/98: Initialize multiple colormaps
298 level *= 256;
299 for (t=0; t<numcolormaps; t++) // killough 4/4/98
300 c_zlight[t][i][j] = colormaps[t] + level;
301 }
302 }
303}
304
305//
306// R_SetViewSize
307// Do not really change anything here,
308// because it might be in the middle of a refresh.
309// The change will take effect next refresh.
310//
311
312boolean setsizeneeded;
313int setblocks;
314
315void R_SetViewSize(int blocks)
316{
317 setsizeneeded = true;
318 setblocks = blocks;
319}
320
321//
322// R_ExecuteSetViewSize
323//
324
325void R_ExecuteSetViewSize (void)
326{
327 int i;
328
329 setsizeneeded = false;
330
331 if (setblocks == 11)
332 {
333 scaledviewwidth = SCREENWIDTH;
334 viewheight = SCREENHEIGHT;
335 }
336 else
337 {
338 scaledviewwidth = setblocks*32;
339 viewheight = (setblocks*168/10)&~7;
340 }
341
342 viewwidth = scaledviewwidth;
343
344 centery = viewheight/2;
345 centerx = viewwidth/2;
346 centerxfrac = centerx<<FRACBITS;
347 centeryfrac = centery<<FRACBITS;
348 projection = centerxfrac;
349
350 R_InitBuffer (scaledviewwidth, viewheight);
351
352 R_InitTextureMapping();
353
354 // psprite scales
355 pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
356 pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
357
358 // thing clipping
359 for (i=0 ; i<viewwidth ; i++)
360 screenheightarray[i] = viewheight;
361
362 // planes
363 for (i=0 ; i<viewheight ; i++)
364 { // killough 5/2/98: reformatted
365 fixed_t dy = D_abs(((i-viewheight/2)<<FRACBITS)+FRACUNIT/2);
366 yslope[i] = FixedDiv ( (viewwidth)/2*FRACUNIT, dy);
367 }
368
369 for (i=0 ; i<viewwidth ; i++)
370 {
371 fixed_t cosadj = D_abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
372 distscale[i] = FixedDiv(FRACUNIT,cosadj);
373 }
374
375 // Calculate the light levels to use
376 // for each level / scale combination.
377 for (i=0; i<LIGHTLEVELS; i++)
378 {
379 int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
380 for (j=0 ; j<MAXLIGHTSCALE ; j++)
381 {
382 // CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
383 // brighter than normal res
384 int scale = FixedDiv ((320/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
385 int t, level = startmap - (scale >>= LIGHTSCALESHIFT)/DISTMAP;
386
387 if (level < 0)
388 level = 0;
389
390 if (level >= NUMCOLORMAPS)
391 level = NUMCOLORMAPS-1;
392
393 // killough 3/20/98: initialize multiple colormaps
394 level *= 256;
395
396 for (t=0; t<numcolormaps; t++) // killough 4/4/98
397 c_scalelight[t][i][j] = colormaps[t] + level;
398 }
399 }
400}
401
402//
403// R_Init
404//
405
406extern int screenblocks;
407
408void R_Init (void)
409{
410 // CPhipps - R_DrawColumn isn't constant anymore, so must
411 // initialise in code
412 colfunc = R_DrawColumn; // current column draw function
413 if (SCREENWIDTH<320)
414 I_Error("R_Init: Screenwidth(%d) < 320",SCREENWIDTH);
415#if 1
416 printf("\nR_LoadTrigTables: ");
417 R_LoadTrigTables();
418#endif
419 printf("\nR_InitData: ");
420 R_InitData();
421 R_SetViewSize(screenblocks);
422 printf("\nR_Init: R_InitPlanes ");
423 R_InitPlanes();
424 printf("R_InitLightTables ");
425 R_InitLightTables();
426 printf("R_InitSkyMap ");
427 R_InitSkyMap();
428 printf("R_InitTranslationsTables ");
429 R_InitTranslationTables();
430}
431
432//
433// R_PointInSubsector
434//
435// killough 5/2/98: reformatted, cleaned up
436
437subsector_t *R_PointInSubsector(fixed_t x, fixed_t y)
438{
439 int nodenum = numnodes-1;
440 while (!(nodenum & NF_SUBSECTOR))
441 nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)];
442 return &subsectors[nodenum & ~NF_SUBSECTOR];
443}
444
445//
446// R_SetupFrame
447//
448
449void R_SetupFrame (player_t *player)
450{
451 int i, cm;
452
453 viewplayer = player;
454 viewx = player->mo->x;
455 viewy = player->mo->y;
456 viewangle = player->mo->angle + viewangleoffset;
457 extralight = player->extralight;
458
459 viewz = player->viewz;
460
461 viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
462 viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
463
464 // killough 3/20/98, 4/4/98: select colormap based on player status
465
466 if (player->mo->subsector->sector->heightsec != -1)
467 {
468 const sector_t *s = player->mo->subsector->sector->heightsec + sectors;
469 cm = viewz < s->floorheight ? s->bottommap : viewz > s->ceilingheight ?
470 s->topmap : s->midmap;
471 if (cm < 0 || cm > numcolormaps)
472 cm = 0;
473 }
474 else
475 cm = 0;
476
477 fullcolormap = colormaps[cm];
478 zlight = c_zlight[cm];
479 scalelight = c_scalelight[cm];
480
481 if (player->fixedcolormap)
482 {
483 // killough 3/20/98: localize scalelightfixed (readability/optimization)
484 static lighttable_t *scalelightfixed[MAXLIGHTSCALE];
485
486 fixedcolormap = fullcolormap // killough 3/20/98: use fullcolormap
487 + player->fixedcolormap*256*sizeof(lighttable_t);
488
489 walllights = scalelightfixed;
490
491 for (i=0 ; i<MAXLIGHTSCALE ; i++)
492 scalelightfixed[i] = fixedcolormap;
493 }
494 else
495 fixedcolormap = 0;
496
497 validcount++;
498}
499
500//
501// R_RenderView
502//
503void R_RenderPlayerView (player_t* player)
504{
505 R_SetupFrame (player);
506
507 // Clear buffers.
508 R_ClearClipSegs ();
509 R_ClearDrawSegs ();
510 R_ClearPlanes ();
511 R_ClearSprites ();
512
513 // check for new console commands.
514 // NetUpdate ();
515
516 // The head node is the last node output.
517 R_RenderBSPNode (numnodes-1);
518
519 // Check for new console commands.
520 // NetUpdate ();
521
522 R_DrawPlanes ();
523
524 // Check for new console commands.
525 // NetUpdate ();
526
527 R_DrawMasked ();
528
529 // Check for new console commands.
530 // NetUpdate ();
531}