Sign in to follow this  
Pyroclastic Flow

Infinate Terrain

Recommended Posts

Is it possible to create a terrain from a heightmap that seems to go on forever? I'm fairly new to games development, so please bare with me. I have managed to get a terrain drawn in my game, using the nehe heightmap tutorial, however, if I move in one direction for too long, I am able to get to the end of the height map, which isn't what I want. Is there any possible way to make my existing terrain (using a height map) appear to be very large (make it unlikly to ever get to the end of it) or never-ending? Thanks in advance. P.S. I have googled around and found that automatic terrain generation can be done with "perlin noise". But I'm not sure if this is what I really need.

Share this post


Link to post
Share on other sites
The method I use is a height map of 256x256 which is a 'base'.

I then generate the area local to the player (The height map that is rendered) using bezier patches with the base as control points.

This produces persistent rolling hills which can be hundreds of miles in each direction.

A drawback is they are (as I said) rolling, not rugged or jagged like some of the better terrains.

Short answer is yes, it most certainly can be done, by procedural generation. The exact method you use will depend on what you want but expect it to be a lot of experimenting.

Share this post


Link to post
Share on other sites
Also an interesting fact is coordinate precision. If you use typical 32 bit float, you might loose precision earlier when moving away from center than if you use 64 bit double coordinates. You would notice typical artifacts like seams between terrain patches in this situation.

Share this post


Link to post
Share on other sites
Further to the above, in my system the 3D co-ordinates are centred around the player. (The player is always at 0) so the local world moves around the camera the edge of the map's co-ordinates never gets very large.

The players real position is stored in doubles separately.

Share this post


Link to post
Share on other sites
I made an infinite terrain once from a heightmap. Basically you want 3x3 chunks, each containing a reference of the terrain, it would look something like this if you would look at it from above:


|----|----|----|
| 1 | 2 | 3 |
|----|----|----|
| 4 |p 5 | 6 |
|----|----|----|
| 7 | 8 | 9 |
|----|----|----|

1,2,3...9 are the chunks
p is the player

Once the player steps over the edge between chunk 4 and 5, you move the player back by the width of a chunk and then scroll the chunks, so that it looks like this:


|----|----|----|
| 3 | 1 | 2 |
|----|----|----|
| 6 | 4 p| 5 |
|----|----|----|
| 9 | 7 | 8 |
|----|----|----|


And you could walk for an eterniy.

Share this post


Link to post
Share on other sites
Quote:
Original post by Pyroclastic Flow
Thanks guys, you are a great help!

Devnub, how could i calculate which chunk the player is on, and how would I create seemless terrain that when re-arranged would fit together perfectly, so the player cannot tell?


I'm not sure I know what you mean. The player will always be in the middle chunk, and which chunk is currently in the middle doesn't matter. It only works as a way to scroll/loop the terrain and has no other uses, at least that I can think of.

For example, if the player starts at position(0,0,0)(x,y,z), he will be in the center of the middle chunk. Now if the terrain size is 256 and moves to position (-129,0,0)(x,y,z), the chunks will swap places so that the right column becomes the left column, the left column becomes the center column and the center column becomes the right column. Like I showed in my ascii-figure.

Here's some source which might help explain it better:

struct Chunk {
Terrain *terrain;

float minX, maxX, minZ, maxZ;

void setBounds(float minX, float maxX, float minZ, float maxZ) {
this->minX = minX;
this->maxX = maxX;
this->minZ = minZ;
this->maxZ = maxZ;
}

float width() {
return abs(maxX - minX);
}

float depth() {
return abs(maxZ - minZ);
}
}

Chunk* chunks[3][3];

