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

游戏

开发平台:

Visual C++

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