diff options
Diffstat (limited to 'src/r_bsp.c')
-rw-r--r-- | src/r_bsp.c | 664 |
1 files changed, 664 insertions, 0 deletions
diff --git a/src/r_bsp.c b/src/r_bsp.c new file mode 100644 index 0000000..e9ce6c5 --- /dev/null +++ b/src/r_bsp.c | |||
@@ -0,0 +1,664 @@ | |||
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 | * Copyright 2005, 2006 by | ||
12 | * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version 2 | ||
17 | * of the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
27 | * 02111-1307, USA. | ||
28 | * | ||
29 | * DESCRIPTION: | ||
30 | * BSP traversal, handling of LineSegs for rendering. | ||
31 | * | ||
32 | *-----------------------------------------------------------------------------*/ | ||
33 | |||
34 | #include "doomstat.h" | ||
35 | #include "m_bbox.h" | ||
36 | #include "r_main.h" | ||
37 | #include "r_segs.h" | ||
38 | #include "r_plane.h" | ||
39 | #include "r_things.h" | ||
40 | #include "r_bsp.h" // cph - sanity checking | ||
41 | #include "v_video.h" | ||
42 | #include "lprintf.h" | ||
43 | |||
44 | seg_t *curline; | ||
45 | side_t *sidedef; | ||
46 | line_t *linedef; | ||
47 | sector_t *frontsector; | ||
48 | sector_t *backsector; | ||
49 | drawseg_t *ds_p; | ||
50 | |||
51 | // killough 4/7/98: indicates doors closed wrt automap bugfix: | ||
52 | // cph - replaced by linedef rendering flags - int doorclosed; | ||
53 | |||
54 | // killough: New code which removes 2s linedef limit | ||
55 | drawseg_t *drawsegs; | ||
56 | unsigned maxdrawsegs; | ||
57 | // drawseg_t drawsegs[MAXDRAWSEGS]; // old code -- killough | ||
58 | |||
59 | // | ||
60 | // R_ClearDrawSegs | ||
61 | // | ||
62 | |||
63 | void R_ClearDrawSegs(void) | ||
64 | { | ||
65 | ds_p = drawsegs; | ||
66 | } | ||
67 | |||
68 | // CPhipps - | ||
69 | // Instead of clipsegs, let's try using an array with one entry for each column, | ||
70 | // indicating whether it's blocked by a solid wall yet or not. | ||
71 | |||
72 | byte solidcol[MAX_SCREENWIDTH]; | ||
73 | |||
74 | // CPhipps - | ||
75 | // R_ClipWallSegment | ||
76 | // | ||
77 | // Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those | ||
78 | // columns which aren't solid, and updates the solidcol[] array appropriately | ||
79 | |||
80 | static void R_ClipWallSegment(int first, int last, boolean solid) | ||
81 | { | ||
82 | byte *p; | ||
83 | while (first < last) { | ||
84 | if (solidcol[first]) { | ||
85 | if (!(p = memchr(solidcol+first, 0, last-first))) return; // All solid | ||
86 | first = p - solidcol; | ||
87 | } else { | ||
88 | int to; | ||
89 | if (!(p = memchr(solidcol+first, 1, last-first))) to = last; | ||
90 | else to = p - solidcol; | ||
91 | R_StoreWallRange(first, to-1); | ||
92 | if (solid) { | ||
93 | memset(solidcol+first,1,to-first); | ||
94 | } | ||
95 | first = to; | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | |||
100 | // | ||
101 | // R_ClearClipSegs | ||
102 | // | ||
103 | |||
104 | void R_ClearClipSegs (void) | ||
105 | { | ||
106 | memset(solidcol, 0, SCREENWIDTH); | ||
107 | } | ||
108 | |||
109 | // killough 1/18/98 -- This function is used to fix the automap bug which | ||
110 | // showed lines behind closed doors simply because the door had a dropoff. | ||
111 | // | ||
112 | // cph - converted to R_RecalcLineFlags. This recalculates all the flags for | ||
113 | // a line, including closure and texture tiling. | ||
114 | |||
115 | static void R_RecalcLineFlags(void) | ||
116 | { | ||
117 | linedef->r_validcount = gametic; | ||
118 | |||
119 | /* First decide if the line is closed, normal, or invisible */ | ||
120 | if (!(linedef->flags & ML_TWOSIDED) | ||
121 | || backsector->ceilingheight <= frontsector->floorheight | ||
122 | || backsector->floorheight >= frontsector->ceilingheight | ||
123 | || ( | ||
124 | // if door is closed because back is shut: | ||
125 | backsector->ceilingheight <= backsector->floorheight | ||
126 | |||
127 | // preserve a kind of transparent door/lift special effect: | ||
128 | && (backsector->ceilingheight >= frontsector->ceilingheight || | ||
129 | curline->sidedef->toptexture) | ||
130 | |||
131 | && (backsector->floorheight <= frontsector->floorheight || | ||
132 | curline->sidedef->bottomtexture) | ||
133 | |||
134 | // properly render skies (consider door "open" if both ceilings are sky): | ||
135 | && (backsector->ceilingpic !=skyflatnum || | ||
136 | frontsector->ceilingpic!=skyflatnum) | ||
137 | ) | ||
138 | ) | ||
139 | linedef->r_flags = RF_CLOSED; | ||
140 | else { | ||
141 | // Reject empty lines used for triggers | ||
142 | // and special events. | ||
143 | // Identical floor and ceiling on both sides, | ||
144 | // identical light levels on both sides, | ||
145 | // and no middle texture. | ||
146 | // CPhipps - recode for speed, not certain if this is portable though | ||
147 | if (backsector->ceilingheight != frontsector->ceilingheight | ||
148 | || backsector->floorheight != frontsector->floorheight | ||
149 | || curline->sidedef->midtexture | ||
150 | || memcmp(&backsector->floor_xoffs, &frontsector->floor_xoffs, | ||
151 | sizeof(frontsector->floor_xoffs) + sizeof(frontsector->floor_yoffs) + | ||
152 | sizeof(frontsector->ceiling_xoffs) + sizeof(frontsector->ceiling_yoffs) + | ||
153 | sizeof(frontsector->ceilingpic) + sizeof(frontsector->floorpic) + | ||
154 | sizeof(frontsector->lightlevel) + sizeof(frontsector->floorlightsec) + | ||
155 | sizeof(frontsector->ceilinglightsec))) { | ||
156 | linedef->r_flags = 0; return; | ||
157 | } else | ||
158 | linedef->r_flags = RF_IGNORE; | ||
159 | } | ||
160 | |||
161 | /* cph - I'm too lazy to try and work with offsets in this */ | ||
162 | if (curline->sidedef->rowoffset) return; | ||
163 | |||
164 | /* Now decide on texture tiling */ | ||
165 | if (linedef->flags & ML_TWOSIDED) { | ||
166 | int c; | ||
167 | |||
168 | /* Does top texture need tiling */ | ||
169 | if ((c = frontsector->ceilingheight - backsector->ceilingheight) > 0 && | ||
170 | (textureheight[texturetranslation[curline->sidedef->toptexture]] > c)) | ||
171 | linedef->r_flags |= RF_TOP_TILE; | ||
172 | |||
173 | /* Does bottom texture need tiling */ | ||
174 | if ((c = frontsector->floorheight - backsector->floorheight) > 0 && | ||
175 | (textureheight[texturetranslation[curline->sidedef->bottomtexture]] > c)) | ||
176 | linedef->r_flags |= RF_BOT_TILE; | ||
177 | } else { | ||
178 | int c; | ||
179 | /* Does middle texture need tiling */ | ||
180 | if ((c = frontsector->ceilingheight - frontsector->floorheight) > 0 && | ||
181 | (textureheight[texturetranslation[curline->sidedef->midtexture]] > c)) | ||
182 | linedef->r_flags |= RF_MID_TILE; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | // | ||
187 | // killough 3/7/98: Hack floor/ceiling heights for deep water etc. | ||
188 | // | ||
189 | // If player's view height is underneath fake floor, lower the | ||
190 | // drawn ceiling to be just under the floor height, and replace | ||
191 | // the drawn floor and ceiling textures, and light level, with | ||
192 | // the control sector's. | ||
193 | // | ||
194 | // Similar for ceiling, only reflected. | ||
195 | // | ||
196 | // killough 4/11/98, 4/13/98: fix bugs, add 'back' parameter | ||
197 | // | ||
198 | |||
199 | sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, | ||
200 | int *floorlightlevel, int *ceilinglightlevel, | ||
201 | boolean back) | ||
202 | { | ||
203 | if (floorlightlevel) | ||
204 | *floorlightlevel = sec->floorlightsec == -1 ? | ||
205 | sec->lightlevel : sectors[sec->floorlightsec].lightlevel; | ||
206 | |||
207 | if (ceilinglightlevel) | ||
208 | *ceilinglightlevel = sec->ceilinglightsec == -1 ? // killough 4/11/98 | ||
209 | sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel; | ||
210 | |||
211 | if (sec->heightsec != -1) | ||
212 | { | ||
213 | const sector_t *s = §ors[sec->heightsec]; | ||
214 | int heightsec = viewplayer->mo->subsector->sector->heightsec; | ||
215 | int underwater = heightsec!=-1 && viewz<=sectors[heightsec].floorheight; | ||
216 | |||
217 | // Replace sector being drawn, with a copy to be hacked | ||
218 | *tempsec = *sec; | ||
219 | |||
220 | // Replace floor and ceiling height with other sector's heights. | ||
221 | tempsec->floorheight = s->floorheight; | ||
222 | tempsec->ceilingheight = s->ceilingheight; | ||
223 | |||
224 | // killough 11/98: prevent sudden light changes from non-water sectors: | ||
225 | if (underwater && (tempsec-> floorheight = sec->floorheight, | ||
226 | tempsec->ceilingheight = s->floorheight-1, !back)) | ||
227 | { // head-below-floor hack | ||
228 | tempsec->floorpic = s->floorpic; | ||
229 | tempsec->floor_xoffs = s->floor_xoffs; | ||
230 | tempsec->floor_yoffs = s->floor_yoffs; | ||
231 | |||
232 | if (underwater) { | ||
233 | if (s->ceilingpic == skyflatnum) { | ||
234 | tempsec->floorheight = tempsec->ceilingheight+1; | ||
235 | tempsec->ceilingpic = tempsec->floorpic; | ||
236 | tempsec->ceiling_xoffs = tempsec->floor_xoffs; | ||
237 | tempsec->ceiling_yoffs = tempsec->floor_yoffs; | ||
238 | } else { | ||
239 | tempsec->ceilingpic = s->ceilingpic; | ||
240 | tempsec->ceiling_xoffs = s->ceiling_xoffs; | ||
241 | tempsec->ceiling_yoffs = s->ceiling_yoffs; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | tempsec->lightlevel = s->lightlevel; | ||
246 | |||
247 | if (floorlightlevel) | ||
248 | *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel : | ||
249 | sectors[s->floorlightsec].lightlevel; // killough 3/16/98 | ||
250 | |||
251 | if (ceilinglightlevel) | ||
252 | *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel : | ||
253 | sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98 | ||
254 | } | ||
255 | else | ||
256 | if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight && | ||
257 | sec->ceilingheight > s->ceilingheight) | ||
258 | { // Above-ceiling hack | ||
259 | tempsec->ceilingheight = s->ceilingheight; | ||
260 | tempsec->floorheight = s->ceilingheight + 1; | ||
261 | |||
262 | tempsec->floorpic = tempsec->ceilingpic = s->ceilingpic; | ||
263 | tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs; | ||
264 | tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; | ||
265 | |||
266 | if (s->floorpic != skyflatnum) | ||
267 | { | ||
268 | tempsec->ceilingheight = sec->ceilingheight; | ||
269 | tempsec->floorpic = s->floorpic; | ||
270 | tempsec->floor_xoffs = s->floor_xoffs; | ||
271 | tempsec->floor_yoffs = s->floor_yoffs; | ||
272 | } | ||
273 | |||
274 | tempsec->lightlevel = s->lightlevel; | ||
275 | |||
276 | if (floorlightlevel) | ||
277 | *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel : | ||
278 | sectors[s->floorlightsec].lightlevel; // killough 3/16/98 | ||
279 | |||
280 | if (ceilinglightlevel) | ||
281 | *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel : | ||
282 | sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98 | ||
283 | } | ||
284 | sec = tempsec; // Use other sector | ||
285 | } | ||
286 | return sec; | ||
287 | } | ||
288 | |||
289 | // | ||
290 | // R_AddLine | ||
291 | // Clips the given segment | ||
292 | // and adds any visible pieces to the line list. | ||
293 | // | ||
294 | |||
295 | static void R_AddLine (seg_t *line) | ||
296 | { | ||
297 | int x1; | ||
298 | int x2; | ||
299 | angle_t angle1; | ||
300 | angle_t angle2; | ||
301 | angle_t span; | ||
302 | angle_t tspan; | ||
303 | static sector_t tempsec; // killough 3/8/98: ceiling/water hack | ||
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 | #ifdef GL_DOOM | ||
356 | // proff 11/99: we have to add these segs to avoid gaps in OpenGL | ||
357 | if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness | ||
358 | { | ||
359 | if (V_GetMode() == VID_MODEGL) | ||
360 | { | ||
361 | if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM | ||
362 | { | ||
363 | unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a | ||
364 | unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough | ||
365 | drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs)); | ||
366 | //ds_p = drawsegs+maxdrawsegs; | ||
367 | ds_p = drawsegs + pos; // jff 8/9/98 fix from ZDOOM1.14a | ||
368 | maxdrawsegs = newmax; | ||
369 | } | ||
370 | ds_p->curline = curline; | ||
371 | ds_p++; | ||
372 | gld_AddWall(curline); | ||
373 | return; | ||
374 | } | ||
375 | else | ||
376 | return; | ||
377 | } | ||
378 | #else | ||
379 | // Does not cross a pixel? | ||
380 | if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness | ||
381 | return; | ||
382 | #endif | ||
383 | |||
384 | backsector = line->backsector; | ||
385 | |||
386 | // Single sided line? | ||
387 | if (backsector) | ||
388 | // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water | ||
389 | backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); | ||
390 | |||
391 | /* cph - roll up linedef properties in flags */ | ||
392 | if ((linedef = curline->linedef)->r_validcount != gametic) | ||
393 | R_RecalcLineFlags(); | ||
394 | |||
395 | if (linedef->r_flags & RF_IGNORE) | ||
396 | { | ||
397 | return; | ||
398 | } | ||
399 | else | ||
400 | R_ClipWallSegment (x1, x2, linedef->r_flags & RF_CLOSED); | ||
401 | } | ||
402 | |||
403 | // | ||
404 | // R_CheckBBox | ||
405 | // Checks BSP node/subtree bounding box. | ||
406 | // Returns true | ||
407 | // if some part of the bbox might be visible. | ||
408 | // | ||
409 | |||
410 | static const int checkcoord[12][4] = // killough -- static const | ||
411 | { | ||
412 | {3,0,2,1}, | ||
413 | {3,0,2,0}, | ||
414 | {3,1,2,0}, | ||
415 | {0}, | ||
416 | {2,0,2,1}, | ||
417 | {0,0,0,0}, | ||
418 | {3,1,3,0}, | ||
419 | {0}, | ||
420 | {2,0,3,1}, | ||
421 | {2,1,3,1}, | ||
422 | {2,1,3,0} | ||
423 | }; | ||
424 | |||
425 | // killough 1/28/98: static // CPhipps - const parameter, reformatted | ||
426 | static boolean R_CheckBBox(const fixed_t *bspcoord) | ||
427 | { | ||
428 | angle_t angle1, angle2; | ||
429 | |||
430 | { | ||
431 | int boxpos; | ||
432 | const int* check; | ||
433 | |||
434 | // Find the corners of the box | ||
435 | // that define the edges from current viewpoint. | ||
436 | boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT ] ? 1 : 2) + | ||
437 | (viewy >= bspcoord[BOXTOP ] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8); | ||
438 | |||
439 | if (boxpos == 5) | ||
440 | return true; | ||
441 | |||
442 | check = checkcoord[boxpos]; | ||
443 | angle1 = R_PointToAngle (bspcoord[check[0]], bspcoord[check[1]]) - viewangle; | ||
444 | angle2 = R_PointToAngle (bspcoord[check[2]], bspcoord[check[3]]) - viewangle; | ||
445 | } | ||
446 | |||
447 | // cph - replaced old code, which was unclear and badly commented | ||
448 | // Much more efficient code now | ||
449 | if ((signed)angle1 < (signed)angle2) { /* it's "behind" us */ | ||
450 | /* Either angle1 or angle2 is behind us, so it doesn't matter if we | ||
451 | * change it to the corect sign | ||
452 | */ | ||
453 | if ((angle1 >= ANG180) && (angle1 < ANG270)) | ||
454 | angle1 = INT_MAX; /* which is ANG180-1 */ | ||
455 | else | ||
456 | angle2 = INT_MIN; | ||
457 | } | ||
458 | |||
459 | if ((signed)angle2 >= (signed)clipangle) return false; // Both off left edge | ||
460 | if ((signed)angle1 <= -(signed)clipangle) return false; // Both off right edge | ||
461 | if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; // Clip at left edge | ||
462 | if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle; // Clip at right edge | ||
463 | |||
464 | // Find the first clippost | ||
465 | // that touches the source post | ||
466 | // (adjacent pixels are touching). | ||
467 | angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; | ||
468 | angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; | ||
469 | { | ||
470 | int sx1 = viewangletox[angle1]; | ||
471 | int sx2 = viewangletox[angle2]; | ||
472 | // const cliprange_t *start; | ||
473 | |||
474 | // Does not cross a pixel. | ||
475 | if (sx1 == sx2) | ||
476 | return false; | ||
477 | |||
478 | if (!memchr(solidcol+sx1, 0, sx2-sx1)) return false; | ||
479 | // All columns it covers are already solidly covered | ||
480 | } | ||
481 | |||
482 | return true; | ||
483 | } | ||
484 | |||
485 | // | ||
486 | // R_Subsector | ||
487 | // Determine floor/ceiling planes. | ||
488 | // Add sprites of things in sector. | ||
489 | // Draw one or more line segments. | ||
490 | // | ||
491 | // killough 1/31/98 -- made static, polished | ||
492 | |||
493 | static void R_Subsector(int num) | ||
494 | { | ||
495 | int count; | ||
496 | seg_t *line; | ||
497 | subsector_t *sub; | ||
498 | sector_t tempsec; // killough 3/7/98: deep water hack | ||
499 | int floorlightlevel; // killough 3/16/98: set floor lightlevel | ||
500 | int ceilinglightlevel; // killough 4/11/98 | ||
501 | #ifdef GL_DOOM | ||
502 | visplane_t dummyfloorplane; | ||
503 | visplane_t dummyceilingplane; | ||
504 | #endif | ||
505 | |||
506 | #ifdef RANGECHECK | ||
507 | if (num>=numsubsectors) | ||
508 | I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors); | ||
509 | #endif | ||
510 | |||
511 | sub = &subsectors[num]; | ||
512 | frontsector = sub->sector; | ||
513 | count = sub->numlines; | ||
514 | line = &segs[sub->firstline]; | ||
515 | |||
516 | // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect | ||
517 | frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, | ||
518 | &ceilinglightlevel, false); // killough 4/11/98 | ||
519 | |||
520 | // killough 3/7/98: Add (x,y) offsets to flats, add deep water check | ||
521 | // killough 3/16/98: add floorlightlevel | ||
522 | // killough 10/98: add support for skies transferred from sidedefs | ||
523 | |||
524 | floorplane = frontsector->floorheight < viewz || // killough 3/7/98 | ||
525 | (frontsector->heightsec != -1 && | ||
526 | sectors[frontsector->heightsec].ceilingpic == skyflatnum) ? | ||
527 | R_FindPlane(frontsector->floorheight, | ||
528 | frontsector->floorpic == skyflatnum && // kilough 10/98 | ||
529 | frontsector->sky & PL_SKYFLAT ? frontsector->sky : | ||
530 | frontsector->floorpic, | ||
531 | floorlightlevel, // killough 3/16/98 | ||
532 | frontsector->floor_xoffs, // killough 3/7/98 | ||
533 | frontsector->floor_yoffs | ||
534 | ) : NULL; | ||
535 | |||
536 | ceilingplane = frontsector->ceilingheight > viewz || | ||
537 | frontsector->ceilingpic == skyflatnum || | ||
538 | (frontsector->heightsec != -1 && | ||
539 | sectors[frontsector->heightsec].floorpic == skyflatnum) ? | ||
540 | R_FindPlane(frontsector->ceilingheight, // killough 3/8/98 | ||
541 | frontsector->ceilingpic == skyflatnum && // kilough 10/98 | ||
542 | frontsector->sky & PL_SKYFLAT ? frontsector->sky : | ||
543 | frontsector->ceilingpic, | ||
544 | ceilinglightlevel, // killough 4/11/98 | ||
545 | frontsector->ceiling_xoffs, // killough 3/7/98 | ||
546 | frontsector->ceiling_yoffs | ||
547 | ) : NULL; | ||
548 | #ifdef GL_DOOM | ||
549 | // check if the sector is faked | ||
550 | if ((frontsector==sub->sector) && (V_GetMode() == VID_MODEGL)) | ||
551 | { | ||
552 | // if the sector has bottomtextures, then the floorheight will be set to the | ||
553 | // highest surounding floorheight | ||
554 | if ((frontsector->no_bottomtextures) || (!floorplane)) | ||
555 | { | ||
556 | int i=frontsector->linecount; | ||
557 | |||
558 | dummyfloorplane.height=INT_MIN; | ||
559 | while (i--) | ||
560 | { | ||
561 | line_t *tmpline=frontsector->lines[i]; | ||
562 | if (tmpline->backsector) | ||
563 | if (tmpline->backsector != frontsector) | ||
564 | if (tmpline->backsector->floorheight>dummyfloorplane.height) | ||
565 | { | ||
566 | dummyfloorplane.height=tmpline->backsector->floorheight; | ||
567 | dummyfloorplane.lightlevel=tmpline->backsector->lightlevel; | ||
568 | } | ||
569 | if (tmpline->frontsector) | ||
570 | if (tmpline->frontsector != frontsector) | ||
571 | if (tmpline->frontsector->floorheight>dummyfloorplane.height) | ||
572 | { | ||
573 | dummyfloorplane.height=tmpline->frontsector->floorheight; | ||
574 | dummyfloorplane.lightlevel=tmpline->frontsector->lightlevel; | ||
575 | } | ||
576 | } | ||
577 | if (dummyfloorplane.height!=INT_MIN) | ||
578 | floorplane=&dummyfloorplane; | ||
579 | } | ||
580 | // the same for ceilings. they will be set to the lowest ceilingheight | ||
581 | if ((frontsector->no_toptextures) || (!ceilingplane)) | ||
582 | { | ||
583 | int i=frontsector->linecount; | ||
584 | |||
585 | dummyceilingplane.height=INT_MAX; | ||
586 | while (i--) | ||
587 | { | ||
588 | line_t *tmpline=frontsector->lines[i]; | ||
589 | if (tmpline->backsector) | ||
590 | if (tmpline->backsector != frontsector) | ||
591 | if (tmpline->backsector->ceilingheight<dummyceilingplane.height) | ||
592 | { | ||
593 | dummyceilingplane.height=tmpline->backsector->ceilingheight; | ||
594 | dummyceilingplane.lightlevel=tmpline->backsector->lightlevel; | ||
595 | } | ||
596 | if (tmpline->frontsector) | ||
597 | if (tmpline->frontsector != frontsector) | ||
598 | if (tmpline->frontsector->ceilingheight<dummyceilingplane.height) | ||
599 | { | ||
600 | dummyceilingplane.height=tmpline->frontsector->ceilingheight; | ||
601 | dummyceilingplane.lightlevel=tmpline->frontsector->lightlevel; | ||
602 | } | ||
603 | } | ||
604 | if (dummyceilingplane.height!=INT_MAX) | ||
605 | ceilingplane=&dummyceilingplane; | ||
606 | } | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | // killough 9/18/98: Fix underwater slowdown, by passing real sector | ||
611 | // instead of fake one. Improve sprite lighting by basing sprite | ||
612 | // lightlevels on floor & ceiling lightlevels in the surrounding area. | ||
613 | // | ||
614 | // 10/98 killough: | ||
615 | // | ||
616 | // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! | ||
617 | // That is part of the 242 effect!!! If you simply pass sub->sector to | ||
618 | // the old code you will not get correct lighting for underwater sprites!!! | ||
619 | // Either you must pass the fake sector and handle validcount here, on the | ||
620 | // real sector, or you must account for the lighting in some other way, | ||
621 | // like passing it as an argument. | ||
622 | |||
623 | R_AddSprites(sub, (floorlightlevel+ceilinglightlevel)/2); | ||
624 | while (count--) | ||
625 | { | ||
626 | if (line->miniseg == false) | ||
627 | R_AddLine (line); | ||
628 | line++; | ||
629 | curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */ | ||
630 | } | ||
631 | #ifdef GL_DOOM | ||
632 | if (V_GetMode() == VID_MODEGL) | ||
633 | gld_AddPlane(num, floorplane, ceilingplane); | ||
634 | #endif | ||
635 | } | ||
636 | |||
637 | // | ||
638 | // RenderBSPNode | ||
639 | // Renders all subsectors below a given node, | ||
640 | // traversing subtree recursively. | ||
641 | // Just call with BSP root. | ||
642 | // | ||
643 | // killough 5/2/98: reformatted, removed tail recursion | ||
644 | |||
645 | void R_RenderBSPNode(int bspnum) | ||
646 | { | ||
647 | while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? | ||
648 | { | ||
649 | const node_t *bsp = &nodes[bspnum]; | ||
650 | |||
651 | // Decide which side the view point is on. | ||
652 | int side = R_PointOnSide(viewx, viewy, bsp); | ||
653 | // Recursively divide front space. | ||
654 | R_RenderBSPNode(bsp->children[side]); | ||
655 | |||
656 | // Possibly divide back space. | ||
657 | |||
658 | if (!R_CheckBBox(bsp->bbox[side^1])) | ||
659 | return; | ||
660 | |||
661 | bspnum = bsp->children[side^1]; | ||
662 | } | ||
663 | R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); | ||
664 | } | ||