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

📄 simpleobject8.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			m_pVertices[ vind ].nrm.z = nz / length;

			// Set texture coords:
			m_pVertices[ vind ].t0.x = pRing[i].t0.x;
			m_pVertices[ vind ].t0.y = (float) j / (float) Rings;
		}
	}

	///////////////////////////////////////////
	// Now make indices to form triangles

	int ind;			// index location to fill with a vertex index
	int v1, v2, v3;		// vertex indices of a triangle
	UINT jplus, iplus;	// j+1, i+1 wrapped back to 0 if > Rings or Sides, respectively


	ind = 0;

	for( j=0; j < Rings; j ++ )
	{
		for( i=0; i < Sides; i++ )
		{
			// first triangle of each "square" patch of surface
			//  on the torus

			iplus = i + 1;
			if( iplus == Sides )
				iplus = 0;
			jplus = j + 1;
			if( jplus == Rings )
				jplus = 0;


			// CCW winding order
			v1 = j		* Sides		+ i;
			v2 = j		* Sides		+ iplus;
			v3 = jplus	* Sides		+ i;


			assert( v1 < nvert && v1 >= 0 );
			assert( v2 < nvert && v2 >= 0 );
			assert( v3 < nvert && v3 >= 0 );

			assert( ind < nind );
			m_pIndices[ ind++ ] = v1;
			assert( ind < nind );
			m_pIndices[ ind++ ] = v2;
			assert( ind < nind );
			m_pIndices[ ind++ ] = v3;

			// second triangle of the pair
			v1 = v3;
			v2 = v2;
			v3 = jplus * Sides	+ iplus;

			assert( v3 < nvert && v1 >= 0 );

			assert( ind < nind );
			m_pIndices[ ind++ ] = v1;
			assert( ind < nind );
			m_pIndices[ ind++ ] = v2;
			assert( ind < nind );
			m_pIndices[ ind++ ] = v3;

		}
	}



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

	if( pRing != NULL )
	{
		free( pRing );
		pRing = NULL;
	}
}



