Now that we have a good landscape, we will want to populate it with a variety of trees, bushes, and so on. The Landscape Generator proposes several tools to procedurally place them over the landscape. Here’s an overview of the different functions we can use.
But the first of all, we need to make clear one thing: the foliage generation process can be divided in two main steps. In the first step, we define the position of the foliage elements over the landscape, it’s the “generation” phase. In the second step, we take this foliage elements, and we instantiate them, it’s the “spawning” phase.
Generate objects allows us to create foliage elements over the landscape according to an input module. The input module represents the probability mask of the generation, it means that if the value of the module for the coordinates (x, y) is 1, then there will be a foliage at coordinates (x, y). If the value of module is 0.0, then there is a 50% probability that a foliage will be generated.
Forest based generation is slightly more complex: seeds will be generated over the terrain according to probabilities given by the input module. These seeds may be converted in foliages, the foliages will grow and will generate new seeds around. This is really useful to create a landscape with patch of foliages over the terrain, like groves. However, it’s really important to be careful: this method is complex and it can take a really long time to simulate the evolution of a forest over a long period, or if the number of seeds is really high.
As we can see on this screenshot, there are a lot of parameters. First the parameters of the Generate Forests node:
- Meta Landscape: the landscape where we want to generate forests ; note that a simple landscape can easily be casted to a meta landscape.
- Module: a probability mask for the generation of initial seeds: if the value of the module is 1, then there is 100% chance of generating a seed at a position, when it’s -1, then there is 0% chance of generating a seed.
- Foliage Type: the kind of foliage of the forests.
- Forest Generation Parameters: a structure containing relevant parameters for the generation of forests.
Let’s have a look in about this last structure:
- Initial Seed Discretization Step: describe the distance between initial seed; a grid is generated over the terrain and seeds may (or may not) be generated at the junctions of the grid according to the input module, this parameter is the width of a grid cell. But to be more simple: the more the discretization step, the less the number of forests. Try to choose a number big enough, because a low discretization step can cause a really long generation time.
- Generation Count: the total number of years we want to simulate (trees are growing, seeding and aging every year).
- Seeds Per Tree Per Generation: the number of seeds a tree will create per generation.
- Reproductive Age: the minimum age of a tree before it starts spreading its seeds.
- Tree Max Age: the maximum age of a tree before it dies.
- Propagation Radius: the radius where seeds will be generated around a tree.
- Initial Emergence Probability: the initial probability that a seed will become a tree.
- Emergence Probability Decay Factor: at each generation, the probability of emergence of a seed (i.e. its conversion into a tree) is multiplied by this factor; according to the given parameters, when a seed is generated, it has a probability of 0.3 to become a tree, if it doesn’t become a tree, then the probability for the next year will be 0.3 x 0.5 = 0.15.
The default parameters usually give interesting results, but feel free to tweak them as you wish. Just note that increasing the number of seeds in anyway (by reducing the discretization step, the seeds per tree and so on), or the number of generation, will increase the generation time. Sometimes, it can be really long, however you can cancel the process anytime if you see that the generation process seems to be stuck.
When we have generated foliages (with either GenerateObjects or GenerateForests), we can apply different operators to get a better control over the generated objects.
Propagate will consider every foliage element given in input and will generate new elements around it. The parameters allows to specify the minimum distance and the maximum distance from a propagated object to its source object (Min Radius and Max Radius), the average number of new objects, the average scale of the new objects, and the standard deviation for both (given that the number and the scale are random, following normal distributions).
Rarefy is the inverse of Propagate. It can be used to ensure that there is always a minimum distance between two objects, thus it will remove objects that are too close from each other.
Split By Probability
As seen before, the Generate Objects and Generate Forests functions take as parameter the kind of foliage that we want to instantiate, but it’s limited to only one foliage type. So basically a generated forest may contain only one kind of tree… It’s not realistic. To overcome this, we can use the split functions which will split the population into several populations of new foliages types. Using the split functions, we can convert a forest containing one kind of tree into a forest containing 4, 5 or more kinds of trees.
Split By Probability will consider each element of the elements given as input, and according to the probabilities given in the Probability by Foliage parameter. In the example given there, every element of the input elements will be converted in either FoliageA or FoliageB with a probability of 0.5 for the first one, and the probability of 0.5 for the second one. If the sum of the probabilities doesn’t match 1, then it will be normalized to match 1.
Also please note that the return value is an array of foliage elements.
Split By Scale
The previous split function makes the split according to a probability. But we can also split according to the scale of objects. It’s useful to convert the smallest trees of a generated population into a smaller model or the biggest one to a bigger model. In this example, the foliages whose scale have been previously generated between 0 and 0.3 will be converted to the foliage type FoliageA and the foliages whose scale is between 0.3 and 1.0 will be converted to the foliage type FoliageB. The parameter Update Scale will reinterpolate the scale of converted elements for the new type: for instance an element with scale 0.3 will have scale 1.0 with the foliage type FoliageA, a foliage with the scale 0.15 will have the scale 0.5 with FoliageA, an element with scale 1.0 will have scale 1.0 with FoliageB.
Split By Age
This one is a bit more tricky: it works only with Generate Forests. When generating a forest, each tree has an age. Split By Age allows to have a different foliage type for younger trees, older trees, almost dead trees, and so on. In this example, the foliage whose age is between 0 and 10 will be associated to the foliage type FoliageA and the ones between 10 and 25 will be associated to foliage type FoliageB.
Application (Spawn Foliage).
Once the generation phase is completed, we can go for the spawning phase. For this we call SpawnFoliage. It will spawn the generated elements over the landscape.
We also propose some functions to edit the existing foliages on a landscape.
Clear foliage on landscape
As its names state it, this function clear all existing foliage over the landscape given as parameter.
Get existing foliage elements on landscape
This function takes the existing foliage elements on the landscape given as parameter and returns a collection of foliage elements, so they can used with the previous foliage operators. Using this, we can Propagate or Rarefy existing foliages on an existing terrain.