The Inspiration
So this one genuinely caught my attention when I saw it in the field trip. The reason I picked it specifically is the concept behind it. The piece is called Phenomena and teamLab describes it as being about bodies that exist in the world and influence one another just by being close to each other, like how two people standing near each other are quietly affecting their shared space even before they do anything. I find that really compelling as an idea, especially as something you’d try to turn into code. It’s not just a visual effect, it’s a statement about proximity and influence as a kind of physics. That got me thinking about this assignment very differently than the previous ones.
On top of that there were two things about the installation mechanics that genuinely puzzled me. The first one was the bloom trigger. My initial assumption was that the objects were flowering when they hit each other — some kind of collision detection causing the growth, and during the field trip I learned from one of the teamLab staff the I do not need to hit them to see them glow; the trigger is shaking. You pick up one of the floating objects and you shake it, and the flowers grow from inside it. The impact isn’t what causes the bloom, the movement is. That’s a completely different system and I thought it was a much more interesting design decision. It makes the interaction feel alive in a different way, you’re not smashing things together, you’re waking something up.
The second thing I got stuck on is something I remember discussing with Mustafa in the trip and actually brought up with the professor in class: how are those objects charged? There are LEDs glowing inside physical spheres that are being handed to and shaken by museum visitors, but there are no visible cables. I was honestly baffled by this for a while. The answer is (as professor said I searched it up and confirmed) wireless charging built into the table/base they rest on, the spheres charge inductively when placed down and then run on their own battery while being carried. It’s a small detail but knowing it makes the installation feel even more thoughtfully designed.
The Concept for the Sketch
I wanted to recreate this in 2D with two types of interaction: you can drag an orb and throw it to shake it (the throw velocity drives how much it blooms), and you can drag one orb into another to trigger a collision bloom on both. The idea is that every orb is an independent body with its own personality, its own color, its own slow drift, but they’re all part of the same shared space and they influence each other when they collide.
The twist I added is that the bloom direction is sensitive to what triggered it. A shake-bloom fires petals in the direction the orb was thrown, it follows the impulse. A collision-bloom fires petals in all directions equally, it’s a symmetric eruption. Both go through the same bloom() function, the only difference is whether I pass a direction angle or null. I really like that distinction because it matches the physics logic: a shake has a direction, a collision doesn’t.
The Physics Behind It
There are really three systems running here and they each borrow from what we’ve been building in class.
Petals are just particles with a lifespan. Each one has a position, velocity, and a slow angular spin. They get an initial velocity from the bloom call, then drag pulls them to a stop as lifespan ticks down.
Shockwave rings expand outward from the center of the bloom using lerp(r, maxR, 0.12) so they ease into their final radius rather than jumping there linearly.
Orb collision uses the same axis-projection pattern from the flocking separation work but instead of a steering force it does a proper 1D elastic velocity exchange:
let dvA = a.vel.dot(axis);
let dvB = b.vel.dot(axis);
a.vel.sub(p5.Vector.mult(axis, dvA - dvB));
b.vel.sub(p5.Vector.mult(axis, dvB - dvA));
This is just transferring the velocity component along the collision axis from one orb to the other. It’s not perfectly accurate rigid-body physics but it looks right and it’s enough to trigger the bloom.
Building It Up: Milestones & Challenges
Milestone 1: One Orb, Shake to Bloom
I started with a single orb. The goal was just to nail the interaction loop: grab → drag → release → bloom. Everything else could wait.
I stored the last 6–8 mouse positions in a dragHistory array during the drag. On release I subtract the first position from the last and divide by the length to get an average throw velocity. That average becomes both the orb’s initial velocity and the intensity input to bloom(). Fast throw = dense bloom, soft release = barely anything. This felt much more natural than just using the distance of the drag.
Getting the petal shape right took longer than I expected. My first attempt used circle() for all the petals and it looked like a sneeze. I switched to ellipse(0, 0, sz * 0.45, sz) after the rotate(this.angle) call and that immediately gave the petal elongation that reads as organic.
Milestone 2: Multiple Orbs and the Collision Problem
Adding five more orbs was straightforward. The harder thing was getting collision to feel right.
My first implementation just pushed overlapping orbs apart, same as separation. It looked fine statically but when you threw one orb into another the receiving orb barely moved and no bloom fired. The problem was I wasn’t measuring the impact. I needed to know how violent the collision was to decide bloom intensity, and that means comparing velocities before and after, not just positions.
The fix was computing impact = abs(dvA - dvB) — the difference in velocity components along the collision axis right before the velocity exchange happens. A slow drift touching another orb gives a tiny impact value. A fast throw gives a big one. I feed that directly into onCollision(impact) and map it to bloom intensity. Once I had that, smashing two orbs together at speed gives a massive synchronized double bloom and it looks exactly like what I was going for.
Petal Count vs. Performance
Once I had 6 orbs and was generating up to 55 petals per bloom event, I noticed the frame rate dropping noticeably after a few big collisions especially if I triggered two or three in quick succession. The sketch was potentially running hundreds of petal particles at once, each doing its own update() and show() call every frame.
The fix was two-pronged: I capped the max petal count per bloom at 55 (was originally 80), and I bumped the decay rate range from random(1, 3) up to random(2, 4) so petals die faster. After that the performance was fine even with all six orbs being thrown around simultaneously.
The Bloom Direction Distinction (The Part I’m Most Proud Of)
This is the piece of code I keep coming back to:
bloom(intensity, dirAngle) {
let count = floor(map(intensity, 0, 1, 6, 55));
for (let i = 0; i < count; i++) {
let angle = (dirAngle !== null)
? dirAngle + random(-0.6, 0.6)
: random(TWO_PI);
// ...
}
}
The dirAngle !== null check is doing a lot of work. Shake-blooms get the throw heading with a ±0.6 radian spread so the petals fan out in the direction of the throw like water spraying off a shaken bottle. Collision-blooms pass null and get random(TWO_PI) full circle. One function, one parameter, two completely different visual results. It felt like a clean way to encode the physics intent directly into the visuals.
The Final Result
Six glowing orbs drifting slowly in a dark space. Drag any one and throw it to see a directional petal bloom. Drag it into another to trigger a symmetric collision bloom on both. Faster collisions make bigger blooms. The orbs bounce off walls and off each other and slowly come to rest.
Controls:
- Click + drag: grab an orb and move it
- Release: throw it to bloom
- Drag into another orb: collision bloom on both
Reflection & Future Work
What I kept thinking about while building this is how the teamLab piece communicates its concept through its interaction design. The fact that shaking causes the bloom (not hitting) is a deliberate choice that makes you feel like you’re agitating something alive. Because it’s a shake it feels like you’re disturbing something that was at rest. I tried to preserve that feeling in the code by making throw velocity the input rather than a click event.
I also really like how the six orbs end up telling different stories in the same run. The slow-moving ones barely bloom at all unless you grab them. The ones that happen to drift into each other bloom spontaneously. The whole thing feels organic in a way that I didn’t explicitly program.
What I’d do differently or add next:
- Chained blooms: if a petal from one bloom hits another orb and crosses its radius, trigger a small secondary bloom. This would match the “influence” theme of the original much more directly
- Sound: a soft tone triggered at bloom intensity would complete the sensory loop; teamLab installations always have audio that’s responsive to the interaction