r_bsp.c 21 KB

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