T3DLIB11.CPP
资源名称:Source.rar [点击查看]
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:286k
源码类别:
游戏
开发平台:
Visual C++
- // compute starting points for u,v,w interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- wi = wl + FIXP16_ROUND_UP;
- zi = zl + FIXP16_ROUND_UP;
- si = sl + FIXP16_ROUND_UP;
- ti = tl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dw = (wr - wl)/dx;
- dz = (zr - zl)/dx;
- ds = (sr - sl)/dx;
- dt = (tr - tl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dw = (wr - wl);
- dz = (zr - zl);
- ds = (sr - sl);
- dt = (tr - tl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // write textel assume 5.6.5
- // write thru z buffer always
- // get textel first
- textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
- // extract rgb components
- r_textel = ((textel >> 11) );
- g_textel = ((textel >> 5) & 0x3f);
- b_textel = (textel & 0x1f);
- // modulate textel with gouraud shading
- r_textel*=ui;
- g_textel*=vi;
- b_textel*=wi;
- // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
- // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
- // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
- // and they all cancel out for the most part, but we will need logical anding, we will do
- // it later when we optimize more...
- screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) +
- ((g_textel >> (FIXP16_SHIFT+8)) << 5) +
- ((r_textel >> (FIXP16_SHIFT+8)) << 11));
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate u,v
- ui+=du;
- vi+=dv;
- wi+=dw;
- zi+=dz;
- si+=ds;
- ti+=dt;
- } // end for xi
- // interpolate u,v,w,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- sl+=dsdyl;
- tl+=dtdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- sr+=dsdyr;
- tr+=dtdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if non-clipped
- } // end if
- else
- if (tri_type==TRI_TYPE_GENERAL)
- {
- // first test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // pre-test y clipping status
- if (y1 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- dsdyl = ((ts2 - ts1) << FIXP16_SHIFT)/dyl;
- dtdyl = ((tt2 - tt1) << FIXP16_SHIFT)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
- dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dyr;
- dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dyr;
- // compute overclip
- dyr = (min_clip_y - y0);
- dyl = (min_clip_y - y1);
- // computer new LHS starting values
- xl = dxdyl*dyl + (x1 << FIXP16_SHIFT);
- ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
- vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
- wl = dwdyl*dyl + (tw1 << FIXP16_SHIFT);
- zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
- sl = dsdyl*dyl + (ts1 << FIXP16_SHIFT);
- tl = dtdyl*dyl + (tt1 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dyr + (x0 << FIXP16_SHIFT);
- ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
- wr = dwdyr*dyr + (tw0 << FIXP16_SHIFT);
- zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
- sr = dsdyr*dyr + (ts0 << FIXP16_SHIFT);
- tr = dtdyr*dyr + (tt0 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr > dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dwdyl,dwdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(dsdyl,dsdyr,temp);
- SWAP(dtdyl,dtdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(wl,wr,temp);
- SWAP(zl,zr,temp);
- SWAP(sl,sr,temp);
- SWAP(tl,tr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tw1,tw2,temp);
- SWAP(tz1,tz2,temp);
- SWAP(ts1,ts2,temp);
- SWAP(tt1,tt2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- if (y0 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;
- dsdyl = ((ts1 - ts0) << FIXP16_SHIFT)/dyl;
- dtdyl = ((tt1 - tt0) << FIXP16_SHIFT)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
- dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dyr;
- dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dyr;
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
- sl = dsdyl*dy + (ts0 << FIXP16_SHIFT);
- tl = dtdyl*dy + (tt0 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
- wr = dwdyr*dy + (tw0 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
- sr = dsdyr*dy + (ts0 << FIXP16_SHIFT);
- tr = dtdyr*dy + (tt0 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dwdyl,dwdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(dsdyl,dsdyr,temp);
- SWAP(dtdyl,dtdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(wl,wr,temp);
- SWAP(zl,zr,temp);
- SWAP(sl,sr,temp);
- SWAP(tl,tr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tw1,tw2,temp);
- SWAP(tz1,tz2,temp);
- SWAP(ts1,ts2,temp);
- SWAP(tt1,tt2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- {
- // no initial y clipping
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;
- dsdyl = ((ts1 - ts0) << FIXP16_SHIFT)/dyl;
- dtdyl = ((tt1 - tt0) << FIXP16_SHIFT)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
- dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dyr;
- dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dyr;
- // no clipping y
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- wl = (tw0 << FIXP16_SHIFT);
- zl = (tz0 << FIXP16_SHIFT);
- sl = (ts0 << FIXP16_SHIFT);
- tl = (tt0 << FIXP16_SHIFT);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- wr = (tw0 << FIXP16_SHIFT);
- zr = (tz0 << FIXP16_SHIFT);
- sr = (ts0 << FIXP16_SHIFT);
- tr = (tt0 << FIXP16_SHIFT);
- // set starting y
- ystart = y0;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dwdyl,dwdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(dsdyl,dsdyr,temp);
- SWAP(dtdyl,dtdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(wl,wr,temp);
- SWAP(zl,zr,temp);
- SWAP(sl,sr,temp);
- SWAP(tl,tr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tw1,tw2,temp);
- SWAP(tz1,tz2,temp);
- SWAP(ts1,ts2,temp);
- SWAP(tt1,tt2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end else
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v,w interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- wi = wl + FIXP16_ROUND_UP;
- zi = zl + FIXP16_ROUND_UP;
- si = sl + FIXP16_ROUND_UP;
- ti = tl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dw = (wr - wl)/dx;
- dz = (zr - zl)/dx;
- ds = (sr - sl)/dx;
- dt = (tr - tl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dw = (wr - wl);
- dz = (zr - zl);
- ds = (sr - sl);
- dt = (tr - tl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- wi+=dx*dw;
- zi+=dx*dz;
- si+=dx*ds;
- ti+=dx*dt;
- // set x to left clip edge
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // write textel assume 5.6.5
- // write thru z buffer always
- // get textel first
- textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
- // extract rgb components
- r_textel = ((textel >> 11) );
- g_textel = ((textel >> 5) & 0x3f);
- b_textel = (textel & 0x1f);
- // modulate textel with gouraud shading
- r_textel*=ui;
- g_textel*=vi;
- b_textel*=wi;
- // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
- // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
- // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
- // and they all cancel out for the most part, but we will need logical anding, we will do
- // it later when we optimize more...
- screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) +
- ((g_textel >> (FIXP16_SHIFT+8)) << 5) +
- ((r_textel >> (FIXP16_SHIFT+8)) << 11));
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate u,v
- ui+=du;
- vi+=dv;
- wi+=dw;
- zi+=dz;
- si+=ds;
- ti+=dt;
- } // end for xi
- // interpolate u,v,w,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- sl+=dsdyl;
- tl+=dtdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- sr+=dsdyr;
- tr+=dtdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- dsdyl = ((ts2 - ts1) << FIXP16_SHIFT)/dyl;
- dtdyl = ((tt2 - tt1) << FIXP16_SHIFT)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- wl = (tw1 << FIXP16_SHIFT);
- zl = (tz1 << FIXP16_SHIFT);
- sl = (ts1 << FIXP16_SHIFT);
- tl = (tt1 << FIXP16_SHIFT);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- sl+=dsdyl;
- tl+=dtdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;
- dsdyr = ((ts1 - ts2) << FIXP16_SHIFT)/dyr;
- dtdyr = ((tt1 - tt2) << FIXP16_SHIFT)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- wr = (tw2 << FIXP16_SHIFT);
- zr = (tz2 << FIXP16_SHIFT);
- sr = (ts2 << FIXP16_SHIFT);
- tr = (tt2 << FIXP16_SHIFT);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- sr+=dsdyr;
- tr+=dtdyr;
- } // end else
- } // end if
- } // end for y
- } // end if
- else
- {
- // no x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v,w interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- wi = wl + FIXP16_ROUND_UP;
- zi = zl + FIXP16_ROUND_UP;
- si = sl + FIXP16_ROUND_UP;
- ti = tl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dw = (wr - wl)/dx;
- dz = (zr - zl)/dx;
- ds = (sr - sl)/dx;
- dt = (tr - tl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dw = (wr - wl);
- dz = (zr - zl);
- ds = (sr - sl);
- dt = (tr - tl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // write textel assume 5.6.5
- // write thru z buffer always
- // get textel first
- textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
- // extract rgb components
- r_textel = ((textel >> 11) );
- g_textel = ((textel >> 5) & 0x3f);
- b_textel = (textel & 0x1f);
- // modulate textel with gouraud shading
- r_textel*=ui;
- g_textel*=vi;
- b_textel*=wi;
- // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
- // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
- // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
- // and they all cancel out for the most part, but we will need logical anding, we will do
- // it later when we optimize more...
- screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) +
- ((g_textel >> (FIXP16_SHIFT+8)) << 5) +
- ((r_textel >> (FIXP16_SHIFT+8)) << 11));
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate u,v
- ui+=du;
- vi+=dv;
- wi+=dw;
- zi+=dz;
- si+=ds;
- ti+=dt;
- } // end for xi
- // interpolate u,v,w,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- sl+=dsdyl;
- tl+=dtdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- sr+=dsdyr;
- tr+=dtdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- dsdyl = ((ts2 - ts1) << FIXP16_SHIFT)/dyl;
- dtdyl = ((tt2 - tt1) << FIXP16_SHIFT)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- wl = (tw1 << FIXP16_SHIFT);
- zl = (tz1 << FIXP16_SHIFT);
- sl = (ts1 << FIXP16_SHIFT);
- tl = (tt1 << FIXP16_SHIFT);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- sl+=dsdyl;
- tl+=dtdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;
- dsdyr = ((ts1 - ts2) << FIXP16_SHIFT)/dyr;
- dtdyr = ((tt1 - tt2) << FIXP16_SHIFT)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- wr = (tw2 << FIXP16_SHIFT);
- zr = (tz2 << FIXP16_SHIFT);
- sr = (ts2 << FIXP16_SHIFT);
- tr = (tt2 << FIXP16_SHIFT);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- sr+=dsdyr;
- tr+=dtdyr;
- } // end else
- } // end if
- } // end for y
- } // end else
- } // end if
- } // end Draw_Textured_TriangleGSWTZB_16
- ///////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- void Draw_Triangle_2DWTZB_16(POLYF4DV2_PTR face, // ptr to face
- UCHAR *_dest_buffer, // pointer to video buffer
- int mem_pitch, // bytes per line, 320, 640 etc.
- UCHAR *_zbuffer, // pointer to z-buffer
- int zpitch) // bytes per line of zbuffer
- {
- // this function draws a flat shaded polygon with zbuffering
- int v0=0,
- v1=1,
- v2=2,
- temp=0,
- tri_type = TRI_TYPE_NONE,
- irestart = INTERP_LHS;
- int dx,dy,dyl,dyr, // general deltas
- z,
- dz,
- xi,yi, // the current interpolated x,y
- zi, // the current interpolated z
- index_x,index_y, // looping vars
- x,y, // hold general x,y
- xstart,
- xend,
- ystart,
- yrestart,
- yend,
- xl,
- dxdyl,
- xr,
- dxdyr,
- dzdyl,
- zl,
- dzdyr,
- zr;
- int x0,y0,tz0, // cached vertices
- x1,y1,tz1,
- x2,y2,tz2;
- USHORT *screen_ptr = NULL,
- *screen_line = NULL,
- *textmap = NULL,
- *dest_buffer = (USHORT *)_dest_buffer;
- UINT *z_ptr = NULL,
- *zbuffer = (UINT *)_zbuffer;
- USHORT color; // polygon color
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // adjust memory pitch to words, divide by 2
- mem_pitch >>=1;
- // adjust zbuffer pitch for 32 bit alignment
- zpitch >>= 2;
- // apply fill convention to coordinates
- face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
- face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
- face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
- face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
- face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
- face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
- // first trivial clipping rejection tests
- if (((face->tvlist[0].y < min_clip_y) &&
- (face->tvlist[1].y < min_clip_y) &&
- (face->tvlist[2].y < min_clip_y)) ||
- ((face->tvlist[0].y > max_clip_y) &&
- (face->tvlist[1].y > max_clip_y) &&
- (face->tvlist[2].y > max_clip_y)) ||
- ((face->tvlist[0].x < min_clip_x) &&
- (face->tvlist[1].x < min_clip_x) &&
- (face->tvlist[2].x < min_clip_x)) ||
- ((face->tvlist[0].x > max_clip_x) &&
- (face->tvlist[1].x > max_clip_x) &&
- (face->tvlist[2].x > max_clip_x)))
- return;
- // sort vertices
- if (face->tvlist[v1].y < face->tvlist[v0].y)
- {SWAP(v0,v1,temp);}
- if (face->tvlist[v2].y < face->tvlist[v0].y)
- {SWAP(v0,v2,temp);}
- if (face->tvlist[v2].y < face->tvlist[v1].y)
- {SWAP(v1,v2,temp);}
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_TOP;
- // sort vertices left to right
- if (face->tvlist[v1].x < face->tvlist[v0].x)
- {SWAP(v0,v1,temp);}
- } // end if
- else
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v1].y, face->tvlist[v2].y) )
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_BOTTOM;
- // sort vertices left to right
- if (face->tvlist[v2].x < face->tvlist[v1].x)
- {SWAP(v1,v2,temp);}
- } // end if
- else
- {
- // must be a general triangle
- tri_type = TRI_TYPE_GENERAL;
- } // end else
- // extract vertices for processing, now that we have order
- x0 = (int)(face->tvlist[v0].x+0.0);
- y0 = (int)(face->tvlist[v0].y+0.0);
- tz0 = (int)(face->tvlist[v0].z+0.5);
- x1 = (int)(face->tvlist[v1].x+0.0);
- y1 = (int)(face->tvlist[v1].y+0.0);
- tz1 = (int)(face->tvlist[v1].z+0.5);
- x2 = (int)(face->tvlist[v2].x+0.0);
- y2 = (int)(face->tvlist[v2].y+0.0);
- tz2 = (int)(face->tvlist[v2].z+0.5);
- // degenerate triangle
- if ( ((x0 == x1) && (x1 == x2)) || ((y0 == y1) && (y1 == y2)))
- return;
- // extract constant color
- color = face->lit_color[0];
- // set interpolation restart value
- yrestart = y1;
- // what kind of triangle
- if (tri_type & TRI_TYPE_FLAT_MASK)
- {
- if (tri_type == TRI_TYPE_FLAT_TOP)
- {
- // compute all deltas
- dy = (y2 - y0);
- dxdyl = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;
- dxdyr = ((x2 - x1) << FIXP16_SHIFT)/dy;
- dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dy + (x1 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x1 << FIXP16_SHIFT);
- zl = (tz0 << FIXP16_SHIFT);
- zr = (tz1 << FIXP16_SHIFT);
- // set starting y
- ystart = y0;
- } // end else
- } // end if flat top
- else
- {
- // must be flat bottom
- // compute all deltas
- dy = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dy;
- dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy;
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- zl = (tz0 << FIXP16_SHIFT);
- zr = (tz0 << FIXP16_SHIFT);
- // set starting y
- ystart = y0;
- } // end else
- } // end else flat bottom
- // test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi<=yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v,w interpolants
- zi = zl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- zi+=dx*dz;
- // reset vars
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi<=xend; xi++)
- {
- // write thru z buffer
- // write textel assume 5.6.5
- screen_ptr[xi] = color;
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate u,v,w,z
- zi+=dz;
- } // end for xi
- // interpolate z,x along right and left edge
- xl+=dxdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance z-buffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if clip
- else
- {
- // non-clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi<=yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v,w interpolants
- zi = zl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi<=xend; xi++)
- {
- // write thru z buffer
- // write textel assume 5.6.5
- screen_ptr[xi] = color;
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate z
- zi+=dz;
- } // end for xi
- // interpolate x,z along right and left edge
- xl+=dxdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance z-buffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if non-clipped
- } // end if
- else
- if (tri_type==TRI_TYPE_GENERAL)
- {
- // first test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // pre-test y clipping status
- if (y1 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
- // compute overclip
- dyr = (min_clip_y - y0);
- dyl = (min_clip_y - y1);
- // computer new LHS starting values
- xl = dxdyl*dyl + (x1 << FIXP16_SHIFT);
- zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dyr + (x0 << FIXP16_SHIFT);
- zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr > dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- if (y0 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- {
- // no initial y clipping
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
- // no clipping y
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- zl = (tz0 << FIXP16_SHIFT);
- zr = (tz0 << FIXP16_SHIFT);
- // set starting y
- ystart = y0;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end else
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi<=yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for z interpolants
- zi = zl + FIXP16_ROUND_UP;
- // compute z interpolants
- if ((dx = (xend - xstart))>0)
- {
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- zi+=dx*dz;
- // set x to left clip edge
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi<=xend; xi++)
- {
- // write thru z buffer
- // write textel assume 5.6.5
- screen_ptr[xi] = color;
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate z
- zi+=dz;
- } // end for xi
- // interpolate z,x along right and left edge
- xl+=dxdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance z-buffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- zl = (tz1 << FIXP16_SHIFT);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- zr = (tz2 << FIXP16_SHIFT);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end if
- else
- {
- // no x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi<=yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v,w,z interpolants
- zi = zl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi<=xend; xi++)
- {
- // write thru z buffer
- // write textel assume 5.6.5
- screen_ptr[xi] = color;
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate z
- zi+=dz;
- } // end for xi
- // interpolate x,z along right and left edge
- xl+=dxdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance z-buffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- zl = (tz1 << FIXP16_SHIFT);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- zr = (tz2 << FIXP16_SHIFT);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end else
- } // end if
- } // end Draw_Triangle_2DWTZB_16
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_Gouraud_TriangleWTZB2_16(POLYF4DV2_PTR face, // ptr to face
- UCHAR *_dest_buffer, // pointer to video buffer
- int mem_pitch, // bytes per line, 320, 640 etc.
- UCHAR *_zbuffer, // pointer to z-buffer
- int zpitch) // bytes per line of zbuffer
- {
- // this function draws a gouraud shaded polygon, based on the affine texture mapper, instead
- // of interpolating the texture coordinates, we simply interpolate the (R,G,B) values across
- // the polygons, I simply needed at another interpolant, I have mapped u->red, v->green, w->blue
- // also a new interpolant for z buffering has been added
- int v0=0,
- v1=1,
- v2=2,
- temp=0,
- tri_type = TRI_TYPE_NONE,
- irestart = INTERP_LHS;
- int dx,dy,dyl,dyr, // general deltas
- u,v,w,z,
- du,dv,dw,dz,
- xi,yi, // the current interpolated x,y
- ui,vi,wi,zi, // the current interpolated u,v,w,z
- index_x,index_y, // looping vars
- x,y, // hold general x,y
- xstart,
- xend,
- ystart,
- yrestart,
- yend,
- xl,
- dxdyl,
- xr,
- dxdyr,
- dudyl,
- ul,
- dvdyl,
- vl,
- dwdyl,
- wl,
- dzdyl,
- zl,
- dudyr,
- ur,
- dvdyr,
- vr,
- dwdyr,
- wr,
- dzdyr,
- zr;
- int x0,y0,tu0,tv0,tw0,tz0, // cached vertices
- x1,y1,tu1,tv1,tw1,tz1,
- x2,y2,tu2,tv2,tw2,tz2;
- int r_base0, g_base0, b_base0,
- r_base1, g_base1, b_base1,
- r_base2, g_base2, b_base2;
- USHORT *screen_ptr = NULL,
- *screen_line = NULL,
- *textmap = NULL,
- *dest_buffer = (USHORT *)_dest_buffer;
- UINT *z_ptr = NULL,
- *zbuffer = (UINT *)_zbuffer;
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // adjust memory pitch to words, divide by 2
- mem_pitch >>=1;
- // adjust zbuffer pitch for 32 bit alignment
- zpitch >>= 2;
- // apply fill convention to coordinates
- face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
- face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
- face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
- face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
- face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
- face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
- // first trivial clipping rejection tests
- if (((face->tvlist[0].y < min_clip_y) &&
- (face->tvlist[1].y < min_clip_y) &&
- (face->tvlist[2].y < min_clip_y)) ||
- ((face->tvlist[0].y > max_clip_y) &&
- (face->tvlist[1].y > max_clip_y) &&
- (face->tvlist[2].y > max_clip_y)) ||
- ((face->tvlist[0].x < min_clip_x) &&
- (face->tvlist[1].x < min_clip_x) &&
- (face->tvlist[2].x < min_clip_x)) ||
- ((face->tvlist[0].x > max_clip_x) &&
- (face->tvlist[1].x > max_clip_x) &&
- (face->tvlist[2].x > max_clip_x)))
- return;
- // sort vertices
- if (face->tvlist[v1].y < face->tvlist[v0].y)
- {SWAP(v0,v1,temp);}
- if (face->tvlist[v2].y < face->tvlist[v0].y)
- {SWAP(v0,v2,temp);}
- if (face->tvlist[v2].y < face->tvlist[v1].y)
- {SWAP(v1,v2,temp);}
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y))
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_TOP;
- // sort vertices left to right
- if (face->tvlist[v1].x < face->tvlist[v0].x)
- {SWAP(v0,v1,temp);}
- } // end if
- else
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v1].y, face->tvlist[v2].y) )
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_BOTTOM;
- // sort vertices left to right
- if (face->tvlist[v2].x < face->tvlist[v1].x)
- {SWAP(v1,v2,temp);}
- } // end if
- else
- {
- // must be a general triangle
- tri_type = TRI_TYPE_GENERAL;
- } // end else
- // assume 5.6.5 format -- sorry!
- // we can't afford a function call in the inner loops, so we must write
- // two hard coded versions, if we want support for both 5.6.5, and 5.5.5
- _RGB565FROM16BIT(face->lit_color[v0], &r_base0, &g_base0, &b_base0);
- _RGB565FROM16BIT(face->lit_color[v1], &r_base1, &g_base1, &b_base1);
- _RGB565FROM16BIT(face->lit_color[v2], &r_base2, &g_base2, &b_base2);
- // scale to 8 bit
- r_base0 <<= 3;
- g_base0 <<= 2;
- b_base0 <<= 3;
- // scale to 8 bit
- r_base1 <<= 3;
- g_base1 <<= 2;
- b_base1 <<= 3;
- // scale to 8 bit
- r_base2 <<= 3;
- g_base2 <<= 2;
- b_base2 <<= 3;
- // extract vertices for processing, now that we have order
- x0 = (int)(face->tvlist[v0].x+0.0);
- y0 = (int)(face->tvlist[v0].y+0.0);
- tz0 = (int)(face->tvlist[v0].z+0.5);
- tu0 = r_base0;
- tv0 = g_base0;
- tw0 = b_base0;
- x1 = (int)(face->tvlist[v1].x+0.0);
- y1 = (int)(face->tvlist[v1].y+0.0);
- tz1 = (int)(face->tvlist[v1].z+0.5);
- tu1 = r_base1;
- tv1 = g_base1;
- tw1 = b_base1;
- x2 = (int)(face->tvlist[v2].x+0.0);
- y2 = (int)(face->tvlist[v2].y+0.0);
- tz2 = (int)(face->tvlist[v2].z+0.5);
- tu2 = r_base2;
- tv2 = g_base2;
- tw2 = b_base2;
- // degenerate triangle
- if ( ((x0 == x1) && (x1 == x2)) || ((y0 == y1) && (y1 == y2)))
- return;
- // set interpolation restart value
- yrestart = y1;
- // what kind of triangle
- if (tri_type & TRI_TYPE_FLAT_MASK)
- {
- if (tri_type == TRI_TYPE_FLAT_TOP)
- {
- // compute all deltas
- dy = (y2 - y0);
- dxdyl = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;
- dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;
- dwdyl = ((tw2 - tw0) << FIXP16_SHIFT)/dy;
- dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;
- dxdyr = ((x2 - x1) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;
- dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;
- dwdyr = ((tw2 - tw1) << FIXP16_SHIFT)/dy;
- dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dy + (x1 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
- wr = dwdyr*dy + (tw1 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x1 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- wl = (tw0 << FIXP16_SHIFT);
- zl = (tz0 << FIXP16_SHIFT);
- ur = (tu1 << FIXP16_SHIFT);
- vr = (tv1 << FIXP16_SHIFT);
- wr = (tw1 << FIXP16_SHIFT);
- zr = (tz1 << FIXP16_SHIFT);
- // set starting y
- ystart = y0;
- } // end else
- } // end if flat top
- else
- {
- // must be flat bottom
- // compute all deltas
- dy = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;
- dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dy;
- dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy;
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;
- dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dy;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
- wr = dwdyr*dy + (tw0 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- wl = (tw0 << FIXP16_SHIFT);
- zl = (tz0 << FIXP16_SHIFT);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- wr = (tw0 << FIXP16_SHIFT);
- zr = (tz0 << FIXP16_SHIFT);
- // set starting y
- ystart = y0;
- } // end else
- } // end else flat bottom
- // test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v,w interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- wi = wl + FIXP16_ROUND_UP;
- zi = zl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dw = (wr - wl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dw = (wr - wl);
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- wi+=dx*dw;
- zi+=dx*dz;
- // reset vars
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // write thru z buffer always
- // write textel assume 5.6.5
- screen_ptr[xi] = ((ui >> (FIXP16_SHIFT+3)) << 11) +
- ((vi >> (FIXP16_SHIFT+2)) << 5) +
- (wi >> (FIXP16_SHIFT+3));
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate u,v,w,z
- ui+=du;
- vi+=dv;
- wi+=dw;
- zi+=dz;
- } // end for xi
- // interpolate u,v,w,z,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance z-buffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if clip
- else
- {
- // non-clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v,w interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- wi = wl + FIXP16_ROUND_UP;
- zi = zl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dw = (wr - wl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dw = (wr - wl);
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // write thru z buffer always
- // write textel assume 5.6.5
- screen_ptr[xi] = ((ui >> (FIXP16_SHIFT+3)) << 11) +
- ((vi >> (FIXP16_SHIFT+2)) << 5) +
- (wi >> (FIXP16_SHIFT+3));
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate u,v,w,z
- ui+=du;
- vi+=dv;
- wi+=dw;
- zi+=dz;
- } // end for xi
- // interpolate u,v,w,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance z-buffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if non-clipped
- } // end if
- else
- if (tri_type==TRI_TYPE_GENERAL)
- {
- // first test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // pre-test y clipping status
- if (y1 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
- // compute overclip
- dyr = (min_clip_y - y0);
- dyl = (min_clip_y - y1);
- // computer new LHS starting values
- xl = dxdyl*dyl + (x1 << FIXP16_SHIFT);
- ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
- vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
- wl = dwdyl*dyl + (tw1 << FIXP16_SHIFT);
- zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dyr + (x0 << FIXP16_SHIFT);
- ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
- wr = dwdyr*dyr + (tw0 << FIXP16_SHIFT);
- zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr > dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dwdyl,dwdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(wl,wr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tw1,tw2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- if (y0 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
- wr = dwdyr*dy + (tw0 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dwdyl,dwdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(wl,wr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tw1,tw2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- {
- // no initial y clipping
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
- // no clipping y
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- wl = (tw0 << FIXP16_SHIFT);
- zl = (tz0 << FIXP16_SHIFT);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- wr = (tw0 << FIXP16_SHIFT);
- zr = (tz0 << FIXP16_SHIFT);
- // set starting y
- ystart = y0;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dwdyl,dwdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(wl,wr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tw1,tw2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end else
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v,w interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- wi = wl + FIXP16_ROUND_UP;
- zi = zl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dw = (wr - wl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dw = (wr - wl);
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- wi+=dx*dw;
- zi+=dx*dz;
- // set x to left clip edge
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // write thru z buffer always
- // write textel assume 5.6.5
- screen_ptr[xi] = ((ui >> (FIXP16_SHIFT+3)) << 11) +
- ((vi >> (FIXP16_SHIFT+2)) << 5) +
- (wi >> (FIXP16_SHIFT+3));
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate u,v,w,z
- ui+=du;
- vi+=dv;
- wi+=dw;
- zi+=dz;
- } // end for xi
- // interpolate u,v,w,z,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance z-buffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- wl = (tw1 << FIXP16_SHIFT);
- zl = (tz1 << FIXP16_SHIFT);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- wr = (tw2 << FIXP16_SHIFT);
- zr = (tz2 << FIXP16_SHIFT);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end if
- else
- {
- // no x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v,w,z interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- wi = wl + FIXP16_ROUND_UP;
- zi = zl + FIXP16_ROUND_UP;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dw = (wr - wl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dw = (wr - wl);
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // write thru z buffer always
- // write textel assume 5.6.5
- screen_ptr[xi] = ((ui >> (FIXP16_SHIFT+3)) << 11) +
- ((vi >> (FIXP16_SHIFT+2)) << 5) +
- (wi >> (FIXP16_SHIFT+3));
- // update z-buffer
- z_ptr[xi] = zi;
- // interpolate u,v,w,z
- ui+=du;
- vi+=dv;
- wi+=dw;
- zi+=dz;
- } // end for xi
- // interpolate u,v,w,x,z along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance z-buffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dwdyl = ((tw2 - tw1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- wl = (tw1 << FIXP16_SHIFT);
- zl = (tz1 << FIXP16_SHIFT);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- wl+=dwdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;
- dwdyr = ((tw1 - tw2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- wr = (tw2 << FIXP16_SHIFT);
- zr = (tz2 << FIXP16_SHIFT);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- wr+=dwdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end else
- } // end if
- } // end Draw_Gouraud_TriangleWTZB2_16
- ///////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- void BHV_Reset_Tree(BHV_NODEV1_PTR bhv_tree)
- {
- // this function simply resets all of the culled flags in the root of the
- // tree which will enable the entire tree as visible
- for (int iobject = 0; iobject < bhv_tree->num_objects; iobject++)
- {
- // reset the culled flag
- RESET_BIT(bhv_tree->objects[iobject]->state, OBJECT4DV2_STATE_CULLED);
- } // end if
- } // end BHV_Reset_Tree
- //////////////////////////////////////////////////////////////////////////////
- int BHV_FrustrumCull(BHV_NODEV1_PTR bhv_tree, // the root of the BHV
- CAM4DV1_PTR cam, // camera to cull relative to
- int cull_flags) // clipping planes to consider
- {
- // NOTE: is matrix based
- // this function culls the BHV from the viewing
- // frustrum by using the sent camera information and
- // the cull_flags determine what axes culling should take place
- // x, y, z or all which is controlled by ORing the flags
- // together. as the BHV is culled the state information in each node is
- // modified, so rendering functions can refer to it
- // test for valid BHV and camera
- if (!bhv_tree || !cam)
- return(0);
- // we need to walk the tree from top to bottom culling
- // step 1: transform the center of the nodes bounding
- // sphere into camera space
- POINT4D sphere_pos; // hold result of transforming center of bounding sphere
- // transform point
- Mat_Mul_VECTOR4D_4X4(&bhv_tree->pos, &cam->mcam, &sphere_pos);
- // step 2: based on culling flags remove the object
- if (cull_flags & CULL_OBJECT_Z_PLANE)
- {
- // cull only based on z clipping planes
- // test far plane
- if ( ((sphere_pos.z - bhv_tree->radius.z) > cam->far_clip_z) ||
- ((sphere_pos.z + bhv_tree->radius.z) < cam->near_clip_z) )
- {
- // this entire node is culled, so we need to set the culled flag
- // for every object
- for (int iobject = 0; iobject < bhv_tree->num_objects; iobject++)
- {
- SET_BIT(bhv_tree->objects[iobject]->state, OBJECT4DV2_STATE_CULLED);
- } // end for iobject
- #if 0
- Write_Error("n[ZBHV p(%f, %f, %f) r(%f) #objs(%d)]", bhv_tree->pos.x,
- bhv_tree->pos.y,
- bhv_tree->pos.z,
- bhv_tree->radius.x,
- bhv_tree->num_objects);
- #endif
- // this node was visited and culled
- bhv_nodes_visited++;
- return(1);
- } // end if
- } // end if
- if (cull_flags & CULL_OBJECT_X_PLANE)
- {
- // cull only based on x clipping planes
- // we could use plane equations, but simple similar triangles
- // is easier since this is really a 2D problem
- // if the view volume is 90 degrees the the problem is trivial
- // buts lets assume its not
- // test the the right and left clipping planes against the leftmost and rightmost
- // points of the bounding sphere
- float z_test = (0.5)*cam->viewplane_width*sphere_pos.z/cam->view_dist;
- if ( ((sphere_pos.x - bhv_tree->radius.x) > z_test) || // right side
- ((sphere_pos.x + bhv_tree->radius.x) < -z_test) ) // left side, note sign change
- {
- // this entire node is culled, so we need to set the culled flag
- // for every object
- for (int iobject = 0; iobject < bhv_tree->num_objects; iobject++)
- {
- SET_BIT(bhv_tree->objects[iobject]->state, OBJECT4DV2_STATE_CULLED);
- } // end for iobject
- #if 0
- Write_Error("n[XBHV p(%f, %f, %f) r(%f) #objs(%d)]", bhv_tree->pos.x,
- bhv_tree->pos.y,
- bhv_tree->pos.z,
- bhv_tree->radius.x, bhv_tree->num_objects);
- #endif
- // this node was visited and culled
- bhv_nodes_visited++;
- return(1);
- } // end if
- } // end if
- if (cull_flags & CULL_OBJECT_Y_PLANE)
- {
- // cull only based on y clipping planes
- // we could use plane equations, but simple similar triangles
- // is easier since this is really a 2D problem
- // if the view volume is 90 degrees the the problem is trivial
- // buts lets assume its not
- // test the the top and bottom clipping planes against the bottommost and topmost
- // points of the bounding sphere
- float z_test = (0.5)*cam->viewplane_height*sphere_pos.z/cam->view_dist;
- if ( ((sphere_pos.y - bhv_tree->radius.y) > z_test) || // top side
- ((sphere_pos.y + bhv_tree->radius.y) < -z_test) ) // bottom side, note sign change
- {
- // this entire node is culled, so we need to set the culled flag
- // for every object
- for (int iobject = 0; iobject < bhv_tree->num_objects; iobject++)
- {
- SET_BIT(bhv_tree->objects[iobject]->state, OBJECT4DV2_STATE_CULLED);
- } // end for iobject
- #if 0
- Write_Error("n[YBHV p(%f, %f, %f) r(%f) #objs(%d)]", bhv_tree->pos.x,
- bhv_tree->pos.y,
- bhv_tree->pos.z,
- bhv_tree->radius.x,
- bhv_tree->num_objects);
- #endif
- // this node was visited and culled
- bhv_nodes_visited++;
- return(1);
- } // end if
- } // end if
- // at this point, we have concluded that this BHV node is too large
- // to cull, so we need to traverse the children and see if we can cull them
- for (int ichild = 0; ichild < bhv_tree->num_children; ichild++)
- {
- // recursively call..
- BHV_FrustrumCull(bhv_tree->links[ichild], cam, cull_flags);
- // here's where we can optimize by tracking the total number
- // of objects culled and we can exit early if all the objects
- // are already culled...
- } // end ichild
- // return failure to cull anything!
- return(0);
- } // end BHV_FrustrumCull
- //////////////////////////////////////////////////////////////////////////////
- void BHV_Build_Tree(BHV_NODEV1_PTR bhv_tree, // tree to build
- OBJ_CONTAINERV1_PTR bhv_objects, // ptr to all objects in intial scene
- int num_objects, // number of objects in initial scene
- int level, // recursion level
- int num_divisions, // number of division per level
- int universe_radius) // initial size of universe to enclose
- {
- // this function builds the BHV tree using a divide and conquer
- // divisioning algorithm to cluster the objects together
- Write_Error("nEntering BHV function...");
- // are we building root?
- if (level == 0)
- {
- Write_Error("nlevel = 0");
- // position at (0,0,0)
- bhv_tree->pos.x = 0;
- bhv_tree->pos.y = 0;
- bhv_tree->pos.z = 0;
- bhv_tree->pos.w = 1;
- // set radius of node to maximum
- bhv_tree->radius.x = universe_radius;
- bhv_tree->radius.y = universe_radius;
- bhv_tree->radius.z = universe_radius;
- bhv_tree->radius.w = 1;
- Write_Error("nnode pos[%f, %f, %f], r[%f, %f, %f]",
- bhv_tree->pos.x,bhv_tree->pos.y,bhv_tree->pos.z,
- bhv_tree->radius.x,bhv_tree->radius.y,bhv_tree->radius.z);
- // build root, simply add all objects to root
- for (int index = 0; index < num_objects; index++)
- {
- // make sure object is not culled
- if (!(bhv_objects[index].state & OBJECT4DV2_STATE_CULLED))
- {
- bhv_tree->objects[bhv_tree->num_objects++] = (OBJ_CONTAINERV1_PTR)&bhv_objects[index];
- } // end if
- } // end for index
- // at this point all the objects have been inserted into the root node
- // and num_objects is set to the number of objects
- // enable the node
- bhv_tree->state = 1;
- bhv_tree->attr = 0;
- // and set all links to NULL
- for (int ilink = 0; ilink < MAX_BHV_PER_NODE; ilink++)
- bhv_tree->links[ilink] = NULL;
- // set the number of objects
- bhv_tree->num_objects = num_objects;
- Write_Error("nInserted %d objects into root node", bhv_tree->num_objects);
- Write_Error("nMaking recursive call with root node...");
- // done, so now allow recursion to build the rest of the tree
- BHV_Build_Tree(bhv_tree,
- bhv_objects,
- num_objects,
- 1,
- num_divisions,
- universe_radius);
- } // end if
- else
- {
- Write_Error("nEntering Level = %d > 0 block, number of objects = %d",level, bhv_tree->num_objects);
- // test for exit state
- if (bhv_tree->num_objects <= MIN_OBJECTS_PER_BHV_CELL)
- return;
- // building a child node (hard part)
- // we must take the current node and split it into a number of children nodes, and then
- // create a bvh for each child and then insert all the objects into each child
- // the for each child call the recursion again....
- // create 3D cell temp storage to track cells
- BHV_CELL cells[MAX_BHV_CELL_DIVISIONS][MAX_BHV_CELL_DIVISIONS][MAX_BHV_CELL_DIVISIONS];
- // find origin of bounding volume based on radius and center
- int x0 = bhv_tree->pos.x - bhv_tree->radius.x;
- int y0 = bhv_tree->pos.y - bhv_tree->radius.y;
- int z0 = bhv_tree->pos.z - bhv_tree->radius.z;
- // compute cell sizes on x,y,z axis
- float cell_size_x = 2*bhv_tree->radius.x / (float)num_divisions;
- float cell_size_y = 2*bhv_tree->radius.y / (float)num_divisions;
- float cell_size_z = 2*bhv_tree->radius.z / (float)num_divisions;
- Write_Error("ncell pos=(%d, %d, %d) size=(%f, %f, %f)", x0,y0,z0, cell_size_x, cell_size_y, cell_size_z);
- int cell_x, cell_y, cell_z; // used to locate cell in 3D matrix
- // clear cell memory out
- memset(cells, 0, sizeof(cells));
- // now partition space up into num_divisions (must be < MAX_BHV_CELL_DIVISIONS)
- // and then sort each object's center into each cell of the 3D sorting matrix
- for (int obj_index = 0; obj_index < bhv_tree->num_objects; obj_index++)
- {
- // compute cell position in temp sorting matrix
- cell_x = (bhv_tree->objects[obj_index]->pos.x - x0)/cell_size_x;
- cell_y = (bhv_tree->objects[obj_index]->pos.y - y0)/cell_size_y;
- cell_z = (bhv_tree->objects[obj_index]->pos.z - z0)/cell_size_z;
- // insert this object into list
- cells[cell_x][cell_y][cell_z].obj_list[ cells[cell_x][cell_y][cell_z].num_objects ] = bhv_tree->objects[obj_index];
- Write_Error("ninserting object %d located at (%f, %f, %f) into cell (%d, %d, %d)", obj_index,
- bhv_tree->objects[obj_index]->pos.x,
- bhv_tree->objects[obj_index]->pos.y,
- bhv_tree->objects[obj_index]->pos.z,
- cell_x, cell_y, cell_z);
- // increment number of objects in this cell
- if (++cells[cell_x][cell_y][cell_z].num_objects >= MAX_OBJECTS_PER_BHV_CELL)
- cells[cell_x][cell_y][cell_z].num_objects = MAX_OBJECTS_PER_BHV_CELL-1;
- } // end for obj_index
- Write_Error("nEntering sorting section...");
- // now the 3D sorting matrix has all the information we need, the next step
- // is to create a BHV node for each non-empty
- for (int icell_x = 0; icell_x < num_divisions; icell_x++)
- {
- for (int icell_y = 0; icell_y < num_divisions; icell_y++)
- {
- for (int icell_z = 0; icell_z < num_divisions; icell_z++)
- {
- // are there any objects in this node?
- if ( cells[icell_x][icell_y][icell_z].num_objects > 0)
- {
- Write_Error("nCell %d, %d, %d contains %d objects", icell_x, icell_y, icell_z,
- cells[icell_x][icell_y][icell_z].num_objects);
- Write_Error("nCreating child node...");
- // create a node and set the link to it
- bhv_tree->links[ bhv_tree->num_children ] = (BHV_NODEV1_PTR)malloc(sizeof(BHV_NODEV1));
- // zero node out
- memset(bhv_tree->links[ bhv_tree->num_children ], 0, sizeof(BHV_NODEV1) );
- // set the node up
- BHV_NODEV1_PTR curr_node = bhv_tree->links[ bhv_tree->num_children ];
- // position
- curr_node->pos.x = (icell_x*cell_size_x + cell_size_x/2) + x0;
- curr_node->pos.y = (icell_y*cell_size_y + cell_size_y/2) + y0;
- curr_node->pos.z = (icell_z*cell_size_z + cell_size_z/2) + z0;
- curr_node->pos.w = 1;
- // radius is cell_size / 2
- curr_node->radius.x = cell_size_x/2;
- curr_node->radius.y = cell_size_y/2;
- curr_node->radius.z = cell_size_z/2;
- curr_node->radius.w = 1;
- // set number of objects
- curr_node->num_objects = cells[icell_x][icell_y][icell_z].num_objects;
- // set num children
- curr_node->num_children = 0;
- // set state and attr
- curr_node->state = 1; // enable node
- curr_node->attr = 0;
- // now insert each object into this node's object list
- for (int icell_index = 0; icell_index < curr_node->num_objects; icell_index++)
- {
- curr_node->objects[icell_index] = cells[icell_x][icell_y][icell_z].obj_list[icell_index];
- } // end for icell_index
- Write_Error("nChild node pos=(%f, %f, %f), r=(%f, %f, %f)",
- curr_node->pos.x,curr_node->pos.y,curr_node->pos.z,
- curr_node->radius.x,curr_node->radius.y,curr_node->radius.z);
- // increment number of children of parent
- bhv_tree->num_children++;
- } // end if
- } // end for icell_z
- } // end for icell_y
- } // end for icell_x
- Write_Error("nParent has %d children..", bhv_tree->num_children);
- // now for each child build a BHV
- for (int inode = 0; inode < bhv_tree->num_children; inode++)
- {
- Write_Error("nfor Level %d, creating child %d", level, inode);
- BHV_Build_Tree(bhv_tree->links[inode],
- NULL, // unused now
- NULL, // unused now
- level+1,
- num_divisions,
- universe_radius);
- } // end if
- } // end else level > 0
- Write_Error("nExiting BHV...level = %d", level);
- } // end BHV_Build_Tree