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

📄 simpleobject8.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
字号:
/*********************************************************************NVMH2****
Path:  c:\Dev\devrel\Nv_sdk_4\Dx8\NVEffectsBrowser\Effects\SimpleFog
File:  SimpleObject8.cpp

Copyright (C) 1999, 2000 NVIDIA Corporation
This file is provided without support, instruction, or implied warranty of any
kind.  NVIDIA makes no guarantee of its fitness for a particular purpose and is
not liable under any circumstances for any damages or loss whatsoever arising
from the use or inability to use this file or items derived from it.

Comments:

This code doesn't use vertex buffers for rendering.  For any sort of serious
application, this is a big mistake.  You should use vertex buffers all the time.
We have papers on our developer website about this.

Switching to vertex buffers does not change the code for vertex or pixel shaders,
and offers significant performance improvements.




******************************************************************************/



#include <assert.h>
#include "SimpleObject8.h"
#include "NV_Error.h"

#include <math.h>


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


#define UL_PI      3.1415926535897932384626433832795028841971693993751
#define UL_SQRT_2  1.4142135623730950488016887242096980785696718753769
#define UL_PI2     (UL_PI/2.0)


#define BOUNDCHK(in, cmp, msg, quit) {if(in>=cmp){DoError(msg,quit);}}

//////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

SimpleObject8::SimpleObject8()
{
	m_pVertices = NULL;
	m_pIndices	= NULL;

	m_wNumVerts = 0;
	m_nNumInd	= 0;
	m_PrimType  = D3DPT_TRIANGLELIST;

	m_bIsValid = false;
}

SimpleObject8::~SimpleObject8()
{
	UnAllocate();
}

//////////////////////////////////////////////////////////////////////

void SimpleObject8::UnAllocate()
{
	if( m_pVertices )
		free( m_pVertices	);
	if( m_pIndices	)
		free( m_pIndices	);

	m_pVertices = NULL;
	m_pIndices = NULL;

	m_wNumVerts = 0;
	m_nNumInd	= 0;
	m_PrimType  = D3DPT_TRIANGLELIST;

	m_bIsValid = false;
}



void SimpleObject8::Allocate( WORD nvert, int nind )
{
	UnAllocate();

	m_pVertices = (SimpleObjVertex*) calloc( nvert, sizeof( SimpleObjVertex ) );
	NULLCHECK( m_pVertices, "SimpleObject8:: Can't allocate vertices!", true );
	m_wNumVerts = nvert;

	m_pIndices = (WORD*) calloc( nind, sizeof( WORD ) );
	NULLCHECK( m_pIndices, "SimpleObject8:: Can't allocate indices!", true );
	m_nNumInd = nind;

}


//-----------------------------------------------------------------------------
// Name: SimpleObject8::InitSphere( float radius, int nLat, int nLong )
// Desc: Make a 'dumb' sphere by sweeping an arc.  'dumb' cause it will have
//		a lot of points at the poles
//-----------------------------------------------------------------------------