void SimpleObject8::InitTorus( float InnerRadius, float OuterRadius, UINT Sides, UINT Rings )
{
	// Creates a torus "spun" about the z axis.
	// With this non=wrapped model, vertices overlap at the seams.  
	// These overlapped vertices have appropriate texture coords so no
	//  change in tex coord wrapping mode is necessary.


	UINT i,j;
	int nvert, nind;

	if( Sides < 3 )
		Sides = 3;
	if( Rings < 3 )
		Rings = 3;
	if( InnerRadius > OuterRadius )
	{
		float tmp = InnerRadius;
		InnerRadius = OuterRadius;
		OuterRadius = InnerRadius;
	}

	nvert = ( Sides + 1 ) * ( Rings + 1 );
	nind = 3 * Sides * 2 * Rings;		// # of triangle vertex indices

	// allocate memory for vertices
	Allocate( nvert, nind );


	m_PrimType = D3DPT_TRIANGLELIST;	// Could optimize to create tri
										//  strips, but not today!


	// Fill in vertex data

	// phi is angle around z axis
	// theta is angle around each ring

	UINT  nphi_verts;
	UINT  ntheta_verts;

	nphi_verts = Rings + 1;
	ntheta_verts = Sides + 1;

	float d_phi = 2.0f * (float)UL_PI / ((float)(nphi_verts - 1) );
	float d_theta = 2.0f * (float)UL_PI / ((float)(ntheta_verts - 1));

	float cent_radius = (InnerRadius + OuterRadius) / 2.0f;
	float ring_radius = (OuterRadius - InnerRadius) / 2.0f;

	float angle;


	SimpleObjVertex * pRing = (SimpleObjVertex*) calloc( ntheta_verts, sizeof( SimpleObjVertex));
	NULLCHECK( pRing, "SimpleObject8:: Can't allocate a ring of vertices!", true );


	// make the first ring - centered about cent_radius;
	for( i=0; i < ntheta_verts; i++ )
	{
		angle = (float) i * d_theta;

		pRing[i].pos.x = ring_radius * ((float)cos( angle ));
		pRing[i].pos.z = ring_radius * ((float)sin( angle ));
		pRing[i].pos.y = 0.0f;

		pRing[i].pos.x += cent_radius;

		// Set normals
		pRing[i].nrm.x = (float) cos( angle );
		pRing[i].nrm.z = (float) sin( angle );
		pRing[i].nrm.y = 0.0f;

		pRing[i].t0.x = (float) i / (float)(ntheta_verts - 1);
	}

	int vind;
	float nx, ny, nz, length;
	vind = 0;

	for( j=0; j < nphi_verts; j++ )
	{
		// rotate each ring into position
		//  around the sweep angle
		
		angle = (float) j * d_phi;

		for( i=0; i < ntheta_verts; i++, vind++ )
		{
			assert( vind < nvert );
			m_pVertices[ vind ].pos.x = pRing[i].pos.x * ((float)cos( angle ));
			m_pVertices[ vind ].pos.y = pRing[i].pos.x * ((float)sin( angle ));
			m_pVertices[ vind ].pos.z = pRing[i].pos.z;

			// rotate normals into position
			nx = m_pVertices[ vind ].nrm.x = pRing[i].nrm.x * ((float)cos(angle));
			ny = m_pVertices[ vind ].nrm.y = pRing[i].nrm.x * ((float)sin(angle));
			nz = m_pVertices[ vind ].nrm.z = pRing[i].nrm.z;

			// normalize normals.  Shouldn't have to in this case, but
			//  just a safety measure.
			length = (float) sqrt(nx*nx + ny*ny + nz*nz);
			assert( length > 0.0f );

			m_pVertices[ vind ].nrm.x = nx / length;
			m_pVertices[ vind ].nrm.y = ny / length;
			m_pVertices[ vind ].nrm.z = nz / length;

			// Set texture coords:
			m_pVertices[ vind ].t0.x = pRing[i].t0.x;
			m_pVertices[ vind ].t0.y = (float) j / (float)( nphi_verts - 1);
		}
	}

	///////////////////////////////////////////
	// Now make indices to form triangles

	int ind;			// index location to fill with a vertex index
	int v1, v2, v3;		// vertex indices of a triangle
	UINT jplus, iplus;	// j+1, i+1 wrapped back to 0 if > Rings or Sides, respectively


	ind = 0;

	for( j=0; j < Rings; j ++ )
	{
		for( i=0; i < Sides; i++ )
		{
			// first triangle of each "square" patch of surface
			//  on the torus

			iplus = i + 1;
			jplus = j + 1;

			// CCW winding order
			v1 = j		* ntheta_verts		+ i;
			v2 = j		* ntheta_verts		+ iplus;
			v3 = jplus	* ntheta_verts		+ i;


			assert( v1 < nvert && v1 >= 0 );
			assert( v2 < nvert && v2 >= 0 );
			assert( v3 < nvert && v3 >= 0 );

			assert( ind < nind );
			m_pIndices[ ind++ ] = v1;
			assert( ind < nind );
			m_pIndices[ ind++ ] = v2;
			assert( ind < nind );
			m_pIndices[ ind++ ] = v3;

			// second triangle of the pair
			v1 = v3;
			v2 = v2;
			v3 = jplus * ntheta_verts	+ iplus;

			assert( v3 < nvert && v1 >= 0 );

			assert( ind < nind );
			m_pIndices[ ind++ ] = v1;
			assert( ind < nind );
			m_pIndices[ ind++ ] = v2;
			assert( ind < nind );
			m_pIndices[ ind++ ] = v3;
		}
	}



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

	if( pRing != NULL )
	{
		free( pRing );
		pRing = NULL;
	}

}


void SimpleObject8::InitTorus( float InnerRadius, float OuterRadius, UINT Sides, UINT Rings,
								float TexCoordUMax, float TexCoordVMax )
{

	// Create a torus with user-adjustable scaling of texture coords so a 
	//  texture can repeat several times around the torus

	InitTorus( InnerRadius, OuterRadius, Sides, Rings );

	int i;

	for( i=0; i < m_wNumVerts; i ++ )
	{
		m_pVertices[i].t0.x *= TexCoordUMax;
		m_pVertices[i].t0.y *= TexCoordVMax;
	}
}



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.0f;
		minmag = FLT_MAX;

		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
		assert( false );		// something's gone wrong in the calcs

	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::Translate( float x, float y, float z )
{

	int numvert = m_wNumVerts;
	int ind;

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


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

	float minx = FLT_MAX;
	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_wNumInd )
	{
		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, &d1, &d0 );		// 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_wNumInd/3,	// prim count
										m_pIndices,
										D3DFMT_INDEX16,
										m_pVertices,
										sizeof( SimpleObjVertex ) );


}



/*
// Old dX7 func - no longer applicable
HRESULT SimpleObject8::Draw( LPDIRECT3DDEVICE7 pDev )
{
	HRESULT res = E_FAIL;

	if( pDev && m_bIsValid )
	{
		res = pDev->DrawIndexedPrimitive( m_PrimType, gSObjVertexFVF,
						m_pVertices, m_wNumVerts, m_pIndices, m_wNumInd, 0 );
	}

	return res;
}
*/

⌨️ 快捷键说明

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