More selected projects

breathe(){grow();breathe();}

breathe(){grow();breathe();} is a simplification of the recursive function which is at the heart of this animation. In this animation, a digital tree is grown when an external sensor is blown into - a visual representation of the beauty of recursion.

produced by: David Williams

Introduction / Concept

For this project, I wanted to further explore the generation of tree-like forms using recursion methods. A recursive function is one which calls itself; it will continue doing so infinitely, unless there is an exit condition. In this case, the tree ceases to grow once the branches have become a certain length. A simplification in pseudo-code of the branching function would be something like this:

Branch{

x = 20;

Draw a line x length / 2;

Move to the end of the line;

rotate 45 degrees

Branch;

}

Each time Branch is called, the same action is performed over and over again, each time rotating 45 degrees and drawing the line at half of the original length.

In order to grow the tree, I wanted to use an input that was simple yet meaningful. I decided on a basic microphone amplifier module connected to the computer via an Arduino microcontroller. This module would be capable of producing a numerical output based on sound (vibration) input, so would respond well to someone blowing into the sensor. Just as plants in real life rely on air to live, so too, in a way, does my digital tree rely on the breath of the participant in order to grow.

Technical

The first step was creating the fractal tree shape. I had investigated Lindenmayer Systems (or L-Systems for short) – which work in a similar sort of way to recursive functions but rely on re-writing an ‘alphabet’ which can be used to describe movement and rotation vectors. L-Systems are a powerful an effective way of computer modelling plant-like forms, ‘The Algorithmic Beauty of Plants’ (Przemyslaw Prusinkiewicz and Aristid Lindenmayer, 1990), (co-written by the creator of the L-System, Artist Lindenmayer), demonstrates this excellently and was a great source of inspiration for this project. However, as I wanted to create something which would work well with live incoming sensor data, I settled on a comparatively simpler method of creating my trees.

In his book, The Nature of Code (Daniel Shiffman, 2012), Daniel Shiffman introduces a simple method for drawing a recursive tree. In class we had seen this code that had been adapted from the Processing language to work with openFrameworks, so I used both of these as a starting point.

Adding functionality, such as reducing line width by a given factor within the ‘Branch’ function was the first step – achieved in a similar way to reducing the line length. Then there was the matter of ‘growing’ the tree. This was achieved with incremental counters. I initially set up the counters to work on their own for testing, but later these would be dependent on incoming sensor values. The counters incremented the corresponding ‘end Y’ values, and were constrained with ‘if’ statements which used the length of the original vertical line as the conditional. I then used a translate function to move to the end of the original line (the ‘trunk’ of the tree) and start drawing the branches.

My next task was to set-up serial communication from the Arduinio to openFrameworks. The Arduinio code was quite simple(“FC-109 (MAX9812) microphone amplifier module,” 2015) and took the difference values from the mic – stronger blow = bigger difference. The serial receiving code in openFrameworks was taken from openFrameworks examples folder. As serial data is received by openFrameworks as a string, I simply had to convert this to an integer in order to use the values with my code. When the sensor was over a certain threshold (a big blow), this then triggered the counters, again, with an ‘if’ statement.

So the sensor communication was working fine – I could blow into the microphone and my tree would grow. However, the tree didn’t look particularly realistic – the branching was all the same and it looked a bit rigid, though I did succeed in creating multiple branches with the help of Daniel Shiffman ‘Stochastic Tree’ code ("The Nature of Code", p402, 2012). As such, I started experimenting with how to introduce an element of randomness to the branching. My first attempt involved simply using the ‘ofRandom’ function directly within the branching function – however, as this was being called within a ‘draw’ loop, the angles changed at a constant rate. The trick was to initialise the randomness at the ‘setup’ stage. I created a two vectors which would hold the random angle values. One was quite broad, ranging from -45 to +45 (left and right). The other was slightly more constrained, -20 to +20. The vectors were filled with a ‘for’ loop which used the number of branches as a conditional. These two angle vectors were then used to in the ‘draw’ function for the branch and within the ‘branch’ function itself (the smaller and larger values respectively). This meant that the ‘big’ branches would have a wide sweep, while the branching within these larger ones would be more constrained.

I also wanted to be able to reset the drawing and be able to draw a different tree. For this, I used a counter which grabbed the elapsed time in seconds. When the set time had elapsed, new random values were pushed into the angle vectors and everything is reset – including the timer.

A few finishing touches involved adding a wind effect and leaves to the tree. I added a wind effect by applying perlin noise via the ofSignedNoise function (again, needing negative and positive numbers) to the angles within the ‘branch’ call in the ‘draw’ section. I wanted the wind to be triggered by the sensor also but only once the tree was fully grown, so I used a boolean to tell when the animation had stopped (based on the branching function with the timers), which would in turn set the wind variable to be ‘true’ and kick of the perlin noise, acting in this case as simulated wind.

The leaves on the tree I did not model at all, they are just circles. They do however grow in diameter as the tree gets larger. It took a little bit of playing around to get the values right, but I found that I could draw them at the end of each branch of a certain length so that only the smaller branches have leaves. The call to draw these was nested inside of the ‘for’ loop inside the branch function.

Reflection / Future development

I was pleased with the outcome of this project and that I achieved what I had set out to do. The sensor worked well with the animation and I was able to draw some quite nice looking digital trees and I enjoyed the task of solving this problem.

As I mentioned at the beginning, my idea for this project was very simple. This simplicity has it’s strengths and weaknesses. Some plus points, as I see them, are that I enjoy the minimal aesthetic of the animation, as well as the fact that I was able to produce something which looks almost organic in nature – I feel that it resists the rigidly geometric look which often characterise computational animations (such as in my earlier work). Also despite it’s simplicity, I found it moderately compelling. I found myself repeatedly engaging with the finished animation, excited by what kind of tree might grow next time.

However, the weaknesses of this simplicity are, as I alluded, that the novelty of the piece is probably quite quick to wear off – it is not compelling enough to sustain a participants interest over a longer period of time. Also, whilst I may have learned something from programming it and enjoyed making it, it certainly isn’t a particularly original idea. Therefore I would categorise the piece as something more akin to a toy that to an artwork.

There are numerous ways of course in which this project could be expanded; be it delving deeper into the complexity of the modelling with textures, different shapes, modelled leaves and so forth; or even introducing genetic algorithms to simulate different real-world phenomena and evolve the appearance and other aspects of the tree over time. A forest of trees could be created which all respond to different programmed environmental conditions. Adding sound also may be a nice addition. Given time, I may explore some of these options in the future.

Credits go to Daniel Shiffman and all at the Processing foundation, Aristid Lindenmayer and all working within the field of Algorithmic Botany (“Algorithmic Botany: Home,” n.d.), the openFrameworks community, Theo Papatheodorou and all of my tutors and peers at Goldsmiths University.

 

References

Algorithmic Botany: Home [WWW Document], n.d. URL http://algorithmicbotany.org/ (accessed 4.26.18).

Daniel Shiffman, 2012. The Nature of Code, 0005 ed. Daniel Shiffman.

FC-109 (MAX9812) microphone amplifier module, 2015. . ELECTROpit. http://electropit.com/index.php/2015/12/20/fc-109-max9812-microphone-amplifier-module/

FORM+CODE In Design, Art, and Architecture by Casey Reas, Chandler McWilliams, and LUST [WWW Document], n.d. URL http://formandcode.com/code-examples/repeat-recursive-tree (accessed 4.23.18).

Przemyslaw Prusinkiewicz, Aristid Lindenmayer, 1990. The Algorithmic Beauty of Plants. Springer-Verlag.