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

游戏

开发平台:

Visual C++

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