This project is based on: http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/
Couple days ago, I came across this interesting article called “Polygonal Map Generation for Games”. At first glance, I wasn’t entirely interested, as I mostly generate my terrain using perlin noise. This is a much easier implementation - Unity’s Math library officially supports perlin noise, making it easier for Unity users to implement perlin noise based terrains. However, the maps generated by perlin noise aren’t entirely good for creating island maps. Sure, there is a workaround for it, but it’s always hard to get an island looking map just by using perlin noise. They often end up less realistic maps that look like a noise if seen from the top view. Otherwise, if the map has a fixed size in general, polygonal map generation would work much better. There will always be just one mountain where player can go on top of, unlike the noise function.
A voronoi diagram has been calculated using csDelaunay library (https://github.com/PouletFrit/csDelaunay) . When you pick random points and generate Voronoi polygons, the maps tend to look very irregular. These irregular polygons are definitely not what we want for a terrain. If maps were generated directly using the edges would look rough. This is where the Lloyd’s algorithm and relaxation comes in. Using multiple relaxation iterations, we can make the voronoi polygon map a lot more smoother and distribute the polygons evenly. Therefore, making the map look smoother.
During the map data generation, the following information needs to be calculated: adjacent polygon (neighbor cells), edges, island. Using these information, elevation of the terrain as well as the biome can be calculated. Once the island coast has been generated, we can fill the selected island with land, others with water. Calculating the elevation is quite easy (compared to perlin noise), as I just took the distance of a cell from the coast and used that information for elevation. So the center cell of the whole island would have the highest elevation.
Finally, the data goes through a so-called “Elevation Curve”, which lowers the lower part of the terrain further more, while making elevated terrains even more elevated. A flat curve (constant 1) would make a minimal difference between the lower part and the higher part of the terrain.
Once all the data has been generated, it was all about generating the mesh (with mesh colliders), translating the generated data to a texture then assigning the texture to the mesh. Except, I had to create the height map for the mesh separately (in float[,] variable), so that I could assign this variable to the terrain mesh directly.
You might notice that the generated map looks a little bit “pixelated”. This is because Unity has a limit on how many vertices one mesh object can have. It’s generally not a good practice have a lot of vertices on a single mesh. A workaround for this would be separating the terrain mesh into different parts (in this case, into 4 smaller mesh objects) and connecting them together. Similar to Minecraft’s implementation of chunks. This would also allow me to put multiple islands together. Terrain’s texture size in the pictures below have 200x200. Terrain textures bigger than this would exceed the maximum allowed number of verticies on the mesh.
I’m happy with the end result, but its performance is not as good as if I were to generate using perlin noise. If I were to make a full map using this method of terrain generation (multiple islands), it would definitely be much harder for computers. To be fair, all of the calculations are done on a single thread, meaning the calculations that I’ve performed was only done on a single core of a processor. Multi-threaded calculations would definitely be a lot better for the performance.