Mountains are the only bodies of land found in Aero Empire, and are where towns and cities reside. However, the previous mountains have been fairly simple - a mixture of 2D gaussians with some perlin noise written to a 2D heightmap. However, there is one big problem with heightmaps, and that is that you lose a lot of detail on the sides of steep cliffs. This is caused because a heightmap only specifies the height of the terrain at uniform grid locations - so to have a steep cliff, you must make pixels much lower than their neighboring pixels, causing the height at that location to drop off. However, there is no information for what the actual cliff should look like, so it become flat.
Example heightmap for previous Aero Empire mountains.
Example of a rendered heightmap mountain in Aero Empire's engine.
As you can see, while the x and y directions have a lot of detail (as these are what are sampled with a heightmap), the z direction has a noticeable lack of detail, especially where the mountain becomes steep. However, for simple mountains like these, this was not a great problem.
One day, one of my colleges showed me some images from his hometown, Zhangjiajie, and I was both awed and inspired - and thought that mountains like that would fit Aero Empire much better.
Image of Zhangjiajie, found in a google image search.
When I started thinking about adding mountains like those to Aero Empire, I knew instantly that heightmaps would not represent them effectively. Certainly, there are tricks to alleviate this problem of heightmaps (like horizontal displacement maps), but this has it's own problems, including greater memory usage which would slow down the mountain generation time (which was already getting slow). Additionally, height maps typically usually use too many triangles (as the triangles are forced to fit the grid, regardless of the actual structure). Again, while there are ways to alleviate this problem, pillars do not fit a square, 2D heightmap well.
The simple solution to this problem was to have a simple model that fit the pillar structure (and mountains in general) well. The idea was to use stacks of elliptical layers - the simplest such structure is a 2 layer stack where both the top and the bottom are the same size, creating a cylinder.
A 2-layer cylinder next to a more general 3-layer stack.
The number of sides for each layer can be dynamically set based on the circumference of the layer to get a better distribution of triangles. Then, the top layer of the stack must be triangulated, and the layers of the stack must be linked with triangles (if you align the two sets of vertices for the two layers, this is easy to do). While this can make pillars, it still does not add much detail to the sides of the pillars, as all the layers are elliptical. This is easy to remedy by just adding noise to each layer.
To procedurally generate stacks, I first generate a top layer, add noise to it, then copy that layer, move it down, and some random scaling, rotation, translation and additional noise, and add that layer to the stack. I keep adding these layers until I get from a specified (or generated) top height to bottom height.
A 3-layer stack with noise added next to a procedurally generated stack.
Finally, while this model was designed specifically for pillars, it is not restricted to pillars. It works well for mountains by scaling subsequent layers based on some height curve. This creates what looks like a contour map for the mountain. Using the same procedural algorithm as above, but with an additional scaling factor based on height, I can generate anything from hills to mountains to steep cliffs/plateaus.
A scene rendered in Aero Empire's rendering engine with many procedurally placed pillars and two overlapping steep hills.
One final note is that it is easy and efficient to generate multiple levels of detail for these stacks. You can simply remove every other layer (not including the top or bottom layer), and lower the number of sides of each layer. This creates similar looking mountains, but at a much lower triangle budget, which can replace the higher detail version when the mountain is seen from a distance.
The same scene as above, but at a lower level of detail rendered by the above algorithm. The full scene had 10,873 triangles, but at the lower level of detail, the scene only has 2,685 triangles.
Obviously, there's still much to do for the mountains. These have to be textured (with texture that fit the new mountain types), better procedural placement of the mountains would be good (clustering, etc), adding sharp cracks and splitting pillars in to two pieces (which can be seen in many images from Zhangjiajie) would add for more variation, and also allow the ability to fly between said pillars (which would be a cool gameplay dynamic). Since we're making a push for a playable game demo in the near future, I will probably not put too much more work into this until after the game demo release, but certainly expect some interesting mountains generated for the final game.
Look forward to future updates!