Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
// Processing code by Etienne JACOB
// motion blur template by beesandbombs
int[][] result;
float t, c;
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);
}
void push() {
pushMatrix();
pushStyle();
}
void pop() {
popStyle();
popMatrix();
}
void draw() {
if (!recording) {
t = mouseX*1.0/width;
c = mouseY*1.0/height;
if (mousePressed)
println(c);
draw_();
} else {
for (int i=0; i<width*height; i++)
for (int a=0; a<3; a++)
result[i][a] = 0;
c = 0;
for (int sa=0; sa<samplesPerFrame; sa++) {
t = map(frameCount-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();
if (frameCount<=numFrames)
{
saveFrame("fr###.gif");
println(frameCount,"/",numFrames);
}
if (frameCount==numFrames)
stop();
}
}
// It's probably stupid to use this. I don't know Java and its equivalent of C++'s std::pair<int,int>
class IntegerPair
{
int x,y;
IntegerPair(int x_,int y_)
{
x = x_;
y = y_;
}
}
//////////////////////////////////////////////////////////////////////////////
int samplesPerFrame = 5;
int numFrames = 275;
float shutterAngle = .6;
boolean recording = true; // set to false for time with mouse position, set to true to render frames
// Hilbert curve algo from wikipedia (https://en.wikipedia.org/wiki/Hilbert_curve)
//convert d to (x,y)
IntegerPair d2xy(int n, int d) {
int rx, ry, s, t=d;
int x,y;
x = 0;
y = 0;
for (s=1; s<n; s*=2) {
rx = 1 & (t/2);
ry = 1 & (t ^ rx);
IntegerPair res = rot(s, new IntegerPair(x,y), rx, ry);
x = res.x;
y = res.y;
x += s * rx;
y += s * ry;
t /= 4;
}
return new IntegerPair(x,y);
}
//rotate/flip a quadrant appropriately
IntegerPair rot(int n, IntegerPair input, int rx, int ry) {
int x = input.x;
int y = input.y;
if (ry == 0) {
if (rx == 1) {
x = n-1 - x;
y = n-1 - y;
}
//Swap x and y
int t = x;
x = y;
y = t;
}
return new IntegerPair(x,y);
}
int N = 6;
int n = (int)pow(4,N);
class Point
{
int i;
PVector [] positions = new PVector[N]; // position of point at each level
Point(int i_)
{
i = i_;
for(int j=1;j<=N;j++)
{
int n2 = (int)pow(4,j);
float fi = map(i,0,n-1,0,n2-1)*0.999999;
IntegerPair pair1 = d2xy(n2,floor(fi));
IntegerPair pair2 = d2xy(n2,floor(fi+1));
float lp = fi - floor(fi);
PVector v1 = new PVector(pair1.x,pair1.y);
PVector v2 = new PVector(pair2.x,pair2.y);
float f = 0.77;
float x1 = map(v1.x + 0.5,0,pow(2,j),-f*width/2,f*width/2);
float y1 = map(v1.y + 0.5,0,pow(2,j),-f*height/2,f*height/2);
float x2 = map(v2.x + 0.5,0,pow(2,j),-f*width/2,f*width/2);
float y2 = map(v2.y + 0.5,0,pow(2,j),-f*height/2,f*height/2);
positions[j-1] = new PVector(lerp(x1,x2,lp),lerp(y1,y2,lp));
if(j%2==0) positions[j-1] = new PVector(positions[j-1].y,positions[j-1].x);
}
}
}
Point [] array = new Point[n];
// go from v1 to v2 with rotation arround their middle
PVector rotater(PVector v1,PVector v2,float p,boolean orientation)
{
PVector mid = v1.copy().add(v2).mult(0.5);
PVector midToV1 = v1.copy().sub(mid);
float angle = atan2(midToV1.y,midToV1.x);
float o = (orientation?-1:1);
float r = midToV1.mag();
return new PVector(mid.x+r*cos(angle+o*PI*p),mid.y+r*sin(angle+o*PI*p));
}
// https://easings.net/#easeOutElastic
float easeOutElastic(float x)
{
float c4 = (2*PI)/3;
if(x<=0) return 0;
if(x>=1) return 1;
return pow(2, -10 * x) * sin((x * 10 - 0.75) * c4) + 1;
}
void drawCurve(float p)
{
p = (p+12345-0.05)%1;
p = constrain(map(p,0,0.88,0,1),0,1);
stroke(255);
strokeWeight(1.4);
noFill();
beginShape();
for(int i=0;i<n;i++)
{
PVector deepPos = array[i].positions[N-1]; // position on last hilbert curve
float delay = 0.001*deepPos.mag()*sin(PI*p);
float pp = 1-pow(1-p,1.5);
float delayedP = (12345+pp-delay)%1;
float finishedLastCurveTime = 0.57;
float floatIndex;
if(delayedP<finishedLastCurveTime)
floatIndex = map(delayedP,0,finishedLastCurveTime,0,N-1);
else
floatIndex = map(delayedP,finishedLastCurveTime,1.0,N-1,N);
int ind1 = floor(floatIndex);
int ind2 = (ind1+1)%N;
float frac = floatIndex - ind1;
PVector v1 = array[i].positions[ind1];
PVector v2 = array[i].positions[ind2];
float easing;
if(ind1==N-1)
{
float aux = constrain(map(frac,0.25,1,0,1),0,1);
easing = easeOutElastic(pow(aux,2.2));
}
else
easing = ease(frac,2.2);
PVector v = rotater(v1,v2,easing,ind1%2==0);
vertex(v.x,v.y);
}
endShape();
}
void setup(){
size(600,600,P3D);
result = new int[width*height][3];
for(int i=0;i<n;i++)
{
array[i] = new Point(i);
}
smooth(8);
}
void draw_(){
background(0);
push();
translate(width/2,height/2);
rotate(-HALF_PI);
drawCurve(t);
pop();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment