Assignment 4

Concept

For this assignment, as stated in the assignment prompt, I was inspired by Memo Akten’s Simple Harmonic Motion series, where he uses pure mathematical oscillation to create hypnotic, organic visuals. His work showed me that layering simple sine waves together can produce patterns of unexpected complexity and beauty. My concept, “Ripple Interference,” simulates what happens when you drop multiple stones into a still pond at the same time — each stone creates circular ripples, and where those ripples meet they either amplify or cancel each other out. This interference is pure Simple Harmonic Motion: every circle on the grid is oscillating up and down in size and color based on the sum of sine waves reaching it from multiple sources. The result is a constantly shifting, living pattern that feels organic despite being entirely mathematical.

SKETCH

Code Highlight

The section I’m most proud of is the wave interference calculation at the heart of the sketch:

let waveSum = 0;
 for (let src of waveSources) {
   let d = dist(x, y, src.x, src.y);

   // Each source creates a radial sine wave
   waveSum += sin(d * 0.04 * src.freq - time * src.speed);
 }

 // Normalize so value stays between -1 and 1
 waveSum /= waveSources.length;

This is the core of everything. For each point in the grid, I measure the distance to every wave source, then plug that into a sine function. The distance replaces the linear progress variable from the example we did in class, turning the flat wave into a circular ripple spreading outward. When multiple sources combine, their values add together — this is wave superposition, the same principle that creates interference patterns in real physics. Dividing by the number of sources at the end keeps the value normalized between -1 and 1, which feeds cleanly into the same map(sin(…)) color technique from the class example. What I love about this is that a single line of math creates emergent visual complexity from something simple.

Milestones and Challenges
Milestones

  • Extended the example we did in class from a single 1D wave row to a full 35×35 2D grid of oscillating circles
  • Successfully implemented radial wave propagation (circular ripples instead of flat waves)
  • Combined multiple wave sources using superposition to create interference patterns
  • Retained and extended the class example’s sine-based color mapping into 2D
  • Added interactive wave source placement with click

Challenge 1: Going from 1D to 2D
The example from class maps i linearly across the x-axis to get the wave position. When I first tried expanding this to a grid, I simply ran two nested loops and used the row number j for a second wave — but this just created a grid of identical horizontal waves stacked on top of each other, which looked flat and uninteresting. The breakthrough was switching from using the grid position directly to using the distance from a source point. Replacing width * progress with dist(x, y, src.x, src.y) inside the sin() function was what made the waves actually radiate outward like real ripples.

Challenge 2: Balancing the Interference Pattern
Once multiple wave sources were working, the interference looked chaotic — the colors and sizes were flickering too rapidly with no visual coherence. The problem was that summing multiple sine waves was pushing the total value well beyond -1 to 1, making the map() calls produce extreme values. Dividing waveSum by the number of sources normalized it back to a usable range. This small fix made a dramatic difference — the patterns became smooth, readable, and beautiful instead of noisy.

Reflection and Future Improvements
This assignment taught me how much complexity can emerge from a single mathematical operation repeated in different configurations. The sine function is doing all the real work here — everything else is just deciding where to sample it and what to do with the result. Memo Akten’s work resonates more deeply now because I understand how restraint in the tools you use forces you to be more creative with how you use them.
Below are some ideas I would implement in the future:

  • Moving wave sources – Sources that drift slowly across the canvas, constantly changing the interference pattern
  • Mouse-responsive waves – The mouse position acts as a live wave source that follows your cursor
  • Frequency controls – Sliders to adjust each source’s frequency in real time
  • Different grid shapes – Hexagonal or circular grids instead of square
  • Sound integration – Map wave amplitude to audio frequency for a visual synthesizer

Salem Al Shamsi – Assignment 4

The Conductor — Invisible Hand

Concept & Inspiration :

For this project, I was inspired by Memo Akten’s “Simple Harmonic Motion #12 for 16 Percussionists.” In that piece, 16 performers stand on stage, and each one receives instructions from a computer through their earpiece when to step forward, when to hit their drum, and when to turn on their flashlight. They don’t know what the bigger picture looks like. They just follow their own simple instructions. But when you watch all 16 of them together, something beautiful and complex emerges.

I wanted to translate that idea into a visual sketch. Instead of real performers, I have 16 glowing nodes arranged in a circle. Instead of a computer sending cues through earpieces, I have an invisible point, “the conductor,” that orbits around them. When it gets close to a node, that node lights up. The conductor’s path starts clean and orderly, then gradually becomes chaotic and unpredictable, then returns to order. And the viewer can use their mouse to become a second conductor, creating a tension between human control and machine control.

 

Code I’m Proud Of:

