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

游戏

开发平台:

Visual C++

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