⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t3dlib9.cpp

📁 3D游戏编程大师技巧第十一章的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// 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 + -