Tuesday 23 December 2008

Perlin's magic on terrain generation

After building the terrain from a fixed heightmap and fixing the slopes, terrain generation seems to be a good next step. There seems to be quite a number of ways to do generate terrain. I think the selection of a method depends primarily on the look you are going for.

I decided on three initial characteristics: a) The landscape must be a fair playground, b) it must be reproducible, and c) it must be relatively smooth.

The idea behind a fair playground is to have a two player arena such that the terrain gives no advantage to either player. This means the terrain must be a mirror of sorts. A player in the north looking toward the center will see the same effective terrain as a player looking from the south.

The term 'effective terrain' refers to those aspects of the terrain that are not cosmetic. For example: having different vegetation in the north and the south may influence the look dramatically. If it is not used in the game logic the choice of vegetation is not part of the effective terrain. This separation of effective and cosmetic concerns on your drawable objects could be an import design consideration that would simplify many aspects of the game design and implementation.

A terrain is reproducible when its form can be recreated from its input. In other words, although I might need a lot of terrains for my game, I would like to be sure that the same terrain is presented for the same scenario. This reproducibility also give me a handle on the generated terrains, and allows me to handpick scenarios by tweaking the input parameters. The idea here is to use predictable random numbers.

After some googling I decided to start with Perlin Noise based generator (Perlin was already used before to create the animating clouds). It seems that I can get a smooth terrain using this method. For the implementation I used an article on the Nerdy Inverse Network as a starting point.

During my previous blog, I created a class called Terrain, originally copied from RiemersTexturedTerrain. Now, we need to separate the height map from the terrain, and IHeightMap together with the reference implementation HeightMapLoaded emerged.

The new class, called HeightMapPerlin addresses expectation (b) and (c) described above. Here is its constructor: public HeightMapPerlin(Game g, int width, int length, float minHeight, float xHeight, int seed, float persistence, int octaves)

The seed produces the same terrain for any given seed value. The value of persistence influence how pointy the hills are. Low values produce a less pointry terrain. The number of hills are influenced by the value of octaves. More octaves, more hills. The slope is influenced by the value of minHeight and maxHeight. Some experimentation with these values is nessasary to get the right kind of terrain to suit a particular need. The published image shows a rendering with persistence = 2.9f and octaves = 4.

I can now generate a terrain with given properties, but the issue of fairness has not been addressed yet.

No comments:

Post a Comment