getActivation() method from the Shockwave class:

getActivation(nodeX, nodeY) {
    let d = dist(this.x, this.y, nodeX, nodeY);
    let distFromWave = abs(d - this.radius);

    if (distFromWave < this.activationWidth) {
      return map(distFromWave, 0, this.activationWidth, 1, 0);
    }
    return 0;
  }

What this does is pretty simple: it checks how far a node is from the wave’s current edge. If the node is within the wave’s “thickness” (60 pixels), it gets activated stronger if it’s right on the edge, weaker if it’s at the boundary. If it’s outside that band, nothing happens. So when you click, the ring expands outward and each node lights up only when the wave actually reaches it, not all at once. That one small function is what makes the whole click interaction feel like dropping a stone in water instead of just flipping a switch.

Milestones and Challenges

Stage 1: Circle of 16 Nodes. I placed 16 nodes evenly around a circle using cos() and sin(). The main challenge was getting the spacing right and making the glow effect look soft instead of harsh.

Stage 2: The Invisible Conductor I added an invisible point that orbits the circle and activates nearby nodes based on distance. The tricky part was making the activation smooth without lerp(), the nodes just snapped on and off like a light switch, which looked bad.

Stage 3: Hit Flashes and Ripples. When a node reaches peak activation, it now flashes bright and sends out a ripple ring. The challenge was making sure the hit only fires once per pass, not every single frame while the conductor is nearby. I solved this with a simple flag called wasAboveThreshold.

Stage 4: Order to Chaos to Order. This is where it got interesting. I made the conductor’s path morph between a circle, a figure-8, and random noise over a 35-second cycle. Getting the blending right took some trial and error at first; the transitions were too sudden, and it looked glitchy instead of smooth.

Embedded Sketch

Stage 5:Polish and Mouse Interactivity I added connection lines between nodes, a center glow, film grain, and mouse interactivity. The mouse acts as a second conductor with a smaller reach (so you can only affect a few nodes at a time). Clicking sends a shockwave. The biggest challenge here was combining three different activation sources (machine, mouse, and shockwave) without them conflicting with each other.

Reflection

This project taught me a lot about how simple rules can create complex-looking behavior. Each node only knows one thing: how far it is from the conductor, but when you watch all 16 together, it looks like something alive. That’s basically the same idea behind Akten’s original piece, and I think that’s what makes it so powerful. If I had more time, I’d love to add sound, maybe a soft tone or drum hit when each node gets activated, so it feels more like an actual performance. I’d also like to try it with more nodes (maybe 32 or 64) to see how the patterns change. Another idea is to let the viewer switch between order and chaos manually using a key press, so they have even more control over the composition.

Amal – Assignment 4: Tadpole Anemone

Concept + Inspiration

This project was created in response to the assignment requirement to use Memo Akten’s exploration of Simple Harmonic Motion as a starting point. The goal was to understand how oscillation can function as a generative system rather than just a repetitive mechanical movement.

What I found most interesting in Memo Akten’s work is how simple sine functions can create complexity when layered together. Instead of treating harmonic motion as a physics simulation, I treated it as a compositional structure. I used multiple oscillators with different frequencies and phase shifts so that interference patterns would emerge naturally from the system.

Rather than keeping the study abstract, I translated the oscillatory behavior into a tidepool ecosystem. Each anemone is driven by overlapping harmonic functions that simulate tidal pull, organic sway, and micro-movements within the tentacles. A slower oscillator controls the bloom intensity, which creates a bioluminescent effect that feels ecological instead of mechanical.

Sea Anemones shine with fluorescence! – Mendonoma Sightings

I was mainly inspired by their bioluminescence and the way they sway so beautifully in the water, this is the image the drew the majority of the inspiration and what I’ve tried to mimic. However when I was done, I realized that this looks like the small lights in the new near by gas station “the hub”, makes me wonder if the inspo was more subconscious??

Code I Am Particularly Proud Of

One section of code I am particularly proud of is the multi-layer harmonic interference that drives the tentacle motion:

// I used AI to help achieve this :)
let oscA = sin(this.t * 1.55 + p);
let oscB = sin(this.t * 0.92 + p * 0.7 + this.phase);
let oscC = sin(this.t * 0.45 + p * 1.9);

let sway = (0.75 * oscA + 0.45 * oscB + 0.25 * oscC + this.current) * 0.65;

I used AI to help refine this blending logic. My intention was to create layered oscillation instead of a single sine-driven movement. The AI-assisted refinement helped structure the interference in a way that felt balanced without becoming chaotic.

This section is important to me because it shifts the system from predictable motion to something that feels organic. By combining oscillators with different frequencies and phase relationships, the movement becomes more ecological and less mechanical while still remaining mathematically grounded in Simple Harmonic Motion.

