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

游戏

开发平台:

Visual C++

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