Generating 3D Terrain (need help on Z-component)

Started by
4 comments, last by Jason Z 11 years, 1 month ago

Hey, so I'm currently working on a simple game that is 3D but seen only from the side with a slight angle (like "little big planet" or other similar games), where I need to generate basically a 2D Terrain (X and Y) but with a depth to it.

I've got it working for X and Y axis as a 2D terrain but I'm not sure how I can extend this to feature depth.

This is how I create my terrain:


	this->vertices = new TexturedNormalVertex[TERRAIN_X * TERRAIN_Y];
	this->indices = new int[(TERRAIN_X - 1) * (TERRAIN_Y - 1) * 6];


void Terrain::GenerateTerrain()
{
	// Setup vertices
	for(int x = 0; x < TERRAIN_X; x++)
	{
		for(int y = 0; y < TERRAIN_Y; y++)
		{
			float X = (float)x;
			float Y = (float)y;

			// HEIGHT
			if(y > 0)
			{
				// RANDOMLY GENERATE THE TERRAIN SLOPE
				srand((unsigned int)time(NULL));
				float randomNumber1 = rand() % 3 + 0.0f;
				srand((unsigned int)time(NULL));
				float randomNumber2 = rand() % 7 + 1.0f;
				srand((unsigned int)time(NULL));
				float randomNumber3 = rand() % 10 + 2.0f;
				float waveMagnitude = 20;
				float waveLength = 20;
				float offset = 0.0f;

				float height = waveMagnitude / (randomNumber1 + 0.00001f) * sin(X / waveLength * randomNumber1 + randomNumber1 + 0.000001f);
				height += waveMagnitude / randomNumber2 * sin(X / waveLength * randomNumber2 + randomNumber2);
				height += waveMagnitude / randomNumber3 * sin(X / waveLength * randomNumber3 + randomNumber3);
				Y = Y + (height + offset);
			}


			this->vertices[x + y * TERRAIN_X].pos = XMFLOAT3(X, Y, 1);
			this->vertices[x + y * TERRAIN_X].texCoord = XMFLOAT2(X / TEXTURE_SCALING, Y / TEXTURE_SCALING);
			this->vertices[x + y * TERRAIN_X].normal = XMFLOAT3(0, 0, -1);
			this->vertices[x + y * TERRAIN_X].biTangent = XMFLOAT3(0, 0, 0);
			this->vertices[x + y * TERRAIN_X].tangent = XMFLOAT3(0, 0, 0);	
		}
	}


	this->vertexCount = TERRAIN_X * TERRAIN_Y;

	// Define terrain using indices
	int counter = 0;
	for(int y = 0; y < TERRAIN_Y - 1; y++)
	{
		for(int x = 0; x < TERRAIN_X - 1; x++)
		{
			int lowerLeft = x + y * TERRAIN_X;
			int lowerRight = (x + 1) + y * TERRAIN_X;
			int topLeft = x + (y + 1) * TERRAIN_X;
			int topRight = (x + 1) + (y + 1) * TERRAIN_X;

			indices[counter++] = topLeft;
			indices[counter++] = lowerRight;
			indices[counter++] = lowerLeft;

			indices[counter++] = topLeft;
			indices[counter++] = topRight;
			indices[counter++] = lowerRight;
		}
	}
	
	




	this->InitializeBuffer();


}

Advertisement

What is it that you really want to do? Currently you are already using 3D points for your vertices, but you are setting the Z value always to 1.0. You need to decide how much of a depth you want to cover, and determine how many rows of vertices that will incorporate, and then generate the vertices accordingly.

I'm not really sure what you are having trouble with - can you elaborate on your question?

Well basically what you just said xD

Currently I don't have a depth to this as I'm just generating x and y positions and indices for these.

I'm just not sure how to extend this along the z axis. It's probably something easy but somehow I'm stuck tongue.png