The Sketch

Milestones and Challenges

The first milestone was building a single anemone driven by one primary harmonic function. The focus at this stage was verifying that the tentacle sway behaved consistently and that amplitude, frequency, and phase shifts were functioning correctly.

Challenge: The motion initially felt mechanical and repetitive. With only one oscillator driving the movement, the behavior was too predictable and visually flat. This prototype helped me understand the limitations of a single harmonic source.

[gif to be added but the upload time is sooooo looooooonnnnggg :/]

instead here is a video:

The second milestone introduced multiple oscillators and expanded the system into a grid of anemones. This is where interference patterns began to emerge. I layered harmonic functions with different frequencies and phase offsets to create more complex sway.

Challenge: Balancing complexity without losing control. When too many oscillators were layered equally, the movement became chaotic. I had to adjust weight values so the system felt organic rather than noisy.

This stage also introduced the idea of a global tide and a directional current controlled by mouse movement.

Reflection and Ideas for Future Work

Through this project, I began to understand how Simple Harmonic Motion can function as a structural system rather than just a visual effect. Layering oscillators changed the behavior significantly, and small adjustments in frequency and phase created noticeable shifts in organic quality. The process reinforced how sensitive generative systems are to parameter balance.

One of the main insights was that complexity does not require complicated formulas. It requires intentional relationships between simple ones. When I reduced or reweighted oscillators, the motion became more coherent. When I over-layered them, the system lost clarity. This balance became central to the final result.

For future development, I would like to explore local interaction between anemones instead of having them behave independently. Introducing neighbor-based influence could allow wave propagation across the field. I am also interested in integrating audio input so harmonic frequencies respond dynamically to sound.

Finally, I would experiment with scaling the system for projection or installation, where viewer proximity could influence tide intensity or bloom cycles. Expanding the system spatially would shift it from a screen-based study into an environmental experience.

Assignment 4

Concept

Inspired by Memo Akten, my concept is to simulate a row of searchlights fixed along the bottom of the screen. Each light oscillates back and forth using a sine wave.

The “personality” of the piece comes from the Phase Offset. Because each light starts its swing a fraction of a second after the one next to it, the beams create a harmonic wave effect as they sweep across the sky. I used high-transparency triangles to mimic the look of light passing through fog or haze.

Memo Akten’s Simple Harmonic Motion #6 Performance proof of concept (2011)

The Sketch
  • Watch: The beams move in a synchronized wave.

  • Interact: Move the Mouse to change the “Spread” of the lights. Moving Right makes the wave more chaotic; moving Left brings them into perfect sync.

  • Click: To change the color palette from “Cold Searchlight” to “Warm Amber.”

Code Highlight

I am particularly proud of the display() function for the beams. Instead of drawing a simple line, I used a gradient-like approach with multiple triangles. This creates the “glow” effect where the light is brightest at the source and fades as it stretches into the dark.

display() {
    // We use a loop to draw layers of the beam for a glow effect
    for (let i = 8; i > 0; i--) {
      // As i gets smaller, the beam gets thinner and brighter
      let alpha = map(i, 1, 8, 15, 2); 
      let beamWidth = i * 4;
      
      fill(50, 20, 100, alpha); // Soft white/blue glow
      noStroke();
      
      push();
      translate(this.x, this.y);
      rotate(this.angle);
      
      // Draw the triangular beam of light
      triangle(0, 0, -beamWidth, -height, beamWidth, -height);
      pop();
    }
  }
Milestones

This was my first attempt. I successfully mapped the Sine wave to the rotation of a line, but it felt very mechanical and flat. There was no phase offset yet, so every light moved in perfect, boring unison.

In this version, I moved away from the basic “sticks” and made it actually look like a light. By drawing multiple overlapping triangles with very low opacity, I create the illusion of light scattering through a hazy or smoky sky. All that’s left is the interaction!

Reflection and Future Work

This assignment highlighted how much “mood” can be created with very little code. By using Simple Harmonic Motion to drive rotation and layering simple shapes with transparency, I created a complex, atmospheric environment. Future improvements:

  • Particle Haze: I would like to add tiny “dust” particles that catch the light only when the beam passes over them.

  • Sound-Reactive: Having the beams “grow” or “shrink” in length based on the volume of a music track.

  • 3D Volumetric: Moving this into a 3D space where the beams can rotate on two axes, allowing them to point toward or away from the viewer.

Buernortey – Assignment 4

Concept and Inspiration

This sketch is inspired by my high school physics experiments with simple harmonic motion, especially spring–mass systems. In those experiments, we measured displacement and time as a mass oscillated back and forth, but the motion was mostly understood through formulas and graphs.

For this project, I wanted to recreate that experiment visually and interactively. Instead of only calculating values, my goal was to simulate the motion directly and allow parameters like amplitude, oscillation rate, and damping to be adjusted live. This turns the physics formula into something observable and explorable.

The final result is an interactive spring–mass simulation driven directly by the SHM equation.

Development Stages

Below are the main stages of how the sketch evolved:

Stage 1 — Basic Oscillation

Purpose: Test the SHM formula using a moving dot. This stage ensures the sine-based oscillation behaves as expected.

Stage 2 — Spring–Mass Visualization

Purpose: Represent the physics lab setup visually. A zig-zag spring connects the mass to equilibrium, giving a realistic spring–mass system.

Stage 3 — Interactive SHM with Damping

Purpose: Add interactivity and more realistic physics. Users can control amplitude, oscillation rate, and damping. Motion trail shows past displacement.

Code Highlight

The most important line in the final sketch is:

let x = equilibrium + amplitude * sin(angle) * exp(-damping * time);

This combines harmonic oscillation(sin()), displacement scaling (amplitude), and exponential decay (damping). It directly translates the physics model into animation behavior.

Final Sketch

In the final version, the sketch became fully interactive. Users can adjust sliders to control amplitude, oscillation rate, and damping, and a motion trail shows the displacement history over time. The spring–mass system is visualized clearly, and all variable names are stable to avoid conflicts with p5.js reserved functions.

Challenges Encountered

During development, the first connector looked more like a rope than a spring, so I had to adjust the zig-zag design to make it visually accurate. Balancing the damping values took several tests to ensure the motion was realistic but not too quick to stop. Slider ranges also needed careful tuning to prevent unstable or jittery motion. Additionally, the variable originally named speed conflicted with a reserved p5.js function, requiring a rename to rate. Each challenge was solved through iterative testing and visual adjustments to maintain smooth and accurate motion.

Reflection and Future Improvements

This project helped me understand simple harmonic motion more intuitively than through static formulas. Seeing the oscillation respond to parameter changes in real time made the relationships between amplitude, speed, and damping much clearer. For future improvements, I would add a live sine graph alongside the spring, a toggle to switch to a pendulum mode, multiple coupled springs to simulate more complex systems, and data readouts similar to a virtual lab tool to record measurements and analyze motion quantitatively.

Haris – Assignment 4

Concept

When looking at Memo Akten’s work there was one piece that really took my attention. It was the “Simple Harmonic Motion #12 (2015)”. This although seemingly simple work with people hitting drums with their flashlight really caught my attention by the way it was done with playing with the lights and having all the actors “controlled by the computer”. So I decided that this is the perfect piece to somehow try to recreate in a similar way in p5.

Process

To begin with i first made the “map”. I decided to go with a “stage” looking design to fit the theme so to create something that fits what I imagined I made a completely black background with gray boxes to indicate stages where the people could move.

After it was time to create the performers. I created a performer class where I could create each of the human like performers that would move around the screen. I also decided to give them hands to give them some personality.

At first I experimented with random timing for movements, but this did not feel intentional or rhythmic. The animation looked chaotic rather than composed. To fix this, I replaced random triggers with sine wave oscillators, meaning that every action was driven by harmonic motion instead of randomness.

let g = (sin(frameCount * 0.02 + this.pid * 0.7) + 1) * 0.5;
this.onStage = g > 0.65;

let a = (sin(frameCount * 0.05 + this.pid) + 1) * 0.5;
this.armTarget = a > 0.75 ? 1 : 0;

After motion was working, I implemented the spotlight effect. Rather than drawing a single circle of light, I layered multiple translucent ellipses. This creates a gradient glow that visually resembles stage lighting and feels more organic than a flat shape.

The final step was adding sound. Each time a performer raises their arms while in the spotlight, a drum sound is triggered. I detect this moment by checking for a transition from arms-down to arms-up. This event-based logic ensures the sound only plays at meaningful moments instead of continuously.

Code Highlight

The proudest part of my project was definitely the movement.

let g = (sin(frameCount * 0.02 + this.pid * 0.7) + 1) * 0.5;
this.onStage = g > 0.65;

let a = (sin(frameCount * 0.05 + this.pid) + 1) * 0.5;
this.armTarget = a > 0.75 ? 1 : 0;

I am particularly proud of this part because it captures the entire conceptual idea in just a few lines of code. Instead of manually controlling each performer or assigning scripted movements, each performer is moved by a sine wave with a slightly different phase offset. This means every performer follows the same rule but behaves differently over time.

Future Improvements

