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

游戏

开发平台:

Visual C++

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