void SimpleObject8::InitSphere( float radius, int nLat, int nLong )
{
	int i,j;

	if( nLong < 1 )	nLong = 1;
	if( nLat  < 3 ) nLat  = 3;
	if( radius < 0 ) radius = -radius;

	nLong++;		// repeat edge for texture coord happy
	nLat+=2;		// two rings on the ends

	WORD nvert = nLong * nLat;	
	int ntri  = 2 * nLong * nLat;

	m_PrimType  = D3DPT_TRIANGLELIST;

	// Allocate memory:
	Allocate( nvert, ntri * 3 );

	//m_csDesc = "I'm a sphere!";
	//m_csName = "Sphere01";

	// make vertex positions
	int index;
	float ringz;			// z cord of a latitude ring
	float ring_r;			// radius of x,y ring
	float theta, rho;		// theta = x,y plane angle, rho = z
	float x,y,u,v;				// x,y coord of pt.
	float mag;
	

	for( j=0; j < nLat; j++ )
	{
		rho = (float)( UL_PI * j / (float)(nLat-1) - UL_PI/2.0f );
		ringz  = (float) ( radius * sin(rho) );
		ring_r = (float) sqrt( radius * radius - ringz*ringz );

		for( i=0; i < nLong; i++)
		{
			theta = (float)( 2* UL_PI * i / (float)( nLong - 1 ) );
			x = (float) ( ring_r * cos(theta) );
			y = (float) ( ring_r * sin(theta) );

			index = i + j*nLong;
			if( index > m_wNumVerts )
			{
				FDebug("InitSphere Error! %n index of only %n allocated!\n", index, m_wNumVerts );
				index = m_wNumVerts -1;
			}

			m_pVertices[ index ].pos.x = x;
			m_pVertices[ index ].pos.y = y;
			m_pVertices[ index ].pos.z = ringz;
			
			u = (float)( (float)i/(float)(nLong-1) );
			v = (float)( (float)j/(float)(nLat-1)  );
			// Correct for sphere pinch & "degenerate" triangle at caps
			if( j==0 )
			{
				u -= 0.5f / (float)nLong;
			}
			else if( j == nLat-1 )
			{
				u += 0.5f / (float)nLong;
			}
			m_pVertices[ index ].t0.x = u;
			m_pVertices[ index ].t0.y = v;

			//FDebug("U:  %f    V:  %f   ind: %d\n", u, v, index );

			mag = (float)sqrt( x*x + y*y + ringz*ringz );
			m_pVertices[ index ].nrm.x = x/mag;
			m_pVertices[ index ].nrm.y = y/mag;
			m_pVertices[ index ].nrm.z = ringz/mag;
			
			// m_pVertices[ index ].diffuse = D3DRGB( u, v, 1-u );
			m_pVertices[ index ].diffuse = D3DCOLOR_ARGB( 255, 255, 255, 255 );

		}
	}


	// stitch the tris
	// Culling is CCW

	WORD  nind = 0;
	WORD  i0, i1, i2, i3;

	for( j=0; j < nLat-1; j++ )
	{
		for( i=0; i < nLong; i++)
		{
			i0 = i   + j*nLong;
			i1 = i   + (j+1)*nLong;
			i2 = (i+1)%nLong + j*nLong;		// % to wrap back to zero
			i3 = (i+1)%nLong + (j+1)*nLong;
		
			BOUNDCHK( nind, m_nNumInd-2, "InitSphere:: Index too high!", true );

			m_pIndices[nind++] = i2;
			m_pIndices[nind++] = i1;
			m_pIndices[nind++] = i0;

			BOUNDCHK( nind, m_nNumInd-2, "InitSphere:: Index too high 2!", true );
			m_pIndices[nind++] = i3;
			m_pIndices[nind++] = i1;
			m_pIndices[nind++] = i2;
		}
	}

	m_bIsValid = true;
	// all done!
}

