Sign in to follow this  

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

This topic is 1754 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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();


}

 

 

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites

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

Edited by lipsryme

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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 : /

Edited by lipsryme

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites

This topic is 1754 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this