Archived

This topic is now archived and is closed to further replies.

tcs

Generating Texture Coordinates for Terrain

Recommended Posts

tcs    122
Hello ! I''m working on a terrain engine. The "normal" way to generate texture coordinates for it would be to just tile them along the XY axis, a simple flat projection. While this looks ok, you get texture stretching artifacts at the hills and at high gradients because the texture coordinate is only advanced when the XZ position changes, Y is not taken into account. I tried to avoid this bug by making a distance based texturing scheme where I don''t take the grid distance of two vertices. I take the real 3D distance, so I got the same texel density on the who terrain. This is nice, but causes artifacts because th textures are badly distored. Here''s my code in case you think I could make something good looking out of this approach:
    
bool CLandscape::CalculateTextureCoordinates(unsigned int iLandscapeWidth,
											 CDynamicArray2D *pHeightmap,
											 CDynamicArray3D *&pTexCoords,
											 LoadingParam *pLoadParams)
{
	////////////////////////////////////////////////////////////////////////

	// Generate texture coordinates for the landscape. The method that is

	// used here uses various tricks to make a 2D projection look good,
	// even on high gradients where lots of texture space is vertically

	// distributed

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


	unsigned int iX, iY;
	float fVertex1[3];
	float fVertex2[3];
	float fScalineWidth;

	// Allocate space for the textur coordinate array. Need one texture

	// coordinate for every pixel. Memory is freed by the caller

	pTexCoords = new CDynamicArray3D(iLandscapeWidth, iLandscapeWidth, 2);

	// Calculate the horizontal surface length

	for (iY=0; iY<iLandscapeWidth; iY++)
	{
		fScalineWidth = 0.0f;

		// Leave out the first one, it''s zero anyway
		for (iX=1; iX<iLandscapeWidth; iX++)
		{
			// Calculate the first vertex

			fVertex1[x] = (iX - 1) * pLoadParams->fGridSize;
			fVertex1[y] = pHeightmap->m_Array[iX - 1][iY] * (iLandscapeWidth * pLoadParams->fGridSize /
				(float) pLoadParams->iHeightScaling);
			fVertex1[z] = iY * pLoadParams->fGridSize;
			
			// Calculate the second vertex

			fVertex2[x] = iX * pLoadParams->fGridSize;
			fVertex2[y] = pHeightmap->m_Array[iX][iY] * (iLandscapeWidth * pLoadParams->fGridSize /
				(float) pLoadParams->iHeightScaling);
			fVertex2[z] = iY * pLoadParams->fGridSize;

			// Add distance to the overall length of this scanline

			fScalineWidth += GetDistance(fVertex1, fVertex2);

			// Save the unscaled texture coordinate in the array

			pTexCoords->m_Array[iX][iY][u] = fScalineWidth;
		}

		// Scale the texture coordinates to match the 0.0f - 1.0f range

		for (iX=1; iX<iLandscapeWidth; iX++)
		{
			pTexCoords->m_Array[iX][iY][u] /= fScalineWidth;
		}
	}

	// Calculate the vertical surface length

		
	for (iX=0; iX<iLandscapeWidth; iX++)
	{
		fScalineWidth = 0.0f;

		// Leave out the first one, it''s zero anyway
		for (iY=1; iY<iLandscapeWidth; iY++)
		{
			// Calculate the first vertex

			fVertex1[x] = iX * pLoadParams->fGridSize;
			fVertex1[y] = pHeightmap->m_Array[iX][iY - 1] * (iLandscapeWidth * pLoadParams->fGridSize /
				(float) pLoadParams->iHeightScaling);
			fVertex1[z] = (iY - 1) * pLoadParams->fGridSize;
			
			// Calculate the second vertex

			fVertex2[x] = iX * pLoadParams->fGridSize;
			fVertex2[y] = pHeightmap->m_Array[iX][iY] * (iLandscapeWidth * pLoadParams->fGridSize /
				(float) pLoadParams->iHeightScaling);
			fVertex2[z] = iY * pLoadParams->fGridSize;

			// Add distance to the overall length of this scanline

			fScalineWidth += GetDistance(fVertex1, fVertex2);

			// Save the unscaled texture coordinate in the array

			pTexCoords->m_Array[iX][iY][v] = fScalineWidth;
		}

		// Scale the texture coordinates to match the 0.0f - 1.0f range

		for (iY=1; iY<iLandscapeWidth; iY++)
		{
			pTexCoords->m_Array[iX][iY][v] /= fScalineWidth;
		}
	}

	return true;
}
    
What is your suggestion to generate texture coordinates ? Can the approach described above be modified to look good ? Any other ideas ? Thanks for your time Tim -------------------------- glvelocity.gamedev.net www.gamedev.net/hosted/glvelocity

Share this post


Link to post
Share on other sites