void initChunks(Terrain *terrain) {
const float size = terrain->size();
const float halfSize = size / 2;

float minX = -halfSize;
float maxX = halfSize;
float minZ = -halfSize;
float maxZ = halfSize;

// top-left chunk
chunks[0][0]->setBounds(minX-size, maxX-size, minZ-size, maxZ-size);
// top chunk
chunks[0][1]->setBounds( minX, maxX, minZ-size, maxZ-size);
// top right chunk
chunks[0][2]->setBounds(minX+size, maxX+size, minZ-size, maxZ-size);

// left chunk.. etc..
chunks[1][0]->setBounds(minX-size, maxX-size, minZ, maxZ);
chunks[1][1]->setBounds( minX, maxX, minZ, maxZ);
chunks[1][2]->setBounds(minX+size, maxX+size, minZ, maxZ);

chunks[2][0]->setBounds(minX-size, maxX-size, minZ+size, maxZ+size);
chunks[2][1]->setBounds( minX, maxX, minZ+size, maxZ+size);
chunks[2][2]->setBounds(minX+size, maxX+size, minZ+size, maxZ+size);
}

void infinity(Vector3 &cameraPosition) {
float minX, maxX, minZ, maxZ;
minX = chunks[1][1]->minX;
maxX = chunks[1][1]->maxX;
minZ = chunks[1][1]->minZ;
maxZ = chunks[1][1]->maxZ;

bool moved = false;
// check if we've crossed the boundaries of the middle chunk
if(cameraPosition.x > chunks[1][1]->maxX) {
// move the camera back
cameraPosition.x -= chunks[1][1]->width();
// move all the chunks to the left
Chunk* temp = chunks[0][0];
chunks[0][0] = chunks[0][1];
chunks[0][1] = chunks[0][2];
chunks[0][2] = temp;

temp = chunks[1][0];
chunks[1][0] = chunks[1][1];
chunks[1][1] = chunks[1][2];
chunks[1][2] = temp;

temp = chunks[2][0];
chunks[2][0] = chunks[2][1];
chunks[2][1] = chunks[2][2];
chunks[2][2] = temp;

moved = true;
} else if(cameraPosition.x < chunks[1][1]->minX)) {
// move the camera
cameraPosition.x += chunks[1][1]->width();
// move the chunks to the right
// ....
moved = true;
}

if(cameraPosition.z < chunks[1][1]->minZ) {
// move all the chunks down
moved = true;
} else if(cameraPosition.z > chunks[1][1]->maxZ) {
// move all the chunks up
moved = true;
}

if(moved) {
// calculate the new min and max boundaries for the chunks, since they have changed position
const float size = chunks[1][1]->width();

chunks[0][0]->setBounds(minX-size, maxX-size, minZ-size, maxZ-size);
chunks[0][1]->setBounds( minX, maxX, minZ-size, maxZ-size);
chunks[0][2]->setBounds(minX+size, maxX+size, minZ-size, maxZ-size);

chunks[1][0]->setBounds(minX-size, maxX-size, minZ, maxZ);
chunks[1][1]->setBounds( minX, maxX, minZ, maxZ);
chunks[1][2]->setBounds(minX+size, maxX+size, minZ, maxZ);

chunks[2][0]->setBounds(minX-size, maxX-size, minZ+size, maxZ+size);
chunks[2][1]->setBounds( minX, maxX, minZ+size, maxZ+size);
chunks[2][2]->setBounds(minX+size, maxX+size, minZ+size, maxZ+size);
}
}

void render() {
// scroll the chunks
infinity(cameraPosition);

// clear screen etc
// ...
// set the modelview matrix and camera position/orientation
// ...

// render the chunks
for(int j=0; j<3; j++) {
for(int i=0; i<3; i++) {
chunks[j][i]->terrain->render();
}
}





Wrote the source on the fly, so there are probably some errors.. But I hope it helps..

Oh and another thing.. This code will not only repeat the terrain, but also any objects placed on the terrain, so basically you will walk in a loop. If you don't want that, then simply don't move the camera position and move the bounds of the chunks differently.. it shouldn't be to hard to figure out.



As for making seamless heightmaps, I guess a paint program like Photoshop or Gimp should do the trick. Just google seamless texture tutorial or something similar.
If you're going to procedually generate the heightmaps, I have no clue.

Share this post


Link to post
Share on other sites

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