Procedural generation of assets

"The Art Of"

Procedural generation of assets is a well known technique widely used in the game industry. It`s used to generate various kinds of objects (meshes), level design (terrain, universe, mazes, dungeons, etc), plot complications, dialogues, sounds, loot, textures, and so on. What all those have in common are: They can be decomposed in small building blocks and assembly rules. Among the reasons for using such constructions one can find:

  • Storage space optimization. For such cases it may be better to store a set of blocks and rules than all the possible combinations generated by it.
  • Computational creativity and diversity. The possibility of generating virtually infinitely different assets, for example, in the level design never facing the same level twice.
  • Time complexity of development of repeated assets. Modeling assets of the same kind with some variation can be time consuming, while generating various of them from the same blocks and rules are easier. A simple example can be hand crafting each tree of a forest versus generating various trees and forming a forest.

Of course there is a downside, to create such generators it`s required to have a deeper knowledge of what is going to be modeled, otherwise one may fail to identify the correct parameters, blocks and rules hence generating assets with inconsistent and artificial appearance.

The tools behind of procedural generation are the rewriting rules, related to grammar, and probabilistic distributions. Taking the specific case of meshes, both play important rules on the assembly of an object. The first controls the general structure of a model while the second introduce the variations in the appearance per object.

Here we are going to address the generation of plant`s root meshes based on simple rules.

Procedural generation of tree-like structures

skeleton & Mesh

Rewrite rule

The base for the construction of the skeleton lies in the following rewrite rule:

Given the alphabet {s,l,r,$}, "s" represents a piece of a segment, "l" turn to left by θ degrees, "r" turn to right by θ degrees and "$" the ending of a segment. Then we use the rules "$" → "s$", the growing of a segment, "$" → ("s$", "la$") and "$" → ("s$", "ra$"), the branching and one step growing of a segment to left and right respectively. One important thing to notice is that we start with a single chain but may end with many, as the branching rules initiate new chains which grow independently. One may notice we have three rules for the same symbol "$", here is where the probability distribution comes in, you can assign probabilities for each rule and sample obtaining different constructions.

Noise addition

From a visual inspection it`s perceptible that only branching with straight lines and fixed segments size does not achieve what is proposed. So one way of making it more natural is adding noise in each step.

We sample a δL (length) and δθ (angle) from a normal distribution and add it to the growth of each segment for each step. These noises simulates a continuous process where it grows a random length until it changes its growing direction a little bit.

Surface generation

To generate the surface, we first choose a planar geometry to use as a base, and "pass" it through the skeleton curves scaling it according with the segment's length. This is done in the following way: For each point "p" in the curve segment, we discretize a unitary circle in #n points in the plane xy, scale it according to the length of the segment at the point "p", rotate the circle to make it normal to the point direction and finally translate it to the point "p".

Having all the points from the surface, we need to make facets from them by linking each two points of a circle to the next equivalent two points in the next circle following the right hand rule to keep the surface normals right.

Growth animation

Generating the frames for the animation during the simulation is straightforward, after each epoch (an epoch means each branch have been visited and updated), one generate the surface and draw it. In the other hand, generating the frames after the simulation one must keep track of the epochs.

Future ideas

For future work...

  • Try out more sophisticated geometries to add volume to the skeleton.
  • Refine the animation over a pair of points, instead of each point being a frame.
  • Simulate the growth of segments pieces after its creation, now they are static and does not grow after being added.
  • Simulate the growing of the root over surfaces other than planes.
  • Simulate bindweed-like plants
  • Add physics interactions like wind flow
  • Add a structure during the growth to control the density of branches over the space

Blender add-on

Implementation & parameters

The final result of this work is a blender add-on. It`s implemented using python, which is the scripting language used on blender. We added an small UI which can be accessed in "Object mode" in the tool shelf by the shortcut "T" > "Create" tab.

Adjustable parameters

  • Initialization
    • Starting position and direction
  • Basic growth
    • Mean step, how much a branch grow in one epoch
    • Branch direction, the angle which branches occur.
    • Level/Length ratio, the decay of the length of branches per level
    • Minimum #nodes before split, number of steps before being able to branch
  • Growth noise
    • Variance step,the variance of growth
    • Direction noise (mean & variance), the angle noise added to the direction of branches
    • Branch rate, the probability of branching
    • Left/Right rate, rate of branching to left and branching to right
  • Stopping criterion
    • Maximum length of a branch
    • Maximum nodes/branches
    • Maximum iterations
  • Surface generation
    • Circle points, the number of points to discretize the circle
    • Diameter/Length ratio