📄 t3dlib9.cpp
字号:
// T3DLIB9.CPP - z buffering
// I N C L U D E S ///////////////////////////////////////////////////////////
#define DEBUG_ON
#define WIN32_LEAN_AND_MEAN
#include <windows.h> // include important windows stuff
#include <windowsx.h>
#include <mmsystem.h>
#include <objbase.h>
#include <iostream.h> // include important C/C++ stuff
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include <fcntl.h>
#include <direct.h>
#include <wchar.h>
#include <limits.h>
#include <float.h>
#include <search.h>
#include <ddraw.h> // needed for defs in T3DLIB1.H
#include "T3DLIB1.H"
#include "T3DLIB4.H"
#include "T3DLIB5.H"
#include "T3DLIB6.H"
#include "T3DLIB7.H"
#include "T3DLIB8.H"
#include "T3DLIB9.H"
// DEFINES //////////////////////////////////////////////////////////////////
// GLOBALS //////////////////////////////////////////////////////////////////
// FUNCTIONS ////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void Draw_Triangle_2DZB_16(POLYF4DV2_PTR face, // ptr to face
UCHAR *_dest_buffer, // pointer to video buffer
int mem_pitch, // bytes per line, 320, 640 etc.
UCHAR *_zbuffer, // pointer to z-buffer
int zpitch) // bytes per line of zbuffer
{
// this function draws a flat shaded polygon with zbuffering
int v0=0,
v1=1,
v2=2,
temp=0,
tri_type = TRI_TYPE_NONE,
irestart = INTERP_LHS;
int dx,dy,dyl,dyr, // general deltas
z,
dz,
xi,yi, // the current interpolated x,y
zi, // the current interpolated z
index_x,index_y, // looping vars
x,y, // hold general x,y
xstart,
xend,
ystart,
yrestart,
yend,
xl,
dxdyl,
xr,
dxdyr,
dzdyl,
zl,
dzdyr,
zr;
int x0,y0,tz0, // cached vertices
x1,y1,tz1,
x2,y2,tz2;
USHORT *screen_ptr = NULL,
*screen_line = NULL,
*textmap = NULL,
*dest_buffer = (USHORT *)_dest_buffer;
UINT *z_ptr = NULL,
*zbuffer = (UINT *)_zbuffer;
USHORT color; // polygon color
#ifdef DEBUG_ON
// track rendering stats
debug_polys_rendered_per_frame++;
#endif
// adjust memory pitch to words, divide by 2
mem_pitch >>=1;
// adjust zbuffer pitch for 32 bit alignment
zpitch >>= 2;
// apply fill convention to coordinates
face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
// first trivial clipping rejection tests
if (((face->tvlist[0].y < min_clip_y) &&
(face->tvlist[1].y < min_clip_y) &&
(face->tvlist[2].y < min_clip_y)) ||
((face->tvlist[0].y > max_clip_y) &&
(face->tvlist[1].y > max_clip_y) &&
(face->tvlist[2].y > max_clip_y)) ||
((face->tvlist[0].x < min_clip_x) &&
(face->tvlist[1].x < min_clip_x) &&
(face->tvlist[2].x < min_clip_x)) ||
((face->tvlist[0].x > max_clip_x) &&
(face->tvlist[1].x > max_clip_x) &&
(face->tvlist[2].x > max_clip_x)))
return;
// sort vertices
if (face->tvlist[v1].y < face->tvlist[v0].y)
{SWAP(v0,v1,temp);}
if (face->tvlist[v2].y < face->tvlist[v0].y)
{SWAP(v0,v2,temp);}
if (face->tvlist[v2].y < face->tvlist[v1].y)
{SWAP(v1,v2,temp);}
// now test for trivial flat sided cases
if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
{
// set triangle type
tri_type = TRI_TYPE_FLAT_TOP;
// sort vertices left to right
if (face->tvlist[v1].x < face->tvlist[v0].x)
{SWAP(v0,v1,temp);}
} // end if
else
// now test for trivial flat sided cases
if (FCMP(face->tvlist[v1].y, face->tvlist[v2].y) )
{
// set triangle type
tri_type = TRI_TYPE_FLAT_BOTTOM;
// sort vertices left to right
if (face->tvlist[v2].x < face->tvlist[v1].x)
{SWAP(v1,v2,temp);}
} // end if
else
{
// must be a general triangle
tri_type = TRI_TYPE_GENERAL;
} // end else
// extract vertices for processing, now that we have order
x0 = (int)(face->tvlist[v0].x+0.0);
y0 = (int)(face->tvlist[v0].y+0.0);
tz0 = (int)(face->tvlist[v0].z+0.5);
x1 = (int)(face->tvlist[v1].x+0.0);
y1 = (int)(face->tvlist[v1].y+0.0);
tz1 = (int)(face->tvlist[v1].z+0.5);
x2 = (int)(face->tvlist[v2].x+0.0);
y2 = (int)(face->tvlist[v2].y+0.0);
tz2 = (int)(face->tvlist[v2].z+0.5);
// degenerate triangle
if ( ((x0 == x1) && (x1 == x2)) || ((y0 == y1) && (y1 == y2)))
return;
// extract constant color
color = face->lit_color[0];
// set interpolation restart value
yrestart = y1;
// what kind of triangle
if (tri_type & TRI_TYPE_FLAT_MASK)
{
if (tri_type == TRI_TYPE_FLAT_TOP)
{
// compute all deltas
dy = (y2 - y0);
dxdyl = ((x2 - x0) << FIXP16_SHIFT)/dy;
dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;
dxdyr = ((x2 - x1) << FIXP16_SHIFT)/dy;
dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;
// test for y clipping
if (y0 < min_clip_y)
{
// compute overclip
dy = (min_clip_y - y0);
// computer new LHS starting values
xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
// compute new RHS starting values
xr = dxdyr*dy + (x1 << FIXP16_SHIFT);
zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
// compute new starting y
ystart = min_clip_y;
} // end if
else
{
// no clipping
// set starting values
xl = (x0 << FIXP16_SHIFT);
xr = (x1 << FIXP16_SHIFT);
zl = (tz0 << FIXP16_SHIFT);
zr = (tz1 << FIXP16_SHIFT);
// set starting y
ystart = y0;
} // end else
} // end if flat top
else
{
// must be flat bottom
// compute all deltas
dy = (y1 - y0);
dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dy;
dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy;
dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dy;
dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;
// test for y clipping
if (y0 < min_clip_y)
{
// compute overclip
dy = (min_clip_y - y0);
// computer new LHS starting values
xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
// compute new RHS starting values
xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
// compute new starting y
ystart = min_clip_y;
} // end if
else
{
// no clipping
// set starting values
xl = (x0 << FIXP16_SHIFT);
xr = (x0 << FIXP16_SHIFT);
zl = (tz0 << FIXP16_SHIFT);
zr = (tz0 << FIXP16_SHIFT);
// set starting y
ystart = y0;
} // end else
} // end else flat bottom
// test for bottom clip, always
if ((yend = y2) > max_clip_y)
yend = max_clip_y;
// test for horizontal clipping
if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
(x1 < min_clip_x) || (x1 > max_clip_x) ||
(x2 < min_clip_x) || (x2 > max_clip_x))
{
// clip version
// point screen ptr to starting line
screen_ptr = dest_buffer + (ystart * mem_pitch);
// point zbuffer to starting line
z_ptr = zbuffer + (ystart * zpitch);
for (yi = ystart; yi<=yend; yi++)
{
// compute span endpoints
xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
// compute starting points for u,v,w interpolants
zi = zl + FIXP16_ROUND_UP;
// compute u,v interpolants
if ((dx = (xend - xstart))>0)
{
dz = (zr - zl)/dx;
} // end if
else
{
dz = (zr - zl);
} // end else
///////////////////////////////////////////////////////////////////////
// test for x clipping, LHS
if (xstart < min_clip_x)
{
// compute x overlap
dx = min_clip_x - xstart;
// slide interpolants over
zi+=dx*dz;
// reset vars
xstart = min_clip_x;
} // end if
// test for x clipping RHS
if (xend > max_clip_x)
xend = max_clip_x;
///////////////////////////////////////////////////////////////////////
// draw span
for (xi=xstart; xi<=xend; xi++)
{
// 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] = color;
// update z-buffer
z_ptr[xi] = zi;
} // end if
// interpolate u,v,w,z
zi+=dz;
} // end for xi
// interpolate z,x along right and left edge
xl+=dxdyl;
zl+=dzdyl;
xr+=dxdyr;
zr+=dzdyr;
// advance screen ptr
screen_ptr+=mem_pitch;
// advance z-buffer ptr
z_ptr+=zpitch;
} // end for y
} // end if clip
else
{
// non-clip version
// point screen ptr to starting line
screen_ptr = dest_buffer + (ystart * mem_pitch);
// point zbuffer to starting line
z_ptr = zbuffer + (ystart * zpitch);
for (yi = ystart; yi<=yend; yi++)
{
// compute span endpoints
xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
// compute starting points for u,v,w interpolants
zi = zl + FIXP16_ROUND_UP;
// compute u,v interpolants
if ((dx = (xend - xstart))>0)
{
dz = (zr - zl)/dx;
} // end if
else
{
dz = (zr - zl);
} // end else
// draw span
for (xi=xstart; xi<=xend; xi++)
{
// 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] = color;
// update z-buffer
z_ptr[xi] = zi;
} // end if
// interpolate z
zi+=dz;
} // end for xi
// interpolate x,z along right and left edge
xl+=dxdyl;
zl+=dzdyl;
xr+=dxdyr;
zr+=dzdyr;
// advance screen ptr
screen_ptr+=mem_pitch;
// advance z-buffer ptr
z_ptr+=zpitch;
} // end for y
} // end if non-clipped
} // end if
else
if (tri_type==TRI_TYPE_GENERAL)
{
// first test for bottom clip, always
if ((yend = y2) > max_clip_y)
yend = max_clip_y;
// pre-test y clipping status
if (y1 < min_clip_y)
{
// compute all deltas
// LHS
dyl = (y2 - y1);
dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;
// RHS
dyr = (y2 - y0);
dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
// compute overclip
dyr = (min_clip_y - y0);
dyl = (min_clip_y - y1);
// computer new LHS starting values
xl = dxdyl*dyl + (x1 << FIXP16_SHIFT);
zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
// compute new RHS starting values
xr = dxdyr*dyr + (x0 << FIXP16_SHIFT);
zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
// compute new starting y
ystart = min_clip_y;
// test if we need swap to keep rendering left to right
if (dxdyr > dxdyl)
{
SWAP(dxdyl,dxdyr,temp);
SWAP(dzdyl,dzdyr,temp);
SWAP(xl,xr,temp);
SWAP(zl,zr,temp);
SWAP(x1,x2,temp);
SWAP(y1,y2,temp);
SWAP(tz1,tz2,temp);
// set interpolation restart
irestart = INTERP_RHS;
} // end if
} // end if
else
if (y0 < min_clip_y)
{
// compute all deltas
// LHS
dyl = (y1 - y0);
dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;
// RHS
dyr = (y2 - y0);
dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;
// compute overclip
dy = (min_clip_y - y0);
// computer new LHS starting values
xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
// compute new RHS starting values
xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
// compute new starting y
ystart = min_clip_y;
// test if we need swap to keep rendering left to right
if (dxdyr < dxdyl)
{
SWAP(dxdyl,dxdyr,temp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -