r_segs.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  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-2004 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. * All the clipping: columns, horizontal spans, sky columns.
  31. *
  32. *-----------------------------------------------------------------------------*/
  33. //
  34. // 4/25/98, 5/2/98 killough: reformatted, beautified
  35. #include "doomstat.h"
  36. #include "r_main.h"
  37. #include "r_bsp.h"
  38. #include "r_segs.h"
  39. #include "r_plane.h"
  40. #include "r_things.h"
  41. #include "r_draw.h"
  42. #include "w_wad.h"
  43. #include "v_video.h"
  44. #include "lprintf.h"
  45. // OPTIMIZE: closed two sided lines as single sided
  46. // killough 1/6/98: replaced globals with statics where appropriate
  47. // True if any of the segs textures might be visible.
  48. static boolean segtextured;
  49. static boolean markfloor; // False if the back side is the same plane.
  50. static boolean markceiling;
  51. static boolean maskedtexture;
  52. static int toptexture;
  53. static int bottomtexture;
  54. static int midtexture;
  55. static fixed_t toptexheight, midtexheight, bottomtexheight; // cph
  56. angle_t rw_normalangle; // angle to line origin
  57. int rw_angle1;
  58. fixed_t rw_distance;
  59. //
  60. // regular wall
  61. //
  62. static int rw_x;
  63. static int rw_stopx;
  64. static angle_t rw_centerangle;
  65. static fixed_t rw_offset;
  66. static fixed_t rw_scale;
  67. static fixed_t rw_scalestep;
  68. static fixed_t rw_midtexturemid;
  69. static fixed_t rw_toptexturemid;
  70. static fixed_t rw_bottomtexturemid;
  71. static int rw_lightlevel;
  72. static int worldtop;
  73. static int worldbottom;
  74. static int worldhigh;
  75. static int worldlow;
  76. static fixed_t pixhigh;
  77. static fixed_t pixlow;
  78. static fixed_t pixhighstep;
  79. static fixed_t pixlowstep;
  80. static fixed_t topfrac;
  81. static fixed_t topstep;
  82. static fixed_t bottomfrac;
  83. static fixed_t bottomstep;
  84. static int *maskedtexturecol; // dropoff overflow
  85. //
  86. // R_ScaleFromGlobalAngle
  87. // Returns the texture mapping scale
  88. // for the current line (horizontal span)
  89. // at the given angle.
  90. // rw_distance must be calculated first.
  91. //
  92. // killough 5/2/98: reformatted, cleaned up
  93. // CPhipps - moved here from r_main.c
  94. static fixed_t R_ScaleFromGlobalAngle(angle_t visangle)
  95. {
  96. int anglea = ANG90 + (visangle-viewangle);
  97. int angleb = ANG90 + (visangle-rw_normalangle);
  98. int den = FixedMul(rw_distance, finesine[anglea>>ANGLETOFINESHIFT]);
  99. // proff 11/06/98: Changed for high-res
  100. fixed_t num = FixedMul(projectiony, finesine[angleb>>ANGLETOFINESHIFT]);
  101. return den > num>>16 ? (num = FixedDiv(num, den)) > 64*FRACUNIT ?
  102. 64*FRACUNIT : num < 256 ? 256 : num : 64*FRACUNIT;
  103. }
  104. //
  105. // R_RenderMaskedSegRange
  106. //
  107. void R_RenderMaskedSegRange(drawseg_t *ds, int x1, int x2)
  108. {
  109. int texnum;
  110. sector_t tempsec; // killough 4/13/98
  111. const rpatch_t *patch;
  112. R_DrawColumn_f colfunc;
  113. draw_column_vars_t dcvars;
  114. angle_t angle;
  115. R_SetDefaultDrawColumnVars(&dcvars);
  116. // Calculate light table.
  117. // Use different light tables
  118. // for horizontal / vertical / diagonal. Diagonal?
  119. curline = ds->curline; // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
  120. // killough 4/11/98: draw translucent 2s normal textures
  121. colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_STANDARD, drawvars.filterwall, drawvars.filterz);
  122. if (curline->linedef->tranlump >= 0 && general_translucency)
  123. {
  124. colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_TRANSLUCENT, drawvars.filterwall, drawvars.filterz);
  125. tranmap = main_tranmap;
  126. if (curline->linedef->tranlump > 0)
  127. tranmap = W_CacheLumpNum(curline->linedef->tranlump-1);
  128. }
  129. // killough 4/11/98: end translucent 2s normal code
  130. frontsector = curline->frontsector;
  131. backsector = curline->backsector;
  132. // cph 2001/11/25 - middle textures did not animate in v1.2
  133. texnum = curline->sidedef->midtexture;
  134. if (!comp[comp_maskedanim])
  135. texnum = texturetranslation[texnum];
  136. // killough 4/13/98: get correct lightlevel for 2s normal textures
  137. rw_lightlevel = R_FakeFlat(frontsector, &tempsec, NULL, NULL, false) ->lightlevel;
  138. maskedtexturecol = ds->maskedtexturecol;
  139. rw_scalestep = ds->scalestep;
  140. spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
  141. mfloorclip = ds->sprbottomclip;
  142. mceilingclip = ds->sprtopclip;
  143. // find positioning
  144. if (curline->linedef->flags & ML_DONTPEGBOTTOM)
  145. {
  146. dcvars.texturemid = frontsector->floorheight > backsector->floorheight
  147. ? frontsector->floorheight : backsector->floorheight;
  148. dcvars.texturemid = dcvars.texturemid + textureheight[texnum] - viewz;
  149. }
  150. else
  151. {
  152. dcvars.texturemid =frontsector->ceilingheight<backsector->ceilingheight
  153. ? frontsector->ceilingheight : backsector->ceilingheight;
  154. dcvars.texturemid = dcvars.texturemid - viewz;
  155. }
  156. dcvars.texturemid += curline->sidedef->rowoffset;
  157. if (fixedcolormap) {
  158. dcvars.colormap = fixedcolormap;
  159. dcvars.nextcolormap = dcvars.colormap; // for filtering -- POPE
  160. }
  161. patch = R_CacheTextureCompositePatchNum(texnum);
  162. // draw the columns
  163. for (dcvars.x = x1 ; dcvars.x <= x2 ; dcvars.x++, spryscale += rw_scalestep)
  164. if (maskedtexturecol[dcvars.x] != INT_MAX) // dropoff overflow
  165. {
  166. // calculate texture offset - POPE
  167. angle = (ds->rw_centerangle + xtoviewangle[dcvars.x]) >> ANGLETOFINESHIFT;
  168. dcvars.texu = ds->rw_offset - FixedMul(finetangent[angle], ds->rw_distance);
  169. if (drawvars.filterwall == RDRAW_FILTER_LINEAR)
  170. dcvars.texu -= (FRACUNIT>>1);
  171. if (!fixedcolormap)
  172. dcvars.z = spryscale; // for filtering -- POPE
  173. dcvars.colormap = R_ColourMap(rw_lightlevel,spryscale);
  174. dcvars.nextcolormap = R_ColourMap(rw_lightlevel+1,spryscale); // for filtering -- POPE
  175. // killough 3/2/98:
  176. //
  177. // This calculation used to overflow and cause crashes in Doom:
  178. //
  179. // sprtopscreen = centeryfrac - FixedMul(dcvars.texturemid, spryscale);
  180. //
  181. // This code fixes it, by using double-precision intermediate
  182. // arithmetic and by skipping the drawing of 2s normals whose
  183. // mapping to screen coordinates is totally out of range:
  184. {
  185. int_64_t t = ((int_64_t) centeryfrac << FRACBITS) -
  186. (int_64_t) dcvars.texturemid * spryscale;
  187. if (t + (int_64_t) textureheight[texnum] * spryscale < 0 ||
  188. t > (int_64_t) MAX_SCREENHEIGHT << FRACBITS*2)
  189. continue; // skip if the texture is out of screen's range
  190. sprtopscreen = (long)(t >> FRACBITS);
  191. }
  192. dcvars.iscale = 0xffffffffu / (unsigned) spryscale;
  193. // killough 1/25/98: here's where Medusa came in, because
  194. // it implicitly assumed that the column was all one patch.
  195. // Originally, Doom did not construct complete columns for
  196. // multipatched textures, so there were no header or trailer
  197. // bytes in the column referred to below, which explains
  198. // the Medusa effect. The fix is to construct true columns
  199. // when forming multipatched textures (see r_data.c).
  200. // draw the texture
  201. R_DrawMaskedColumn(
  202. patch,
  203. colfunc,
  204. &dcvars,
  205. R_GetPatchColumnWrapped(patch, maskedtexturecol[dcvars.x]),
  206. R_GetPatchColumnWrapped(patch, maskedtexturecol[dcvars.x]-1),
  207. R_GetPatchColumnWrapped(patch, maskedtexturecol[dcvars.x]+1)
  208. );
  209. maskedtexturecol[dcvars.x] = INT_MAX; // dropoff overflow
  210. }
  211. // Except for main_tranmap, mark others purgable at this point
  212. if (curline->linedef->tranlump > 0 && general_translucency)
  213. W_UnlockLumpNum(curline->linedef->tranlump-1); // cph - unlock it
  214. R_UnlockTextureCompositePatchNum(texnum);
  215. 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 */
  216. }
  217. //
  218. // R_RenderSegLoop
  219. // Draws zero, one, or two textures (and possibly a masked texture) for walls.
  220. // Can draw or mark the starting pixel of floor and ceiling textures.
  221. // CALLED: CORE LOOPING ROUTINE.
  222. //
  223. #define HEIGHTBITS 12
  224. #define HEIGHTUNIT (1<<HEIGHTBITS)
  225. static int didsolidcol; /* True if at least one column was marked solid */
  226. static void R_RenderSegLoop (void)
  227. {
  228. const rpatch_t *tex_patch;
  229. R_DrawColumn_f colfunc = R_GetDrawColumnFunc(RDC_PIPELINE_STANDARD, drawvars.filterwall, drawvars.filterz);
  230. draw_column_vars_t dcvars;
  231. fixed_t texturecolumn = 0; // shut up compiler warning
  232. R_SetDefaultDrawColumnVars(&dcvars);
  233. rendered_segs++;
  234. for ( ; rw_x < rw_stopx ; rw_x++)
  235. {
  236. // mark floor / ceiling areas
  237. int yh = bottomfrac>>HEIGHTBITS;
  238. int yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
  239. // no space above wall?
  240. int bottom,top = ceilingclip[rw_x]+1;
  241. if (yl < top)
  242. yl = top;
  243. if (markceiling)
  244. {
  245. bottom = yl-1;
  246. if (bottom >= floorclip[rw_x])
  247. bottom = floorclip[rw_x]-1;
  248. if (top <= bottom)
  249. {
  250. ceilingplane->top[rw_x] = top;
  251. ceilingplane->bottom[rw_x] = bottom;
  252. }
  253. // SoM: this should be set here
  254. ceilingclip[rw_x] = bottom;
  255. }
  256. // yh = bottomfrac>>HEIGHTBITS;
  257. bottom = floorclip[rw_x]-1;
  258. if (yh > bottom)
  259. yh = bottom;
  260. if (markfloor)
  261. {
  262. top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh;
  263. if (++top <= bottom)
  264. {
  265. floorplane->top[rw_x] = top;
  266. floorplane->bottom[rw_x] = bottom;
  267. }
  268. // SoM: This should be set here to prevent overdraw
  269. floorclip[rw_x] = top;
  270. }
  271. // texturecolumn and lighting are independent of wall tiers
  272. if (segtextured)
  273. {
  274. // calculate texture offset
  275. angle_t angle =(rw_centerangle+xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
  276. texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
  277. if (drawvars.filterwall == RDRAW_FILTER_LINEAR)
  278. texturecolumn -= (FRACUNIT>>1);
  279. dcvars.texu = texturecolumn; // for filtering -- POPE
  280. texturecolumn >>= FRACBITS;
  281. dcvars.colormap = R_ColourMap(rw_lightlevel,rw_scale);
  282. dcvars.nextcolormap = R_ColourMap(rw_lightlevel+1,rw_scale); // for filtering -- POPE
  283. dcvars.z = rw_scale; // for filtering -- POPE
  284. dcvars.x = rw_x;
  285. dcvars.iscale = 0xffffffffu / (unsigned)rw_scale;
  286. }
  287. // draw the wall tiers
  288. if (midtexture)
  289. {
  290. dcvars.yl = yl; // single sided line
  291. dcvars.yh = yh;
  292. dcvars.texturemid = rw_midtexturemid;
  293. tex_patch = R_CacheTextureCompositePatchNum(midtexture);
  294. dcvars.source = R_GetTextureColumn(tex_patch, texturecolumn);
  295. dcvars.prevsource = R_GetTextureColumn(tex_patch, texturecolumn-1);
  296. dcvars.nextsource = R_GetTextureColumn(tex_patch, texturecolumn+1);
  297. dcvars.texheight = midtexheight;
  298. colfunc (&dcvars);
  299. R_UnlockTextureCompositePatchNum(midtexture);
  300. tex_patch = NULL;
  301. ceilingclip[rw_x] = viewheight;
  302. floorclip[rw_x] = -1;
  303. }
  304. else
  305. {
  306. // two sided line
  307. if (toptexture)
  308. {
  309. // top wall
  310. int mid = pixhigh>>HEIGHTBITS;
  311. pixhigh += pixhighstep;
  312. if (mid >= floorclip[rw_x])
  313. mid = floorclip[rw_x]-1;
  314. if (mid >= yl)
  315. {
  316. dcvars.yl = yl;
  317. dcvars.yh = mid;
  318. dcvars.texturemid = rw_toptexturemid;
  319. tex_patch = R_CacheTextureCompositePatchNum(toptexture);
  320. dcvars.source = R_GetTextureColumn(tex_patch,texturecolumn);
  321. dcvars.prevsource = R_GetTextureColumn(tex_patch,texturecolumn-1);
  322. dcvars.nextsource = R_GetTextureColumn(tex_patch,texturecolumn+1);
  323. dcvars.texheight = toptexheight;
  324. colfunc (&dcvars);
  325. R_UnlockTextureCompositePatchNum(toptexture);
  326. tex_patch = NULL;
  327. ceilingclip[rw_x] = mid;
  328. }
  329. else
  330. ceilingclip[rw_x] = yl-1;
  331. }
  332. else // no top wall
  333. {
  334. if (markceiling)
  335. ceilingclip[rw_x] = yl-1;
  336. }
  337. if (bottomtexture) // bottom wall
  338. {
  339. int mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
  340. pixlow += pixlowstep;
  341. // no space above wall?
  342. if (mid <= ceilingclip[rw_x])
  343. mid = ceilingclip[rw_x]+1;
  344. if (mid <= yh)
  345. {
  346. dcvars.yl = mid;
  347. dcvars.yh = yh;
  348. dcvars.texturemid = rw_bottomtexturemid;
  349. tex_patch = R_CacheTextureCompositePatchNum(bottomtexture);
  350. dcvars.source = R_GetTextureColumn(tex_patch, texturecolumn);
  351. dcvars.prevsource = R_GetTextureColumn(tex_patch, texturecolumn-1);
  352. dcvars.nextsource = R_GetTextureColumn(tex_patch, texturecolumn+1);
  353. dcvars.texheight = bottomtexheight;
  354. colfunc (&dcvars);
  355. R_UnlockTextureCompositePatchNum(bottomtexture);
  356. tex_patch = NULL;
  357. floorclip[rw_x] = mid;
  358. }
  359. else
  360. floorclip[rw_x] = yh+1;
  361. }
  362. else // no bottom wall
  363. {
  364. if (markfloor)
  365. floorclip[rw_x] = yh+1;
  366. }
  367. // cph - if we completely blocked further sight through this column,
  368. // add this info to the solid columns array for r_bsp.c
  369. if ((markceiling || markfloor) &&
  370. (floorclip[rw_x] <= ceilingclip[rw_x] + 1)) {
  371. solidcol[rw_x] = 1; didsolidcol = 1;
  372. }
  373. // save texturecol for backdrawing of masked mid texture
  374. if (maskedtexture)
  375. maskedtexturecol[rw_x] = texturecolumn;
  376. }
  377. rw_scale += rw_scalestep;
  378. topfrac += topstep;
  379. bottomfrac += bottomstep;
  380. }
  381. }
  382. // killough 5/2/98: move from r_main.c, made static, simplified
  383. static fixed_t R_PointToDist(fixed_t x, fixed_t y)
  384. {
  385. fixed_t dx = D_abs(x - viewx);
  386. fixed_t dy = D_abs(y - viewy);
  387. if (dy > dx)
  388. {
  389. fixed_t t = dx;
  390. dx = dy;
  391. dy = t;
  392. }
  393. return FixedDiv(dx, finesine[(tantoangle[FixedDiv(dy,dx) >> DBITS]
  394. + ANG90) >> ANGLETOFINESHIFT]);
  395. }
  396. //
  397. // R_StoreWallRange
  398. // A wall segment will be drawn
  399. // between start and stop pixels (inclusive).
  400. //
  401. void R_StoreWallRange(const int start, const int stop)
  402. {
  403. fixed_t hyp;
  404. angle_t offsetangle;
  405. if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM
  406. {
  407. unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a
  408. unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough
  409. drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs));
  410. ds_p = drawsegs + pos; // jff 8/9/98 fix from ZDOOM1.14a
  411. maxdrawsegs = newmax;
  412. }
  413. if(curline->miniseg == false) // figgi -- skip minisegs
  414. curline->linedef->flags |= ML_MAPPED;
  415. #ifdef GL_DOOM
  416. if (V_GetMode() == VID_MODEGL)
  417. {
  418. // proff 11/99: the rest of the calculations is not needed for OpenGL
  419. ds_p++->curline = curline;
  420. gld_AddWall(curline);
  421. return;
  422. }
  423. #endif
  424. #ifdef RANGECHECK
  425. if (start >=viewwidth || start > stop)
  426. I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
  427. #endif
  428. sidedef = curline->sidedef;
  429. linedef = curline->linedef;
  430. // mark the segment as visible for auto map
  431. linedef->flags |= ML_MAPPED;
  432. // calculate rw_distance for scale calculation
  433. rw_normalangle = curline->angle + ANG90;
  434. offsetangle = rw_normalangle-rw_angle1;
  435. if (D_abs(offsetangle) > ANG90)
  436. offsetangle = ANG90;
  437. hyp = (viewx==curline->v1->x && viewy==curline->v1->y)?
  438. 0 : R_PointToDist (curline->v1->x, curline->v1->y);
  439. rw_distance = FixedMul(hyp, finecosine[offsetangle>>ANGLETOFINESHIFT]);
  440. ds_p->x1 = rw_x = start;
  441. ds_p->x2 = stop;
  442. ds_p->curline = curline;
  443. rw_stopx = stop+1;
  444. { // killough 1/6/98, 2/1/98: remove limit on openings
  445. extern int *openings; // dropoff overflow
  446. extern size_t maxopenings;
  447. size_t pos = lastopening - openings;
  448. size_t need = (rw_stopx - start)*4 + pos;
  449. if (need > maxopenings)
  450. {
  451. drawseg_t *ds; //jff 8/9/98 needed for fix from ZDoom
  452. int *oldopenings = openings; // dropoff overflow
  453. int *oldlast = lastopening; // dropoff overflow
  454. do
  455. maxopenings = maxopenings ? maxopenings*2 : 16384;
  456. while (need > maxopenings);
  457. openings = realloc(openings, maxopenings * sizeof(*openings));
  458. lastopening = openings + pos;
  459. // jff 8/9/98 borrowed fix for openings from ZDOOM1.14
  460. // [RH] We also need to adjust the openings pointers that
  461. // were already stored in drawsegs.
  462. for (ds = drawsegs; ds < ds_p; ds++)
  463. {
  464. #define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast)\
  465. ds->p = ds->p - oldopenings + openings;
  466. ADJUST (maskedtexturecol);
  467. ADJUST (sprtopclip);
  468. ADJUST (sprbottomclip);
  469. }
  470. #undef ADJUST
  471. }
  472. } // killough: end of code to remove limits on openings
  473. // calculate scale at both ends and step
  474. ds_p->scale1 = rw_scale =
  475. R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
  476. if (stop > start)
  477. {
  478. ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
  479. ds_p->scalestep = rw_scalestep = (ds_p->scale2-rw_scale) / (stop-start);
  480. }
  481. else
  482. ds_p->scale2 = ds_p->scale1;
  483. // calculate texture boundaries
  484. // and decide if floor / ceiling marks are needed
  485. worldtop = frontsector->ceilingheight - viewz;
  486. worldbottom = frontsector->floorheight - viewz;
  487. midtexture = toptexture = bottomtexture = maskedtexture = 0;
  488. ds_p->maskedtexturecol = NULL;
  489. if (!backsector)
  490. {
  491. // single sided line
  492. midtexture = texturetranslation[sidedef->midtexture];
  493. midtexheight = (linedef->r_flags & RF_MID_TILE) ? 0 : textureheight[midtexture] >> FRACBITS;
  494. // a single sided line is terminal, so it must mark ends
  495. markfloor = markceiling = true;
  496. if (linedef->flags & ML_DONTPEGBOTTOM)
  497. { // bottom of texture at bottom
  498. fixed_t vtop = frontsector->floorheight +
  499. textureheight[sidedef->midtexture];
  500. rw_midtexturemid = vtop - viewz;
  501. }
  502. else // top of texture at top
  503. rw_midtexturemid = worldtop;
  504. rw_midtexturemid += FixedMod(sidedef->rowoffset, textureheight[midtexture]);
  505. ds_p->silhouette = SIL_BOTH;
  506. ds_p->sprtopclip = screenheightarray;
  507. ds_p->sprbottomclip = negonearray;
  508. ds_p->bsilheight = INT_MAX;
  509. ds_p->tsilheight = INT_MIN;
  510. }
  511. else // two sided line
  512. {
  513. ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
  514. ds_p->silhouette = 0;
  515. if (linedef->r_flags & RF_CLOSED) { /* cph - closed 2S line e.g. door */
  516. // cph - killough's (outdated) comment follows - this deals with both
  517. // "automap fixes", his and mine
  518. // killough 1/17/98: this test is required if the fix
  519. // for the automap bug (r_bsp.c) is used, or else some
  520. // sprites will be displayed behind closed doors. That
  521. // fix prevents lines behind closed doors with dropoffs
  522. // from being displayed on the automap.
  523. ds_p->silhouette = SIL_BOTH;
  524. ds_p->sprbottomclip = negonearray;
  525. ds_p->bsilheight = INT_MAX;
  526. ds_p->sprtopclip = screenheightarray;
  527. ds_p->tsilheight = INT_MIN;
  528. } else { /* not solid - old code */
  529. if (frontsector->floorheight > backsector->floorheight)
  530. {
  531. ds_p->silhouette = SIL_BOTTOM;
  532. ds_p->bsilheight = frontsector->floorheight;
  533. }
  534. else
  535. if (backsector->floorheight > viewz)
  536. {
  537. ds_p->silhouette = SIL_BOTTOM;
  538. ds_p->bsilheight = INT_MAX;
  539. }
  540. if (frontsector->ceilingheight < backsector->ceilingheight)
  541. {
  542. ds_p->silhouette |= SIL_TOP;
  543. ds_p->tsilheight = frontsector->ceilingheight;
  544. }
  545. else
  546. if (backsector->ceilingheight < viewz)
  547. {
  548. ds_p->silhouette |= SIL_TOP;
  549. ds_p->tsilheight = INT_MIN;
  550. }
  551. }
  552. worldhigh = backsector->ceilingheight - viewz;
  553. worldlow = backsector->floorheight - viewz;
  554. // hack to allow height changes in outdoor areas
  555. if (frontsector->ceilingpic == skyflatnum
  556. && backsector->ceilingpic == skyflatnum)
  557. worldtop = worldhigh;
  558. markfloor = worldlow != worldbottom
  559. || backsector->floorpic != frontsector->floorpic
  560. || backsector->lightlevel != frontsector->lightlevel
  561. // killough 3/7/98: Add checks for (x,y) offsets
  562. || backsector->floor_xoffs != frontsector->floor_xoffs
  563. || backsector->floor_yoffs != frontsector->floor_yoffs
  564. // killough 4/15/98: prevent 2s normals
  565. // from bleeding through deep water
  566. || frontsector->heightsec != -1
  567. // killough 4/17/98: draw floors if different light levels
  568. || backsector->floorlightsec != frontsector->floorlightsec
  569. ;
  570. markceiling = worldhigh != worldtop
  571. || backsector->ceilingpic != frontsector->ceilingpic
  572. || backsector->lightlevel != frontsector->lightlevel
  573. // killough 3/7/98: Add checks for (x,y) offsets
  574. || backsector->ceiling_xoffs != frontsector->ceiling_xoffs
  575. || backsector->ceiling_yoffs != frontsector->ceiling_yoffs
  576. // killough 4/15/98: prevent 2s normals
  577. // from bleeding through fake ceilings
  578. || (frontsector->heightsec != -1 &&
  579. frontsector->ceilingpic!=skyflatnum)
  580. // killough 4/17/98: draw ceilings if different light levels
  581. || backsector->ceilinglightsec != frontsector->ceilinglightsec
  582. ;
  583. if (backsector->ceilingheight <= frontsector->floorheight
  584. || backsector->floorheight >= frontsector->ceilingheight)
  585. markceiling = markfloor = true; // closed door
  586. if (worldhigh < worldtop) // top texture
  587. {
  588. toptexture = texturetranslation[sidedef->toptexture];
  589. toptexheight = (linedef->r_flags & RF_TOP_TILE) ? 0 : textureheight[toptexture] >> FRACBITS;
  590. rw_toptexturemid = linedef->flags & ML_DONTPEGTOP ? worldtop :
  591. backsector->ceilingheight+textureheight[sidedef->toptexture]-viewz;
  592. rw_toptexturemid += FixedMod(sidedef->rowoffset, textureheight[toptexture]);
  593. }
  594. if (worldlow > worldbottom) // bottom texture
  595. {
  596. bottomtexture = texturetranslation[sidedef->bottomtexture];
  597. bottomtexheight = (linedef->r_flags & RF_BOT_TILE) ? 0 : textureheight[bottomtexture] >> FRACBITS;
  598. rw_bottomtexturemid = linedef->flags & ML_DONTPEGBOTTOM ? worldtop :
  599. worldlow;
  600. rw_bottomtexturemid += FixedMod(sidedef->rowoffset, textureheight[bottomtexture]);
  601. }
  602. // allocate space for masked texture tables
  603. if (sidedef->midtexture) // masked midtexture
  604. {
  605. maskedtexture = true;
  606. ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
  607. lastopening += rw_stopx - rw_x;
  608. }
  609. }
  610. // calculate rw_offset (only needed for textured lines)
  611. segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
  612. if (segtextured)
  613. {
  614. rw_offset = FixedMul (hyp, -finesine[offsetangle >>ANGLETOFINESHIFT]);
  615. rw_offset += sidedef->textureoffset + curline->offset;
  616. rw_centerangle = ANG90 + viewangle - rw_normalangle;
  617. rw_lightlevel = frontsector->lightlevel;
  618. }
  619. // Remember the vars used to determine fractional U texture
  620. // coords for later - POPE
  621. ds_p->rw_offset = rw_offset;
  622. ds_p->rw_distance = rw_distance;
  623. ds_p->rw_centerangle = rw_centerangle;
  624. // if a floor / ceiling plane is on the wrong side of the view
  625. // plane, it is definitely invisible and doesn't need to be marked.
  626. // killough 3/7/98: add deep water check
  627. if (frontsector->heightsec == -1)
  628. {
  629. if (frontsector->floorheight >= viewz) // above view plane
  630. markfloor = false;
  631. if (frontsector->ceilingheight <= viewz &&
  632. frontsector->ceilingpic != skyflatnum) // below view plane
  633. markceiling = false;
  634. }
  635. // calculate incremental stepping values for texture edges
  636. worldtop >>= 4;
  637. worldbottom >>= 4;
  638. topstep = -FixedMul (rw_scalestep, worldtop);
  639. topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
  640. bottomstep = -FixedMul (rw_scalestep,worldbottom);
  641. bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
  642. if (backsector)
  643. {
  644. worldhigh >>= 4;
  645. worldlow >>= 4;
  646. if (worldhigh < worldtop)
  647. {
  648. pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
  649. pixhighstep = -FixedMul (rw_scalestep,worldhigh);
  650. }
  651. if (worldlow > worldbottom)
  652. {
  653. pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
  654. pixlowstep = -FixedMul (rw_scalestep,worldlow);
  655. }
  656. }
  657. // render it
  658. if (markceiling) {
  659. if (ceilingplane) // killough 4/11/98: add NULL ptr checks
  660. ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
  661. else
  662. markceiling = 0;
  663. }
  664. if (markfloor) {
  665. if (floorplane) // killough 4/11/98: add NULL ptr checks
  666. /* cph 2003/04/18 - ceilingplane and floorplane might be the same
  667. * visplane (e.g. if both skies); R_CheckPlane doesn't know about
  668. * modifications to the plane that might happen in parallel with the check
  669. * being made, so we have to override it and split them anyway if that is
  670. * a possibility, otherwise the floor marking would overwrite the ceiling
  671. * marking, resulting in HOM. */
  672. if (markceiling && ceilingplane == floorplane)
  673. floorplane = R_DupPlane (floorplane, rw_x, rw_stopx-1);
  674. else
  675. floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
  676. else
  677. markfloor = 0;
  678. }
  679. didsolidcol = 0;
  680. R_RenderSegLoop();
  681. /* cph - if a column was made solid by this wall, we _must_ save full clipping info */
  682. if (backsector && didsolidcol) {
  683. if (!(ds_p->silhouette & SIL_BOTTOM)) {
  684. ds_p->silhouette |= SIL_BOTTOM;
  685. ds_p->bsilheight = backsector->floorheight;
  686. }
  687. if (!(ds_p->silhouette & SIL_TOP)) {
  688. ds_p->silhouette |= SIL_TOP;
  689. ds_p->tsilheight = backsector->ceilingheight;
  690. }
  691. }
  692. // save sprite clipping info
  693. if ((ds_p->silhouette & SIL_TOP || maskedtexture) && !ds_p->sprtopclip)
  694. {
  695. memcpy (lastopening, ceilingclip+start, sizeof(int)*(rw_stopx-start)); // dropoff overflow
  696. ds_p->sprtopclip = lastopening - start;
  697. lastopening += rw_stopx - start;
  698. }
  699. if ((ds_p->silhouette & SIL_BOTTOM || maskedtexture) && !ds_p->sprbottomclip)
  700. {
  701. memcpy (lastopening, floorclip+start, sizeof(int)*(rw_stopx-start)); // dropoff overflow
  702. ds_p->sprbottomclip = lastopening - start;
  703. lastopening += rw_stopx - start;
  704. }
  705. if (maskedtexture && !(ds_p->silhouette & SIL_TOP))
  706. {
  707. ds_p->silhouette |= SIL_TOP;
  708. ds_p->tsilheight = INT_MIN;
  709. }
  710. if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM))
  711. {
  712. ds_p->silhouette |= SIL_BOTTOM;
  713. ds_p->bsilheight = INT_MAX;
  714. }
  715. ds_p++;
  716. }