Generating random 3D terrain with python
--
In previous posts, I developed an engine for displaying 3D graphics using only the python3 standard library (which you can find here: https://medium.com/quick-code/3d-graphics-with-the-python-standard-library-af3794d0cba) and I wanted try this out for terrain generation. As usual, all the code for this post can be found on my github at https://github.com/hnhaefliger so feel free to go and download it from there. Before we get started, here’s an idea of what the intended outcome is:
To begin, we’re going to build a class to generate coherent height maps, which for this project will be based on perlin noise. The first step of this is creating a list of gradient vectors when we initialise the object:
This function will create a list of random unit vectors each with a magnitude of one. Next we will need a function to compute the dot product of these vectors and one to interpolate our values:
Now that we’ve got everything we need, we can write the function to get the z value at an x, y coordinate:
Moving away from the math of terrain generation, we can get around to the 3D display part. The first step in this will be computing a flat mesh of points and faces. Then we can add the noise as a z value. To make our terrain more realistic, we’ll add three layers of noise on top of each other. The first of these, I will refer to as ‘mountains’ will have a low frequency and high amplitude, this will give our land it’s shape. The second, which I will call ‘boulders’, will have a higher frequency and lower amplitude and the final layer, ‘rocks’, will have an even higher frequency and lower amplitude. These last two will give more detail to our otherwise bland landforms.
These parameters can be played with until you reach the desired effect. Then we have a couple more variables to define before we can create our map:
Finally we write this code to put all of our work together:
The first function will allow us to color the map differently for specified heights. The first loop then creates the coordinates, x, y, z (mountains + boulders + rocks), and in the second we create a list of triangles to link together the points. One particularity is the so-called z modifiers, which allow us to flatten out the terrain below water level, so that it still has a feeling of depth but not as drastic as the regular land and play with the steepness of the mountains.
Now we can use our 3D engine to display all of this:
The landmasses outputted by this program range from spanning mountain ranges to dotted archipelagoes. Something I might look at in a future post is turning this into a globe and creating planets with different habitats.