R_SEGS.C 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. //**************************************************************************
  2. //**
  3. //** R_SEGS.C
  4. //**
  5. //** This version has the tall-sector-crossing-precision-bug fixed.
  6. //**
  7. //**************************************************************************
  8. #include "DoomDef.h"
  9. #include "R_local.h"
  10. // OPTIMIZE: closed two sided lines as single sided
  11. boolean segtextured; // true if any of the segs textures might be vis
  12. boolean markfloor; // false if the back side is the same plane
  13. boolean markceiling;
  14. boolean maskedtexture;
  15. int toptexture, bottomtexture, midtexture;
  16. angle_t rw_normalangle;
  17. int rw_angle1; // angle to line origin
  18. //
  19. // wall
  20. //
  21. int rw_x;
  22. int rw_stopx;
  23. angle_t rw_centerangle;
  24. fixed_t rw_offset;
  25. fixed_t rw_distance;
  26. fixed_t rw_scale;
  27. fixed_t rw_scalestep;
  28. fixed_t rw_midtexturemid;
  29. fixed_t rw_toptexturemid;
  30. fixed_t rw_bottomtexturemid;
  31. int worldtop, worldbottom, worldhigh, worldlow;
  32. fixed_t pixhigh, pixlow;
  33. fixed_t pixhighstep, pixlowstep;
  34. fixed_t topfrac, topstep;
  35. fixed_t bottomfrac, bottomstep;
  36. lighttable_t **walllights;
  37. short *maskedtexturecol;
  38. /*
  39. ================
  40. =
  41. = R_RenderMaskedSegRange
  42. =
  43. ================
  44. */
  45. void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
  46. {
  47. unsigned index;
  48. column_t *col;
  49. int lightnum;
  50. int texnum;
  51. //
  52. // calculate light table
  53. // use different light tables for horizontal / vertical / diagonal
  54. // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
  55. curline = ds->curline;
  56. frontsector = curline->frontsector;
  57. backsector = curline->backsector;
  58. texnum = texturetranslation[curline->sidedef->midtexture];
  59. lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
  60. if (curline->v1->y == curline->v2->y)
  61. lightnum--;
  62. else if (curline->v1->x == curline->v2->x)
  63. lightnum++;
  64. if (lightnum < 0)
  65. walllights = scalelight[0];
  66. else if (lightnum >= LIGHTLEVELS)
  67. walllights = scalelight[LIGHTLEVELS-1];
  68. else
  69. walllights = scalelight[lightnum];
  70. maskedtexturecol = ds->maskedtexturecol;
  71. rw_scalestep = ds->scalestep;
  72. spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
  73. mfloorclip = ds->sprbottomclip;
  74. mceilingclip = ds->sprtopclip;
  75. //
  76. // find positioning
  77. //
  78. if (curline->linedef->flags & ML_DONTPEGBOTTOM)
  79. {
  80. dc_texturemid = frontsector->floorheight > backsector->floorheight
  81. ? frontsector->floorheight : backsector->floorheight;
  82. dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
  83. }
  84. else
  85. {
  86. dc_texturemid =frontsector->ceilingheight<backsector->ceilingheight
  87. ? frontsector->ceilingheight : backsector->ceilingheight;
  88. dc_texturemid = dc_texturemid - viewz;
  89. }
  90. dc_texturemid += curline->sidedef->rowoffset;
  91. if (fixedcolormap)
  92. dc_colormap = fixedcolormap;
  93. //
  94. // draw the columns
  95. //
  96. for (dc_x = x1 ; dc_x <= x2 ; dc_x++)
  97. {
  98. // calculate lighting
  99. if (maskedtexturecol[dc_x] != MAXSHORT)
  100. {
  101. if (!fixedcolormap)
  102. {
  103. index = spryscale>>LIGHTSCALESHIFT;
  104. if (index >= MAXLIGHTSCALE )
  105. index = MAXLIGHTSCALE-1;
  106. dc_colormap = walllights[index];
  107. }
  108. sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
  109. dc_iscale = 0xffffffffu / (unsigned)spryscale;
  110. //
  111. // draw the texture
  112. //
  113. col = (column_t *)(
  114. (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
  115. R_DrawMaskedColumn (col, -1);
  116. maskedtexturecol[dc_x] = MAXSHORT;
  117. }
  118. spryscale += rw_scalestep;
  119. }
  120. }
  121. /*
  122. ================
  123. =
  124. = R_RenderSegLoop
  125. =
  126. = Draws zero, one, or two textures (and possibly a masked texture) for walls
  127. = Can draw or mark the starting pixel of floor and ceiling textures
  128. =
  129. = CALLED: CORE LOOPING ROUTINE
  130. ================
  131. */
  132. #define HEIGHTBITS 12
  133. #define HEIGHTUNIT (1<<HEIGHTBITS)
  134. void R_RenderSegLoop (void)
  135. {
  136. angle_t angle;
  137. unsigned index;
  138. int yl, yh, mid;
  139. fixed_t texturecolumn;
  140. int top, bottom;
  141. // texturecolumn = 0; // shut up compiler warning
  142. for ( ; rw_x < rw_stopx ; rw_x++)
  143. {
  144. //
  145. // mark floor / ceiling areas
  146. //
  147. yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
  148. if (yl < ceilingclip[rw_x]+1)
  149. yl = ceilingclip[rw_x]+1; // no space above wall
  150. if (markceiling)
  151. {
  152. top = ceilingclip[rw_x]+1;
  153. bottom = yl-1;
  154. if (bottom >= floorclip[rw_x])
  155. bottom = floorclip[rw_x]-1;
  156. if (top <= bottom)
  157. {
  158. ceilingplane->top[rw_x] = top;
  159. ceilingplane->bottom[rw_x] = bottom;
  160. }
  161. }
  162. yh = bottomfrac>>HEIGHTBITS;
  163. if (yh >= floorclip[rw_x])
  164. yh = floorclip[rw_x]-1;
  165. if (markfloor)
  166. {
  167. top = yh+1;
  168. bottom = floorclip[rw_x]-1;
  169. if (top <= ceilingclip[rw_x])
  170. top = ceilingclip[rw_x]+1;
  171. if (top <= bottom)
  172. {
  173. floorplane->top[rw_x] = top;
  174. floorplane->bottom[rw_x] = bottom;
  175. }
  176. }
  177. //
  178. // texturecolumn and lighting are independent of wall tiers
  179. //
  180. if (segtextured)
  181. {
  182. // calculate texture offset
  183. angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
  184. texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
  185. texturecolumn >>= FRACBITS;
  186. // calculate lighting
  187. index = rw_scale>>LIGHTSCALESHIFT;
  188. if (index >= MAXLIGHTSCALE )
  189. index = MAXLIGHTSCALE-1;
  190. dc_colormap = walllights[index];
  191. dc_x = rw_x;
  192. dc_iscale = 0xffffffffu / (unsigned)rw_scale;
  193. }
  194. //
  195. // draw the wall tiers
  196. //
  197. if (midtexture)
  198. { // single sided line
  199. dc_yl = yl;
  200. dc_yh = yh;
  201. dc_texturemid = rw_midtexturemid;
  202. dc_source = R_GetColumn(midtexture,texturecolumn);
  203. colfunc ();
  204. ceilingclip[rw_x] = viewheight;
  205. floorclip[rw_x] = -1;
  206. }
  207. else
  208. { // two sided line
  209. if (toptexture)
  210. { // top wall
  211. mid = pixhigh>>HEIGHTBITS;
  212. pixhigh += pixhighstep;
  213. if (mid >= floorclip[rw_x])
  214. mid = floorclip[rw_x]-1;
  215. if (mid >= yl)
  216. {
  217. dc_yl = yl;
  218. dc_yh = mid;
  219. dc_texturemid = rw_toptexturemid;
  220. dc_source = R_GetColumn(toptexture,texturecolumn);
  221. colfunc ();
  222. ceilingclip[rw_x] = mid;
  223. }
  224. else
  225. ceilingclip[rw_x] = yl-1;
  226. }
  227. else
  228. { // no top wall
  229. if (markceiling)
  230. ceilingclip[rw_x] = yl-1;
  231. }
  232. if (bottomtexture)
  233. { // bottom wall
  234. mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
  235. pixlow += pixlowstep;
  236. if (mid <= ceilingclip[rw_x])
  237. mid = ceilingclip[rw_x]+1; // no space above wall
  238. if (mid <= yh)
  239. {
  240. dc_yl = mid;
  241. dc_yh = yh;
  242. dc_texturemid = rw_bottomtexturemid;
  243. dc_source = R_GetColumn(bottomtexture,
  244. texturecolumn);
  245. colfunc ();
  246. floorclip[rw_x] = mid;
  247. }
  248. else
  249. floorclip[rw_x] = yh+1;
  250. }
  251. else
  252. { // no bottom wall
  253. if (markfloor)
  254. floorclip[rw_x] = yh+1;
  255. }
  256. if (maskedtexture)
  257. { // save texturecol for backdrawing of masked mid texture
  258. maskedtexturecol[rw_x] = texturecolumn;
  259. }
  260. }
  261. rw_scale += rw_scalestep;
  262. topfrac += topstep;
  263. bottomfrac += bottomstep;
  264. }
  265. }
  266. /*
  267. =====================
  268. =
  269. = R_StoreWallRange
  270. =
  271. = A wall segment will be drawn between start and stop pixels (inclusive)
  272. =
  273. ======================
  274. */
  275. void R_StoreWallRange (int start, int stop)
  276. {
  277. fixed_t hyp;
  278. fixed_t sineval;
  279. angle_t distangle, offsetangle;
  280. fixed_t vtop;
  281. int lightnum;
  282. if (ds_p == &drawsegs[MAXDRAWSEGS])
  283. return; // don't overflow and crash
  284. #ifdef RANGECHECK
  285. if (start >=viewwidth || start > stop)
  286. I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
  287. #endif
  288. #ifdef __NeXT__
  289. RD_DrawLine (curline);
  290. #endif
  291. sidedef = curline->sidedef;
  292. linedef = curline->linedef;
  293. // mark the segment as visible for auto map
  294. linedef->flags |= ML_MAPPED;
  295. //
  296. // calculate rw_distance for scale calculation
  297. //
  298. rw_normalangle = curline->angle + ANG90;
  299. offsetangle = abs(rw_normalangle-rw_angle1);
  300. if (offsetangle > ANG90)
  301. offsetangle = ANG90;
  302. distangle = ANG90 - offsetangle;
  303. hyp = R_PointToDist (curline->v1->x, curline->v1->y);
  304. sineval = finesine[distangle>>ANGLETOFINESHIFT];
  305. rw_distance = FixedMul (hyp, sineval);
  306. ds_p->x1 = rw_x = start;
  307. ds_p->x2 = stop;
  308. ds_p->curline = curline;
  309. rw_stopx = stop+1;
  310. //
  311. // calculate scale at both ends and step
  312. //
  313. ds_p->scale1 = rw_scale =
  314. R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
  315. if (stop > start )
  316. {
  317. ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
  318. ds_p->scalestep = rw_scalestep =
  319. (ds_p->scale2 - rw_scale) / (stop-start);
  320. }
  321. else
  322. {
  323. //
  324. // try to fix the stretched line bug
  325. //
  326. #if 0
  327. if (rw_distance < FRACUNIT/2)
  328. {
  329. fixed_t trx,try;
  330. fixed_t gxt,gyt;
  331. trx = curline->v1->x - viewx;
  332. try = curline->v1->y - viewy;
  333. gxt = FixedMul(trx,viewcos);
  334. gyt = -FixedMul(try,viewsin);
  335. ds_p->scale1 = FixedDiv(projection, gxt-gyt);
  336. }
  337. #endif
  338. ds_p->scale2 = ds_p->scale1;
  339. }
  340. //
  341. // calculate texture boundaries and decide if floor / ceiling marks
  342. // are needed
  343. //
  344. worldtop = frontsector->ceilingheight - viewz;
  345. worldbottom = frontsector->floorheight - viewz;
  346. midtexture = toptexture = bottomtexture = maskedtexture = 0;
  347. ds_p->maskedtexturecol = NULL;
  348. if (!backsector)
  349. {
  350. //
  351. // single sided line
  352. //
  353. midtexture = texturetranslation[sidedef->midtexture];
  354. // a single sided line is terminal, so it must mark ends
  355. markfloor = markceiling = true;
  356. if (linedef->flags & ML_DONTPEGBOTTOM)
  357. {
  358. vtop = frontsector->floorheight +
  359. textureheight[sidedef->midtexture];
  360. rw_midtexturemid = vtop - viewz; // bottom of texture at bottom
  361. }
  362. else
  363. rw_midtexturemid = worldtop; // top of texture at top
  364. rw_midtexturemid += sidedef->rowoffset;
  365. ds_p->silhouette = SIL_BOTH;
  366. ds_p->sprtopclip = screenheightarray;
  367. ds_p->sprbottomclip = negonearray;
  368. ds_p->bsilheight = MAXINT;
  369. ds_p->tsilheight = MININT;
  370. }
  371. else
  372. {
  373. //
  374. // two sided line
  375. //
  376. ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
  377. ds_p->silhouette = 0;
  378. if (frontsector->floorheight > backsector->floorheight)
  379. {
  380. ds_p->silhouette = SIL_BOTTOM;
  381. ds_p->bsilheight = frontsector->floorheight;
  382. }
  383. else if (backsector->floorheight > viewz)
  384. {
  385. ds_p->silhouette = SIL_BOTTOM;
  386. ds_p->bsilheight = MAXINT;
  387. // ds_p->sprbottomclip = negonearray;
  388. }
  389. if (frontsector->ceilingheight < backsector->ceilingheight)
  390. {
  391. ds_p->silhouette |= SIL_TOP;
  392. ds_p->tsilheight = frontsector->ceilingheight;
  393. }
  394. else if (backsector->ceilingheight < viewz)
  395. {
  396. ds_p->silhouette |= SIL_TOP;
  397. ds_p->tsilheight = MININT;
  398. // ds_p->sprtopclip = screenheightarray;
  399. }
  400. if (backsector->ceilingheight <= frontsector->floorheight)
  401. {
  402. ds_p->sprbottomclip = negonearray;
  403. ds_p->bsilheight = MAXINT;
  404. ds_p->silhouette |= SIL_BOTTOM;
  405. }
  406. if (backsector->floorheight >= frontsector->ceilingheight)
  407. {
  408. ds_p->sprtopclip = screenheightarray;
  409. ds_p->tsilheight = MININT;
  410. ds_p->silhouette |= SIL_TOP;
  411. }
  412. worldhigh = backsector->ceilingheight - viewz;
  413. worldlow = backsector->floorheight - viewz;
  414. // hack to allow height changes in outdoor areas
  415. if (frontsector->ceilingpic == skyflatnum
  416. && backsector->ceilingpic == skyflatnum)
  417. worldtop = worldhigh;
  418. if (worldlow != worldbottom
  419. || backsector->floorpic != frontsector->floorpic
  420. || backsector->lightlevel != frontsector->lightlevel)
  421. markfloor = true;
  422. else
  423. markfloor = false; // same plane on both sides
  424. if (worldhigh != worldtop
  425. || backsector->ceilingpic != frontsector->ceilingpic
  426. || backsector->lightlevel != frontsector->lightlevel)
  427. markceiling = true;
  428. else
  429. markceiling = false; // same plane on both sides
  430. if (backsector->ceilingheight <= frontsector->floorheight
  431. || backsector->floorheight >= frontsector->ceilingheight)
  432. markceiling = markfloor = true; // closed door
  433. if (worldhigh < worldtop)
  434. { // top texture
  435. toptexture = texturetranslation[sidedef->toptexture];
  436. if (linedef->flags & ML_DONTPEGTOP)
  437. rw_toptexturemid = worldtop; // top of texture at top
  438. else
  439. {
  440. vtop = backsector->ceilingheight +
  441. textureheight[sidedef->toptexture];
  442. rw_toptexturemid = vtop - viewz; // bottom of texture
  443. }
  444. }
  445. if (worldlow > worldbottom)
  446. { // bottom texture
  447. bottomtexture = texturetranslation[sidedef->bottomtexture];
  448. if (linedef->flags & ML_DONTPEGBOTTOM )
  449. { // bottom of texture at bottom
  450. rw_bottomtexturemid = worldtop;// top of texture at top
  451. }
  452. else // top of texture at top
  453. rw_bottomtexturemid = worldlow;
  454. }
  455. rw_toptexturemid += sidedef->rowoffset;
  456. rw_bottomtexturemid += sidedef->rowoffset;
  457. //
  458. // allocate space for masked texture tables
  459. //
  460. if (sidedef->midtexture)
  461. { // masked midtexture
  462. maskedtexture = true;
  463. ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
  464. lastopening += rw_stopx - rw_x;
  465. }
  466. }
  467. //
  468. // calculate rw_offset (only needed for textured lines)
  469. //
  470. segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
  471. if (segtextured)
  472. {
  473. offsetangle = rw_normalangle-rw_angle1;
  474. if (offsetangle > ANG180)
  475. offsetangle = -offsetangle;
  476. if (offsetangle > ANG90)
  477. offsetangle = ANG90;
  478. sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
  479. rw_offset = FixedMul (hyp, sineval);
  480. if (rw_normalangle-rw_angle1 < ANG180)
  481. rw_offset = -rw_offset;
  482. rw_offset += sidedef->textureoffset + curline->offset;
  483. rw_centerangle = ANG90 + viewangle - rw_normalangle;
  484. //
  485. // calculate light table
  486. // use different light tables for horizontal / vertical / diagonal
  487. // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
  488. if (!fixedcolormap)
  489. {
  490. lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
  491. if (curline->v1->y == curline->v2->y)
  492. lightnum--;
  493. else if (curline->v1->x == curline->v2->x)
  494. lightnum++;
  495. if (lightnum < 0)
  496. walllights = scalelight[0];
  497. else if (lightnum >= LIGHTLEVELS)
  498. walllights = scalelight[LIGHTLEVELS-1];
  499. else
  500. walllights = scalelight[lightnum];
  501. }
  502. }
  503. //
  504. // if a floor / ceiling plane is on the wrong side of the view plane
  505. // it is definately invisible and doesn't need to be marked
  506. //
  507. if (frontsector->floorheight >= viewz)
  508. markfloor = false; // above view plane
  509. if (frontsector->ceilingheight <= viewz
  510. && frontsector->ceilingpic != skyflatnum)
  511. markceiling = false; // below view plane
  512. //
  513. // calculate incremental stepping values for texture edges
  514. //
  515. worldtop >>= 4;
  516. worldbottom >>= 4;
  517. topstep = -FixedMul (rw_scalestep, worldtop);
  518. topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
  519. bottomstep = -FixedMul (rw_scalestep,worldbottom);
  520. bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
  521. if (backsector)
  522. {
  523. worldhigh >>= 4;
  524. worldlow >>= 4;
  525. if (worldhigh < worldtop)
  526. {
  527. pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
  528. pixhighstep = -FixedMul (rw_scalestep,worldhigh);
  529. }
  530. if (worldlow > worldbottom)
  531. {
  532. pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
  533. pixlowstep = -FixedMul (rw_scalestep,worldlow);
  534. }
  535. }
  536. //
  537. // render it
  538. //
  539. if (markceiling)
  540. ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
  541. if (markfloor)
  542. floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
  543. R_RenderSegLoop ();
  544. //
  545. // save sprite clipping info
  546. //
  547. if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
  548. {
  549. memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
  550. ds_p->sprtopclip = lastopening - start;
  551. lastopening += rw_stopx - start;
  552. }
  553. if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
  554. {
  555. memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
  556. ds_p->sprbottomclip = lastopening - start;
  557. lastopening += rw_stopx - start;
  558. }
  559. if (maskedtexture && !(ds_p->silhouette&SIL_TOP))
  560. {
  561. ds_p->silhouette |= SIL_TOP;
  562. ds_p->tsilheight = MININT;
  563. }
  564. if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
  565. {
  566. ds_p->silhouette |= SIL_BOTTOM;
  567. ds_p->bsilheight = MAXINT;
  568. }
  569. ds_p++;
  570. }