If I were to continue working on this project I would maybe like to add some interactivity into it. At this point in time I am not sure how interactivity would work on this project and in what sense it could be implemented so I would love some suggestions. I would also maybe work a bit on visuals, but overall I am really happy with the final project.

Assignment 4: Harmonic Motion

My inspiration comes from Memo Akten’s Simple Harmonic Motion 8-9.  I wanted to build something that felt alive on screen. Waves have always fascinated me, specifically the way two simple oscillations combine into something unexpectedly complex. I used the principles of adding waves together such that: peak + peak = higher peak, trough + trough = lower trough, and peak + trough cancel each other.

Please move mouse around and click around the sketch for special effects.

I started with the simplest possible thing: a single sine wave drawn as dots across the canvas.

I added a second wave with a different frequency and a phase offset of PI, so it starts on the opposite side of the cycle from wave one. The two waves drift in and out of sync as time moves forward. Wave two has a slightly higher frequency and a smaller amplitude, so it has its own distinct character.

This is where things got interesting. I added a third wave that is the sum of the first two. When the two source waves push in the same direction, the result amplifies. When they oppose each other, they cancel out. The yellow interference wave is the visual record of that conversation between the two.

let y3 = y1 + y2;
stroke(255, 220, 80);
strokeWeight(5);
point(x, height / 2 + y3);

 

I replaced the solid background() call with a semi-transparent rectangle drawn each frame. The old frames fade slowly instead of disappearing instantly.

fill(10, 10, 20, 25);
noStroke();
rect(0, 0, width, height);

I replaced fixed amps with values that oscillate slowly over time using a second, slower sine function.

let amp1 = map(sin(t * 0.3), -1, 1, 40, 130);
let amp2 = map(sin(t * 0.17 + PI), -1, 1, 30, 110);

The two amplitudes breathe at different rates, so they are never in sync with each other. The interference wave gets dramatically more expressive as a result, going nearly flat at times and spiking wide at others.

 

I switched to HSB color mode and tied the hue and brightness of each point to its position in the wave cycle.

let hue1 = map(sin(x * 0.01 + t * 0.5), -1, 1, 160, 220);
let bright1 = map(abs(y1), 0, amp1, 60, 100);

I expanded from two base waves to four, each with its own frequency, speed, phase, and breathing amplitude. I also added two partial interference sums alongside the full sum of all four.

The frequency ratios across the four waves are close to harmonic but slightly off, so the pattern never fully repeats. There is always something new happening somewhere on the canvas.

let yA    = ys[0] + ys[1];
let yB    = ys[2] + ys[3];
let yFull = ys[0] + ys[1] + ys[2] + ys[3];

 

At this point the draw() loop was getting hard to read. I pulled the repeating logic into dedicated functions. All wave parameters moved into a waveDefs array of objects.  I also moved the array definition inside setup().

 

function waveY(x, def, amp) { ... }
function breathingAmp(i) { ... }
function driftHue(x, hueMin, hueMax, freqX, freqT) { ... }
function drawWavePoint(x, y, centerY, hue, sat, maxAmp, weight, alpha) { ... }
function drawSumPoint(x, y, centerY, maxDisplace, hueMin, hueMax, sat, weight, alpha) { ... }
 This is the highlight of code im proud of.
  ampPhases = [0, PI, HALF_PI, PI / 3];

  waveDefs = [
    { freqX: 0.020, freqT: 1.0, phase: 0,        ampMin: 40, ampMax: 130, hueMin: 160, hueMax: 220, weight: 3 },
    { freqX: 0.035, freqT: 1.5, phase: PI,        ampMin: 30, ampMax: 110, hueMin: 260, hueMax: 320, weight: 3 },
    { freqX: 0.055, freqT: 0.7, phase: HALF_PI,   ampMin: 20, ampMax:  80, hueMin: 100, hueMax: 160, weight: 2 },
    { freqX: 0.013, freqT: 2.0, phase: PI / 4,    ampMin: 15, ampMax:  60, hueMin:  20, hueMax:  60, weight: 2 },
  ];
}

function waveY(x, def, amp) {
  return sin(x * def.freqX + t * def.freqT + def.phase) * amp;
}

function breathingAmp(i) {
  return map(sin(t * ampSpeeds[i] + ampPhases[i]), -1, 1, waveDefs[i].ampMin, waveDefs[i].ampMax);
}

function driftHue(x, hueMin, hueMax, freqX, freqT) {
  return map(sin(x * freqX + t * freqT), -1, 1, hueMin, hueMax);
}

function drawWavePoint(x, y, hue, sat, maxAmp, weight, alpha) {
  let bright = map(abs(y), 0, maxAmp, 55, 100);
  stroke(hue, sat, bright, alpha);
  strokeWeight(weight);
  point(x, height / 2 + y);
}

