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

📄 terrain.cpp

📁 game programing code
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	//normalize the terrain for our purposes
	NormalizeTerrain( fTempBuffer );

	//transfer the terrain into our class's unsigned char height buffer
	for( z=0; z<m_iSize; z++ )
	{
		for( x=0; x<m_iSize; x++ )
			SetHeightAtPoint( ( unsigned char )fTempBuffer[( z*m_iSize )+x], x, z );
	}

	//delete temporary buffer
	if( fTempBuffer )
	{
		//delete the data
		delete[] fTempBuffer;
	}

	return true;
}

//--------------------------------------------------------------
// Name:			CTERRAIN::MakeTerrainPlasma - public
// Description:		Create a height data set using the "Midpoint
//					Displacement" algorithm.  Thanks a lot to 
//					Jason Shankel for this code!
// Arguments:		-iSize: Desired size of the height map
//					-fRoughness: Desired roughness of the created map
// Return Value:	A boolean value: -true: successful creation
//									 -false: unsuccessful creation
//--------------------------------------------------------------
bool CTERRAIN::MakeTerrainPlasma( int iSize, float fRoughness )
{
	float* fTempBuffer;
	float fHeight, fHeightReducer;
	int iRectSize= iSize;
	int ni, nj;
	int mi, mj;
	int pmi, pmj;
	int i, j;
	int x, z;

	if( m_heightData.m_ucpData )
		UnloadHeightMap( );

	if( fRoughness<0 )
		fRoughness*= -1;

	fHeight		  = ( float )iRectSize/2.0f;
	fHeightReducer= ( float )pow( 2, -1*fRoughness );

	m_iSize= iSize;

	//allocate the memory for our height data
	m_heightData.m_ucpData= new unsigned char [m_iSize*m_iSize];
	fTempBuffer= new float [m_iSize*m_iSize];

	//check to see if memory was successfully allocated
	if( m_heightData.m_ucpData==NULL )
	{
		//something is seriously wrong here
		g_log.Write( LOG_FAILURE, "Could not allocate memory for height map" );
		return false;
	}

	//check to see if memory was successfully allocated
	if( fTempBuffer==NULL )
	{
		//something is seriously wrong here
		g_log.Write( LOG_FAILURE, "Could not allocate memory for height map" );
		return false;
	}

	//set the first value in the height field
	fTempBuffer[0]= 0.0f;

	//being the displacement process
	while( iRectSize>0 )
	{
		/*Diamond step -

		Find the values at the center of the retangles by averaging the values at 
		the corners and adding a random offset:


		a.....b
		.     .  
		.  e  .
		.     .
		c.....d   

		e  = (a+b+c+d)/4 + random

		In the code below:
		a = (i,j)
		b = (ni,j)
		c = (i,nj)
		d = (ni,nj)
		e = (mi,mj)   */
		for( i=0; i<m_iSize; i+=iRectSize )
		{
			for( j=0; j<m_iSize; j+=iRectSize )
			{
				ni= ( i+iRectSize )%m_iSize;
				nj= ( j+iRectSize )%m_iSize;

				mi= ( i+iRectSize/2 );
				mj= ( j+iRectSize/2 );

				fTempBuffer[mi+mj*m_iSize]= ( float )( ( fTempBuffer[i+j*m_iSize] + fTempBuffer[ni+j*m_iSize] + fTempBuffer[i+nj*m_iSize] + fTempBuffer[ni+nj*m_iSize] )/4 + RangedRandom( -fHeight/2, fHeight/2 ) );
			}
		}

		/*Square step -

		Find the values on the left and top sides of each rectangle
		The right and bottom sides are the left and top sides of the neighboring rectangles,
		  so we don't need to calculate them

		The height m_heightData.m_ucpData wraps, so we're never left hanging.  The right side of the last
			rectangle in a row is the left side of the first rectangle in the row.  The bottom
			side of the last rectangle in a column is the top side of the first rectangle in
			the column

              .......
		      .     .
		      .     .
		      .  d  .
		      .     .
		      .     .
		......a..g..b
		.     .     .
		.     .     .
		.  e  h  f  .
		.     .     .
		.     .     .
		......c......

		g = (d+f+a+b)/4 + random
		h = (a+c+e+f)/4 + random
		
		In the code below:
			a= (i,j) 
			b= (ni,j) 
			c= (i,nj) 
			d= (mi,pmj) 
			e= (pmi,mj) 
			f= (mi,mj) 
			g= (mi,j)
			h= (i,mj)*/
		for( i=0; i<m_iSize; i+=iRectSize )
		{
			for( j=0; j<m_iSize; j+=iRectSize )
			{

				ni= ( i+iRectSize )%m_iSize;
				nj= ( j+iRectSize )%m_iSize;

				mi= ( i+iRectSize/2 );
				mj= ( j+iRectSize/2 );

				pmi= ( i-iRectSize/2+m_iSize )%m_iSize;
				pmj= ( j-iRectSize/2+m_iSize )%m_iSize;
				
				//Calculate the square value for the top side of the rectangle
				fTempBuffer[mi+j*m_iSize]= ( float )( ( fTempBuffer[i+j*m_iSize]	  +
														fTempBuffer[ni+j*m_iSize]	  +
														fTempBuffer[mi+pmj*m_iSize]	  +
														fTempBuffer[mi+mj*m_iSize] )/4+
														RangedRandom( -fHeight/2, fHeight/2 ) );

				//Calculate the square value for the left side of the rectangle
				fTempBuffer[i+mj*m_iSize]= ( float )( ( fTempBuffer[i+j*m_iSize]	  +
														fTempBuffer[i+nj*m_iSize]	  +
														fTempBuffer[pmi+mj*m_iSize]	  +
														fTempBuffer[mi+mj*m_iSize] )/4+ 
														RangedRandom( -fHeight/2, fHeight/2 ) );
			}
		}

		//reduce the rectangle size by two to prepare for the next
		//displacement stage
		iRectSize/= 2;

		//reduce the height by the height reducer
		fHeight*= fHeightReducer;
	}

	//normalize the terrain for our purposes
	NormalizeTerrain( fTempBuffer );

	//transfer the terrain into our class's unsigned char height buffer
	for( z=0; z<m_iSize; z++ )
	{
		for( x=0; x<m_iSize; x++ )
			SetHeightAtPoint( ( unsigned char )fTempBuffer[( z*m_iSize )+x], x, z );
	}

	//delete temporary buffer
	if( fTempBuffer )
	{
		//delete the data
		delete[] fTempBuffer;
	}

	return true;
}

