diff options
Diffstat (limited to 'apps/plugins/doom/r_main.c')
-rw-r--r-- | apps/plugins/doom/r_main.c | 531 |
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 | |||
56 | int viewangleoffset; | ||
57 | |||
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; | ||
63 | fixed_t projection; | ||
64 | fixed_t viewx, viewy, viewz; | ||
65 | angle_t viewangle; | ||
66 | fixed_t viewcos, viewsin; | ||
67 | player_t *viewplayer; | ||
68 | extern lighttable_t **walllights; | ||
69 | |||
70 | // | ||
71 | // precalculated math tables | ||
72 | // | ||
73 | |||
74 | angle_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 | |||
81 | int 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 | |||
87 | angle_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 | |||
92 | int numcolormaps; | ||
93 | lighttable_t *(*c_scalelight)[LIGHTLEVELS][MAXLIGHTSCALE]; | ||
94 | lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ]; | ||
95 | lighttable_t *(*scalelight)[MAXLIGHTSCALE]; | ||
96 | lighttable_t *(*zlight)[MAXLIGHTZ]; | ||
97 | lighttable_t *fullcolormap; | ||
98 | lighttable_t **colormaps; | ||
99 | |||
100 | // killough 3/20/98, 4/4/98: end dynamic colormaps | ||
101 | |||
102 | int extralight; // bumped light from gun blasts | ||
103 | |||
104 | void (*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 | |||
115 | int 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 | |||
134 | int 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 | |||
169 | angle_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 | |||
185 | angle_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 | |||
206 | static 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 | |||
271 | void 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 | |||
312 | boolean setsizeneeded; | ||
313 | int setblocks; | ||
314 | |||
315 | void R_SetViewSize(int blocks) | ||
316 | { | ||
317 | setsizeneeded = true; | ||
318 | setblocks = blocks; | ||
319 | } | ||
320 | |||
321 | // | ||
322 | // R_ExecuteSetViewSize | ||
323 | // | ||
324 | |||
325 | void 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 | |||
406 | extern int screenblocks; | ||
407 | |||
408 | void 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 | |||
437 | subsector_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 | |||
449 | void 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 | // | ||
503 | void 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 | } | ||