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

Recommended Posts

lipsryme    1522

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 on other sites
Jason Z    6434

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 on other sites
lipsryme    1522

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

Share on other sites
Jason Z    6434

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 on other sites
lipsryme    1522

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 on other sites
Jason Z    6434

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!