Tools.
Processing, Illustrator, After Effects
Concept.
Nancy Wu, Lily Kim, Tina Huamin, and Kai Watanabe collaborated to create a drawing software code in Processing then drew frame by frame to create this rotoscope.
Code created for this drawing software in Processing:
//import codeanticode.tablet.*;
//Tablet tablet;
int sw = 5;
float x;
float y;
float m;
float n;
int i=0;
int a=0;
float opa = 255;
float speed;
PImage selector;
PImage swopa;
int sx = 1240;
int sy = 6;
color scolor;
//Tablet tablet;
int sw = 5;
float x;
float y;
float m;
float n;
int i=0;
int a=0;
float opa = 255;
float speed;
PImage selector;
PImage swopa;
int sx = 1240;
int sy = 6;
color scolor;
String videoPrefix = "footage-";
int totalFrames = 167;
PImage videoFrame;
String drawingPrefix = "animation-";
PImage drawing;
PImage drawing;
int currentFrame = 0;
boolean toggledraw=true;
boolean showVideo = true;
boolean line = true;
boolean dots = false;
boolean scratch = false;
boolean multiline = false;
boolean bubble = false;
boolean showInterface = true;
boolean overlay =false;
boolean speedbrush;
boolean toggledraw=true;
boolean showVideo = true;
boolean line = true;
boolean dots = false;
boolean scratch = false;
boolean multiline = false;
boolean bubble = false;
boolean showInterface = true;
boolean overlay =false;
boolean speedbrush;
PGraphics d; // Drawing layer
//pGraphics d1; //overlay layer
void setup() {
size(1280, 720);
//tablet = new Tablet(this);
size(1280, 720);
//tablet = new Tablet(this);
d = createGraphics(width, height);
//d1 = createGraphics(width, height);
loadFrame();
loadDrawing();
selector = loadImage("colors.png");
swopa = loadImage("swopa.png");
scolor = color(0, 0, 0);
}
//d1 = createGraphics(width, height);
loadFrame();
loadDrawing();
selector = loadImage("colors.png");
swopa = loadImage("swopa.png");
scolor = color(0, 0, 0);
}
void draw() {
background(153);
sw=5+a*2;
opa=255+25.5*(-i);
x = random(-10, 10);
y =random (-20, 20);
m= random (1, 3);
n= random (1, 2);
background(153);
sw=5+a*2;
opa=255+25.5*(-i);
x = random(-10, 10);
y =random (-20, 20);
m= random (1, 3);
n= random (1, 2);
if (showVideo) {
image(videoFrame, 0, 0, width, height);
}
if (overlay) {
d.blendMode(ADD);
} else {
d.blendMode(BLEND);
}
if (toggledraw) {
if (mousePressed) {
image(videoFrame, 0, 0, width, height);
}
if (overlay) {
d.blendMode(ADD);
} else {
d.blendMode(BLEND);
}
if (toggledraw) {
if (mousePressed) {
if (line) {
d.beginDraw();
//d.strokeWeight(30 * tablet.getPressure());
d.strokeWeight(sw);
d.stroke(scolor, opa);
d.line(mouseX, mouseY, pmouseX, pmouseY);
d.endDraw();
}
if (dots) {
d.beginDraw();
d.noStroke();
d.fill(scolor, opa);
float rx1 = random(-3*sw, 3*sw);
float ry1 = random(-3*sw, 3*sw);
float rx2 = random(-5*sw, 5*sw);
float ry2 = random(-5*sw, 5*sw);
d.ellipse(mouseX+rx1, mouseY+ry1, sw, sw);
d.ellipse(mouseX+rx2, mouseY+ry2, sw/1.5, sw/1.5);
d.endDraw();
}
if (scratch) {
d.beginDraw();
d.stroke(scolor, opa);
d.beginDraw();
//d.strokeWeight(30 * tablet.getPressure());
d.strokeWeight(sw);
d.stroke(scolor, opa);
d.line(mouseX, mouseY, pmouseX, pmouseY);
d.endDraw();
}
if (dots) {
d.beginDraw();
d.noStroke();
d.fill(scolor, opa);
float rx1 = random(-3*sw, 3*sw);
float ry1 = random(-3*sw, 3*sw);
float rx2 = random(-5*sw, 5*sw);
float ry2 = random(-5*sw, 5*sw);
d.ellipse(mouseX+rx1, mouseY+ry1, sw, sw);
d.ellipse(mouseX+rx2, mouseY+ry2, sw/1.5, sw/1.5);
d.endDraw();
}
if (scratch) {
d.beginDraw();
d.stroke(scolor, opa);
d.strokeWeight(sw);
d.line(mouseX+m*x, mouseY+n*y, mouseX-y, mouseY-x);
d.line(mouseX-n*x, mouseY+m*y, mouseX+y, mouseY-x);
d.line(mouseX-m*y, mouseY+n*x, mouseX+x, mouseY-y);
d.line(mouseX+n*y, mouseY+m*x, mouseX-x, mouseY-y);
d.line(mouseX+m*x, mouseY+n*y, mouseX-y, mouseY-x);
d.line(mouseX-n*x, mouseY+m*y, mouseX+y, mouseY-x);
d.line(mouseX-m*y, mouseY+n*x, mouseX+x, mouseY-y);
d.line(mouseX+n*y, mouseY+m*x, mouseX-x, mouseY-y);
d.endDraw();
}
if (multiline) {
d.beginDraw();
//d.strokeWeight(30 * tablet.getPressure());
d.strokeWeight(sw);
d.stroke(scolor, opa);
d.line(mouseX, mouseY, pmouseX, pmouseY);
d.line(mouseX+5, mouseY+10, pmouseX+5, pmouseY+10);
d.line(mouseX-5, mouseY-10, pmouseX-5, pmouseY-10);
d.line(mouseX-2.5, mouseY-5, pmouseX-2.5, pmouseY-5);
d.line(mouseX+2.5, mouseY+5, pmouseX+2.5, pmouseY+5);
d.endDraw();
}
if (bubble) {
d.beginDraw();
d.stroke(scolor, opa);
d.strokeWeight(1);
d.noFill();
float rx1 = random(-3*sw, 3*sw);
float ry1 = random(-3*sw, 3*sw);
float rx2 = random(-5*sw, 5*sw);
float ry2 = random(-5*sw, 5*sw);
d.ellipse(mouseX+rx1, mouseY+ry1, sw, sw);
d.ellipse(mouseX+rx2, mouseY+ry2, sw/1.5, sw/1.5);
d.endDraw();
}
if (speedbrush) {
d.beginDraw();
d.noFill();
float mouseSpeed= abs(mouseX-pmouseX)+abs(mouseY-pmouseY);
d.stroke(scolor, opa);
float targetSpeed = mouseSpeed* sw * 0.1;
float easing = 0.1;
speed += (targetSpeed - speed) * easing;
d.strokeWeight(speed);
d.line(pmouseX, pmouseY, mouseX, mouseY);
d.endDraw();
}
}
}
d.line(mouseX+m*x, mouseY+n*y, mouseX-y, mouseY-x);
d.line(mouseX-n*x, mouseY+m*y, mouseX+y, mouseY-x);
d.line(mouseX-m*y, mouseY+n*x, mouseX+x, mouseY-y);
d.line(mouseX+n*y, mouseY+m*x, mouseX-x, mouseY-y);
d.line(mouseX+m*x, mouseY+n*y, mouseX-y, mouseY-x);
d.line(mouseX-n*x, mouseY+m*y, mouseX+y, mouseY-x);
d.line(mouseX-m*y, mouseY+n*x, mouseX+x, mouseY-y);
d.line(mouseX+n*y, mouseY+m*x, mouseX-x, mouseY-y);
d.endDraw();
}
if (multiline) {
d.beginDraw();
//d.strokeWeight(30 * tablet.getPressure());
d.strokeWeight(sw);
d.stroke(scolor, opa);
d.line(mouseX, mouseY, pmouseX, pmouseY);
d.line(mouseX+5, mouseY+10, pmouseX+5, pmouseY+10);
d.line(mouseX-5, mouseY-10, pmouseX-5, pmouseY-10);
d.line(mouseX-2.5, mouseY-5, pmouseX-2.5, pmouseY-5);
d.line(mouseX+2.5, mouseY+5, pmouseX+2.5, pmouseY+5);
d.endDraw();
}
if (bubble) {
d.beginDraw();
d.stroke(scolor, opa);
d.strokeWeight(1);
d.noFill();
float rx1 = random(-3*sw, 3*sw);
float ry1 = random(-3*sw, 3*sw);
float rx2 = random(-5*sw, 5*sw);
float ry2 = random(-5*sw, 5*sw);
d.ellipse(mouseX+rx1, mouseY+ry1, sw, sw);
d.ellipse(mouseX+rx2, mouseY+ry2, sw/1.5, sw/1.5);
d.endDraw();
}
if (speedbrush) {
d.beginDraw();
d.noFill();
float mouseSpeed= abs(mouseX-pmouseX)+abs(mouseY-pmouseY);
d.stroke(scolor, opa);
float targetSpeed = mouseSpeed* sw * 0.1;
float easing = 0.1;
speed += (targetSpeed - speed) * easing;
d.strokeWeight(speed);
d.line(pmouseX, pmouseY, mouseX, mouseY);
d.endDraw();
}
}
}
image(d, 0, 0, width, height);
//println(sw);
if (showInterface) {
push();
textSize(12);
//text("Strokeweight",20,70);
//text("Opacity",20,40);
fill(255, 100);
noStroke();
rect(5, 15, 160, 70, 10);
fill(0);
text(opa/2.55, 105, 40);
text(sw, 110, 70);
image(swopa, 0, 0);
image(selector, sx, sy);
pop();
}
}
void keyPressed() {
if (key == ' ' ) {
showVideo = !showVideo;
}
if (key=='1') {
line=true;
dots=false;
scratch =false;
multiline = false;
bubble = false;
speedbrush = false;
//checkBrushes();
}
if (key=='2') {
dots=true;
line=false;
scratch =false;
multiline = false;
bubble = false;
speedbrush = false;
//checkBrushes();
}
if (key=='3') {
scratch =true;
dots=false;
line=false;
multiline = false;
bubble = false;
speedbrush = false;
//checkBrushes();
}
if (key=='4') {
multiline = true;
scratch =false;
dots=false;
line=false;
bubble = false;
speedbrush = false;
}
if (key=='5') {
bubble = true;
multiline = false;
scratch =false;
dots=false;
line=false;
speedbrush = false;
}
if (key=='6') {
speedbrush = true;
bubble = false;
multiline = false;
scratch =false;
dots=false;
line=false;
}
if (key=='o' || key == 'O') {
overlay=!overlay;
}
// if (key=='n'){
if (key == ' ' ) {
showVideo = !showVideo;
}
if (key=='1') {
line=true;
dots=false;
scratch =false;
multiline = false;
bubble = false;
speedbrush = false;
//checkBrushes();
}
if (key=='2') {
dots=true;
line=false;
scratch =false;
multiline = false;
bubble = false;
speedbrush = false;
//checkBrushes();
}
if (key=='3') {
scratch =true;
dots=false;
line=false;
multiline = false;
bubble = false;
speedbrush = false;
//checkBrushes();
}
if (key=='4') {
multiline = true;
scratch =false;
dots=false;
line=false;
bubble = false;
speedbrush = false;
}
if (key=='5') {
bubble = true;
multiline = false;
scratch =false;
dots=false;
line=false;
speedbrush = false;
}
if (key=='6') {
speedbrush = true;
bubble = false;
multiline = false;
scratch =false;
dots=false;
line=false;
}
if (key=='o' || key == 'O') {
overlay=!overlay;
}
// if (key=='n'){
//}
if (key == 'z' ) {
d.beginDraw();
d.clear();
d.endDraw();
}
if (key == 's') {
showInterface =!showInterface;
}
if (key == ']') {
a++;
a++;
//sw=5+a*2;
}
if (key == '[') {
//sw=5+a*2;
if (sw==1) {
sw=1;
} else {
a--;
}
}
}
if (key == '[') {
//sw=5+a*2;
if (sw==1) {
sw=1;
} else {
a--;
}
}
if (key=='t') {
if (toggledraw==true) {
toggledraw=false;
} else {
toggledraw=true;
}
}
if (toggledraw==true) {
toggledraw=false;
} else {
toggledraw=true;
}
}
if (key == CODED) {
if (keyCode == LEFT) { // Left arrow key
saveAnimationFrame();
currentFrame--;
if (currentFrame < 0) {
currentFrame = totalFrames - 1;
}
loadFrame();
loadDrawing();
} else if (keyCode == RIGHT) { // Right arrow key
saveAnimationFrame();
currentFrame++;
if (currentFrame >= totalFrames) {
currentFrame = 0;
}
loadFrame();
loadDrawing();
}
if (keyCode == UP) {
if (i==0) {
i=0;
} else {
i--;
}
} else if (keyCode == DOWN) {
if (i==9) {
i=9;
} else {
i++;
}
}
}
}
if (keyCode == LEFT) { // Left arrow key
saveAnimationFrame();
currentFrame--;
if (currentFrame < 0) {
currentFrame = totalFrames - 1;
}
loadFrame();
loadDrawing();
} else if (keyCode == RIGHT) { // Right arrow key
saveAnimationFrame();
currentFrame++;
if (currentFrame >= totalFrames) {
currentFrame = 0;
}
loadFrame();
loadDrawing();
}
if (keyCode == UP) {
if (i==0) {
i=0;
} else {
i--;
}
} else if (keyCode == DOWN) {
if (i==9) {
i=9;
} else {
i++;
}
}
}
}
void mousePressed() {
if (overSelector()) {
toggledraw=false;
scolor = selector.get(mouseX-sx, mouseY-sy);
} else {
toggledraw=true;
}
}
if (overSelector()) {
toggledraw=false;
scolor = selector.get(mouseX-sx, mouseY-sy);
} else {
toggledraw=true;
}
}
//void checkBrushes(){
// if(line==true){
// dots=false;
// }
// else if(dots==true){
// line=false;
// }
//}
void saveAnimationFrame() {
d.save("frames/" + drawingPrefix + nf(currentFrame, 4) + ".png");
// Clear the drawing layer
d.beginDraw();
d.clear();
d.endDraw();
}
// if(line==true){
// dots=false;
// }
// else if(dots==true){
// line=false;
// }
//}
void saveAnimationFrame() {
d.save("frames/" + drawingPrefix + nf(currentFrame, 4) + ".png");
// Clear the drawing layer
d.beginDraw();
d.clear();
d.endDraw();
}
void loadFrame() {
String filename = videoPrefix + nf(currentFrame, 4) + ".png";
videoFrame = loadImage(filename);
println(currentFrame + " / " + (totalFrames-1));
}
String filename = videoPrefix + nf(currentFrame, 4) + ".png";
videoFrame = loadImage(filename);
println(currentFrame + " / " + (totalFrames-1));
}
void loadDrawing() {
try {
String filename = drawingPrefix + nf(currentFrame, 4) + ".png";
drawing = loadImage("frames/" + filename);
d.beginDraw();
d.image(drawing, 0, 0, width, height);
d.endDraw();
}
catch (Exception e) {
println("Computer says 'No!' " + e);
}
}
try {
String filename = drawingPrefix + nf(currentFrame, 4) + ".png";
drawing = loadImage("frames/" + filename);
d.beginDraw();
d.image(drawing, 0, 0, width, height);
d.endDraw();
}
catch (Exception e) {
println("Computer says 'No!' " + e);
}
}
boolean overSelector() {
if (mouseX > sx && mouseX < sx+selector.width &&
mouseY > sy && mouseY < sy+selector.height) {
return true;
} else {
return false;
}
}
if (mouseX > sx && mouseX < sx+selector.width &&
mouseY > sy && mouseY < sy+selector.height) {
return true;
} else {
return false;
}
}