R_PLANE.C 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. //**************************************************************************
  2. //**
  3. //** r_plane.c : Heretic 2 : Raven Software, Corp.
  4. //**
  5. //** $RCSfile: r_plane.c,v $
  6. //** $Revision: 1.5 $
  7. //** $Date: 95/07/13 15:17:12 $
  8. //** $Author: cjr $
  9. //**
  10. //**************************************************************************
  11. // HEADER FILES ------------------------------------------------------------
  12. #include "h2def.h"
  13. #include "r_local.h"
  14. // MACROS ------------------------------------------------------------------
  15. // TYPES -------------------------------------------------------------------
  16. // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
  17. // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
  18. // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
  19. // EXTERNAL DATA DECLARATIONS ----------------------------------------------
  20. extern fixed_t Sky1ScrollDelta;
  21. extern fixed_t Sky2ScrollDelta;
  22. // PUBLIC DATA DEFINITIONS -------------------------------------------------
  23. int Sky1Texture;
  24. int Sky2Texture;
  25. fixed_t Sky1ColumnOffset;
  26. fixed_t Sky2ColumnOffset;
  27. int skyflatnum;
  28. int skytexturemid;
  29. fixed_t skyiscale;
  30. boolean DoubleSky;
  31. planefunction_t floorfunc, ceilingfunc;
  32. // Opening
  33. visplane_t visplanes[MAXVISPLANES], *lastvisplane;
  34. visplane_t *floorplane, *ceilingplane;
  35. short openings[MAXOPENINGS], *lastopening;
  36. // Clip values are the solid pixel bounding the range.
  37. // floorclip start out SCREENHEIGHT
  38. // ceilingclip starts out -1
  39. short floorclip[SCREENWIDTH];
  40. short ceilingclip[SCREENWIDTH];
  41. // spanstart holds the start of a plane span, initialized to 0
  42. int spanstart[SCREENHEIGHT];
  43. int spanstop[SCREENHEIGHT];
  44. // Texture mapping
  45. lighttable_t **planezlight;
  46. fixed_t planeheight;
  47. fixed_t yslope[SCREENHEIGHT];
  48. fixed_t distscale[SCREENWIDTH];
  49. fixed_t basexscale, baseyscale;
  50. fixed_t cachedheight[SCREENHEIGHT];
  51. fixed_t cacheddistance[SCREENHEIGHT];
  52. fixed_t cachedxstep[SCREENHEIGHT];
  53. fixed_t cachedystep[SCREENHEIGHT];
  54. // PRIVATE DATA DEFINITIONS ------------------------------------------------
  55. // CODE --------------------------------------------------------------------
  56. //==========================================================================
  57. //
  58. // R_InitSky
  59. //
  60. // Called at level load.
  61. //
  62. //==========================================================================
  63. void R_InitSky(int map)
  64. {
  65. Sky1Texture = P_GetMapSky1Texture(map);
  66. Sky2Texture = P_GetMapSky2Texture(map);
  67. Sky1ScrollDelta = P_GetMapSky1ScrollDelta(map);
  68. Sky2ScrollDelta = P_GetMapSky2ScrollDelta(map);
  69. Sky1ColumnOffset = 0;
  70. Sky2ColumnOffset = 0;
  71. DoubleSky = P_GetMapDoubleSky(map);
  72. }
  73. //==========================================================================
  74. //
  75. // R_InitSkyMap
  76. //
  77. // Called whenever the view size changes.
  78. //
  79. //==========================================================================
  80. void R_InitSkyMap(void)
  81. {
  82. skyflatnum = R_FlatNumForName("F_SKY");
  83. skytexturemid = 200*FRACUNIT;
  84. skyiscale = FRACUNIT;
  85. }
  86. //==========================================================================
  87. //
  88. // R_InitPlanes
  89. //
  90. // Called at game startup.
  91. //
  92. //==========================================================================
  93. void R_InitPlanes(void)
  94. {
  95. }
  96. //==========================================================================
  97. //
  98. // R_MapPlane
  99. //
  100. // Globals used: planeheight, ds_source, basexscale, baseyscale,
  101. // viewx, viewy.
  102. //
  103. //==========================================================================
  104. void R_MapPlane(int y, int x1, int x2)
  105. {
  106. angle_t angle;
  107. fixed_t distance, length;
  108. unsigned index;
  109. #ifdef RANGECHECK
  110. if(x2 < x1 || x1 < 0 || x2 >= viewwidth || (unsigned)y > viewheight)
  111. {
  112. I_Error("R_MapPlane: %i, %i at %i", x1, x2, y);
  113. }
  114. #endif
  115. if(planeheight != cachedheight[y])
  116. {
  117. cachedheight[y] = planeheight;
  118. distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]);
  119. ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale);
  120. ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale);
  121. }
  122. else
  123. {
  124. distance = cacheddistance[y];
  125. ds_xstep = cachedxstep[y];
  126. ds_ystep = cachedystep[y];
  127. }
  128. length = FixedMul(distance, distscale[x1]);
  129. angle = (viewangle+xtoviewangle[x1])>>ANGLETOFINESHIFT;
  130. ds_xfrac = viewx+FixedMul(finecosine[angle], length);
  131. ds_yfrac = -viewy-FixedMul(finesine[angle], length);
  132. if(fixedcolormap)
  133. {
  134. ds_colormap = fixedcolormap;
  135. }
  136. else
  137. {
  138. index = distance >> LIGHTZSHIFT;
  139. if(index >= MAXLIGHTZ )
  140. {
  141. index = MAXLIGHTZ-1;
  142. }
  143. ds_colormap = planezlight[index];
  144. }
  145. ds_y = y;
  146. ds_x1 = x1;
  147. ds_x2 = x2;
  148. spanfunc(); // High or low detail
  149. }
  150. //==========================================================================
  151. //
  152. // R_ClearPlanes
  153. //
  154. // Called at the beginning of each frame.
  155. //
  156. //==========================================================================
  157. void R_ClearPlanes(void)
  158. {
  159. int i;
  160. angle_t angle;
  161. // Opening / clipping determination
  162. for(i = 0; i < viewwidth; i++)
  163. {
  164. floorclip[i] = viewheight;
  165. ceilingclip[i] = -1;
  166. }
  167. lastvisplane = visplanes;
  168. lastopening = openings;
  169. // Texture calculation
  170. memset(cachedheight, 0, sizeof(cachedheight));
  171. angle = (viewangle-ANG90)>>ANGLETOFINESHIFT; // left to right mapping
  172. // Scale will be unit scale at SCREENWIDTH/2 distance
  173. basexscale = FixedDiv(finecosine[angle], centerxfrac);
  174. baseyscale = -FixedDiv(finesine[angle], centerxfrac);
  175. }
  176. //==========================================================================
  177. //
  178. // R_FindPlane
  179. //
  180. //==========================================================================
  181. visplane_t *R_FindPlane(fixed_t height, int picnum,
  182. int lightlevel, int special)
  183. {
  184. visplane_t *check;
  185. if(special < 150)
  186. { // Don't let low specials affect search
  187. special = 0;
  188. }
  189. if(picnum == skyflatnum)
  190. { // All skies map together
  191. height = 0;
  192. lightlevel = 0;
  193. }
  194. for(check = visplanes; check < lastvisplane; check++)
  195. {
  196. if(height == check->height
  197. && picnum == check->picnum
  198. && lightlevel == check->lightlevel
  199. && special == check->special)
  200. break;
  201. }
  202. if(check < lastvisplane)
  203. {
  204. return(check);
  205. }
  206. if(lastvisplane-visplanes == MAXVISPLANES)
  207. {
  208. I_Error("R_FindPlane: no more visplanes");
  209. }
  210. lastvisplane++;
  211. check->height = height;
  212. check->picnum = picnum;
  213. check->lightlevel = lightlevel;
  214. check->special = special;
  215. check->minx = SCREENWIDTH;
  216. check->maxx = -1;
  217. memset(check->top, 0xff, sizeof(check->top));
  218. return(check);
  219. }
  220. //==========================================================================
  221. //
  222. // R_CheckPlane
  223. //
  224. //==========================================================================
  225. visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop)
  226. {
  227. int intrl, intrh;
  228. int unionl, unionh;
  229. int x;
  230. if(start < pl->minx)
  231. {
  232. intrl = pl->minx;
  233. unionl = start;
  234. }
  235. else
  236. {
  237. unionl = pl->minx;
  238. intrl = start;
  239. }
  240. if(stop > pl->maxx)
  241. {
  242. intrh = pl->maxx;
  243. unionh = stop;
  244. }
  245. else
  246. {
  247. unionh = pl->maxx;
  248. intrh = stop;
  249. }
  250. for(x = intrl; x <= intrh; x++)
  251. {
  252. if(pl->top[x] != 0xff)
  253. {
  254. break;
  255. }
  256. }
  257. if(x > intrh)
  258. {
  259. pl->minx = unionl;
  260. pl->maxx = unionh;
  261. return pl; // use the same visplane
  262. }
  263. // Make a new visplane
  264. lastvisplane->height = pl->height;
  265. lastvisplane->picnum = pl->picnum;
  266. lastvisplane->lightlevel = pl->lightlevel;
  267. lastvisplane->special = pl->special;
  268. pl = lastvisplane++;
  269. pl->minx = start;
  270. pl->maxx = stop;
  271. memset(pl->top, 0xff, sizeof(pl->top));
  272. return pl;
  273. }
  274. //==========================================================================
  275. //
  276. // R_MakeSpans
  277. //
  278. //==========================================================================
  279. void R_MakeSpans(int x, int t1, int b1, int t2, int b2)
  280. {
  281. while(t1 < t2 && t1 <= b1)
  282. {
  283. R_MapPlane(t1, spanstart[t1], x-1);
  284. t1++;
  285. }
  286. while(b1 > b2 && b1 >= t1)
  287. {
  288. R_MapPlane(b1, spanstart[b1], x-1);
  289. b1--;
  290. }
  291. while(t2 < t1 && t2 <= b2)
  292. {
  293. spanstart[t2] = x;
  294. t2++;
  295. }
  296. while(b2 > b1 && b2 >= t2)
  297. {
  298. spanstart[b2] = x;
  299. b2--;
  300. }
  301. }
  302. //==========================================================================
  303. //
  304. // R_DrawPlanes
  305. //
  306. //==========================================================================
  307. #define SKYTEXTUREMIDSHIFTED 200
  308. void R_DrawPlanes(void)
  309. {
  310. visplane_t *pl;
  311. int light;
  312. int x, stop;
  313. int angle;
  314. byte *tempSource;
  315. byte *source;
  316. byte *source2;
  317. byte *dest;
  318. int count;
  319. int offset;
  320. int skyTexture;
  321. int offset2;
  322. int skyTexture2;
  323. int scrollOffset;
  324. extern byte *ylookup[MAXHEIGHT];
  325. extern int columnofs[MAXWIDTH];
  326. #ifdef RANGECHECK
  327. if(ds_p-drawsegs > MAXDRAWSEGS)
  328. {
  329. I_Error("R_DrawPlanes: drawsegs overflow (%i)", ds_p-drawsegs);
  330. }
  331. if(lastvisplane-visplanes > MAXVISPLANES)
  332. {
  333. I_Error("R_DrawPlanes: visplane overflow (%i)",
  334. lastvisplane-visplanes);
  335. }
  336. if(lastopening-openings > MAXOPENINGS)
  337. {
  338. I_Error("R_DrawPlanes: opening overflow (%i)",
  339. lastopening-openings);
  340. }
  341. #endif
  342. for(pl = visplanes; pl < lastvisplane; pl++)
  343. {
  344. if(pl->minx > pl->maxx)
  345. {
  346. continue;
  347. }
  348. if(pl->picnum == skyflatnum)
  349. { // Sky flat
  350. if(DoubleSky)
  351. { // Render 2 layers, sky 1 in front
  352. offset = Sky1ColumnOffset>>16;
  353. skyTexture = texturetranslation[Sky1Texture];
  354. offset2 = Sky2ColumnOffset>>16;
  355. skyTexture2 = texturetranslation[Sky2Texture];
  356. for(x = pl->minx; x <= pl->maxx; x++)
  357. {
  358. dc_yl = pl->top[x];
  359. dc_yh = pl->bottom[x];
  360. if(dc_yl <= dc_yh)
  361. {
  362. count = dc_yh-dc_yl;
  363. if(count < 0)
  364. {
  365. return;
  366. }
  367. angle = (viewangle+xtoviewangle[x])
  368. >>ANGLETOSKYSHIFT;
  369. source = R_GetColumn(skyTexture, angle+offset)
  370. +SKYTEXTUREMIDSHIFTED+(dc_yl-centery);
  371. source2 = R_GetColumn(skyTexture2, angle+offset2)
  372. +SKYTEXTUREMIDSHIFTED+(dc_yl-centery);
  373. dest = ylookup[dc_yl]+columnofs[x];
  374. do
  375. {
  376. if(*source)
  377. {
  378. *dest = *source++;
  379. source2++;
  380. }
  381. else
  382. {
  383. *dest = *source2++;
  384. source++;
  385. }
  386. dest += SCREENWIDTH;
  387. } while(count--);
  388. }
  389. }
  390. continue; // Next visplane
  391. }
  392. else
  393. { // Render single layer
  394. if(pl->special == 200)
  395. { // Use sky 2
  396. offset = Sky2ColumnOffset>>16;
  397. skyTexture = texturetranslation[Sky2Texture];
  398. }
  399. else
  400. { // Use sky 1
  401. offset = Sky1ColumnOffset>>16;
  402. skyTexture = texturetranslation[Sky1Texture];
  403. }
  404. for(x = pl->minx; x <= pl->maxx; x++)
  405. {
  406. dc_yl = pl->top[x];
  407. dc_yh = pl->bottom[x];
  408. if(dc_yl <= dc_yh)
  409. {
  410. count = dc_yh-dc_yl;
  411. if(count < 0)
  412. {
  413. return;
  414. }
  415. angle = (viewangle+xtoviewangle[x])
  416. >>ANGLETOSKYSHIFT;
  417. source = R_GetColumn(skyTexture, angle+offset)
  418. +SKYTEXTUREMIDSHIFTED+(dc_yl-centery);
  419. dest = ylookup[dc_yl]+columnofs[x];
  420. do
  421. {
  422. *dest = *source++;
  423. dest += SCREENWIDTH;
  424. } while(count--);
  425. }
  426. }
  427. continue; // Next visplane
  428. }
  429. }
  430. // Regular flat
  431. tempSource = W_CacheLumpNum(firstflat+
  432. flattranslation[pl->picnum], PU_STATIC);
  433. scrollOffset = leveltime>>1&63;
  434. switch(pl->special)
  435. { // Handle scrolling flats
  436. case 201: case 202: case 203: // Scroll_North_xxx
  437. ds_source = tempSource+((scrollOffset
  438. <<(pl->special-201)&63)<<6);
  439. break;
  440. case 204: case 205: case 206: // Scroll_East_xxx
  441. ds_source = tempSource+((63-scrollOffset)
  442. <<(pl->special-204)&63);
  443. break;
  444. case 207: case 208: case 209: // Scroll_South_xxx
  445. ds_source = tempSource+(((63-scrollOffset)
  446. <<(pl->special-207)&63)<<6);
  447. break;
  448. case 210: case 211: case 212: // Scroll_West_xxx
  449. ds_source = tempSource+(scrollOffset
  450. <<(pl->special-210)&63);
  451. break;
  452. case 213: case 214: case 215: // Scroll_NorthWest_xxx
  453. ds_source = tempSource+(scrollOffset
  454. <<(pl->special-213)&63)+((scrollOffset
  455. <<(pl->special-213)&63)<<6);
  456. break;
  457. case 216: case 217: case 218: // Scroll_NorthEast_xxx
  458. ds_source = tempSource+((63-scrollOffset)
  459. <<(pl->special-216)&63)+((scrollOffset
  460. <<(pl->special-216)&63)<<6);
  461. break;
  462. case 219: case 220: case 221: // Scroll_SouthEast_xxx
  463. ds_source = tempSource+((63-scrollOffset)
  464. <<(pl->special-219)&63)+(((63-scrollOffset)
  465. <<(pl->special-219)&63)<<6);
  466. break;
  467. case 222: case 223: case 224: // Scroll_SouthWest_xxx
  468. ds_source = tempSource+(scrollOffset
  469. <<(pl->special-222)&63)+(((63-scrollOffset)
  470. <<(pl->special-222)&63)<<6);
  471. break;
  472. default:
  473. ds_source = tempSource;
  474. break;
  475. }
  476. planeheight = abs(pl->height-viewz);
  477. light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight;
  478. if(light >= LIGHTLEVELS)
  479. {
  480. light = LIGHTLEVELS-1;
  481. }
  482. if(light < 0)
  483. {
  484. light = 0;
  485. }
  486. planezlight = zlight[light];
  487. pl->top[pl->maxx+1] = 0xff;
  488. pl->top[pl->minx-1] = 0xff;
  489. stop = pl->maxx+1;
  490. for(x = pl->minx; x <= stop; x++)
  491. {
  492. R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1],
  493. pl->top[x], pl->bottom[x]);
  494. }
  495. Z_ChangeTag(tempSource, PU_CACHE);
  496. }
  497. }