wh0wh0 – bamb00

A music video designed and coded for a single ”bamb00” by a Polish drummer wh0wh0 (Jacek Prościński).

The video is a live recording of the website bamb00.net, coded in JavaScript to animate 3D objects, triggered by the sounds of the drums. Every playback generates a different result – random elements, perspectives. and movements – guided by algorithmic rules.
Read more about the coding process

GOALS

When I first heard the track, I realized this task would require a unique approach. Jacek’s music is insanely dynamic and sounds different at every performance. Sometimes, certain parts are extended longer than usual. That’s why I began thinking about how to make the visuals more adaptable over time and focused on the generative aspect of the project. With so many layers and sounds involved, I knew that to create a proper visualization, I needed to try something that would give me flexibility and also challenge me. I decided to work in 3D. Additionally, the system had to function in real-time for the live shows (ideally at 60 fps), which meant it needed to be lightweight to render and designed in a simple, efficient way.

Solutions

DYNAMIC

I began by gathering all the information about the scenes, key moments, and drum notes into a MIDI track. A MIDI track is easy to edit in a program like Ableton and can also be loaded onto a website.

Ableton session

I counted thirteen scenes and set different parameters for each to vary their dynamics.

if (STAGE==12) { dynamic = 0.92; changeTransforms = true; changeFlips = false; changePartsSet = true; changeViewChance = 0.9; changeRandomProtY = false; changeScales = true; changeSpaces = true; showTotalBox = true; showPartBox = false; showGroundBox = false; showVertices = false; glitchGrids = true; randomizeGrid = true; }

To amplify the sense of the vast number and density of notes being played, I made sure not to miss any sounds in the MIDI track. I then connected each note to specific functions, such as moving, flipping, or rotating particles, rotating the camera, adjusting gaps or scales, and changing sets of elements.

if (midiNote==0) { // KICK if (chance(0.85)) resetParts(); else if (changeTransforms) for (int i=0; i<7; i++) translateParticle(); if (chance(changeViewChance)) setRandomView(); if (changeSpaces) randomSpacing(); if (changeScales) randomScaling(); if (changeRandomRotY) randomRotY(); if (changeRandomProtY) randomPRotY(); if (changePartsSet) randomPartsSet(); }

HEAD PARTS

The core element of the video is a head divided into multiple parts of varying sizes. To generate these parts, I needed a library capable of intersecting 3D objects. miho’s JSCG library was the best choice. It's based on the JavaScript csg.js library, which I later used in the on-line version.

With this library, cutting the object into blocks became straightforward. Each block was created by intersecting the object (the head) with a translated cube. However, generating these intersections was time-consuming (around 30 seconds for a 5x5x5 set), so I pre-generated all the configurations I wanted to use.

EASING

I aimed to avoid working with a classic timeline as much as possible. In most cases, I used my eased() function to smooth the animation.

function eased(from, to, ease) { return from + ( to - from ) * ease; }

For example, when working with position, this function calculates a point along the path to a given destination based on the progress and the speed I choose.

Click to move the object with ease: read the code

OUTLINE

To achieve a simple, clean effect, I went for an outline "vector" style. Initially, I considered using an edge detection filter, but it proved to be too crisp and not performed well. Instead, I separated the object's fill and stroke, then slightly translate the fill towards the camera, allowing it to partially overlay the strokes.

Move left-right to see more details: read the code

RESULTS

You can find the results here: