T3DLIB12.CPP
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:252k
源码类别:

游戏

开发平台:

Visual C++

  1. ui+=du;
  2. vi+=dv;
  3. wi+=dw;
  4. zi+=dz;
  5. si+=ds;
  6. ti+=dt;
  7. } // end for xi
  8. // interpolate u,v,w,x along right and left edge
  9. xl+=dxdyl;
  10. ul+=dudyl;
  11. vl+=dvdyl;
  12. wl+=dwdyl;
  13. zl+=dzdyl;
  14. sl+=dsdyl;
  15. tl+=dtdyl;
  16. xr+=dxdyr;
  17. ur+=dudyr;
  18. vr+=dvdyr;
  19. wr+=dwdyr;
  20. zr+=dzdyr;
  21. sr+=dsdyr;
  22. tr+=dtdyr;
  23. // advance screen ptr
  24. screen_ptr+=mem_pitch;
  25.         // advance zbuffer ptr
  26.         z_ptr+=zpitch;
  27. } // end for y
  28. } // end if non-clipped
  29. } // end if
  30. else
  31. if (tri_type==TRI_TYPE_GENERAL)
  32. {
  33. // first test for bottom clip, always
  34. if ((yend = y2) > max_clip_y)
  35. yend = max_clip_y;
  36. // pre-test y clipping status
  37. if (y1 < min_clip_y)
  38. {
  39. // compute all deltas
  40. // LHS
  41. dyl = (y2 - y1);
  42. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  43. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  44. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  45. dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;  
  46. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  47. dsdyl = ((ts2 - ts1) << FIXP16_SHIFT)/dyl;    
  48. dtdyl = ((tt2 - tt1) << FIXP16_SHIFT)/dyl;  
  49. // RHS
  50. dyr = (y2 - y0);
  51. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  52. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  53. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  54. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;   
  55. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  56. dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dyr;   
  57. dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dyr;  
  58. // compute overclip
  59. dyr = (min_clip_y - y0);
  60. dyl = (min_clip_y - y1);
  61. // computer new LHS starting values
  62. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  63. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  64. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  65. wl = dwdyl*dyl + (tw1 << FIXP16_SHIFT);
  66. zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  67. sl = dsdyl*dyl + (ts1 << FIXP16_SHIFT);
  68. tl = dtdyl*dyl + (tt1 << FIXP16_SHIFT);
  69. // compute new RHS starting values
  70. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  71. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  72. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  73. wr = dwdyr*dyr + (tw0 << FIXP16_SHIFT);
  74. zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  75. sr = dsdyr*dyr + (ts0 << FIXP16_SHIFT);
  76. tr = dtdyr*dyr + (tt0 << FIXP16_SHIFT);
  77. // compute new starting y
  78. ystart = min_clip_y;
  79. // test if we need swap to keep rendering left to right
  80. if (dxdyr > dxdyl)
  81. {
  82. SWAP(dxdyl,dxdyr,temp);
  83. SWAP(dudyl,dudyr,temp);
  84. SWAP(dvdyl,dvdyr,temp);
  85. SWAP(dwdyl,dwdyr,temp);
  86. SWAP(dzdyl,dzdyr,temp);
  87. SWAP(dsdyl,dsdyr,temp);
  88. SWAP(dtdyl,dtdyr,temp);
  89.           SWAP(xl,xr,temp);
  90. SWAP(ul,ur,temp);
  91. SWAP(vl,vr,temp);
  92. SWAP(wl,wr,temp);
  93. SWAP(zl,zr,temp);
  94. SWAP(sl,sr,temp);
  95. SWAP(tl,tr,temp);
  96. SWAP(x1,x2,temp);
  97. SWAP(y1,y2,temp);
  98. SWAP(tu1,tu2,temp);
  99. SWAP(tv1,tv2,temp);
  100. SWAP(tw1,tw2,temp);
  101. SWAP(tz1,tz2,temp);
  102. SWAP(ts1,ts2,temp);
  103. SWAP(tt1,tt2,temp);
  104. // set interpolation restart
  105. irestart = INTERP_RHS;
  106. } // end if
  107. } // end if
  108. else
  109. if (y0 < min_clip_y)
  110. {
  111. // compute all deltas
  112. // LHS
  113. dyl = (y1 - y0);
  114. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  115. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  116. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  117. dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl; 
  118. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl; 
  119. dsdyl = ((ts1 - ts0) << FIXP16_SHIFT)/dyl;    
  120. dtdyl = ((tt1 - tt0) << FIXP16_SHIFT)/dyl; 
  121. // RHS
  122. dyr = (y2 - y0);
  123. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  124. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  125. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  126. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;   
  127. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  128. dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dyr;   
  129. dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dyr;   
  130. // compute overclip
  131. dy = (min_clip_y - y0);
  132. // computer new LHS starting values
  133. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  134. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  135. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  136. wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
  137. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  138. sl = dsdyl*dy + (ts0 << FIXP16_SHIFT);
  139. tl = dtdyl*dy + (tt0 << FIXP16_SHIFT);
  140. // compute new RHS starting values
  141. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  142. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  143. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  144. wr = dwdyr*dy + (tw0 << FIXP16_SHIFT);
  145. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  146. sr = dsdyr*dy + (ts0 << FIXP16_SHIFT);
  147. tr = dtdyr*dy + (tt0 << FIXP16_SHIFT);
  148. // compute new starting y
  149. ystart = min_clip_y;
  150. // test if we need swap to keep rendering left to right
  151. if (dxdyr < dxdyl)
  152. {
  153. SWAP(dxdyl,dxdyr,temp);
  154. SWAP(dudyl,dudyr,temp);
  155. SWAP(dvdyl,dvdyr,temp);
  156. SWAP(dwdyl,dwdyr,temp);
  157. SWAP(dzdyl,dzdyr,temp);
  158. SWAP(dsdyl,dsdyr,temp);
  159. SWAP(dtdyl,dtdyr,temp);
  160. SWAP(xl,xr,temp);
  161. SWAP(ul,ur,temp);
  162. SWAP(vl,vr,temp);
  163. SWAP(wl,wr,temp);
  164. SWAP(zl,zr,temp);
  165. SWAP(sl,sr,temp);
  166. SWAP(tl,tr,temp);
  167. SWAP(x1,x2,temp);
  168. SWAP(y1,y2,temp);
  169. SWAP(tu1,tu2,temp);
  170. SWAP(tv1,tv2,temp);
  171. SWAP(tw1,tw2,temp);
  172. SWAP(tz1,tz2,temp);
  173. SWAP(ts1,ts2,temp);
  174. SWAP(tt1,tt2,temp);
  175. // set interpolation restart
  176. irestart = INTERP_RHS;
  177. } // end if
  178. } // end if
  179. else
  180. {
  181. // no initial y clipping
  182. // compute all deltas
  183. // LHS
  184. dyl = (y1 - y0);
  185. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  186. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  187. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  188. dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl;   
  189. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;  
  190. dsdyl = ((ts1 - ts0) << FIXP16_SHIFT)/dyl;    
  191. dtdyl = ((tt1 - tt0) << FIXP16_SHIFT)/dyl;   
  192. // RHS
  193. dyr = (y2 - y0);
  194. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  195. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  196. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  197. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;
  198. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
  199. dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dyr;   
  200. dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dyr;
  201. // no clipping y
  202. // set starting values
  203. xl = (x0 << FIXP16_SHIFT);
  204. xr = (x0 << FIXP16_SHIFT);
  205. ul = (tu0 << FIXP16_SHIFT);
  206. vl = (tv0 << FIXP16_SHIFT);
  207. wl = (tw0 << FIXP16_SHIFT);
  208. zl = (tz0 << FIXP16_SHIFT);
  209. sl = (ts0 << FIXP16_SHIFT);
  210. tl = (tt0 << FIXP16_SHIFT);
  211. ur = (tu0 << FIXP16_SHIFT);
  212. vr = (tv0 << FIXP16_SHIFT);
  213. wr = (tw0 << FIXP16_SHIFT);
  214. zr = (tz0 << FIXP16_SHIFT);
  215. sr = (ts0 << FIXP16_SHIFT);
  216. tr = (tt0 << FIXP16_SHIFT);
  217. // set starting y
  218. ystart = y0;
  219. // test if we need swap to keep rendering left to right
  220. if (dxdyr < dxdyl)
  221. {
  222. SWAP(dxdyl,dxdyr,temp);
  223. SWAP(dudyl,dudyr,temp);
  224. SWAP(dvdyl,dvdyr,temp);
  225. SWAP(dwdyl,dwdyr,temp);
  226. SWAP(dzdyl,dzdyr,temp);
  227. SWAP(dsdyl,dsdyr,temp);
  228. SWAP(dtdyl,dtdyr,temp);
  229. SWAP(xl,xr,temp);
  230. SWAP(ul,ur,temp);
  231. SWAP(vl,vr,temp);
  232. SWAP(wl,wr,temp);
  233. SWAP(zl,zr,temp);
  234. SWAP(sl,sr,temp);
  235. SWAP(tl,tr,temp);
  236. SWAP(x1,x2,temp);
  237. SWAP(y1,y2,temp);
  238. SWAP(tu1,tu2,temp);
  239. SWAP(tv1,tv2,temp);
  240. SWAP(tw1,tw2,temp);
  241. SWAP(tz1,tz2,temp);
  242. SWAP(ts1,ts2,temp);
  243. SWAP(tt1,tt2,temp);
  244. // set interpolation restart
  245. irestart = INTERP_RHS;
  246. } // end if
  247. } // end else
  248.     // test for horizontal clipping
  249. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  250. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  251. (x2 < min_clip_x) || (x2 > max_clip_x))
  252. {
  253.     // clip version
  254. // x clipping
  255. // point screen ptr to starting line
  256. screen_ptr = dest_buffer + (ystart * mem_pitch);
  257.     // point zbuffer to starting line
  258.     z_ptr = zbuffer + (ystart * zpitch);
  259. for (yi = ystart; yi < yend; yi++)
  260. {
  261. // compute span endpoints
  262. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  263. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  264. // compute starting points for u,v,w interpolants
  265. ui = ul + FIXP16_ROUND_UP;
  266. vi = vl + FIXP16_ROUND_UP;
  267. wi = wl + FIXP16_ROUND_UP;
  268. zi = zl + FIXP16_ROUND_UP;
  269. si = sl + FIXP16_ROUND_UP;
  270. ti = tl + FIXP16_ROUND_UP;
  271. // compute u,v interpolants
  272. if ((dx = (xend - xstart))>0)
  273. {
  274. du = (ur - ul)/dx;
  275. dv = (vr - vl)/dx;
  276. dw = (wr - wl)/dx;
  277. dz = (zr - zl)/dx;
  278. ds = (sr - sl)/dx;
  279. dt = (tr - tl)/dx;
  280. } // end if
  281. else
  282. {
  283. du = (ur - ul);
  284. dv = (vr - vl);
  285. dw = (wr - wl);
  286. dz = (zr - zl);
  287. ds = (sr - sl);
  288. dt = (tr - tl);
  289. } // end else
  290. ///////////////////////////////////////////////////////////////////////
  291. // test for x clipping, LHS
  292. if (xstart < min_clip_x)
  293. {
  294. // compute x overlap
  295. dx = min_clip_x - xstart;
  296. // slide interpolants over
  297. ui+=dx*du;
  298. vi+=dx*dv;
  299. wi+=dx*dw;
  300. zi+=dx*dz;
  301. si+=dx*ds;
  302. ti+=dx*dt;
  303. // set x to left clip edge
  304. xstart = min_clip_x;
  305. } // end if
  306. // test for x clipping RHS
  307. if (xend > max_clip_x)
  308. xend = max_clip_x;
  309. ///////////////////////////////////////////////////////////////////////
  310. // draw span
  311. for (xi=xstart; xi < xend; xi++)
  312. {
  313. // write textel assume 5.6.5
  314.             // write thru z buffer always
  315.     // get textel first
  316.   textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
  317.             if (textel)
  318.             {
  319.            
  320.             // extract rgb components
  321.             r_textel  = ((textel >> 11)       ); 
  322.             g_textel  = ((textel >> 5)  & 0x3f); 
  323.             b_textel =   (textel        & 0x1f);
  324.             // modulate textel with gouraud shading
  325.             r_textel*=ui; 
  326.             g_textel*=vi;
  327.             b_textel*=wi;
  328.             // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  329.             // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  330.             // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  331.             // and they all cancel out for the most part, but we will need logical anding, we will do
  332.             // it later when we optimize more...
  333.             screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) + 
  334.                              ((g_textel >> (FIXP16_SHIFT+8)) << 5) + 
  335.                              ((r_textel >> (FIXP16_SHIFT+8)) << 11));
  336.             // update z-buffer
  337.             z_ptr[xi] = zi;   
  338.             } // end if
  339. // interpolate u,v
  340. ui+=du;
  341. vi+=dv;
  342. wi+=dw;
  343. zi+=dz;
  344. si+=ds;
  345. ti+=dt;
  346. } // end for xi
  347. // interpolate u,v,w,x along right and left edge
  348. xl+=dxdyl;
  349.         ul+=dudyl;
  350. vl+=dvdyl;
  351. wl+=dwdyl;
  352. zl+=dzdyl;
  353. sl+=dsdyl;
  354. tl+=dtdyl;
  355. xr+=dxdyr;
  356.       ur+=dudyr;
  357. vr+=dvdyr;
  358. wr+=dwdyr;
  359. zr+=dzdyr;
  360. sr+=dsdyr;
  361. tr+=dtdyr;
  362. // advance screen ptr
  363. screen_ptr+=mem_pitch;
  364.         // advance zbuffer ptr
  365.         z_ptr+=zpitch;
  366. // test for yi hitting second region, if so change interpolant
  367. if (yi==yrestart)
  368. {
  369.     // test interpolation side change flag
  370. if (irestart == INTERP_LHS)
  371. {
  372. // LHS
  373. dyl = (y2 - y1);
  374. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  375. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  376. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  377. dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;  
  378. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  379. dsdyl = ((ts2 - ts1) << FIXP16_SHIFT)/dyl;   
  380. dtdyl = ((tt2 - tt1) << FIXP16_SHIFT)/dyl;  
  381. // set starting values
  382. xl = (x1  << FIXP16_SHIFT);
  383. ul = (tu1 << FIXP16_SHIFT);
  384. vl = (tv1 << FIXP16_SHIFT);
  385. wl = (tw1 << FIXP16_SHIFT);
  386. zl = (tz1 << FIXP16_SHIFT);
  387. sl = (ts1 << FIXP16_SHIFT);
  388. tl = (tt1 << FIXP16_SHIFT);
  389. // interpolate down on LHS to even up
  390. xl+=dxdyl;
  391. ul+=dudyl;
  392. vl+=dvdyl;
  393. wl+=dwdyl;
  394. zl+=dzdyl;
  395. sl+=dsdyl;
  396. tl+=dtdyl;
  397. } // end if
  398. else
  399. {
  400. // RHS
  401. dyr = (y1 - y2);
  402. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  403. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  404. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  405. dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;   
  406. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  407. dsdyr = ((ts1 - ts2) << FIXP16_SHIFT)/dyr;   
  408. dtdyr = ((tt1 - tt2) << FIXP16_SHIFT)/dyr;  
  409. // set starting values
  410. xr = (x2  << FIXP16_SHIFT);
  411. ur = (tu2 << FIXP16_SHIFT);
  412. vr = (tv2 << FIXP16_SHIFT);
  413. wr = (tw2 << FIXP16_SHIFT);
  414. zr = (tz2 << FIXP16_SHIFT);
  415. sr = (ts2 << FIXP16_SHIFT);
  416. tr = (tt2 << FIXP16_SHIFT);
  417. // interpolate down on RHS to even up
  418. xr+=dxdyr;
  419. ur+=dudyr;
  420. vr+=dvdyr;
  421. wr+=dwdyr;
  422. zr+=dzdyr;
  423. sr+=dsdyr;
  424. tr+=dtdyr;
  425. } // end else
  426. } // end if
  427. } // end for y
  428. } // end if
  429. else
  430. {
  431. // no x clipping
  432. // point screen ptr to starting line
  433. screen_ptr = dest_buffer + (ystart * mem_pitch);
  434.     // point zbuffer to starting line
  435.     z_ptr = zbuffer + (ystart * zpitch);
  436. for (yi = ystart; yi < yend; yi++)
  437. {
  438. // compute span endpoints
  439. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  440. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  441. // compute starting points for u,v,w interpolants
  442. ui = ul + FIXP16_ROUND_UP;
  443. vi = vl + FIXP16_ROUND_UP;
  444. wi = wl + FIXP16_ROUND_UP;
  445. zi = zl + FIXP16_ROUND_UP;
  446. si = sl + FIXP16_ROUND_UP;
  447. ti = tl + FIXP16_ROUND_UP;
  448. // compute u,v interpolants
  449. if ((dx = (xend - xstart))>0)
  450. {
  451. du = (ur - ul)/dx;
  452. dv = (vr - vl)/dx;
  453. dw = (wr - wl)/dx;
  454. dz = (zr - zl)/dx;
  455. ds = (sr - sl)/dx;
  456. dt = (tr - tl)/dx;
  457. } // end if
  458. else
  459. {
  460. du = (ur - ul);
  461. dv = (vr - vl);
  462. dw = (wr - wl);
  463. dz = (zr - zl);
  464. ds = (sr - sl);
  465. dt = (tr - tl);
  466. } // end else
  467. // draw span
  468. for (xi=xstart; xi < xend; xi++)
  469. {
  470. // write textel assume 5.6.5
  471.             // write thru z buffer always
  472.     // get textel first
  473.   textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
  474.             if (textel)
  475.             {
  476.            
  477.             // extract rgb components
  478.             r_textel  = ((textel >> 11)       ); 
  479.             g_textel  = ((textel >> 5)  & 0x3f); 
  480.             b_textel =   (textel        & 0x1f);
  481.             // modulate textel with gouraud shading
  482.             r_textel*=ui; 
  483.             g_textel*=vi;
  484.             b_textel*=wi;
  485.             // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  486.             // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  487.             // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  488.             // and they all cancel out for the most part, but we will need logical anding, we will do
  489.             // it later when we optimize more...
  490.             screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) + 
  491.                              ((g_textel >> (FIXP16_SHIFT+8)) << 5) + 
  492.                              ((r_textel >> (FIXP16_SHIFT+8)) << 11));
  493.             // update z-buffer
  494.             z_ptr[xi] = zi;   
  495.             } // end if
  496. // interpolate u,v
  497. ui+=du;
  498. vi+=dv;
  499. wi+=dw;
  500. zi+=dz;
  501. si+=ds;
  502. ti+=dt;
  503. } // end for xi
  504. // interpolate u,v,w,x along right and left edge
  505. xl+=dxdyl;
  506. ul+=dudyl;
  507. vl+=dvdyl;
  508. wl+=dwdyl;
  509. zl+=dzdyl;
  510. sl+=dsdyl;
  511. tl+=dtdyl;
  512. xr+=dxdyr;
  513. ur+=dudyr;
  514. vr+=dvdyr;
  515. wr+=dwdyr;
  516. zr+=dzdyr;
  517. sr+=dsdyr;
  518. tr+=dtdyr;
  519. // advance screen ptr
  520. screen_ptr+=mem_pitch;
  521.         // advance zbuffer ptr
  522.         z_ptr+=zpitch;
  523. // test for yi hitting second region, if so change interpolant
  524. if (yi==yrestart)
  525. {
  526. // test interpolation side change flag
  527. if (irestart == INTERP_LHS)
  528. {
  529. // LHS
  530. dyl = (y2 - y1);
  531. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  532. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  533. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  534. dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;   
  535. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  536. dsdyl = ((ts2 - ts1) << FIXP16_SHIFT)/dyl;   
  537. dtdyl = ((tt2 - tt1) << FIXP16_SHIFT)/dyl;   
  538. // set starting values
  539. xl = (x1  << FIXP16_SHIFT);
  540. ul = (tu1 << FIXP16_SHIFT);
  541. vl = (tv1 << FIXP16_SHIFT);
  542. wl = (tw1 << FIXP16_SHIFT);
  543. zl = (tz1 << FIXP16_SHIFT);
  544. sl = (ts1 << FIXP16_SHIFT);
  545. tl = (tt1 << FIXP16_SHIFT);
  546. // interpolate down on LHS to even up
  547. xl+=dxdyl;
  548. ul+=dudyl;
  549. vl+=dvdyl;
  550. wl+=dwdyl;
  551. zl+=dzdyl;
  552. sl+=dsdyl;
  553. tl+=dtdyl;
  554. } // end if
  555. else
  556. {
  557. // RHS
  558. dyr = (y1 - y2);
  559. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  560. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  561. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  562. dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;   
  563. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  564. dsdyr = ((ts1 - ts2) << FIXP16_SHIFT)/dyr;   
  565. dtdyr = ((tt1 - tt2) << FIXP16_SHIFT)/dyr;   
  566. // set starting values
  567. xr = (x2  << FIXP16_SHIFT);
  568. ur = (tu2 << FIXP16_SHIFT);
  569. vr = (tv2 << FIXP16_SHIFT);
  570. wr = (tw2 << FIXP16_SHIFT);
  571. zr = (tz2 << FIXP16_SHIFT);
  572. sr = (ts2 << FIXP16_SHIFT);
  573. tr = (tt2 << FIXP16_SHIFT);
  574. // interpolate down on RHS to even up
  575. xr+=dxdyr;
  576. ur+=dudyr;
  577. vr+=dvdyr;
  578. wr+=dwdyr;
  579. zr+=dzdyr;
  580. sr+=dsdyr;
  581. tr+=dtdyr;
  582. } // end else
  583. } // end if
  584. } // end for y
  585.    } // end else
  586. } // end if
  587. } // end Draw_Textured_TriangleGSWTZB2_16
  588. ///////////////////////////////////////////////////////////////////////////////////////////////////
  589. void Draw_Textured_Triangle_Alpha16_2(POLYF4DV2_PTR face,   // ptr to face
  590.                                 UCHAR *_dest_buffer,      // pointer to video buffer
  591.                                 int mem_pitch, int alpha) // bytes per line, 320, 640 etc.
  592. {
  593. // this function draws a textured triangle in 16-bit mode
  594. int v0=0,
  595.     v1=1,
  596. v2=2,
  597. temp=0,
  598. tri_type = TRI_TYPE_NONE,
  599. irestart = INTERP_LHS;
  600. int dx,dy,dyl,dyr,      // general deltas
  601.     u,v,
  602.     du,dv,
  603.     xi,yi,              // the current interpolated x,y
  604. ui,vi,              // the current interpolated u,v
  605. index_x,index_y,    // looping vars
  606. x,y,                // hold general x,y
  607. xstart,
  608. xend,
  609. ystart,
  610. yrestart,
  611. yend,
  612. xl,                 
  613. dxdyl,              
  614. xr,
  615. dxdyr,             
  616. dudyl,    
  617. ul,
  618. dvdyl,   
  619. vl,
  620. dudyr,
  621. ur,
  622. dvdyr,
  623. vr;
  624. int x0,y0,tu0,tv0,    // cached vertices
  625. x1,y1,tu1,tv1,
  626. x2,y2,tu2,tv2;
  627. USHORT *screen_ptr  = NULL,
  628.    *screen_line = NULL,
  629.    *textmap     = NULL,
  630.        *dest_buffer = (USHORT *)_dest_buffer,
  631.        textel;
  632. #ifdef DEBUG_ON
  633. // track rendering stats
  634.     debug_polys_rendered_per_frame++;
  635. #endif
  636. // extract texture map
  637. textmap = (USHORT *)face->texture->buffer;
  638. // extract base 2 of texture width
  639. int texture_shift2 = logbase2ofx[face->texture->width];
  640. // adjust memory pitch to words, divide by 2
  641. mem_pitch >>=1;
  642. // apply fill convention to coordinates
  643. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  644. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  645. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  646. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  647. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  648. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  649. // first trivial clipping rejection tests 
  650. if (((face->tvlist[0].y < min_clip_y)  && 
  651.  (face->tvlist[1].y < min_clip_y)  &&
  652.  (face->tvlist[2].y < min_clip_y)) ||
  653. ((face->tvlist[0].y > max_clip_y)  && 
  654.  (face->tvlist[1].y > max_clip_y)  &&
  655.  (face->tvlist[2].y > max_clip_y)) ||
  656. ((face->tvlist[0].x < min_clip_x)  && 
  657.  (face->tvlist[1].x < min_clip_x)  &&
  658.  (face->tvlist[2].x < min_clip_x)) ||
  659. ((face->tvlist[0].x > max_clip_x)  && 
  660.  (face->tvlist[1].x > max_clip_x)  &&
  661.  (face->tvlist[2].x > max_clip_x)))
  662.    return;
  663. // sort vertices
  664. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  665. {SWAP(v0,v1,temp);} 
  666. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  667. {SWAP(v0,v2,temp);}
  668. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  669. {SWAP(v1,v2,temp);}
  670. // now test for trivial flat sided cases
  671. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  672. // set triangle type
  673. tri_type = TRI_TYPE_FLAT_TOP;
  674. // sort vertices left to right
  675. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  676. {SWAP(v0,v1,temp);}
  677. } // end if
  678. else
  679. // now test for trivial flat sided cases
  680. if (FCMP(face->tvlist[v1].y, face->tvlist[v2].y) )
  681. // set triangle type
  682. tri_type = TRI_TYPE_FLAT_BOTTOM;
  683. // sort vertices left to right
  684. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  685. {SWAP(v1,v2,temp);}
  686. } // end if
  687. else
  688. {
  689. // must be a general triangle
  690. tri_type = TRI_TYPE_GENERAL;
  691. } // end else
  692. // extract vertices for processing, now that we have order
  693. x0  = (int)(face->tvlist[v0].x+0.0);
  694. y0  = (int)(face->tvlist[v0].y+0.0);
  695. tu0 = (int)(face->tvlist[v0].u0);
  696. tv0 = (int)(face->tvlist[v0].v0);
  697. x1  = (int)(face->tvlist[v1].x+0.0);
  698. y1  = (int)(face->tvlist[v1].y+0.0);
  699. tu1 = (int)(face->tvlist[v1].u0);
  700. tv1 = (int)(face->tvlist[v1].v0);
  701. x2  = (int)(face->tvlist[v2].x+0.0);
  702. y2  = (int)(face->tvlist[v2].y+0.0);
  703. tu2 = (int)(face->tvlist[v2].u0);
  704. tv2 = (int)(face->tvlist[v2].v0);
  705. // degenerate triangle
  706. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  707.    return;
  708. // assign both source1 and source2 alpha tables based on polygon alpha level
  709. USHORT *alpha_table_src1 = (USHORT *)&rgb_alpha_table[(NUM_ALPHA_LEVELS-1) - alpha][0];
  710. USHORT *alpha_table_src2 = (USHORT *)&rgb_alpha_table[alpha][0];
  711. // set interpolation restart value
  712. yrestart = y1;
  713. // what kind of triangle
  714. if (tri_type & TRI_TYPE_FLAT_MASK)
  715. {
  716. if (tri_type == TRI_TYPE_FLAT_TOP)
  717. {
  718. // compute all deltas
  719. dy = (y2 - y0);
  720. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  721. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  722. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  723. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  724. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  725. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  726. // test for y clipping
  727. if (y0 < min_clip_y)
  728. {
  729. // compute overclip
  730. dy = (min_clip_y - y0);
  731. // computer new LHS starting values
  732. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  733. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  734. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  735. // compute new RHS starting values
  736. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  737. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  738. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  739. // compute new starting y
  740. ystart = min_clip_y;
  741. } // end if
  742. else
  743. {
  744. // no clipping
  745. // set starting values
  746. xl = (x0 << FIXP16_SHIFT);
  747. xr = (x1 << FIXP16_SHIFT);
  748. ul = (tu0 << FIXP16_SHIFT);
  749. vl = (tv0 << FIXP16_SHIFT);
  750. ur = (tu1 << FIXP16_SHIFT);
  751. vr = (tv1 << FIXP16_SHIFT);
  752. // set starting y
  753. ystart = y0;
  754. } // end else
  755. } // end if flat top
  756. else
  757. {
  758. // must be flat bottom
  759. // compute all deltas
  760. dy = (y1 - y0);
  761. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  762. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  763. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  764. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  765. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  766. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  767. // test for y clipping
  768. if (y0 < min_clip_y)
  769. {
  770. // compute overclip
  771. dy = (min_clip_y - y0);
  772. // computer new LHS starting values
  773. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  774. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  775. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  776. // compute new RHS starting values
  777. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  778. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  779. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  780. // compute new starting y
  781. ystart = min_clip_y;
  782. } // end if
  783. else
  784. {
  785. // no clipping
  786. // set starting values
  787. xl = (x0 << FIXP16_SHIFT);
  788. xr = (x0 << FIXP16_SHIFT);
  789. ul = (tu0 << FIXP16_SHIFT);
  790. vl = (tv0 << FIXP16_SHIFT);
  791. ur = (tu0 << FIXP16_SHIFT);
  792. vr = (tv0 << FIXP16_SHIFT);
  793. // set starting y
  794. ystart = y0;
  795. } // end else
  796. } // end else flat bottom
  797. // test for bottom clip, always
  798. if ((yend = y2) > max_clip_y)
  799. yend = max_clip_y;
  800.     // test for horizontal clipping
  801. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  802. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  803. (x2 < min_clip_x) || (x2 > max_clip_x))
  804. {
  805.     // clip version
  806. // point screen ptr to starting line
  807. screen_ptr = dest_buffer + (ystart * mem_pitch);
  808. for (yi = ystart; yi < yend; yi++)
  809. {
  810. // compute span endpoints
  811. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  812. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  813. // compute starting points for u,v interpolants
  814. ui = ul + FIXP16_ROUND_UP;
  815. vi = vl + FIXP16_ROUND_UP;
  816. // compute u,v interpolants
  817. if ((dx = (xend - xstart))>0)
  818. {
  819. du = (ur - ul)/dx;
  820. dv = (vr - vl)/dx;
  821. } // end if
  822. else
  823. {
  824. du = (ur - ul);
  825. dv = (vr - vl);
  826. } // end else
  827. ///////////////////////////////////////////////////////////////////////
  828. // test for x clipping, LHS
  829. if (xstart < min_clip_x)
  830. {
  831. // compute x overlap
  832. dx = min_clip_x - xstart;
  833. // slide interpolants over
  834. ui+=dx*du;
  835. vi+=dx*dv;
  836. // reset vars
  837. xstart = min_clip_x;
  838. } // end if
  839. // test for x clipping RHS
  840. if (xend > max_clip_x)
  841. xend = max_clip_x;
  842. ///////////////////////////////////////////////////////////////////////
  843. // draw span
  844. for (xi=xstart; xi < xend; xi++)
  845. {
  846. // write textel
  847.             // check for transparency
  848.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  849.             if (textel)
  850.                {
  851.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + alpha_table_src2[textel];
  852.                } // end if
  853. // interpolate u,v
  854. ui+=du;
  855. vi+=dv;
  856. } // end for xi
  857. // interpolate u,v,x along right and left edge
  858. xl+=dxdyl;
  859. ul+=dudyl;
  860. vl+=dvdyl;
  861. xr+=dxdyr;
  862. ur+=dudyr;
  863. vr+=dvdyr;
  864.  
  865. // advance screen ptr
  866. screen_ptr+=mem_pitch;
  867. } // end for y
  868. } // end if clip
  869. else
  870. {
  871. // non-clip version
  872. // point screen ptr to starting line
  873. screen_ptr = dest_buffer + (ystart * mem_pitch);
  874. for (yi = ystart; yi < yend; yi++)
  875. {
  876. // compute span endpoints
  877. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  878. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  879. // compute starting points for u,v interpolants
  880. ui = ul + FIXP16_ROUND_UP;
  881. vi = vl + FIXP16_ROUND_UP;
  882. // compute u,v interpolants
  883. if ((dx = (xend - xstart))>0)
  884. {
  885. du = (ur - ul)/dx;
  886. dv = (vr - vl)/dx;
  887. } // end if
  888. else
  889. {
  890. du = (ur - ul);
  891. dv = (vr - vl);
  892. } // end else
  893. // draw span
  894. for (xi=xstart; xi < xend; xi++)
  895. {
  896. // write textel
  897.             // check for transparency
  898.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  899.             if (textel)
  900.                {
  901.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + alpha_table_src2[textel];
  902.                } // end if
  903. // interpolate u,v
  904. ui+=du;
  905. vi+=dv;
  906. } // end for xi
  907. // interpolate u,v,x along right and left edge
  908. xl+=dxdyl;
  909. ul+=dudyl;
  910. vl+=dvdyl;
  911. xr+=dxdyr;
  912. ur+=dudyr;
  913. vr+=dvdyr;
  914. // advance screen ptr
  915. screen_ptr+=mem_pitch;
  916. } // end for y
  917. } // end if non-clipped
  918. } // end if
  919. else
  920. if (tri_type==TRI_TYPE_GENERAL)
  921. {
  922. // first test for bottom clip, always
  923. if ((yend = y2) > max_clip_y)
  924. yend = max_clip_y;
  925. // pre-test y clipping status
  926. if (y1 < min_clip_y)
  927. {
  928. // compute all deltas
  929. // LHS
  930. dyl = (y2 - y1);
  931. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  932. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  933. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  934. // RHS
  935. dyr = (y2 - y0);
  936. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  937. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  938. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  939. // compute overclip
  940. dyr = (min_clip_y - y0);
  941. dyl = (min_clip_y - y1);
  942. // computer new LHS starting values
  943. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  944. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  945. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  946. // compute new RHS starting values
  947. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  948. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  949. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  950. // compute new starting y
  951. ystart = min_clip_y;
  952. // test if we need swap to keep rendering left to right
  953. if (dxdyr > dxdyl)
  954. {
  955. SWAP(dxdyl,dxdyr,temp);
  956. SWAP(dudyl,dudyr,temp);
  957. SWAP(dvdyl,dvdyr,temp);
  958. SWAP(xl,xr,temp);
  959. SWAP(ul,ur,temp);
  960. SWAP(vl,vr,temp);
  961. SWAP(x1,x2,temp);
  962. SWAP(y1,y2,temp);
  963. SWAP(tu1,tu2,temp);
  964. SWAP(tv1,tv2,temp);
  965. // set interpolation restart
  966. irestart = INTERP_RHS;
  967. } // end if
  968. } // end if
  969. else
  970. if (y0 < min_clip_y)
  971. {
  972. // compute all deltas
  973. // LHS
  974. dyl = (y1 - y0);
  975. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  976. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  977. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  978. // RHS
  979. dyr = (y2 - y0);
  980. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  981. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  982. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  983. // compute overclip
  984. dy = (min_clip_y - y0);
  985. // computer new LHS starting values
  986. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  987. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  988. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  989. // compute new RHS starting values
  990. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  991. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  992. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  993. // compute new starting y
  994. ystart = min_clip_y;
  995. // test if we need swap to keep rendering left to right
  996. if (dxdyr < dxdyl)
  997. {
  998. SWAP(dxdyl,dxdyr,temp);
  999. SWAP(dudyl,dudyr,temp);
  1000. SWAP(dvdyl,dvdyr,temp);
  1001. SWAP(xl,xr,temp);
  1002. SWAP(ul,ur,temp);
  1003. SWAP(vl,vr,temp);
  1004. SWAP(x1,x2,temp);
  1005. SWAP(y1,y2,temp);
  1006. SWAP(tu1,tu2,temp);
  1007. SWAP(tv1,tv2,temp);
  1008. // set interpolation restart
  1009. irestart = INTERP_RHS;
  1010. } // end if
  1011. } // end if
  1012. else
  1013. {
  1014. // no initial y clipping
  1015. // compute all deltas
  1016. // LHS
  1017. dyl = (y1 - y0);
  1018. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1019. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  1020. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  1021. // RHS
  1022. dyr = (y2 - y0);
  1023. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  1024. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1025. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1026. // no clipping y
  1027. // set starting values
  1028. xl = (x0 << FIXP16_SHIFT);
  1029. xr = (x0 << FIXP16_SHIFT);
  1030. ul = (tu0 << FIXP16_SHIFT);
  1031. vl = (tv0 << FIXP16_SHIFT);
  1032. ur = (tu0 << FIXP16_SHIFT);
  1033. vr = (tv0 << FIXP16_SHIFT);
  1034. // set starting y
  1035. ystart = y0;
  1036. // test if we need swap to keep rendering left to right
  1037. if (dxdyr < dxdyl)
  1038. {
  1039. SWAP(dxdyl,dxdyr,temp);
  1040. SWAP(dudyl,dudyr,temp);
  1041. SWAP(dvdyl,dvdyr,temp);
  1042. SWAP(xl,xr,temp);
  1043. SWAP(ul,ur,temp);
  1044. SWAP(vl,vr,temp);
  1045. SWAP(x1,x2,temp);
  1046. SWAP(y1,y2,temp);
  1047. SWAP(tu1,tu2,temp);
  1048. SWAP(tv1,tv2,temp);
  1049. // set interpolation restart
  1050. irestart = INTERP_RHS;
  1051. } // end if
  1052. } // end else
  1053.     // test for horizontal clipping
  1054. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1055. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1056. (x2 < min_clip_x) || (x2 > max_clip_x))
  1057. {
  1058.     // clip version
  1059. // x clipping
  1060. // point screen ptr to starting line
  1061. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1062. for (yi = ystart; yi < yend; yi++)
  1063. {
  1064. // compute span endpoints
  1065. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1066. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1067. // compute starting points for u,v interpolants
  1068. ui = ul + FIXP16_ROUND_UP;
  1069. vi = vl + FIXP16_ROUND_UP;
  1070. // compute u,v interpolants
  1071. if ((dx = (xend - xstart))>0)
  1072. {
  1073. du = (ur - ul)/dx;
  1074. dv = (vr - vl)/dx;
  1075. } // end if
  1076. else
  1077. {
  1078. du = (ur - ul);
  1079. dv = (vr - vl);
  1080. } // end else
  1081. ///////////////////////////////////////////////////////////////////////
  1082. // test for x clipping, LHS
  1083. if (xstart < min_clip_x)
  1084. {
  1085. // compute x overlap
  1086. dx = min_clip_x - xstart;
  1087. // slide interpolants over
  1088. ui+=dx*du;
  1089. vi+=dx*dv;
  1090. // set x to left clip edge
  1091. xstart = min_clip_x;
  1092. } // end if
  1093. // test for x clipping RHS
  1094. if (xend > max_clip_x)
  1095. xend = max_clip_x;
  1096. ///////////////////////////////////////////////////////////////////////
  1097. // draw span
  1098. for (xi=xstart; xi < xend; xi++)
  1099. {
  1100. // write textel
  1101.             // check for transparency
  1102.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1103.             if (textel)
  1104.                {
  1105.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + alpha_table_src2[textel];
  1106.                } // end if
  1107. // interpolate u,v
  1108. ui+=du;
  1109. vi+=dv;
  1110. } // end for xi
  1111. // interpolate u,v,x along right and left edge
  1112. xl+=dxdyl;
  1113. ul+=dudyl;
  1114. vl+=dvdyl;
  1115. xr+=dxdyr;
  1116. ur+=dudyr;
  1117. vr+=dvdyr;
  1118. // advance screen ptr
  1119. screen_ptr+=mem_pitch;
  1120. // test for yi hitting second region, if so change interpolant
  1121. if (yi==yrestart)
  1122. {
  1123.     // test interpolation side change flag
  1124. if (irestart == INTERP_LHS)
  1125. {
  1126. // LHS
  1127. dyl = (y2 - y1);
  1128. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1129. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1130. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1131. // set starting values
  1132. xl = (x1  << FIXP16_SHIFT);
  1133. ul = (tu1 << FIXP16_SHIFT);
  1134. vl = (tv1 << FIXP16_SHIFT);
  1135. // interpolate down on LHS to even up
  1136. xl+=dxdyl;
  1137. ul+=dudyl;
  1138. vl+=dvdyl;
  1139. } // end if
  1140. else
  1141. {
  1142. // RHS
  1143. dyr = (y1 - y2);
  1144. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1145. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1146. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1147. // set starting values
  1148. xr = (x2  << FIXP16_SHIFT);
  1149. ur = (tu2 << FIXP16_SHIFT);
  1150. vr = (tv2 << FIXP16_SHIFT);
  1151. // interpolate down on RHS to even up
  1152. xr+=dxdyr;
  1153. ur+=dudyr;
  1154. vr+=dvdyr;
  1155. } // end else
  1156. } // end if
  1157. } // end for y
  1158. } // end if
  1159. else
  1160. {
  1161. // no x clipping
  1162. // point screen ptr to starting line
  1163. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1164. for (yi = ystart; yi < yend; yi++)
  1165. {
  1166. // compute span endpoints
  1167. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1168. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1169. // compute starting points for u,v interpolants
  1170. ui = ul + FIXP16_ROUND_UP;
  1171. vi = vl + FIXP16_ROUND_UP;
  1172. // compute u,v interpolants
  1173. if ((dx = (xend - xstart))>0)
  1174. {
  1175. du = (ur - ul)/dx;
  1176. dv = (vr - vl)/dx;
  1177. } // end if
  1178. else
  1179. {
  1180. du = (ur - ul);
  1181. dv = (vr - vl);
  1182. } // end else
  1183. // draw span
  1184. for (xi=xstart; xi < xend; xi++)
  1185. {
  1186. // write textel
  1187.             // check for transparency
  1188.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1189.             if (textel)
  1190.                {
  1191.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + alpha_table_src2[textel];
  1192.                } // end if
  1193. // interpolate u,v
  1194. ui+=du;
  1195. vi+=dv;
  1196. } // end for xi
  1197. // interpolate u,v,x along right and left edge
  1198. xl+=dxdyl;
  1199. ul+=dudyl;
  1200. vl+=dvdyl;
  1201. xr+=dxdyr;
  1202. ur+=dudyr;
  1203. vr+=dvdyr;
  1204. // advance screen ptr
  1205. screen_ptr+=mem_pitch;
  1206. // test for yi hitting second region, if so change interpolant
  1207. if (yi==yrestart)
  1208. {
  1209. // test interpolation side change flag
  1210. if (irestart == INTERP_LHS)
  1211. {
  1212. // LHS
  1213. dyl = (y2 - y1);
  1214. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1215. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1216. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1217. // set starting values
  1218. xl = (x1  << FIXP16_SHIFT);
  1219. ul = (tu1 << FIXP16_SHIFT);
  1220. vl = (tv1 << FIXP16_SHIFT);
  1221. // interpolate down on LHS to even up
  1222. xl+=dxdyl;
  1223. ul+=dudyl;
  1224. vl+=dvdyl;
  1225. } // end if
  1226. else
  1227. {
  1228. // RHS
  1229. dyr = (y1 - y2);
  1230. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1231. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1232. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1233. // set starting values
  1234. xr = (x2  << FIXP16_SHIFT);
  1235. ur = (tu2 << FIXP16_SHIFT);
  1236. vr = (tv2 << FIXP16_SHIFT);
  1237. // interpolate down on RHS to even up
  1238. xr+=dxdyr;
  1239. ur+=dudyr;
  1240. vr+=dvdyr;
  1241. } // end else
  1242. } // end if
  1243. } // end for y
  1244.    } // end else
  1245. } // end if
  1246. } // end Draw_Textured_Triangle_Alpha16_2
  1247. ///////////////////////////////////////////////////////////////////////////////
  1248. void Draw_Textured_TriangleZB_Alpha16_2(POLYF4DV2_PTR face,  // ptr to face
  1249.                               UCHAR *_dest_buffer,  // pointer to video buffer
  1250.                               int mem_pitch,        // bytes per line, 320, 640 etc.
  1251.                               UCHAR *_zbuffer,       // pointer to z-buffer
  1252.                               int zpitch,          // bytes per line of zbuffer
  1253.                               int alpha)
  1254. {
  1255. // this function draws a textured triangle in 16-bit mode
  1256. int v0=0,
  1257.     v1=1,
  1258. v2=2,
  1259. temp=0,
  1260. tri_type = TRI_TYPE_NONE,
  1261. irestart = INTERP_LHS;
  1262. int dx,dy,dyl,dyr,      // general deltas
  1263.     u,v,z,
  1264.     du,dv,dz,
  1265.     xi,yi,              // the current interpolated x,y
  1266. ui,vi,zi,           // the current interpolated u,v,z
  1267. index_x,index_y,    // looping vars
  1268. x,y,                // hold general x,y
  1269. xstart,
  1270. xend,
  1271. ystart,
  1272. yrestart,
  1273. yend,
  1274. xl,                 
  1275. dxdyl,              
  1276. xr,
  1277. dxdyr,             
  1278. dudyl,    
  1279. ul,
  1280. dvdyl,   
  1281. vl,
  1282. dzdyl,   
  1283. zl,
  1284. dudyr,
  1285. ur,
  1286. dvdyr,
  1287. vr,
  1288. dzdyr,
  1289. zr;
  1290. int x0,y0,tu0,tv0,tz0,    // cached vertices
  1291. x1,y1,tu1,tv1,tz1,
  1292. x2,y2,tu2,tv2,tz2;
  1293. USHORT *screen_ptr  = NULL,
  1294.    *screen_line = NULL,
  1295.    *textmap     = NULL,
  1296.        *dest_buffer = (USHORT *)_dest_buffer,
  1297.         textel; 
  1298. UINT  *z_ptr = NULL,
  1299.       *zbuffer = (UINT *)_zbuffer;
  1300. #ifdef DEBUG_ON
  1301. // track rendering stats
  1302.     debug_polys_rendered_per_frame++;
  1303. #endif
  1304. // extract texture map
  1305. textmap = (USHORT *)face->texture->buffer;
  1306. // extract base 2 of texture width
  1307. int texture_shift2 = logbase2ofx[face->texture->width];
  1308. // adjust memory pitch to words, divide by 2
  1309. mem_pitch >>=1;
  1310. // adjust zbuffer pitch for 32 bit alignment
  1311. zpitch >>= 2;
  1312. // apply fill convention to coordinates
  1313. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  1314. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  1315. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  1316. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  1317. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  1318. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  1319. // first trivial clipping rejection tests 
  1320. if (((face->tvlist[0].y < min_clip_y)  && 
  1321.  (face->tvlist[1].y < min_clip_y)  &&
  1322.  (face->tvlist[2].y < min_clip_y)) ||
  1323. ((face->tvlist[0].y > max_clip_y)  && 
  1324.  (face->tvlist[1].y > max_clip_y)  &&
  1325.  (face->tvlist[2].y > max_clip_y)) ||
  1326. ((face->tvlist[0].x < min_clip_x)  && 
  1327.  (face->tvlist[1].x < min_clip_x)  &&
  1328.  (face->tvlist[2].x < min_clip_x)) ||
  1329. ((face->tvlist[0].x > max_clip_x)  && 
  1330.  (face->tvlist[1].x > max_clip_x)  &&
  1331.  (face->tvlist[2].x > max_clip_x)))
  1332.    return;
  1333. // sort vertices
  1334. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  1335. {SWAP(v0,v1,temp);} 
  1336. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  1337. {SWAP(v0,v2,temp);}
  1338. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  1339. {SWAP(v1,v2,temp);}
  1340. // now test for trivial flat sided cases
  1341. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  1342. // set triangle type
  1343. tri_type = TRI_TYPE_FLAT_TOP;
  1344. // sort vertices left to right
  1345. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  1346. {SWAP(v0,v1,temp);}
  1347. } // end if
  1348. else
  1349. // now test for trivial flat sided cases
  1350. if (FCMP(face->tvlist[v1].y ,face->tvlist[v2].y))
  1351. // set triangle type
  1352. tri_type = TRI_TYPE_FLAT_BOTTOM;
  1353. // sort vertices left to right
  1354. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  1355. {SWAP(v1,v2,temp);}
  1356. } // end if
  1357. else
  1358. {
  1359. // must be a general triangle
  1360. tri_type = TRI_TYPE_GENERAL;
  1361. } // end else
  1362. // extract vertices for processing, now that we have order
  1363. x0  = (int)(face->tvlist[v0].x+0.0);
  1364. y0  = (int)(face->tvlist[v0].y+0.0);
  1365. tu0 = (int)(face->tvlist[v0].u0);
  1366. tv0 = (int)(face->tvlist[v0].v0);
  1367. tz0 = (int)(face->tvlist[v0].z+0.5);
  1368. x1  = (int)(face->tvlist[v1].x+0.0);
  1369. y1  = (int)(face->tvlist[v1].y+0.0);
  1370. tu1 = (int)(face->tvlist[v1].u0);
  1371. tv1 = (int)(face->tvlist[v1].v0);
  1372. tz1 = (int)(face->tvlist[v1].z+0.5);
  1373. x2  = (int)(face->tvlist[v2].x+0.0);
  1374. y2  = (int)(face->tvlist[v2].y+0.0);
  1375. tu2 = (int)(face->tvlist[v2].u0);
  1376. tv2 = (int)(face->tvlist[v2].v0);
  1377. tz2 = (int)(face->tvlist[v2].z+0.5);
  1378. // degenerate triangle
  1379. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  1380.    return;
  1381. // assign both source1 and source2 alpha tables based on polygon alpha level
  1382. USHORT *alpha_table_src1 = (USHORT *)&rgb_alpha_table[(NUM_ALPHA_LEVELS-1) - alpha][0];
  1383. USHORT *alpha_table_src2 = (USHORT *)&rgb_alpha_table[alpha][0];
  1384. // set interpolation restart value
  1385. yrestart = y1;
  1386. // what kind of triangle
  1387. if (tri_type & TRI_TYPE_FLAT_MASK)
  1388. {
  1389. if (tri_type == TRI_TYPE_FLAT_TOP)
  1390. {
  1391. // compute all deltas
  1392. dy = (y2 - y0);
  1393. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1394. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1395. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  1396. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;    
  1397. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  1398. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  1399. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  1400. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;  
  1401. // test for y clipping
  1402. if (y0 < min_clip_y)
  1403. {
  1404. // compute overclip
  1405. dy = (min_clip_y - y0);
  1406. // computer new LHS starting values
  1407. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1408. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1409. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1410. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1411. // compute new RHS starting values
  1412. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  1413. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  1414. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  1415. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  1416. // compute new starting y
  1417. ystart = min_clip_y;
  1418. } // end if
  1419. else
  1420. {
  1421. // no clipping
  1422. // set starting values
  1423. xl = (x0 << FIXP16_SHIFT);
  1424. xr = (x1 << FIXP16_SHIFT);
  1425. ul = (tu0 << FIXP16_SHIFT);
  1426. vl = (tv0 << FIXP16_SHIFT);
  1427. zl = (tz0 << FIXP16_SHIFT);
  1428. ur = (tu1 << FIXP16_SHIFT);
  1429. vr = (tv1 << FIXP16_SHIFT);
  1430. zr = (tz1 << FIXP16_SHIFT);
  1431. // set starting y
  1432. ystart = y0;
  1433. } // end else
  1434. } // end if flat top
  1435. else
  1436. {
  1437. // must be flat bottom
  1438. // compute all deltas
  1439. dy = (y1 - y0);
  1440. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  1441. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  1442. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  1443. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy;   
  1444. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1445. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1446. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  1447. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  1448. // test for y clipping
  1449. if (y0 < min_clip_y)
  1450. {
  1451. // compute overclip
  1452. dy = (min_clip_y - y0);
  1453. // computer new LHS starting values
  1454. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1455. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1456. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1457. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1458. // compute new RHS starting values
  1459. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1460. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  1461. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  1462. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  1463. // compute new starting y
  1464. ystart = min_clip_y;
  1465. } // end if
  1466. else
  1467. {
  1468. // no clipping
  1469. // set starting values
  1470. xl = (x0 << FIXP16_SHIFT);
  1471. xr = (x0 << FIXP16_SHIFT);
  1472. ul = (tu0 << FIXP16_SHIFT);
  1473. vl = (tv0 << FIXP16_SHIFT);
  1474. zl = (tz0 << FIXP16_SHIFT);
  1475. ur = (tu0 << FIXP16_SHIFT);
  1476. vr = (tv0 << FIXP16_SHIFT);
  1477. zr = (tz0 << FIXP16_SHIFT);
  1478. // set starting y
  1479. ystart = y0;
  1480. } // end else
  1481. } // end else flat bottom
  1482. // test for bottom clip, always
  1483. if ((yend = y2) > max_clip_y)
  1484. yend = max_clip_y;
  1485.     // test for horizontal clipping
  1486. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1487. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1488. (x2 < min_clip_x) || (x2 > max_clip_x))
  1489. {
  1490.     // clip version
  1491. // point screen ptr to starting line
  1492. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1493.     // point zbuffer to starting line
  1494.     z_ptr = zbuffer + (ystart * zpitch);
  1495. for (yi = ystart; yi < yend; yi++)
  1496. {
  1497. // compute span endpoints
  1498. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1499. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1500. // compute starting points for u,v interpolants
  1501. ui = ul + FIXP16_ROUND_UP;
  1502. vi = vl + FIXP16_ROUND_UP;
  1503. zi = zl + FIXP16_ROUND_UP;
  1504. // compute u,v interpolants
  1505. if ((dx = (xend - xstart))>0)
  1506. {
  1507. du = (ur - ul)/dx;
  1508. dv = (vr - vl)/dx;
  1509. dz = (zr - zl)/dx;
  1510. } // end if
  1511. else
  1512. {
  1513. du = (ur - ul);
  1514. dv = (vr - vl);
  1515. dz = (zr - zl);
  1516. } // end else
  1517. ///////////////////////////////////////////////////////////////////////
  1518. // test for x clipping, LHS
  1519. if (xstart < min_clip_x)
  1520. {
  1521. // compute x overlap
  1522. dx = min_clip_x - xstart;
  1523. // slide interpolants over
  1524. ui+=dx*du;
  1525. vi+=dx*dv;
  1526. zi+=dx*dz;
  1527. // reset vars
  1528. xstart = min_clip_x;
  1529. } // end if
  1530. // test for x clipping RHS
  1531. if (xend > max_clip_x)
  1532. xend = max_clip_x;
  1533. ///////////////////////////////////////////////////////////////////////
  1534. // draw span
  1535. for (xi=xstart; xi < xend; xi++)
  1536. {
  1537.             // get textel
  1538.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1539.             if (textel)
  1540.             {
  1541.             // test if z of current pixel is nearer than current z buffer value
  1542.             if (zi < z_ptr[xi])
  1543.                {
  1544.       // write textel
  1545.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + 
  1546.                              alpha_table_src2[textel];
  1547.                // update z-buffer
  1548.                z_ptr[xi] = zi;           
  1549.                } // end if
  1550.             } // end if
  1551. // interpolate u,v,z
  1552. ui+=du;
  1553. vi+=dv;
  1554. zi+=dz;
  1555. } // end for xi
  1556. // interpolate u,v,x along right and left edge
  1557. xl+=dxdyl;
  1558. ul+=dudyl;
  1559. vl+=dvdyl;
  1560. zl+=dzdyl;
  1561. xr+=dxdyr;
  1562. ur+=dudyr;
  1563. vr+=dvdyr;
  1564. zr+=dzdyr;
  1565.  
  1566. // advance screen ptr
  1567. screen_ptr+=mem_pitch;
  1568.         // advance zbuffer ptr
  1569.         z_ptr+=zpitch;
  1570. } // end for y
  1571. } // end if clip
  1572. else
  1573. {
  1574. // non-clip version
  1575. // point screen ptr to starting line
  1576. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1577.     // point zbuffer to starting line
  1578.     z_ptr = zbuffer + (ystart * zpitch);
  1579. for (yi = ystart; yi < yend; yi++)
  1580. {
  1581. // compute span endpoints
  1582. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1583. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1584. // compute starting points for u,v interpolants
  1585. ui = ul + FIXP16_ROUND_UP;
  1586. vi = vl + FIXP16_ROUND_UP;
  1587. zi = zl + FIXP16_ROUND_UP;
  1588. // compute u,v interpolants
  1589. if ((dx = (xend - xstart))>0)
  1590. {
  1591. du = (ur - ul)/dx;
  1592. dv = (vr - vl)/dx;
  1593. dz = (zr - zl)/dx;
  1594. } // end if
  1595. else
  1596. {
  1597. du = (ur - ul);
  1598. dv = (vr - vl);
  1599. dz = (zr - zl);
  1600. } // end else
  1601. // draw span
  1602. for (xi=xstart; xi < xend; xi++)
  1603. {
  1604.                // get textel
  1605.                textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1606.                if (textel)
  1607.                {
  1608.                // test if z of current pixel is nearer than current z buffer value
  1609.                if (zi < z_ptr[xi])
  1610.                   {
  1611.          // write textel
  1612.                   screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + 
  1613.                              alpha_table_src2[textel];
  1614.                   // update z-buffer
  1615.                   z_ptr[xi] = zi;           
  1616.                   } // end if
  1617.                } // end if
  1618. // interpolate u,v,z
  1619. ui+=du;
  1620. vi+=dv;
  1621. zi+=dz;
  1622. } // end for xi
  1623. // interpolate u,v,x along right and left edge
  1624. xl+=dxdyl;
  1625. ul+=dudyl;
  1626. vl+=dvdyl;
  1627. zl+=dzdyl;
  1628. xr+=dxdyr;
  1629. ur+=dudyr;
  1630. vr+=dvdyr;
  1631. zr+=dzdyr;
  1632. // advance screen ptr
  1633. screen_ptr+=mem_pitch;
  1634.         // advance zbuffer ptr
  1635.         z_ptr+=zpitch;
  1636. } // end for y
  1637. } // end if non-clipped
  1638. } // end if
  1639. else
  1640. if (tri_type==TRI_TYPE_GENERAL)
  1641. {
  1642. // first test for bottom clip, always
  1643. if ((yend = y2) > max_clip_y)
  1644. yend = max_clip_y;
  1645. // pre-test y clipping status
  1646. if (y1 < min_clip_y)
  1647. {
  1648. // compute all deltas
  1649. // LHS
  1650. dyl = (y2 - y1);
  1651. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  1652. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1653. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  1654. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  1655. // RHS
  1656. dyr = (y2 - y0);
  1657. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  1658. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1659. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1660. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  1661. // compute overclip
  1662. dyr = (min_clip_y - y0);
  1663. dyl = (min_clip_y - y1);
  1664. // computer new LHS starting values
  1665. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  1666. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  1667. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  1668. zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  1669. // compute new RHS starting values
  1670. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  1671. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  1672. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  1673. zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  1674. // compute new starting y
  1675. ystart = min_clip_y;
  1676. // test if we need swap to keep rendering left to right
  1677. if (dxdyr > dxdyl)
  1678. {
  1679. SWAP(dxdyl,dxdyr,temp);
  1680. SWAP(dudyl,dudyr,temp);
  1681. SWAP(dvdyl,dvdyr,temp);
  1682. SWAP(dzdyl,dzdyr,temp);
  1683. SWAP(xl,xr,temp);
  1684. SWAP(ul,ur,temp);
  1685. SWAP(vl,vr,temp);
  1686. SWAP(zl,zr,temp);
  1687. SWAP(x1,x2,temp);
  1688. SWAP(y1,y2,temp);
  1689. SWAP(tu1,tu2,temp);
  1690. SWAP(tv1,tv2,temp);
  1691. SWAP(tz1,tz2,temp);
  1692. // set interpolation restart
  1693. irestart = INTERP_RHS;
  1694. } // end if
  1695. } // end if
  1696. else
  1697. if (y0 < min_clip_y)
  1698. {
  1699. // compute all deltas
  1700. // LHS
  1701. dyl = (y1 - y0);
  1702. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1703. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  1704. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  1705. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;  
  1706. // RHS
  1707. dyr = (y2 - y0);
  1708. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  1709. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1710. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1711. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  1712. // compute overclip
  1713. dy = (min_clip_y - y0);
  1714. // computer new LHS starting values
  1715. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1716. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1717. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1718. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1719. // compute new RHS starting values
  1720. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1721. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  1722. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  1723. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  1724. // compute new starting y
  1725. ystart = min_clip_y;
  1726. // test if we need swap to keep rendering left to right
  1727. if (dxdyr < dxdyl)
  1728. {
  1729. SWAP(dxdyl,dxdyr,temp);
  1730. SWAP(dudyl,dudyr,temp);
  1731. SWAP(dvdyl,dvdyr,temp);
  1732. SWAP(dzdyl,dzdyr,temp);
  1733. SWAP(xl,xr,temp);
  1734. SWAP(ul,ur,temp);
  1735. SWAP(vl,vr,temp);
  1736. SWAP(zl,zr,temp);
  1737. SWAP(x1,x2,temp);
  1738. SWAP(y1,y2,temp);
  1739. SWAP(tu1,tu2,temp);
  1740. SWAP(tv1,tv2,temp);
  1741. SWAP(tz1,tz2,temp);
  1742. // set interpolation restart
  1743. irestart = INTERP_RHS;
  1744. } // end if
  1745. } // end if
  1746. else
  1747. {
  1748. // no initial y clipping
  1749. // compute all deltas
  1750. // LHS
  1751. dyl = (y1 - y0);
  1752. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1753. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  1754. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  1755. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;   
  1756. // RHS
  1757. dyr = (y2 - y0);
  1758. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  1759. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1760. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1761. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;  
  1762. // no clipping y
  1763. // set starting values
  1764. xl = (x0 << FIXP16_SHIFT);
  1765. xr = (x0 << FIXP16_SHIFT);
  1766. ul = (tu0 << FIXP16_SHIFT);
  1767. vl = (tv0 << FIXP16_SHIFT);
  1768. zl = (tz0 << FIXP16_SHIFT);
  1769. ur = (tu0 << FIXP16_SHIFT);
  1770. vr = (tv0 << FIXP16_SHIFT);
  1771. zr = (tz0 << FIXP16_SHIFT);
  1772. // set starting y
  1773. ystart = y0;
  1774. // test if we need swap to keep rendering left to right
  1775. if (dxdyr < dxdyl)
  1776. {
  1777. SWAP(dxdyl,dxdyr,temp);
  1778. SWAP(dudyl,dudyr,temp);
  1779. SWAP(dvdyl,dvdyr,temp);
  1780. SWAP(dzdyl,dzdyr,temp);
  1781. SWAP(xl,xr,temp);
  1782. SWAP(ul,ur,temp);
  1783. SWAP(vl,vr,temp);
  1784. SWAP(zl,zr,temp);
  1785. SWAP(x1,x2,temp);
  1786. SWAP(y1,y2,temp);
  1787. SWAP(tu1,tu2,temp);
  1788. SWAP(tv1,tv2,temp);
  1789. SWAP(tz1,tz2,temp);
  1790. // set interpolation restart
  1791. irestart = INTERP_RHS;
  1792. } // end if
  1793. } // end else
  1794.     // test for horizontal clipping
  1795. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1796. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1797. (x2 < min_clip_x) || (x2 > max_clip_x))
  1798. {
  1799.     // clip version
  1800. // x clipping
  1801. // point screen ptr to starting line
  1802. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1803.     // point zbuffer to starting line
  1804.     z_ptr = zbuffer + (ystart * zpitch);
  1805. for (yi = ystart; yi < yend; yi++)
  1806. {
  1807. // compute span endpoints
  1808. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1809. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1810. // compute starting points for u,v interpolants
  1811. ui = ul + FIXP16_ROUND_UP;
  1812. vi = vl + FIXP16_ROUND_UP;
  1813. zi = zl + FIXP16_ROUND_UP;
  1814. // compute u,v interpolants
  1815. if ((dx = (xend - xstart))>0)
  1816. {
  1817. du = (ur - ul)/dx;
  1818. dv = (vr - vl)/dx;
  1819. dz = (zr - zl)/dx;
  1820. } // end if
  1821. else
  1822. {
  1823. du = (ur - ul);
  1824. dv = (vr - vl);
  1825. dz = (zr - zl);
  1826. } // end else
  1827. ///////////////////////////////////////////////////////////////////////
  1828. // test for x clipping, LHS
  1829. if (xstart < min_clip_x)
  1830. {
  1831. // compute x overlap
  1832. dx = min_clip_x - xstart;
  1833. // slide interpolants over
  1834. ui+=dx*du;
  1835. vi+=dx*dv;
  1836. zi+=dx*dz;
  1837. // set x to left clip edge
  1838. xstart = min_clip_x;
  1839. } // end if
  1840. // test for x clipping RHS
  1841. if (xend > max_clip_x)
  1842. xend = max_clip_x;
  1843. ///////////////////////////////////////////////////////////////////////
  1844. // draw span
  1845. for (xi=xstart; xi < xend; xi++)
  1846. {
  1847.             // get textel
  1848.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1849.             if (textel)
  1850.             {
  1851.             // test if z of current pixel is nearer than current z buffer value
  1852.             if (zi < z_ptr[xi])
  1853.                {
  1854.       // write textel
  1855.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + 
  1856.                              alpha_table_src2[textel];
  1857.                // update z-buffer
  1858.                z_ptr[xi] = zi;           
  1859.                } // end if
  1860.             } // end if
  1861. // interpolate u,v,z
  1862. ui+=du;
  1863. vi+=dv;
  1864. zi+=dz;
  1865. } // end for xi
  1866. // interpolate u,v,x along right and left edge
  1867. xl+=dxdyl;
  1868. ul+=dudyl;
  1869. vl+=dvdyl;
  1870. zl+=dzdyl;
  1871. xr+=dxdyr;
  1872. ur+=dudyr;
  1873. vr+=dvdyr;
  1874. zr+=dzdyr;
  1875. // advance screen ptr
  1876. screen_ptr+=mem_pitch;
  1877.         // advance zbuffer ptr
  1878.         z_ptr+=zpitch;
  1879. // test for yi hitting second region, if so change interpolant
  1880. if (yi==yrestart)
  1881. {
  1882.     // test interpolation side change flag
  1883. if (irestart == INTERP_LHS)
  1884. {
  1885. // LHS
  1886. dyl = (y2 - y1);
  1887. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1888. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1889. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1890. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  1891. // set starting values
  1892. xl = (x1  << FIXP16_SHIFT);
  1893. ul = (tu1 << FIXP16_SHIFT);
  1894. vl = (tv1 << FIXP16_SHIFT);
  1895. zl = (tz1 << FIXP16_SHIFT);
  1896. // interpolate down on LHS to even up
  1897. xl+=dxdyl;
  1898. ul+=dudyl;
  1899. vl+=dvdyl;
  1900. zl+=dzdyl;
  1901. } // end if
  1902. else
  1903. {
  1904. // RHS
  1905. dyr = (y1 - y2);
  1906. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1907. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1908. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1909. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;  
  1910. // set starting values
  1911. xr = (x2  << FIXP16_SHIFT);
  1912. ur = (tu2 << FIXP16_SHIFT);
  1913. vr = (tv2 << FIXP16_SHIFT);
  1914. zr = (tz2 << FIXP16_SHIFT);
  1915. // interpolate down on RHS to even up
  1916. xr+=dxdyr;
  1917. ur+=dudyr;
  1918. vr+=dvdyr;
  1919. zr+=dzdyr;
  1920. } // end else
  1921. } // end if
  1922. } // end for y
  1923. } // end if
  1924. else
  1925. {
  1926. // no x clipping
  1927. // point screen ptr to starting line
  1928. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1929.     // point zbuffer to starting line
  1930.     z_ptr = zbuffer + (ystart * zpitch);
  1931. for (yi = ystart; yi < yend; yi++)
  1932. {
  1933. // compute span endpoints
  1934. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1935. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1936. // compute starting points for u,v interpolants
  1937. ui = ul + FIXP16_ROUND_UP;
  1938. vi = vl + FIXP16_ROUND_UP;
  1939. zi = zl + FIXP16_ROUND_UP;
  1940. // compute u,v interpolants
  1941. if ((dx = (xend - xstart))>0)
  1942. {
  1943. du = (ur - ul)/dx;
  1944. dv = (vr - vl)/dx;
  1945. dz = (zr - zl)/dx;
  1946. } // end if
  1947. else
  1948. {
  1949. du = (ur - ul);
  1950. dv = (vr - vl);
  1951. dz = (zr - zl);
  1952. } // end else
  1953. // draw span
  1954. for (xi=xstart; xi < xend; xi++)
  1955. {
  1956.             // test if z of current pixel is nearer than current z buffer value
  1957.             // get textel
  1958.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1959.             if (textel)
  1960.             {
  1961.             // test if z of current pixel is nearer than current z buffer value
  1962.             if (zi < z_ptr[xi])
  1963.                {
  1964.       // write textel
  1965.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + 
  1966.                              alpha_table_src2[textel];
  1967.                // update z-buffer
  1968.                z_ptr[xi] = zi;           
  1969.                } // end if
  1970.             } // end if
  1971. // interpolate u,v
  1972. ui+=du;
  1973. vi+=dv;
  1974. zi+=dz;
  1975. } // end for xi
  1976. // interpolate u,v,x along right and left edge
  1977. xl+=dxdyl;
  1978. ul+=dudyl;
  1979. vl+=dvdyl;
  1980. zl+=dzdyl;
  1981. xr+=dxdyr;
  1982. ur+=dudyr;
  1983. vr+=dvdyr;
  1984. zr+=dzdyr;
  1985. // advance screen ptr
  1986. screen_ptr+=mem_pitch;
  1987.         // advance zbuffer ptr
  1988.         z_ptr+=zpitch;
  1989. // test for yi hitting second region, if so change interpolant
  1990. if (yi==yrestart)
  1991. {
  1992. // test interpolation side change flag
  1993. if (irestart == INTERP_LHS)
  1994. {
  1995. // LHS
  1996. dyl = (y2 - y1);
  1997. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1998. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1999. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  2000. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  2001. // set starting values
  2002. xl = (x1  << FIXP16_SHIFT);
  2003. ul = (tu1 << FIXP16_SHIFT);
  2004. vl = (tv1 << FIXP16_SHIFT);
  2005. zl = (tz1 << FIXP16_SHIFT);
  2006. // interpolate down on LHS to even up
  2007. xl+=dxdyl;
  2008. ul+=dudyl;
  2009. vl+=dvdyl;
  2010. zl+=dzdyl;
  2011. } // end if
  2012. else
  2013. {
  2014. // RHS
  2015. dyr = (y1 - y2);
  2016. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  2017. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  2018. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  2019. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr; 
  2020. // set starting values
  2021. xr = (x2  << FIXP16_SHIFT);
  2022. ur = (tu2 << FIXP16_SHIFT);
  2023. vr = (tv2 << FIXP16_SHIFT);
  2024. zr = (tz2 << FIXP16_SHIFT);
  2025. // interpolate down on RHS to even up
  2026. xr+=dxdyr;
  2027. ur+=dudyr;
  2028. vr+=dvdyr;
  2029. zr+=dzdyr;
  2030. } // end else
  2031. } // end if
  2032. } // end for y
  2033.    } // end else
  2034. } // end if
  2035. } // end Draw_Textured_TriangleZB_Alpha16_2
  2036. ///////////////////////////////////////////////////////////////////////////////
  2037. void Draw_Textured_TriangleWTZB_Alpha16_2(POLYF4DV2_PTR face,  // ptr to face
  2038.                               UCHAR *_dest_buffer,  // pointer to video buffer
  2039.                               int mem_pitch,        // bytes per line, 320, 640 etc.
  2040.                               UCHAR *_zbuffer,       // pointer to z-buffer
  2041.                               int zpitch,          // bytes per line of zbuffer
  2042.                               int alpha)
  2043. {
  2044. // this function draws a textured triangle in 16-bit mode
  2045. int v0=0,
  2046.     v1=1,
  2047. v2=2,
  2048. temp=0,
  2049. tri_type = TRI_TYPE_NONE,
  2050. irestart = INTERP_LHS;
  2051. int dx,dy,dyl,dyr,      // general deltas
  2052.     u,v,z,
  2053.     du,dv,dz,
  2054.     xi,yi,              // the current interpolated x,y
  2055. ui,vi,zi,           // the current interpolated u,v,z
  2056. index_x,index_y,    // looping vars
  2057. x,y,                // hold general x,y
  2058. xstart,
  2059. xend,
  2060. ystart,
  2061. yrestart,
  2062. yend,
  2063. xl,                 
  2064. dxdyl,              
  2065. xr,
  2066. dxdyr,             
  2067. dudyl,    
  2068. ul,
  2069. dvdyl,   
  2070. vl,
  2071. dzdyl,   
  2072. zl,
  2073. dudyr,
  2074. ur,
  2075. dvdyr,
  2076. vr,
  2077. dzdyr,
  2078. zr;
  2079. int x0,y0,tu0,tv0,tz0,    // cached vertices
  2080. x1,y1,tu1,tv1,tz1,
  2081. x2,y2,tu2,tv2,tz2;
  2082. USHORT *screen_ptr  = NULL,
  2083.    *screen_line = NULL,
  2084.    *textmap     = NULL,
  2085.        *dest_buffer = (USHORT *)_dest_buffer,
  2086.         textel; 
  2087. UINT  *z_ptr = NULL,
  2088.       *zbuffer = (UINT *)_zbuffer;
  2089. #ifdef DEBUG_ON
  2090. // track rendering stats
  2091.     debug_polys_rendered_per_frame++;
  2092. #endif
  2093. // extract texture map
  2094. textmap = (USHORT *)face->texture->buffer;
  2095. // extract base 2 of texture width
  2096. int texture_shift2 = logbase2ofx[face->texture->width];
  2097. // adjust memory pitch to words, divide by 2
  2098. mem_pitch >>=1;
  2099. // adjust zbuffer pitch for 32 bit alignment
  2100. zpitch >>= 2;
  2101. // apply fill convention to coordinates
  2102. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  2103. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  2104. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  2105. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  2106. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  2107. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  2108. // first trivial clipping rejection tests 
  2109. if (((face->tvlist[0].y < min_clip_y)  && 
  2110.  (face->tvlist[1].y < min_clip_y)  &&
  2111.  (face->tvlist[2].y < min_clip_y)) ||
  2112. ((face->tvlist[0].y > max_clip_y)  && 
  2113.  (face->tvlist[1].y > max_clip_y)  &&
  2114.  (face->tvlist[2].y > max_clip_y)) ||
  2115. ((face->tvlist[0].x < min_clip_x)  && 
  2116.  (face->tvlist[1].x < min_clip_x)  &&
  2117.  (face->tvlist[2].x < min_clip_x)) ||
  2118. ((face->tvlist[0].x > max_clip_x)  && 
  2119.  (face->tvlist[1].x > max_clip_x)  &&
  2120.  (face->tvlist[2].x > max_clip_x)))
  2121.    return;
  2122. // sort vertices
  2123. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  2124. {SWAP(v0,v1,temp);} 
  2125. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  2126. {SWAP(v0,v2,temp);}
  2127. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  2128. {SWAP(v1,v2,temp);}
  2129. // now test for trivial flat sided cases
  2130. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  2131. // set triangle type
  2132. tri_type = TRI_TYPE_FLAT_TOP;
  2133. // sort vertices left to right
  2134. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  2135. {SWAP(v0,v1,temp);}
  2136. } // end if
  2137. else
  2138. // now test for trivial flat sided cases
  2139. if (FCMP(face->tvlist[v1].y ,face->tvlist[v2].y))
  2140. // set triangle type
  2141. tri_type = TRI_TYPE_FLAT_BOTTOM;
  2142. // sort vertices left to right
  2143. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  2144. {SWAP(v1,v2,temp);}
  2145. } // end if
  2146. else
  2147. {
  2148. // must be a general triangle
  2149. tri_type = TRI_TYPE_GENERAL;
  2150. } // end else
  2151. // extract vertices for processing, now that we have order
  2152. x0  = (int)(face->tvlist[v0].x+0.0);
  2153. y0  = (int)(face->tvlist[v0].y+0.0);
  2154. tu0 = (int)(face->tvlist[v0].u0);
  2155. tv0 = (int)(face->tvlist[v0].v0);
  2156. tz0 = (int)(face->tvlist[v0].z+0.5);
  2157. x1  = (int)(face->tvlist[v1].x+0.0);
  2158. y1  = (int)(face->tvlist[v1].y+0.0);
  2159. tu1 = (int)(face->tvlist[v1].u0);
  2160. tv1 = (int)(face->tvlist[v1].v0);
  2161. tz1 = (int)(face->tvlist[v1].z+0.5);
  2162. x2  = (int)(face->tvlist[v2].x+0.0);
  2163. y2  = (int)(face->tvlist[v2].y+0.0);
  2164. tu2 = (int)(face->tvlist[v2].u0);
  2165. tv2 = (int)(face->tvlist[v2].v0);
  2166. tz2 = (int)(face->tvlist[v2].z+0.5);
  2167. // degenerate triangle
  2168. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  2169.    return;
  2170. // assign both source1 and source2 alpha tables based on polygon alpha level
  2171. USHORT *alpha_table_src1 = (USHORT *)&rgb_alpha_table[(NUM_ALPHA_LEVELS-1) - alpha][0];
  2172. USHORT *alpha_table_src2 = (USHORT *)&rgb_alpha_table[alpha][0];
  2173. // set interpolation restart value
  2174. yrestart = y1;
  2175. // what kind of triangle
  2176. if (tri_type & TRI_TYPE_FLAT_MASK)
  2177. {
  2178. if (tri_type == TRI_TYPE_FLAT_TOP)
  2179. {
  2180. // compute all deltas
  2181. dy = (y2 - y0);
  2182. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2183. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2184. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  2185. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;    
  2186. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  2187. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  2188. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  2189. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;  
  2190. // test for y clipping
  2191. if (y0 < min_clip_y)
  2192. {
  2193. // compute overclip
  2194. dy = (min_clip_y - y0);
  2195. // computer new LHS starting values
  2196. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2197. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2198. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2199. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2200. // compute new RHS starting values
  2201. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  2202. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  2203. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  2204. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  2205. // compute new starting y
  2206. ystart = min_clip_y;
  2207. } // end if
  2208. else
  2209. {
  2210. // no clipping
  2211. // set starting values
  2212. xl = (x0 << FIXP16_SHIFT);
  2213. xr = (x1 << FIXP16_SHIFT);
  2214. ul = (tu0 << FIXP16_SHIFT);
  2215. vl = (tv0 << FIXP16_SHIFT);
  2216. zl = (tz0 << FIXP16_SHIFT);
  2217. ur = (tu1 << FIXP16_SHIFT);
  2218. vr = (tv1 << FIXP16_SHIFT);
  2219. zr = (tz1 << FIXP16_SHIFT);
  2220. // set starting y
  2221. ystart = y0;
  2222. } // end else
  2223. } // end if flat top
  2224. else
  2225. {
  2226. // must be flat bottom
  2227. // compute all deltas
  2228. dy = (y1 - y0);
  2229. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  2230. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  2231. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  2232. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy;   
  2233. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2234. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2235. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  2236. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  2237. // test for y clipping
  2238. if (y0 < min_clip_y)
  2239. {
  2240. // compute overclip
  2241. dy = (min_clip_y - y0);
  2242. // computer new LHS starting values
  2243. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2244. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2245. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2246. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2247. // compute new RHS starting values
  2248. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2249. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2250. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2251. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  2252. // compute new starting y
  2253. ystart = min_clip_y;
  2254. } // end if
  2255. else
  2256. {
  2257. // no clipping
  2258. // set starting values
  2259. xl = (x0 << FIXP16_SHIFT);
  2260. xr = (x0 << FIXP16_SHIFT);
  2261. ul = (tu0 << FIXP16_SHIFT);
  2262. vl = (tv0 << FIXP16_SHIFT);
  2263. zl = (tz0 << FIXP16_SHIFT);
  2264. ur = (tu0 << FIXP16_SHIFT);
  2265. vr = (tv0 << FIXP16_SHIFT);
  2266. zr = (tz0 << FIXP16_SHIFT);
  2267. // set starting y
  2268. ystart = y0;
  2269. } // end else
  2270. } // end else flat bottom
  2271. // test for bottom clip, always
  2272. if ((yend = y2) > max_clip_y)
  2273. yend = max_clip_y;
  2274.     // test for horizontal clipping
  2275. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  2276. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  2277. (x2 < min_clip_x) || (x2 > max_clip_x))
  2278. {
  2279.     // clip version
  2280. // point screen ptr to starting line
  2281. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2282.     // point zbuffer to starting line
  2283.     z_ptr = zbuffer + (ystart * zpitch);
  2284. for (yi = ystart; yi < yend; yi++)
  2285. {
  2286. // compute span endpoints
  2287. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2288. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2289. // compute starting points for u,v interpolants
  2290. ui = ul + FIXP16_ROUND_UP;
  2291. vi = vl + FIXP16_ROUND_UP;
  2292. zi = zl + FIXP16_ROUND_UP;
  2293. // compute u,v interpolants
  2294. if ((dx = (xend - xstart))>0)
  2295. {
  2296. du = (ur - ul)/dx;
  2297. dv = (vr - vl)/dx;
  2298. dz = (zr - zl)/dx;
  2299. } // end if
  2300. else
  2301. {
  2302. du = (ur - ul);
  2303. dv = (vr - vl);
  2304. dz = (zr - zl);
  2305. } // end else
  2306. ///////////////////////////////////////////////////////////////////////
  2307. // test for x clipping, LHS
  2308. if (xstart < min_clip_x)
  2309. {
  2310. // compute x overlap
  2311. dx = min_clip_x - xstart;
  2312. // slide interpolants over
  2313. ui+=dx*du;
  2314. vi+=dx*dv;
  2315. zi+=dx*dz;
  2316. // reset vars
  2317. xstart = min_clip_x;
  2318. } // end if
  2319. // test for x clipping RHS
  2320. if (xend > max_clip_x)
  2321. xend = max_clip_x;
  2322. ///////////////////////////////////////////////////////////////////////
  2323. // draw span
  2324. for (xi=xstart; xi < xend; xi++)
  2325. {
  2326.             // get textel
  2327.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2328.             if (textel)
  2329.             {
  2330.       // write textel
  2331.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + 
  2332.                              alpha_table_src2[textel];
  2333.                // update z-buffer, write thru
  2334.                z_ptr[xi] = zi;           
  2335.             } // end if
  2336. // interpolate u,v,z
  2337. ui+=du;
  2338. vi+=dv;
  2339. zi+=dz;
  2340. } // end for xi
  2341. // interpolate u,v,x along right and left edge
  2342. xl+=dxdyl;
  2343. ul+=dudyl;
  2344. vl+=dvdyl;
  2345. zl+=dzdyl;
  2346. xr+=dxdyr;
  2347. ur+=dudyr;
  2348. vr+=dvdyr;
  2349. zr+=dzdyr;
  2350.  
  2351. // advance screen ptr
  2352. screen_ptr+=mem_pitch;
  2353.         // advance zbuffer ptr
  2354.         z_ptr+=zpitch;
  2355. } // end for y
  2356. } // end if clip
  2357. else
  2358. {
  2359. // non-clip version
  2360. // point screen ptr to starting line
  2361. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2362.     // point zbuffer to starting line
  2363.     z_ptr = zbuffer + (ystart * zpitch);
  2364. for (yi = ystart; yi < yend; yi++)
  2365. {
  2366. // compute span endpoints
  2367. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2368. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2369. // compute starting points for u,v interpolants
  2370. ui = ul + FIXP16_ROUND_UP;
  2371. vi = vl + FIXP16_ROUND_UP;
  2372. zi = zl + FIXP16_ROUND_UP;
  2373. // compute u,v interpolants
  2374. if ((dx = (xend - xstart))>0)
  2375. {
  2376. du = (ur - ul)/dx;
  2377. dv = (vr - vl)/dx;
  2378. dz = (zr - zl)/dx;
  2379. } // end if
  2380. else
  2381. {
  2382. du = (ur - ul);
  2383. dv = (vr - vl);
  2384. dz = (zr - zl);
  2385. } // end else
  2386. // draw span
  2387. for (xi=xstart; xi < xend; xi++)
  2388. {
  2389.             // test if z of current pixel is nearer than current z buffer value
  2390.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2391.             if (textel)
  2392.             {
  2393.       // write textel
  2394.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + 
  2395.                              alpha_table_src2[textel];
  2396.                // update z-buffer, write thru
  2397.                z_ptr[xi] = zi;           
  2398.             } // end if
  2399. // interpolate u,v,z
  2400. ui+=du;
  2401. vi+=dv;
  2402. zi+=dz;
  2403. } // end for xi
  2404. // interpolate u,v,x along right and left edge
  2405. xl+=dxdyl;
  2406. ul+=dudyl;
  2407. vl+=dvdyl;
  2408. zl+=dzdyl;
  2409. xr+=dxdyr;
  2410. ur+=dudyr;
  2411. vr+=dvdyr;
  2412. zr+=dzdyr;
  2413. // advance screen ptr
  2414. screen_ptr+=mem_pitch;
  2415.         // advance zbuffer ptr
  2416.         z_ptr+=zpitch;
  2417. } // end for y
  2418. } // end if non-clipped
  2419. } // end if
  2420. else
  2421. if (tri_type==TRI_TYPE_GENERAL)
  2422. {
  2423. // first test for bottom clip, always
  2424. if ((yend = y2) > max_clip_y)
  2425. yend = max_clip_y;
  2426. // pre-test y clipping status
  2427. if (y1 < min_clip_y)
  2428. {
  2429. // compute all deltas
  2430. // LHS
  2431. dyl = (y2 - y1);
  2432. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  2433. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2434. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  2435. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  2436. // RHS
  2437. dyr = (y2 - y0);
  2438. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2439. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2440. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2441. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  2442. // compute overclip
  2443. dyr = (min_clip_y - y0);
  2444. dyl = (min_clip_y - y1);
  2445. // computer new LHS starting values
  2446. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  2447. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  2448. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  2449. zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  2450. // compute new RHS starting values
  2451. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  2452. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  2453. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  2454. zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  2455. // compute new starting y
  2456. ystart = min_clip_y;
  2457. // test if we need swap to keep rendering left to right
  2458. if (dxdyr > dxdyl)
  2459. {
  2460. SWAP(dxdyl,dxdyr,temp);
  2461. SWAP(dudyl,dudyr,temp);
  2462. SWAP(dvdyl,dvdyr,temp);
  2463. SWAP(dzdyl,dzdyr,temp);
  2464. SWAP(xl,xr,temp);
  2465. SWAP(ul,ur,temp);
  2466. SWAP(vl,vr,temp);
  2467. SWAP(zl,zr,temp);
  2468. SWAP(x1,x2,temp);
  2469. SWAP(y1,y2,temp);
  2470. SWAP(tu1,tu2,temp);
  2471. SWAP(tv1,tv2,temp);
  2472. SWAP(tz1,tz2,temp);
  2473. // set interpolation restart
  2474. irestart = INTERP_RHS;
  2475. } // end if
  2476. } // end if
  2477. else
  2478. if (y0 < min_clip_y)
  2479. {
  2480. // compute all deltas
  2481. // LHS
  2482. dyl = (y1 - y0);
  2483. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  2484. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  2485. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  2486. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;  
  2487. // RHS
  2488. dyr = (y2 - y0);
  2489. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2490. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2491. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2492. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  2493. // compute overclip
  2494. dy = (min_clip_y - y0);
  2495. // computer new LHS starting values
  2496. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2497. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2498. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2499. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2500. // compute new RHS starting values
  2501. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2502. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2503. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2504. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  2505. // compute new starting y
  2506. ystart = min_clip_y;
  2507. // test if we need swap to keep rendering left to right
  2508. if (dxdyr < dxdyl)
  2509. {
  2510. SWAP(dxdyl,dxdyr,temp);
  2511. SWAP(dudyl,dudyr,temp);
  2512. SWAP(dvdyl,dvdyr,temp);
  2513. SWAP(dzdyl,dzdyr,temp);
  2514. SWAP(xl,xr,temp);
  2515. SWAP(ul,ur,temp);
  2516. SWAP(vl,vr,temp);
  2517. SWAP(zl,zr,temp);
  2518. SWAP(x1,x2,temp);
  2519. SWAP(y1,y2,temp);
  2520. SWAP(tu1,tu2,temp);
  2521. SWAP(tv1,tv2,temp);
  2522. SWAP(tz1,tz2,temp);
  2523. // set interpolation restart
  2524. irestart = INTERP_RHS;
  2525. } // end if
  2526. } // end if
  2527. else
  2528. {
  2529. // no initial y clipping
  2530. // compute all deltas
  2531. // LHS
  2532. dyl = (y1 - y0);
  2533. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  2534. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  2535. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  2536. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;   
  2537. // RHS
  2538. dyr = (y2 - y0);
  2539. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  2540. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2541. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2542. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;  
  2543. // no clipping y
  2544. // set starting values
  2545. xl = (x0 << FIXP16_SHIFT);
  2546. xr = (x0 << FIXP16_SHIFT);
  2547. ul = (tu0 << FIXP16_SHIFT);
  2548. vl = (tv0 << FIXP16_SHIFT);
  2549. zl = (tz0 << FIXP16_SHIFT);
  2550. ur = (tu0 << FIXP16_SHIFT);
  2551. vr = (tv0 << FIXP16_SHIFT);
  2552. zr = (tz0 << FIXP16_SHIFT);
  2553. // set starting y
  2554. ystart = y0;
  2555. // test if we need swap to keep rendering left to right
  2556. if (dxdyr < dxdyl)
  2557. {
  2558. SWAP(dxdyl,dxdyr,temp);
  2559. SWAP(dudyl,dudyr,temp);
  2560. SWAP(dvdyl,dvdyr,temp);
  2561. SWAP(dzdyl,dzdyr,temp);
  2562. SWAP(xl,xr,temp);
  2563. SWAP(ul,ur,temp);
  2564. SWAP(vl,vr,temp);
  2565. SWAP(zl,zr,temp);
  2566. SWAP(x1,x2,temp);
  2567. SWAP(y1,y2,temp);
  2568. SWAP(tu1,tu2,temp);
  2569. SWAP(tv1,tv2,temp);
  2570. SWAP(tz1,tz2,temp);
  2571. // set interpolation restart
  2572. irestart = INTERP_RHS;
  2573. } // end if
  2574. } // end else
  2575.     // test for horizontal clipping
  2576. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  2577. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  2578. (x2 < min_clip_x) || (x2 > max_clip_x))
  2579. {
  2580.     // clip version
  2581. // x clipping
  2582. // point screen ptr to starting line
  2583. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2584.     // point zbuffer to starting line
  2585.     z_ptr = zbuffer + (ystart * zpitch);
  2586. for (yi = ystart; yi < yend; yi++)
  2587. {
  2588. // compute span endpoints
  2589. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2590. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2591. // compute starting points for u,v interpolants
  2592. ui = ul + FIXP16_ROUND_UP;
  2593. vi = vl + FIXP16_ROUND_UP;
  2594. zi = zl + FIXP16_ROUND_UP;
  2595. // compute u,v interpolants
  2596. if ((dx = (xend - xstart))>0)
  2597. {
  2598. du = (ur - ul)/dx;
  2599. dv = (vr - vl)/dx;
  2600. dz = (zr - zl)/dx;
  2601. } // end if
  2602. else
  2603. {
  2604. du = (ur - ul);
  2605. dv = (vr - vl);
  2606. dz = (zr - zl);
  2607. } // end else
  2608. ///////////////////////////////////////////////////////////////////////
  2609. // test for x clipping, LHS
  2610. if (xstart < min_clip_x)
  2611. {
  2612. // compute x overlap
  2613. dx = min_clip_x - xstart;
  2614. // slide interpolants over
  2615. ui+=dx*du;
  2616. vi+=dx*dv;
  2617. zi+=dx*dz;
  2618. // set x to left clip edge
  2619. xstart = min_clip_x;
  2620. } // end if
  2621. // test for x clipping RHS
  2622. if (xend > max_clip_x)
  2623. xend = max_clip_x;
  2624. ///////////////////////////////////////////////////////////////////////
  2625. // draw span
  2626. for (xi=xstart; xi < xend; xi++)
  2627. {
  2628.             // get textel
  2629.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2630.             if (textel)
  2631.             {
  2632.       // write textel
  2633.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + 
  2634.                              alpha_table_src2[textel];
  2635.                // update z-buffer, write thru
  2636.                z_ptr[xi] = zi;           
  2637.             } // end if
  2638.     
  2639. // interpolate u,v,z
  2640. ui+=du;
  2641. vi+=dv;
  2642. zi+=dz;
  2643. } // end for xi
  2644. // interpolate u,v,x along right and left edge
  2645. xl+=dxdyl;
  2646. ul+=dudyl;
  2647. vl+=dvdyl;
  2648. zl+=dzdyl;
  2649. xr+=dxdyr;
  2650. ur+=dudyr;
  2651. vr+=dvdyr;
  2652. zr+=dzdyr;
  2653. // advance screen ptr
  2654. screen_ptr+=mem_pitch;
  2655.         // advance zbuffer ptr
  2656.         z_ptr+=zpitch;
  2657. // test for yi hitting second region, if so change interpolant
  2658. if (yi==yrestart)
  2659. {
  2660.     // test interpolation side change flag
  2661. if (irestart == INTERP_LHS)
  2662. {
  2663. // LHS
  2664. dyl = (y2 - y1);
  2665. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  2666. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2667. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  2668. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  2669. // set starting values
  2670. xl = (x1  << FIXP16_SHIFT);
  2671. ul = (tu1 << FIXP16_SHIFT);
  2672. vl = (tv1 << FIXP16_SHIFT);
  2673. zl = (tz1 << FIXP16_SHIFT);
  2674. // interpolate down on LHS to even up
  2675. xl+=dxdyl;
  2676. ul+=dudyl;
  2677. vl+=dvdyl;
  2678. zl+=dzdyl;
  2679. } // end if
  2680. else
  2681. {
  2682. // RHS
  2683. dyr = (y1 - y2);
  2684. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  2685. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  2686. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  2687. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;  
  2688. // set starting values
  2689. xr = (x2  << FIXP16_SHIFT);
  2690. ur = (tu2 << FIXP16_SHIFT);
  2691. vr = (tv2 << FIXP16_SHIFT);
  2692. zr = (tz2 << FIXP16_SHIFT);
  2693. // interpolate down on RHS to even up
  2694. xr+=dxdyr;
  2695. ur+=dudyr;
  2696. vr+=dvdyr;
  2697. zr+=dzdyr;
  2698. } // end else
  2699. } // end if
  2700. } // end for y
  2701. } // end if
  2702. else
  2703. {
  2704. // no x clipping
  2705. // point screen ptr to starting line
  2706. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2707.     // point zbuffer to starting line
  2708.     z_ptr = zbuffer + (ystart * zpitch);
  2709. for (yi = ystart; yi < yend; yi++)
  2710. {
  2711. // compute span endpoints
  2712. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2713. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2714. // compute starting points for u,v interpolants
  2715. ui = ul + FIXP16_ROUND_UP;
  2716. vi = vl + FIXP16_ROUND_UP;
  2717. zi = zl + FIXP16_ROUND_UP;
  2718. // compute u,v interpolants
  2719. if ((dx = (xend - xstart))>0)
  2720. {
  2721. du = (ur - ul)/dx;
  2722. dv = (vr - vl)/dx;
  2723. dz = (zr - zl)/dx;
  2724. } // end if
  2725. else
  2726. {
  2727. du = (ur - ul);
  2728. dv = (vr - vl);
  2729. dz = (zr - zl);
  2730. } // end else
  2731. // draw span
  2732. for (xi=xstart; xi < xend; xi++)
  2733. {
  2734.             // test if z of current pixel is nearer than current z buffer value
  2735.             // get textel
  2736.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2737.             if (textel)
  2738.             {
  2739.       // write textel
  2740.                screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] + 
  2741.                              alpha_table_src2[textel];
  2742.                // update z-buffer, write thru
  2743.                z_ptr[xi] = zi;           
  2744.             } // end if
  2745. // interpolate u,v
  2746. ui+=du;
  2747. vi+=dv;
  2748. zi+=dz;
  2749. } // end for xi
  2750. // interpolate u,v,x along right and left edge
  2751. xl+=dxdyl;
  2752. ul+=dudyl;
  2753. vl+=dvdyl;
  2754. zl+=dzdyl;
  2755. xr+=dxdyr;
  2756. ur+=dudyr;
  2757. vr+=dvdyr;
  2758. zr+=dzdyr;
  2759. // advance screen ptr
  2760. screen_ptr+=mem_pitch;
  2761.         // advance zbuffer ptr
  2762.         z_ptr+=zpitch;
  2763. // test for yi hitting second region, if so change interpolant
  2764. if (yi==yrestart)
  2765. {
  2766. // test interpolation side change flag
  2767. if (irestart == INTERP_LHS)
  2768. {
  2769. // LHS
  2770. dyl = (y2 - y1);
  2771. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  2772. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2773. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  2774. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  2775. // set starting values
  2776. xl = (x1  << FIXP16_SHIFT);
  2777. ul = (tu1 << FIXP16_SHIFT);
  2778. vl = (tv1 << FIXP16_SHIFT);
  2779. zl = (tz1 << FIXP16_SHIFT);
  2780. // interpolate down on LHS to even up
  2781. xl+=dxdyl;
  2782. ul+=dudyl;
  2783. vl+=dvdyl;
  2784. zl+=dzdyl;
  2785. } // end if
  2786. else
  2787. {
  2788. // RHS
  2789. dyr = (y1 - y2);
  2790. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  2791. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  2792. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  2793. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr; 
  2794. // set starting values
  2795. xr = (x2  << FIXP16_SHIFT);
  2796. ur = (tu2 << FIXP16_SHIFT);
  2797. vr = (tv2 << FIXP16_SHIFT);
  2798. zr = (tz2 << FIXP16_SHIFT);
  2799. // interpolate down on RHS to even up
  2800. xr+=dxdyr;
  2801. ur+=dudyr;
  2802. vr+=dvdyr;
  2803. zr+=dzdyr;
  2804. } // end else
  2805. } // end if
  2806. } // end for y
  2807.    } // end else
  2808. } // end if
  2809. } // end Draw_Textured_TriangleWTZB_Alpha16_2
  2810. ///////////////////////////////////////////////////////////////////////////////
  2811. void Draw_Textured_TriangleZB3_16(POLYF4DV2_PTR face,  // ptr to face
  2812.                               UCHAR *_dest_buffer,  // pointer to video buffer
  2813.                               int mem_pitch,        // bytes per line, 320, 640 etc.
  2814.                               UCHAR *_zbuffer,       // pointer to z-buffer
  2815.                               int zpitch)          // bytes per line of zbuffer
  2816. {
  2817. // this function draws a textured triangle in 16-bit mode
  2818. int v0=0,
  2819.     v1=1,
  2820. v2=2,
  2821. temp=0,
  2822. tri_type = TRI_TYPE_NONE,
  2823. irestart = INTERP_LHS;
  2824. int dx,dy,dyl,dyr,      // general deltas
  2825.     u,v,z,
  2826.     du,dv,dz,
  2827.     xi,yi,              // the current interpolated x,y
  2828. ui,vi,zi,           // the current interpolated u,v,z
  2829. index_x,index_y,    // looping vars
  2830. x,y,                // hold general x,y
  2831. xstart,
  2832. xend,
  2833. ystart,
  2834. yrestart,
  2835. yend,
  2836. xl,                 
  2837. dxdyl,              
  2838. xr,
  2839. dxdyr,             
  2840. dudyl,    
  2841. ul,
  2842. dvdyl,   
  2843. vl,
  2844. dzdyl,   
  2845. zl,
  2846. dudyr,
  2847. ur,
  2848. dvdyr,
  2849. vr,
  2850. dzdyr,
  2851. zr;
  2852. int x0,y0,tu0,tv0,tz0,    // cached vertices
  2853. x1,y1,tu1,tv1,tz1,
  2854. x2,y2,tu2,tv2,tz2;
  2855. USHORT *screen_ptr  = NULL,
  2856.    *screen_line = NULL,
  2857.    *textmap     = NULL,
  2858.        *dest_buffer = (USHORT *)_dest_buffer,
  2859.         textel;                       
  2860. UINT  *z_ptr = NULL,
  2861.       *zbuffer = (UINT *)_zbuffer;
  2862. #ifdef DEBUG_ON
  2863. // track rendering stats
  2864.     debug_polys_rendered_per_frame++;
  2865. #endif
  2866. // extract texture map
  2867. textmap = (USHORT *)face->texture->buffer;
  2868. // extract base 2 of texture width
  2869. int texture_shift2 = logbase2ofx[face->texture->width];
  2870. // adjust memory pitch to words, divide by 2
  2871. mem_pitch >>=1;
  2872. // adjust zbuffer pitch for 32 bit alignment
  2873. zpitch >>= 2;
  2874. // apply fill convention to coordinates
  2875. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  2876. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  2877. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  2878. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  2879. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  2880. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  2881. // first trivial clipping rejection tests 
  2882. if (((face->tvlist[0].y < min_clip_y)  && 
  2883.  (face->tvlist[1].y < min_clip_y)  &&
  2884.  (face->tvlist[2].y < min_clip_y)) ||
  2885. ((face->tvlist[0].y > max_clip_y)  && 
  2886.  (face->tvlist[1].y > max_clip_y)  &&
  2887.  (face->tvlist[2].y > max_clip_y)) ||
  2888. ((face->tvlist[0].x < min_clip_x)  && 
  2889.  (face->tvlist[1].x < min_clip_x)  &&
  2890.  (face->tvlist[2].x < min_clip_x)) ||
  2891. ((face->tvlist[0].x > max_clip_x)  && 
  2892.  (face->tvlist[1].x > max_clip_x)  &&
  2893.  (face->tvlist[2].x > max_clip_x)))
  2894.    return;
  2895. // sort vertices
  2896. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  2897. {SWAP(v0,v1,temp);} 
  2898. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  2899. {SWAP(v0,v2,temp);}
  2900. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  2901. {SWAP(v1,v2,temp);}
  2902. // now test for trivial flat sided cases
  2903. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  2904. // set triangle type
  2905. tri_type = TRI_TYPE_FLAT_TOP;
  2906. // sort vertices left to right
  2907. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  2908. {SWAP(v0,v1,temp);}
  2909. } // end if
  2910. else
  2911. // now test for trivial flat sided cases
  2912. if (FCMP(face->tvlist[v1].y ,face->tvlist[v2].y))
  2913. // set triangle type
  2914. tri_type = TRI_TYPE_FLAT_BOTTOM;
  2915. // sort vertices left to right
  2916. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  2917. {SWAP(v1,v2,temp);}
  2918. } // end if
  2919. else
  2920. {
  2921. // must be a general triangle
  2922. tri_type = TRI_TYPE_GENERAL;
  2923. } // end else
  2924. // extract vertices for processing, now that we have order
  2925. x0  = (int)(face->tvlist[v0].x+0.0);
  2926. y0  = (int)(face->tvlist[v0].y+0.0);
  2927. tu0 = (int)(face->tvlist[v0].u0);
  2928. tv0 = (int)(face->tvlist[v0].v0);
  2929. tz0 = (int)(face->tvlist[v0].z+0.5);
  2930. x1  = (int)(face->tvlist[v1].x+0.0);
  2931. y1  = (int)(face->tvlist[v1].y+0.0);
  2932. tu1 = (int)(face->tvlist[v1].u0);
  2933. tv1 = (int)(face->tvlist[v1].v0);
  2934. tz1 = (int)(face->tvlist[v1].z+0.5);
  2935. x2  = (int)(face->tvlist[v2].x+0.0);
  2936. y2  = (int)(face->tvlist[v2].y+0.0);
  2937. tu2 = (int)(face->tvlist[v2].u0);
  2938. tv2 = (int)(face->tvlist[v2].v0);
  2939. tz2 = (int)(face->tvlist[v2].z+0.5);
  2940. // degenerate triangle
  2941. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  2942.    return;
  2943. // set interpolation restart value
  2944. yrestart = y1;
  2945. // what kind of triangle
  2946. if (tri_type & TRI_TYPE_FLAT_MASK)
  2947. {
  2948. if (tri_type == TRI_TYPE_FLAT_TOP)
  2949. {
  2950. // compute all deltas
  2951. dy = (y2 - y0);
  2952. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2953. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2954. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  2955. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;    
  2956. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  2957. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  2958. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  2959. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;  
  2960. // test for y clipping
  2961. if (y0 < min_clip_y)
  2962. {
  2963. // compute overclip
  2964. dy = (min_clip_y - y0);
  2965. // computer new LHS starting values
  2966. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2967. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2968. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2969. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2970. // compute new RHS starting values
  2971. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  2972. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  2973. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  2974. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  2975. // compute new starting y
  2976. ystart = min_clip_y;
  2977. } // end if
  2978. else
  2979. {
  2980. // no clipping
  2981. // set starting values
  2982. xl = (x0 << FIXP16_SHIFT);
  2983. xr = (x1 << FIXP16_SHIFT);
  2984. ul = (tu0 << FIXP16_SHIFT);
  2985. vl = (tv0 << FIXP16_SHIFT);
  2986. zl = (tz0 << FIXP16_SHIFT);
  2987. ur = (tu1 << FIXP16_SHIFT);
  2988. vr = (tv1 << FIXP16_SHIFT);
  2989. zr = (tz1 << FIXP16_SHIFT);
  2990. // set starting y
  2991. ystart = y0;
  2992. } // end else
  2993. } // end if flat top
  2994. else
  2995. {
  2996. // must be flat bottom
  2997. // compute all deltas
  2998. dy = (y1 - y0);
  2999. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  3000. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  3001. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  3002. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy;   
  3003. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  3004. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  3005. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  3006. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  3007. // test for y clipping
  3008. if (y0 < min_clip_y)
  3009. {
  3010. // compute overclip
  3011. dy = (min_clip_y - y0);
  3012. // computer new LHS starting values
  3013. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  3014. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  3015. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  3016. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  3017. // compute new RHS starting values
  3018. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  3019. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  3020. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  3021. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  3022. // compute new starting y
  3023. ystart = min_clip_y;
  3024. } // end if
  3025. else
  3026. {
  3027. // no clipping
  3028. // set starting values
  3029. xl = (x0 << FIXP16_SHIFT);
  3030. xr = (x0 << FIXP16_SHIFT);
  3031. ul = (tu0 << FIXP16_SHIFT);
  3032. vl = (tv0 << FIXP16_SHIFT);
  3033. zl = (tz0 << FIXP16_SHIFT);
  3034. ur = (tu0 << FIXP16_SHIFT);
  3035. vr = (tv0 << FIXP16_SHIFT);
  3036. zr = (tz0 << FIXP16_SHIFT);
  3037. // set starting y
  3038. ystart = y0;
  3039. } // end else
  3040. } // end else flat bottom
  3041. // test for bottom clip, always
  3042. if ((yend = y2) > max_clip_y)
  3043. yend = max_clip_y;
  3044.     // test for horizontal clipping
  3045. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  3046. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  3047. (x2 < min_clip_x) || (x2 > max_clip_x))
  3048. {
  3049.     // clip version
  3050. // point screen ptr to starting line
  3051. screen_ptr = dest_buffer + (ystart * mem_pitch);
  3052.     // point zbuffer to starting line
  3053.     z_ptr = zbuffer + (ystart * zpitch);
  3054. for (yi = ystart; yi < yend; yi++)
  3055. {
  3056. // compute span endpoints
  3057. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3058. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3059. // compute starting points for u,v interpolants
  3060. ui = ul + FIXP16_ROUND_UP;
  3061. vi = vl + FIXP16_ROUND_UP;
  3062. zi = zl + FIXP16_ROUND_UP;
  3063. // compute u,v interpolants
  3064. if ((dx = (xend - xstart))>0)
  3065. {
  3066. du = (ur - ul)/dx;
  3067. dv = (vr - vl)/dx;
  3068. dz = (zr - zl)/dx;
  3069. } // end if
  3070. else
  3071. {
  3072. du = (ur - ul);
  3073. dv = (vr - vl);
  3074. dz = (zr - zl);
  3075. } // end else
  3076. ///////////////////////////////////////////////////////////////////////
  3077. // test for x clipping, LHS
  3078. if (xstart < min_clip_x)
  3079. {
  3080. // compute x overlap
  3081. dx = min_clip_x - xstart;
  3082. // slide interpolants over
  3083. ui+=dx*du;
  3084. vi+=dx*dv;
  3085. zi+=dx*dz;
  3086. // reset vars
  3087. xstart = min_clip_x;
  3088. } // end if
  3089. // test for x clipping RHS
  3090. if (xend > max_clip_x)
  3091. xend = max_clip_x;
  3092. ///////////////////////////////////////////////////////////////////////
  3093. // draw span
  3094. for (xi=xstart; xi < xend; xi++)
  3095. {
  3096.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  3097.             if (textel)
  3098.             {
  3099.             // test if z of current pixel is nearer than current z buffer value
  3100.             if (zi < z_ptr[xi])
  3101.                {
  3102.        // write textel
  3103.                screen_ptr[xi] = textel;
  3104.                // update z-buffer
  3105.                z_ptr[xi] = zi;           
  3106.                } // end if
  3107.              } // end if
  3108.         
  3109. // interpolate u,v,z
  3110. ui+=du;
  3111. vi+=dv;
  3112. zi+=dz;
  3113. } // end for xi
  3114. // interpolate u,v,x along right and left edge
  3115. xl+=dxdyl;
  3116. ul+=dudyl;
  3117. vl+=dvdyl;
  3118. zl+=dzdyl;
  3119. xr+=dxdyr;
  3120. ur+=dudyr;
  3121. vr+=dvdyr;
  3122. zr+=dzdyr;
  3123.  
  3124. // advance screen ptr
  3125. screen_ptr+=mem_pitch;
  3126.         // advance zbuffer ptr
  3127.         z_ptr+=zpitch;
  3128. } // end for y
  3129. } // end if clip
  3130. else
  3131. {
  3132. // non-clip version
  3133. // point screen ptr to starting line
  3134. screen_ptr = dest_buffer + (ystart * mem_pitch);
  3135.     // point zbuffer to starting line
  3136.     z_ptr = zbuffer + (ystart * zpitch);
  3137. for (yi = ystart; yi < yend; yi++)
  3138. {
  3139. // compute span endpoints
  3140. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3141. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3142. // compute starting points for u,v interpolants
  3143. ui = ul + FIXP16_ROUND_UP;
  3144. vi = vl + FIXP16_ROUND_UP;
  3145. zi = zl + FIXP16_ROUND_UP;
  3146. // compute u,v interpolants
  3147. if ((dx = (xend - xstart))>0)
  3148. {
  3149. du = (ur - ul)/dx;
  3150. dv = (vr - vl)/dx;
  3151. dz = (zr - zl)/dx;
  3152. } // end if
  3153. else
  3154. {
  3155. du = (ur - ul);
  3156. dv = (vr - vl);
  3157. dz = (zr - zl);
  3158. } // end else
  3159. // draw span
  3160. for (xi=xstart; xi < xend; xi++)
  3161. {
  3162.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  3163.             if (textel)
  3164.             {
  3165.             // test if z of current pixel is nearer than current z buffer value
  3166.             if (zi < z_ptr[xi])
  3167.                {
  3168.        // write textel
  3169.                screen_ptr[xi] = textel;
  3170.                // update z-buffer
  3171.                z_ptr[xi] = zi;           
  3172.                } // end if
  3173.              } // end if
  3174. // interpolate u,v,z
  3175. ui+=du;
  3176. vi+=dv;
  3177. zi+=dz;
  3178. } // end for xi
  3179. // interpolate u,v,x along right and left edge
  3180. xl+=dxdyl;
  3181. ul+=dudyl;
  3182. vl+=dvdyl;
  3183. zl+=dzdyl;
  3184. xr+=dxdyr;
  3185. ur+=dudyr;
  3186. vr+=dvdyr;
  3187. zr+=dzdyr;
  3188. // advance screen ptr
  3189. screen_ptr+=mem_pitch;
  3190.         // advance zbuffer ptr
  3191.         z_ptr+=zpitch;
  3192. } // end for y
  3193. } // end if non-clipped
  3194. } // end if
  3195. else
  3196. if (tri_type==TRI_TYPE_GENERAL)
  3197. {
  3198. // first test for bottom clip, always
  3199. if ((yend = y2) > max_clip_y)
  3200. yend = max_clip_y;
  3201. // pre-test y clipping status
  3202. if (y1 < min_clip_y)
  3203. {
  3204. // compute all deltas
  3205. // LHS
  3206. dyl = (y2 - y1);
  3207. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  3208. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  3209. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  3210. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  3211. // RHS
  3212. dyr = (y2 - y0);
  3213. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  3214. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  3215. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  3216. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  3217. // compute overclip
  3218. dyr = (min_clip_y - y0);
  3219. dyl = (min_clip_y - y1);
  3220. // computer new LHS starting values
  3221. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  3222. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  3223. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  3224. zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  3225. // compute new RHS starting values
  3226. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  3227. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  3228. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  3229. zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  3230. // compute new starting y
  3231. ystart = min_clip_y;
  3232. // test if we need swap to keep rendering left to right
  3233. if (dxdyr > dxdyl)
  3234. {
  3235. SWAP(dxdyl,dxdyr,temp);
  3236. SWAP(dudyl,dudyr,temp);
  3237. SWAP(dvdyl,dvdyr,temp);
  3238. SWAP(dzdyl,dzdyr,temp);
  3239. SWAP(xl,xr,temp);
  3240. SWAP(ul,ur,temp);
  3241. SWAP(vl,vr,temp);
  3242. SWAP(zl,zr,temp);
  3243. SWAP(x1,x2,temp);
  3244. SWAP(y1,y2,temp);
  3245. SWAP(tu1,tu2,temp);
  3246. SWAP(tv1,tv2,temp);
  3247. SWAP(tz1,tz2,temp);
  3248. // set interpolation restart
  3249. irestart = INTERP_RHS;
  3250. } // end if
  3251. } // end if
  3252. else
  3253. if (y0 < min_clip_y)
  3254. {
  3255. // compute all deltas
  3256. // LHS
  3257. dyl = (y1 - y0);
  3258. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  3259. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  3260. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  3261. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;  
  3262. // RHS
  3263. dyr = (y2 - y0);
  3264. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  3265. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  3266. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  3267. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  3268. // compute overclip
  3269. dy = (min_clip_y - y0);
  3270. // computer new LHS starting values
  3271. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  3272. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  3273. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  3274. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  3275. // compute new RHS starting values
  3276. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  3277. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  3278. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  3279. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  3280. // compute new starting y
  3281. ystart = min_clip_y;
  3282. // test if we need swap to keep rendering left to right
  3283. if (dxdyr < dxdyl)
  3284. {
  3285. SWAP(dxdyl,dxdyr,temp);
  3286. SWAP(dudyl,dudyr,temp);
  3287. SWAP(dvdyl,dvdyr,temp);
  3288. SWAP(dzdyl,dzdyr,temp);
  3289. SWAP(xl,xr,temp);
  3290. SWAP(ul,ur,temp);
  3291. SWAP(vl,vr,temp);
  3292. SWAP(zl,zr,temp);
  3293. SWAP(x1,x2,temp);
  3294. SWAP(y1,y2,temp);
  3295. SWAP(tu1,tu2,temp);
  3296. SWAP(tv1,tv2,temp);
  3297. SWAP(tz1,tz2,temp);
  3298. // set interpolation restart
  3299. irestart = INTERP_RHS;
  3300. } // end if
  3301. } // end if
  3302. else
  3303. {
  3304. // no initial y clipping
  3305. // compute all deltas
  3306. // LHS
  3307. dyl = (y1 - y0);
  3308. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  3309. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  3310. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  3311. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;   
  3312. // RHS
  3313. dyr = (y2 - y0);
  3314. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  3315. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  3316. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  3317. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;  
  3318. // no clipping y
  3319. // set starting values
  3320. xl = (x0 << FIXP16_SHIFT);
  3321. xr = (x0 << FIXP16_SHIFT);
  3322. ul = (tu0 << FIXP16_SHIFT);
  3323. vl = (tv0 << FIXP16_SHIFT);
  3324. zl = (tz0 << FIXP16_SHIFT);
  3325. ur = (tu0 << FIXP16_SHIFT);
  3326. vr = (tv0 << FIXP16_SHIFT);
  3327. zr = (tz0 << FIXP16_SHIFT);
  3328. // set starting y
  3329. ystart = y0;
  3330. // test if we need swap to keep rendering left to right
  3331. if (dxdyr < dxdyl)
  3332. {
  3333. SWAP(dxdyl,dxdyr,temp);
  3334. SWAP(dudyl,dudyr,temp);
  3335. SWAP(dvdyl,dvdyr,temp);
  3336. SWAP(dzdyl,dzdyr,temp);
  3337. SWAP(xl,xr,temp);
  3338. SWAP(ul,ur,temp);
  3339. SWAP(vl,vr,temp);
  3340. SWAP(zl,zr,temp);
  3341. SWAP(x1,x2,temp);
  3342. SWAP(y1,y2,temp);
  3343. SWAP(tu1,tu2,temp);
  3344. SWAP(tv1,tv2,temp);
  3345. SWAP(tz1,tz2,temp);
  3346. // set interpolation restart
  3347. irestart = INTERP_RHS;
  3348. } // end if
  3349. } // end else
  3350.     // test for horizontal clipping
  3351. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  3352. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  3353. (x2 < min_clip_x) || (x2 > max_clip_x))
  3354. {
  3355.     // clip version
  3356. // x clipping
  3357. // point screen ptr to starting line
  3358. screen_ptr = dest_buffer + (ystart * mem_pitch);
  3359.     // point zbuffer to starting line
  3360.     z_ptr = zbuffer + (ystart * zpitch);
  3361. for (yi = ystart; yi < yend; yi++)
  3362. {
  3363. // compute span endpoints
  3364. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3365. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3366. // compute starting points for u,v interpolants
  3367. ui = ul + FIXP16_ROUND_UP;
  3368. vi = vl + FIXP16_ROUND_UP;
  3369. zi = zl + FIXP16_ROUND_UP;
  3370. // compute u,v interpolants
  3371. if ((dx = (xend - xstart))>0)
  3372. {
  3373. du = (ur - ul)/dx;
  3374. dv = (vr - vl)/dx;
  3375. dz = (zr - zl)/dx;
  3376. } // end if
  3377. else
  3378. {
  3379. du = (ur - ul);
  3380. dv = (vr - vl);
  3381. dz = (zr - zl);
  3382. } // end else
  3383. ///////////////////////////////////////////////////////////////////////
  3384. // test for x clipping, LHS
  3385. if (xstart < min_clip_x)
  3386. {
  3387. // compute x overlap
  3388. dx = min_clip_x - xstart;
  3389. // slide interpolants over
  3390. ui+=dx*du;
  3391. vi+=dx*dv;
  3392. zi+=dx*dz;
  3393. // set x to left clip edge
  3394. xstart = min_clip_x;
  3395. } // end if
  3396. // test for x clipping RHS
  3397. if (xend > max_clip_x)
  3398. xend = max_clip_x;
  3399. ///////////////////////////////////////////////////////////////////////
  3400. // draw span
  3401. for (xi=xstart; xi < xend; xi++)
  3402. {
  3403.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  3404.             if (textel)
  3405.             {
  3406.             // test if z of current pixel is nearer than current z buffer value
  3407.             if (zi < z_ptr[xi])
  3408.                {
  3409.        // write textel
  3410.                screen_ptr[xi] = textel;
  3411.                // update z-buffer
  3412.                z_ptr[xi] = zi;           
  3413.                } // end if
  3414.              } // end if
  3415. // interpolate u,v,z
  3416. ui+=du;
  3417. vi+=dv;
  3418. zi+=dz;
  3419. } // end for xi
  3420. // interpolate u,v,x along right and left edge
  3421. xl+=dxdyl;
  3422. ul+=dudyl;
  3423. vl+=dvdyl;
  3424. zl+=dzdyl;
  3425. xr+=dxdyr;
  3426. ur+=dudyr;
  3427. vr+=dvdyr;
  3428. zr+=dzdyr;
  3429. // advance screen ptr
  3430. screen_ptr+=mem_pitch;
  3431.         // advance zbuffer ptr
  3432.         z_ptr+=zpitch;
  3433. // test for yi hitting second region, if so change interpolant
  3434. if (yi==yrestart)
  3435. {
  3436.     // test interpolation side change flag
  3437. if (irestart == INTERP_LHS)
  3438. {
  3439. // LHS
  3440. dyl = (y2 - y1);
  3441. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  3442. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  3443. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  3444. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  3445. // set starting values
  3446. xl = (x1  << FIXP16_SHIFT);
  3447. ul = (tu1 << FIXP16_SHIFT);
  3448. vl = (tv1 << FIXP16_SHIFT);
  3449. zl = (tz1 << FIXP16_SHIFT);
  3450. // interpolate down on LHS to even up
  3451. xl+=dxdyl;
  3452. ul+=dudyl;
  3453. vl+=dvdyl;
  3454. zl+=dzdyl;
  3455. } // end if
  3456. else
  3457. {
  3458. // RHS
  3459. dyr = (y1 - y2);
  3460. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  3461. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  3462. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  3463. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;  
  3464. // set starting values
  3465. xr = (x2  << FIXP16_SHIFT);
  3466. ur = (tu2 << FIXP16_SHIFT);
  3467. vr = (tv2 << FIXP16_SHIFT);
  3468. zr = (tz2 << FIXP16_SHIFT);
  3469. // interpolate down on RHS to even up
  3470. xr+=dxdyr;
  3471. ur+=dudyr;
  3472. vr+=dvdyr;
  3473. zr+=dzdyr;
  3474. } // end else
  3475. } // end if
  3476. } // end for y
  3477. } // end if
  3478. else
  3479. {
  3480. // no x clipping
  3481. // point screen ptr to starting line
  3482. screen_ptr = dest_buffer + (ystart * mem_pitch);
  3483.     // point zbuffer to starting line
  3484.     z_ptr = zbuffer + (ystart * zpitch);
  3485. for (yi = ystart; yi < yend; yi++)
  3486. {
  3487. // compute span endpoints
  3488. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3489. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3490. // compute starting points for u,v interpolants
  3491. ui = ul + FIXP16_ROUND_UP;
  3492. vi = vl + FIXP16_ROUND_UP;
  3493. zi = zl + FIXP16_ROUND_UP;
  3494. // compute u,v interpolants
  3495. if ((dx = (xend - xstart))>0)
  3496. {
  3497. du = (ur - ul)/dx;
  3498. dv = (vr - vl)/dx;
  3499. dz = (zr - zl)/dx;
  3500. } // end if
  3501. else
  3502. {
  3503. du = (ur - ul);
  3504. dv = (vr - vl);
  3505. dz = (zr - zl);
  3506. } // end else
  3507. // draw span
  3508. for (xi=xstart; xi < xend; xi++)
  3509. {
  3510.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  3511.             if (textel)
  3512.             {
  3513.             // test if z of current pixel is nearer than current z buffer value
  3514.             if (zi < z_ptr[xi])
  3515.                {
  3516.        // write textel
  3517.                screen_ptr[xi] = textel;
  3518.                // update z-buffer
  3519.                z_ptr[xi] = zi;           
  3520.                } // end if
  3521.              } // end if
  3522. // interpolate u,v
  3523. ui+=du;
  3524. vi+=dv;
  3525. zi+=dz;
  3526. } // end for xi
  3527. // interpolate u,v,x along right and left edge
  3528. xl+=dxdyl;
  3529. ul+=dudyl;
  3530. vl+=dvdyl;
  3531. zl+=dzdyl;
  3532. xr+=dxdyr;
  3533. ur+=dudyr;
  3534. vr+=dvdyr;
  3535. zr+=dzdyr;
  3536. // advance screen ptr
  3537. screen_ptr+=mem_pitch;
  3538.         // advance zbuffer ptr
  3539.         z_ptr+=zpitch;
  3540. // test for yi hitting second region, if so change interpolant
  3541. if (yi==yrestart)
  3542. {
  3543. // test interpolation side change flag
  3544. if (irestart == INTERP_LHS)
  3545. {
  3546. // LHS
  3547. dyl = (y2 - y1);
  3548. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  3549. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  3550. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  3551. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  3552. // set starting values
  3553. xl = (x1  << FIXP16_SHIFT);
  3554. ul = (tu1 << FIXP16_SHIFT);
  3555. vl = (tv1 << FIXP16_SHIFT);
  3556. zl = (tz1 << FIXP16_SHIFT);
  3557. // interpolate down on LHS to even up
  3558. xl+=dxdyl;
  3559. ul+=dudyl;
  3560. vl+=dvdyl;
  3561. zl+=dzdyl;
  3562. } // end if
  3563. else
  3564. {
  3565. // RHS
  3566. dyr = (y1 - y2);
  3567. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  3568. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  3569. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  3570. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr; 
  3571. // set starting values
  3572. xr = (x2  << FIXP16_SHIFT);
  3573. ur = (tu2 << FIXP16_SHIFT);
  3574. vr = (tv2 << FIXP16_SHIFT);
  3575. zr = (tz2 << FIXP16_SHIFT);
  3576. // interpolate down on RHS to even up
  3577. xr+=dxdyr;
  3578. ur+=dudyr;
  3579. vr+=dvdyr;
  3580. zr+=dzdyr;
  3581. } // end else
  3582. } // end if
  3583. } // end for y
  3584.    } // end else
  3585. } // end if
  3586. } // end Draw_Textured_TriangleZB3_16