r_poly.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  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. #include <assert.h>
  16. #include "r_local.h"
  17. #define AFFINE_SPANLET_SIZE 16
  18. #define AFFINE_SPANLET_SIZE_BITS 4
  19. typedef struct
  20. {
  21. byte *pbase, *pdest;
  22. short *pz;
  23. fixed16_t s, t;
  24. fixed16_t sstep, tstep;
  25. int izi, izistep, izistep_times_2;
  26. int spancount;
  27. unsigned u, v;
  28. } spanletvars_t;
  29. spanletvars_t s_spanletvars;
  30. static int r_polyblendcolor;
  31. static espan_t *s_polygon_spans;
  32. polydesc_t r_polydesc;
  33. msurface_t *r_alpha_surfaces;
  34. extern int *r_turb_turb;
  35. static int clip_current;
  36. vec5_t r_clip_verts[2][MAXWORKINGVERTS+2];
  37. static int s_minindex, s_maxindex;
  38. static void R_DrawPoly( qboolean iswater );
  39. /*
  40. ** R_DrawSpanletOpaque
  41. */
  42. void R_DrawSpanletOpaque( void )
  43. {
  44. unsigned btemp;
  45. do
  46. {
  47. unsigned ts, tt;
  48. ts = s_spanletvars.s >> 16;
  49. tt = s_spanletvars.t >> 16;
  50. btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
  51. if (btemp != 255)
  52. {
  53. if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
  54. {
  55. *s_spanletvars.pz = s_spanletvars.izi >> 16;
  56. *s_spanletvars.pdest = btemp;
  57. }
  58. }
  59. s_spanletvars.izi += s_spanletvars.izistep;
  60. s_spanletvars.pdest++;
  61. s_spanletvars.pz++;
  62. s_spanletvars.s += s_spanletvars.sstep;
  63. s_spanletvars.t += s_spanletvars.tstep;
  64. } while (--s_spanletvars.spancount > 0);
  65. }
  66. /*
  67. ** R_DrawSpanletTurbulentStipple33
  68. */
  69. void R_DrawSpanletTurbulentStipple33( void )
  70. {
  71. unsigned btemp;
  72. int sturb, tturb;
  73. byte *pdest = s_spanletvars.pdest;
  74. short *pz = s_spanletvars.pz;
  75. int izi = s_spanletvars.izi;
  76. if ( s_spanletvars.v & 1 )
  77. {
  78. s_spanletvars.pdest += s_spanletvars.spancount;
  79. s_spanletvars.pz += s_spanletvars.spancount;
  80. if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
  81. s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
  82. else
  83. s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
  84. if ( s_spanletvars.u & 1 )
  85. {
  86. izi += s_spanletvars.izistep;
  87. s_spanletvars.s += s_spanletvars.sstep;
  88. s_spanletvars.t += s_spanletvars.tstep;
  89. pdest++;
  90. pz++;
  91. s_spanletvars.spancount--;
  92. }
  93. s_spanletvars.sstep *= 2;
  94. s_spanletvars.tstep *= 2;
  95. while ( s_spanletvars.spancount > 0 )
  96. {
  97. sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
  98. tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
  99. btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
  100. if ( *pz <= ( izi >> 16 ) )
  101. *pdest = btemp;
  102. izi += s_spanletvars.izistep_times_2;
  103. s_spanletvars.s += s_spanletvars.sstep;
  104. s_spanletvars.t += s_spanletvars.tstep;
  105. pdest += 2;
  106. pz += 2;
  107. s_spanletvars.spancount -= 2;
  108. }
  109. }
  110. }
  111. /*
  112. ** R_DrawSpanletTurbulentStipple66
  113. */
  114. void R_DrawSpanletTurbulentStipple66( void )
  115. {
  116. unsigned btemp;
  117. int sturb, tturb;
  118. byte *pdest = s_spanletvars.pdest;
  119. short *pz = s_spanletvars.pz;
  120. int izi = s_spanletvars.izi;
  121. if ( !( s_spanletvars.v & 1 ) )
  122. {
  123. s_spanletvars.pdest += s_spanletvars.spancount;
  124. s_spanletvars.pz += s_spanletvars.spancount;
  125. if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
  126. s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
  127. else
  128. s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
  129. if ( s_spanletvars.u & 1 )
  130. {
  131. izi += s_spanletvars.izistep;
  132. s_spanletvars.s += s_spanletvars.sstep;
  133. s_spanletvars.t += s_spanletvars.tstep;
  134. pdest++;
  135. pz++;
  136. s_spanletvars.spancount--;
  137. }
  138. s_spanletvars.sstep *= 2;
  139. s_spanletvars.tstep *= 2;
  140. while ( s_spanletvars.spancount > 0 )
  141. {
  142. sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
  143. tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
  144. btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
  145. if ( *pz <= ( izi >> 16 ) )
  146. *pdest = btemp;
  147. izi += s_spanletvars.izistep_times_2;
  148. s_spanletvars.s += s_spanletvars.sstep;
  149. s_spanletvars.t += s_spanletvars.tstep;
  150. pdest += 2;
  151. pz += 2;
  152. s_spanletvars.spancount -= 2;
  153. }
  154. }
  155. else
  156. {
  157. s_spanletvars.pdest += s_spanletvars.spancount;
  158. s_spanletvars.pz += s_spanletvars.spancount;
  159. if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
  160. s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
  161. else
  162. s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
  163. while ( s_spanletvars.spancount > 0 )
  164. {
  165. sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
  166. tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
  167. btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
  168. if ( *pz <= ( izi >> 16 ) )
  169. *pdest = btemp;
  170. izi += s_spanletvars.izistep;
  171. s_spanletvars.s += s_spanletvars.sstep;
  172. s_spanletvars.t += s_spanletvars.tstep;
  173. pdest++;
  174. pz++;
  175. s_spanletvars.spancount--;
  176. }
  177. }
  178. }
  179. /*
  180. ** R_DrawSpanletTurbulentBlended
  181. */
  182. void R_DrawSpanletTurbulentBlended66( void )
  183. {
  184. unsigned btemp;
  185. int sturb, tturb;
  186. do
  187. {
  188. sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
  189. tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
  190. btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
  191. if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) )
  192. *s_spanletvars.pdest = vid.alphamap[btemp*256+*s_spanletvars.pdest];
  193. s_spanletvars.izi += s_spanletvars.izistep;
  194. s_spanletvars.pdest++;
  195. s_spanletvars.pz++;
  196. s_spanletvars.s += s_spanletvars.sstep;
  197. s_spanletvars.t += s_spanletvars.tstep;
  198. } while ( --s_spanletvars.spancount > 0 );
  199. }
  200. void R_DrawSpanletTurbulentBlended33( void )
  201. {
  202. unsigned btemp;
  203. int sturb, tturb;
  204. do
  205. {
  206. sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
  207. tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
  208. btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
  209. if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) )
  210. *s_spanletvars.pdest = vid.alphamap[btemp+*s_spanletvars.pdest*256];
  211. s_spanletvars.izi += s_spanletvars.izistep;
  212. s_spanletvars.pdest++;
  213. s_spanletvars.pz++;
  214. s_spanletvars.s += s_spanletvars.sstep;
  215. s_spanletvars.t += s_spanletvars.tstep;
  216. } while ( --s_spanletvars.spancount > 0 );
  217. }
  218. /*
  219. ** R_DrawSpanlet33
  220. */
  221. void R_DrawSpanlet33( void )
  222. {
  223. unsigned btemp;
  224. do
  225. {
  226. unsigned ts, tt;
  227. ts = s_spanletvars.s >> 16;
  228. tt = s_spanletvars.t >> 16;
  229. btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
  230. if ( btemp != 255 )
  231. {
  232. if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
  233. {
  234. *s_spanletvars.pdest = vid.alphamap[btemp+*s_spanletvars.pdest*256];
  235. }
  236. }
  237. s_spanletvars.izi += s_spanletvars.izistep;
  238. s_spanletvars.pdest++;
  239. s_spanletvars.pz++;
  240. s_spanletvars.s += s_spanletvars.sstep;
  241. s_spanletvars.t += s_spanletvars.tstep;
  242. } while (--s_spanletvars.spancount > 0);
  243. }
  244. void R_DrawSpanletConstant33( void )
  245. {
  246. do
  247. {
  248. if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
  249. {
  250. *s_spanletvars.pdest = vid.alphamap[r_polyblendcolor+*s_spanletvars.pdest*256];
  251. }
  252. s_spanletvars.izi += s_spanletvars.izistep;
  253. s_spanletvars.pdest++;
  254. s_spanletvars.pz++;
  255. } while (--s_spanletvars.spancount > 0);
  256. }
  257. /*
  258. ** R_DrawSpanlet66
  259. */
  260. void R_DrawSpanlet66( void )
  261. {
  262. unsigned btemp;
  263. do
  264. {
  265. unsigned ts, tt;
  266. ts = s_spanletvars.s >> 16;
  267. tt = s_spanletvars.t >> 16;
  268. btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
  269. if ( btemp != 255 )
  270. {
  271. if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
  272. {
  273. *s_spanletvars.pdest = vid.alphamap[btemp*256+*s_spanletvars.pdest];
  274. }
  275. }
  276. s_spanletvars.izi += s_spanletvars.izistep;
  277. s_spanletvars.pdest++;
  278. s_spanletvars.pz++;
  279. s_spanletvars.s += s_spanletvars.sstep;
  280. s_spanletvars.t += s_spanletvars.tstep;
  281. } while (--s_spanletvars.spancount > 0);
  282. }
  283. /*
  284. ** R_DrawSpanlet33Stipple
  285. */
  286. void R_DrawSpanlet33Stipple( void )
  287. {
  288. unsigned btemp;
  289. byte *pdest = s_spanletvars.pdest;
  290. short *pz = s_spanletvars.pz;
  291. int izi = s_spanletvars.izi;
  292. if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) )
  293. {
  294. s_spanletvars.pdest += s_spanletvars.spancount;
  295. s_spanletvars.pz += s_spanletvars.spancount;
  296. if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
  297. s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
  298. else
  299. s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
  300. if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) )
  301. {
  302. izi += s_spanletvars.izistep;
  303. s_spanletvars.s += s_spanletvars.sstep;
  304. s_spanletvars.t += s_spanletvars.tstep;
  305. pdest++;
  306. pz++;
  307. s_spanletvars.spancount--;
  308. }
  309. s_spanletvars.sstep *= 2;
  310. s_spanletvars.tstep *= 2;
  311. while ( s_spanletvars.spancount > 0 )
  312. {
  313. unsigned s = s_spanletvars.s >> 16;
  314. unsigned t = s_spanletvars.t >> 16;
  315. btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
  316. if ( btemp != 255 )
  317. {
  318. if ( *pz <= ( izi >> 16 ) )
  319. *pdest = btemp;
  320. }
  321. izi += s_spanletvars.izistep_times_2;
  322. s_spanletvars.s += s_spanletvars.sstep;
  323. s_spanletvars.t += s_spanletvars.tstep;
  324. pdest += 2;
  325. pz += 2;
  326. s_spanletvars.spancount -= 2;
  327. }
  328. }
  329. }
  330. /*
  331. ** R_DrawSpanlet66Stipple
  332. */
  333. void R_DrawSpanlet66Stipple( void )
  334. {
  335. unsigned btemp;
  336. byte *pdest = s_spanletvars.pdest;
  337. short *pz = s_spanletvars.pz;
  338. int izi = s_spanletvars.izi;
  339. s_spanletvars.pdest += s_spanletvars.spancount;
  340. s_spanletvars.pz += s_spanletvars.spancount;
  341. if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
  342. s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
  343. else
  344. s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
  345. if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) )
  346. {
  347. if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) )
  348. {
  349. izi += s_spanletvars.izistep;
  350. s_spanletvars.s += s_spanletvars.sstep;
  351. s_spanletvars.t += s_spanletvars.tstep;
  352. pdest++;
  353. pz++;
  354. s_spanletvars.spancount--;
  355. }
  356. s_spanletvars.sstep *= 2;
  357. s_spanletvars.tstep *= 2;
  358. while ( s_spanletvars.spancount > 0 )
  359. {
  360. unsigned s = s_spanletvars.s >> 16;
  361. unsigned t = s_spanletvars.t >> 16;
  362. btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
  363. if ( btemp != 255 )
  364. {
  365. if ( *pz <= ( izi >> 16 ) )
  366. *pdest = btemp;
  367. }
  368. izi += s_spanletvars.izistep_times_2;
  369. s_spanletvars.s += s_spanletvars.sstep;
  370. s_spanletvars.t += s_spanletvars.tstep;
  371. pdest += 2;
  372. pz += 2;
  373. s_spanletvars.spancount -= 2;
  374. }
  375. }
  376. else
  377. {
  378. while ( s_spanletvars.spancount > 0 )
  379. {
  380. unsigned s = s_spanletvars.s >> 16;
  381. unsigned t = s_spanletvars.t >> 16;
  382. btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
  383. if ( btemp != 255 )
  384. {
  385. if ( *pz <= ( izi >> 16 ) )
  386. *pdest = btemp;
  387. }
  388. izi += s_spanletvars.izistep;
  389. s_spanletvars.s += s_spanletvars.sstep;
  390. s_spanletvars.t += s_spanletvars.tstep;
  391. pdest++;
  392. pz++;
  393. s_spanletvars.spancount--;
  394. }
  395. }
  396. }
  397. /*
  398. ** R_ClipPolyFace
  399. **
  400. ** Clips the winding at clip_verts[clip_current] and changes clip_current
  401. ** Throws out the back side
  402. */
  403. int R_ClipPolyFace (int nump, clipplane_t *pclipplane)
  404. {
  405. int i, outcount;
  406. float dists[MAXWORKINGVERTS+3];
  407. float frac, clipdist, *pclipnormal;
  408. float *in, *instep, *outstep, *vert2;
  409. clipdist = pclipplane->dist;
  410. pclipnormal = pclipplane->normal;
  411. // calc dists
  412. if (clip_current)
  413. {
  414. in = r_clip_verts[1][0];
  415. outstep = r_clip_verts[0][0];
  416. clip_current = 0;
  417. }
  418. else
  419. {
  420. in = r_clip_verts[0][0];
  421. outstep = r_clip_verts[1][0];
  422. clip_current = 1;
  423. }
  424. instep = in;
  425. for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
  426. {
  427. dists[i] = DotProduct (instep, pclipnormal) - clipdist;
  428. }
  429. // handle wraparound case
  430. dists[nump] = dists[0];
  431. memcpy (instep, in, sizeof (vec5_t));
  432. // clip the winding
  433. instep = in;
  434. outcount = 0;
  435. for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
  436. {
  437. if (dists[i] >= 0)
  438. {
  439. memcpy (outstep, instep, sizeof (vec5_t));
  440. outstep += sizeof (vec5_t) / sizeof (float);
  441. outcount++;
  442. }
  443. if (dists[i] == 0 || dists[i+1] == 0)
  444. continue;
  445. if ( (dists[i] > 0) == (dists[i+1] > 0) )
  446. continue;
  447. // split it into a new vertex
  448. frac = dists[i] / (dists[i] - dists[i+1]);
  449. vert2 = instep + sizeof (vec5_t) / sizeof (float);
  450. outstep[0] = instep[0] + frac*(vert2[0] - instep[0]);
  451. outstep[1] = instep[1] + frac*(vert2[1] - instep[1]);
  452. outstep[2] = instep[2] + frac*(vert2[2] - instep[2]);
  453. outstep[3] = instep[3] + frac*(vert2[3] - instep[3]);
  454. outstep[4] = instep[4] + frac*(vert2[4] - instep[4]);
  455. outstep += sizeof (vec5_t) / sizeof (float);
  456. outcount++;
  457. }
  458. return outcount;
  459. }
  460. /*
  461. ** R_PolygonDrawSpans
  462. */
  463. void R_PolygonDrawSpans(espan_t *pspan, qboolean iswater )
  464. {
  465. int count;
  466. fixed16_t snext, tnext;
  467. float sdivz, tdivz, zi, z, du, dv, spancountminus1;
  468. float sdivzspanletstepu, tdivzspanletstepu, zispanletstepu;
  469. s_spanletvars.pbase = cacheblock;
  470. if ( iswater )
  471. r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
  472. sdivzspanletstepu = d_sdivzstepu * AFFINE_SPANLET_SIZE;
  473. tdivzspanletstepu = d_tdivzstepu * AFFINE_SPANLET_SIZE;
  474. zispanletstepu = d_zistepu * AFFINE_SPANLET_SIZE;
  475. // we count on FP exceptions being turned off to avoid range problems
  476. s_spanletvars.izistep = (int)(d_zistepu * 0x8000 * 0x10000);
  477. s_spanletvars.izistep_times_2 = s_spanletvars.izistep * 2;
  478. s_spanletvars.pz = 0;
  479. do
  480. {
  481. s_spanletvars.pdest = (byte *)d_viewbuffer + ( d_scantable[pspan->v] /*r_screenwidth * pspan->v*/) + pspan->u;
  482. s_spanletvars.pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
  483. s_spanletvars.u = pspan->u;
  484. s_spanletvars.v = pspan->v;
  485. count = pspan->count;
  486. if (count <= 0)
  487. goto NextSpan;
  488. // calculate the initial s/z, t/z, 1/z, s, and t and clamp
  489. du = (float)pspan->u;
  490. dv = (float)pspan->v;
  491. sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
  492. tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
  493. zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
  494. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  495. // we count on FP exceptions being turned off to avoid range problems
  496. s_spanletvars.izi = (int)(zi * 0x8000 * 0x10000);
  497. s_spanletvars.s = (int)(sdivz * z) + sadjust;
  498. s_spanletvars.t = (int)(tdivz * z) + tadjust;
  499. if ( !iswater )
  500. {
  501. if (s_spanletvars.s > bbextents)
  502. s_spanletvars.s = bbextents;
  503. else if (s_spanletvars.s < 0)
  504. s_spanletvars.s = 0;
  505. if (s_spanletvars.t > bbextentt)
  506. s_spanletvars.t = bbextentt;
  507. else if (s_spanletvars.t < 0)
  508. s_spanletvars.t = 0;
  509. }
  510. do
  511. {
  512. // calculate s and t at the far end of the span
  513. if (count >= AFFINE_SPANLET_SIZE )
  514. s_spanletvars.spancount = AFFINE_SPANLET_SIZE;
  515. else
  516. s_spanletvars.spancount = count;
  517. count -= s_spanletvars.spancount;
  518. if (count)
  519. {
  520. // calculate s/z, t/z, zi->fixed s and t at far end of span,
  521. // calculate s and t steps across span by shifting
  522. sdivz += sdivzspanletstepu;
  523. tdivz += tdivzspanletstepu;
  524. zi += zispanletstepu;
  525. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  526. snext = (int)(sdivz * z) + sadjust;
  527. tnext = (int)(tdivz * z) + tadjust;
  528. if ( !iswater )
  529. {
  530. if (snext > bbextents)
  531. snext = bbextents;
  532. else if (snext < AFFINE_SPANLET_SIZE)
  533. snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
  534. // from causing overstepping & running off the
  535. // edge of the texture
  536. if (tnext > bbextentt)
  537. tnext = bbextentt;
  538. else if (tnext < AFFINE_SPANLET_SIZE)
  539. tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
  540. }
  541. s_spanletvars.sstep = (snext - s_spanletvars.s) >> AFFINE_SPANLET_SIZE_BITS;
  542. s_spanletvars.tstep = (tnext - s_spanletvars.t) >> AFFINE_SPANLET_SIZE_BITS;
  543. }
  544. else
  545. {
  546. // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
  547. // can't step off polygon), clamp, calculate s and t steps across
  548. // span by division, biasing steps low so we don't run off the
  549. // texture
  550. spancountminus1 = (float)(s_spanletvars.spancount - 1);
  551. sdivz += d_sdivzstepu * spancountminus1;
  552. tdivz += d_tdivzstepu * spancountminus1;
  553. zi += d_zistepu * spancountminus1;
  554. z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
  555. snext = (int)(sdivz * z) + sadjust;
  556. tnext = (int)(tdivz * z) + tadjust;
  557. if ( !iswater )
  558. {
  559. if (snext > bbextents)
  560. snext = bbextents;
  561. else if (snext < AFFINE_SPANLET_SIZE)
  562. snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
  563. // from causing overstepping & running off the
  564. // edge of the texture
  565. if (tnext > bbextentt)
  566. tnext = bbextentt;
  567. else if (tnext < AFFINE_SPANLET_SIZE)
  568. tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
  569. }
  570. if (s_spanletvars.spancount > 1)
  571. {
  572. s_spanletvars.sstep = (snext - s_spanletvars.s) / (s_spanletvars.spancount - 1);
  573. s_spanletvars.tstep = (tnext - s_spanletvars.t) / (s_spanletvars.spancount - 1);
  574. }
  575. }
  576. if ( iswater )
  577. {
  578. s_spanletvars.s = s_spanletvars.s & ((CYCLE<<16)-1);
  579. s_spanletvars.t = s_spanletvars.t & ((CYCLE<<16)-1);
  580. }
  581. r_polydesc.drawspanlet();
  582. s_spanletvars.s = snext;
  583. s_spanletvars.t = tnext;
  584. } while (count > 0);
  585. NextSpan:
  586. pspan++;
  587. } while (pspan->count != DS_SPAN_LIST_END);
  588. }
  589. /*
  590. **
  591. ** R_PolygonScanLeftEdge
  592. **
  593. ** Goes through the polygon and scans the left edge, filling in
  594. ** screen coordinate data for the spans
  595. */
  596. void R_PolygonScanLeftEdge (void)
  597. {
  598. int i, v, itop, ibottom, lmaxindex;
  599. emitpoint_t *pvert, *pnext;
  600. espan_t *pspan;
  601. float du, dv, vtop, vbottom, slope;
  602. fixed16_t u, u_step;
  603. pspan = s_polygon_spans;
  604. i = s_minindex;
  605. if (i == 0)
  606. i = r_polydesc.nump;
  607. lmaxindex = s_maxindex;
  608. if (lmaxindex == 0)
  609. lmaxindex = r_polydesc.nump;
  610. vtop = ceil (r_polydesc.pverts[i].v);
  611. do
  612. {
  613. pvert = &r_polydesc.pverts[i];
  614. pnext = pvert - 1;
  615. vbottom = ceil (pnext->v);
  616. if (vtop < vbottom)
  617. {
  618. du = pnext->u - pvert->u;
  619. dv = pnext->v - pvert->v;
  620. slope = du / dv;
  621. u_step = (int)(slope * 0x10000);
  622. // adjust u to ceil the integer portion
  623. u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
  624. (0x10000 - 1);
  625. itop = (int)vtop;
  626. ibottom = (int)vbottom;
  627. for (v=itop ; v<ibottom ; v++)
  628. {
  629. pspan->u = u >> 16;
  630. pspan->v = v;
  631. u += u_step;
  632. pspan++;
  633. }
  634. }
  635. vtop = vbottom;
  636. i--;
  637. if (i == 0)
  638. i = r_polydesc.nump;
  639. } while (i != lmaxindex);
  640. }
  641. /*
  642. ** R_PolygonScanRightEdge
  643. **
  644. ** Goes through the polygon and scans the right edge, filling in
  645. ** count values.
  646. */
  647. void R_PolygonScanRightEdge (void)
  648. {
  649. int i, v, itop, ibottom;
  650. emitpoint_t *pvert, *pnext;
  651. espan_t *pspan;
  652. float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
  653. fixed16_t u, u_step;
  654. pspan = s_polygon_spans;
  655. i = s_minindex;
  656. vvert = r_polydesc.pverts[i].v;
  657. if (vvert < r_refdef.fvrecty_adj)
  658. vvert = r_refdef.fvrecty_adj;
  659. if (vvert > r_refdef.fvrectbottom_adj)
  660. vvert = r_refdef.fvrectbottom_adj;
  661. vtop = ceil (vvert);
  662. do
  663. {
  664. pvert = &r_polydesc.pverts[i];
  665. pnext = pvert + 1;
  666. vnext = pnext->v;
  667. if (vnext < r_refdef.fvrecty_adj)
  668. vnext = r_refdef.fvrecty_adj;
  669. if (vnext > r_refdef.fvrectbottom_adj)
  670. vnext = r_refdef.fvrectbottom_adj;
  671. vbottom = ceil (vnext);
  672. if (vtop < vbottom)
  673. {
  674. uvert = pvert->u;
  675. if (uvert < r_refdef.fvrectx_adj)
  676. uvert = r_refdef.fvrectx_adj;
  677. if (uvert > r_refdef.fvrectright_adj)
  678. uvert = r_refdef.fvrectright_adj;
  679. unext = pnext->u;
  680. if (unext < r_refdef.fvrectx_adj)
  681. unext = r_refdef.fvrectx_adj;
  682. if (unext > r_refdef.fvrectright_adj)
  683. unext = r_refdef.fvrectright_adj;
  684. du = unext - uvert;
  685. dv = vnext - vvert;
  686. slope = du / dv;
  687. u_step = (int)(slope * 0x10000);
  688. // adjust u to ceil the integer portion
  689. u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
  690. (0x10000 - 1);
  691. itop = (int)vtop;
  692. ibottom = (int)vbottom;
  693. for (v=itop ; v<ibottom ; v++)
  694. {
  695. pspan->count = (u >> 16) - pspan->u;
  696. u += u_step;
  697. pspan++;
  698. }
  699. }
  700. vtop = vbottom;
  701. vvert = vnext;
  702. i++;
  703. if (i == r_polydesc.nump)
  704. i = 0;
  705. } while (i != s_maxindex);
  706. pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
  707. }
  708. /*
  709. ** R_ClipAndDrawPoly
  710. */
  711. void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured )
  712. {
  713. emitpoint_t outverts[MAXWORKINGVERTS+3], *pout;
  714. float *pv;
  715. int i, nump;
  716. float scale;
  717. vec3_t transformed, local;
  718. if ( !textured )
  719. {
  720. r_polydesc.drawspanlet = R_DrawSpanletConstant33;
  721. }
  722. else
  723. {
  724. /*
  725. ** choose the correct spanlet routine based on alpha
  726. */
  727. if ( alpha == 1 )
  728. {
  729. // isturbulent is ignored because we know that turbulent surfaces
  730. // can't be opaque
  731. r_polydesc.drawspanlet = R_DrawSpanletOpaque;
  732. }
  733. else
  734. {
  735. if ( sw_stipplealpha->value )
  736. {
  737. if ( isturbulent )
  738. {
  739. if ( alpha > 0.33 )
  740. r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple66;
  741. else
  742. r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple33;
  743. }
  744. else
  745. {
  746. if ( alpha > 0.33 )
  747. r_polydesc.drawspanlet = R_DrawSpanlet66Stipple;
  748. else
  749. r_polydesc.drawspanlet = R_DrawSpanlet33Stipple;
  750. }
  751. }
  752. else
  753. {
  754. if ( isturbulent )
  755. {
  756. if ( alpha > 0.33 )
  757. r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended66;
  758. else
  759. r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended33;
  760. }
  761. else
  762. {
  763. if ( alpha > 0.33 )
  764. r_polydesc.drawspanlet = R_DrawSpanlet66;
  765. else
  766. r_polydesc.drawspanlet = R_DrawSpanlet33;
  767. }
  768. }
  769. }
  770. }
  771. // clip to the frustum in worldspace
  772. nump = r_polydesc.nump;
  773. clip_current = 0;
  774. for (i=0 ; i<4 ; i++)
  775. {
  776. nump = R_ClipPolyFace (nump, &view_clipplanes[i]);
  777. if (nump < 3)
  778. return;
  779. if (nump > MAXWORKINGVERTS)
  780. ri.Sys_Error(ERR_DROP, "R_ClipAndDrawPoly: too many points: %d", nump );
  781. }
  782. // transform vertices into viewspace and project
  783. pv = &r_clip_verts[clip_current][0][0];
  784. for (i=0 ; i<nump ; i++)
  785. {
  786. VectorSubtract (pv, r_origin, local);
  787. TransformVector (local, transformed);
  788. if (transformed[2] < NEAR_CLIP)
  789. transformed[2] = NEAR_CLIP;
  790. pout = &outverts[i];
  791. pout->zi = 1.0 / transformed[2];
  792. pout->s = pv[3];
  793. pout->t = pv[4];
  794. scale = xscale * pout->zi;
  795. pout->u = (xcenter + scale * transformed[0]);
  796. scale = yscale * pout->zi;
  797. pout->v = (ycenter - scale * transformed[1]);
  798. pv += sizeof (vec5_t) / sizeof (pv);
  799. }
  800. // draw it
  801. r_polydesc.nump = nump;
  802. r_polydesc.pverts = outverts;
  803. R_DrawPoly( isturbulent );
  804. }
  805. /*
  806. ** R_BuildPolygonFromSurface
  807. */
  808. void R_BuildPolygonFromSurface(msurface_t *fa)
  809. {
  810. int i, lindex, lnumverts;
  811. medge_t *pedges, *r_pedge;
  812. int vertpage;
  813. float *vec;
  814. vec5_t *pverts;
  815. float tmins[2] = { 0, 0 };
  816. r_polydesc.nump = 0;
  817. // reconstruct the polygon
  818. pedges = currentmodel->edges;
  819. lnumverts = fa->numedges;
  820. vertpage = 0;
  821. pverts = r_clip_verts[0];
  822. for (i=0 ; i<lnumverts ; i++)
  823. {
  824. lindex = currentmodel->surfedges[fa->firstedge + i];
  825. if (lindex > 0)
  826. {
  827. r_pedge = &pedges[lindex];
  828. vec = currentmodel->vertexes[r_pedge->v[0]].position;
  829. }
  830. else
  831. {
  832. r_pedge = &pedges[-lindex];
  833. vec = currentmodel->vertexes[r_pedge->v[1]].position;
  834. }
  835. VectorCopy (vec, pverts[i] );
  836. }
  837. VectorCopy( fa->texinfo->vecs[0], r_polydesc.vright );
  838. VectorCopy( fa->texinfo->vecs[1], r_polydesc.vup );
  839. VectorCopy( fa->plane->normal, r_polydesc.vpn );
  840. VectorCopy( r_origin, r_polydesc.viewer_position );
  841. if ( fa->flags & SURF_PLANEBACK )
  842. {
  843. VectorSubtract( vec3_origin, r_polydesc.vpn, r_polydesc.vpn );
  844. }
  845. if ( fa->texinfo->flags & SURF_WARP )
  846. {
  847. r_polydesc.pixels = fa->texinfo->image->pixels[0];
  848. r_polydesc.pixel_width = fa->texinfo->image->width;
  849. r_polydesc.pixel_height = fa->texinfo->image->height;
  850. }
  851. else
  852. {
  853. surfcache_t *scache;
  854. scache = D_CacheSurface( fa, 0 );
  855. r_polydesc.pixels = scache->data;
  856. r_polydesc.pixel_width = scache->width;
  857. r_polydesc.pixel_height = scache->height;
  858. tmins[0] = fa->texturemins[0];
  859. tmins[1] = fa->texturemins[1];
  860. }
  861. r_polydesc.dist = DotProduct( r_polydesc.vpn, pverts[0] );
  862. r_polydesc.s_offset = fa->texinfo->vecs[0][3] - tmins[0];
  863. r_polydesc.t_offset = fa->texinfo->vecs[1][3] - tmins[1];
  864. // scrolling texture addition
  865. if (fa->texinfo->flags & SURF_FLOWING)
  866. {
  867. r_polydesc.s_offset += -128 * ( (r_newrefdef.time*0.25) - (int)(r_newrefdef.time*0.25) );
  868. }
  869. r_polydesc.nump = lnumverts;
  870. }
  871. /*
  872. ** R_PolygonCalculateGradients
  873. */
  874. void R_PolygonCalculateGradients (void)
  875. {
  876. vec3_t p_normal, p_saxis, p_taxis;
  877. float distinv;
  878. TransformVector (r_polydesc.vpn, p_normal);
  879. TransformVector (r_polydesc.vright, p_saxis);
  880. TransformVector (r_polydesc.vup, p_taxis);
  881. distinv = 1.0 / (-(DotProduct (r_polydesc.viewer_position, r_polydesc.vpn)) + r_polydesc.dist );
  882. d_sdivzstepu = p_saxis[0] * xscaleinv;
  883. d_sdivzstepv = -p_saxis[1] * yscaleinv;
  884. d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv;
  885. d_tdivzstepu = p_taxis[0] * xscaleinv;
  886. d_tdivzstepv = -p_taxis[1] * yscaleinv;
  887. d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv;
  888. d_zistepu = p_normal[0] * xscaleinv * distinv;
  889. d_zistepv = -p_normal[1] * yscaleinv * distinv;
  890. d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv;
  891. sadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vright) + r_polydesc.s_offset ) * 0x10000 );
  892. tadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vup ) + r_polydesc.t_offset ) * 0x10000 );
  893. // -1 (-epsilon) so we never wander off the edge of the texture
  894. bbextents = (r_polydesc.pixel_width << 16) - 1;
  895. bbextentt = (r_polydesc.pixel_height << 16) - 1;
  896. }
  897. /*
  898. ** R_DrawPoly
  899. **
  900. ** Polygon drawing function. Uses the polygon described in r_polydesc
  901. ** to calculate edges and gradients, then renders the resultant spans.
  902. **
  903. ** This should NOT be called externally since it doesn't do clipping!
  904. */
  905. static void R_DrawPoly( qboolean iswater )
  906. {
  907. int i, nump;
  908. float ymin, ymax;
  909. emitpoint_t *pverts;
  910. espan_t spans[MAXHEIGHT+1];
  911. s_polygon_spans = spans;
  912. // find the top and bottom vertices, and make sure there's at least one scan to
  913. // draw
  914. ymin = 999999.9;
  915. ymax = -999999.9;
  916. pverts = r_polydesc.pverts;
  917. for (i=0 ; i<r_polydesc.nump ; i++)
  918. {
  919. if (pverts->v < ymin)
  920. {
  921. ymin = pverts->v;
  922. s_minindex = i;
  923. }
  924. if (pverts->v > ymax)
  925. {
  926. ymax = pverts->v;
  927. s_maxindex = i;
  928. }
  929. pverts++;
  930. }
  931. ymin = ceil (ymin);
  932. ymax = ceil (ymax);
  933. if (ymin >= ymax)
  934. return; // doesn't cross any scans at all
  935. cachewidth = r_polydesc.pixel_width;
  936. cacheblock = r_polydesc.pixels;
  937. // copy the first vertex to the last vertex, so we don't have to deal with
  938. // wrapping
  939. nump = r_polydesc.nump;
  940. pverts = r_polydesc.pverts;
  941. pverts[nump] = pverts[0];
  942. R_PolygonCalculateGradients ();
  943. R_PolygonScanLeftEdge ();
  944. R_PolygonScanRightEdge ();
  945. R_PolygonDrawSpans( s_polygon_spans, iswater );
  946. }
  947. /*
  948. ** R_DrawAlphaSurfaces
  949. */
  950. void R_DrawAlphaSurfaces( void )
  951. {
  952. msurface_t *s = r_alpha_surfaces;
  953. currentmodel = r_worldmodel;
  954. modelorg[0] = -r_origin[0];
  955. modelorg[1] = -r_origin[1];
  956. modelorg[2] = -r_origin[2];
  957. while ( s )
  958. {
  959. R_BuildPolygonFromSurface( s );
  960. if (s->texinfo->flags & SURF_TRANS66)
  961. R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true );
  962. else
  963. R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true );
  964. s = s->nextalphasurface;
  965. }
  966. r_alpha_surfaces = NULL;
  967. }
  968. /*
  969. ** R_IMFlatShadedQuad
  970. */
  971. void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha )
  972. {
  973. vec3_t s0, s1;
  974. r_polydesc.nump = 4;
  975. VectorCopy( r_origin, r_polydesc.viewer_position );
  976. VectorCopy( a, r_clip_verts[0][0] );
  977. VectorCopy( b, r_clip_verts[0][1] );
  978. VectorCopy( c, r_clip_verts[0][2] );
  979. VectorCopy( d, r_clip_verts[0][3] );
  980. r_clip_verts[0][0][3] = 0;
  981. r_clip_verts[0][1][3] = 0;
  982. r_clip_verts[0][2][3] = 0;
  983. r_clip_verts[0][3][3] = 0;
  984. r_clip_verts[0][0][4] = 0;
  985. r_clip_verts[0][1][4] = 0;
  986. r_clip_verts[0][2][4] = 0;
  987. r_clip_verts[0][3][4] = 0;
  988. VectorSubtract( d, c, s0 );
  989. VectorSubtract( c, b, s1 );
  990. CrossProduct( s0, s1, r_polydesc.vpn );
  991. VectorNormalize( r_polydesc.vpn );
  992. r_polydesc.dist = DotProduct( r_polydesc.vpn, r_clip_verts[0][0] );
  993. r_polyblendcolor = color;
  994. R_ClipAndDrawPoly( alpha, false, false );
  995. }