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

游戏

开发平台:

Visual C++

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