r_scan.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // d_scan.c
  16. //
  17. // Portable C scan-level rasterization code, all pixel depths.
  18. #include "r_local.h"
  19. unsigned char *r_turb_pbase, *r_turb_pdest;
  20. fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
  21. int *r_turb_turb;
  22. int r_turb_spancount;
  23. void D_DrawTurbulent8Span (void);
  24. /*
  25. =============
  26. D_WarpScreen
  27. this performs a slight compression of the screen at the same time as
  28. the sine warp, to keep the edges from wrapping
  29. =============
  30. */
  31. void D_WarpScreen (void)
  32. {
  33. int w, h;
  34. int u,v, u2, v2;
  35. byte *dest;
  36. int *turb;
  37. int *col;
  38. byte **row;
  39. static int cached_width, cached_height;
  40. static byte *rowptr[1200+AMP2*2];
  41. static int column[1600+AMP2*2];
  42. //
  43. // these are constant over resolutions, and can be saved
  44. //
  45. w = r_newrefdef.width;
  46. h = r_newrefdef.height;
  47. if (w != cached_width || h != cached_height)
  48. {
  49. cached_width = w;
  50. cached_height = h;
  51. for (v=0 ; v<h+AMP2*2 ; v++)
  52. {
  53. v2 = (int)((float)v/(h + AMP2 * 2) * r_refdef.vrect.height);
  54. rowptr[v] = r_warpbuffer + (WARP_WIDTH * v2);
  55. }
  56. for (u=0 ; u<w+AMP2*2 ; u++)
  57. {
  58. u2 = (int)((float)u/(w + AMP2 * 2) * r_refdef.vrect.width);
  59. column[u] = u2;
  60. }
  61. }
  62. turb = intsintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
  63. dest = vid.buffer + r_newrefdef.y * vid.rowbytes + r_newrefdef.x;
  64. for (v=0 ; v<h ; v++, dest += vid.rowbytes)
  65. {
  66. col = &column[turb[v]];
  67. row = &rowptr[v];
  68. for (u=0 ; u<w ; u+=4)
  69. {
  70. dest[u+0] = row[turb[u+0]][col[u+0]];
  71. dest[u+1] = row[turb[u+1]][col[u+1]];
  72. dest[u+2] = row[turb[u+2]][col[u+2]];
  73. dest[u+3] = row[turb[u+3]][col[u+3]];
  74. }
  75. }
  76. }
  77. #if !id386
  78. /*
  79. =============
  80. D_DrawTurbulent8Span
  81. =============
  82. */
  83. void D_DrawTurbulent8Span (void)
  84. {
  85. int sturb, tturb;
  86. do
  87. {
  88. sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
  89. tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
  90. *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
  91. r_turb_s += r_turb_sstep;
  92. r_turb_t += r_turb_tstep;
  93. } while (--r_turb_spancount > 0);
  94. }
  95. #endif // !id386
  96. /*
  97. =============
  98. Turbulent8
  99. =============
  100. */
  101. void Turbulent8 (espan_t *pspan)
  102. {
  103. int count;
  104. fixed16_t snext, tnext;
  105. float sdivz, tdivz, zi, z, du, dv, spancountminus1;
  106. float sdivz16stepu, tdivz16stepu, zi16stepu;
  107. r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
  108. r_turb_sstep = 0; // keep compiler happy
  109. r_turb_tstep = 0; // ditto
  110. r_turb_pbase = (unsigned char *)cacheblock;
  111. sdivz16stepu = d_sdivzstepu * 16;
  112. tdivz16stepu = d_tdivzstepu * 16;
  113. zi16stepu = d_zistepu * 16;
  114. do
  115. {
  116. r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
  117. (r_screenwidth * pspan->v) + pspan->u);
  118. count = pspan->count;
  119. // calculate the initial s/z, t/z, 1/z, s, and t and clamp
  120. du = (float)pspan->u;
  121. dv = (float)pspan->v;
  122. sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
  123. tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
  124. zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  125. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  126. r_turb_s = (int)(sdivz * z) + sadjust;
  127. if (r_turb_s > bbextents)
  128. r_turb_s = bbextents;
  129. else if (r_turb_s < 0)
  130. r_turb_s = 0;
  131. r_turb_t = (int)(tdivz * z) + tadjust;
  132. if (r_turb_t > bbextentt)
  133. r_turb_t = bbextentt;
  134. else if (r_turb_t < 0)
  135. r_turb_t = 0;
  136. do
  137. {
  138. // calculate s and t at the far end of the span
  139. if (count >= 16)
  140. r_turb_spancount = 16;
  141. else
  142. r_turb_spancount = count;
  143. count -= r_turb_spancount;
  144. if (count)
  145. {
  146. // calculate s/z, t/z, zi->fixed s and t at far end of span,
  147. // calculate s and t steps across span by shifting
  148. sdivz += sdivz16stepu;
  149. tdivz += tdivz16stepu;
  150. zi += zi16stepu;
  151. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  152. snext = (int)(sdivz * z) + sadjust;
  153. if (snext > bbextents)
  154. snext = bbextents;
  155. else if (snext < 16)
  156. snext = 16; // prevent round-off error on <0 steps from
  157. // from causing overstepping & running off the
  158. // edge of the texture
  159. tnext = (int)(tdivz * z) + tadjust;
  160. if (tnext > bbextentt)
  161. tnext = bbextentt;
  162. else if (tnext < 16)
  163. tnext = 16; // guard against round-off error on <0 steps
  164. r_turb_sstep = (snext - r_turb_s) >> 4;
  165. r_turb_tstep = (tnext - r_turb_t) >> 4;
  166. }
  167. else
  168. {
  169. // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
  170. // can't step off polygon), clamp, calculate s and t steps across
  171. // span by division, biasing steps low so we don't run off the
  172. // texture
  173. spancountminus1 = (float)(r_turb_spancount - 1);
  174. sdivz += d_sdivzstepu * spancountminus1;
  175. tdivz += d_tdivzstepu * spancountminus1;
  176. zi += d_zistepu * spancountminus1;
  177. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  178. snext = (int)(sdivz * z) + sadjust;
  179. if (snext > bbextents)
  180. snext = bbextents;
  181. else if (snext < 16)
  182. snext = 16; // prevent round-off error on <0 steps from
  183. // from causing overstepping & running off the
  184. // edge of the texture
  185. tnext = (int)(tdivz * z) + tadjust;
  186. if (tnext > bbextentt)
  187. tnext = bbextentt;
  188. else if (tnext < 16)
  189. tnext = 16; // guard against round-off error on <0 steps
  190. if (r_turb_spancount > 1)
  191. {
  192. r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
  193. r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
  194. }
  195. }
  196. r_turb_s = r_turb_s & ((CYCLE<<16)-1);
  197. r_turb_t = r_turb_t & ((CYCLE<<16)-1);
  198. D_DrawTurbulent8Span ();
  199. r_turb_s = snext;
  200. r_turb_t = tnext;
  201. } while (count > 0);
  202. } while ((pspan = pspan->pnext) != NULL);
  203. }
  204. //====================
  205. //PGM
  206. /*
  207. =============
  208. NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures
  209. but the turbulence is automatically 0.
  210. =============
  211. */
  212. void NonTurbulent8 (espan_t *pspan)
  213. {
  214. int count;
  215. fixed16_t snext, tnext;
  216. float sdivz, tdivz, zi, z, du, dv, spancountminus1;
  217. float sdivz16stepu, tdivz16stepu, zi16stepu;
  218. // r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
  219. r_turb_turb = blanktable;
  220. r_turb_sstep = 0; // keep compiler happy
  221. r_turb_tstep = 0; // ditto
  222. r_turb_pbase = (unsigned char *)cacheblock;
  223. sdivz16stepu = d_sdivzstepu * 16;
  224. tdivz16stepu = d_tdivzstepu * 16;
  225. zi16stepu = d_zistepu * 16;
  226. do
  227. {
  228. r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
  229. (r_screenwidth * pspan->v) + pspan->u);
  230. count = pspan->count;
  231. // calculate the initial s/z, t/z, 1/z, s, and t and clamp
  232. du = (float)pspan->u;
  233. dv = (float)pspan->v;
  234. sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
  235. tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
  236. zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  237. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  238. r_turb_s = (int)(sdivz * z) + sadjust;
  239. if (r_turb_s > bbextents)
  240. r_turb_s = bbextents;
  241. else if (r_turb_s < 0)
  242. r_turb_s = 0;
  243. r_turb_t = (int)(tdivz * z) + tadjust;
  244. if (r_turb_t > bbextentt)
  245. r_turb_t = bbextentt;
  246. else if (r_turb_t < 0)
  247. r_turb_t = 0;
  248. do
  249. {
  250. // calculate s and t at the far end of the span
  251. if (count >= 16)
  252. r_turb_spancount = 16;
  253. else
  254. r_turb_spancount = count;
  255. count -= r_turb_spancount;
  256. if (count)
  257. {
  258. // calculate s/z, t/z, zi->fixed s and t at far end of span,
  259. // calculate s and t steps across span by shifting
  260. sdivz += sdivz16stepu;
  261. tdivz += tdivz16stepu;
  262. zi += zi16stepu;
  263. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  264. snext = (int)(sdivz * z) + sadjust;
  265. if (snext > bbextents)
  266. snext = bbextents;
  267. else if (snext < 16)
  268. snext = 16; // prevent round-off error on <0 steps from
  269. // from causing overstepping & running off the
  270. // edge of the texture
  271. tnext = (int)(tdivz * z) + tadjust;
  272. if (tnext > bbextentt)
  273. tnext = bbextentt;
  274. else if (tnext < 16)
  275. tnext = 16; // guard against round-off error on <0 steps
  276. r_turb_sstep = (snext - r_turb_s) >> 4;
  277. r_turb_tstep = (tnext - r_turb_t) >> 4;
  278. }
  279. else
  280. {
  281. // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
  282. // can't step off polygon), clamp, calculate s and t steps across
  283. // span by division, biasing steps low so we don't run off the
  284. // texture
  285. spancountminus1 = (float)(r_turb_spancount - 1);
  286. sdivz += d_sdivzstepu * spancountminus1;
  287. tdivz += d_tdivzstepu * spancountminus1;
  288. zi += d_zistepu * spancountminus1;
  289. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  290. snext = (int)(sdivz * z) + sadjust;
  291. if (snext > bbextents)
  292. snext = bbextents;
  293. else if (snext < 16)
  294. snext = 16; // prevent round-off error on <0 steps from
  295. // from causing overstepping & running off the
  296. // edge of the texture
  297. tnext = (int)(tdivz * z) + tadjust;
  298. if (tnext > bbextentt)
  299. tnext = bbextentt;
  300. else if (tnext < 16)
  301. tnext = 16; // guard against round-off error on <0 steps
  302. if (r_turb_spancount > 1)
  303. {
  304. r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
  305. r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
  306. }
  307. }
  308. r_turb_s = r_turb_s & ((CYCLE<<16)-1);
  309. r_turb_t = r_turb_t & ((CYCLE<<16)-1);
  310. D_DrawTurbulent8Span ();
  311. r_turb_s = snext;
  312. r_turb_t = tnext;
  313. } while (count > 0);
  314. } while ((pspan = pspan->pnext) != NULL);
  315. }
  316. //PGM
  317. //====================
  318. #if !id386
  319. /*
  320. =============
  321. D_DrawSpans16
  322. FIXME: actually make this subdivide by 16 instead of 8!!!
  323. =============
  324. */
  325. void D_DrawSpans16 (espan_t *pspan)
  326. {
  327. int count, spancount;
  328. unsigned char *pbase, *pdest;
  329. fixed16_t s, t, snext, tnext, sstep, tstep;
  330. float sdivz, tdivz, zi, z, du, dv, spancountminus1;
  331. float sdivz8stepu, tdivz8stepu, zi8stepu;
  332. sstep = 0; // keep compiler happy
  333. tstep = 0; // ditto
  334. pbase = (unsigned char *)cacheblock;
  335. sdivz8stepu = d_sdivzstepu * 8;
  336. tdivz8stepu = d_tdivzstepu * 8;
  337. zi8stepu = d_zistepu * 8;
  338. do
  339. {
  340. pdest = (unsigned char *)((byte *)d_viewbuffer +
  341. (r_screenwidth * pspan->v) + pspan->u);
  342. count = pspan->count;
  343. // calculate the initial s/z, t/z, 1/z, s, and t and clamp
  344. du = (float)pspan->u;
  345. dv = (float)pspan->v;
  346. sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
  347. tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
  348. zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  349. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  350. s = (int)(sdivz * z) + sadjust;
  351. if (s > bbextents)
  352. s = bbextents;
  353. else if (s < 0)
  354. s = 0;
  355. t = (int)(tdivz * z) + tadjust;
  356. if (t > bbextentt)
  357. t = bbextentt;
  358. else if (t < 0)
  359. t = 0;
  360. do
  361. {
  362. // calculate s and t at the far end of the span
  363. if (count >= 8)
  364. spancount = 8;
  365. else
  366. spancount = count;
  367. count -= spancount;
  368. if (count)
  369. {
  370. // calculate s/z, t/z, zi->fixed s and t at far end of span,
  371. // calculate s and t steps across span by shifting
  372. sdivz += sdivz8stepu;
  373. tdivz += tdivz8stepu;
  374. zi += zi8stepu;
  375. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  376. snext = (int)(sdivz * z) + sadjust;
  377. if (snext > bbextents)
  378. snext = bbextents;
  379. else if (snext < 8)
  380. snext = 8; // prevent round-off error on <0 steps from
  381. // from causing overstepping & running off the
  382. // edge of the texture
  383. tnext = (int)(tdivz * z) + tadjust;
  384. if (tnext > bbextentt)
  385. tnext = bbextentt;
  386. else if (tnext < 8)
  387. tnext = 8; // guard against round-off error on <0 steps
  388. sstep = (snext - s) >> 3;
  389. tstep = (tnext - t) >> 3;
  390. }
  391. else
  392. {
  393. // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
  394. // can't step off polygon), clamp, calculate s and t steps across
  395. // span by division, biasing steps low so we don't run off the
  396. // texture
  397. spancountminus1 = (float)(spancount - 1);
  398. sdivz += d_sdivzstepu * spancountminus1;
  399. tdivz += d_tdivzstepu * spancountminus1;
  400. zi += d_zistepu * spancountminus1;
  401. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  402. snext = (int)(sdivz * z) + sadjust;
  403. if (snext > bbextents)
  404. snext = bbextents;
  405. else if (snext < 8)
  406. snext = 8; // prevent round-off error on <0 steps from
  407. // from causing overstepping & running off the
  408. // edge of the texture
  409. tnext = (int)(tdivz * z) + tadjust;
  410. if (tnext > bbextentt)
  411. tnext = bbextentt;
  412. else if (tnext < 8)
  413. tnext = 8; // guard against round-off error on <0 steps
  414. if (spancount > 1)
  415. {
  416. sstep = (snext - s) / (spancount - 1);
  417. tstep = (tnext - t) / (spancount - 1);
  418. }
  419. }
  420. do
  421. {
  422. *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
  423. s += sstep;
  424. t += tstep;
  425. } while (--spancount > 0);
  426. s = snext;
  427. t = tnext;
  428. } while (count > 0);
  429. } while ((pspan = pspan->pnext) != NULL);
  430. }
  431. #endif
  432. #if !id386
  433. /*
  434. =============
  435. D_DrawZSpans
  436. =============
  437. */
  438. void D_DrawZSpans (espan_t *pspan)
  439. {
  440. int count, doublecount, izistep;
  441. int izi;
  442. short *pdest;
  443. unsigned ltemp;
  444. float zi;
  445. float du, dv;
  446. // FIXME: check for clamping/range problems
  447. // we count on FP exceptions being turned off to avoid range problems
  448. izistep = (int)(d_zistepu * 0x8000 * 0x10000);
  449. do
  450. {
  451. pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
  452. count = pspan->count;
  453. // calculate the initial 1/z
  454. du = (float)pspan->u;
  455. dv = (float)pspan->v;
  456. zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  457. // we count on FP exceptions being turned off to avoid range problems
  458. izi = (int)(zi * 0x8000 * 0x10000);
  459. if ((long)pdest & 0x02)
  460. {
  461. *pdest++ = (short)(izi >> 16);
  462. izi += izistep;
  463. count--;
  464. }
  465. if ((doublecount = count >> 1) > 0)
  466. {
  467. do
  468. {
  469. ltemp = izi >> 16;
  470. izi += izistep;
  471. ltemp |= izi & 0xFFFF0000;
  472. izi += izistep;
  473. *(int *)pdest = ltemp;
  474. pdest += 2;
  475. } while (--doublecount > 0);
  476. }
  477. if (count & 1)
  478. *pdest = (short)(izi >> 16);
  479. } while ((pspan = pspan->pnext) != NULL);
  480. }
  481. #endif