diff options
Diffstat (limited to 'apps/plugins/doom/r_bsp.c')
-rw-r--r-- | apps/plugins/doom/r_bsp.c | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/apps/plugins/doom/r_bsp.c b/apps/plugins/doom/r_bsp.c new file mode 100644 index 0000000000..358787dc58 --- /dev/null +++ b/apps/plugins/doom/r_bsp.c | |||
@@ -0,0 +1,576 @@ | |||
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 | * BSP traversal, handling of LineSegs for rendering. | ||
29 | * | ||
30 | *-----------------------------------------------------------------------------*/ | ||
31 | |||
32 | #include "doomdef.h" | ||
33 | |||
34 | #include "m_bbox.h" | ||
35 | |||
36 | #include "i_system.h" | ||
37 | |||
38 | #include "r_main.h" | ||
39 | #include "r_plane.h" | ||
40 | #include "r_things.h" | ||
41 | |||
42 | // State. | ||
43 | #include "doomstat.h" | ||
44 | #include "r_state.h" | ||
45 | #include "r_segs.h" | ||
46 | #include "rockmacros.h" | ||
47 | |||
48 | seg_t *curline; | ||
49 | side_t *sidedef; | ||
50 | line_t *linedef; | ||
51 | sector_t *frontsector; | ||
52 | sector_t *backsector; | ||
53 | drawseg_t *ds_p; | ||
54 | |||
55 | |||
56 | drawseg_t *drawsegs; | ||
57 | unsigned maxdrawsegs; | ||
58 | |||
59 | // | ||
60 | // R_ClearDrawSegs | ||
61 | // | ||
62 | void R_ClearDrawSegs (void) | ||
63 | { | ||
64 | ds_p = drawsegs; | ||
65 | } | ||
66 | |||
67 | // CPhipps - | ||
68 | // Instead of clipsegs, let's try using an array with one entry for each column, | ||
69 | // indicating whether it's blocked by a solid wall yet or not. | ||
70 | |||
71 | byte solidcol[SCREENWIDTH] IBSS_ATTR; | ||
72 | |||
73 | // CPhipps - | ||
74 | // R_ClipWallSegment | ||
75 | // | ||
76 | // Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those | ||
77 | // columns which aren't solid, and updates the solidcol[] array appropriately | ||
78 | |||
79 | void R_ClipWallSegment(int first, int last, boolean solid) | ||
80 | { | ||
81 | byte *p; | ||
82 | while (first < last) { | ||
83 | if (solidcol[first]) { | ||
84 | if (!(p = memchr(solidcol+first, 0, last-first))) return; // All solid | ||
85 | first = p - solidcol; | ||
86 | } else { | ||
87 | int to; | ||
88 | if (!(p = memchr(solidcol+first, 1, last-first))) to = last; | ||
89 | else to = p - solidcol; | ||
90 | R_StoreWallRange(first, to-1); | ||
91 | if (solid) { | ||
92 | memset(solidcol+first,1,to-first); | ||
93 | } | ||
94 | first = to; | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | |||
99 | // | ||
100 | // R_ClearClipSegs | ||
101 | // | ||
102 | |||
103 | void R_ClearClipSegs (void) | ||
104 | { | ||
105 | memset(solidcol, 0, SCREENWIDTH); | ||
106 | } | ||
107 | |||
108 | // killough 1/18/98 -- This function is used to fix the automap bug which | ||
109 | // showed lines behind closed doors simply because the door had a dropoff. | ||
110 | // | ||
111 | // cph - converted to R_RecalcLineFlags. This recalculates all the flags for | ||
112 | // a line, including closure and texture tiling. | ||
113 | |||
114 | static void R_RecalcLineFlags(void) | ||
115 | { | ||
116 | linedef->r_validcount = gametic; | ||
117 | |||
118 | /* First decide if the line is closed, normal, or invisible */ | ||
119 | if (!(linedef->flags & ML_TWOSIDED) | ||
120 | || backsector->ceilingheight <= frontsector->floorheight | ||
121 | || backsector->floorheight >= frontsector->ceilingheight | ||
122 | || ( | ||
123 | // if door is closed because back is shut: | ||
124 | backsector->ceilingheight <= backsector->floorheight | ||
125 | |||
126 | // preserve a kind of transparent door/lift special effect: | ||
127 | && (backsector->ceilingheight >= frontsector->ceilingheight || | ||
128 | curline->sidedef->toptexture) | ||
129 | |||
130 | && (backsector->floorheight <= frontsector->floorheight || | ||
131 | curline->sidedef->bottomtexture) | ||
132 | |||
133 | // properly render skies (consider door "open" if both ceilings are sky): | ||
134 | && (backsector->ceilingpic !=skyflatnum || | ||
135 | frontsector->ceilingpic!=skyflatnum) | ||
136 | ) | ||
137 | ) | ||
138 | linedef->r_flags = RF_CLOSED; | ||
139 | else { | ||
140 | // Reject empty lines used for triggers | ||
141 | // and special events. | ||
142 | // Identical floor and ceiling on both sides, | ||
143 | // identical light levels on both sides, | ||
144 | // and no middle texture. | ||
145 | // CPhipps - recode for speed, not certain if this is portable though | ||
146 | if (backsector->ceilingheight != frontsector->ceilingheight | ||
147 | || backsector->floorheight != frontsector->floorheight | ||
148 | || curline->sidedef->midtexture | ||
149 | || memcmp(&backsector->floor_xoffs, &frontsector->floor_xoffs, | ||
150 | sizeof(frontsector->floor_xoffs) + sizeof(frontsector->floor_yoffs) + | ||
151 | sizeof(frontsector->ceiling_xoffs) + sizeof(frontsector->ceiling_yoffs) + | ||
152 | sizeof(frontsector->ceilingpic) + sizeof(frontsector->floorpic) + | ||
153 | sizeof(frontsector->lightlevel) + sizeof(frontsector->floorlightsec) + | ||
154 | sizeof(frontsector->ceilinglightsec))) { | ||
155 | linedef->r_flags = 0; return; | ||
156 | } else | ||
157 | linedef->r_flags = RF_IGNORE; | ||
158 | } | ||
159 | |||
160 | /* cph - I'm too lazy to try and work with offsets in this */ | ||
161 | if (curline->sidedef->rowoffset) return; | ||
162 | |||
163 | /* Now decide on texture tiling */ | ||
164 | if (linedef->flags & ML_TWOSIDED) { | ||
165 | int c; | ||
166 | |||
167 | /* Does top texture need tiling */ | ||
168 | if ((c = frontsector->ceilingheight - backsector->ceilingheight) > 0 && | ||
169 | (textureheight[texturetranslation[curline->sidedef->toptexture]] > c)) | ||
170 | linedef->r_flags |= RF_TOP_TILE; | ||
171 | |||
172 | /* Does bottom texture need tiling */ | ||
173 | if ((c = frontsector->floorheight - backsector->floorheight) > 0 && | ||
174 | (textureheight[texturetranslation[curline->sidedef->bottomtexture]] > c)) | ||
175 | linedef->r_flags |= RF_BOT_TILE; | ||
176 | } else { | ||
177 | int c; | ||
178 | /* Does middle texture need tiling */ | ||
179 | if ((c = frontsector->ceilingheight - frontsector->floorheight) > 0 && | ||
180 | (textureheight[texturetranslation[curline->sidedef->midtexture]] > c)) | ||
181 | linedef->r_flags |= RF_MID_TILE; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | // | ||
186 | // killough 3/7/98: Hack floor/ceiling heights for deep water etc. | ||
187 | // | ||
188 | // If player's view height is underneath fake floor, lower the | ||
189 | // drawn ceiling to be just under the floor height, and replace | ||
190 | // the drawn floor and ceiling textures, and light level, with | ||
191 | // the control sector's. | ||
192 | // | ||
193 | // Similar for ceiling, only reflected. | ||
194 | // | ||
195 | // killough 4/11/98, 4/13/98: fix bugs, add 'back' parameter | ||
196 | // | ||
197 | |||
198 | sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, | ||
199 | int *floorlightlevel, int *ceilinglightlevel, | ||
200 | boolean back) | ||
201 | { | ||
202 | if (floorlightlevel) | ||
203 | *floorlightlevel = sec->floorlightsec == -1 ? | ||
204 | sec->lightlevel : sectors[sec->floorlightsec].lightlevel; | ||
205 | |||
206 | if (ceilinglightlevel) | ||
207 | *ceilinglightlevel = sec->ceilinglightsec == -1 ? // killough 4/11/98 | ||
208 | sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel; | ||
209 | |||
210 | if (sec->heightsec != -1) | ||
211 | { | ||
212 | const sector_t *s = §ors[sec->heightsec]; | ||
213 | int heightsec = viewplayer->mo->subsector->sector->heightsec; | ||
214 | int underwater = heightsec!=-1 && viewz<=sectors[heightsec].floorheight; | ||
215 | |||
216 | // Replace sector being drawn, with a copy to be hacked | ||
217 | *tempsec = *sec; | ||
218 | |||
219 | // Replace floor and ceiling height with other sector's heights. | ||
220 | tempsec->floorheight = s->floorheight; | ||
221 | tempsec->ceilingheight = s->ceilingheight; | ||
222 | |||
223 | // killough 11/98: prevent sudden light changes from non-water sectors: | ||
224 | if (underwater && (tempsec-> floorheight = sec->floorheight, | ||
225 | tempsec->ceilingheight = s->floorheight-1, !back)) | ||
226 | { // head-below-floor hack | ||
227 | tempsec->floorpic = s->floorpic; | ||
228 | tempsec->floor_xoffs = s->floor_xoffs; | ||
229 | tempsec->floor_yoffs = s->floor_yoffs; | ||
230 | |||
231 | if (underwater) { | ||
232 | if (s->ceilingpic == skyflatnum) { | ||
233 | tempsec->floorheight = tempsec->ceilingheight+1; | ||
234 | tempsec->ceilingpic = tempsec->floorpic; | ||
235 | tempsec->ceiling_xoffs = tempsec->floor_xoffs; | ||
236 | tempsec->ceiling_yoffs = tempsec->floor_yoffs; | ||
237 | } else { | ||
238 | tempsec->ceilingpic = s->ceilingpic; | ||
239 | tempsec->ceiling_xoffs = s->ceiling_xoffs; | ||
240 | tempsec->ceiling_yoffs = s->ceiling_yoffs; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | tempsec->lightlevel = s->lightlevel; | ||
245 | |||
246 | if (floorlightlevel) | ||
247 | *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel : | ||
248 | sectors[s->floorlightsec].lightlevel; // killough 3/16/98 | ||
249 | |||
250 | if (ceilinglightlevel) | ||
251 | *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel : | ||
252 | sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98 | ||
253 | } | ||
254 | else | ||
255 | if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight && | ||
256 | sec->ceilingheight > s->ceilingheight) | ||
257 | { // Above-ceiling hack | ||
258 | tempsec->ceilingheight = s->ceilingheight; | ||
259 | tempsec->floorheight = s->ceilingheight + 1; | ||
260 | |||
261 | tempsec->floorpic = tempsec->ceilingpic = s->ceilingpic; | ||
262 | tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs; | ||
263 | tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; | ||
264 | |||
265 | if (s->floorpic != skyflatnum) | ||
266 | { | ||
267 | tempsec->ceilingheight = sec->ceilingheight; | ||
268 | tempsec->floorpic = s->floorpic; | ||
269 | tempsec->floor_xoffs = s->floor_xoffs; | ||
270 | tempsec->floor_yoffs = s->floor_yoffs; | ||
271 | } | ||
272 | |||
273 | tempsec->lightlevel = s->lightlevel; | ||
274 | |||
275 | if (floorlightlevel) | ||
276 | *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel : | ||
277 | sectors[s->floorlightsec].lightlevel; // killough 3/16/98 | ||
278 | |||
279 | if (ceilinglightlevel) | ||
280 | *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel : | ||
281 | sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98 | ||
282 | } | ||
283 | sec = tempsec; // Use other sector | ||
284 | } | ||
285 | return sec; | ||
286 | } | ||
287 | |||
288 | // | ||
289 | // R_AddLine | ||
290 | // Clips the given segment | ||
291 | // and adds any visible pieces to the line list. | ||
292 | // | ||
293 | |||
294 | static void R_AddLine (seg_t *line) | ||
295 | { | ||
296 | int x1; | ||
297 | int x2; | ||
298 | angle_t angle1; | ||
299 | angle_t angle2; | ||
300 | angle_t span; | ||
301 | angle_t tspan; | ||
302 | static sector_t tempsec; // killough 3/8/98: ceiling/water hack | ||
303 | // boolean solid = true; | ||
304 | |||
305 | curline = line; | ||
306 | |||
307 | angle1 = R_PointToAngle (line->v1->x, line->v1->y); | ||
308 | angle2 = R_PointToAngle (line->v2->x, line->v2->y); | ||
309 | |||
310 | // Clip to view edges. | ||
311 | span = angle1 - angle2; | ||
312 | |||
313 | // Back side, i.e. backface culling | ||
314 | if (span >= ANG180) | ||
315 | return; | ||
316 | |||
317 | // Global angle needed by segcalc. | ||
318 | rw_angle1 = angle1; | ||
319 | angle1 -= viewangle; | ||
320 | angle2 -= viewangle; | ||
321 | |||
322 | tspan = angle1 + clipangle; | ||
323 | if (tspan > 2*clipangle) | ||
324 | { | ||
325 | tspan -= 2*clipangle; | ||
326 | |||
327 | // Totally off the left edge? | ||
328 | if (tspan >= span) | ||
329 | return; | ||
330 | |||
331 | angle1 = clipangle; | ||
332 | } | ||
333 | |||
334 | tspan = clipangle - angle2; | ||
335 | if (tspan > 2*clipangle) | ||
336 | { | ||
337 | tspan -= 2*clipangle; | ||
338 | |||
339 | // Totally off the left edge? | ||
340 | if (tspan >= span) | ||
341 | return; | ||
342 | angle2 = 0-clipangle; | ||
343 | } | ||
344 | |||
345 | // The seg is in the view range, | ||
346 | // but not necessarily visible. | ||
347 | |||
348 | angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; | ||
349 | angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; | ||
350 | |||
351 | // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur: | ||
352 | x1 = viewangletox[angle1]; | ||
353 | x2 = viewangletox[angle2]; | ||
354 | |||
355 | // Does not cross a pixel? | ||
356 | if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness | ||
357 | return; | ||
358 | |||
359 | backsector = line->backsector; | ||
360 | |||
361 | // Single sided line? | ||
362 | if (backsector) | ||
363 | // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water | ||
364 | backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); | ||
365 | |||
366 | /* cph - roll up linedef properties in flags */ | ||
367 | if ((linedef = curline->linedef)->r_validcount != gametic) | ||
368 | R_RecalcLineFlags(); | ||
369 | |||
370 | if (linedef->r_flags & RF_IGNORE) | ||
371 | { | ||
372 | return; | ||
373 | } | ||
374 | else | ||
375 | R_ClipWallSegment (x1, x2, linedef->r_flags & RF_CLOSED); | ||
376 | } | ||
377 | |||
378 | // | ||
379 | // R_CheckBBox | ||
380 | // Checks BSP node/subtree bounding box. | ||
381 | // Returns true | ||
382 | // if some part of the bbox might be visible. | ||
383 | // | ||
384 | |||
385 | static const int checkcoord[12][4] = // killough -- static const | ||
386 | { | ||
387 | {3,0,2,1}, | ||
388 | {3,0,2,0}, | ||
389 | {3,1,2,0}, | ||
390 | {0}, | ||
391 | {2,0,2,1}, | ||
392 | {0,0,0,0}, | ||
393 | {3,1,3,0}, | ||
394 | {0}, | ||
395 | {2,0,3,1}, | ||
396 | {2,1,3,1}, | ||
397 | {2,1,3,0} | ||
398 | }; | ||
399 | |||
400 | // killough 1/28/98: static // CPhipps - const parameter, reformatted | ||
401 | static boolean R_CheckBBox(const fixed_t *bspcoord) | ||
402 | { | ||
403 | angle_t angle1, angle2; | ||
404 | |||
405 | { | ||
406 | int boxpos; | ||
407 | const int* check; | ||
408 | |||
409 | // Find the corners of the box | ||
410 | // that define the edges from current viewpoint. | ||
411 | boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT ] ? 1 : 2) + | ||
412 | (viewy >= bspcoord[BOXTOP ] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8); | ||
413 | |||
414 | if (boxpos == 5) | ||
415 | return true; | ||
416 | |||
417 | check = checkcoord[boxpos]; | ||
418 | angle1 = R_PointToAngle (bspcoord[check[0]], bspcoord[check[1]]) - viewangle; | ||
419 | angle2 = R_PointToAngle (bspcoord[check[2]], bspcoord[check[3]]) - viewangle; | ||
420 | } | ||
421 | |||
422 | // cph - replaced old code, which was unclear and badly commented | ||
423 | // Much more efficient code now | ||
424 | if ((signed)angle1 < (signed)angle2) { /* it's "behind" us */ | ||
425 | /* Either angle1 or angle2 is behind us, so it doesn't matter if we | ||
426 | * change it to the corect sign | ||
427 | */ | ||
428 | if ((angle1 >= ANG180) && (angle1 < ANG270)) | ||
429 | angle1 = INT_MAX; /* which is ANG180-1 */ | ||
430 | else | ||
431 | angle2 = INT_MIN; | ||
432 | } | ||
433 | |||
434 | if ((signed)angle2 >= (signed)clipangle) return false; // Both off left edge | ||
435 | if ((signed)angle1 <= -(signed)clipangle) return false; // Both off right edge | ||
436 | if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; // Clip at left edge | ||
437 | if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle; // Clip at right edge | ||
438 | |||
439 | // Find the first clippost | ||
440 | // that touches the source post | ||
441 | // (adjacent pixels are touching). | ||
442 | angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; | ||
443 | angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; | ||
444 | { | ||
445 | int sx1 = viewangletox[angle1]; | ||
446 | int sx2 = viewangletox[angle2]; | ||
447 | // const cliprange_t *start; | ||
448 | |||
449 | // Does not cross a pixel. | ||
450 | if (sx1 == sx2) | ||
451 | return false; | ||
452 | |||
453 | if (!memchr(solidcol+sx1, 0, sx2-sx1)) return false; | ||
454 | // All columns it covers are already solidly covered | ||
455 | } | ||
456 | |||
457 | return true; | ||
458 | } | ||
459 | |||
460 | // | ||
461 | // R_Subsector | ||
462 | // Determine floor/ceiling planes. | ||
463 | // Add sprites of things in sector. | ||
464 | // Draw one or more line segments. | ||
465 | // | ||
466 | // killough 1/31/98 -- made static, polished | ||
467 | |||
468 | // Had to move this out of the function - causes stack overflows in RockBox | ||
469 | sector_t tempsec IBSS_ATTR; // killough 3/7/98: deep water hack | ||
470 | static void R_Subsector(int num) | ||
471 | { | ||
472 | int count; | ||
473 | seg_t *line; | ||
474 | subsector_t *sub; | ||
475 | |||
476 | int floorlightlevel; // killough 3/16/98: set floor lightlevel | ||
477 | int ceilinglightlevel; // killough 4/11/98 | ||
478 | |||
479 | #ifdef RANGECHECK | ||
480 | if (num>=numsubsectors) | ||
481 | I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors); | ||
482 | #endif | ||
483 | |||
484 | sub = &subsectors[num]; | ||
485 | frontsector = sub->sector; | ||
486 | count = sub->numlines; | ||
487 | line = &segs[sub->firstline]; | ||
488 | // sscount++; | ||
489 | |||
490 | // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect | ||
491 | frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, | ||
492 | &ceilinglightlevel, false); // killough 4/11/98 | ||
493 | |||
494 | // killough 3/7/98: Add (x,y) offsets to flats, add deep water check | ||
495 | // killough 3/16/98: add floorlightlevel | ||
496 | // killough 10/98: add support for skies transferred from sidedefs | ||
497 | |||
498 | floorplane = frontsector->floorheight < viewz || // killough 3/7/98 | ||
499 | (frontsector->heightsec != -1 && | ||
500 | sectors[frontsector->heightsec].ceilingpic == skyflatnum) | ||
501 | ? | ||
502 | R_FindPlane(frontsector->floorheight, | ||
503 | frontsector->floorpic == skyflatnum && // kilough 10/98 | ||
504 | frontsector->sky & PL_SKYFLAT ? frontsector->sky : | ||
505 | frontsector->floorpic, | ||
506 | floorlightlevel, // killough 3/16/98 | ||
507 | frontsector->floor_xoffs, // killough 3/7/98 | ||
508 | frontsector->floor_yoffs | ||
509 | ) : NULL; | ||
510 | |||
511 | ceilingplane = frontsector->ceilingheight > viewz || | ||
512 | frontsector->ceilingpic == skyflatnum || | ||
513 | (frontsector->heightsec != -1 && | ||
514 | sectors[frontsector->heightsec].floorpic == skyflatnum) | ||
515 | ? | ||
516 | R_FindPlane(frontsector->ceilingheight, // killough 3/8/98 | ||
517 | frontsector->ceilingpic == skyflatnum && // kilough 10/98 | ||
518 | frontsector->sky & PL_SKYFLAT ? frontsector->sky : | ||
519 | frontsector->ceilingpic, | ||
520 | ceilinglightlevel, // killough 4/11/98 | ||
521 | frontsector->ceiling_xoffs, // killough 3/7/98 | ||
522 | frontsector->ceiling_yoffs | ||
523 | ) : NULL; | ||
524 | |||
525 | // killough 9/18/98: Fix underwater slowdown, by passing real sector | ||
526 | // instead of fake one. Improve sprite lighting by basing sprite | ||
527 | // lightlevels on floor & ceiling lightlevels in the surrounding area. | ||
528 | // | ||
529 | // 10/98 killough: | ||
530 | // | ||
531 | // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! | ||
532 | // That is part of the 242 effect!!! If you simply pass sub->sector to | ||
533 | // the old code you will not get correct lighting for underwater sprites!!! | ||
534 | // Either you must pass the fake sector and handle validcount here, on the | ||
535 | // real sector, or you must account for the lighting in some other way, | ||
536 | // like passing it as an argument. | ||
537 | |||
538 | R_AddSprites(sub, (floorlightlevel+ceilinglightlevel)/2); | ||
539 | |||
540 | while (count--) | ||
541 | { | ||
542 | if (line->miniseg == false) | ||
543 | R_AddLine (line); | ||
544 | line++; | ||
545 | } | ||
546 | |||
547 | } | ||
548 | |||
549 | // | ||
550 | // RenderBSPNode | ||
551 | // Renders all subsectors below a given node, | ||
552 | // traversing subtree recursively. | ||
553 | // Just call with BSP root. | ||
554 | // | ||
555 | // killough 5/2/98: reformatted, removed tail recursion | ||
556 | |||
557 | void R_RenderBSPNode(int bspnum) | ||
558 | { | ||
559 | while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? | ||
560 | { | ||
561 | const node_t *bsp = &nodes[bspnum]; | ||
562 | |||
563 | // Decide which side the view point is on. | ||
564 | int side = R_PointOnSide(viewx, viewy, bsp); | ||
565 | // Recursively divide front space. | ||
566 | R_RenderBSPNode(bsp->children[side]); | ||
567 | |||
568 | // Possibly divide back space. | ||
569 | |||
570 | if (!R_CheckBBox(bsp->bbox[side^1])) | ||
571 | return; | ||
572 | |||
573 | bspnum = bsp->children[side^1]; | ||
574 | } | ||
575 | R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); | ||
576 | } | ||