function drawSumPoint(x, y, maxDisplace, hueMin, hueMax, sat, weight, alpha) {
  let hue = map(y, -maxDisplace, maxDisplace, hueMin, hueMax);
  let bright = map(abs(y), 0, maxDisplace, 60, 100);
  stroke(hue, sat, bright, alpha);
  strokeWeight(weight);
  point(x, height / 2 + y);
}

I added a mousePull() function that bends each wave point toward the cursor. The pull strength falls off with distance, reaching zero at 200 pixels away. Moving the mouse slowly across the canvas bends the waves toward it in a way that feels physical. The effect fades naturally so it never feels abrupt. The final step was a Ripple class. Clicking spawns a ring that expands outward from the click position and displaces any wave point it passes through. The ring has a bandwidth of 40 pixels. Points inside that band get displaced, everything outside it is untouched. The ripple fades as it expands and gets removed from the array once it exceeds its maximum radius. Multiple ripples can coexist and their displacements stack on top of each other.

function mousePull(x, baseY, centerY) {
  let dist = sqrt(dx * dx + dy * dy);
  let influence = constrain(map(dist, 0, 200, 60, 0), 0, 60);
  return dy * (influence / max(dist, 1)) * -1;
}


class Ripple {
  constructor(x, y) {
    this.radius = 0;
    this.speed  = 4;
    this.maxRadius = 300;
    this.strength  = 55;
  }

  influence(px, py) {
    let ring = abs(dist - this.radius);
    if (ring > 40) return 0;
    let fade    = map(this.radius, 0, this.maxRadius, 1, 0);
    let falloff = map(ring, 0, 40, 1, 0);
    return sin(ring * 0.3) * this.strength * fade * falloff;
  }
}

 

For future improvements, I want to make the waves responsive to music/notes. I think this can be done by using Fast Fourier Transform which I’ve used and written a paper about before in one of my INTRO TO IM projects. it would work by processing the whole audio file once then storing the data in a queue and mapping each frequency band to an intersection between waves. I really wanna try this but it seems a little bit challenging so I didnt implement it in this sketch.

Week 4- SHM x Abu Dhabi

Concept

This project began with Abu Dhabi.

More specifically, it began with the building everyone calls the “Pineapple Building,” formally the Aldar Headquarters Building. Growing up in the UAE, I have always been surrounded by architecture that feels sculptural, patterned, and repetitive. What fascinates me about this building is not just its circular form, but its structural skin. It feels cellular. Layered. Alive.

Our class is about nature. At first, I struggled with how to connect Abu Dhabi’s hyper-urban identity to natural systems. Then I began thinking about cities as organisms.

Cities breathe.T hey pulse. They expand and contract.

That is where Simple Harmonic Motion came in.

Inspired by Memo Akten’s approach to translating natural systems into generative code, I wanted to build something that felt architectural but behaved like a living surface. Instead of simulating water, particles, or gravity, I decided to simulate a kinetic façade  an aperture system that opens and closes like breathing cells across a city skin.

The triangular repetition of the Pineapple Building translated into a 6-fold radial aperture. Each module behaves like a mechanical petal system. When tiled together, they form a shifting urban membrane.

The result is not a literal copy of Abu Dhabi architecture, but a computational abstraction of its rhythm.

Code Highlight

One piece of code I am particularly proud of is the phase variation across the grid. At first, all modules were opening and closing at the same time, which felt flat and mechanical in a static way.

Introducing a spatial phase shift changed everything:

const p = i * 0.42 + j * 0.36;
const open01 = 0.5 + 0.5 * sin(t + p);

Instead of synchronized movement, the surface now moves like a wave. It feels less like a digital animation and more like a living field.

I also implemented easing to make the motion linger at the open and closed states:

function easeInOut(x) {
return x < 0.5 ? 4 * x * x * x
: 1 - pow(-2 * x + 2, 3) / 2;
}

This small adjustment made the motion feel architectural rather than purely mathematical.

EMBEDED SKETCH

Milestones and Challenges

Milestone 1: Building a Stable Radial System

The first step was creating a single aperture module. I constructed six evenly spaced angles:

for (let i = 0; i < 6; i++) {
let angle = i * TWO_PI / 6;
}

This established rotational symmetry. However, early attempts resulted in uneven overlaps and distorted petal geometry. The relationship between the inner hub radius, hinge radius, and outer tip radius required several rounds of trial and error.

Too much spread caused the petals to disconnect.
Too little spread made the motion invisible.

Balancing geometry and movement became the central challenge.

Milestone 2: Introducing Simple Harmonic Motion

To simulate breathing, I introduced a sine-based oscillation:

