Concept
For this assignment, I wanted to build on top of ideas I thought of last week, particularly leveraging organic shapes in nature to produce generative, and *somewhat* interactive art. I especially wanted to dabble with mathematics and its ability to generate aesthetic abstractions and animations. To that latter point, my mind immediately shifted to the complex and patterned loops defined by parametric equations. I came across Re-generate, a work by Akshan Ish, that utilizes shapes governed by parametric relations, and was immediately inspired to adopt the concept. As I thought about possible shapes I wanted to recreate, I thought of butterfly shapes, and just as I hoped, I found a parametric curve that modeled them. With the mathematics by my side, I was now ready to translate it into a p5.js animated, generative sketch.
Process, Challenges, and Implementation
I created a butterfly class from which butterfly objects would be instantiated. The main attributes specified the starting point coordinates, the angle from the x-axis in the Cartesian plane used to control the drawing of the wings, the parameters that control the magnitude of the radius, the color of the stroke (which is randomized from a given color palette, and the angle that controls the rotation of the Cartesian plane so that different objects will be drawn from a different starting point. Having the explicit equations for the x and the y parameters facilitated things for me as I would have had to derive them myself otherwise. One thing I had struggled with a little bit here was making the curve draw incrementally over time. After realizing that the angle determines how much of the curve is drawn, it became evident that incrementing the angle in every frame by a little bit and drawing up to that point would essentially produce that effect.
class Butterfly { constructor(x, y) { this.x = x; // starting x location this.y = y; // starting y location this.theta = 0; // current drawing angle // choose a random color from the color palette for the butterfly animation this.color = random([ color("#7c9eb7"), color("#c5d6db"), color("#ffd3d7"), color("#ffc20c"), ]); // controlling hyperparameters for the butterfly shape this.b = random(3, 6); this.a = random([4, 6]); // variable controlling the rotation of the object this.angleRot = random([-1, 1]) * random([0, 1, 2, 3, 4]); } drawButterfly() { push(); // save the current drawing state translate(this.x, this.y); // move the origin to the object's position stroke(this.color); // set the stroke color based on the chosen color rotate((this.angleRot * PI) / 4); // rotate the object noFill(); strokeWeight(1); beginShape(); // draw the curve for (let i = 0; i <= this.theta; i += 0.1) { // calculate the radius based on the parameteric equation for the butterfly curve let r = exp(sin(i)) - this.a * cos(4 * i) + pow(sin((1 / this.b) * 12 * (2 * i - PI)), 5); // calculate x and y position of the curve let x = r * cos(i) * random(10, 20); let y = r * sin(i) * random(10, 20); // draw circle curveVertex(x, y, r); } endShape(); this.theta += 0.01; // increment theta for animation pop(); // restore original sketch state } finished() { return this.theta > TWO_PI; // to indicate that the drawing of the shape has ended } }
When the sketch is played, a Butterfly object is inserted into a global array of butterflies. The user can add objects to the sketch at any location by pressing the mouse. Once a butterfly object is drawn in full, it is deleted and another object is instantiated in its place at a random location. One issue I encountered was that the more objects I created by pressing the mouse, the more overcrowded the sketch became. I tackled the issue by placing bounds on the length of the butterfly array so that objects are only re-instantiated only if the array size does not hit a certain maximum size.
Admittedly, I had a lot of fun playing with different shapes and introducing randomness and Perlin noise into the sketch. I found that different methods produced different emergent qualities. For instance, curves with randomness were akin to children’s drawings on a blackboard, but with Perlin noise, they were more seamless and refined. Circles with randomness had a glowing radiance that reminded me of fireworks or diamonds. The use of circles with Perlin noise, however, elicited a more abstract effect and almost had a level of depth to it that I liked. Here are images from the four experiments below.
3.1 – Lines with Perlin noise 3.2 – Circles with randomness3.3 – Lines with randomness3.4 – Cirlces with Perlin noise
Embedded Sketch
I am embedding the sketch that I liked the most. The p5.js sketch for each of these can be found by clicking the URL linked with the caption below each one of the images above.
Reflections and Ideas for the Future
What I loved about the process of creating these sketches was how it naturally flowed from my earlier projects and how it amalgamated the power of mathematics to create something generative and abstract yet still organic and nature-inspired. I want to continue experimenting with different polar curves and to continue abstracting my work and learning more advanced animation strategies.