r_plane.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. // Emacs style mode select -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // Here is a core component: drawing the floors and ceilings,
  21. // while maintaining a per column clipping list only.
  22. // Moreover, the sky areas have to be determined.
  23. //
  24. //-----------------------------------------------------------------------------
  25. static const char
  26. rcsid[] = "$Id: r_plane.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";
  27. #include <stdlib.h>
  28. #include "i_system.h"
  29. #include "z_zone.h"
  30. #include "w_wad.h"
  31. #include "doomdef.h"
  32. #include "doomstat.h"
  33. #include "r_local.h"
  34. #include "r_sky.h"
  35. planefunction_t floorfunc;
  36. planefunction_t ceilingfunc;
  37. //
  38. // opening
  39. //
  40. // Here comes the obnoxious "visplane".
  41. #define MAXVISPLANES 128
  42. visplane_t visplanes[MAXVISPLANES];
  43. visplane_t* lastvisplane;
  44. visplane_t* floorplane;
  45. visplane_t* ceilingplane;
  46. // ?
  47. #define MAXOPENINGS SCREENWIDTH*64
  48. short openings[MAXOPENINGS];
  49. short* lastopening;
  50. //
  51. // Clip values are the solid pixel bounding the range.
  52. // floorclip starts out SCREENHEIGHT
  53. // ceilingclip starts out -1
  54. //
  55. short floorclip[SCREENWIDTH];
  56. short ceilingclip[SCREENWIDTH];
  57. //
  58. // spanstart holds the start of a plane span
  59. // initialized to 0 at start
  60. //
  61. int spanstart[SCREENHEIGHT];
  62. int spanstop[SCREENHEIGHT];
  63. //
  64. // texture mapping
  65. //
  66. lighttable_t** planezlight;
  67. fixed_t planeheight;
  68. fixed_t yslope[SCREENHEIGHT];
  69. fixed_t distscale[SCREENWIDTH];
  70. fixed_t basexscale;
  71. fixed_t baseyscale;
  72. fixed_t cachedheight[SCREENHEIGHT];
  73. fixed_t cacheddistance[SCREENHEIGHT];
  74. fixed_t cachedxstep[SCREENHEIGHT];
  75. fixed_t cachedystep[SCREENHEIGHT];
  76. //
  77. // R_InitPlanes
  78. // Only at game startup.
  79. //
  80. void R_InitPlanes (void)
  81. {
  82. // Doh!
  83. }
  84. //
  85. // R_MapPlane
  86. //
  87. // Uses global vars:
  88. // planeheight
  89. // ds_source
  90. // basexscale
  91. // baseyscale
  92. // viewx
  93. // viewy
  94. //
  95. // BASIC PRIMITIVE
  96. //
  97. void
  98. R_MapPlane
  99. ( int y,
  100. int x1,
  101. int x2 )
  102. {
  103. angle_t angle;
  104. fixed_t distance;
  105. fixed_t length;
  106. unsigned index;
  107. #ifdef RANGECHECK
  108. if (x2 < x1
  109. || x1<0
  110. || x2>=viewwidth
  111. || (unsigned)y>viewheight)
  112. {
  113. I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
  114. }
  115. #endif
  116. if (planeheight != cachedheight[y])
  117. {
  118. cachedheight[y] = planeheight;
  119. distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
  120. ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale);
  121. ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale);
  122. }
  123. else
  124. {
  125. distance = cacheddistance[y];
  126. ds_xstep = cachedxstep[y];
  127. ds_ystep = cachedystep[y];
  128. }
  129. length = FixedMul (distance,distscale[x1]);
  130. angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
  131. ds_xfrac = viewx + FixedMul(finecosine[angle], length);
  132. ds_yfrac = -viewy - FixedMul(finesine[angle], length);
  133. if (fixedcolormap)
  134. ds_colormap = fixedcolormap;
  135. else
  136. {
  137. index = distance >> LIGHTZSHIFT;
  138. if (index >= MAXLIGHTZ )
  139. index = MAXLIGHTZ-1;
  140. ds_colormap = planezlight[index];
  141. }
  142. ds_y = y;
  143. ds_x1 = x1;
  144. ds_x2 = x2;
  145. // high or low detail
  146. spanfunc ();
  147. }
  148. //
  149. // R_ClearPlanes
  150. // At begining of frame.
  151. //
  152. void R_ClearPlanes (void)
  153. {
  154. int i;
  155. angle_t angle;
  156. // opening / clipping determination
  157. for (i=0 ; i<viewwidth ; i++)
  158. {
  159. floorclip[i] = viewheight;
  160. ceilingclip[i] = -1;
  161. }
  162. lastvisplane = visplanes;
  163. lastopening = openings;
  164. // texture calculation
  165. memset (cachedheight, 0, sizeof(cachedheight));
  166. // left to right mapping
  167. angle = (viewangle-ANG90)>>ANGLETOFINESHIFT;
  168. // scale will be unit scale at SCREENWIDTH/2 distance
  169. basexscale = FixedDiv (finecosine[angle],centerxfrac);
  170. baseyscale = -FixedDiv (finesine[angle],centerxfrac);
  171. }
  172. //
  173. // R_FindPlane
  174. //
  175. visplane_t*
  176. R_FindPlane
  177. ( fixed_t height,
  178. int picnum,
  179. int lightlevel )
  180. {
  181. visplane_t* check;
  182. if (picnum == skyflatnum)
  183. {
  184. height = 0; // all skys map together
  185. lightlevel = 0;
  186. }
  187. for (check=visplanes; check<lastvisplane; check++)
  188. {
  189. if (height == check->height
  190. && picnum == check->picnum
  191. && lightlevel == check->lightlevel)
  192. {
  193. break;
  194. }
  195. }
  196. if (check < lastvisplane)
  197. return check;
  198. if (lastvisplane - visplanes == MAXVISPLANES)
  199. I_Error ("R_FindPlane: no more visplanes");
  200. lastvisplane++;
  201. check->height = height;
  202. check->picnum = picnum;
  203. check->lightlevel = lightlevel;
  204. check->minx = SCREENWIDTH;
  205. check->maxx = -1;
  206. memset (check->top,0xff,sizeof(check->top));
  207. return check;
  208. }
  209. //
  210. // R_CheckPlane
  211. //
  212. visplane_t*
  213. R_CheckPlane
  214. ( visplane_t* pl,
  215. int start,
  216. int stop )
  217. {
  218. int intrl;
  219. int intrh;
  220. int unionl;
  221. int unionh;
  222. int x;
  223. if (start < pl->minx)
  224. {
  225. intrl = pl->minx;
  226. unionl = start;
  227. }
  228. else
  229. {
  230. unionl = pl->minx;
  231. intrl = start;
  232. }
  233. if (stop > pl->maxx)
  234. {
  235. intrh = pl->maxx;
  236. unionh = stop;
  237. }
  238. else
  239. {
  240. unionh = pl->maxx;
  241. intrh = stop;
  242. }
  243. for (x=intrl ; x<= intrh ; x++)
  244. if (pl->top[x] != 0xff)
  245. break;
  246. if (x > intrh)
  247. {
  248. pl->minx = unionl;
  249. pl->maxx = unionh;
  250. // use the same one
  251. return pl;
  252. }
  253. // make a new visplane
  254. lastvisplane->height = pl->height;
  255. lastvisplane->picnum = pl->picnum;
  256. lastvisplane->lightlevel = pl->lightlevel;
  257. pl = lastvisplane++;
  258. pl->minx = start;
  259. pl->maxx = stop;
  260. memset (pl->top,0xff,sizeof(pl->top));
  261. return pl;
  262. }
  263. //
  264. // R_MakeSpans
  265. //
  266. void
  267. R_MakeSpans
  268. ( int x,
  269. int t1,
  270. int b1,
  271. int t2,
  272. int b2 )
  273. {
  274. while (t1 < t2 && t1<=b1)
  275. {
  276. R_MapPlane (t1,spanstart[t1],x-1);
  277. t1++;
  278. }
  279. while (b1 > b2 && b1>=t1)
  280. {
  281. R_MapPlane (b1,spanstart[b1],x-1);
  282. b1--;
  283. }
  284. while (t2 < t1 && t2<=b2)
  285. {
  286. spanstart[t2] = x;
  287. t2++;
  288. }
  289. while (b2 > b1 && b2>=t2)
  290. {
  291. spanstart[b2] = x;
  292. b2--;
  293. }
  294. }
  295. //
  296. // R_DrawPlanes
  297. // At the end of each frame.
  298. //
  299. void R_DrawPlanes (void)
  300. {
  301. visplane_t* pl;
  302. int light;
  303. int x;
  304. int stop;
  305. int angle;
  306. #ifdef RANGECHECK
  307. if (ds_p - drawsegs > MAXDRAWSEGS)
  308. I_Error ("R_DrawPlanes: drawsegs overflow (%i)",
  309. ds_p - drawsegs);
  310. if (lastvisplane - visplanes > MAXVISPLANES)
  311. I_Error ("R_DrawPlanes: visplane overflow (%i)",
  312. lastvisplane - visplanes);
  313. if (lastopening - openings > MAXOPENINGS)
  314. I_Error ("R_DrawPlanes: opening overflow (%i)",
  315. lastopening - openings);
  316. #endif
  317. for (pl = visplanes ; pl < lastvisplane ; pl++)
  318. {
  319. if (pl->minx > pl->maxx)
  320. continue;
  321. // sky flat
  322. if (pl->picnum == skyflatnum)
  323. {
  324. dc_iscale = pspriteiscale>>detailshift;
  325. // Sky is allways drawn full bright,
  326. // i.e. colormaps[0] is used.
  327. // Because of this hack, sky is not affected
  328. // by INVUL inverse mapping.
  329. dc_colormap = colormaps;
  330. dc_texturemid = skytexturemid;
  331. for (x=pl->minx ; x <= pl->maxx ; x++)
  332. {
  333. dc_yl = pl->top[x];
  334. dc_yh = pl->bottom[x];
  335. if (dc_yl <= dc_yh)
  336. {
  337. angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
  338. dc_x = x;
  339. dc_source = R_GetColumn(skytexture, angle);
  340. colfunc ();
  341. }
  342. }
  343. continue;
  344. }
  345. // regular flat
  346. ds_source = W_CacheLumpNum(firstflat +
  347. flattranslation[pl->picnum],
  348. PU_STATIC);
  349. planeheight = abs(pl->height-viewz);
  350. light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight;
  351. if (light >= LIGHTLEVELS)
  352. light = LIGHTLEVELS-1;
  353. if (light < 0)
  354. light = 0;
  355. planezlight = zlight[light];
  356. pl->top[pl->maxx+1] = 0xff;
  357. pl->top[pl->minx-1] = 0xff;
  358. stop = pl->maxx + 1;
  359. for (x=pl->minx ; x<= stop ; x++)
  360. {
  361. R_MakeSpans(x,pl->top[x-1],
  362. pl->bottom[x-1],
  363. pl->top[x],
  364. pl->bottom[x]);
  365. }
  366. Z_ChangeTag (ds_source, PU_CACHE);
  367. }
  368. }