d_scan.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /*
  2. Copyright (C) 1996-1997 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 "quakedef.h"
  19. #include "r_local.h"
  20. #include "d_local.h"
  21. unsigned char *r_turb_pbase, *r_turb_pdest;
  22. fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
  23. int *r_turb_turb;
  24. int r_turb_spancount;
  25. void D_DrawTurbulent8Span (void);
  26. /*
  27. =============
  28. D_WarpScreen
  29. // this performs a slight compression of the screen at the same time as
  30. // the sine warp, to keep the edges from wrapping
  31. =============
  32. */
  33. void D_WarpScreen (void)
  34. {
  35. int w, h;
  36. int u,v;
  37. byte *dest;
  38. int *turb;
  39. int *col;
  40. byte **row;
  41. byte *rowptr[1024];
  42. int column[1280];
  43. float wratio, hratio;
  44. w = r_refdef.vrect.width;
  45. h = r_refdef.vrect.height;
  46. wratio = w / (float)scr_vrect.width;
  47. hratio = h / (float)scr_vrect.height;
  48. for (v=0 ; v<scr_vrect.height+AMP2*2 ; v++)
  49. {
  50. rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
  51. (screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
  52. }
  53. for (u=0 ; u<scr_vrect.width+AMP2*2 ; u++)
  54. {
  55. column[u] = r_refdef.vrect.x +
  56. (int)((float)u * wratio * w / (w + AMP2 * 2));
  57. }
  58. turb = intsintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  59. dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
  60. for (v=0 ; v<scr_vrect.height ; v++, dest += vid.rowbytes)
  61. {
  62. col = &column[turb[v]];
  63. row = &rowptr[v];
  64. for (u=0 ; u<scr_vrect.width ; u+=4)
  65. {
  66. dest[u+0] = row[turb[u+0]][col[u+0]];
  67. dest[u+1] = row[turb[u+1]][col[u+1]];
  68. dest[u+2] = row[turb[u+2]][col[u+2]];
  69. dest[u+3] = row[turb[u+3]][col[u+3]];
  70. }
  71. }
  72. }
  73. #if !id386
  74. /*
  75. =============
  76. D_DrawTurbulent8Span
  77. =============
  78. */
  79. void D_DrawTurbulent8Span (void)
  80. {
  81. int sturb, tturb;
  82. do
  83. {
  84. sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
  85. tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
  86. *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
  87. r_turb_s += r_turb_sstep;
  88. r_turb_t += r_turb_tstep;
  89. } while (--r_turb_spancount > 0);
  90. }
  91. #endif // !id386
  92. /*
  93. =============
  94. Turbulent8
  95. =============
  96. */
  97. void Turbulent8 (espan_t *pspan)
  98. {
  99. int count;
  100. fixed16_t snext, tnext;
  101. float sdivz, tdivz, zi, z, du, dv, spancountminus1;
  102. float sdivz16stepu, tdivz16stepu, zi16stepu;
  103. r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
  104. r_turb_sstep = 0; // keep compiler happy
  105. r_turb_tstep = 0; // ditto
  106. r_turb_pbase = (unsigned char *)cacheblock;
  107. sdivz16stepu = d_sdivzstepu * 16;
  108. tdivz16stepu = d_tdivzstepu * 16;
  109. zi16stepu = d_zistepu * 16;
  110. do
  111. {
  112. r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
  113. (screenwidth * pspan->v) + pspan->u);
  114. count = pspan->count;
  115. // calculate the initial s/z, t/z, 1/z, s, and t and clamp
  116. du = (float)pspan->u;
  117. dv = (float)pspan->v;
  118. sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
  119. tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
  120. zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  121. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  122. r_turb_s = (int)(sdivz * z) + sadjust;
  123. if (r_turb_s > bbextents)
  124. r_turb_s = bbextents;
  125. else if (r_turb_s < 0)
  126. r_turb_s = 0;
  127. r_turb_t = (int)(tdivz * z) + tadjust;
  128. if (r_turb_t > bbextentt)
  129. r_turb_t = bbextentt;
  130. else if (r_turb_t < 0)
  131. r_turb_t = 0;
  132. do
  133. {
  134. // calculate s and t at the far end of the span
  135. if (count >= 16)
  136. r_turb_spancount = 16;
  137. else
  138. r_turb_spancount = count;
  139. count -= r_turb_spancount;
  140. if (count)
  141. {
  142. // calculate s/z, t/z, zi->fixed s and t at far end of span,
  143. // calculate s and t steps across span by shifting
  144. sdivz += sdivz16stepu;
  145. tdivz += tdivz16stepu;
  146. zi += zi16stepu;
  147. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  148. snext = (int)(sdivz * z) + sadjust;
  149. if (snext > bbextents)
  150. snext = bbextents;
  151. else if (snext < 16)
  152. snext = 16; // prevent round-off error on <0 steps from
  153. // from causing overstepping & running off the
  154. // edge of the texture
  155. tnext = (int)(tdivz * z) + tadjust;
  156. if (tnext > bbextentt)
  157. tnext = bbextentt;
  158. else if (tnext < 16)
  159. tnext = 16; // guard against round-off error on <0 steps
  160. r_turb_sstep = (snext - r_turb_s) >> 4;
  161. r_turb_tstep = (tnext - r_turb_t) >> 4;
  162. }
  163. else
  164. {
  165. // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
  166. // can't step off polygon), clamp, calculate s and t steps across
  167. // span by division, biasing steps low so we don't run off the
  168. // texture
  169. spancountminus1 = (float)(r_turb_spancount - 1);
  170. sdivz += d_sdivzstepu * spancountminus1;
  171. tdivz += d_tdivzstepu * spancountminus1;
  172. zi += d_zistepu * spancountminus1;
  173. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  174. snext = (int)(sdivz * z) + sadjust;
  175. if (snext > bbextents)
  176. snext = bbextents;
  177. else if (snext < 16)
  178. snext = 16; // prevent round-off error on <0 steps from
  179. // from causing overstepping & running off the
  180. // edge of the texture
  181. tnext = (int)(tdivz * z) + tadjust;
  182. if (tnext > bbextentt)
  183. tnext = bbextentt;
  184. else if (tnext < 16)
  185. tnext = 16; // guard against round-off error on <0 steps
  186. if (r_turb_spancount > 1)
  187. {
  188. r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
  189. r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
  190. }
  191. }
  192. r_turb_s = r_turb_s & ((CYCLE<<16)-1);
  193. r_turb_t = r_turb_t & ((CYCLE<<16)-1);
  194. D_DrawTurbulent8Span ();
  195. r_turb_s = snext;
  196. r_turb_t = tnext;
  197. } while (count > 0);
  198. } while ((pspan = pspan->pnext) != NULL);
  199. }
  200. #if !id386
  201. /*
  202. =============
  203. D_DrawSpans8
  204. =============
  205. */
  206. void D_DrawSpans8 (espan_t *pspan)
  207. {
  208. int count, spancount;
  209. unsigned char *pbase, *pdest;
  210. fixed16_t s, t, snext, tnext, sstep, tstep;
  211. float sdivz, tdivz, zi, z, du, dv, spancountminus1;
  212. float sdivz8stepu, tdivz8stepu, zi8stepu;
  213. sstep = 0; // keep compiler happy
  214. tstep = 0; // ditto
  215. pbase = (unsigned char *)cacheblock;
  216. sdivz8stepu = d_sdivzstepu * 8;
  217. tdivz8stepu = d_tdivzstepu * 8;
  218. zi8stepu = d_zistepu * 8;
  219. do
  220. {
  221. pdest = (unsigned char *)((byte *)d_viewbuffer +
  222. (screenwidth * pspan->v) + pspan->u);
  223. count = pspan->count;
  224. // calculate the initial s/z, t/z, 1/z, s, and t and clamp
  225. du = (float)pspan->u;
  226. dv = (float)pspan->v;
  227. sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
  228. tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
  229. zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  230. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  231. s = (int)(sdivz * z) + sadjust;
  232. if (s > bbextents)
  233. s = bbextents;
  234. else if (s < 0)
  235. s = 0;
  236. t = (int)(tdivz * z) + tadjust;
  237. if (t > bbextentt)
  238. t = bbextentt;
  239. else if (t < 0)
  240. t = 0;
  241. do
  242. {
  243. // calculate s and t at the far end of the span
  244. if (count >= 8)
  245. spancount = 8;
  246. else
  247. spancount = count;
  248. count -= spancount;
  249. if (count)
  250. {
  251. // calculate s/z, t/z, zi->fixed s and t at far end of span,
  252. // calculate s and t steps across span by shifting
  253. sdivz += sdivz8stepu;
  254. tdivz += tdivz8stepu;
  255. zi += zi8stepu;
  256. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  257. snext = (int)(sdivz * z) + sadjust;
  258. if (snext > bbextents)
  259. snext = bbextents;
  260. else if (snext < 8)
  261. snext = 8; // prevent round-off error on <0 steps from
  262. // from causing overstepping & running off the
  263. // edge of the texture
  264. tnext = (int)(tdivz * z) + tadjust;
  265. if (tnext > bbextentt)
  266. tnext = bbextentt;
  267. else if (tnext < 8)
  268. tnext = 8; // guard against round-off error on <0 steps
  269. sstep = (snext - s) >> 3;
  270. tstep = (tnext - t) >> 3;
  271. }
  272. else
  273. {
  274. // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
  275. // can't step off polygon), clamp, calculate s and t steps across
  276. // span by division, biasing steps low so we don't run off the
  277. // texture
  278. spancountminus1 = (float)(spancount - 1);
  279. sdivz += d_sdivzstepu * spancountminus1;
  280. tdivz += d_tdivzstepu * spancountminus1;
  281. zi += d_zistepu * spancountminus1;
  282. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  283. snext = (int)(sdivz * z) + sadjust;
  284. if (snext > bbextents)
  285. snext = bbextents;
  286. else if (snext < 8)
  287. snext = 8; // prevent round-off error on <0 steps from
  288. // from causing overstepping & running off the
  289. // edge of the texture
  290. tnext = (int)(tdivz * z) + tadjust;
  291. if (tnext > bbextentt)
  292. tnext = bbextentt;
  293. else if (tnext < 8)
  294. tnext = 8; // guard against round-off error on <0 steps
  295. if (spancount > 1)
  296. {
  297. sstep = (snext - s) / (spancount - 1);
  298. tstep = (tnext - t) / (spancount - 1);
  299. }
  300. }
  301. do
  302. {
  303. *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
  304. s += sstep;
  305. t += tstep;
  306. } while (--spancount > 0);
  307. s = snext;
  308. t = tnext;
  309. } while (count > 0);
  310. } while ((pspan = pspan->pnext) != NULL);
  311. }
  312. #endif
  313. #if !id386
  314. /*
  315. =============
  316. D_DrawZSpans
  317. =============
  318. */
  319. void D_DrawZSpans (espan_t *pspan)
  320. {
  321. int count, doublecount, izistep;
  322. int izi;
  323. short *pdest;
  324. unsigned ltemp;
  325. double zi;
  326. float du, dv;
  327. // FIXME: check for clamping/range problems
  328. // we count on FP exceptions being turned off to avoid range problems
  329. izistep = (int)(d_zistepu * 0x8000 * 0x10000);
  330. do
  331. {
  332. pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
  333. count = pspan->count;
  334. // calculate the initial 1/z
  335. du = (float)pspan->u;
  336. dv = (float)pspan->v;
  337. zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  338. // we count on FP exceptions being turned off to avoid range problems
  339. izi = (int)(zi * 0x8000 * 0x10000);
  340. if ((long)pdest & 0x02)
  341. {
  342. *pdest++ = (short)(izi >> 16);
  343. izi += izistep;
  344. count--;
  345. }
  346. if ((doublecount = count >> 1) > 0)
  347. {
  348. do
  349. {
  350. ltemp = izi >> 16;
  351. izi += izistep;
  352. ltemp |= izi & 0xFFFF0000;
  353. izi += izistep;
  354. *(int *)pdest = ltemp;
  355. pdest += 2;
  356. } while (--doublecount > 0);
  357. }
  358. if (count & 1)
  359. *pdest = (short)(izi >> 16);
  360. } while ((pspan = pspan->pnext) != NULL);
  361. }
  362. #endif