Processing (p5js)¶
Processing is a programming system for learning how to code within the context of the visual arts. It is well-suited to rapid prototyping of interactive graphics and idiosyncratic user interfaces. The language was originally implemented using Java, but has now been adapted to JavaScript in the p5js system. Programs in this system are called ‘sketches’ and run within a normal web browser. Code may be edited locally or using an online editor. As a result, sketches are easy to host online.
Pausch Bridge p5js Example¶
The following p5js sketch was developed by Nick Diamant as a prototype for an online Pausch Bridge animation loop editor. Special thanks to Nick for contributing this code.
The sketch shown below can be tested live in your browser by following this link.
Downloads¶
The sketch and the p5js runtime can be downloaded as the zip package Pausch01.zip.
Please note that not all browsers will load the index.html file from a local drive due to security protections. (On my computer, FireFox works, Safari mostly works, but Chrome does not.) If you have trouble running it, please consult the Get Started page; you could either upload the sketch.js file into the online editor or set up a local server.
Pausch01/sketch.js code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | // Loop editor for the Pausch Bridge lighting system written using p5js
// (https://p5js.org/). This implements a 'piano roll' drawing canvas in which
// each row can be sequenced out to the 57 lighting groups of the bridge. The
// preview playback continuously loops through the image as it is drawn.
//
// Original version by Nick Diamant <ndiamant@andrew.cmu.edu>,
// downloaded from https://editor.p5js.org/dinkolas/sketches/Ai9tqWsYU
// Changes:
// 2021-03-26: garthz@cmu.edu
// added comments to the code
// added the keyPressed implementation to save the image
// -------------------------------------------------------------------------------------
let N = 300; // Number of video frames in the loop.
let w = 57; // Width of the preview display, e.g. number of lighting groups on bridge.
let row = 0; // Playhead index, current frame of loop.
let h = 0; // Current hue index for drawing brush.
function setup() {
createCanvas(windowWidth, windowHeight);
frameRate(30);
background(0);
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
background(0);
}
function keyPressed() {
// fetch the 'piano roll' portion of the canvas
pixels = get(width * 0.1, height * 0.2, width * 0.8, height * 0.7)
pixels.save('Pausch01', 'png');
}
function draw() {
// Draw a new line segment whenever the mouse button is pressed. The color
// continuously cycles through hues. Four overlapping segments are drawn with
// varying width to create a soft edge effect.
if (mouseIsPressed) {
h = (h + 1) % 100;
colorMode(HSB, 100);
blendMode(LIGHTEST);
for (let i = 0; i < 4; i++) {
strokeWeight(map(i, 0, 3, 40, 5));
stroke(h, 100, map(i, 0, 3, 10, 100));
line(mouseX, mouseY, pmouseX, pmouseY);
}
}
// Clear the margins to black all around to leave space for the playbar and preview pane.
blendMode(BLEND);
noStroke();
fill(0);
rect(0, 0, width, height * 0.2);
rect(0, 0, width * 0.1, height);
rect(width * 0.9, 0, width * 0.1, height);
rect(0, height * 0.9, width, height * 0.1);
// Draw the playhead dot moving vertically in the playbar.
let rowYCoord = map(row, 0, N - 1, height * 0.2, height * 0.9);
colorMode(RGB, 100);
noStroke();
fill(100);
ellipse(width * 0.05, rowYCoord, 10, 10);
// Read back the canvas image pixels and extract the currently playing row into an array.
let colors = [];
loadPixels();
let d = pixelDensity();
let y = floor(rowYCoord);
for (let i = 0; i < w; i++) {
let x = floor(map(i, 0, w - 1, width * 0.1, width * 0.9));
//4 * ((y * d + j) * width * d + (x * d + i));
let p = 4 * ((y * d) * width * d + (x * d));
let r = pixels[p];
let g = pixels[p + 1];
let b = pixels[p + 2];
colors.push({
r: r,
g: g,
b: b
});
}
// Redraw the preview pane at the top with rectangles representing the
// bridge lighting colors using the color data extracted from the currently playing row.
for (let i = 0; i < w; i++) {
let x = map(i, 0, w - 1, width * 0.1, width * 0.9);
let c = colors[i];
noStroke();
fill(c.r, c.g, c.b);
rect(x, height * 0.05, width * 0.8 / w, height * 0.1);
}
// Advance the playhead.
row = (row + 1) % N;
}
|