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

游戏

开发平台:

Visual C++

  1. // compute starting points for u,v,w interpolants
  2. ui = ul + FIXP16_ROUND_UP;
  3. vi = vl + FIXP16_ROUND_UP;
  4. wi = wl + FIXP16_ROUND_UP;
  5. zi = zl + FIXP16_ROUND_UP;
  6. si = sl + FIXP16_ROUND_UP;
  7. ti = tl + FIXP16_ROUND_UP;
  8. // compute u,v interpolants
  9. if ((dx = (xend - xstart))>0)
  10. {
  11. du = (ur - ul)/dx;
  12. dv = (vr - vl)/dx;
  13. dw = (wr - wl)/dx;
  14. dz = (zr - zl)/dx;
  15. ds = (sr - sl)/dx;
  16. dt = (tr - tl)/dx;
  17. } // end if
  18. else
  19. {
  20. du = (ur - ul);
  21. dv = (vr - vl);
  22. dw = (wr - wl);
  23. dz = (zr - zl);
  24. ds = (sr - sl);
  25. dt = (tr - tl);
  26. } // end else
  27. // draw span
  28. for (xi=xstart; xi < xend; xi++)
  29. {
  30. // write textel assume 5.6.5
  31.             // write thru z buffer always
  32.     // get textel first
  33.   textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
  34.             // extract rgb components
  35.             r_textel  = ((textel >> 11)       ); 
  36.             g_textel  = ((textel >> 5)  & 0x3f); 
  37.             b_textel =   (textel        & 0x1f);
  38.             // modulate textel with gouraud shading
  39.             r_textel*=ui; 
  40.             g_textel*=vi;
  41.             b_textel*=wi;
  42.             // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  43.             // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  44.             // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  45.             // and they all cancel out for the most part, but we will need logical anding, we will do
  46.             // it later when we optimize more...
  47.             screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) + 
  48.                              ((g_textel >> (FIXP16_SHIFT+8)) << 5) + 
  49.                              ((r_textel >> (FIXP16_SHIFT+8)) << 11));
  50.             // update z-buffer
  51.             z_ptr[xi] = zi;   
  52. // interpolate u,v
  53. ui+=du;
  54. vi+=dv;
  55. wi+=dw;
  56. zi+=dz;
  57. si+=ds;
  58. ti+=dt;
  59. } // end for xi
  60. // interpolate u,v,w,x along right and left edge
  61. xl+=dxdyl;
  62. ul+=dudyl;
  63. vl+=dvdyl;
  64. wl+=dwdyl;
  65. zl+=dzdyl;
  66. sl+=dsdyl;
  67. tl+=dtdyl;
  68. xr+=dxdyr;
  69. ur+=dudyr;
  70. vr+=dvdyr;
  71. wr+=dwdyr;
  72. zr+=dzdyr;
  73. sr+=dsdyr;
  74. tr+=dtdyr;
  75. // advance screen ptr
  76. screen_ptr+=mem_pitch;
  77.         // advance zbuffer ptr
  78.         z_ptr+=zpitch;
  79. } // end for y
  80. } // end if non-clipped
  81. } // end if
  82. else
  83. if (tri_type==TRI_TYPE_GENERAL)
  84. {
  85. // first test for bottom clip, always
  86. if ((yend = y2) > max_clip_y)
  87. yend = max_clip_y;
  88. // pre-test y clipping status
  89. if (y1 < min_clip_y)
  90. {
  91. // compute all deltas
  92. // LHS
  93. dyl = (y2 - y1);
  94. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  95. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  96. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  97. dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;  
  98. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  99. dsdyl = ((ts2 - ts1) << FIXP16_SHIFT)/dyl;    
  100. dtdyl = ((tt2 - tt1) << FIXP16_SHIFT)/dyl;  
  101. // RHS
  102. dyr = (y2 - y0);
  103. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  104. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  105. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  106. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;   
  107. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  108. dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dyr;   
  109. dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dyr;  
  110. // compute overclip
  111. dyr = (min_clip_y - y0);
  112. dyl = (min_clip_y - y1);
  113. // computer new LHS starting values
  114. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  115. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  116. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  117. wl = dwdyl*dyl + (tw1 << FIXP16_SHIFT);
  118. zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  119. sl = dsdyl*dyl + (ts1 << FIXP16_SHIFT);
  120. tl = dtdyl*dyl + (tt1 << FIXP16_SHIFT);
  121. // compute new RHS starting values
  122. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  123. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  124. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  125. wr = dwdyr*dyr + (tw0 << FIXP16_SHIFT);
  126. zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  127. sr = dsdyr*dyr + (ts0 << FIXP16_SHIFT);
  128. tr = dtdyr*dyr + (tt0 << FIXP16_SHIFT);
  129. // compute new starting y
  130. ystart = min_clip_y;
  131. // test if we need swap to keep rendering left to right
  132. if (dxdyr > dxdyl)
  133. {
  134. SWAP(dxdyl,dxdyr,temp);
  135. SWAP(dudyl,dudyr,temp);
  136. SWAP(dvdyl,dvdyr,temp);
  137. SWAP(dwdyl,dwdyr,temp);
  138. SWAP(dzdyl,dzdyr,temp);
  139. SWAP(dsdyl,dsdyr,temp);
  140. SWAP(dtdyl,dtdyr,temp);
  141.           SWAP(xl,xr,temp);
  142. SWAP(ul,ur,temp);
  143. SWAP(vl,vr,temp);
  144. SWAP(wl,wr,temp);
  145. SWAP(zl,zr,temp);
  146. SWAP(sl,sr,temp);
  147. SWAP(tl,tr,temp);
  148. SWAP(x1,x2,temp);
  149. SWAP(y1,y2,temp);
  150. SWAP(tu1,tu2,temp);
  151. SWAP(tv1,tv2,temp);
  152. SWAP(tw1,tw2,temp);
  153. SWAP(tz1,tz2,temp);
  154. SWAP(ts1,ts2,temp);
  155. SWAP(tt1,tt2,temp);
  156. // set interpolation restart
  157. irestart = INTERP_RHS;
  158. } // end if
  159. } // end if
  160. else
  161. if (y0 < min_clip_y)
  162. {
  163. // compute all deltas
  164. // LHS
  165. dyl = (y1 - y0);
  166. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  167. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  168. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  169. dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl; 
  170. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl; 
  171. dsdyl = ((ts1 - ts0) << FIXP16_SHIFT)/dyl;    
  172. dtdyl = ((tt1 - tt0) << FIXP16_SHIFT)/dyl; 
  173. // RHS
  174. dyr = (y2 - y0);
  175. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  176. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  177. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  178. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;   
  179. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  180. dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dyr;   
  181. dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dyr;   
  182. // compute overclip
  183. dy = (min_clip_y - y0);
  184. // computer new LHS starting values
  185. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  186. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  187. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  188. wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
  189. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  190. sl = dsdyl*dy + (ts0 << FIXP16_SHIFT);
  191. tl = dtdyl*dy + (tt0 << FIXP16_SHIFT);
  192. // compute new RHS starting values
  193. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  194. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  195. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  196. wr = dwdyr*dy + (tw0 << FIXP16_SHIFT);
  197. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  198. sr = dsdyr*dy + (ts0 << FIXP16_SHIFT);
  199. tr = dtdyr*dy + (tt0 << FIXP16_SHIFT);
  200. // compute new starting y
  201. ystart = min_clip_y;
  202. // test if we need swap to keep rendering left to right
  203. if (dxdyr < dxdyl)
  204. {
  205. SWAP(dxdyl,dxdyr,temp);
  206. SWAP(dudyl,dudyr,temp);
  207. SWAP(dvdyl,dvdyr,temp);
  208. SWAP(dwdyl,dwdyr,temp);
  209. SWAP(dzdyl,dzdyr,temp);
  210. SWAP(dsdyl,dsdyr,temp);
  211. SWAP(dtdyl,dtdyr,temp);
  212. SWAP(xl,xr,temp);
  213. SWAP(ul,ur,temp);
  214. SWAP(vl,vr,temp);
  215. SWAP(wl,wr,temp);
  216. SWAP(zl,zr,temp);
  217. SWAP(sl,sr,temp);
  218. SWAP(tl,tr,temp);
  219. SWAP(x1,x2,temp);
  220. SWAP(y1,y2,temp);
  221. SWAP(tu1,tu2,temp);
  222. SWAP(tv1,tv2,temp);
  223. SWAP(tw1,tw2,temp);
  224. SWAP(tz1,tz2,temp);
  225. SWAP(ts1,ts2,temp);
  226. SWAP(tt1,tt2,temp);
  227. // set interpolation restart
  228. irestart = INTERP_RHS;
  229. } // end if
  230. } // end if
  231. else
  232. {
  233. // no initial y clipping
  234. // compute all deltas
  235. // LHS
  236. dyl = (y1 - y0);
  237. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  238. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  239. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  240. dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl;   
  241. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;  
  242. dsdyl = ((ts1 - ts0) << FIXP16_SHIFT)/dyl;    
  243. dtdyl = ((tt1 - tt0) << FIXP16_SHIFT)/dyl;   
  244. // RHS
  245. dyr = (y2 - y0);
  246. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  247. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  248. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  249. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;
  250. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
  251. dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dyr;   
  252. dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dyr;
  253. // no clipping y
  254. // set starting values
  255. xl = (x0 << FIXP16_SHIFT);
  256. xr = (x0 << FIXP16_SHIFT);
  257. ul = (tu0 << FIXP16_SHIFT);
  258. vl = (tv0 << FIXP16_SHIFT);
  259. wl = (tw0 << FIXP16_SHIFT);
  260. zl = (tz0 << FIXP16_SHIFT);
  261. sl = (ts0 << FIXP16_SHIFT);
  262. tl = (tt0 << FIXP16_SHIFT);
  263. ur = (tu0 << FIXP16_SHIFT);
  264. vr = (tv0 << FIXP16_SHIFT);
  265. wr = (tw0 << FIXP16_SHIFT);
  266. zr = (tz0 << FIXP16_SHIFT);
  267. sr = (ts0 << FIXP16_SHIFT);
  268. tr = (tt0 << FIXP16_SHIFT);
  269. // set starting y
  270. ystart = y0;
  271. // test if we need swap to keep rendering left to right
  272. if (dxdyr < dxdyl)
  273. {
  274. SWAP(dxdyl,dxdyr,temp);
  275. SWAP(dudyl,dudyr,temp);
  276. SWAP(dvdyl,dvdyr,temp);
  277. SWAP(dwdyl,dwdyr,temp);
  278. SWAP(dzdyl,dzdyr,temp);
  279. SWAP(dsdyl,dsdyr,temp);
  280. SWAP(dtdyl,dtdyr,temp);
  281. SWAP(xl,xr,temp);
  282. SWAP(ul,ur,temp);
  283. SWAP(vl,vr,temp);
  284. SWAP(wl,wr,temp);
  285. SWAP(zl,zr,temp);
  286. SWAP(sl,sr,temp);
  287. SWAP(tl,tr,temp);
  288. SWAP(x1,x2,temp);
  289. SWAP(y1,y2,temp);
  290. SWAP(tu1,tu2,temp);
  291. SWAP(tv1,tv2,temp);
  292. SWAP(tw1,tw2,temp);
  293. SWAP(tz1,tz2,temp);
  294. SWAP(ts1,ts2,temp);
  295. SWAP(tt1,tt2,temp);
  296. // set interpolation restart
  297. irestart = INTERP_RHS;
  298. } // end if
  299. } // end else
  300.     // test for horizontal clipping
  301. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  302. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  303. (x2 < min_clip_x) || (x2 > max_clip_x))
  304. {
  305.     // clip version
  306. // x clipping
  307. // point screen ptr to starting line
  308. screen_ptr = dest_buffer + (ystart * mem_pitch);
  309.     // point zbuffer to starting line
  310.     z_ptr = zbuffer + (ystart * zpitch);
  311. for (yi = ystart; yi < yend; yi++)
  312. {
  313. // compute span endpoints
  314. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  315. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  316. // compute starting points for u,v,w interpolants
  317. ui = ul + FIXP16_ROUND_UP;
  318. vi = vl + FIXP16_ROUND_UP;
  319. wi = wl + FIXP16_ROUND_UP;
  320. zi = zl + FIXP16_ROUND_UP;
  321. si = sl + FIXP16_ROUND_UP;
  322. ti = tl + FIXP16_ROUND_UP;
  323. // compute u,v interpolants
  324. if ((dx = (xend - xstart))>0)
  325. {
  326. du = (ur - ul)/dx;
  327. dv = (vr - vl)/dx;
  328. dw = (wr - wl)/dx;
  329. dz = (zr - zl)/dx;
  330. ds = (sr - sl)/dx;
  331. dt = (tr - tl)/dx;
  332. } // end if
  333. else
  334. {
  335. du = (ur - ul);
  336. dv = (vr - vl);
  337. dw = (wr - wl);
  338. dz = (zr - zl);
  339. ds = (sr - sl);
  340. dt = (tr - tl);
  341. } // end else
  342. ///////////////////////////////////////////////////////////////////////
  343. // test for x clipping, LHS
  344. if (xstart < min_clip_x)
  345. {
  346. // compute x overlap
  347. dx = min_clip_x - xstart;
  348. // slide interpolants over
  349. ui+=dx*du;
  350. vi+=dx*dv;
  351. wi+=dx*dw;
  352. zi+=dx*dz;
  353. si+=dx*ds;
  354. ti+=dx*dt;
  355. // set x to left clip edge
  356. xstart = min_clip_x;
  357. } // end if
  358. // test for x clipping RHS
  359. if (xend > max_clip_x)
  360. xend = max_clip_x;
  361. ///////////////////////////////////////////////////////////////////////
  362. // draw span
  363. for (xi=xstart; xi < xend; xi++)
  364. {
  365. // write textel assume 5.6.5
  366.             // write thru z buffer always
  367.     // get textel first
  368.   textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
  369.             // extract rgb components
  370.             r_textel  = ((textel >> 11)       ); 
  371.             g_textel  = ((textel >> 5)  & 0x3f); 
  372.             b_textel =   (textel        & 0x1f);
  373.             // modulate textel with gouraud shading
  374.             r_textel*=ui; 
  375.             g_textel*=vi;
  376.             b_textel*=wi;
  377.             // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  378.             // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  379.             // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  380.             // and they all cancel out for the most part, but we will need logical anding, we will do
  381.             // it later when we optimize more...
  382.             screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) + 
  383.                              ((g_textel >> (FIXP16_SHIFT+8)) << 5) + 
  384.                              ((r_textel >> (FIXP16_SHIFT+8)) << 11));
  385.             // update z-buffer
  386.             z_ptr[xi] = zi;   
  387. // interpolate u,v
  388. ui+=du;
  389. vi+=dv;
  390. wi+=dw;
  391. zi+=dz;
  392. si+=ds;
  393. ti+=dt;
  394. } // end for xi
  395. // interpolate u,v,w,x along right and left edge
  396. xl+=dxdyl;
  397.         ul+=dudyl;
  398. vl+=dvdyl;
  399. wl+=dwdyl;
  400. zl+=dzdyl;
  401. sl+=dsdyl;
  402. tl+=dtdyl;
  403. xr+=dxdyr;
  404.       ur+=dudyr;
  405. vr+=dvdyr;
  406. wr+=dwdyr;
  407. zr+=dzdyr;
  408. sr+=dsdyr;
  409. tr+=dtdyr;
  410. // advance screen ptr
  411. screen_ptr+=mem_pitch;
  412.         // advance zbuffer ptr
  413.         z_ptr+=zpitch;
  414. // test for yi hitting second region, if so change interpolant
  415. if (yi==yrestart)
  416. {
  417.     // test interpolation side change flag
  418. if (irestart == INTERP_LHS)
  419. {
  420. // LHS
  421. dyl = (y2 - y1);
  422. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  423. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  424. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  425. dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;  
  426. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  427. dsdyl = ((ts2 - ts1) << FIXP16_SHIFT)/dyl;   
  428. dtdyl = ((tt2 - tt1) << FIXP16_SHIFT)/dyl;  
  429. // set starting values
  430. xl = (x1  << FIXP16_SHIFT);
  431. ul = (tu1 << FIXP16_SHIFT);
  432. vl = (tv1 << FIXP16_SHIFT);
  433. wl = (tw1 << FIXP16_SHIFT);
  434. zl = (tz1 << FIXP16_SHIFT);
  435. sl = (ts1 << FIXP16_SHIFT);
  436. tl = (tt1 << FIXP16_SHIFT);
  437. // interpolate down on LHS to even up
  438. xl+=dxdyl;
  439. ul+=dudyl;
  440. vl+=dvdyl;
  441. wl+=dwdyl;
  442. zl+=dzdyl;
  443. sl+=dsdyl;
  444. tl+=dtdyl;
  445. } // end if
  446. else
  447. {
  448. // RHS
  449. dyr = (y1 - y2);
  450. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  451. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  452. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  453. dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;   
  454. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  455. dsdyr = ((ts1 - ts2) << FIXP16_SHIFT)/dyr;   
  456. dtdyr = ((tt1 - tt2) << FIXP16_SHIFT)/dyr;  
  457. // set starting values
  458. xr = (x2  << FIXP16_SHIFT);
  459. ur = (tu2 << FIXP16_SHIFT);
  460. vr = (tv2 << FIXP16_SHIFT);
  461. wr = (tw2 << FIXP16_SHIFT);
  462. zr = (tz2 << FIXP16_SHIFT);
  463. sr = (ts2 << FIXP16_SHIFT);
  464. tr = (tt2 << FIXP16_SHIFT);
  465. // interpolate down on RHS to even up
  466. xr+=dxdyr;
  467. ur+=dudyr;
  468. vr+=dvdyr;
  469. wr+=dwdyr;
  470. zr+=dzdyr;
  471. sr+=dsdyr;
  472. tr+=dtdyr;
  473. } // end else
  474. } // end if
  475. } // end for y
  476. } // end if
  477. else
  478. {
  479. // no x clipping
  480. // point screen ptr to starting line
  481. screen_ptr = dest_buffer + (ystart * mem_pitch);
  482.     // point zbuffer to starting line
  483.     z_ptr = zbuffer + (ystart * zpitch);
  484. for (yi = ystart; yi < yend; yi++)
  485. {
  486. // compute span endpoints
  487. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  488. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  489. // compute starting points for u,v,w interpolants
  490. ui = ul + FIXP16_ROUND_UP;
  491. vi = vl + FIXP16_ROUND_UP;
  492. wi = wl + FIXP16_ROUND_UP;
  493. zi = zl + FIXP16_ROUND_UP;
  494. si = sl + FIXP16_ROUND_UP;
  495. ti = tl + FIXP16_ROUND_UP;
  496. // compute u,v interpolants
  497. if ((dx = (xend - xstart))>0)
  498. {
  499. du = (ur - ul)/dx;
  500. dv = (vr - vl)/dx;
  501. dw = (wr - wl)/dx;
  502. dz = (zr - zl)/dx;
  503. ds = (sr - sl)/dx;
  504. dt = (tr - tl)/dx;
  505. } // end if
  506. else
  507. {
  508. du = (ur - ul);
  509. dv = (vr - vl);
  510. dw = (wr - wl);
  511. dz = (zr - zl);
  512. ds = (sr - sl);
  513. dt = (tr - tl);
  514. } // end else
  515. // draw span
  516. for (xi=xstart; xi < xend; xi++)
  517. {
  518. // write textel assume 5.6.5
  519.             // write thru z buffer always
  520.     // get textel first
  521.   textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
  522.             // extract rgb components
  523.             r_textel  = ((textel >> 11)       ); 
  524.             g_textel  = ((textel >> 5)  & 0x3f); 
  525.             b_textel =   (textel        & 0x1f);
  526.             // modulate textel with gouraud shading
  527.             r_textel*=ui; 
  528.             g_textel*=vi;
  529.             b_textel*=wi;
  530.             // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  531.             // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  532.             // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  533.             // and they all cancel out for the most part, but we will need logical anding, we will do
  534.             // it later when we optimize more...
  535.             screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) + 
  536.                              ((g_textel >> (FIXP16_SHIFT+8)) << 5) + 
  537.                              ((r_textel >> (FIXP16_SHIFT+8)) << 11));
  538.             // update z-buffer
  539.             z_ptr[xi] = zi;   
  540. // interpolate u,v
  541. ui+=du;
  542. vi+=dv;
  543. wi+=dw;
  544. zi+=dz;
  545. si+=ds;
  546. ti+=dt;
  547. } // end for xi
  548. // interpolate u,v,w,x along right and left edge
  549. xl+=dxdyl;
  550. ul+=dudyl;
  551. vl+=dvdyl;
  552. wl+=dwdyl;
  553. zl+=dzdyl;
  554. sl+=dsdyl;
  555. tl+=dtdyl;
  556. xr+=dxdyr;
  557. ur+=dudyr;
  558. vr+=dvdyr;
  559. wr+=dwdyr;
  560. zr+=dzdyr;
  561. sr+=dsdyr;
  562. tr+=dtdyr;
  563. // advance screen ptr
  564. screen_ptr+=mem_pitch;
  565.         // advance zbuffer ptr
  566.         z_ptr+=zpitch;
  567. // test for yi hitting second region, if so change interpolant
  568. if (yi==yrestart)
  569. {
  570. // test interpolation side change flag
  571. if (irestart == INTERP_LHS)
  572. {
  573. // LHS
  574. dyl = (y2 - y1);
  575. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  576. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  577. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  578. dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;   
  579. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  580. dsdyl = ((ts2 - ts1) << FIXP16_SHIFT)/dyl;   
  581. dtdyl = ((tt2 - tt1) << FIXP16_SHIFT)/dyl;   
  582. // set starting values
  583. xl = (x1  << FIXP16_SHIFT);
  584. ul = (tu1 << FIXP16_SHIFT);
  585. vl = (tv1 << FIXP16_SHIFT);
  586. wl = (tw1 << FIXP16_SHIFT);
  587. zl = (tz1 << FIXP16_SHIFT);
  588. sl = (ts1 << FIXP16_SHIFT);
  589. tl = (tt1 << FIXP16_SHIFT);
  590. // interpolate down on LHS to even up
  591. xl+=dxdyl;
  592. ul+=dudyl;
  593. vl+=dvdyl;
  594. wl+=dwdyl;
  595. zl+=dzdyl;
  596. sl+=dsdyl;
  597. tl+=dtdyl;
  598. } // end if
  599. else
  600. {
  601. // RHS
  602. dyr = (y1 - y2);
  603. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  604. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  605. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  606. dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;   
  607. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  608. dsdyr = ((ts1 - ts2) << FIXP16_SHIFT)/dyr;   
  609. dtdyr = ((tt1 - tt2) << FIXP16_SHIFT)/dyr;   
  610. // set starting values
  611. xr = (x2  << FIXP16_SHIFT);
  612. ur = (tu2 << FIXP16_SHIFT);
  613. vr = (tv2 << FIXP16_SHIFT);
  614. wr = (tw2 << FIXP16_SHIFT);
  615. zr = (tz2 << FIXP16_SHIFT);
  616. sr = (ts2 << FIXP16_SHIFT);
  617. tr = (tt2 << FIXP16_SHIFT);
  618. // interpolate down on RHS to even up
  619. xr+=dxdyr;
  620. ur+=dudyr;
  621. vr+=dvdyr;
  622. wr+=dwdyr;
  623. zr+=dzdyr;
  624. sr+=dsdyr;
  625. tr+=dtdyr;
  626. } // end else
  627. } // end if
  628. } // end for y
  629.    } // end else
  630. } // end if
  631. } // end Draw_Textured_TriangleGSWTZB_16
  632. ///////////////////////////////////////////////////////////////////////////////
  633. /////////////////////////////////////////////////////////////////////////////
  634. void Draw_Triangle_2DWTZB_16(POLYF4DV2_PTR face,   // ptr to face
  635.                            UCHAR *_dest_buffer,   // pointer to video buffer
  636.                            int mem_pitch,         // bytes per line, 320, 640 etc.
  637.                            UCHAR *_zbuffer,       // pointer to z-buffer
  638.                            int zpitch)            // bytes per line of zbuffer
  639. {
  640. // this function draws a flat shaded polygon with zbuffering
  641. int v0=0,
  642.     v1=1,
  643. v2=2,
  644. temp=0,
  645. tri_type = TRI_TYPE_NONE,
  646. irestart = INTERP_LHS;
  647. int dx,dy,dyl,dyr,      // general deltas
  648.     z,
  649.     dz,
  650.     xi,yi,              // the current interpolated x,y
  651. zi,                 // the current interpolated z
  652. index_x,index_y,    // looping vars
  653. x,y,                // hold general x,y
  654. xstart,
  655. xend,
  656. ystart,
  657. yrestart,
  658. yend,
  659. xl,                 
  660. dxdyl,              
  661. xr,
  662. dxdyr,             
  663.     dzdyl,   
  664. zl,
  665. dzdyr,
  666. zr;
  667. int x0,y0,tz0,    // cached vertices
  668. x1,y1,tz1,
  669. x2,y2,tz2;
  670. USHORT *screen_ptr  = NULL,
  671.    *screen_line = NULL,
  672.    *textmap     = NULL,
  673.        *dest_buffer = (USHORT *)_dest_buffer;
  674. UINT  *z_ptr = NULL,
  675.       *zbuffer = (UINT *)_zbuffer;
  676. USHORT color;    // polygon color
  677. #ifdef DEBUG_ON
  678. // track rendering stats
  679.     debug_polys_rendered_per_frame++;
  680. #endif
  681. // adjust memory pitch to words, divide by 2
  682. mem_pitch >>=1;
  683. // adjust zbuffer pitch for 32 bit alignment
  684. zpitch >>= 2;
  685. // apply fill convention to coordinates
  686. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  687. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  688. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  689. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  690. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  691. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  692. // first trivial clipping rejection tests 
  693. if (((face->tvlist[0].y < min_clip_y)  && 
  694.  (face->tvlist[1].y < min_clip_y)  &&
  695.  (face->tvlist[2].y < min_clip_y)) ||
  696. ((face->tvlist[0].y > max_clip_y)  && 
  697.  (face->tvlist[1].y > max_clip_y)  &&
  698.  (face->tvlist[2].y > max_clip_y)) ||
  699. ((face->tvlist[0].x < min_clip_x)  && 
  700.  (face->tvlist[1].x < min_clip_x)  &&
  701.  (face->tvlist[2].x < min_clip_x)) ||
  702. ((face->tvlist[0].x > max_clip_x)  && 
  703.  (face->tvlist[1].x > max_clip_x)  &&
  704.  (face->tvlist[2].x > max_clip_x)))
  705.    return;
  706. // sort vertices
  707. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  708. {SWAP(v0,v1,temp);} 
  709. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  710. {SWAP(v0,v2,temp);}
  711. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  712. {SWAP(v1,v2,temp);}
  713. // now test for trivial flat sided cases
  714. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  715. // set triangle type
  716. tri_type = TRI_TYPE_FLAT_TOP;
  717. // sort vertices left to right
  718. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  719. {SWAP(v0,v1,temp);}
  720. } // end if
  721. else
  722. // now test for trivial flat sided cases
  723. if (FCMP(face->tvlist[v1].y, face->tvlist[v2].y) )
  724. // set triangle type
  725. tri_type = TRI_TYPE_FLAT_BOTTOM;
  726. // sort vertices left to right
  727. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  728. {SWAP(v1,v2,temp);}
  729. } // end if
  730. else
  731. {
  732. // must be a general triangle
  733. tri_type = TRI_TYPE_GENERAL;
  734. } // end else
  735. // extract vertices for processing, now that we have order
  736. x0  = (int)(face->tvlist[v0].x+0.0);
  737. y0  = (int)(face->tvlist[v0].y+0.0);
  738. tz0 = (int)(face->tvlist[v0].z+0.5);
  739. x1  = (int)(face->tvlist[v1].x+0.0);
  740. y1  = (int)(face->tvlist[v1].y+0.0);
  741. tz1 = (int)(face->tvlist[v1].z+0.5);
  742. x2  = (int)(face->tvlist[v2].x+0.0);
  743. y2  = (int)(face->tvlist[v2].y+0.0);
  744. tz2 = (int)(face->tvlist[v2].z+0.5);
  745. // degenerate triangle
  746. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  747.    return;
  748. // extract constant color
  749. color = face->lit_color[0];
  750. // set interpolation restart value
  751. yrestart = y1;
  752. // what kind of triangle
  753. if (tri_type & TRI_TYPE_FLAT_MASK)
  754. {
  755. if (tri_type == TRI_TYPE_FLAT_TOP)
  756. {
  757. // compute all deltas
  758. dy = (y2 - y0);
  759. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  760. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy; 
  761. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  762. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;   
  763. // test for y clipping
  764. if (y0 < min_clip_y)
  765. {
  766. // compute overclip
  767. dy = (min_clip_y - y0);
  768. // computer new LHS starting values
  769. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  770. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  771. // compute new RHS starting values
  772. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  773. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  774. // compute new starting y
  775. ystart = min_clip_y;
  776. } // end if
  777. else
  778. {
  779. // no clipping
  780. // set starting values
  781. xl = (x0 << FIXP16_SHIFT);
  782. xr = (x1 << FIXP16_SHIFT);
  783. zl = (tz0 << FIXP16_SHIFT);
  784. zr = (tz1 << FIXP16_SHIFT);
  785. // set starting y
  786. ystart = y0;
  787. } // end else
  788. } // end if flat top
  789. else
  790. {
  791. // must be flat bottom
  792. // compute all deltas
  793. dy = (y1 - y0);
  794. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  795. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy; 
  796. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  797. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  798. // test for y clipping
  799. if (y0 < min_clip_y)
  800. {
  801. // compute overclip
  802. dy = (min_clip_y - y0);
  803. // computer new LHS starting values
  804. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  805. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  806. // compute new RHS starting values
  807. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  808. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  809. // compute new starting y
  810. ystart = min_clip_y;
  811. } // end if
  812. else
  813. {
  814. // no clipping
  815. // set starting values
  816. xl = (x0 << FIXP16_SHIFT);
  817. xr = (x0 << FIXP16_SHIFT);
  818. zl = (tz0 << FIXP16_SHIFT);
  819. zr = (tz0 << FIXP16_SHIFT);
  820. // set starting y
  821. ystart = y0;
  822. } // end else
  823. } // end else flat bottom
  824. // test for bottom clip, always
  825. if ((yend = y2) > max_clip_y)
  826. yend = max_clip_y;
  827.     // test for horizontal clipping
  828. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  829. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  830. (x2 < min_clip_x) || (x2 > max_clip_x))
  831. {
  832.     // clip version
  833. // point screen ptr to starting line
  834. screen_ptr = dest_buffer + (ystart * mem_pitch);
  835.     // point zbuffer to starting line
  836.     z_ptr = zbuffer + (ystart * zpitch);
  837. for (yi = ystart; yi<=yend; yi++)
  838. {
  839. // compute span endpoints
  840. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  841. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  842. // compute starting points for u,v,w interpolants
  843. zi = zl + FIXP16_ROUND_UP;
  844. // compute u,v interpolants
  845. if ((dx = (xend - xstart))>0)
  846. {
  847. dz = (zr - zl)/dx;
  848. } // end if
  849. else
  850. {
  851. dz = (zr - zl);
  852. } // end else
  853. ///////////////////////////////////////////////////////////////////////
  854. // test for x clipping, LHS
  855. if (xstart < min_clip_x)
  856. {
  857. // compute x overlap
  858. dx = min_clip_x - xstart;
  859. // slide interpolants over
  860. zi+=dx*dz;
  861. // reset vars
  862. xstart = min_clip_x;
  863. } // end if
  864. // test for x clipping RHS
  865. if (xend > max_clip_x)
  866. xend = max_clip_x;
  867. ///////////////////////////////////////////////////////////////////////
  868. // draw span
  869. for (xi=xstart; xi<=xend; xi++)
  870. {
  871.             // write thru z buffer 
  872.             // write textel assume 5.6.5
  873.      screen_ptr[xi] = color;
  874.             // update z-buffer
  875.             z_ptr[xi] = zi;           
  876.               
  877. // interpolate u,v,w,z
  878. zi+=dz;
  879. } // end for xi
  880. // interpolate z,x along right and left edge
  881. xl+=dxdyl;
  882. zl+=dzdyl;
  883. xr+=dxdyr;
  884. zr+=dzdyr;
  885.  
  886. // advance screen ptr
  887. screen_ptr+=mem_pitch;
  888.         // advance z-buffer ptr
  889.         z_ptr+=zpitch;
  890. } // end for y
  891. } // end if clip
  892. else
  893. {
  894. // non-clip version
  895. // point screen ptr to starting line
  896. screen_ptr = dest_buffer + (ystart * mem_pitch);
  897.     // point zbuffer to starting line
  898.     z_ptr = zbuffer + (ystart * zpitch);
  899. for (yi = ystart; yi<=yend; yi++)
  900. {
  901. // compute span endpoints
  902. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  903. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  904. // compute starting points for u,v,w interpolants
  905. zi = zl + FIXP16_ROUND_UP;
  906. // compute u,v interpolants
  907. if ((dx = (xend - xstart))>0)
  908. {
  909. dz = (zr - zl)/dx;
  910. } // end if
  911. else
  912. {
  913. dz = (zr - zl);
  914. } // end else
  915. // draw span
  916. for (xi=xstart; xi<=xend; xi++)
  917. {
  918.             // write thru z buffer 
  919.             // write textel assume 5.6.5
  920.      screen_ptr[xi] = color;
  921.             // update z-buffer
  922.             z_ptr[xi] = zi;     
  923. // interpolate z
  924. zi+=dz;
  925. } // end for xi
  926. // interpolate x,z along right and left edge
  927. xl+=dxdyl;
  928. zl+=dzdyl;
  929. xr+=dxdyr;
  930. zr+=dzdyr;
  931. // advance screen ptr
  932. screen_ptr+=mem_pitch;
  933.         // advance z-buffer ptr
  934.         z_ptr+=zpitch;
  935. } // end for y
  936. } // end if non-clipped
  937. } // end if
  938. else
  939. if (tri_type==TRI_TYPE_GENERAL)
  940. {
  941. // first test for bottom clip, always
  942. if ((yend = y2) > max_clip_y)
  943. yend = max_clip_y;
  944. // pre-test y clipping status
  945. if (y1 < min_clip_y)
  946. {
  947. // compute all deltas
  948. // LHS
  949. dyl = (y2 - y1);
  950. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  951. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl; 
  952. // RHS
  953. dyr = (y2 - y0);
  954. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  955. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;  
  956. // compute overclip
  957. dyr = (min_clip_y - y0);
  958. dyl = (min_clip_y - y1);
  959. // computer new LHS starting values
  960. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  961. zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  962. // compute new RHS starting values
  963. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  964. zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  965. // compute new starting y
  966. ystart = min_clip_y;
  967. // test if we need swap to keep rendering left to right
  968. if (dxdyr > dxdyl)
  969. {
  970. SWAP(dxdyl,dxdyr,temp);
  971. SWAP(dzdyl,dzdyr,temp);
  972. SWAP(xl,xr,temp);
  973. SWAP(zl,zr,temp);
  974. SWAP(x1,x2,temp);
  975. SWAP(y1,y2,temp);
  976. SWAP(tz1,tz2,temp);
  977. // set interpolation restart
  978. irestart = INTERP_RHS;
  979. } // end if
  980. } // end if
  981. else
  982. if (y0 < min_clip_y)
  983. {
  984. // compute all deltas
  985. // LHS
  986. dyl = (y1 - y0);
  987. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  988. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl; 
  989. // RHS
  990. dyr = (y2 - y0);
  991. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  992. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;  
  993. // compute overclip
  994. dy = (min_clip_y - y0);
  995. // computer new LHS starting values
  996. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  997. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  998. // compute new RHS starting values
  999. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1000. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  1001. // compute new starting y
  1002. ystart = min_clip_y;
  1003. // test if we need swap to keep rendering left to right
  1004. if (dxdyr < dxdyl)
  1005. {
  1006. SWAP(dxdyl,dxdyr,temp);
  1007. SWAP(dzdyl,dzdyr,temp);
  1008. SWAP(xl,xr,temp);
  1009. SWAP(zl,zr,temp);
  1010. SWAP(x1,x2,temp);
  1011. SWAP(y1,y2,temp);
  1012. SWAP(tz1,tz2,temp);
  1013. // set interpolation restart
  1014. irestart = INTERP_RHS;
  1015. } // end if
  1016. } // end if
  1017. else
  1018. {
  1019. // no initial y clipping
  1020. // compute all deltas
  1021. // LHS
  1022. dyl = (y1 - y0);
  1023. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1024. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl; 
  1025. // RHS
  1026. dyr = (y2 - y0);
  1027. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  1028. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
  1029. // no clipping y
  1030. // set starting values
  1031. xl = (x0 << FIXP16_SHIFT);
  1032. xr = (x0 << FIXP16_SHIFT);
  1033. zl = (tz0 << FIXP16_SHIFT);
  1034. zr = (tz0 << FIXP16_SHIFT);
  1035. // set starting y
  1036. ystart = y0;
  1037. // test if we need swap to keep rendering left to right
  1038. if (dxdyr < dxdyl)
  1039. {
  1040. SWAP(dxdyl,dxdyr,temp);
  1041. SWAP(dzdyl,dzdyr,temp);
  1042. SWAP(xl,xr,temp);
  1043. SWAP(zl,zr,temp);
  1044. SWAP(x1,x2,temp);
  1045. SWAP(y1,y2,temp);
  1046. SWAP(tz1,tz2,temp);
  1047. // set interpolation restart
  1048. irestart = INTERP_RHS;
  1049. } // end if
  1050. } // end else
  1051.     // test for horizontal clipping
  1052. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1053. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1054. (x2 < min_clip_x) || (x2 > max_clip_x))
  1055. {
  1056.     // clip version
  1057. // x clipping
  1058. // point screen ptr to starting line
  1059. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1060.     // point zbuffer to starting line
  1061.     z_ptr = zbuffer + (ystart * zpitch);
  1062. for (yi = ystart; yi<=yend; yi++)
  1063. {
  1064. // compute span endpoints
  1065. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1066. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1067. // compute starting points for z interpolants
  1068. zi = zl + FIXP16_ROUND_UP;
  1069. // compute z interpolants
  1070. if ((dx = (xend - xstart))>0)
  1071. {
  1072. dz = (zr - zl)/dx;
  1073. } // end if
  1074. else
  1075. {
  1076. dz = (zr - zl);
  1077. } // end else
  1078. ///////////////////////////////////////////////////////////////////////
  1079. // test for x clipping, LHS
  1080. if (xstart < min_clip_x)
  1081. {
  1082. // compute x overlap
  1083. dx = min_clip_x - xstart;
  1084. // slide interpolants over
  1085. zi+=dx*dz;
  1086. // set x to left clip edge
  1087. xstart = min_clip_x;
  1088. } // end if
  1089. // test for x clipping RHS
  1090. if (xend > max_clip_x)
  1091. xend = max_clip_x;
  1092. ///////////////////////////////////////////////////////////////////////
  1093. // draw span
  1094. for (xi=xstart; xi<=xend; xi++)
  1095. {
  1096.             // write thru z buffer 
  1097.             // write textel assume 5.6.5
  1098.      screen_ptr[xi] = color;
  1099.             // update z-buffer
  1100.             z_ptr[xi] = zi;     
  1101. // interpolate z
  1102. zi+=dz;
  1103. } // end for xi
  1104. // interpolate z,x along right and left edge
  1105. xl+=dxdyl;
  1106. zl+=dzdyl;
  1107. xr+=dxdyr;
  1108. zr+=dzdyr;
  1109. // advance screen ptr
  1110. screen_ptr+=mem_pitch;
  1111.         // advance z-buffer ptr
  1112.         z_ptr+=zpitch;
  1113. // test for yi hitting second region, if so change interpolant
  1114. if (yi==yrestart)
  1115. {
  1116.     // test interpolation side change flag
  1117. if (irestart == INTERP_LHS)
  1118. {
  1119. // LHS
  1120. dyl = (y2 - y1);
  1121. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1122. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  1123. // set starting values
  1124. xl = (x1  << FIXP16_SHIFT);
  1125. zl = (tz1 << FIXP16_SHIFT);
  1126. // interpolate down on LHS to even up
  1127. xl+=dxdyl;
  1128. zl+=dzdyl;
  1129. } // end if
  1130. else
  1131. {
  1132. // RHS
  1133. dyr = (y1 - y2);
  1134. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1135. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  1136. // set starting values
  1137. xr = (x2  << FIXP16_SHIFT);
  1138. zr = (tz2 << FIXP16_SHIFT);
  1139. // interpolate down on RHS to even up
  1140. xr+=dxdyr;
  1141. zr+=dzdyr;
  1142. } // end else
  1143. } // end if
  1144. } // end for y
  1145. } // end if
  1146. else
  1147. {
  1148. // no x clipping
  1149. // point screen ptr to starting line
  1150. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1151.     // point zbuffer to starting line
  1152.     z_ptr = zbuffer + (ystart * zpitch);
  1153. for (yi = ystart; yi<=yend; yi++)
  1154. {
  1155. // compute span endpoints
  1156. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1157. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1158. // compute starting points for u,v,w,z interpolants
  1159. zi = zl + FIXP16_ROUND_UP;
  1160. // compute u,v interpolants
  1161. if ((dx = (xend - xstart))>0)
  1162. {
  1163. dz = (zr - zl)/dx;
  1164. } // end if
  1165. else
  1166. {
  1167. dz = (zr - zl);
  1168. } // end else
  1169. // draw span
  1170. for (xi=xstart; xi<=xend; xi++)
  1171. {
  1172.             // write thru z buffer 
  1173.             // write textel assume 5.6.5
  1174.      screen_ptr[xi] = color;
  1175.             // update z-buffer
  1176.             z_ptr[xi] = zi;     
  1177. // interpolate z
  1178. zi+=dz;
  1179. } // end for xi
  1180. // interpolate x,z along right and left edge
  1181. xl+=dxdyl;
  1182. zl+=dzdyl;
  1183. xr+=dxdyr;
  1184. zr+=dzdyr;
  1185. // advance screen ptr
  1186. screen_ptr+=mem_pitch;
  1187.         // advance z-buffer ptr
  1188.         z_ptr+=zpitch;
  1189. // test for yi hitting second region, if so change interpolant
  1190. if (yi==yrestart)
  1191. {
  1192. // test interpolation side change flag
  1193. if (irestart == INTERP_LHS)
  1194. {
  1195. // LHS
  1196. dyl = (y2 - y1);
  1197. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1198. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  1199. // set starting values
  1200. xl = (x1  << FIXP16_SHIFT);
  1201. zl = (tz1 << FIXP16_SHIFT);
  1202. // interpolate down on LHS to even up
  1203. xl+=dxdyl;
  1204. zl+=dzdyl;
  1205. } // end if
  1206. else
  1207. {
  1208. // RHS
  1209. dyr = (y1 - y2);
  1210. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1211. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  1212. // set starting values
  1213. xr = (x2  << FIXP16_SHIFT);
  1214. zr = (tz2 << FIXP16_SHIFT);
  1215. // interpolate down on RHS to even up
  1216. xr+=dxdyr;
  1217. zr+=dzdyr;
  1218. } // end else
  1219. } // end if
  1220. } // end for y
  1221.    } // end else
  1222. } // end if
  1223. } // end Draw_Triangle_2DWTZB_16
  1224. ///////////////////////////////////////////////////////////////////////////////
  1225. ///////////////////////////////////////////////////////////////////////////////
  1226. void Draw_Gouraud_TriangleWTZB2_16(POLYF4DV2_PTR face,   // ptr to face
  1227.                               UCHAR *_dest_buffer,   // pointer to video buffer
  1228.                               int mem_pitch,         // bytes per line, 320, 640 etc.
  1229.                               UCHAR *_zbuffer,       // pointer to z-buffer
  1230.                               int zpitch)            // bytes per line of zbuffer
  1231. {
  1232. // this function draws a gouraud shaded polygon, based on the affine texture mapper, instead
  1233. // of interpolating the texture coordinates, we simply interpolate the (R,G,B) values across
  1234. // the polygons, I simply needed at another interpolant, I have mapped u->red, v->green, w->blue
  1235. // also a new interpolant for z buffering has been added
  1236. int v0=0,
  1237.     v1=1,
  1238. v2=2,
  1239. temp=0,
  1240. tri_type = TRI_TYPE_NONE,
  1241. irestart = INTERP_LHS;
  1242. int dx,dy,dyl,dyr,      // general deltas
  1243.     u,v,w,z,
  1244.     du,dv,dw,dz,
  1245.     xi,yi,              // the current interpolated x,y
  1246. ui,vi,wi,zi,        // the current interpolated u,v,w,z
  1247. index_x,index_y,    // looping vars
  1248. x,y,                // hold general x,y
  1249. xstart,
  1250. xend,
  1251. ystart,
  1252. yrestart,
  1253. yend,
  1254. xl,                 
  1255. dxdyl,              
  1256. xr,
  1257. dxdyr,             
  1258.     dudyl,    
  1259. ul,
  1260. dvdyl,   
  1261. vl,
  1262. dwdyl,   
  1263. wl,
  1264. dzdyl,   
  1265. zl,
  1266. dudyr,
  1267. ur,
  1268. dvdyr,
  1269. vr,
  1270. dwdyr,
  1271. wr,
  1272. dzdyr,
  1273. zr;
  1274. int x0,y0,tu0,tv0,tw0,tz0,    // cached vertices
  1275. x1,y1,tu1,tv1,tw1,tz1,
  1276. x2,y2,tu2,tv2,tw2,tz2;
  1277. int r_base0, g_base0, b_base0,
  1278.     r_base1, g_base1, b_base1,
  1279.     r_base2, g_base2, b_base2;
  1280. USHORT *screen_ptr  = NULL,
  1281.    *screen_line = NULL,
  1282.    *textmap     = NULL,
  1283.        *dest_buffer = (USHORT *)_dest_buffer;
  1284. UINT  *z_ptr = NULL,
  1285.       *zbuffer = (UINT *)_zbuffer;
  1286. #ifdef DEBUG_ON
  1287. // track rendering stats
  1288.     debug_polys_rendered_per_frame++;
  1289. #endif
  1290. // adjust memory pitch to words, divide by 2
  1291. mem_pitch >>=1;
  1292. // adjust zbuffer pitch for 32 bit alignment
  1293. zpitch >>= 2;
  1294. // apply fill convention to coordinates
  1295. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  1296. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  1297. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  1298. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  1299. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  1300. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  1301. // first trivial clipping rejection tests 
  1302. if (((face->tvlist[0].y < min_clip_y)  && 
  1303.  (face->tvlist[1].y < min_clip_y)  &&
  1304.  (face->tvlist[2].y < min_clip_y)) ||
  1305. ((face->tvlist[0].y > max_clip_y)  && 
  1306.  (face->tvlist[1].y > max_clip_y)  &&
  1307.  (face->tvlist[2].y > max_clip_y)) ||
  1308. ((face->tvlist[0].x < min_clip_x)  && 
  1309.  (face->tvlist[1].x < min_clip_x)  &&
  1310.  (face->tvlist[2].x < min_clip_x)) ||
  1311. ((face->tvlist[0].x > max_clip_x)  && 
  1312.  (face->tvlist[1].x > max_clip_x)  &&
  1313.  (face->tvlist[2].x > max_clip_x)))
  1314.    return;
  1315. // sort vertices
  1316. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  1317. {SWAP(v0,v1,temp);} 
  1318. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  1319. {SWAP(v0,v2,temp);}
  1320. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  1321. {SWAP(v1,v2,temp);}
  1322. // now test for trivial flat sided cases
  1323. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y))
  1324. // set triangle type
  1325. tri_type = TRI_TYPE_FLAT_TOP;
  1326. // sort vertices left to right
  1327. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  1328. {SWAP(v0,v1,temp);}
  1329. } // end if
  1330. else
  1331. // now test for trivial flat sided cases
  1332. if (FCMP(face->tvlist[v1].y, face->tvlist[v2].y) )
  1333. // set triangle type
  1334. tri_type = TRI_TYPE_FLAT_BOTTOM;
  1335. // sort vertices left to right
  1336. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  1337. {SWAP(v1,v2,temp);}
  1338. } // end if
  1339. else
  1340. {
  1341. // must be a general triangle
  1342. tri_type = TRI_TYPE_GENERAL;
  1343. } // end else
  1344. // assume 5.6.5 format -- sorry!
  1345. // we can't afford a function call in the inner loops, so we must write 
  1346. // two hard coded versions, if we want support for both 5.6.5, and 5.5.5
  1347. _RGB565FROM16BIT(face->lit_color[v0], &r_base0, &g_base0, &b_base0);
  1348. _RGB565FROM16BIT(face->lit_color[v1], &r_base1, &g_base1, &b_base1);
  1349. _RGB565FROM16BIT(face->lit_color[v2], &r_base2, &g_base2, &b_base2);
  1350. // scale to 8 bit 
  1351. r_base0 <<= 3;
  1352. g_base0 <<= 2;
  1353. b_base0 <<= 3;
  1354. // scale to 8 bit 
  1355. r_base1 <<= 3;
  1356. g_base1 <<= 2;
  1357. b_base1 <<= 3;
  1358. // scale to 8 bit 
  1359. r_base2 <<= 3;
  1360. g_base2 <<= 2;
  1361. b_base2 <<= 3;
  1362. // extract vertices for processing, now that we have order
  1363. x0  = (int)(face->tvlist[v0].x+0.0);
  1364. y0  = (int)(face->tvlist[v0].y+0.0);
  1365. tz0 = (int)(face->tvlist[v0].z+0.5);
  1366. tu0 = r_base0;
  1367. tv0 = g_base0; 
  1368. tw0 = b_base0; 
  1369. x1  = (int)(face->tvlist[v1].x+0.0);
  1370. y1  = (int)(face->tvlist[v1].y+0.0);
  1371. tz1 = (int)(face->tvlist[v1].z+0.5);
  1372. tu1 = r_base1;
  1373. tv1 = g_base1; 
  1374. tw1 = b_base1; 
  1375. x2  = (int)(face->tvlist[v2].x+0.0);
  1376. y2  = (int)(face->tvlist[v2].y+0.0);
  1377. tz2 = (int)(face->tvlist[v2].z+0.5);
  1378. tu2 = r_base2; 
  1379. tv2 = g_base2; 
  1380. tw2 = b_base2; 
  1381. // degenerate triangle
  1382. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  1383.    return;
  1384. // set interpolation restart value
  1385. yrestart = y1;
  1386. // what kind of triangle
  1387. if (tri_type & TRI_TYPE_FLAT_MASK)
  1388. {
  1389. if (tri_type == TRI_TYPE_FLAT_TOP)
  1390. {
  1391. // compute all deltas
  1392. dy = (y2 - y0);
  1393. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1394. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1395. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  1396. dwdyl = ((tw2 - tw0) << FIXP16_SHIFT)/dy;  
  1397. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy; 
  1398. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  1399. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  1400. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  1401. dwdyr = ((tw2 - tw1) << FIXP16_SHIFT)/dy;   
  1402. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;   
  1403. // test for y clipping
  1404. if (y0 < min_clip_y)
  1405. {
  1406. // compute overclip
  1407. dy = (min_clip_y - y0);
  1408. // computer new LHS starting values
  1409. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1410. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1411. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1412. wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
  1413. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1414. // compute new RHS starting values
  1415. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  1416. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  1417. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  1418. wr = dwdyr*dy + (tw1 << FIXP16_SHIFT);
  1419. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  1420. // compute new starting y
  1421. ystart = min_clip_y;
  1422. } // end if
  1423. else
  1424. {
  1425. // no clipping
  1426. // set starting values
  1427. xl = (x0 << FIXP16_SHIFT);
  1428. xr = (x1 << FIXP16_SHIFT);
  1429. ul = (tu0 << FIXP16_SHIFT);
  1430. vl = (tv0 << FIXP16_SHIFT);
  1431. wl = (tw0 << FIXP16_SHIFT);
  1432. zl = (tz0 << FIXP16_SHIFT);
  1433. ur = (tu1 << FIXP16_SHIFT);
  1434. vr = (tv1 << FIXP16_SHIFT);
  1435. wr = (tw1 << FIXP16_SHIFT);
  1436. zr = (tz1 << FIXP16_SHIFT);
  1437. // set starting y
  1438. ystart = y0;
  1439. } // end else
  1440. } // end if flat top
  1441. else
  1442. {
  1443. // must be flat bottom
  1444. // compute all deltas
  1445. dy = (y1 - y0);
  1446. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  1447. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  1448. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  1449. dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dy; 
  1450. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy; 
  1451. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1452. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1453. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  1454. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dy;   
  1455. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  1456. // test for y clipping
  1457. if (y0 < min_clip_y)
  1458. {
  1459. // compute overclip
  1460. dy = (min_clip_y - y0);
  1461. // computer new LHS starting values
  1462. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1463. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1464. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1465. wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
  1466. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1467. // compute new RHS starting values
  1468. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1469. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  1470. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  1471. wr = dwdyr*dy + (tw0 << FIXP16_SHIFT);
  1472. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  1473. // compute new starting y
  1474. ystart = min_clip_y;
  1475. } // end if
  1476. else
  1477. {
  1478. // no clipping
  1479. // set starting values
  1480. xl = (x0 << FIXP16_SHIFT);
  1481. xr = (x0 << FIXP16_SHIFT);
  1482. ul = (tu0 << FIXP16_SHIFT);
  1483. vl = (tv0 << FIXP16_SHIFT);
  1484. wl = (tw0 << FIXP16_SHIFT);
  1485. zl = (tz0 << FIXP16_SHIFT);
  1486. ur = (tu0 << FIXP16_SHIFT);
  1487. vr = (tv0 << FIXP16_SHIFT);
  1488. wr = (tw0 << FIXP16_SHIFT);
  1489. zr = (tz0 << FIXP16_SHIFT);
  1490. // set starting y
  1491. ystart = y0;
  1492. } // end else
  1493. } // end else flat bottom
  1494. // test for bottom clip, always
  1495. if ((yend = y2) > max_clip_y)
  1496. yend = max_clip_y;
  1497.     // test for horizontal clipping
  1498. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1499. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1500. (x2 < min_clip_x) || (x2 > max_clip_x))
  1501. {
  1502.     // clip version
  1503. // point screen ptr to starting line
  1504. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1505.     // point zbuffer to starting line
  1506.     z_ptr = zbuffer + (ystart * zpitch);
  1507. for (yi = ystart; yi < yend; yi++)
  1508. {
  1509. // compute span endpoints
  1510. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1511. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1512. // compute starting points for u,v,w interpolants
  1513. ui = ul + FIXP16_ROUND_UP;
  1514. vi = vl + FIXP16_ROUND_UP;
  1515. wi = wl + FIXP16_ROUND_UP;
  1516. zi = zl + FIXP16_ROUND_UP;
  1517. // compute u,v interpolants
  1518. if ((dx = (xend - xstart))>0)
  1519. {
  1520. du = (ur - ul)/dx;
  1521. dv = (vr - vl)/dx;
  1522. dw = (wr - wl)/dx;
  1523. dz = (zr - zl)/dx;
  1524. } // end if
  1525. else
  1526. {
  1527. du = (ur - ul);
  1528. dv = (vr - vl);
  1529. dw = (wr - wl);
  1530. dz = (zr - zl);
  1531. } // end else
  1532. ///////////////////////////////////////////////////////////////////////
  1533. // test for x clipping, LHS
  1534. if (xstart < min_clip_x)
  1535. {
  1536. // compute x overlap
  1537. dx = min_clip_x - xstart;
  1538. // slide interpolants over
  1539. ui+=dx*du;
  1540. vi+=dx*dv;
  1541. wi+=dx*dw;
  1542. zi+=dx*dz;
  1543. // reset vars
  1544. xstart = min_clip_x;
  1545. } // end if
  1546. // test for x clipping RHS
  1547. if (xend > max_clip_x)
  1548. xend = max_clip_x;
  1549. ///////////////////////////////////////////////////////////////////////
  1550. // draw span
  1551. for (xi=xstart; xi < xend; xi++)
  1552. {
  1553.             // write thru z buffer always
  1554. // write textel assume 5.6.5
  1555.      screen_ptr[xi] = ((ui >> (FIXP16_SHIFT+3)) << 11) + 
  1556.                                 ((vi >> (FIXP16_SHIFT+2)) << 5) + 
  1557.                                  (wi >> (FIXP16_SHIFT+3));   
  1558.             // update z-buffer
  1559.             z_ptr[xi] = zi;           
  1560. // interpolate u,v,w,z
  1561. ui+=du;
  1562. vi+=dv;
  1563. wi+=dw;
  1564. zi+=dz;
  1565. } // end for xi
  1566. // interpolate u,v,w,z,x along right and left edge
  1567. xl+=dxdyl;
  1568. ul+=dudyl;
  1569. vl+=dvdyl;
  1570. wl+=dwdyl;
  1571. zl+=dzdyl;
  1572. xr+=dxdyr;
  1573. ur+=dudyr;
  1574. vr+=dvdyr;
  1575. wr+=dwdyr;
  1576. zr+=dzdyr;
  1577.  
  1578. // advance screen ptr
  1579. screen_ptr+=mem_pitch;
  1580.         // advance z-buffer ptr
  1581.         z_ptr+=zpitch;
  1582. } // end for y
  1583. } // end if clip
  1584. else
  1585. {
  1586. // non-clip version
  1587. // point screen ptr to starting line
  1588. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1589.     // point zbuffer to starting line
  1590.     z_ptr = zbuffer + (ystart * zpitch);
  1591. for (yi = ystart; yi < yend; yi++)
  1592. {
  1593. // compute span endpoints
  1594. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1595. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1596. // compute starting points for u,v,w interpolants
  1597. ui = ul + FIXP16_ROUND_UP;
  1598. vi = vl + FIXP16_ROUND_UP;
  1599. wi = wl + FIXP16_ROUND_UP;
  1600. zi = zl + FIXP16_ROUND_UP;
  1601. // compute u,v interpolants
  1602. if ((dx = (xend - xstart))>0)
  1603. {
  1604. du = (ur - ul)/dx;
  1605. dv = (vr - vl)/dx;
  1606. dw = (wr - wl)/dx;
  1607. dz = (zr - zl)/dx;
  1608. } // end if
  1609. else
  1610. {
  1611. du = (ur - ul);
  1612. dv = (vr - vl);
  1613. dw = (wr - wl);
  1614. dz = (zr - zl);
  1615. } // end else
  1616. // draw span
  1617. for (xi=xstart; xi < xend; xi++)
  1618. {
  1619.             // write thru z buffer always
  1620. // write textel assume 5.6.5
  1621.      screen_ptr[xi] = ((ui >> (FIXP16_SHIFT+3)) << 11) + 
  1622.                                 ((vi >> (FIXP16_SHIFT+2)) << 5) + 
  1623.                                  (wi >> (FIXP16_SHIFT+3));   
  1624.             // update z-buffer
  1625.             z_ptr[xi] = zi;           
  1626. // interpolate u,v,w,z
  1627. ui+=du;
  1628. vi+=dv;
  1629. wi+=dw;
  1630. zi+=dz;
  1631. } // end for xi
  1632. // interpolate u,v,w,x along right and left edge
  1633. xl+=dxdyl;
  1634. ul+=dudyl;
  1635. vl+=dvdyl;
  1636. wl+=dwdyl;
  1637. zl+=dzdyl;
  1638. xr+=dxdyr;
  1639. ur+=dudyr;
  1640. vr+=dvdyr;
  1641. wr+=dwdyr;
  1642. zr+=dzdyr;
  1643. // advance screen ptr
  1644. screen_ptr+=mem_pitch;
  1645.         // advance z-buffer ptr
  1646.         z_ptr+=zpitch;
  1647. } // end for y
  1648. } // end if non-clipped
  1649. } // end if
  1650. else
  1651. if (tri_type==TRI_TYPE_GENERAL)
  1652. {
  1653. // first test for bottom clip, always
  1654. if ((yend = y2) > max_clip_y)
  1655. yend = max_clip_y;
  1656. // pre-test y clipping status
  1657. if (y1 < min_clip_y)
  1658. {
  1659. // compute all deltas
  1660. // LHS
  1661. dyl = (y2 - y1);
  1662. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  1663. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1664. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  1665. dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;  
  1666. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl; 
  1667. // RHS
  1668. dyr = (y2 - y0);
  1669. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  1670. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1671. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1672. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;   
  1673. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;  
  1674. // compute overclip
  1675. dyr = (min_clip_y - y0);
  1676. dyl = (min_clip_y - y1);
  1677. // computer new LHS starting values
  1678. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  1679. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  1680. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  1681. wl = dwdyl*dyl + (tw1 << FIXP16_SHIFT);
  1682. zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  1683. // compute new RHS starting values
  1684. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  1685. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  1686. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  1687. wr = dwdyr*dyr + (tw0 << FIXP16_SHIFT);
  1688. zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  1689. // compute new starting y
  1690. ystart = min_clip_y;
  1691. // test if we need swap to keep rendering left to right
  1692. if (dxdyr > dxdyl)
  1693. {
  1694. SWAP(dxdyl,dxdyr,temp);
  1695. SWAP(dudyl,dudyr,temp);
  1696. SWAP(dvdyl,dvdyr,temp);
  1697. SWAP(dwdyl,dwdyr,temp);
  1698. SWAP(dzdyl,dzdyr,temp);
  1699. SWAP(xl,xr,temp);
  1700. SWAP(ul,ur,temp);
  1701. SWAP(vl,vr,temp);
  1702. SWAP(wl,wr,temp);
  1703. SWAP(zl,zr,temp);
  1704. SWAP(x1,x2,temp);
  1705. SWAP(y1,y2,temp);
  1706. SWAP(tu1,tu2,temp);
  1707. SWAP(tv1,tv2,temp);
  1708. SWAP(tw1,tw2,temp);
  1709. SWAP(tz1,tz2,temp);
  1710. // set interpolation restart
  1711. irestart = INTERP_RHS;
  1712. } // end if
  1713. } // end if
  1714. else
  1715. if (y0 < min_clip_y)
  1716. {
  1717. // compute all deltas
  1718. // LHS
  1719. dyl = (y1 - y0);
  1720. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1721. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  1722. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  1723. dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl; 
  1724. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl; 
  1725. // RHS
  1726. dyr = (y2 - y0);
  1727. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  1728. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1729. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1730. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;   
  1731. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;  
  1732. // compute overclip
  1733. dy = (min_clip_y - y0);
  1734. // computer new LHS starting values
  1735. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1736. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1737. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1738. wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
  1739. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1740. // compute new RHS starting values
  1741. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1742. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  1743. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  1744. wr = dwdyr*dy + (tw0 << FIXP16_SHIFT);
  1745. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  1746. // compute new starting y
  1747. ystart = min_clip_y;
  1748. // test if we need swap to keep rendering left to right
  1749. if (dxdyr < dxdyl)
  1750. {
  1751. SWAP(dxdyl,dxdyr,temp);
  1752. SWAP(dudyl,dudyr,temp);
  1753. SWAP(dvdyl,dvdyr,temp);
  1754. SWAP(dwdyl,dwdyr,temp);
  1755. SWAP(dzdyl,dzdyr,temp);
  1756. SWAP(xl,xr,temp);
  1757. SWAP(ul,ur,temp);
  1758. SWAP(vl,vr,temp);
  1759. SWAP(wl,wr,temp);
  1760. SWAP(zl,zr,temp);
  1761. SWAP(x1,x2,temp);
  1762. SWAP(y1,y2,temp);
  1763. SWAP(tu1,tu2,temp);
  1764. SWAP(tv1,tv2,temp);
  1765. SWAP(tw1,tw2,temp);
  1766. SWAP(tz1,tz2,temp);
  1767. // set interpolation restart
  1768. irestart = INTERP_RHS;
  1769. } // end if
  1770. } // end if
  1771. else
  1772. {
  1773. // no initial y clipping
  1774. // compute all deltas
  1775. // LHS
  1776. dyl = (y1 - y0);
  1777. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1778. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  1779. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  1780. dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl;   
  1781. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl; 
  1782. // RHS
  1783. dyr = (y2 - y0);
  1784. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  1785. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1786. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1787. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;
  1788. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
  1789. // no clipping y
  1790. // set starting values
  1791. xl = (x0 << FIXP16_SHIFT);
  1792. xr = (x0 << FIXP16_SHIFT);
  1793. ul = (tu0 << FIXP16_SHIFT);
  1794. vl = (tv0 << FIXP16_SHIFT);
  1795. wl = (tw0 << FIXP16_SHIFT);
  1796. zl = (tz0 << FIXP16_SHIFT);
  1797. ur = (tu0 << FIXP16_SHIFT);
  1798. vr = (tv0 << FIXP16_SHIFT);
  1799. wr = (tw0 << FIXP16_SHIFT);
  1800. zr = (tz0 << FIXP16_SHIFT);
  1801. // set starting y
  1802. ystart = y0;
  1803. // test if we need swap to keep rendering left to right
  1804. if (dxdyr < dxdyl)
  1805. {
  1806. SWAP(dxdyl,dxdyr,temp);
  1807. SWAP(dudyl,dudyr,temp);
  1808. SWAP(dvdyl,dvdyr,temp);
  1809. SWAP(dwdyl,dwdyr,temp);
  1810. SWAP(dzdyl,dzdyr,temp);
  1811. SWAP(xl,xr,temp);
  1812. SWAP(ul,ur,temp);
  1813. SWAP(vl,vr,temp);
  1814. SWAP(wl,wr,temp);
  1815. SWAP(zl,zr,temp);
  1816. SWAP(x1,x2,temp);
  1817. SWAP(y1,y2,temp);
  1818. SWAP(tu1,tu2,temp);
  1819. SWAP(tv1,tv2,temp);
  1820. SWAP(tw1,tw2,temp);
  1821. SWAP(tz1,tz2,temp);
  1822. // set interpolation restart
  1823. irestart = INTERP_RHS;
  1824. } // end if
  1825. } // end else
  1826.     // test for horizontal clipping
  1827. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1828. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1829. (x2 < min_clip_x) || (x2 > max_clip_x))
  1830. {
  1831.     // clip version
  1832. // x clipping
  1833. // point screen ptr to starting line
  1834. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1835.     // point zbuffer to starting line
  1836.     z_ptr = zbuffer + (ystart * zpitch);
  1837. for (yi = ystart; yi < yend; yi++)
  1838. {
  1839. // compute span endpoints
  1840. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1841. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1842. // compute starting points for u,v,w interpolants
  1843. ui = ul + FIXP16_ROUND_UP;
  1844. vi = vl + FIXP16_ROUND_UP;
  1845. wi = wl + FIXP16_ROUND_UP;
  1846. zi = zl + FIXP16_ROUND_UP;
  1847. // compute u,v interpolants
  1848. if ((dx = (xend - xstart))>0)
  1849. {
  1850. du = (ur - ul)/dx;
  1851. dv = (vr - vl)/dx;
  1852. dw = (wr - wl)/dx;
  1853. dz = (zr - zl)/dx;
  1854. } // end if
  1855. else
  1856. {
  1857. du = (ur - ul);
  1858. dv = (vr - vl);
  1859. dw = (wr - wl);
  1860. dz = (zr - zl);
  1861. } // end else
  1862. ///////////////////////////////////////////////////////////////////////
  1863. // test for x clipping, LHS
  1864. if (xstart < min_clip_x)
  1865. {
  1866. // compute x overlap
  1867. dx = min_clip_x - xstart;
  1868. // slide interpolants over
  1869. ui+=dx*du;
  1870. vi+=dx*dv;
  1871. wi+=dx*dw;
  1872. zi+=dx*dz;
  1873. // set x to left clip edge
  1874. xstart = min_clip_x;
  1875. } // end if
  1876. // test for x clipping RHS
  1877. if (xend > max_clip_x)
  1878. xend = max_clip_x;
  1879. ///////////////////////////////////////////////////////////////////////
  1880. // draw span
  1881. for (xi=xstart; xi < xend; xi++)
  1882. {
  1883.             // write thru z buffer always
  1884. // write textel assume 5.6.5
  1885.      screen_ptr[xi] = ((ui >> (FIXP16_SHIFT+3)) << 11) + 
  1886.                                 ((vi >> (FIXP16_SHIFT+2)) << 5) + 
  1887.                                  (wi >> (FIXP16_SHIFT+3));   
  1888.             // update z-buffer
  1889.             z_ptr[xi] = zi;           
  1890. // interpolate u,v,w,z
  1891. ui+=du;
  1892. vi+=dv;
  1893. wi+=dw;
  1894. zi+=dz;
  1895. } // end for xi
  1896. // interpolate u,v,w,z,x along right and left edge
  1897. xl+=dxdyl;
  1898.         ul+=dudyl;
  1899. vl+=dvdyl;
  1900. wl+=dwdyl;
  1901. zl+=dzdyl;
  1902. xr+=dxdyr;
  1903.       ur+=dudyr;
  1904. vr+=dvdyr;
  1905. wr+=dwdyr;
  1906. zr+=dzdyr;
  1907. // advance screen ptr
  1908. screen_ptr+=mem_pitch;
  1909.         // advance z-buffer ptr
  1910.         z_ptr+=zpitch;
  1911. // test for yi hitting second region, if so change interpolant
  1912. if (yi==yrestart)
  1913. {
  1914.     // test interpolation side change flag
  1915. if (irestart == INTERP_LHS)
  1916. {
  1917. // LHS
  1918. dyl = (y2 - y1);
  1919. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1920. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1921. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1922. dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;  
  1923. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  1924. // set starting values
  1925. xl = (x1  << FIXP16_SHIFT);
  1926. ul = (tu1 << FIXP16_SHIFT);
  1927. vl = (tv1 << FIXP16_SHIFT);
  1928. wl = (tw1 << FIXP16_SHIFT);
  1929. zl = (tz1 << FIXP16_SHIFT);
  1930. // interpolate down on LHS to even up
  1931. xl+=dxdyl;
  1932. ul+=dudyl;
  1933. vl+=dvdyl;
  1934. wl+=dwdyl;
  1935. zl+=dzdyl;
  1936. } // end if
  1937. else
  1938. {
  1939. // RHS
  1940. dyr = (y1 - y2);
  1941. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1942. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1943. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1944. dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;   
  1945. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  1946. // set starting values
  1947. xr = (x2  << FIXP16_SHIFT);
  1948. ur = (tu2 << FIXP16_SHIFT);
  1949. vr = (tv2 << FIXP16_SHIFT);
  1950. wr = (tw2 << FIXP16_SHIFT);
  1951. zr = (tz2 << FIXP16_SHIFT);
  1952. // interpolate down on RHS to even up
  1953. xr+=dxdyr;
  1954. ur+=dudyr;
  1955. vr+=dvdyr;
  1956. wr+=dwdyr;
  1957. zr+=dzdyr;
  1958. } // end else
  1959. } // end if
  1960. } // end for y
  1961. } // end if
  1962. else
  1963. {
  1964. // no x clipping
  1965. // point screen ptr to starting line
  1966. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1967.     // point zbuffer to starting line
  1968.     z_ptr = zbuffer + (ystart * zpitch);
  1969. for (yi = ystart; yi < yend; yi++)
  1970. {
  1971. // compute span endpoints
  1972. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1973. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1974. // compute starting points for u,v,w,z interpolants
  1975. ui = ul + FIXP16_ROUND_UP;
  1976. vi = vl + FIXP16_ROUND_UP;
  1977. wi = wl + FIXP16_ROUND_UP;
  1978. zi = zl + FIXP16_ROUND_UP;
  1979. // compute u,v interpolants
  1980. if ((dx = (xend - xstart))>0)
  1981. {
  1982. du = (ur - ul)/dx;
  1983. dv = (vr - vl)/dx;
  1984. dw = (wr - wl)/dx;
  1985. dz = (zr - zl)/dx;
  1986. } // end if
  1987. else
  1988. {
  1989. du = (ur - ul);
  1990. dv = (vr - vl);
  1991. dw = (wr - wl);
  1992. dz = (zr - zl);
  1993. } // end else
  1994. // draw span
  1995. for (xi=xstart; xi < xend; xi++)
  1996. {
  1997.             // write thru z buffer always
  1998. // write textel assume 5.6.5
  1999.      screen_ptr[xi] = ((ui >> (FIXP16_SHIFT+3)) << 11) + 
  2000.                                 ((vi >> (FIXP16_SHIFT+2)) << 5) + 
  2001.                                  (wi >> (FIXP16_SHIFT+3));   
  2002.             // update z-buffer
  2003.             z_ptr[xi] = zi;           
  2004. // interpolate u,v,w,z
  2005. ui+=du;
  2006. vi+=dv;
  2007. wi+=dw;
  2008. zi+=dz;
  2009. } // end for xi
  2010. // interpolate u,v,w,x,z along right and left edge
  2011. xl+=dxdyl;
  2012. ul+=dudyl;
  2013. vl+=dvdyl;
  2014. wl+=dwdyl;
  2015. zl+=dzdyl;
  2016. xr+=dxdyr;
  2017. ur+=dudyr;
  2018. vr+=dvdyr;
  2019. wr+=dwdyr;
  2020. zr+=dzdyr;
  2021. // advance screen ptr
  2022. screen_ptr+=mem_pitch;
  2023.         // advance z-buffer ptr
  2024.         z_ptr+=zpitch;
  2025. // test for yi hitting second region, if so change interpolant
  2026. if (yi==yrestart)
  2027. {
  2028. // test interpolation side change flag
  2029. if (irestart == INTERP_LHS)
  2030. {
  2031. // LHS
  2032. dyl = (y2 - y1);
  2033. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  2034. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2035. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  2036. dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;   
  2037. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  2038. // set starting values
  2039. xl = (x1  << FIXP16_SHIFT);
  2040. ul = (tu1 << FIXP16_SHIFT);
  2041. vl = (tv1 << FIXP16_SHIFT);
  2042. wl = (tw1 << FIXP16_SHIFT);
  2043. zl = (tz1 << FIXP16_SHIFT);
  2044. // interpolate down on LHS to even up
  2045. xl+=dxdyl;
  2046. ul+=dudyl;
  2047. vl+=dvdyl;
  2048. wl+=dwdyl;
  2049. zl+=dzdyl;
  2050. } // end if
  2051. else
  2052. {
  2053. // RHS
  2054. dyr = (y1 - y2);
  2055. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  2056. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  2057. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  2058. dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;   
  2059. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  2060. // set starting values
  2061. xr = (x2  << FIXP16_SHIFT);
  2062. ur = (tu2 << FIXP16_SHIFT);
  2063. vr = (tv2 << FIXP16_SHIFT);
  2064. wr = (tw2 << FIXP16_SHIFT);
  2065. zr = (tz2 << FIXP16_SHIFT);
  2066. // interpolate down on RHS to even up
  2067. xr+=dxdyr;
  2068. ur+=dudyr;
  2069. vr+=dvdyr;
  2070. wr+=dwdyr;
  2071. zr+=dzdyr;
  2072. } // end else
  2073. } // end if
  2074. } // end for y
  2075.    } // end else
  2076. } // end if
  2077. } // end Draw_Gouraud_TriangleWTZB2_16
  2078. ///////////////////////////////////////////////////////////////////////////////
  2079. //////////////////////////////////////////////////////////////////////////////
  2080. void BHV_Reset_Tree(BHV_NODEV1_PTR bhv_tree)
  2081. {
  2082. // this function simply resets all of the culled flags in the root of the
  2083. // tree which will enable the entire tree as visible
  2084. for (int iobject = 0; iobject < bhv_tree->num_objects; iobject++)
  2085.     {
  2086.     // reset the culled flag
  2087.     RESET_BIT(bhv_tree->objects[iobject]->state, OBJECT4DV2_STATE_CULLED);
  2088.     } // end if
  2089. } // end BHV_Reset_Tree
  2090. //////////////////////////////////////////////////////////////////////////////
  2091. int BHV_FrustrumCull(BHV_NODEV1_PTR bhv_tree, // the root of the BHV  
  2092.                      CAM4DV1_PTR cam,         // camera to cull relative to
  2093.                      int cull_flags)          // clipping planes to consider
  2094. {
  2095. // NOTE: is matrix based
  2096. // this function culls the BHV from the viewing
  2097. // frustrum by using the sent camera information and
  2098. // the cull_flags determine what axes culling should take place
  2099. // x, y, z or all which is controlled by ORing the flags
  2100. // together. as the BHV is culled the state information in each node is 
  2101. // modified, so rendering functions can refer to it
  2102. // test for valid BHV and camera
  2103. if (!bhv_tree || !cam)
  2104.    return(0);
  2105. // we need to walk the tree from top to bottom culling
  2106. // step 1: transform the center of the nodes bounding
  2107. // sphere into camera space
  2108. POINT4D sphere_pos; // hold result of transforming center of bounding sphere
  2109. // transform point
  2110. Mat_Mul_VECTOR4D_4X4(&bhv_tree->pos, &cam->mcam, &sphere_pos);
  2111. // step 2:  based on culling flags remove the object
  2112. if (cull_flags & CULL_OBJECT_Z_PLANE)
  2113. {
  2114. // cull only based on z clipping planes
  2115. // test far plane
  2116. if ( ((sphere_pos.z - bhv_tree->radius.z) > cam->far_clip_z) ||
  2117.      ((sphere_pos.z + bhv_tree->radius.z) < cam->near_clip_z) )
  2118.    { 
  2119.    // this entire node is culled, so we need to set the culled flag
  2120.    // for every object
  2121.    for (int iobject = 0; iobject < bhv_tree->num_objects; iobject++)
  2122.        {
  2123.        SET_BIT(bhv_tree->objects[iobject]->state, OBJECT4DV2_STATE_CULLED);
  2124.        } // end for iobject
  2125. #if 0
  2126.    Write_Error("n[ZBHV p(%f, %f, %f) r(%f) #objs(%d)]", bhv_tree->pos.x, 
  2127.                                                          bhv_tree->pos.y,
  2128.                                                          bhv_tree->pos.z,
  2129.                                                          bhv_tree->radius.x, 
  2130.                                                          bhv_tree->num_objects);
  2131. #endif
  2132.    // this node was visited and culled
  2133.    bhv_nodes_visited++;
  2134.    return(1);
  2135.    } // end if
  2136. } // end if
  2137. if (cull_flags & CULL_OBJECT_X_PLANE)
  2138. {
  2139. // cull only based on x clipping planes
  2140. // we could use plane equations, but simple similar triangles
  2141. // is easier since this is really a 2D problem
  2142. // if the view volume is 90 degrees the the problem is trivial
  2143. // buts lets assume its not
  2144. // test the the right and left clipping planes against the leftmost and rightmost
  2145. // points of the bounding sphere
  2146. float z_test = (0.5)*cam->viewplane_width*sphere_pos.z/cam->view_dist;
  2147. if ( ((sphere_pos.x - bhv_tree->radius.x) > z_test)  || // right side
  2148.      ((sphere_pos.x + bhv_tree->radius.x) < -z_test) )  // left side, note sign change
  2149.    { 
  2150.    // this entire node is culled, so we need to set the culled flag
  2151.    // for every object
  2152.    for (int iobject = 0; iobject < bhv_tree->num_objects; iobject++)
  2153.        {
  2154.        SET_BIT(bhv_tree->objects[iobject]->state, OBJECT4DV2_STATE_CULLED);
  2155.        } // end for iobject
  2156. #if 0
  2157.    Write_Error("n[XBHV p(%f, %f, %f) r(%f) #objs(%d)]", bhv_tree->pos.x, 
  2158.                                                          bhv_tree->pos.y,
  2159.                                                          bhv_tree->pos.z,
  2160.                                                          bhv_tree->radius.x, bhv_tree->num_objects);
  2161. #endif
  2162.    // this node was visited and culled
  2163.    bhv_nodes_visited++;
  2164.    return(1);
  2165.    } // end if
  2166. } // end if
  2167. if (cull_flags & CULL_OBJECT_Y_PLANE)
  2168. {
  2169. // cull only based on y clipping planes
  2170. // we could use plane equations, but simple similar triangles
  2171. // is easier since this is really a 2D problem
  2172. // if the view volume is 90 degrees the the problem is trivial
  2173. // buts lets assume its not
  2174. // test the the top and bottom clipping planes against the bottommost and topmost
  2175. // points of the bounding sphere
  2176. float z_test = (0.5)*cam->viewplane_height*sphere_pos.z/cam->view_dist;
  2177. if ( ((sphere_pos.y - bhv_tree->radius.y) > z_test)  || // top side
  2178.      ((sphere_pos.y + bhv_tree->radius.y) < -z_test) )  // bottom side, note sign change
  2179.    { 
  2180.    // this entire node is culled, so we need to set the culled flag
  2181.    // for every object
  2182.    for (int iobject = 0; iobject < bhv_tree->num_objects; iobject++)
  2183.        {
  2184.        SET_BIT(bhv_tree->objects[iobject]->state, OBJECT4DV2_STATE_CULLED);
  2185.        } // end for iobject
  2186. #if 0
  2187.    Write_Error("n[YBHV p(%f, %f, %f) r(%f) #objs(%d)]", bhv_tree->pos.x, 
  2188.                                                          bhv_tree->pos.y,
  2189.                                                          bhv_tree->pos.z,
  2190.                                                          bhv_tree->radius.x, 
  2191.                                                          bhv_tree->num_objects);
  2192. #endif
  2193.    // this node was visited and culled
  2194.    bhv_nodes_visited++;
  2195.    return(1);
  2196.    } // end if
  2197. } // end if
  2198. // at this point, we have concluded that this BHV node is too large
  2199. // to cull, so we need to traverse the children and see if we can cull them
  2200. for (int ichild = 0; ichild < bhv_tree->num_children; ichild++)
  2201.     {
  2202.     // recursively call..
  2203.     BHV_FrustrumCull(bhv_tree->links[ichild], cam, cull_flags);
  2204.     // here's where we can optimize by tracking the total number 
  2205.     // of objects culled and we can exit early if all the objects
  2206.     // are already culled...
  2207.     } // end ichild
  2208. // return failure to cull anything!
  2209. return(0);
  2210. } // end BHV_FrustrumCull
  2211. //////////////////////////////////////////////////////////////////////////////
  2212. void BHV_Build_Tree(BHV_NODEV1_PTR bhv_tree,         // tree to build
  2213.                     OBJ_CONTAINERV1_PTR bhv_objects, // ptr to all objects in intial scene
  2214.                     int num_objects,                 // number of objects in initial scene
  2215.                     int level,                       // recursion level
  2216.                     int num_divisions,               // number of division per level
  2217.                     int universe_radius)             // initial size of universe to enclose
  2218. {
  2219. // this function builds the BHV tree using a divide and conquer
  2220. // divisioning algorithm to cluster the objects together
  2221. Write_Error("nEntering BHV function...");
  2222. // are we building root?
  2223. if (level == 0)
  2224.    {
  2225.    Write_Error("nlevel = 0");
  2226.    // position at (0,0,0)
  2227.    bhv_tree->pos.x = 0;
  2228.    bhv_tree->pos.y = 0;
  2229.    bhv_tree->pos.z = 0;
  2230.    bhv_tree->pos.w = 1;
  2231.    // set radius of node to maximum
  2232.    bhv_tree->radius.x = universe_radius;
  2233.    bhv_tree->radius.y = universe_radius;
  2234.    bhv_tree->radius.z = universe_radius;
  2235.    bhv_tree->radius.w = 1;
  2236.    Write_Error("nnode pos[%f, %f, %f], r[%f, %f, %f]", 
  2237.                      bhv_tree->pos.x,bhv_tree->pos.y,bhv_tree->pos.z,
  2238.                      bhv_tree->radius.x,bhv_tree->radius.y,bhv_tree->radius.z);
  2239.    // build root, simply add all objects to root
  2240.    for (int index = 0; index < num_objects; index++)
  2241.        {
  2242.        // make sure object is not culled 
  2243.        if (!(bhv_objects[index].state & OBJECT4DV2_STATE_CULLED))
  2244.           {
  2245.           bhv_tree->objects[bhv_tree->num_objects++] = (OBJ_CONTAINERV1_PTR)&bhv_objects[index];
  2246.           } // end if
  2247.  
  2248.        } // end for index
  2249.    
  2250.    // at this point all the objects have been inserted into the root node
  2251.    // and num_objects is set to the number of objects
  2252.    // enable the node
  2253.    bhv_tree->state = 1;
  2254.    bhv_tree->attr  = 0;
  2255.    // and set all links to NULL
  2256.    for (int ilink = 0; ilink < MAX_BHV_PER_NODE; ilink++)
  2257.        bhv_tree->links[ilink] = NULL;
  2258.    // set the number of objects
  2259.    bhv_tree->num_objects = num_objects;
  2260.    Write_Error("nInserted %d objects into root node", bhv_tree->num_objects);
  2261.    Write_Error("nMaking recursive call with root node...");
  2262.     
  2263.    // done, so now allow recursion to build the rest of the tree
  2264.    BHV_Build_Tree(bhv_tree, 
  2265.                   bhv_objects, 
  2266.                   num_objects, 
  2267.                   1,
  2268.                   num_divisions,
  2269.                   universe_radius);
  2270.    } // end if
  2271. else
  2272.    {
  2273.    Write_Error("nEntering Level = %d > 0 block, number of objects = %d",level, bhv_tree->num_objects);
  2274.    // test for exit state
  2275.    if (bhv_tree->num_objects <= MIN_OBJECTS_PER_BHV_CELL)
  2276.       return;
  2277.    // building a child node (hard part)
  2278.    // we must take the current node and split it into a number of children nodes, and then
  2279.    // create a bvh for each child and then insert all the objects into each child
  2280.    // the for each child call the recursion again....
  2281.    
  2282. // create 3D cell temp storage to track cells
  2283. BHV_CELL cells[MAX_BHV_CELL_DIVISIONS][MAX_BHV_CELL_DIVISIONS][MAX_BHV_CELL_DIVISIONS];
  2284. // find origin of bounding volume based on radius and center
  2285. int x0 = bhv_tree->pos.x - bhv_tree->radius.x;
  2286. int y0 = bhv_tree->pos.y - bhv_tree->radius.y;
  2287. int z0 = bhv_tree->pos.z - bhv_tree->radius.z;
  2288. // compute cell sizes on x,y,z axis
  2289. float cell_size_x = 2*bhv_tree->radius.x / (float)num_divisions;
  2290. float cell_size_y = 2*bhv_tree->radius.y / (float)num_divisions;
  2291. float cell_size_z = 2*bhv_tree->radius.z / (float)num_divisions;
  2292. Write_Error("ncell pos=(%d, %d, %d) size=(%f, %f, %f)", x0,y0,z0, cell_size_x, cell_size_y, cell_size_z);
  2293. int cell_x, cell_y, cell_z; // used to locate cell in 3D matrix
  2294. // clear cell memory out
  2295. memset(cells, 0, sizeof(cells));
  2296. // now partition space up into num_divisions (must be < MAX_BHV_CELL_DIVISIONS)
  2297. // and then sort each object's center into each cell of the 3D sorting matrix
  2298. for (int obj_index = 0; obj_index < bhv_tree->num_objects; obj_index++)
  2299.     {
  2300.     // compute cell position in temp sorting matrix
  2301.     cell_x = (bhv_tree->objects[obj_index]->pos.x - x0)/cell_size_x;
  2302.     cell_y = (bhv_tree->objects[obj_index]->pos.y - y0)/cell_size_y;
  2303.     cell_z = (bhv_tree->objects[obj_index]->pos.z - z0)/cell_size_z;
  2304.     // insert this object into list
  2305.     cells[cell_x][cell_y][cell_z].obj_list[ cells[cell_x][cell_y][cell_z].num_objects ] = bhv_tree->objects[obj_index];
  2306.     Write_Error("ninserting object %d located at (%f, %f, %f) into cell (%d, %d, %d)", obj_index, 
  2307.                                                       bhv_tree->objects[obj_index]->pos.x,
  2308.                                                       bhv_tree->objects[obj_index]->pos.y,
  2309.                                                       bhv_tree->objects[obj_index]->pos.z,
  2310.                                                       cell_x, cell_y, cell_z);
  2311.     // increment number of objects in this cell
  2312.     if (++cells[cell_x][cell_y][cell_z].num_objects >= MAX_OBJECTS_PER_BHV_CELL)
  2313.        cells[cell_x][cell_y][cell_z].num_objects  = MAX_OBJECTS_PER_BHV_CELL-1;   
  2314.     } // end for obj_index
  2315. Write_Error("nEntering sorting section...");
  2316. // now the 3D sorting matrix has all the information we need, the next step
  2317. // is to create a BHV node for each non-empty
  2318. for (int icell_x = 0; icell_x < num_divisions; icell_x++)
  2319.     {
  2320.     for (int icell_y = 0; icell_y < num_divisions; icell_y++)
  2321.         {
  2322.         for (int icell_z = 0; icell_z < num_divisions; icell_z++)
  2323.             {
  2324.             // are there any objects in this node?
  2325.             if ( cells[icell_x][icell_y][icell_z].num_objects > 0)
  2326.                {
  2327.                Write_Error("nCell %d, %d, %d contains %d objects", icell_x, icell_y, icell_z, 
  2328.                                                                     cells[icell_x][icell_y][icell_z].num_objects);
  2329.                Write_Error("nCreating child node...");
  2330.            
  2331.                // create a node and set the link to it
  2332.                bhv_tree->links[ bhv_tree->num_children ] = (BHV_NODEV1_PTR)malloc(sizeof(BHV_NODEV1));
  2333.  
  2334.                // zero node out
  2335.                memset(bhv_tree->links[ bhv_tree->num_children ], 0, sizeof(BHV_NODEV1) );
  2336.                // set the node up
  2337.                BHV_NODEV1_PTR curr_node = bhv_tree->links[ bhv_tree->num_children ];
  2338.                // position
  2339.                curr_node->pos.x = (icell_x*cell_size_x + cell_size_x/2) + x0;
  2340.                curr_node->pos.y = (icell_y*cell_size_y + cell_size_y/2) + y0;
  2341.                curr_node->pos.z = (icell_z*cell_size_z + cell_size_z/2) + z0;
  2342.                curr_node->pos.w = 1;
  2343.                // radius is cell_size / 2
  2344.                curr_node->radius.x = cell_size_x/2;
  2345.                curr_node->radius.y = cell_size_y/2;
  2346.                curr_node->radius.z = cell_size_z/2;
  2347.                curr_node->radius.w = 1;
  2348.                // set number of objects
  2349.                curr_node->num_objects = cells[icell_x][icell_y][icell_z].num_objects;
  2350.                // set num children
  2351.                curr_node->num_children = 0;
  2352.  
  2353.                // set state and attr
  2354.                curr_node->state        = 1; // enable node               
  2355.                curr_node->attr         = 0;
  2356.                
  2357.                // now insert each object into this node's object list
  2358.                for (int icell_index = 0; icell_index < curr_node->num_objects; icell_index++)
  2359.                    {
  2360.                    curr_node->objects[icell_index] = cells[icell_x][icell_y][icell_z].obj_list[icell_index];    
  2361.                    } // end for icell_index
  2362.            
  2363.                Write_Error("nChild node pos=(%f, %f, %f), r=(%f, %f, %f)", 
  2364.                                             curr_node->pos.x,curr_node->pos.y,curr_node->pos.z,
  2365.                                             curr_node->radius.x,curr_node->radius.y,curr_node->radius.z);
  2366.                // increment number of children of parent
  2367.                bhv_tree->num_children++;
  2368.                    
  2369.                } // end if
  2370.             } // end for icell_z
  2371.         } // end for icell_y
  2372.     } // end for icell_x
  2373.     Write_Error("nParent has %d children..", bhv_tree->num_children);
  2374.     // now for each child build a BHV
  2375.     for (int inode = 0; inode < bhv_tree->num_children; inode++)
  2376.         {
  2377.         Write_Error("nfor Level %d, creating child %d", level, inode);
  2378.         BHV_Build_Tree(bhv_tree->links[inode], 
  2379.                   NULL, // unused now
  2380.                   NULL, // unused now
  2381.                   level+1, 
  2382.                   num_divisions,
  2383.                   universe_radius);
  2384.    
  2385.         } // end if     
  2386.    } // end else level > 0
  2387. Write_Error("nExiting BHV...level = %d", level);
  2388. } // end BHV_Build_Tree