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

游戏

开发平台:

Visual C++

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