Well, if you start out with your current landscape, and then duplicated it with the Z coordinate = 2.0, and then specify a group of triangles between the two curves, then you would effectively have a mini-surface. You could repeat this as needed until you had reached the desired size of the surface. Depending on how fancy you want it to be, you could try different algorithms to place the vertices, but in general you just create a uniform grid in the x and z plane, and then offset the vertex positions in the y direction as you see fit.

Well I've tried something like


void Terrain::GenerateTerrain()
{
	// Setup vertices
	for(int x = 0; x < TERRAIN_X; x++)
	{
		for(int y = 0; y < TERRAIN_Y; y++)
		{
			for(int z = 0; z < TERRAIN_Z; z++)
			{
				float X = (float)x;
				float Y = (float)y;
				float Z = (float)z;

				// HEIGHT
				if(y > 0)
				{
					// RANDOMLY GENERATE THE TERRAIN SLOPE
					srand((unsigned int)time(NULL));
					float randomNumber1 = rand() % 3 + 0.0f;
					srand((unsigned int)time(NULL));
					float randomNumber2 = rand() % 7 + 1.0f;
					srand((unsigned int)time(NULL));
					float randomNumber3 = rand() % 10 + 2.0f;
					float waveMagnitude = 20;
					float waveLength = 20;
					float offset = -10.0f;

					float height = waveMagnitude / (randomNumber1 + 0.00001f) * sin(X / waveLength * randomNumber1 + randomNumber1 + 0.000001f);
					height += waveMagnitude / randomNumber2 * sin(X / waveLength * randomNumber2 + randomNumber2);
					height += waveMagnitude / randomNumber3 * sin(X / waveLength * randomNumber3 + randomNumber3);
					Y = Y + (height + offset);
				}



				this->vertices[x + y * TERRAIN_X + z * TERRAIN_Y].pos = XMFLOAT3(X, Y, Z);
				this->vertices[x + y * TERRAIN_X + z * TERRAIN_Y].texCoord = XMFLOAT2(X / TEXTURE_SCALING, Y / TEXTURE_SCALING);
				this->vertices[x + y * TERRAIN_X + z * TERRAIN_Y].normal = XMFLOAT3(0, 0, -1);
				this->vertices[x + y * TERRAIN_X + z * TERRAIN_Y].biTangent = XMFLOAT3(0, 0, 0);
				this->vertices[x + y * TERRAIN_X + z * TERRAIN_Y].tangent = XMFLOAT3(0, 0, 0);	
			}
		}
	}


	this->vertexCount = TERRAIN_X * TERRAIN_Y * TERRAIN_Z;

	// Define terrain using indices
	int counter = 0;
	for(int z = 0; z < TERRAIN_Z - 1; z++)
	{
		for(int y = 0; y < TERRAIN_Y - 1; y++)
		{
			for(int x = 0; x < TERRAIN_X - 1; x++)
			{
				int lowerLeft = x + y * TERRAIN_X + z * TERRAIN_Y;
				int lowerRight = (x + 1) + y * TERRAIN_X + z * TERRAIN_Y;
				int topLeft = x + (y + 1) * TERRAIN_X + z * TERRAIN_Y;
				int topRight = (x + 1) + (y + 1) * TERRAIN_X + z * TERRAIN_Y;
				
				indices[counter++] = topLeft;
				indices[counter++] = lowerRight;
				indices[counter++] = lowerLeft;

				indices[counter++] = topLeft;
				indices[counter++] = topRight;
				indices[counter++] = lowerRight;
			}
		}
	}

...but that doesn't work.

I'm not sure how I would define that group of triangles in between and finally combine those in a single continuous index buffer : /

That is just a task that you will need to come to grips with - it is a fundamental problem that will be unique to each situation. However, if you make a diagram of the two copies of your vertices, and determine what the starting and ending indices of each row is, I'm sure you will be able to work out the solution.

You can inspect what triangles you are defining in PIX / Graphics Debugger, and that should help you figure out the solution fairly quickly. Good luck!

This topic is closed to new replies.

Advertisement