“Witness a canvas of a plain, white brick wall as it transforms into a botanical wonderland of overgrown ivy vines and leaves. Click the mouse to start and stop the growth of the plant, tracking each leaf and children vine the parent vine creates.”
ABSTRACT:
The photo below shows what’s known as “Hedera helix,” the scientific name of the common plant English Ivy. It is known as an invasive, or toxic, plant that grows primarily in Western Asia and Europe.
Hedera helix is capable of growing almost anywhere: on trees, on the ground, on buildings, etc. Since I grew up in the Pacific Northwest, the plant is very familiar to me, as I often spent my middle school years of trying to get volunteer hours by pulling weeds and other invasive species, ivy included.
We often considered as an invasive species by landscapers, or a nuisance to urban planning and architectural design. When we think of plants whose appearance is aesthetically pleasing, interesting, and/or interesting, we would probably think of a hibiscus flower, a rose, or an agave plant before ivy came to mind. Still, I feel that there is something so mesmerizing, and even beautiful, about ivy and the way that it grows, and the scene that is created when a piece of architecture is covered in greenery. Moreover, the subtitle of this project is called “an exploration of algorithmic botany,” as the sketch I created, like algorithmic botany, is an attempt at using computer programming to create a piece of art that mimics this real-life plant, its effects on its surroundings, and its life span in a contained, virtual space. As observed in my sketch, the juxtaposition of the rigid, structured, and geometric brick wall, and the free-flowing vines and chaotic clusters of ivy leaves, which weave across the canvas at random not only offers plenty of visual interest for the user, but also gives the sketch an almost hand-drawn effect. The sketch begins with three main “parent” vines, who grow leaves and make children vines as the user presses the mouse. Once the mouse is un-pressed, the growth of the vines stops, while the leaves that have already been drawn continue to grow into their full size. Lastly, any key will cause all progress of the current vines to disappear and restart, and pressing the mouse again will generate the growth of completely new vines. This aspect of the sketch, along with its interactive quality, give the sketch a sense of time and place, allowing the user to be able to take in, observe, and enjoy the scene they have “drawn” at almost every frame.
SCREEN CAPTURES
Vines grow according to when the mouse is pressed
Each execution of the program creates a different vine; sometimes it creates rather sparse vines
And other times, it creates vines that are dense, lush, and clustered.
____________________________________________
REFLECTION
Design and Composition:
When it came to coming up with design and aesthetic for this project, while I did look at many images of real life english ivy so I could better understand its biology and growth, the majority of images that contributed to my inspirations were hand drawn images, or digital images that appeared to be hand drawn. Some inspirations are below:
From the very beginning, I knew that I wanted the sketch to emulate a calming, simple, and delicate aesthetic, and I knew that creating movement/shapes that were too geometric was what needed to be most avoided in order to make this vision come to life. First, I would like to touch on the background. I chose to use an image for this, rather than creating my own background (see references). I did this for two reasons. The first reason is that when I attempted making my own brick wall background, or a textured stone wall using noise, the program became much slower, and vine movement was no longer fluid. The second reason was that, it seemed that no matter what techniques I tried, whether that was randomizing the brick shape/color, using the noise function, layering different transparent backgrounds on top of each other, nothing gave me the hand drawn, soft look I was going for. Hence, I chose an image of a slightly deteriorated white brick wall, and added a translucent, pale beige background so that it would fit with the muted color palette a bit better. Here is final background:
Next, when it came to drawing the leaves, I initially started by making a completely new sketch, creating the leaf shape using vertex(). The leaf template is shown below:
When it came time to implementing this shape into the program, I played around with varying the leaf opacity and size. I felt that both of these two aspects, using the random() function, added an appropriate amount of variety and visual interest. Another technique I tried was making a variable called fluctuation, which was a random value between 1 and 2. This fluctuation variable was added onto the x-y points of each vertex of the leaf, allowing the shape of each leaf to be slightly varied. Personally, I think that this element made the sketch look a little too busy, and although some critiques during the presentation were that the leaves looked “too uniform,” I do think that this actually is closer to the shape of english ivy; even though there exist many different sub-species, when you look at ivy, the leaves look almost identical to one another (I think this is also why some people might think ivy looks ugly or boring).
Next, the design of the vines was heavily inspired by creative developer John Windle’s, or Soulwire’s, “Tentacles” sketch:
In his sketch, vine/tentacle objects grow from the center and swirl to the edge of the screen. The shape used to create the tentacles is a circle, whose fill is black, while the stroke is an almost white color. By making the stroke color light, it creates contrast and dimension to the tentacles. This aspect of his program was something I knew I wanted to implement in my own sketch. However, since I was only using brown colors, instead of black and white, the effect was not as intense as I would have liked. As a result, I decided to draw two ellipses on top of each other, but slightly staggered. The ellipse on the bottom has no stroke, and the fill is a darker brown color, while the ellipse layered over has the different stroke/fill colors like in the Tentacle program. Some close ups of the vines are displayed below:
My method for creating children vines took inspiration from another of his sketches called “Recursion Toy“.
While the code wasn’t adapted into my program in any way, the idea of using recursion to continually recreate branches was something I wanted to utilize. I explain in further detail the program’s recursive elements below.
____________________________________________
Technical Processes
In terms of the coding, my process was first creating a class called Vine, a class called Stem and a class called Leaf; both the Stem and Leaf class inherit parameters from the Vine class:
Instance variables this.x, this.y, and this.diameter are rather self-explanatory: they represent the x and y position, and the diameter of each “segment of the vine”, which are ellipses. this.fluctuation is set to 0 when a vine is initialized, however it will change later on in the program when the vine begins to grow. Instance variable this.direction dictates the initial angle which the vines will draw at. When the sketch begins, there are 3 main “parent” vines (created in draw()) that begin at the bottom left of the screen, which will each have predetermined angle values. It calls the method createVines() which grows the current vine, displays the vines, creates new children, and creates new stems. The code is shown below:
Inside the createVines() method:
Line 79 shows the recursive aspect of the code: once a vine completes the above 4 methods, a new vine is created, taking the current diameter, x position, y position, and angle as parameters, and appends it into the array this.vines (initialized in the constructor).
Specifically, the growThisVine() method relies on the noise(), sin(), and cos() functions. To ensure that vines grow up and out, and don’t grow too far to the left/right, which result in a spiral shaped vine, the noise value is constrained using the map() function to (-PI/2, PI/2):
It took some trial and error to find the correct bounds for the map() function however the most difficult part of the project was creating the growChildren(). I initially assumed that new vines should be created at the exponential rate of 2^n, like a binary tree. However, I quickly realized that this made the vines not look like vines at all. Instead, they looked like tree branches hat became too clustered and too dense too fast. I needed to find a formula that would make the growth become more sparse program went on. The following is the solution I came up with:
The instance variable this.vine_created _time is initialized in the constructor–in other words, when a new vine object is made. Hence, it keeps track of the frameCount in which the vine was created. Then, if the variable satisfies the condition in line 113, which says that if x frames have passed, x being equal to the time the vine was created (this.vine_created_time) plus 80, a new vine object will be created and added to the list vines. Because the value this.vine_created_time will increase as the time progresses, this condition also allows for vines to be created less frequently as the frameCount of the program increases, which mimics closely to how ivy grows in nature.
Similarly, the createStem() relies on a time variable. In line 129-130, so that the stem growth is slightly lagged, meaning that a stem isn’t drawn immediately after the vine finishes drawing at any given x-y point. It creates stem objects and appends them to the stems array, which is initialized in the draw() function.
In the draw() function, the growStem() method is called upon each item in the stems array. The growStem() function is shown below:
*Note: this.s is created in the constructor function in class Stem, which is actually a vine object.
The variables this.s_length and this.end_length help to ensure that the stems stop growing when they reach a specified length. At first I wanted all stems to be the same length, but later decided that the length of the stem should be based on the diameter of the vines, meaning that stems in the beginning will be longer, and become shorter as the vines grow.
Then, when the stem reaches its maximum length, it creates a new Leaf object, taking this.s.x and this.s.y (x-y positions of the end of the stem) , this.VineDia (the diameter of the vine, which determines the size of the leaf), and this.s.direction (the angle of the vine at point (x, y)) as parameters. The leaf grows using two methods: growleaf() and continueGrowLeaf():
In order to create the effect where leaves gradually “grow” into existence, the scale of the leaves starts from 0 to a specified value. Hence, the growleaf() method calls the continueGrowLeaf() method as long as the leaf hasn’t grown until its maximum size (this.l._max_size, which depends on the vine diameter). Below is the continueGrowLeaf():
Line 194 translates the center of the leaf to the end of the stem, and the scale function in line 195 allows the leaf to grow every frame.
In general, I had difficulties determining the organization of the code. Originally, I only had class Vine, and kept the code for creating the vine, growing the vine, growing children, and growing stems in one method called growVine(). However, when it came time to manipulate the size of the stems and draw the leaves, the code became too disorganized and cluttered. I think re-organizing the structure of the code, by creating one method createVines(), which calls all the other methods — growThisVine(), displayVine(), growChildren(), createStem() — and then calling createVine() recursively for each new vine, makes the logic flow much better and easier to read.
____________________________________________
Future Development
Overall, I am content and satisfied with the final product. I think it adhered closely to my original proposal, in that I was able to succeeding in creating the illusion of hand drawn animation and the detailed yet delicate aesthetic. Admittedly, I spent most of my energy and time focusing on the vine growth, and then shifted towards the stems and leaves, which can be reflected in the final product. I made sure to include lots of dimension and detail to the vines, however I wish I could have spent more time adjusting the leaf shape to make the sketch look even more natural and hand drawn, and many of my peers felt the same way as well.
There a few things that I would like to improve on this sketch, one being stem shape. The stem is actually a child vine, but since it stops growing very quickly, we don’t get to see much wavy movement, as it it’s taking on the shape of a much larger vine. I would need to redefine the fluctuation variable, which is used to create the movement in the Vine constructor, in the Stem constructor and possibly change how noise is used to create this effect. Second, I would love to implement a gradient on the stem, so that it would begin the same brown color as the vine, but gradually change into the green color of the leaves. I think including this gradient would make the vines look much more natural. Third, as mentioned above, I would like to experiment more with adjusting the leaf shape and colors; namely, instead of using vertex() to draw the shape, I think using curveVertex() instead might help give the leaves a rounder, softer shape that isn’t so jarring to the eye. Finally, I would like to change the interactivity, so that the vines can move according to the position of the mouse, along with predetermined random() and noise() values.
Finally, my project is but a tiptoe into the world of algorithmic botany; hence I am very interested in trying to code different types of plants and flowers. The mathematical formula I based this design off of was 2^n, but this is mainly fitted for tree growth, and there are so many more formulas that could be explored later on.
____________________________________________
REFERENCES:
Soulwire “Tentacles”: https://soulwire.co.uk/tentacles/
Soulwire “Recursion Toy”: https://soulwire.co.uk/recursion-toy/