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

游戏

开发平台:

Visual C++

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