let open = 0.5 + 0.5 * sin(t);

This normalized the motion between 0 and 1. However, pure sine motion felt abrupt at the extremes. It lacked the softness of organic motion. That led to introducing easing to create a smoother open-close rhythm.

This was my first real “nature” moment. I realized that nature is rarely linear. Even harmonic systems have softness.

Milestone 3: Scaling to an Urban Surface

Once the single module felt stable, I tiled it into a staggered grid:

const x = i * stepX + (j % 2) * (stepX * 0.5);
const y = j * stepY;

The offset grid created density similar to a façade or cellular membrane.

The biggest challenge here was visual noise. When too many modules moved in sync, the surface felt static. When phase variation was too extreme, it became chaotic. Finding the right coefficients for the phase shift required repeated adjustment and testing.

This stage transformed the project from an object into an environment.

Reflection

I am in AW in what I can create in a week and teach myself….

What I learned from this project is that nature does not only exist in forests or oceans. It exists in systems. It exists in repetition. It exists in oscillation.

Abu Dhabi, often perceived as artificial or hyper-constructed, actually contains its own form of organic logic. Through coding, I translated that logic into a living digital surface.

This project allowed me to think about cities as breathing entities. Architecture as skin. Code as biology.

Future Improvements

Moving forward, I would like to:

  • Introduce mouse interaction so the “city” responds to proximity.

  • Incorporate particle systems inspired by Nature of Code Chapter 4.

  • Experiment with light and shadow instead of line-only rendering.

  • Translate the system into a physical fabrication prototype, possibly laser-cut layered acrylic panels.

I am especially interested in expanding this into a responsive façade simulation, where environmental data could drive the oscillation.

Assignment 4

Concept

For this assignment, I wanted to explore how Simple Harmonic Motion can be used to recreate organic environments. I took inspiration from Memo Akten, specifically his ability to take rigid mathematical oscillations and turn them into fluid, life-like movements.

My goal was to create a painterly ocean. Instead of perfectly smooth curves, I wanted broken lines that feel like the faceted surface of water at night. To tie it all together, I added a breathing moon and a star field, creating a cohesive, glowing atmosphere.

Sketch

Process

I started by creating a Wave class that uses the sine function. At first, the waves were just single lines. The challenge here was getting the “broken” look; I achieved this by using a large xStep in my loop, which created sharp angles between my vertices instead of a smooth curve.

Inspired by a sample sketch from class that used overlapping circles to create a glow, I decided to apply a similar logic to my waves. I implemented a nested loop that draws each wave 30 times per frame. Each layer has a slightly larger strokeWeight and a very low alpha value. This additive layering is what gives the water its ghost-like, ethereal quality.

A major technical hurdle was a gap on the right side of my canvas. Because my xStep didn’t always land perfectly on the edge of the screen (600px), the shape would “break” and draw a straight line back to the start.

I fixed this by manually adding a final vertex at exactly width before closing the shape, ensuring the glow stayed consistent across the whole viewport.

Finally, I added a star field and a glowing moon. The moon uses the same SHM logic as the waves. Its outer glow pulses using a sin() function, making it look like it’s breathing or shining through a thin layer of haze.

Highlight

I am particularly proud of the Layered Glow Logic. It’s a simple loop, but it completely transforms the sketch from a flat math diagram into a piece of digital art. By jittering the y position slightly with i * 2, the glow “spreads” naturally.

// Layering loop for the glow effect
for (let i = 0; i < 30; i++) {
  stroke(255, 10); 
  strokeWeight(0.5 + i * 0.8); // Thickens the stroke for outer "blur"
  
  let glowCol = color(red(this.col), green(this.col), blue(this.col), 15);
  fill(glowCol);
  
  beginShape();
  // ... vertex calculations ...
  let y = (this.yOffset + i * 2) + sin(currentAngle) * this.amplitude;
  vertex(x, y);
  // ... 
  endShape(CLOSE);
}

Reflection and Future Ideas

This project taught me that nature in code doesn’t have to be random. By using pure trigonometry, I was able to simulate the rhythm of the ocean.

Future Ideas:

  • Perlin Noise Integration: I’d like to use noise to vary the amplitude so that “rogue waves” occasionally swell up.

  • Interactive Tides: Mapping the mouse position to the frequency of the waves, so moving the mouse makes the ocean “choppier.”

  • Twinkling Stars: Using a unique sine wave for every star so they shimmer at different frequencies.

Assignment 4 : Yash

Swinging Shadows: Simulating Harmonic Motion and Light

Concept & Inspiration

The initial idea for this sketch was born out of an interest in exploring simple harmonic motion and dynamic lighting. I wanted to create a scene that felt alive, where pendulums swing back and forth, casting real-time, infinite shadows over a central object.