void SimpleObject8::InitSpiral( float width, float height, int n_sub_width,
					int n_sub_height, float n_twists )
{

	int i,j;
	int nvert, nind;

	if( n_sub_height < 0 )
		n_sub_height = 0;
	if( n_sub_width < 0 )
		n_sub_width = 0;


	nvert = (2 + n_sub_width)*(n_sub_height + 2);
	nind = (n_sub_width+1)*(n_sub_height+1)*2 * 3;


	if( nvert > MAX_VERT_IND )
	{
		FDebug("Can't create object - too many verts!\n");
		assert( false );
		return;
	}


	Allocate( nvert, nind );

	m_PrimType = D3DPT_TRIANGLELIST;

	float z;
	float dz, dx;
	float angle;
	float da;
	float radius;

	z = -height / 2.0f;
	angle = 0;
	
	dz = height / (n_sub_height+1.0f);
	da = (float)( n_twists * UL_PI * 2.0f ) / (n_sub_height + 1.0f);

	dx =  width / ( (float)n_sub_width + 1.0f );


	int ind;

	for( j=0; j < n_sub_height + 2; j++ )
	{
		for(i=0; i < n_sub_width + 2; i++)
		{
			radius = width/2.0f - dx * i;

			ind = i + j * (n_sub_width+2);

			assert( ind < nvert );

			m_pVertices[ ind ].pos.x = radius * (float) sin( angle );
			m_pVertices[ ind ].pos.y = radius * (float) cos( angle );
			m_pVertices[ ind ].pos.z = z;

			m_pVertices[ ind ].t0.x = (float)i/(n_sub_width  +1.0f);
			m_pVertices[ ind ].t0.y = (float)j/(n_sub_height +1.0f);

		}

		z += dz;
		angle += da;
	}

	// Set the indices
	int triind;				// triind = index of triangle -> 3 for each
							//   so 0,1,2 = 1st tri, 3,4,5 = 2nd tri
	triind = 0;




	for( j=0; j < n_sub_height + 1; j++ )
	{
		for( i=0; i < n_sub_width + 1; i++ )
		{

			if( i + j*(n_sub_width + 1) >= nvert )
				assert( false );
			if( i + 1 + j * ( n_sub_width + 2 ) >= nvert )
				assert( false );

			if( triind >= nind )
			{
				FDebug( "bad index calc: %d of %d", triind, nind );
				assert( false );
			}

			assert( triind < nind );
			m_pIndices[ triind++ ] = i + j*(n_sub_width+2);
			assert( triind < nind );
			m_pIndices[ triind++ ] = i + 1 + (j+1)*(n_sub_width+2);
			assert( triind < nind );
			m_pIndices[ triind++ ] = i + 1 + j*(n_sub_width+2);
			assert( triind < nind );

			m_pIndices[ triind++ ] = i + j*(n_sub_width+2);
			assert( triind < nind );
			m_pIndices[ triind++ ] = i + (j+1)*(n_sub_width+2);
			assert( triind < nind );
			m_pIndices[ triind++ ] = i + 1 + (j+1)*(n_sub_width+2);		
		}
	}
}


void SimpleObject8::AddPositionNoise( D3DXVECTOR3 vNoiseDir, float noise_magnitude )
{
	
	int numvert = m_wNumVerts;

	D3DXVECTOR3 noise;

	for( int ind = 0; ind < numvert; ind++ )
	{
		noise = vNoiseDir * noise_magnitude * ( ((float)rand())/(float)RAND_MAX );
		
		m_pVertices[ ind ].pos.x += noise.x;
		m_pVertices[ ind ].pos.y += noise.y;
		m_pVertices[ ind ].pos.z += noise.z;		
	}
}


void SimpleObject8::AddPositionNoiseGrid( D3DXVECTOR3 vNoiseDir, float noise_magnitude,
										  int grid_nx, int nsmooth )
{
	// Add noise to the positions with possibility for averaging the noise
	//   values with their nearest neighbors as though they lie on a grid 
	//   of x dimension grid_nx.
	// Function does a crude compensation if the number of vertices doesn't fill
	//   out the last line of the imposed grid.
	// noise_magnitude is max magnitude that will be added - the noise field
	//   is scaled so the max value is that.

	int numvert = m_wNumVerts;

	int gridx = grid_nx;
	int gridy = m_wNumVerts/gridx;

	if( gridy * gridx != m_wNumVerts )
	{
		FDebug("SimpleObject8 -- AddPositionNoiseGrid Vertices not a rectangular grid!\n");
		FDebug("    Compensating for remaining verts...\n");

		gridy++;
	}

	D3DXVECTOR3 noise;

	float * noisemag = (float*) calloc( numvert, sizeof( float ));
	assert( noisemag != NULL );

	int ind;

	for( ind = 0; ind < numvert; ind++ )
	{
		noisemag[ind] = ( ((float)rand())/(float)RAND_MAX );
	}

	// now smooth the noise according to the grid
	int i,j, n;
	int ind0, ind1;

	float avg;
	float maxmag;
	float minmag;

	for( n=0; n < nsmooth; n++ )
	{
		maxmag = 0;
		minmag = 9e9f;

		for( j=0; j < gridy; j++ )
			for( i=0; i < gridx; i++ )
			{	
				ind0 = j*gridx + i;
				
				if( ind0 > numvert-1 )
				{
					FDebug("broke on:  %d    %d\n", i,j );
					break;
				}

				avg = noisemag[ind0];


				ind1 = ind0 + 1;

				if( ind1 > numvert-1 )
					ind1 = numvert-1;
				avg += noisemag[ind1];


				ind1 = ind0 + gridx;

				if( ind1 > numvert-1 )
				{
					ind1 = i;
				}
				avg += noisemag[ind1];


				ind1 = ind0 + gridx + 1;

				if( ind1 > numvert-1 )
				{
					ind1 = i + 1;
				}
				avg += noisemag[ind1];

				noisemag[ ind0 ] = avg / 4.0f;

				if( noisemag[ ind0 ] > maxmag )
				{
					maxmag = noisemag[ ind0 ];
				}
				if( noisemag[ ind0 ] < minmag )
				{
					minmag = noisemag[ ind0 ];
				}
			}
	}

	// scale the noise values so their max is noise_magnitude
	float scale;
	maxmag = maxmag - minmag;

	if( maxmag > 0.0f )
		scale = noise_magnitude / maxmag;
	else
	{
		scale = 0.0f;
		FDebug("AddPositionNoiseGrid: Using scale of 0.0f!!\n");
	}


	for( i=0; i < numvert; i++ )
	{
		noisemag[i] = ( noisemag[i] - minmag ) * scale;
	}


	for( ind = 0; ind < numvert; ind++ )
	{
		noise = vNoiseDir * noisemag[ind];
		
		m_pVertices[ ind ].pos.x += noise.x;
		m_pVertices[ ind ].pos.y += noise.y;
		m_pVertices[ ind ].pos.z += noise.z;		
	}


	free( noisemag );
}


