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

游戏

开发平台:

Visual C++

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