//--------------------------------------------------------------
// Name:			CTERRAIN::RegionPercent - public
// Description:		Get the percentage of which a texture tile should be
//					visible at a given height
// Arguments:		-tileType: type of tile to check
//					-ucHeight: the current height to test for
// Return Value:	A floating point value: the percentage of which the
//					current texture occupies at the given height
//--------------------------------------------------------------
float CTERRAIN::RegionPercent( int tileType, unsigned char ucHeight )
{
	float fTemp1, fTemp2;

	//if the height is lower than the lowest tile's height, then we want full brightness,
	//if we don't do this, the area will get darkened, and no texture will get shown
	if( m_tiles.textureTiles[LOWEST_TILE].IsLoaded( ) )
	{
		if( tileType==LOWEST_TILE && ucHeight<m_tiles.m_regions[LOWEST_TILE].m_iOptimalHeight )
			return 1.0f;
	}
	else if( m_tiles.textureTiles[LOW_TILE].IsLoaded( ) )
	{
		if( tileType==LOW_TILE && ucHeight<m_tiles.m_regions[LOW_TILE].m_iOptimalHeight )
			return 1.0f;
	}
	else if( m_tiles.textureTiles[HIGH_TILE].IsLoaded( ) )
	{
		if( tileType==HIGH_TILE && ucHeight<m_tiles.m_regions[HIGH_TILE].m_iOptimalHeight )
			return 1.0f;
	}
	else if( m_tiles.textureTiles[HIGHEST_TILE].IsLoaded( ) )
	{
		if( tileType==HIGHEST_TILE && ucHeight<m_tiles.m_regions[HIGHEST_TILE].m_iOptimalHeight )
			return 1.0f;
	}

	//height is lower than the region's boundary
	if( ucHeight<m_tiles.m_regions[tileType].m_iLowHeight )
		return 0.0f;

	//height is higher than the region's boundary
	else if( ucHeight>m_tiles.m_regions[tileType].m_iHighHeight )
		return 0.0f;

	//height is below the optimum height
	if( ucHeight<m_tiles.m_regions[tileType].m_iOptimalHeight )
	{
		//calculate the texture percentage for the given tile's region
		fTemp1= ( float )ucHeight-m_tiles.m_regions[tileType].m_iLowHeight;
		fTemp2= ( float )m_tiles.m_regions[tileType].m_iOptimalHeight-m_tiles.m_regions[tileType].m_iLowHeight;

		return ( fTemp1/fTemp2 );
	}

	//height is exactly the same as the optimal height
	else if( ucHeight==m_tiles.m_regions[tileType].m_iOptimalHeight )
		return 1.0f;

	//height is above the optimal height
	else if( ucHeight>m_tiles.m_regions[tileType].m_iOptimalHeight )
	{
		//calculate the texture percentage for the given tile's region
		fTemp1= ( float )m_tiles.m_regions[tileType].m_iHighHeight-m_tiles.m_regions[tileType].m_iOptimalHeight;

		return ( ( fTemp1-( ucHeight-m_tiles.m_regions[tileType].m_iOptimalHeight ) )/fTemp1 );
	}

	//something is seriously wrong if the height doesn't fit the previous cases
	return 0.0f;
}

//--------------------------------------------------------------
// Name:			CTERRAIN::GetTexCoords - public
// Description:		Get texture coordinates :)
//					present in the final texture
// Arguments:		-texture: the texture to get coordinates for
//					-*x, *y: the unaltered texture coordinates, and the
//							 storage place for the altered coordinates
// Return Value:	None
//--------------------------------------------------------------
void CTERRAIN::GetTexCoords( CIMAGE texture, unsigned int* x, unsigned int* y )
{
	unsigned int uiWidth = texture.GetWidth( );
	unsigned int uiHeight= texture.GetHeight( );
	int iRepeatX= -1;
	int iRepeatY= -1;
	int i= 0;

	//loop until we figure out how many times the tile has repeated (on the X axis)
	while( iRepeatX==-1 )
	{
		i++;

		//if x is less than the total width, then we found a winner!
		if( *x<( uiWidth*i ) )
			iRepeatX= i-1;
	}

	//prepare to figure out the repetition on the Y axis
	i= 0;

	//loop until we figure out how many times the tile has repeated (on the Y axis)
	while( iRepeatY==-1 )
	{
		i++;

		//if y is less than the total height, then we have a bingo!
		if( *y<( uiHeight*i ) )
			iRepeatY= i-1;
	}

	//update the given texture coordinates
	*x= *x-( uiWidth*iRepeatX );
	*y= *y-( uiHeight*iRepeatY );
}

//--------------------------------------------------------------
// Name:			CTERRAIN::InterpolateHeight - public
// Description:		Interpolate the heights in the height map so that

⌨️ 快捷键说明

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