While a pure top-down 2D view was the starting point, I quickly realized that squashing the arc of a pendulum into a straight line kills the illusion of gravity and momentum. To fix this, I shifted the frame of reference to a 2.5D isometric perspective. By pitching the camera down slightly, the vertical arc (the Z-axis height) of the pendulum becomes visible, allowing for suspension wires and a much more realistic sense of depth and physics.

The Sketch

Interact with the canvas below! Use the + and buttons to add or remove swinging lamps.

Code Highlight: The  Shadow Engine

Creating realistic lighting and shadows in the canvas without relying on heavy, resource-intensive raycasting is a fun challenge. Instead of standard lighting engines, I am particularly proud of the custom reverse-masking trick used here.

To keep the shadows perfectly sharp while maintaining the angled 2.5D perspective, the math temporarily stretches the angled coordinate space back into a perfect 2D circle, calculates the exact light tangents of the cylinder relative to the light source, and then squashes the coordinates back down to match the camera tilt. It then draws a polygon matching the background color to act as a stencil, creating perfect, infinite shadows.

// 3. Draw shadows cast by the lamps on the cylinder
  fill(bgColor); // Shadows act as a mask matching the background
  noStroke();
  
  for (let pos of currentPositions) {
    // Stretch the position mathematically to compensate for the 2.5D tilt
    let stretchY = cy + (pos.y - cy) / tilt;
    let stretchX = pos.x;
    
    let d = dist(cx, cy, stretchX, stretchY);
    
    if (d > cylinderRadius) {
      // Calculate exact tangent points on the stretched perfect circle
      let angleToCenter = atan2(stretchY - cy, stretchX - cx);
      let theta = asin(cylinderRadius / d); 
      
      let angle1 = angleToCenter + PI - theta;
      let angle2 = angleToCenter + PI + theta;

      let p1x = cx + cylinderRadius * cos(angle1);
      let p1y_circle = cy + cylinderRadius * sin(angle1);
      let p2x = cx + cylinderRadius * cos(angle2);
      let p2y_circle = cy + cylinderRadius * sin(angle2);

      // Squash the Y coordinates back down to match our tilted screen perspective
      let p1y = cy + (p1y_circle - cy) * tilt;
      let p2y = cy + (p2y_circle - cy) * tilt;

      // Project the shadow polygon far off the canvas
      let rayLength = max(width, height) * 2;
      let p3x = p1x + (p1x - pos.x) * rayLength;
      let p3y = p1y + (p1y - pos.y) * rayLength;
      let p4x = p2x + (p2x - pos.x) * rayLength;
      let p4y = p2y + (p2y - pos.y) * rayLength;

      // Draw the masking quad
      beginShape();
      vertex(p1x, p1y);
      vertex(p2x, p2y);
      vertex(p4x, p4y);
      vertex(p3x, p3y);
      endShape(CLOSE);
    }
  }

Milestones and Challenges

Milestone 1: Basic Pendulum Motion with Light Glow

The first major milestone was getting the pendulum physics working with a simple light effect. I started by implementing the basic sine wave motion for a single lamp and added a glowing effect using radial gradients. This helped me understand the core animation loop before adding complexity.

One challenge here was getting the light to look realistic. I had to experiment with diffrent opacity values and multiple gradient layers to achieve the soft glow effect.

Milestone 2: Adding the Cylinder and Shadow Projection

The biggest chalenge was implementing the shadow geometry. I needed to calculate the tangent lines from the lamp position to the cylinder edge, then project those shadows outward. This required understanding some trigonometry with atan2() and asin() to find the exact tangent points.

Getting the shadow to look correct from the tilted perspective was tricky. I had to “stretch” the lamp position back to a top-down view, calculate the tangents, then apply the tilt transform to the shadow vertices. After alot of trial and error with the math, it finaly worked!

Reflection & Future Work

Exploring how mathematical rules govern natural movement has been a recurring theme in my coding practice. Just as manipulating acceleration can simulate organic flocking behaviors, manipulating phase offsets and trigonometric tangents here brings mechanical pendulums to life. Shifting from a flat plane to a 2.5D environment was the biggest hurdle, but it completely transformed the visual weight of the project.

For future iterations, I would love to push the visual polish even further. Adding a subtle, fading particle trail behind the glowing bulbs could give the motion more visual history. Additionally, mapping the user’s mouse coordinates to the tilt variable would allow for dynamic camera control, letting users seamlessly fly the camera from a pure top-down view to a low, ground-level angle in real-time. Finally, integrating these canvas controls into a more robust, styled UI overlay would align it nicely with modern web design standards.