void SimpleObject8::TranslateXMinToZero()
{
	int numvert = m_wNumVerts;

	float minx = 9e9f;
	int ind;

	for( ind = 0; ind < numvert; ind++ )
	{
		if( m_pVertices[ ind ].pos.x < minx )
			minx = m_pVertices[ ind ].pos.x;
	}

	for( ind = 0; ind < numvert; ind++ )
	{
		m_pVertices[ ind ].pos.x -= minx;
	}
}


void SimpleObject8::GenerateNormals()
{
	assert( m_pIndices != NULL );
	assert( m_pVertices != NULL );

	if( m_PrimType != D3DPT_TRIANGLELIST )
	{
		FDebug("Error: primitive type must be D3DPT_TRIANGLELIST\n");
		assert( false );
	}


	int i;
	int vi0, vi1, vi2;	    // vertex indices of triangle

	// zero normals for accumulation
	for( i=0; i < m_wNumVerts; i++ )
	{
		m_pVertices[i].nrm.x = 0.0f;
		m_pVertices[i].nrm.y = 0.0f;
		m_pVertices[i].nrm.z = 0.0f;
	}

	// find each triangle's normal and add into the 
	//   vertex normal

	D3DXVECTOR3 v0, v1, v2;
	D3DXVECTOR3 d0, d1, nrm;

	i=0;
	while( i < m_nNumInd )
	{
		vi0 = m_pIndices[i++];		
		vi1 = m_pIndices[i++];		
		vi2 = m_pIndices[i++];		

		v0 = m_pVertices[ vi0 ].pos;
		v1 = m_pVertices[ vi1 ].pos;
		v2 = m_pVertices[ vi2 ].pos;

		d0 = v1 - v0;
		d1 = v2 - v0;

		D3DXVec3Cross( &nrm, &d0, &d1 );		// triangle normal

		//  accumulate into vertex normals:

		m_pVertices[ vi0 ].nrm += nrm;
		m_pVertices[ vi1 ].nrm += nrm;
		m_pVertices[ vi2 ].nrm += nrm;
	}

	// normalize the normals
	for( i=0; i < m_wNumVerts; i++ )
	{
		D3DXVec3Normalize( &( m_pVertices[i].nrm ), &( m_pVertices[i].nrm ) );
	}
}







void SimpleObject8::Draw( LPDIRECT3DDEVICE8  pD3DDev )
{
	assert( pD3DDev != NULL );

	pD3DDev->DrawIndexedPrimitiveUP(	m_PrimType,
										0,				// min index
										m_wNumVerts,
										m_nNumInd/3,	// prim count
										m_pIndices,
										D3DFMT_INDEX16,
										m_pVertices,
										sizeof( SimpleObjVertex ) );


}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -