• Create Account

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

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

5 replies to this topic

### #1lipsryme  Members

1488
Like
0Likes
Like

Posted 19 February 2013 - 08:33 AM

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

}


### #2Jason Z  Members

6417
Like
0Likes
Like

Posted 19 February 2013 - 05:30 PM

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?

Jason Zink :: DirectX MVP

Direct3D 11 engine on CodePlex: Hieroglyph 3

Games: Lunar Rift

### #3lipsryme  Members

1488
Like
0Likes
Like

Posted 19 February 2013 - 06:46 PM

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

Edited by lipsryme, 19 February 2013 - 06:51 PM.

### #4Jason Z  Members

6417
Like
0Likes
Like

Posted 19 February 2013 - 08:54 PM

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.

Jason Zink :: DirectX MVP

Direct3D 11 engine on CodePlex: Hieroglyph 3

Games: Lunar Rift

### #5lipsryme  Members

1488
Like
0Likes
Like

Posted 21 February 2013 - 08:21 AM

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, 21 February 2013 - 08:24 AM.

### #6Jason Z  Members

6417
Like
0Likes
Like

Posted 21 February 2013 - 09:00 PM

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!

Jason Zink :: DirectX MVP

Direct3D 11 engine on CodePlex: Hieroglyph 3

Games: Lunar Rift

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.