t3dlib10.cpp
资源名称:Source.rar [点击查看]
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:1310k
源码类别:
游戏
开发平台:
Visual C++
- 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 = (1 << FIXP28_SHIFT) / (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 = (1 << FIXP28_SHIFT) / (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 = (1 << FIXP28_SHIFT) / (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) << 0)/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) << 0)/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 << 0);
- 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 << 0);
- 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 << 0);
- sl = (ts0 << FIXP16_SHIFT);
- tl = (tt0 << FIXP16_SHIFT);
- ur = (tu1 << FIXP16_SHIFT);
- vr = (tv1 << FIXP16_SHIFT);
- wr = (tw1 << FIXP16_SHIFT);
- zr = (tz1 << 0);
- 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) << 0)/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) << 0)/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 << 0);
- 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 << 0);
- 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 << 0);
- sl = (ts0 << FIXP16_SHIFT);
- tl = (tt0 << FIXP16_SHIFT);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- wr = (tw0 << FIXP16_SHIFT);
- zr = (tz0 << 0);
- 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) << 0)/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) << 0)/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 << 0);
- 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 << 0);
- 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) << 0)/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) << 0)/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 << 0);
- 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 << 0);
- 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) << 0)/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) << 0)/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 << 0);
- sl = (ts0 << FIXP16_SHIFT);
- tl = (tt0 << FIXP16_SHIFT);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- wr = (tw0 << FIXP16_SHIFT);
- zr = (tz0 << 0);
- 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) << 0)/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 << 0);
- 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) << 0)/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 << 0);
- 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) << 0)/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 << 0);
- 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) << 0)/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 << 0);
- 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_TriangleGSINVZB_Alpha16
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_Gouraud_TriangleINVZB_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 = (1 << FIXP28_SHIFT) / (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 = (1 << FIXP28_SHIFT) / (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 = (1 <<FIXP28_SHIFT) / (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) << 0)/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) << 0)/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 << 0);
- // 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 << 0);
- // 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 << 0);
- ur = (tu1 << FIXP16_SHIFT);
- vr = (tv1 << FIXP16_SHIFT);
- wr = (tw1 << FIXP16_SHIFT);
- zr = (tz1 << 0);
- // 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) << 0)/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) << 0)/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 << 0);
- // 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 << 0);
- // 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 << 0);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- wr = (tw0 << FIXP16_SHIFT);
- zr = (tz0 << 0);
- // 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) << 0)/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) << 0)/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 << 0);
- // 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 << 0);
- // 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) << 0)/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) << 0)/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 << 0);
- // 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 << 0);
- // 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) << 0)/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) << 0)/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 << 0);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- wr = (tw0 << FIXP16_SHIFT);
- zr = (tz0 << 0);
- // 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) << 0)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- wl = (tw1 << FIXP16_SHIFT);
- zl = (tz1 << 0);
- // 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) << 0)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- wr = (tw2 << FIXP16_SHIFT);
- zr = (tz2 << 0);
- // 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) << 0)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- wl = (tw1 << FIXP16_SHIFT);
- zl = (tz1 << 0);
- // 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) << 0)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- wr = (tw2 << FIXP16_SHIFT);
- zr = (tz2 << 0);
- // 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_TriangleINVZB_Alpha16
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_RENDERLIST4DV2_SolidINVZB_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_Perspective_Triangle_INVZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch, alpha);
- else
- Draw_Textured_TriangleINVZB_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_TriangleFSINVZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch, alpha);
- else
- Draw_Textured_TriangleFSINVZB_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_TriangleGSINVZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch,alpha);
- else
- Draw_Textured_TriangleGSINVZB_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_2DINVZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch,alpha);
- else
- Draw_Triangle_2DINVZB_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_TriangleINVZB_Alpha16(&face, video_buffer, lpitch,zbuffer,zpitch,alpha);
- else
- Draw_Gouraud_TriangleINVZB_16(&face, video_buffer, lpitch,zbuffer,zpitch);
- } // end if gouraud
- } // end for poly+
- } // end Draw_RENDERLIST4DV2_SolidINVZB_Alpha16
- /////////////////////////////////////////////////////////////////////////////////////////////
- int DDraw_Init2(int width, int height, int bpp, int windowed, int backbuffer_enable)
- {
- // this function initializes directdraw, but allows for a non flippable pure
- // memory backbuffer even in full screen mode, this is to override an anomaly
- // with new directdraw that does not like us reading from the backbuffer in a chained
- // complex surface, thus we have to create a secondary offscreen surface just like in
- // windowed mode for this case, so the alpha blending code will work fast, otherwise
- // its' like 30 times slower! Alas, if you don't want to use the complex chained backbuffer
- // then send a 0 for the last parameter, or in other words for alpha bleding support with
- // speed send a zero if you're going to do full screen mode, otherwise send a 1 as the last
- // parameter which is the default, hence you can call this function as you have the first
- // version in that case
- int index; // looping variable
- // create IDirectDraw interface 7.0 object and test for error
- if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
- return(0);
- // based on windowed or fullscreen set coorperation level
- if (windowed)
- {
- // set cooperation level to windowed mode
- if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,DDSCL_NORMAL)))
- return(0);
- } // end if
- else
- {
- // set cooperation level to fullscreen mode
- if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,
- DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN |
- DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT | DDSCL_MULTITHREADED )))
- return(0);
- // set the display mode
- if (FAILED(lpdd->SetDisplayMode(width,height,bpp,0,0)))
- return(0);
- } // end else
- // set globals
- screen_height = height;
- screen_width = width;
- screen_bpp = bpp;
- screen_windowed = windowed;
- screen_backbuffer_enable = backbuffer_enable;
- // Create the primary surface
- memset(&ddsd,0,sizeof(ddsd));
- ddsd.dwSize = sizeof(ddsd);
- // we need to let dd know that we want a complex
- // flippable surface structure, set flags for that
- if (!screen_windowed)
- {
- // test for backbuffer enabled
- if (screen_backbuffer_enable)
- {
- // fullscreen mode
- ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
- // set the backbuffer count to 0 for windowed mode
- // 1 for fullscreen mode, 2 for triple buffering
- ddsd.dwBackBufferCount = 1;
- } // end if
- else
- {
- // user is requested no back buffer and wants to use a plain offscreen memory
- // surface to speed up reading for alpha blending
- // fullscreen mode
- ddsd.dwFlags = DDSD_CAPS;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
- // set the backbuffer count to 0 for windowed mode
- // 1 for fullscreen mode, 2 for triple buffering
- ddsd.dwBackBufferCount = 0;
- } // end else
- } // end if
- else
- {
- // windowed mode
- ddsd.dwFlags = DDSD_CAPS;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
- // set the backbuffer count to 0 for windowed mode
- // 1 for fullscreen mode, 2 for triple buffering
- ddsd.dwBackBufferCount = 0;
- } // end else
- // create the primary surface
- lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL);
- // get the pixel format of the primary surface
- DDPIXELFORMAT ddpf; // used to get pixel format
- // initialize structure
- DDRAW_INIT_STRUCT(ddpf);
- // query the format from primary surface
- lpddsprimary->GetPixelFormat(&ddpf);
- // based on masks determine if system is 5.6.5 or 5.5.5
- //RGB Masks for 5.6.5 mode
- //DDPF_RGB 16 R: 0x0000F800
- // G: 0x000007E0
- // B: 0x0000001F
- //RGB Masks for 5.5.5 mode
- //DDPF_RGB 16 R: 0x00007C00
- // G: 0x000003E0
- // B: 0x0000001F
- // test for 6 bit green mask)
- //if (ddpf.dwGBitMask == 0x000007E0)
- // dd_pixel_format = DD_PIXEL_FORMAT565;
- // use number of bits, better method
- dd_pixel_format = ddpf.dwRGBBitCount;
- Write_Error("npixel format = %d",dd_pixel_format);
- // set up conversion macros, so you don't have to test which one to use
- if (dd_pixel_format == DD_PIXEL_FORMAT555)
- {
- RGB16Bit = RGB16Bit555;
- Write_Error("npixel format = 5.5.5");
- } // end if
- else
- {
- RGB16Bit = RGB16Bit565;
- Write_Error("npixel format = 5.6.5");
- } // end else
- // only need a backbuffer for fullscreen modes
- if (!screen_windowed)
- {
- // test for backbuffer enabled
- if (screen_backbuffer_enable)
- {
- // query for the backbuffer i.e the secondary surface
- ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
- if (FAILED(lpddsprimary->GetAttachedSurface(&ddscaps,&lpddsback)))
- return(0);
- } // end if
- else
- {
- // must be requesting this for high performance alpha blending
- lpddsback = DDraw_Create_Surface(width, height, DDSCAPS_SYSTEMMEMORY); // int mem_flags, USHORT color_key_flag);
- } // end else
- } // end if
- else
- {
- // must be windowed, so create a double buffer that will be blitted
- // rather than flipped as in full screen mode
- lpddsback = DDraw_Create_Surface(width, height, DDSCAPS_SYSTEMMEMORY); // int mem_flags, USHORT color_key_flag);
- } // end else
- // create a palette only if 8bit mode
- if (screen_bpp==DD_PIXEL_FORMAT8)
- {
- // create and attach palette
- // clear all entries, defensive programming
- memset(palette,0,MAX_COLORS_PALETTE*sizeof(PALETTEENTRY));
- // load a pre-made "good" palette off disk
- Load_Palette_From_File(DEFAULT_PALETTE_FILE, palette);
- // load and attach the palette, test for windowed mode
- if (screen_windowed)
- {
- // in windowed mode, so the first 10 and last 10 entries have
- // to be slightly modified as does the call to createpalette
- // reset the peFlags bit to PC_EXPLICIT for the "windows" colors
- for (index=0; index < 10; index++)
- palette[index].peFlags = palette[index+246].peFlags = PC_EXPLICIT;
- // now create the palette object, but disable access to all 256 entries
- if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE,
- palette,&lpddpal,NULL)))
- return(0);
- } // end
- else
- {
- // in fullscreen mode, so simple create the palette with the default palette
- // and fill in all 256 entries
- if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256,
- palette,&lpddpal,NULL)))
- return(0);
- } // end if
- // now attach the palette to the primary surface
- if (FAILED(lpddsprimary->SetPalette(lpddpal)))
- return(0);
- } // end if attach palette for 8bit mode
- // clear out both primary and secondary surfaces
- if (screen_windowed)
- {
- // only clear backbuffer
- DDraw_Fill_Surface(lpddsback,0);
- } // end if
- else
- {
- // fullscreen, simply clear everything
- DDraw_Fill_Surface(lpddsprimary,0);
- DDraw_Fill_Surface(lpddsback,0);
- } // end else
- // set software algorithmic clipping region
- min_clip_x = 0;
- max_clip_x = screen_width - 1;
- min_clip_y = 0;
- max_clip_y = screen_height - 1;
- // setup backbuffer clipper always
- RECT screen_rect = {0,0,screen_width,screen_height};
- lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);
- // set up windowed mode clipper
- if (screen_windowed)
- {
- // set windowed clipper
- if (FAILED(lpdd->CreateClipper(0,&lpddclipperwin,NULL)))
- return(0);
- if (FAILED(lpddclipperwin->SetHWnd(0, main_window_handle)))
- return(0);
- if (FAILED(lpddsprimary->SetClipper(lpddclipperwin)))
- return(0);
- } // end if screen windowed
- // return success
- return(1);
- } // end DDraw_Init2
- ///////////////////////////////////////////////////////////
- int DDraw_Flip2(void)
- {
- // this function flip the primary surface with the secondary surface
- // test if either of the buffers are locked
- if (primary_buffer || back_buffer)
- return(0);
- // flip pages
- if (!screen_windowed)
- {
- // test for backbuffer enabled
- if (screen_backbuffer_enable)
- {
- while(FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));
- } // end if
- else
- {
- // must have an overrided off screen memory backbuffer for alpha blending speed
- RECT dest_rect; // used to compute destination rectangle
- // get the window's rectangle in screen coordinates
- GetWindowRect(main_window_handle, &dest_rect);
- // compute the destination rectangle
- dest_rect.left +=window_client_x0;
- dest_rect.top +=window_client_y0;
- dest_rect.right =dest_rect.left+screen_width-1;
- dest_rect.bottom =dest_rect.top +screen_height-1;
- // clip the screen coords
- // blit the entire back surface to the primary
- if (FAILED(lpddsprimary->Blt(&dest_rect, lpddsback,NULL,DDBLT_WAIT,NULL)))
- return(0);
- } // end else
- } // end if
- else
- {
- RECT dest_rect; // used to compute destination rectangle
- // get the window's rectangle in screen coordinates
- GetWindowRect(main_window_handle, &dest_rect);
- // compute the destination rectangle
- dest_rect.left +=window_client_x0;
- dest_rect.top +=window_client_y0;
- dest_rect.right =dest_rect.left+screen_width-1;
- dest_rect.bottom =dest_rect.top +screen_height-1;
- // clip the screen coords
- // blit the entire back surface to the primary
- if (FAILED(lpddsprimary->Blt(&dest_rect, lpddsback,NULL,DDBLT_WAIT,NULL)))
- return(0);
- } // end if
- // return success
- return(1);
- } // end DDraw_Flip2
- ///////////////////////////////////////////////////////////
- int Generate_Mipmaps(BITMAP_IMAGE_PTR source, // source bitmap for mipmap
- BITMAP_IMAGE_PTR *mipmaps, // pointer to array to store mipmap chain
- float gamma) // gamma correction factor
- {
- // this functions creates a mip map chain of bitmap textures
- // on entry source should point to the bottom level d = 0 texture
- // and on exit mipmap will point to an array of pointers that holds
- // all the mip levels including source as entry 0, additionally the
- // function will return the total number of levels or -1 if there
- // is a problem, the last param gamma is used to brighten each mip level up
- // since averaging has the effect of darkening, a value of 1.01 is usually
- // good, values greater that 1.0 brighten each mip map, values less than
- // 1.0 darken each mip map, and 1.0 has no effect
- BITMAP_IMAGE_PTR *tmipmaps; // local temporary pointer to array of pointers
- // step 1: compute number of mip levels total
- int num_mip_levels = logbase2ofx[source->width] + 1;
- // allocate array of pointers to mip maps
- tmipmaps = (BITMAP_IMAGE_PTR *)malloc(num_mip_levels * sizeof(BITMAP_IMAGE_PTR) );
- // point element 0 (level 0) to entry source
- tmipmaps[0] = source;
- // set width and height (same actually)
- int mip_width = source->width;
- int mip_height = source->height;
- // iterate thru and generate pyramid mipmap levels using averaging filter
- for (int mip_level = 1; mip_level < num_mip_levels; mip_level++)
- {
- // scale size of mip map down one level
- mip_width = mip_width / 2;
- mip_height = mip_height / 2;
- // allocate memory for bitmap object
- tmipmaps[mip_level] = (BITMAP_IMAGE_PTR)malloc(sizeof(BITMAP_IMAGE) );
- // create a bitmap to hold mip map
- Create_Bitmap(tmipmaps[mip_level],0,0, mip_width, mip_height, 16);
- // enable the bitmap for rendering
- SET_BIT(tmipmaps[mip_level]->attr, BITMAP_ATTR_LOADED);
- // now interate thru previous level's mipmap and average down to create this level
- for (int x = 0; x < tmipmaps[mip_level]->width; x++)
- {
- for (int y = 0; y < tmipmaps[mip_level]->height; y++)
- {
- // we need to average the 4 pixel located at:
- // (x*2, y*2), (x*2+1, y*2), (x*2,y*2+1), (x*2+1,y*2+1)
- // in previous mipmap level, and then write them
- // to x,y in this mipmap level :) easy!
- float r0, g0, b0, // r,g,b components of 4 sample pixels
- r1, g1, b1,
- r2, g2, b2,
- r3, g3, b3;
- int r_avg, g_avg, b_avg; // used to compute averages
- USHORT *src_buffer = (USHORT *)tmipmaps[mip_level-1]->buffer,
- *dest_buffer = (USHORT *)tmipmaps[mip_level]->buffer;
- // extract rgb components of each pixel
- _RGB565FROM16BIT( src_buffer[(x*2+0) + (y*2+0)*mip_width*2] , &r0, &g0, &b0);
- _RGB565FROM16BIT( src_buffer[(x*2+1) + (y*2+0)*mip_width*2] , &r1, &g1, &b1);
- _RGB565FROM16BIT( src_buffer[(x*2+0) + (y*2+1)*mip_width*2] , &r2, &g2, &b2);
- _RGB565FROM16BIT( src_buffer[(x*2+1) + (y*2+1)*mip_width*2] , &r3, &g3, &b3);
- // compute average, take gamma into consideration
- r_avg = (int)(0.5f + gamma*(r0+r1+r2+r3)/4);
- g_avg = (int)(0.5f + gamma*(g0+g1+g2+g3)/4);
- b_avg = (int)(0.5f + gamma*(b0+b1+b2+b3)/4);
- // clamp values to max r, g, b values for 5.6.5 format
- if (r_avg > 31) r_avg = 31;
- if (g_avg > 63) g_avg = 63;
- if (b_avg > 31) b_avg = 31;
- // write data
- dest_buffer[x + y*mip_width] = _RGB16BIT565(r_avg,g_avg,b_avg);
- } // end for y
- } // end for x
- } // end for mip_level
- // now assign array of pointers to exit
- *mipmaps = (BITMAP_IMAGE_PTR)tmipmaps;
- // return success
- return(num_mip_levels);
- } // end Generate_Mipmaps
- ///////////////////////////////////////////////////////////////////////////////
- int Delete_Mipmaps(BITMAP_IMAGE_PTR *mipmaps, int leave_level_0)
- {
- // this function deletes all the mipmaps in the chain
- // that each pointer in the array mipmaps points to and
- // then releases the array memory itself, the function has the
- // ability to leave the top level 0 bitmap in place if
- // leave_level_0 flag is 1
- BITMAP_IMAGE_PTR *tmipmaps = (BITMAP_IMAGE_PTR *)*mipmaps;
- // are there any mipmaps
- if (!tmipmaps)
- return(0);
- // step 1: compute number of mip levels total
- int num_mip_levels = logbase2ofx[tmipmaps[0]->width] + 1;
- // iterate thru delete each bitmap
- for (int mip_level = 1; mip_level < num_mip_levels; mip_level++)
- {
- // release the memory for the bitmap buffer
- Destroy_Bitmap(tmipmaps[mip_level]);
- // now release the bitmap object itself
- free(tmipmaps[mip_level]);
- } // end for mip_level
- // now depending on the leave_level_0 flag delete everything or leave the
- // original level 0 in place
- if (leave_level_0 == 1)
- {
- // we need a temp pointer to the level 0 bitmap
- BITMAP_IMAGE_PTR temp = tmipmaps[0];
- // and the array storage too
- //free(*tmipmaps);
- // and assign mipmaps to the original level 0
- *tmipmaps = temp;
- } // end if
- else
- {
- // delete everything!
- Destroy_Bitmap(tmipmaps[0]);
- // now release the bitmap object itself
- free(tmipmaps[0]);
- // and the array storage too
- //free(*tmipmaps);
- } // end else
- // return success
- return(1);
- } // end Delete_Mipmaps
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16(RENDERCONTEXTV1_PTR rc)
- {
- // this function renders the rendering list, it's based on the new
- // rendering context data structure which is container for everything
- // we need to consider when rendering, z, 1/z buffering, alpha, mipmapping,
- // perspective, bilerp, etc. the function is basically a merge of all the functions
- // we have written thus far, so its rather long, but better than having
- // 20-30 rendering functions for all possible permutations!
- POLYF4DV2 face; // temp face used to render polygon
- int alpha; // alpha of the face
- // we need to try and separate as much conditional logic as possible
- // at the beginning of the function, so we can minimize it inline during
- // the traversal of the polygon list, let's start by subclassing which
- // kind of rendering we are doing none, z buffered, or 1/z buffered
- if (rc->attr & RENDER_ATTR_NOBUFFER) ////////////////////////////////////
- {
- // no buffering at all
- // at this point, all we have is a list of polygons and it's time
- // to draw them
- for (int poly=0; poly < rc->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 (!(rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
- (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
- (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
- continue; // move onto next poly
- // test for alpha override
- if (rc->alpha_override>= 0)
- {
- // set alpha to override value
- alpha = rc->alpha_override;
- } // end if
- else
- {
- // extract alpha (even if there isn't any)
- alpha = ((rc->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 (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
- {
- // set the vertices
- face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.tvlist[0].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].u0;
- face.tvlist[0].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].v0;
- face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.tvlist[1].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].u0;
- face.tvlist[1].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].v0;
- face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
- face.tvlist[2].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].u0;
- face.tvlist[2].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].v0;
- // test if this is a mipmapped polygon?
- if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_MIPMAP)
- {
- // determine if mipmapping is desired at all globally
- if (rc->attr & RENDER_ATTR_MIPMAP)
- {
- // determine mip level for this polygon
- // first determine how many miplevels there are in mipchain for this polygon
- int tmiplevels = logbase2ofx[((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0]->width];
- // now based on the requested linear miplevel fall off distance, cut
- // the viewdistance into segments, determine what segment polygon is
- // in and select mip level -- simple! later you might want something more
- // robust, also note I only use a single vertex, you might want to find the average
- // since for long walls perpendicular to view direction this might causing mip
- // popping mid surface
- int miplevel = (tmiplevels * rc->rend_list->poly_ptrs[poly]->tvlist[0].z / rc->mip_dist);
- // clamp miplevel
- if (miplevel > tmiplevels) miplevel = tmiplevels;
- // based on miplevel select proper texture
- face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[miplevel];
- // now we must divide each texture coordinate by 2 per miplevel
- for (int ts = 0; ts < miplevel; ts++)
- {
- face.tvlist[0].u0*=.5;
- face.tvlist[0].v0*=.5;
- face.tvlist[1].u0*=.5;
- face.tvlist[1].v0*=.5;
- face.tvlist[2].u0*=.5;
- face.tvlist[2].v0*=.5;
- } // end for
- } // end if mipmmaping enabled globally
- else // mipmapping not selected globally
- {
- // in this case the polygon IS mipmapped, but the caller has requested NO
- // mipmapping, so we will support this by selecting mip level 0 since the
- // texture pointer is pointing to a mip chain regardless
- face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0];
- // note: texture coordinate manipulation is unneeded
- } // end else
- } // end if
- else
- {
- // assign the texture without change
- face.texture = rc->rend_list->poly_ptrs[poly]->texture;
- } // end if
- // is this a plain emissive texture?
- if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
- {
- // draw the textured triangle as emissive
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_Triangle_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet!
- Draw_Textured_Triangle_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_Triangle_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_Triangle_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_Triangle_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- } // end if
- } // end if
- else
- {
- // non alpha
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- // use bilerp?
- if (rc->attr & RENDER_ATTR_BILERP)
- Draw_Textured_Bilerp_Triangle_16(&face, rc->video_buffer, rc->lpitch);
- else
- Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet
- Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- } // end if
- } // end if
- } // end if
- else
- if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT)
- {
- // draw as flat shaded
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet!
- Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- } // end if
- } // end if
- else
- {
- // non alpha
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet
- Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- } // end if
- } // end if
- } // end else
- else
- {
- // must be gouraud POLY4DV2_ATTR_SHADE_MODE_GOURAUD
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
- face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet!
- Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
- } // end if
- } // end if
- } // end if
- else
- {
- // non alpha
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet
- Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- } // end if
- } // end if
- } // end else
- } // end if
- else
- if ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) ||
- (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
- {
- // draw as constant shaded
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- // set the vertices
- face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
- // draw the triangle with basic flat rasterizer
- // test for transparent
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- Draw_Triangle_2D_Alpha16(&face, rc->video_buffer, rc->lpitch,alpha);
- } // end if
- else
- {
- Draw_Triangle_2D3_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- } // end if
- else
- if (rc->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)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
- face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
- face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
- // draw the gouraud shaded triangle
- // test for transparent
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- Draw_Gouraud_Triangle_Alpha16(&face, rc->video_buffer, rc->lpitch,alpha);
- } // end if
- else
- {
- Draw_Gouraud_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
- } // end if
- } // end if gouraud
- } // end for poly
- } // end if RENDER_ATTR_NOBUFFER
- else
- if (rc->attr & RENDER_ATTR_ZBUFFER) ////////////////////////////////////
- {
- // use the z buffer
- // we have is a list of polygons and it's time draw them
- for (int poly=0; poly < rc->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 (!(rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
- (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
- (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
- continue; // move onto next poly
- // test for alpha override
- if (rc->alpha_override>= 0)
- {
- // set alpha to override value
- alpha = rc->alpha_override;
- } // end if
- else
- {
- // extract alpha (even if there isn't any)
- alpha = ((rc->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 (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
- {
- // set the vertices
- face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.tvlist[0].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].u0;
- face.tvlist[0].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].v0;
- face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.tvlist[1].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].u0;
- face.tvlist[1].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].v0;
- face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
- face.tvlist[2].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].u0;
- face.tvlist[2].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].v0;
- // test if this is a mipmapped polygon?
- if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_MIPMAP)
- {
- // determine if mipmapping is desired at all globally
- if (rc->attr & RENDER_ATTR_MIPMAP)
- {
- // determine mip level for this polygon
- // first determine how many miplevels there are in mipchain for this polygon
- int tmiplevels = logbase2ofx[((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0]->width];
- // now based on the requested linear miplevel fall off distance, cut
- // the viewdistance into segments, determine what segment polygon is
- // in and select mip level -- simple! later you might want something more
- // robust, also note I only use a single vertex, you might want to find the average
- // since for long walls perpendicular to view direction this might causing mip
- // popping mid surface
- int miplevel = (tmiplevels * rc->rend_list->poly_ptrs[poly]->tvlist[0].z / rc->mip_dist);
- // clamp miplevel
- if (miplevel > tmiplevels) miplevel = tmiplevels;
- // based on miplevel select proper texture
- face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[miplevel];
- // now we must divide each texture coordinate by 2 per miplevel
- for (int ts = 0; ts < miplevel; ts++)
- {
- face.tvlist[0].u0*=.5;
- face.tvlist[0].v0*=.5;
- face.tvlist[1].u0*=.5;
- face.tvlist[1].v0*=.5;
- face.tvlist[2].u0*=.5;
- face.tvlist[2].v0*=.5;
- } // end for
- } // end if mipmmaping enabled globally
- else // mipmapping not selected globally
- {
- // in this case the polygon IS mipmapped, but the caller has requested NO
- // mipmapping, so we will support this by selecting mip level 0 since the
- // texture pointer is pointing to a mip chain regardless
- face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0];
- // note: texture coordinate manipulation is unneeded
- } // end else
- } // end if
- else
- {
- // assign the texture without change
- face.texture = rc->rend_list->poly_ptrs[poly]->texture;
- } // end if
- // is this a plain emissive texture?
- if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
- {
- // draw the textured triangle as emissive
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet!
- Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- } // end if
- } // end if
- else
- {
- // non alpha
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- // use bilerp?
- if (rc->attr & RENDER_ATTR_BILERP)
- Draw_Textured_Bilerp_TriangleZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- else
- Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet
- Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if
- } // end if
- } // end if
- else
- if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT)
- {
- // draw as flat shaded
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- // test for transparency
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet
- Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- } // end if
- } // end if
- else
- {
- // non alpha
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet
- Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet
- Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet
- Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if
- } // end if
- } // end else if
- else
- { // POLY4DV2_ATTR_SHADE_MODE_GOURAUD
- // must be gouraud POLY4DV2_ATTR_SHADE_MODE_GOURAUD
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
- face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
- // test for transparency
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet :)
- Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet :)
- Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet :)
- Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- } // end if
- } // end if
- else
- {
- // non alpha
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet :)
- Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet :)
- Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet :)
- Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if
- } // end if
- } // end else
- } // end if
- else
- if ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) ||
- (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
- {
- // draw as constant shaded
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- // set the vertices
- face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
- // draw the triangle with basic flat rasterizer
- // test for transparency
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- Draw_Triangle_2DZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
- } // end if
- else
- {
- // non alpha version
- Draw_Triangle_2DZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if
- else
- if (rc->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)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
- face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
- face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
- // draw the gouraud shaded triangle
- // test for transparency
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- Draw_Gouraud_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
- } // end if
- else
- {
- // non alpha
- Draw_Gouraud_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if gouraud
- } // end for poly
- } // end if RENDER_ATTR_ZBUFFER
- else
- if (rc->attr & RENDER_ATTR_INVZBUFFER) ////////////////////////////////////
- {
- // use the inverse z buffer
- // we have is a list of polygons and it's time draw them
- for (int poly=0; poly < rc->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 (!(rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
- (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
- (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
- continue; // move onto next poly
- // test for alpha override
- if (rc->alpha_override>= 0)
- {
- // set alpha to override value
- alpha = rc->alpha_override;
- } // end if
- else
- {
- // extract alpha (even if there isn't any)
- alpha = ((rc->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 (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
- {
- // set the vertices
- face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.tvlist[0].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].u0;
- face.tvlist[0].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].v0;
- face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.tvlist[1].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].u0;
- face.tvlist[1].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].v0;
- face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
- face.tvlist[2].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].u0;
- face.tvlist[2].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].v0;
- // test if this is a mipmapped polygon?
- if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_MIPMAP)
- {
- // determine if mipmapping is desired at all globally
- if (rc->attr & RENDER_ATTR_MIPMAP)
- {
- // determine mip level for this polygon
- // first determine how many miplevels there are in mipchain for this polygon
- int tmiplevels = logbase2ofx[((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0]->width];
- // now based on the requested linear miplevel fall off distance, cut
- // the viewdistance into segments, determine what segment polygon is
- // in and select mip level -- simple! later you might want something more
- // robust, also note I only use a single vertex, you might want to find the average
- // since for long walls perpendicular to view direction this might causing mip
- // popping mid surface
- int miplevel = (tmiplevels * rc->rend_list->poly_ptrs[poly]->tvlist[0].z / rc->mip_dist);
- // clamp miplevel
- if (miplevel > tmiplevels) miplevel = tmiplevels;
- // based on miplevel select proper texture
- face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[miplevel];
- // now we must divide each texture coordinate by 2 per miplevel
- for (int ts = 0; ts < miplevel; ts++)
- {
- face.tvlist[0].u0*=.5;
- face.tvlist[0].v0*=.5;
- face.tvlist[1].u0*=.5;
- face.tvlist[1].v0*=.5;
- face.tvlist[2].u0*=.5;
- face.tvlist[2].v0*=.5;
- } // end for
- } // end if mipmmaping enabled globally
- else // mipmapping not selected globally
- {
- // in this case the polygon IS mipmapped, but the caller has requested NO
- // mipmapping, so we will support this by selecting mip level 0 since the
- // texture pointer is pointing to a mip chain regardless
- face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0];
- // note: texture coordinate manipulation is unneeded
- } // end else
- } // end if
- else
- {
- // assign the texture without change
- face.texture = rc->rend_list->poly_ptrs[poly]->texture;
- } // end if
- // is this a plain emissive texture?
- if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
- {
- // draw the textured triangle as emissive
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- Draw_Textured_Perspective_Triangle_INVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- Draw_Textured_PerspectiveLP_Triangle_INVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- {
- // use perspective linear
- Draw_Textured_PerspectiveLP_Triangle_INVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- } // end if
- } // end if
- else
- {
- // non alpha
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- // use bilerp?
- if (rc->attr & RENDER_ATTR_BILERP)
- Draw_Textured_Bilerp_TriangleINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- else
- Draw_Textured_TriangleINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- Draw_Textured_Perspective_Triangle_INVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- Draw_Textured_PerspectiveLP_Triangle_INVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- {
- // use perspective linear
- Draw_Textured_PerspectiveLP_Triangle_INVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if
- } // end if
- } // end if
- else
- if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT)
- {
- // draw as flat shaded
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- // test for transparency
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleFSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- Draw_Textured_Perspective_Triangle_FSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- Draw_Textured_PerspectiveLP_Triangle_FSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleFSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- {
- // use perspective linear
- Draw_Textured_PerspectiveLP_Triangle_FSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- } // end if
- } // end if
- else
- {
- // non alpha
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleFSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- Draw_Textured_Perspective_Triangle_FSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- Draw_Textured_PerspectiveLP_Triangle_FSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleFSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- {
- // use perspective linear
- Draw_Textured_PerspectiveLP_Triangle_FSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if
- } // end if
- } // end else if
- else
- { // POLY4DV2_ATTR_SHADE_MODE_GOURAUD
- // must be gouraud POLY4DV2_ATTR_SHADE_MODE_GOURAUD
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
- face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
- // test for transparency
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet :)
- Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet :)
- Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet :)
- Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
- } // end if
- } // end if
- } // end if
- else
- {
- // non alpha
- // which texture mapper?
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
- {
- Draw_Textured_TriangleGSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
- {
- // not supported yet :)
- Draw_Textured_TriangleGSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
- {
- // not supported yet :)
- Draw_Textured_TriangleGSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
- {
- // test z distance again perspective transition gate
- if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
- {
- // default back to affine
- Draw_Textured_TriangleFSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- else
- {
- // use perspective linear
- // not supported yet :)
- Draw_Textured_TriangleGSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if
- } // end if
- } // end else
- } // end if
- else
- if ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) ||
- (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
- {
- // draw as constant shaded
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- // set the vertices
- face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
- // draw the triangle with basic flat rasterizer
- // test for transparency
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- Draw_Triangle_2DINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
- } // end if
- else
- {
- // non alpha version
- Draw_Triangle_2DINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if
- else
- if (rc->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)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
- face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
- face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
- face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
- face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
- face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
- face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
- face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
- face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
- face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
- face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
- face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
- // draw the gouraud shaded triangle
- // test for transparency
- if ((rc->attr & RENDER_ATTR_ALPHA) &&
- ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
- {
- // alpha version
- Draw_Gouraud_TriangleINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
- } // end if
- else
- {
- // non alpha
- Draw_Gouraud_TriangleINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
- } // end if
- } // end if gouraud
- } // end for poly
- } // end if RENDER_ATTR_INVZBUFFER
- } // end Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16
- ////////////////////////////////////////////////////////////////////////////////////////
- void Transform_RENDERLIST4DV2(RENDERLIST4DV2_PTR rend_list, // render list to transform
- MATRIX4X4_PTR mt, // transformation matrix
- int coord_select) // selects coords to transform
- {
- // this function simply transforms all of the polygons vertices in the local or trans
- // array of the render list by the sent matrix
- // what coordinates should be transformed?
- switch(coord_select)
- {
- case TRANSFORM_LOCAL_ONLY:
- {
- for (int poly = 0; poly < rend_list->num_polys; poly++)
- {
- // acquire current polygon
- POLYF4DV2_PTR curr_poly = rend_list->poly_ptrs[poly];
- // is this polygon valid?
- // transform this polygon if and only if it's not clipped, not culled,
- // active, and visible, note however the concept of "backface" is
- // irrelevant in a wire frame engine though
- if ((curr_poly==NULL) || !(curr_poly->state & POLY4DV2_STATE_ACTIVE) ||
- (curr_poly->state & POLY4DV2_STATE_CLIPPED ) ||
- (curr_poly->state & POLY4DV2_STATE_BACKFACE) )
- continue; // move onto next poly
- // all good, let's transform
- for (int vertex = 0; vertex < 3; vertex++)
- {
- // transform the vertex by mt
- POINT4D presult; // hold result of each transformation
- // transform point
- Mat_Mul_VECTOR4D_4X4(&curr_poly->vlist[vertex].v, mt, &presult);
- // store result back
- VECTOR4D_COPY(&curr_poly->vlist[vertex].v, &presult);
- } // end for vertex
- } // end for poly
- } break;
- case TRANSFORM_TRANS_ONLY:
- {
- // transform each "transformed" vertex of the render list
- // remember, the idea of the tvlist[] array is to accumulate
- // transformations
- for (int poly = 0; poly < rend_list->num_polys; poly++)
- {
- // acquire current polygon
- POLYF4DV2_PTR curr_poly = rend_list->poly_ptrs[poly];
- // is this polygon valid?
- // transform this polygon if and only if it's not clipped, not culled,
- // active, and visible, note however the concept of "backface" is
- // irrelevant in a wire frame engine though
- if ((curr_poly==NULL) || !(curr_poly->state & POLY4DV2_STATE_ACTIVE) ||
- (curr_poly->state & POLY4DV2_STATE_CLIPPED ) ||
- (curr_poly->state & POLY4DV2_STATE_BACKFACE) )
- continue; // move onto next poly
- // all good, let's transform
- for (int vertex = 0; vertex < 3; vertex++)
- {
- // transform the vertex by mt
- POINT4D presult; // hold result of each transformation
- // transform point
- Mat_Mul_VECTOR4D_4X4(&curr_poly->tvlist[vertex].v, mt, &presult);
- // store result back
- VECTOR4D_COPY(&curr_poly->tvlist[vertex].v, &presult);
- } // end for vertex
- } // end for poly
- } break;
- case TRANSFORM_LOCAL_TO_TRANS:
- {
- // transform each local/model vertex of the render list and store result
- // in "transformed" vertex list
- for (int poly = 0; poly < rend_list->num_polys; poly++)
- {
- // acquire current polygon
- POLYF4DV2_PTR curr_poly = rend_list->poly_ptrs[poly];
- // is this polygon valid?
- // transform this polygon if and only if it's not clipped, not culled,
- // active, and visible, note however the concept of "backface" is
- // irrelevant in a wire frame engine though
- if ((curr_poly==NULL) || !(curr_poly->state & POLY4DV2_STATE_ACTIVE) ||
- (curr_poly->state & POLY4DV2_STATE_CLIPPED ) ||
- (curr_poly->state & POLY4DV2_STATE_BACKFACE) )
- continue; // move onto next poly
- // all good, let's transform
- for (int vertex = 0; vertex < 3; vertex++)
- {
- // transform the vertex by mt
- Mat_Mul_VECTOR4D_4X4(&curr_poly->vlist[vertex].v, mt, &curr_poly->tvlist[vertex].v);
- } // end for vertex
- } // end for poly
- } break;
- default: break;
- } // end switch
- } // end Transform_RENDERLIST4DV2
- /////////////////////////////////////////////////////////////////////////