On Pandemic planet, I demonstrate the possibility of specifying large-scale outline of the continents using polygons defined in a JSON file.
Let’s start with an overview of the planet’s configuration. The configuration has been transferred to the XML format (previously it was JSON and partially remains as such, but that not discussed here).
This planet’s configuration file is available. This is already an outdated version of the configuration, but I will talk about the changes when we proceed to the next planet. In general, the configuration structure has not been changed: it is the root element Task and three child elements Relief, GHeights, and Rivers.
The planet has planetary biomes. Since no changes have yet been made in the procedure for their creation, we will not dwell on this topic.
Base heights mesh
GHeights element defines the most general appearance of the planet. The max_gHeight and sea_level attributes define, respectively, the relative values of the base height mesh’s maximum and the sea level height. ocean_at defines the final sea level as a fraction of the maximum height (which is considered as 1 here). To satisfy the later, necessary scaling has been done.
<GHeights max_gHeight="40000" sea_level="5000" ocean_at="0.37" ocean_down_stength="2.0"> .. </GHeights>
ocean_down_strength attribute allows us to raise or lower the relative level of the sea floor near land shores; this increases or decreases the average number and size of offshore islands, and may help to eliminate the unwanted effect of rombs land-filling (for this planet, the sea floor was lowered).
<Land max_lmId="29" sea_vs_height_sort_priority="0.5"> <Pits max_ratio="0.9" raising="0.1" max_iterations="1"/> <Eartherize land_size_limit="0.1" max_height="const 1" max_height_var="\_->0.2" prop_height_mean="\s->0.3"/> </Land>
Land element contains parameters of the post-processing operations on the resulting base heights mesh*. Pits defines the removal of excessive mesh pits (local minimums), and Eartherize defines the parameters of a special function applied to each landmass. This has all been covered in the previous posts.
Base heights mesh’s layer builders
Further, there is a block of directives for the initial construction of the base heights mesh. It consists of a set of elements which define the creation of data layers. A layer can possibly be created with a function, a polygon from a JSON file, or some action on already created layers.
<GLayerFold fold="\x y->x*y"> <GLayerSphereNoise frequency="5.5" lacunarity="2.0" octaves="7" persistance="0.8"/> <GLayerMapFigure fileName="figure.json" profile="\d->if d<15 then (fromIntegral d/15)**0.5 else 1"/> </GLayerFold>
GLayerSphereNoise element defines a normal 3D noise whose values on the sphere we use. If you see somewhere images (in movies or video games) of entire planets, then they are usually obtained in this way. Here, this is just one of the possible steps of the planet generation process.
GLayerMapFigure element specifies polygons from a JSON file (Pandemic string).
These two elements create two layers of values, which are wrapped in GLayerFold element. As you can guess, it does the multiply operation of the two layers' values.
The word "Fold" in the name of the element is not accidental, the program calls the foldl function of the Haskell language (really, its strict counterpart). Moreover, in an expression like "\x y->x*y" you can recognize the syntax for a lambda function. In fact, such expressions are being interpreted and converted into real lambda functions inside the program.
The number of layers is unlimited, as well as nesting. For example, we could use GLayerFold again for the layer already made and some more.
Currently, in addition to these layer builders, there are the following ones.
- GLayerNoise: this is the 2D noise in the equilateral triangle (and in the rhombus if it consists of two such triangles); the bases function construction algorithm can be found in the corresponding post
- GLayerTransform: layer transformation function
- GLayerSurface: layer's values are obtained via a function defined on the sphere (with polar coordinates)
- GLayerExprFigure: it draws a closed line centered at the north pole using the given function, then the resulting contour is filled according to one more function, and finally obtained figure is scaled and moved to another location on the sphere (currently, there is only random movements)
- GLayerSSShifts: the classic way to get relief on the sphere by random cuts and deformations; it is rarely used due to low performance, but can be used for planets in a style of the cubism abstract art :ж
<Rivers source_streamflow="1" sources_per_romb="3.0"> <RiverShape start_point_offset="3" end_point_offset="16" fractalH="0.8" scale="\h->1.0+(1-h)*0.5" padding_coefficient="1.0" amplification_param="1.2" skew="1.2"/> <Geometry min_sf="1" min_length="8" density="\sf->2*log (0.1+1)/log (0.1*sf+1)" var_density="const 2" min_sf_for_var="2" var_standard_deviation="const 0.2" var_arc="5.0e-5"/> </Rivers>
The rivers generation process is defined by Rivers element. There are two sub-elements here: RiverShape defines the shape of rivers, and Geometry defines the final GIS geometry. We will not linger here further; some information is in the previous posts. Let me just point out that for this planet sources_per_romb has a value of 3.0, which gives from one to three river sources per romb.
Relief element defines the final shape of the planet's relief, which has been previously roughly constructed with parameters defined in GHeights element. The child elements WHeights, HHeights, and Terrain** play a major role here. These define creation of, respectively, the water surface, the hill-layer, and the terrain. Since this part has undergone some changes in the newest version, we will take a closer look at it in the Devil of the Rings planet post.
* Or base heights surface, as it was called in the earlier posts.
** This is a typo in XML-file.