Last active
October 4, 2020 19:51
-
-
Save somaholiday/af9fc6f8eabc033dcab28b1d6fcad22c to your computer and use it in GitHub Desktop.
Processing Template for Creating Looping Animated GIFs (with many thanks to beesandbombs)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This file is slightly adapted from the template used by beesandbombs (https://gist.github.com/beesandbombs) | |
Many thanks to him for sharing his work with the rest of us! | |
*/ | |
void drawFPS() { | |
if (frameCount % 30 == 0) { | |
surface.setTitle(this.getClass().getName() + " | FPS : " + nf(frameRate, 2, 2) + " | Runtime: " + frameCount + " | t: " + nf(t, 1, 5)); | |
} | |
} | |
void drawMouseT() { | |
surface.setTitle(this.getClass().getName() + " | t(mouse) : " + nf(t, 1, 5)); | |
} | |
String getTimestamp() { | |
return year() + nf(month(), 2) + nf(day(), 2) + "-" + nf(hour(), 2) + nf(minute(), 2) + nf(second(), 2); | |
} | |
String getTimeDuration(int ms) { | |
int sec = floor(ms / 1000.); | |
int min = floor(sec / 60.); | |
sec = sec % 60; | |
return min + "m" + nf(sec, 2) + "s"; | |
} | |
void center() { | |
translate(width * 0.5, height * 0.5); | |
} | |
void uncenter() { | |
translate(-width * 0.5, -height * 0.5); | |
} | |
float mapsin(float param, float min, float max) { | |
return map(sin(param), -1, 1, min, max); | |
} | |
float mapcos(float param, float min, float max) { | |
return map(cos(param), -1, 1, min, max); | |
} | |
////////////////////////////////////////////////////////////////////////////// | |
int[][] result; | |
float t; | |
int start; | |
int nfl; // str(numFrames).length() | |
float ease(float p) { | |
return 3*p*p - 2*p*p*p; | |
} | |
float ease(float p, float g) { | |
if (p < 0.5) | |
return 0.5 * pow(2*p, g); | |
else | |
return 1 - 0.5 * pow(2*(1 - p), g); | |
} | |
float mn = .5*sqrt(3); | |
/******* | |
SETUP() | |
******/ | |
void setup() { | |
size(1000, 1000); | |
setup_(); | |
result = new int[width*height][3]; | |
if (state == State.RECORD) { | |
println("RECORDING"); | |
println("numFrames: ", numFrames); | |
println("samplesPerFrame:", samplesPerFrame); | |
println("shutterAngle: ", shutterAngle); | |
start = millis(); | |
nfl = str(numFrames).length(); | |
} | |
} | |
/****** | |
DRAW() | |
*****/ | |
void draw() { | |
switch(state) { | |
case RECORD: { | |
int frame = frameCount; | |
/////////// | |
// sampling | |
for (int i=0; i<width*height; i++) | |
for (int a=0; a<3; a++) | |
result[i][a] = 0; | |
for (int sa=0; sa<samplesPerFrame; sa++) { | |
t = map(frame-1 + sa*shutterAngle/samplesPerFrame, 0, numFrames, 0, 1); | |
draw_(); | |
loadPixels(); | |
for (int i=0; i<pixels.length; i++) { | |
result[i][0] += pixels[i] >> 16 & 0xff; | |
result[i][1] += pixels[i] >> 8 & 0xff; | |
result[i][2] += pixels[i] & 0xff; | |
} | |
} | |
loadPixels(); | |
for (int i=0; i<pixels.length; i++) | |
pixels[i] = 0xff << 24 | | |
int(result[i][0]*1.0/samplesPerFrame) << 16 | | |
int(result[i][1]*1.0/samplesPerFrame) << 8 | | |
int(result[i][2]*1.0/samplesPerFrame); | |
updatePixels(); | |
// sampling | |
/////////// | |
saveFrame("f###.png"); | |
// status report every ten frames | |
if (frameCount % 10 == 0) { | |
println("frame", nf(frame, nfl), "/", numFrames, "•", nf(frame/float(numFrames) * 100, 3, 2), "% •", getTimeDuration(millis() - start)); | |
} | |
if (frame==numFrames) { | |
println("~ completed in", getTimeDuration(millis() - start), "~"); | |
exit(); | |
} | |
break; | |
} | |
case MOUSE: { | |
t = mouseX*1.0/width; | |
draw_(); | |
drawMouseT(); | |
break; | |
} | |
case PREVIEW: | |
default: { | |
t = (millis()/(60.0*numFrames))%1; | |
draw_(); | |
drawFPS(); | |
} | |
} | |
} | |
enum State { | |
RECORD, | |
PREVIEW, | |
MOUSE | |
} | |
////////////////////////////////////////////////////////////////////////////// | |
/* DO YOUR WORK BELOW THIS LINE */ | |
////////////////////////////////////////////////////////////////////////////// | |
// the number of frames your loop should be | |
int numFrames = 120; | |
// the number of samples per frame to take for motion blur | |
int samplesPerFrame = 8; | |
// the distance between samples to be considered for motion blur | |
float shutterAngle = .6; | |
/* | |
Uncomment the State you want to run in: | |
RECORD | |
outputs the sketch into a collection of individual frame files | |
suitable for stitching together in a tool like gifsicle or ffmpeg | |
PREVIEW | |
runs the sketch like normal, looping over and over | |
MOUSE | |
allows you to scrub through the loop by moving your mouse horizontally | |
*/ | |
//State state = State.RECORD; | |
State state = State.PREVIEW; | |
//State state = State.MOUSE; | |
////////////////////////////////////////////////////////////////////////////// | |
void setup_() { | |
// do your setup here | |
// NOTE that Processing 3 enforces that you | |
// call size() ONLY in the normal setup() above | |
} | |
void draw_() { | |
// do your draw here | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment