t3dlib10.cpp
资源名称:Source.rar [点击查看]
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:1310k
源码类别:
游戏
开发平台:
Visual C++
- // compute all deltas
- dy = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;
- dvdyl = ((tv1 - tv0) << 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;
- 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);
- 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);
- 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);
- zl = (tz0 << FIXP16_SHIFT);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << 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 interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + 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;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- 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;
- 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++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // write textel
- // get textel first
- textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // extract rgb components
- r_textel = ((textel >> 11) );
- g_textel = ((textel >> 5) & 0x3f);
- b_textel = (textel & 0x1f);
- // modulate textel with lit background color
- r_textel*=r_base;
- g_textel*=g_base;
- b_textel*=b_base;
- // 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] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer 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 interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + 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;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // write textel
- // get textel first
- textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // extract rgb components
- r_textel = ((textel >> 11) );
- g_textel = ((textel >> 5) & 0x3f);
- b_textel = (textel & 0x1f);
- // modulate textel with lit background color
- r_textel*=r_base;
- g_textel*=g_base;
- b_textel*=b_base;
- // 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] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // 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;
- 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;
- 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);
- 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);
- 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(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,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;
- 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;
- 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);
- 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);
- 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(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,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;
- 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;
- 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);
- zl = (tz0 << FIXP16_SHIFT);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << 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(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,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 interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + 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;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- 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;
- 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++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // write textel
- // get textel first
- textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // extract rgb components
- r_textel = ((textel >> 11) );
- g_textel = ((textel >> 5) & 0x3f);
- b_textel = (textel & 0x1f);
- // modulate textel with lit background color
- r_textel*=r_base;
- g_textel*=g_base;
- b_textel*=b_base;
- // 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] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // 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;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- zl = (tz1 << FIXP16_SHIFT);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- 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;
- dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- zr = (tz2 << FIXP16_SHIFT);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- 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,z interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + 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;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // write textel
- // get textel first
- textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // extract rgb components
- r_textel = ((textel >> 11) );
- g_textel = ((textel >> 5) & 0x3f);
- b_textel = (textel & 0x1f);
- // modulate textel with lit background color
- r_textel*=r_base;
- g_textel*=g_base;
- b_textel*=b_base;
- // 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] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // 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;
- dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- zl = (tz1 << FIXP16_SHIFT);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- 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;
- dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- zr = (tz2 << FIXP16_SHIFT);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end else
- } // end if
- } // end Draw_Textured_TriangleFSZB_Alpha16
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_Textured_TriangleGSZB_Alpha16(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
- int alpha)
- {
- // this function draws a textured gouraud shaded polygon, and z bufferedbased on the affine texture mapper,
- // we simply interpolate the (R,G,B) values across the polygons along with the texture coordinates
- // and then modulate to get the final color
- 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, s,t,
- du,dv,dw,dz, ds, dt,
- xi,yi, // the current interpolated x,y
- ui,vi,wi,zi, si, ti, // the current interpolated u,v
- 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,
- dsdyl,
- sl,
- dtdyl,
- tl,
- dudyr,
- ur,
- dvdyr,
- vr,
- dwdyr,
- wr,
- dzdyr,
- zr,
- dsdyr,
- sr,
- dtdyr,
- tr;
- int x0,y0,tu0,tv0,tw0, tz0, ts0,tt0, // cached vertices
- x1,y1,tu1,tv1,tw1, tz1, ts1,tt1,
- x2,y2,tu2,tv2,tw2, tz2, ts2,tt2;
- int r_base0, g_base0, b_base0,
- r_base1, g_base1, b_base1,
- r_base2, g_base2, b_base2;
- UINT r_textel, g_textel, b_textel;
- USHORT textel;
- 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
- // extract texture map
- textmap = (USHORT *)face->texture->buffer;
- // extract base 2 of texture width
- int texture_shift2 = logbase2ofx[face->texture->width];
- // 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.0);
- face->tvlist[0].y = (int)(face->tvlist[0].y+0.0);
- face->tvlist[1].x = (int)(face->tvlist[1].x+0.0);
- face->tvlist[1].y = (int)(face->tvlist[1].y+0.0);
- face->tvlist[2].x = (int)(face->tvlist[2].x+0.0);
- face->tvlist[2].y = (int)(face->tvlist[2].y+0.0);
- // 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);
- ts0 = (int)(face->tvlist[v0].u0);
- tt0 = (int)(face->tvlist[v0].v0);
- 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);
- ts1 = (int)(face->tvlist[v1].u0);
- tt1 = (int)(face->tvlist[v1].v0);
- 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);
- ts2 = (int)(face->tvlist[v2].u0);
- tt2 = (int)(face->tvlist[v2].v0);
- tu2 = r_base2;
- tv2 = g_base2;
- tw2 = b_base2;
- // degenerate triangle
- if ( ((x0 == x1) && (x1 == x2)) || ((y0 == y1) && (y1 == y2)))
- return;
- // assign both source1 and source2 alpha tables based on polygon alpha level
- USHORT *alpha_table_src1 = (USHORT *)&rgb_alpha_table[(NUM_ALPHA_LEVELS-1) - alpha][0];
- USHORT *alpha_table_src2 = (USHORT *)&rgb_alpha_table[alpha][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;
- dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;
- dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;
- dwdyl = ((tw2 - tw0) << FIXP16_SHIFT)/dy;
- dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;
- dsdyl = ((ts2 - ts0) << FIXP16_SHIFT)/dy;
- dtdyl = ((tt2 - tt0) << 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;
- dsdyr = ((ts2 - ts1) << FIXP16_SHIFT)/dy;
- dtdyr = ((tt2 - tt1) << 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);
- sl = dsdyl*dy + (ts0 << FIXP16_SHIFT);
- tl = dtdyl*dy + (tt0 << 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);
- sr = dsdyr*dy + (ts1 << FIXP16_SHIFT);
- tr = dtdyr*dy + (tt1 << 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);
- sl = (ts0 << FIXP16_SHIFT);
- tl = (tt0 << FIXP16_SHIFT);
- ur = (tu1 << FIXP16_SHIFT);
- vr = (tv1 << FIXP16_SHIFT);
- wr = (tw1 << FIXP16_SHIFT);
- zr = (tz1 << FIXP16_SHIFT);
- sr = (ts1 << FIXP16_SHIFT);
- tr = (tt1 << 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;
- dsdyl = ((ts1 - ts0) << FIXP16_SHIFT)/dy;
- dtdyl = ((tt1 - tt0) << 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;
- dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dy;
- dtdyr = ((tt2 - tt0) << 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);
- 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;
- } // 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);
- 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;
- } // 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;
- 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;
- // 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 textel assume 5.6.5
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // 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] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((b_textel >> (FIXP16_SHIFT+8)) +
- ((g_textel >> (FIXP16_SHIFT+8)) << 5) +
- ((r_textel >> (FIXP16_SHIFT+8)) << 11))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // 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 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;
- 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
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // 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] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((b_textel >> (FIXP16_SHIFT+8)) +
- ((g_textel >> (FIXP16_SHIFT+8)) << 5) +
- ((r_textel >> (FIXP16_SHIFT+8)) << 11))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // 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
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // 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] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((b_textel >> (FIXP16_SHIFT+8)) +
- ((g_textel >> (FIXP16_SHIFT+8)) << 5) +
- ((r_textel >> (FIXP16_SHIFT+8)) << 11))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // 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
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // 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] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((b_textel >> (FIXP16_SHIFT+8)) +
- ((g_textel >> (FIXP16_SHIFT+8)) << 5) +
- ((r_textel >> (FIXP16_SHIFT+8)) << 11))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // 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_TriangleGSZB_Alpha16
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_Gouraud_TriangleZB_Alpha16(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
- int alpha)
- {
- // 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;
- // assign both source1 and source2 alpha tables based on polygon alpha level
- USHORT *alpha_table_src1 = (USHORT *)&rgb_alpha_table[(NUM_ALPHA_LEVELS-1) - alpha][0];
- USHORT *alpha_table_src2 = (USHORT *)&rgb_alpha_table[alpha][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;
- 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++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // write textel assume 5.6.5
- screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((ui >> (FIXP16_SHIFT+3)) << 11) + ((vi >> (FIXP16_SHIFT+2)) << 5) + (wi >> (FIXP16_SHIFT+3))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // 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++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // write textel 5.6.5
- screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((ui >> (FIXP16_SHIFT+3)) << 11) + ((vi >> (FIXP16_SHIFT+2)) << 5) + (wi >> (FIXP16_SHIFT+3))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // 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++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // write textel assume 5.6.5
- screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((ui >> (FIXP16_SHIFT+3)) << 11) + ((vi >> (FIXP16_SHIFT+2)) << 5) + (wi >> (FIXP16_SHIFT+3))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // 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++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi < z_ptr[xi])
- {
- // write textel assume 5.6.5
- screen_ptr[xi] = alpha_table_src1[screen_ptr[xi]] +
- alpha_table_src2[((ui >> (FIXP16_SHIFT+3)) << 11) + ((vi >> (FIXP16_SHIFT+2)) << 5) + (wi >> (FIXP16_SHIFT+3))];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // 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_TriangleZB_Alpha16
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_RENDERLIST4DV2_SolidZB_Alpha16(RENDERLIST4DV2_PTR rend_list,
- UCHAR *video_buffer,
- int lpitch,
- UCHAR *zbuffer,
- int zpitch,
- int alpha_override)
- {
- // 16-bit version
- // this function "executes" the render list or in other words
- // draws all the faces in the list, the function will call the
- // proper rasterizer based on the lighting model of the polygons
- // only call the alpha rasterizer for polys with the POLY4DV2_ATTR_TRANSPARENT
- // flag set
- POLYF4DV2 face; // temp face used to render polygon
- int alpha; // alpha of the face
- // at this point, all we have is a list of polygons and it's time
- // to draw them
- for (int poly=0; poly < rend_list->num_polys; poly++)
- {
- // render this polygon if and only if it's not clipped, not culled,
- // active, and visible, note however the concecpt of "backface" is
- // irrelevant in a wire frame engine though
- if (!(rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
- (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
- (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
- continue; // move onto next poly
- // test for alpha override
- if (alpha_override >= 0)
- {
- // set alpha to override value
- alpha = alpha_override;
- } // end if
- else
- {
- // extract alpha (even if there isn't any)
- alpha = ((rend_list->poly_ptrs[poly]->color & 0xff000000) >> 24);
- } // end else
- // need to test for textured first, since a textured poly can either
- // be emissive, or flat shaded, hence we need to call different
- // rasterizers
- if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
- {
- // set the vertices
- face.tvlist[0].x = (float)rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.tvlist[0].u0 = (float)rend_list->poly_ptrs[poly]->tvlist[0].u0;
- face.tvlist[0].v0 = (float)rend_list->poly_ptrs[poly]->tvlist[0].v0;
- face.tvlist[1].x = (float)rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.tvlist[1].u0 = (float)rend_list->poly_ptrs[poly]->tvlist[1].u0;
- face.tvlist[1].v0 = (float)rend_list->poly_ptrs[poly]->tvlist[1].v0;
- face.tvlist[2].x = (float)rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rend_list->poly_ptrs[poly]->tvlist[2].z;
- face.tvlist[2].u0 = (float)rend_list->poly_ptrs[poly]->tvlist[2].u0;
- face.tvlist[2].v0 = (float)rend_list->poly_ptrs[poly]->tvlist[2].v0;
- // assign the texture
- face.texture = rend_list->poly_ptrs[poly]->texture;
- // is this a plain emissive texture?
- if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
- {
- // draw the textured triangle as emissive
- if ((rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || alpha_override >=0)
- Draw_Textured_TriangleZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch, alpha);
- else
- Draw_Textured_TriangleZB2_16(&face, video_buffer, lpitch,zbuffer,zpitch);
- } // end if
- else
- if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT)
- {
- // draw as flat shaded
- face.lit_color[0] = rend_list->poly_ptrs[poly]->lit_color[0];
- // test for transparency
- if ((rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || alpha_override >=0)
- Draw_Textured_TriangleFSZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch, alpha);
- else
- Draw_Textured_TriangleFSZB2_16(&face, video_buffer, lpitch,zbuffer,zpitch);
- } // end else if
- else
- { // POLY4DV2_ATTR_SHADE_MODE_GOURAUD
- // must be gouraud POLY4DV2_ATTR_SHADE_MODE_GOURAUD
- face.lit_color[0] = rend_list->poly_ptrs[poly]->lit_color[0];
- face.lit_color[1] = rend_list->poly_ptrs[poly]->lit_color[1];
- face.lit_color[2] = rend_list->poly_ptrs[poly]->lit_color[2];
- // test for transparency
- if ((rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || alpha_override >=0)
- Draw_Textured_TriangleGSZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch,alpha);
- else
- Draw_Textured_TriangleGSZB_16(&face, video_buffer, lpitch,zbuffer,zpitch);
- } // end else
- } // end if
- else
- if ((rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) ||
- (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
- {
- // draw as constant shaded
- face.lit_color[0] = rend_list->poly_ptrs[poly]->lit_color[0];
- // set the vertices
- face.tvlist[0].x = (float)rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.tvlist[1].x = (float)rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.tvlist[2].x = (float)rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rend_list->poly_ptrs[poly]->tvlist[2].z;
- // draw the triangle with basic flat rasterizer
- // test for transparency
- if ((rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || alpha_override >=0)
- Draw_Triangle_2DZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch,alpha);
- else
- Draw_Triangle_2DZB_16(&face, video_buffer, lpitch,zbuffer,zpitch);
- } // end if
- else
- if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
- {
- // {andre take advantage of the data structures later..}
- // set the vertices
- face.tvlist[0].x = (float)rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.lit_color[0] = rend_list->poly_ptrs[poly]->lit_color[0];
- face.tvlist[1].x = (float)rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.lit_color[1] = rend_list->poly_ptrs[poly]->lit_color[1];
- face.tvlist[2].x = (float)rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rend_list->poly_ptrs[poly]->tvlist[2].z;
- face.lit_color[2] = rend_list->poly_ptrs[poly]->lit_color[2];
- // draw the gouraud shaded triangle
- // test for transparency
- if ((rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || alpha_override >=0)
- Draw_Gouraud_TriangleZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch,alpha);
- else
- Draw_Gouraud_TriangleZB2_16(&face, video_buffer, lpitch,zbuffer,zpitch);
- } // end if gouraud
- } // end for poly
- } // end Draw_RENDERLIST4DV2_SolidZB_Alpha16
- /////////////////////////////////////////////////////////////////////////////////////////////
- int RGB_Alpha_Table_Builder(int num_alpha_levels, // number of levels to create
- USHORT rgb_alpha_table[NUM_ALPHA_LEVELS][65536]) // lookup table
- {
- // this function creates an alpha lookup table, the purpose of the table is as
- // follows; when alpha blending two RGB values, one can't simply use the formula:
- // final = (alpha)*(source1RGB) + (1-alpha)*(source2RGB)
- // the reason of course is that the multiplication has to be carried out on R, G, B
- // separately, this we first have to extract out r,g,b from both sources, then multiply
- // both, then add the results, then build the result up and store it ! Ouch!
- // therefore, we can use a table to speed this up in some cases, so if we think of
- // the input RGB as a number and then let the table extract everything out and do the
- // multiplication by the alpha blending factor, then we save all that work and in the
- // end an alpha blend turns into two accesses, and an addition, so we avoid 6 multiplications
- // and all the shift. Of course, if the colors are already in r,g,b form already then
- // another approach may be better. In any case, the function works by creating a
- // table that consists of num_alpha_levels rows, each row consist of 65536 entries which
- // represents the scale value of that row times each of the 65536 colors in RGB format
- // also, the num_alpha_levels must be a power of two, so num_alpha_levels of 8 for example
- // will result in a table that has 8 rows, where the multiplier each row would be
- // 8/8, 7/8, 6/8..........1/8, 0/8 is the amount of source pixel to mix
- // first check the pointer
- if (!rgb_alpha_table)
- return(-1);
- int r,g,b; // used to scan colors out of rgbindex
- float alpha = 0;
- float delta_alpha = EPSILON_E6 + 1/((float)(num_alpha_levels-1));
- // we need num_alpha_level_rows
- for (int alpha_level = 0; alpha_level < num_alpha_levels; alpha_level++)
- {
- // there are 65536 RGB values we need to compute, assuming that we are in RGB: 4.4.4 format
- for (int rgbindex = 0; rgbindex < 65536; rgbindex++)
- {
- // extract r,g,b from rgbindex, assuming an encoding of 5.6.5
- _RGB565FROM16BIT(rgbindex, &r, &g, &b);
- // scale
- r = (int)( (float)r * (float)alpha );
- g = (int)( (float)g * (float)alpha );
- b = (int)( (float)b * (float)alpha );
- // build pixel back up and store
- rgb_alpha_table[alpha_level][rgbindex] = _RGB16BIT565(r,g,b);
- } // end for rgbindex
- // decrease alpha level
- alpha+=delta_alpha;
- } // end for row
- // return success
- return(1);
- } // end RGB_Alpha_Table_Builder
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- int Load_OBJECT4DV2_COB2(OBJECT4DV2_PTR obj, // pointer to object
- char *filename, // filename of Caligari COB file
- VECTOR4D_PTR scale, // initial scaling factors
- VECTOR4D_PTR pos, // initial position
- VECTOR4D_PTR rot, // initial rotations
- int vertex_flags, // flags to re-order vertices
- // and perform transforms
- int mipmap ) // mipmap enable flag
- // 0 means no mipmap, 1 means
- // generate mip map
- {
- // this function loads a Caligari TrueSpace .COB file object in off disk, additionally
- // it allows the caller to scale, position, and rotate the object
- // to save extra calls later for non-dynamic objects, note that this function
- // works with a OBJECT4DV2 which has support for textures, but not materials, etc,
- // however we will still parse out the material stuff and get them ready for the
- // next incarnation objects, so we can re-use this code to support those features
- // also, since this version IS going to read in the texture map and texture coordinates
- // we have a couple issues to think about, first COB format like absolute texture paths
- // we can't have that, so we will simple extract out ONLY the texture map bitmap name
- // and use the global texture path variable to build a real file path, also texture
- // coordinates are in 0..1 0..1 form, I still haven't decided if I want to use absolute
- // coordinates or 0..1 0..1, but right now the affine texture mapper uses
- // new version 2.0 supports alpha channel and mip mapping, if mipmap = 1 then the
- // loader will automatically mipmap the texture and then fix the object pointer and
- // all subsequent polygon texture pointers to point to the mipmap chain d=0 texture
- // pointer rather than directly to the texture, thus mipmapped objects
- // must be flagged and processed differently
- // create a parser object
- CPARSERV1 parser;
- char seps[16]; // seperators for token scanning
- char token_buffer[256]; // used as working buffer for token
- char *token; // pointer to next token
- int r,g,b; // working colors
- // cache for texture vertices
- VERTEX2DF texture_vertices[OBJECT4DV2_MAX_VERTICES];
- int num_texture_vertices = 0;
- MATRIX4X4 mat_local, // storage for local transform if user requests it in cob format
- mat_world; // " " for local to world " "
- // initialize matrices
- MAT_IDENTITY_4X4(&mat_local);
- MAT_IDENTITY_4X4(&mat_world);
- // Step 1: clear out the object and initialize it a bit
- memset(obj, 0, sizeof(OBJECT4DV2));
- // set state of object to active and visible
- obj->state = OBJECT4DV2_STATE_ACTIVE | OBJECT4DV2_STATE_VISIBLE;
- // set number of frames
- obj->num_frames = 1;
- obj->curr_frame = 0;
- obj->attr = OBJECT4DV2_ATTR_SINGLE_FRAME;
- // set position of object is caller requested position
- if (pos)
- {
- // set position of object
- obj->world_pos.x = pos->x;
- obj->world_pos.y = pos->y;
- obj->world_pos.z = pos->z;
- obj->world_pos.w = pos->w;
- } // end
- else
- {
- // set it to (0,0,0,1)
- obj->world_pos.x = 0;
- obj->world_pos.y = 0;
- obj->world_pos.z = 0;
- obj->world_pos.w = 1;
- } // end else
- // Step 2: open the file for reading using the parser
- if (!parser.Open(filename))
- {
- Write_Error("Couldn't open .COB file %s.", filename);
- return(0);
- } // end if
- // Step 3:
- // lets find the name of the object first
- while(1)
- {
- // get the next line, we are looking for "Name"
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("Image 'name' not found in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if ( parser.Pattern_Match(parser.buffer, "['Name'] [s>0]") )
- {
- // name should be in second string variable, index 1
- strcpy(obj->name, parser.pstrings[1]);
- Write_Error("nCOB Reader Object Name: %s", obj->name);
- break;
- } // end if
- } // end while
- // step 4: get local and world transforms and store them
- // center 0 0 0
- // x axis 1 0 0
- // y axis 0 1 0
- // z axis 0 0 1
- while(1)
- {
- // get the next line, we are looking for "center"
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("Center not found in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if ( parser.Pattern_Match(parser.buffer, "['center'] [f] [f] [f]") )
- {
- // the "center" holds the translation factors, so place in
- // last row of homogeneous matrix, note that these are row vectors
- // that we need to drop in each column of matrix
- mat_local.M[3][0] = -parser.pfloats[0]; // center x
- mat_local.M[3][1] = -parser.pfloats[1]; // center y
- mat_local.M[3][2] = -parser.pfloats[2]; // center z
- // ok now, the next 3 lines should be the x,y,z transform vectors
- // so build up
- // "x axis"
- parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS);
- parser.Pattern_Match(parser.buffer, "['x'] ['axis'] [f] [f] [f]");
- // place row in x column of transform matrix
- mat_local.M[0][0] = parser.pfloats[0]; // rxx
- mat_local.M[1][0] = parser.pfloats[1]; // rxy
- mat_local.M[2][0] = parser.pfloats[2]; // rxz
- // "y axis"
- parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS);
- parser.Pattern_Match(parser.buffer, "['y'] ['axis'] [f] [f] [f]");
- // place row in y column of transform matrix
- mat_local.M[0][1] = parser.pfloats[0]; // ryx
- mat_local.M[1][1] = parser.pfloats[1]; // ryy
- mat_local.M[2][1] = parser.pfloats[2]; // ryz
- // "z axis"
- parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS);
- parser.Pattern_Match(parser.buffer, "['z'] ['axis'] [f] [f] [f]");
- // place row in z column of transform matrix
- mat_local.M[0][2] = parser.pfloats[0]; // rzx
- mat_local.M[1][2] = parser.pfloats[1]; // rzy
- mat_local.M[2][2] = parser.pfloats[2]; // rzz
- Print_Mat_4X4(&mat_local, "Local COB Matrix:");
- break;
- } // end if
- } // end while
- // now "Transform"
- while(1)
- {
- // get the next line, we are looking for "Transform"
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("Transform not found in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if ( parser.Pattern_Match(parser.buffer, "['Transform']") )
- {
- // "x axis"
- parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS);
- parser.Pattern_Match(parser.buffer, "[f] [f] [f]");
- // place row in x column of transform matrix
- mat_world.M[0][0] = parser.pfloats[0]; // rxx
- mat_world.M[1][0] = parser.pfloats[1]; // rxy
- mat_world.M[2][0] = parser.pfloats[2]; // rxz
- // "y axis"
- parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS);
- parser.Pattern_Match(parser.buffer, "[f] [f] [f]");
- // place row in y column of transform matrix
- mat_world.M[0][1] = parser.pfloats[0]; // ryx
- mat_world.M[1][1] = parser.pfloats[1]; // ryy
- mat_world.M[2][1] = parser.pfloats[2]; // ryz
- // "z axis"
- parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS);
- parser.Pattern_Match(parser.buffer, "[f] [f] [f]");
- // place row in z column of transform matrix
- mat_world.M[0][2] = parser.pfloats[0]; // rzx
- mat_world.M[1][2] = parser.pfloats[1]; // rzy
- mat_world.M[2][2] = parser.pfloats[2]; // rzz
- Print_Mat_4X4(&mat_world, "World COB Matrix:");
- // no need to read in last row, since it's always 0,0,0,1 and we don't use it anyway
- break;
- } // end if
- } // end while
- // step 6: get number of vertices and polys in object
- while(1)
- {
- // get the next line, we are looking for "World Vertices"
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("'World Vertices' line not found in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if (parser.Pattern_Match(parser.buffer, "['World'] ['Vertices'] [i]") )
- {
- // simply extract the number of vertices from the pattern matching
- // output arrays
- obj->num_vertices = parser.pints[0];
- Write_Error("nCOB Reader Num Vertices: %d", obj->num_vertices);
- break;
- } // end if
- } // end while
- // allocate the memory for the vertices and number of polys (unknown, so use 3*num_vertices)
- // the call parameters are redundant in this case, but who cares
- if (!Init_OBJECT4DV2(obj, // object to allocate
- obj->num_vertices,
- obj->num_vertices*3,
- obj->num_frames))
- {
- Write_Error("nASC file error with file %s (can't allocate memory).",filename);
- } // end if
- // Step 7: load the vertex list
- // now read in vertex list, format:
- // "d.d d.d d.d"
- for (int vertex = 0; vertex < obj->num_vertices; vertex++)
- {
- // hunt for vertex
- while(1)
- {
- // get the next vertex
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nVertex list ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if (parser.Pattern_Match(parser.buffer, "[f] [f] [f]"))
- {
- // at this point we have the x,y,z in the the pfloats array locations 0,1,2
- obj->vlist_local[vertex].x = parser.pfloats[0];
- obj->vlist_local[vertex].y = parser.pfloats[1];
- obj->vlist_local[vertex].z = parser.pfloats[2];
- obj->vlist_local[vertex].w = 1;
- // do vertex swapping right here, allow muliple swaps, why not!
- // defines for vertex re-ordering flags
- //#define VERTEX_FLAGS_INVERT_X 1 // inverts the Z-coordinates
- //#define VERTEX_FLAGS_INVERT_Y 2 // inverts the Z-coordinates
- //#define VERTEX_FLAGS_INVERT_Z 4 // inverts the Z-coordinates
- //#define VERTEX_FLAGS_SWAP_YZ 8 // transforms a RHS model to a LHS model
- //#define VERTEX_FLAGS_SWAP_XZ 16 // ???
- //#define VERTEX_FLAGS_SWAP_XY 32
- //#define VERTEX_FLAGS_INVERT_WINDING_ORDER 64 // invert winding order from cw to ccw or ccw to cc
- //#define VERTEX_FLAGS_TRANSFORM_LOCAL 512 // if file format has local transform then do it!
- //#define VERTEX_FLAGS_TRANSFORM_LOCAL_WORLD 1024 // if file format has local to world then do it!
- VECTOR4D temp_vector; // temp for calculations
- // now apply local and world transformations encoded in COB format
- if (vertex_flags & VERTEX_FLAGS_TRANSFORM_LOCAL )
- {
- Mat_Mul_VECTOR4D_4X4(&obj->vlist_local[vertex].v, &mat_local, &temp_vector);
- VECTOR4D_COPY(&obj->vlist_local[vertex].v, &temp_vector);
- } // end if
- if (vertex_flags & VERTEX_FLAGS_TRANSFORM_LOCAL_WORLD )
- {
- Mat_Mul_VECTOR4D_4X4(&obj->vlist_local[vertex].v, &mat_world, &temp_vector);
- VECTOR4D_COPY(&obj->vlist_local[vertex].v, &temp_vector);
- } // end if
- float temp_f; // used for swapping
- // invert signs?
- if (vertex_flags & VERTEX_FLAGS_INVERT_X)
- obj->vlist_local[vertex].x=-obj->vlist_local[vertex].x;
- if (vertex_flags & VERTEX_FLAGS_INVERT_Y)
- obj->vlist_local[vertex].y=-obj->vlist_local[vertex].y;
- if (vertex_flags & VERTEX_FLAGS_INVERT_Z)
- obj->vlist_local[vertex].z=-obj->vlist_local[vertex].z;
- // swap any axes?
- if (vertex_flags & VERTEX_FLAGS_SWAP_YZ)
- SWAP(obj->vlist_local[vertex].y, obj->vlist_local[vertex].z, temp_f);
- if (vertex_flags & VERTEX_FLAGS_SWAP_XZ)
- SWAP(obj->vlist_local[vertex].x, obj->vlist_local[vertex].z, temp_f);
- if (vertex_flags & VERTEX_FLAGS_SWAP_XY)
- SWAP(obj->vlist_local[vertex].x, obj->vlist_local[vertex].y, temp_f);
- // scale vertices
- if (scale)
- {
- obj->vlist_local[vertex].x*=scale->x;
- obj->vlist_local[vertex].y*=scale->y;
- obj->vlist_local[vertex].z*=scale->z;
- } // end if
- Write_Error("nVertex %d = %f, %f, %f, %f", vertex,
- obj->vlist_local[vertex].x,
- obj->vlist_local[vertex].y,
- obj->vlist_local[vertex].z,
- obj->vlist_local[vertex].w);
- // set point field in this vertex, we need that at least
- SET_BIT(obj->vlist_local[vertex].attr, VERTEX4DTV1_ATTR_POINT);
- // found vertex, break out of while for next pass
- break;
- } // end if
- } // end while
- } // end for vertex
- // compute average and max radius
- Compute_OBJECT4DV2_Radius(obj);
- Write_Error("nObject average radius = %f, max radius = %f",
- obj->avg_radius, obj->max_radius);
- // step 8: get number of texture vertices
- while(1)
- {
- // get the next line, we are looking for "Texture Vertices ddd"
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("'Texture Vertices' line not found in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if (parser.Pattern_Match(parser.buffer, "['Texture'] ['Vertices'] [i]") )
- {
- // simply extract the number of texture vertices from the pattern matching
- // output arrays
- num_texture_vertices = parser.pints[0];
- Write_Error("nCOB Reader Texture Vertices: %d", num_texture_vertices);
- break;
- } // end if
- } // end while
- // Step 9: load the texture vertex list in format "U V"
- // "d.d d.d"
- for (int tvertex = 0; tvertex < num_texture_vertices; tvertex++)
- {
- // hunt for texture
- while(1)
- {
- // get the next vertex
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nTexture Vertex list ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if (parser.Pattern_Match(parser.buffer, "[f] [f]"))
- {
- // at this point we have the U V in the the pfloats array locations 0,1 for this
- // texture vertex, store in texture coordinate list
- // note texture coords are in 0..1 format, and must be scaled to texture size
- // after we load the texture
- obj->tlist[tvertex].x = parser.pfloats[0];
- obj->tlist[tvertex].y = parser.pfloats[1];
- Write_Error("nTexture Vertex %d: U=%f, V=%f", tvertex,
- obj->tlist[tvertex].x,
- obj->tlist[tvertex].y );
- // found vertex, break out of while for next pass
- break;
- } // end if
- } // end while
- } // end for
- // when we load in the polygons then we will copy the texture vertices into the polygon
- // vertices assuming that each vertex has a SINGLE texture coordinate, this means that
- // you must NOT use multiple textures on an object! in other words think "skin" this is
- // inline with Quake II md2 format, in 99% of the cases a single object can be textured
- // with a single skin and the texture coordinates can be unique for each vertex and 1:1
- int poly_material[OBJECT4DV2_MAX_POLYS]; // this holds the material index for each polygon
- // we need these indices since when reading the file
- // we read the polygons BEFORE the materials, so we need
- // this data, so we can go back later and extract the material
- // that each poly WAS assigned and get the colors out, since
- // objects and polygons do not currently support materials
- int material_index_referenced[MAX_MATERIALS]; // used to track if an index has been used yet as a material
- // reference. since we don't know how many materials, we need
- // a way to count them up, but if we have seen a material reference
- // more than once then we don't increment the total number of materials
- // this array is for this
- // clear out reference array
- memset(material_index_referenced,0, sizeof(material_index_referenced));
- // step 10: load in the polygons
- // poly list starts off with:
- // "Faces ddd:"
- while(1)
- {
- // get next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("n'Faces' line not found in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if (parser.Pattern_Match(parser.buffer, "['Faces'] [i]"))
- {
- Write_Error("nCOB Reader found face list in .COB file %s.", filename);
- // finally set number of polys
- obj->num_polys = parser.pints[0];
- break;
- } // end if
- } // end while
- // now read each face in format:
- // Face verts nn flags ff mat mm
- // the nn is the number of vertices, always 3
- // the ff is the flags, unused for now, has to do with holes
- // the mm is the material index number
- int poly_surface_desc = 0; // ASC surface descriptor/material in this case
- int poly_num_verts = 0; // number of vertices for current poly (always 3)
- int num_materials_object = 0; // number of materials for this object
- for (int poly=0; poly < obj->num_polys; poly++)
- {
- Write_Error("nPolygon %d:", poly);
- // hunt until next face is found
- while(1)
- {
- // get the next polygon face
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nface list ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if (parser.Pattern_Match(parser.buffer, "['Face'] ['verts'] [i] ['flags'] [i] ['mat'] [i]"))
- {
- // at this point we have the number of vertices for the polygon, the flags, and it's material index
- // in the integer output array locations 0,1,2
- // store the material index for this polygon for retrieval later, but make sure adjust the
- // the index to take into consideration that the data in parser.pints[2] is 0 based, and we need
- // an index relative to the entire library, so we simply need to add num_materials to offset the
- // index properly, but we will leave this reference zero based for now... and fix up later
- poly_material[poly] = parser.pints[2];
- // update the reference array
- if (material_index_referenced[ poly_material[poly] ] == 0)
- {
- // mark as referenced
- material_index_referenced[ poly_material[poly] ] = 1;
- // increment total number of materials for this object
- num_materials_object++;
- } // end if
- // test if number of vertices is 3
- if (parser.pints[0]!=3)
- {
- Write_Error("nface not a triangle! in .COB file %s.", filename);
- return(0);
- } // end if
- // now read out the vertex indices and texture indices format:
- // <vindex0, tindex0> <vindex1, tindex1> <vindex1, tindex1>
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nface list ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // lets replace ",<>" with ' ' to make extraction easy
- ReplaceChars(parser.buffer, parser.buffer, ",<>",' ');
- parser.Pattern_Match(parser.buffer, "[i] [i] [i] [i] [i] [i]");
- // 0,2,4 holds vertex indices
- // 1,3,5 holds texture indices
- // insert polygon, check for winding order invert
- if (vertex_flags & VERTEX_FLAGS_INVERT_WINDING_ORDER)
- {
- poly_num_verts = 3;
- obj->plist[poly].vert[0] = parser.pints[4];
- obj->plist[poly].vert[1] = parser.pints[2];
- obj->plist[poly].vert[2] = parser.pints[0];
- // now copy the texture coordinates into the vertices, this
- // may not be needed if the polygon doesn't have texture mapping
- // enabled, etc.,
- // so here's the deal the texture coordinates that
- // map to vertex 0,1,2 have indices stored in the odd
- // numbered pints[] locations, so we simply need to copy
- // the right texture coordinate into the right vertex
- obj->plist[poly].text[0] = parser.pints[5];
- obj->plist[poly].text[1] = parser.pints[3];
- obj->plist[poly].text[2] = parser.pints[1];
- Write_Error("nAssigning texture vertex index %d [%f, %f] to mesh vertex %d",
- parser.pints[5],
- obj->tlist[ parser.pints[5] ].x,
- obj->tlist[ parser.pints[5] ].y,
- obj->plist[poly].vert[0] );
- Write_Error("nAssigning texture vertex index %d [%f, %f] to mesh vertex %d",
- parser.pints[3],
- obj->tlist[ parser.pints[3] ].x,
- obj->tlist[ parser.pints[3] ].y,
- obj->plist[poly].vert[1] );
- Write_Error("nAssigning texture vertex index %d [%f, %f] to mesh vertex %d",
- parser.pints[1],
- obj->tlist[ parser.pints[1] ].x,
- obj->tlist[ parser.pints[1] ].y,
- obj->plist[poly].vert[2] );
- } // end if
- else
- { // leave winding order alone
- poly_num_verts = 3;
- obj->plist[poly].vert[0] = parser.pints[0];
- obj->plist[poly].vert[1] = parser.pints[2];
- obj->plist[poly].vert[2] = parser.pints[4];
- // now copy the texture coordinates into the vertices, this
- // may not be needed if the polygon doesn't have texture mapping
- // enabled, etc.,
- // so here's the deal the texture coordinates that
- // map to vertex 0,1,2 have indices stored in the odd
- // numbered pints[] locations, so we simply need to copy
- // the right texture coordinate into the right vertex
- obj->plist[poly].text[0] = parser.pints[1];
- obj->plist[poly].text[1] = parser.pints[3];
- obj->plist[poly].text[2] = parser.pints[5];
- Write_Error("nAssigning texture vertex index %d [%f, %f] to mesh vertex %d",
- parser.pints[1],
- obj->tlist[ parser.pints[1] ].x,
- obj->tlist[ parser.pints[1] ].y,
- obj->plist[poly].vert[0] );
- Write_Error("nAssigning texture vertex index %d [%f, %f] to mesh vertex %d",
- parser.pints[3],
- obj->tlist[ parser.pints[3] ].x,
- obj->tlist[ parser.pints[3] ].y,
- obj->plist[poly].vert[1] );
- Write_Error("nAssigning texture vertex index %d [%f, %f] to mesh vertex %d",
- parser.pints[5],
- obj->tlist[ parser.pints[5] ].x,
- obj->tlist[ parser.pints[5] ].y,
- obj->plist[poly].vert[2] );
- } // end else
- // point polygon vertex list to object's vertex list
- // note that this is redundant since the polylist is contained
- // within the object in this case and its up to the user to select
- // whether the local or transformed vertex list is used when building up
- // polygon geometry, might be a better idea to set to NULL in the context
- // of polygons that are part of an object
- obj->plist[poly].vlist = obj->vlist_local;
- // set texture coordinate list, this is needed
- obj->plist[poly].tlist = obj->tlist;
- // set polygon to active
- obj->plist[poly].state = POLY4DV2_STATE_ACTIVE;
- // found the face, break out of while for another pass
- break;
- } // end if
- } // end while
- Write_Error("nLocal material Index=%d, total materials for object = %d, vert_indices [%d, %d, %d]",
- poly_material[poly],
- num_materials_object,
- obj->plist[poly].vert[0],
- obj->plist[poly].vert[1],
- obj->plist[poly].vert[2]);
- } // end for poly
- // now find materials!!! and we are out of here!
- for (int curr_material = 0; curr_material < num_materials_object; curr_material++)
- {
- // hunt for the material header "mat# ddd"
- while(1)
- {
- // get the next polygon material
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nmaterial list ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // check for pattern?
- if (parser.Pattern_Match(parser.buffer, "['mat#'] [i]") )
- {
- // extract the material that is being defined
- int material_index = parser.pints[0];
- // get color of polygon, although it might be irrelevant for a textured surface
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nRGB color ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // replace the , comma's if there are any with spaces
- ReplaceChars(parser.buffer, parser.buffer, ",", ' ', 1);
- // look for "rgb float,float,float"
- if (parser.Pattern_Match(parser.buffer, "['rgb'] [f] [f] [f]") )
- {
- // extract data and store color in material libary
- // pfloats[] 0,1,2,3, has data
- materials[material_index + num_materials].color.r = (int)(parser.pfloats[0]*255 + 0.5);
- materials[material_index + num_materials].color.g = (int)(parser.pfloats[1]*255 + 0.5);
- materials[material_index + num_materials].color.b = (int)(parser.pfloats[2]*255 + 0.5);
- break; // while looking for rgb
- } // end if
- } // end while
- // extract out lighting constants for the heck of it, they are on a line like this:
- // "alpha float ka float ks float exp float ior float"
- // alpha is transparency 0 - 1
- // ka is ambient coefficient 0 - 1
- // ks is specular coefficient 0 - 1
- // exp is highlight power exponent 0 - 1
- // ior is index of refraction (unused)
- // although our engine will have minimal support for these, we might as well get them
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nmaterial properties ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // look for "alpha float ka float ks float exp float ior float"
- if (parser.Pattern_Match(parser.buffer, "['alpha'] [f] ['ka'] [f] ['ks'] [f] ['exp'] [f]") )
- {
- // extract data and store in material libary
- // pfloats[] 0,1,2,3, has data
- materials[material_index + num_materials].color.a = (UCHAR)(parser.pfloats[0]*255 + 0.5);
- materials[material_index + num_materials].ka = parser.pfloats[1];
- materials[material_index + num_materials].kd = 1; // hard code for now
- materials[material_index + num_materials].ks = parser.pfloats[2];
- materials[material_index + num_materials].power = parser.pfloats[3];
- // compute material reflectivities in pre-multiplied format to help engine
- for (int rgb_index=0; rgb_index < 3; rgb_index++)
- {
- // ambient reflectivity
- materials[material_index + num_materials].ra.rgba_M[rgb_index] =
- ( (UCHAR)(materials[material_index + num_materials].ka *
- (float)materials[material_index + num_materials].color.rgba_M[rgb_index] + 0.5) );
- // diffuse reflectivity
- materials[material_index + num_materials].rd.rgba_M[rgb_index] =
- ( (UCHAR)(materials[material_index + num_materials].kd *
- (float)materials[material_index + num_materials].color.rgba_M[rgb_index] + 0.5) );
- // specular reflectivity
- materials[material_index + num_materials].rs.rgba_M[rgb_index] =
- ( (UCHAR)(materials[material_index + num_materials].ks *
- (float)materials[material_index + num_materials].color.rgba_M[rgb_index] + 0.5) );
- } // end for rgb_index
- break;
- } // end if
- } // end while
- // now we need to know the shading model, it's a bit tricky, we need to look for the lines
- // "Shader class: color" first, then after this line is:
- // "Shader name: "xxxxxx" (xxxxxx) "
- // where the xxxxx part will be "plain color" and "plain" for colored polys
- // or "texture map" and "caligari texture" for textures
- // THEN based on that we hunt for "Shader class: reflectance" which is where the type
- // of shading is encoded, we look for the "Shader name: "xxxxxx" (xxxxxx) " again,
- // and based on it's value we map it to our shading system as follows:
- // "constant" -> MATV1_ATTR_SHADE_MODE_CONSTANT
- // "matte" -> MATV1_ATTR_SHADE_MODE_FLAT
- // "plastic" -> MATV1_ATTR_SHADE_MODE_GOURAUD
- // "phong" -> MATV1_ATTR_SHADE_MODE_FASTPHONG
- // and in the case that in the "color" class, we found a "texture map" then the "shading mode" is
- // "texture map" -> MATV1_ATTR_SHADE_MODE_TEXTURE
- // which must be logically or'ed with the other previous modes
- // look for the "shader class: color"
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nshader class ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- if (parser.Pattern_Match(parser.buffer, "['Shader'] ['class:'] ['color']") )
- {
- break;
- } // end if
- } // end while
- // now look for the shader name for this class
- // Shader name: "plain color" or Shader name: "texture map"
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nshader name ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // replace the " with spaces
- ReplaceChars(parser.buffer, parser.buffer, """, ' ', 1);
- // is this a "plain color" poly?
- if (parser.Pattern_Match(parser.buffer, "['Shader'] ['name:'] ['plain'] ['color']") )
- {
- // not much to do this is default, we need to wait for the reflectance type
- // to tell us the shading mode
- break;
- } // end if
- // is this a "texture map" poly?
- if (parser.Pattern_Match(parser.buffer, "['Shader'] ['name:'] ['texture'] ['map']") )
- {
- // set the texture mapping flag in material
- SET_BIT(materials[material_index + num_materials].attr, MATV1_ATTR_SHADE_MODE_TEXTURE);
- // almost done, we need the file name of the darn texture map, its in this format:
- // file name: string "D:Source..modelstextureswall01.bmp"
- // of course the filename in the quotes will change
- // so lets hunt until we find it...
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("ncouldnt find texture name! in .COB file %s.", filename);
- return(0);
- } // end if
- // replace the " with spaces
- ReplaceChars(parser.buffer, parser.buffer, """, ' ', 1);
- // is this the file name?
- if (parser.Pattern_Match(parser.buffer, "['file'] ['name:'] ['string']") )
- {
- // and save the FULL filename (useless though since its the path from the
- // machine that created it, but later we might want some of the info).
- // filename and path starts at char position 19, 0 indexed
- memcpy(materials[material_index + num_materials].texture_file, &parser.buffer[18], strlen(parser.buffer) - 18 + 2 );
- // the OBJECT4DV2 is only allowed a single texture, although we are loading in all
- // the materials, if this is the first texture map, load it, and set a flag disallowing
- // any more texture loads for the object
- if (!obj->texture)
- {
- // step 1: allocate memory for bitmap
- obj->texture = (BITMAP_IMAGE_PTR)malloc(sizeof(BITMAP_IMAGE));
- // load the texture, just use the final file name and the absolute global
- // texture path
- char filename[80];
- char path_filename[80];
- // get the filename
- Extract_Filename_From_Path(materials[material_index + num_materials].texture_file, filename);
- // build the filename with root path
- strcpy(path_filename, texture_path);
- strcat(path_filename, filename);
- // buffer now holds final texture path and file name
- // load the bitmap(8/16 bit)
- Load_Bitmap_File(&bitmap16bit, path_filename);
- // create a proper size and bitdepth bitmap
- Create_Bitmap(obj->texture,0,0,
- bitmap16bit.bitmapinfoheader.biWidth,
- bitmap16bit.bitmapinfoheader.biHeight,
- bitmap16bit.bitmapinfoheader.biBitCount);
- // load the bitmap image (later make this 8/16 bit)
- if (obj->texture->bpp == 16)
- Load_Image_Bitmap16(obj->texture, &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
- else
- {
- Load_Image_Bitmap(obj->texture, &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
- } // end else 8 bit
- // done, so unload the bitmap
- Unload_Bitmap_File(&bitmap16bit);
- // flag object as having textures
- SET_BIT(obj->attr, OBJECT4DV2_ATTR_TEXTURES);
- } // end if
- break;
- } // end if
- } // end while
- break;
- } // end if
- } // end while
- ////////////////////////////////////////////////////////////////////////////////////////////
- // ADDED CODE FOR TRANSPARENCY AND ALPHA BLENDING //////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////
- // Now we need to know if there is any transparency for the material
- // we have decided to encoded this in the shader class: transparency :)
- // also, you must use the "filter" shader, and then set the RGB color to
- // the level of transparency you want, 0,0,0 means totally transparent
- // 255,255,255 means totally opaque, so we are looking for something like
- // this:
- // Shader class: transparency
- // Shader name: "filter" (plain)
- // Number of parameters: 1
- // colour: color (146, 146, 146)
- //
- // and if there isn't transparency then we will see this:
- //
- // Shader class: transparency
- // Shader name: "none" (none)
- // Number of parameters: 0
- //
- // now, since we aren't doing anykind of RGB transparency, we are only concerned
- // with the overall value, so the way, I am going to do this is to look at the
- // 3 values of R, G, B, and use the highest one as the final alpha/transparency
- // value, so a value of 255, 255, 255 with be 100% alpha or totally opaque
- // look for the "Shader class: transparency"
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nshader transparency class not found in .COB file %s.", filename);
- return(0);
- } // end if
- // look for "Shader class: transparency"
- if (parser.Pattern_Match(parser.buffer, "['Shader'] ['class:'] ['transparency']") )
- {
- // now we know the next "shader name" is what we are looking for so, break
- break;
- } // end if
- } // end while
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nshader name ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // get rid of those quotes
- ReplaceChars(parser.buffer, parser.buffer, """,' ',1);
- // did we find the name?
- if (parser.Pattern_Match(parser.buffer, "['Shader'] ['name:'] [s>0]" ) )
- {
- // figure out if transparency is enabled
- if (strcmp(parser.pstrings[2], "none") == 0)
- {
- // disable the alpha bit and write 0 alpha
- RESET_BIT(materials[material_index + num_materials].attr, MATV1_ATTR_TRANSPARENT);
- // set alpha to 0, unused
- materials[material_index + num_materials].color.a = 0;
- } // end if
- else
- if (strcmp(parser.pstrings[2], "filter") == 0)
- {
- // enable the alpha bit and write the alpha level
- SET_BIT(materials[material_index + num_materials].attr, MATV1_ATTR_TRANSPARENT);
- // now search for color line to extract alpha level
- // look for the "Shader class: transparency"
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("ntransparency color not found in .COB file %s.", filename);
- return(0);
- } // end if
- // get rid of extraneous characters
- ReplaceChars(parser.buffer, parser.buffer, ":(,)",' ',1);
- // look for colour: color (146, 146, 146)
- if (parser.Pattern_Match(parser.buffer, "['colour'] ['color'] [i] [i] [i]") )
- {
- // set the alpha level to the highest value
- int max_alpha = MAX(parser.pints[0], parser.pints[1]);
- max_alpha = MAX(max_alpha, parser.pints[2]);
- // set alpha value
- materials[material_index + num_materials].color.a =
- (int)( (float)max_alpha/255 * (float)(NUM_ALPHA_LEVELS-1) + (float)0.5);
- // clamp
- if (materials[material_index + num_materials].color.a >= NUM_ALPHA_LEVELS)
- materials[material_index + num_materials].color.a = NUM_ALPHA_LEVELS-1;
- break;
- } // end if
- } // end while
- } // end if
- break;
- } // end if
- } // end while
- //////////////////////////////////////////////////////////////////////////////////////////////
- // alright, finally! Now we need to know what the actual shader type, now in the COB format
- // I have decided that in the "reflectance" class that's where we will look at what kind
- // of shader is supposed to be used on the polygon
- // look for the "Shader class: reflectance"
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nshader reflectance class not found in .COB file %s.", filename);
- return(0);
- } // end if
- // look for "Shader class: reflectance"
- if (parser.Pattern_Match(parser.buffer, "['Shader'] ['class:'] ['reflectance']") )
- {
- // now we know the next "shader name" is what we are looking for so, break
- break;
- } // end if
- } // end while
- // looking for "Shader name: "xxxxxx" (xxxxxx) " again,
- // and based on it's value we map it to our shading system as follows:
- // "constant" -> MATV1_ATTR_SHADE_MODE_CONSTANT
- // "matte" -> MATV1_ATTR_SHADE_MODE_FLAT
- // "plastic" -> MATV1_ATTR_SHADE_MODE_GOURAUD
- // "phong" -> MATV1_ATTR_SHADE_MODE_FASTPHONG
- // and in the case that in the "color" class, we found a "texture map" then the "shading mode" is
- // "texture map" -> MATV1_ATTR_SHADE_MODE_TEXTURE
- // which must be logically or'ed with the other previous modes
- while(1)
- {
- // get the next line
- if (!parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS))
- {
- Write_Error("nshader name ended abruptly! in .COB file %s.", filename);
- return(0);
- } // end if
- // get rid of those quotes
- ReplaceChars(parser.buffer, parser.buffer, """,' ',1);
- // did we find the name?
- if (parser.Pattern_Match(parser.buffer, "['Shader'] ['name:'] [s>0]" ) )
- {
- // figure out which shader to use
- if (strcmp(parser.pstrings[2], "constant") == 0)
- {
- // set the shading mode flag in material
- SET_BIT(materials[material_index + num_materials].attr, MATV1_ATTR_SHADE_MODE_CONSTANT);
- } // end if
- else
- if (strcmp(parser.pstrings[2], "matte") == 0)
- {
- // set the shading mode flag in material
- SET_BIT(materials[material_index + num_materials].attr, MATV1_ATTR_SHADE_MODE_FLAT);
- } // end if
- else
- if (strcmp(parser.pstrings[2], "plastic") == 0)
- {