I love Structure Synth because it is a quick and easy way to generate 3D artwork. It's very programmer oriented. Rather than using the mouse to position primitives, you position them using a language called EisenScript. First Download Structure Synth and install it before continuing with this tutorial. Structure Synth is developed by Mikael Hvidtfeldt Christensen and available for Windows, Mac, and Linux.

This "Fractal Crab" is an example of a Structure Synth creation using recursion, rendered with Sunflow. The full sized 2560x1600 version is here.

A Simple Scene

The first scene creates three boxes, each offset in the x, y, or z direction. Click and drag in the view to rotate the scene. Shift-click to zoom the scene in and out, and hold down the command key to translate the scene horizontally or vertically.

By rotating the scene slightly you can see that the green box, offset 1 in the z direction, comes out of the screen towards you. The x and y offset are as you'd expect, to the right, and up. If you get lost, click the "Reset View" button to return the default view, looking towards {0,0,0} down the z axis.

{x 1 color red} box
{y 1 color blue} box
{z 1 color green} box

Now that you have your bearings in 3D space, the next step is to put our creation into a rule so we can reuse it. This scene uses the 'threeBox' rule several times, offsetting it 2 units each time.

{x 0} threeBox
{x 2} threeBox
{x 4} threeBox

rule threeBox
{
    {x 1 color red} box
    {y 1 color blue} box
    {z 1 color green} box
}

This works, but it's not how a programmer would write it. We can refactor it like this. This is evaluated something like "Translate 2 in the x direction, three times, and call threeBox each time".

3 * {x 2} threeBox

rule threeBox
{
    {x 1 color red} box
    {y 1 color blue} box
    {z 1 color green} box
}

Unfortunately this gives a slightly different result than the previous scene. Here's how to shift the first threeBox to the left of the origin, before repeating it three times.

1 * {x -2} 3 * {x 2} threeBox

rule threeBox
{
    {x 1 color red} box
    {y 1 color blue} box
    {z 1 color green} box
}

Rotation

We can combine repeating, rotation, and offset to make rings. The '6 * {ry 60}' repeats the threeBox rule 6 times, rotating it 60 degrees each time. Then, the '1 * {x 4}' translates it 4 units from the origin in the direction of the rotation.

6 * {ry 60} 1 * {x 4}  threeBox

rule threeBox
{
    {x 1 color red} box
    {y 1 color blue} box
    {z 1 color green} box
}

Try changing the 6, 60, 1, and 4 values on the first line and observe how each alters the appearance of the scene.

Scaling

Now lets try scaling our boxes each time we repeat by scaling them to 0.75 each time we repeat them. The example below adds a 's 0.75' to the first repeated block.

6 * {ry 60 s 0.75} 1 * {x 4}  threeBox

rule threeBox
{
    {x 1 color red} box
    {y 1 color blue} box
    {z 1 color green} box
}

Recursion

The script below is an example of a recursive rule. You'll notice there is an 'md 8' where we defined this rule. This is short for saying 'maxdepth 8'. Both 'maxdepth' and 'md' are interchangeable. You'll notice recursiveRule calls itself after making a box. Also new in this example is a 'hue 60' declaration. This shifts the hue 60 degrees on the color wheel each time the rule is evaluated.

Try adjusting the rotation angles, axes, and scaling to see what effect each has on this scene.

recursiveRule

rule recursiveRule md 8
{
    box
    {x 1 rz 90 s 0.5 hue 60} recursiveRule
    {x -1 rz 90 s 0.5 hue 60} recursiveRule
}

Randomness

Randomness is implemented in Structure Synth by implementing two or more versions of a rule with the same name. Structure Synth will randomly choose one or another based on the weights you specify. In the example below, the red box rule's weight is reduced so it is called less by adding 'w 0.25'. You can also increase the rule's weight by choosing a value greater than 1.

10 * {x 1} 10 * {y 1} 10 * {z 1} oneBox

rule oneBox w 0.25
{
    {color red} box
}

rule oneBox
{
    {color white} box
}

Combining Randomness and Recursion

This example will make a branching tree. Click the blue arrow to regenerate the scene and see a different random tree. Each time you click the blue arrow, it will increment the seed. If you saw a tree you liked, you can decrement the seed and regenerate the same tree.

This example defines a branch rule. Every time branch calls itself, it reduces the size of the subsequent block by a bit, and translates the box higher. Every now and then the tree will 'fork' and call the rule that results in two branches at a node.

branch

// Create a step or trunk that doesn't fork.
rule branch md 20 w 3
{
    {s 0.95 y 1 hue 20 ry 90} branch
    box
}

// "Fork" and create two branches.
rule branch md 12
{
    {s 0.85 y 1 rz 25 hue 20} branch
    {s 0.85 y 1 rz -25 hue 20} branch
    box
}

You can put a sphere on the end of each branch like this.

branch

rule apple
{
    {s 4 color red} sphere
}

// Create a step or trunk that doesn't fork.
rule branch md 10 > apple
{
    {s 0.95 y 1 hue 20 ry 90} branch
    box
}

// "Fork" and create two branches.
rule branch maxdepth 12
{
    {s 0.85 y 1 rz 25 hue 20} branch
    {s 0.85 y 1 rz -25 hue 20} branch
    box
}

The next step is rendering in a ray tracer! You can use any of the export templates provided to generate a scene file you can render in Sunflow or POVray. Rendering will be a topic for a future article. Have fun!

References and Inspiration

Tags: structure synth, 3D, eiesenscript, generative, tutorial