aahdee-AnimatedLoop
Below are my sketches for my animated loop.
My first idea was to have all faces of the cube expand and reveal an inner sphere, rotate around the sphere, and then close together. Below is my final result.
I had trouble implementing the camera in Processing, so I opted to have the top and bottom of the cube rotate instead. I also changed the speed of the sphere so that it grows when it is revealed. For the cube, I used Penner Ease In Quartic when all of the faces are together and Double Odd Polynomial Ogee when it seperates. I chose these because I wanted the cube to look like it was exploding when it expanded. For the sphere, I also used Double Odd Polynomial Ogee. I wanted the sphere to expand at the same rate so it was appropriate.
I felt like i succeeded in making my gif loop seamlessly, but I feel like it looks a bit boring. I wish I spent more time on making it aesthetically complex instead of functionally complex. I spent so much time making the transition from one cube to six planes seamless that I didn’t have the time to focus on anything else.
Below is my code.
float cDisplace = 0; float maxCDisplace = 50; float fDisplace = 0; float maxFDisplace = 140; float sDisplace = 0; float maxSDisplace = 90; boolean phase1 = true; boolean phase2 = false; boolean phase3 = false; boolean phase4 = false; float cPercent = 0; float fPercent = 0; float sPercent = 0; String myNickname = "aahdee"; int nFramesInLoop = 286; int nElapsedFrames; boolean bRecording; boolean firstRecord = true; void setup() { size(600,600, P3D); background(0); smooth(); bRecording = false; nElapsedFrames = 0; } //from Golan's pattern master functions float function_PennerEaseInQuartic (float t) { return t*t*t*t; } float function_DoubleOddPolynomialOgee (float x, float a, float b, int n) { float min_param_a = 0.0 + EPSILON; float max_param_a = 1.0 - EPSILON; float min_param_b = 0.0; float max_param_b = 1.0; a = constrain(a, min_param_a, max_param_a); b = constrain(b, min_param_b, max_param_b); int p = 2*n + 1; float y = 0; if (x <= a) { y = b - b*pow(1-x/a, p); } else { y = b + (1-b)*pow((x-a)/(1-a), p); } return y; } //phase 1 and 4 void cubeExpand(float percent) { stroke(163, 221, 173); pushMatrix(); translate(300, 300, 0); rotateX(radians(-15)); rotateY(radians(45)); fill(117, 198, 131); box(125*percent); if (percent >= 1) {phase2 = true; phase1 = false;} popMatrix(); } void top(float percent) { stroke(163, 221, 173); pushMatrix(); fill(117, 198, 131); translate(300, 238, 0); rotateX(radians(-15)); rotateY(radians(45+(maxFDisplace*percent))); translate(0, -(maxFDisplace*percent),0); box(125, 0, 125); popMatrix(); } void bottom(float percent) { stroke(163, 221, 173); pushMatrix(); fill(117, 198, 131); translate(300, 361, -14); rotateX(radians(-15)); rotateY(radians(45+(maxFDisplace*percent))); translate(0, maxFDisplace*percent, 0); box(125, 0, 125); popMatrix(); } void frontL(float percent) { stroke(163, 221, 173); pushMatrix(); fill(117, 198, 131); translate(255, 312, 41); rotateX(radians(-15)); rotateY(radians(45)); translate (-(maxFDisplace*percent), 0, -(maxFDisplace*percent)); box(0, 125, 125); popMatrix(); } void frontR(float percent) { stroke(163, 221, 173); pushMatrix(); fill(117, 198, 131); translate(344, 312, 41); rotateX(radians(-15)); rotateY(radians(45)); translate (maxFDisplace*percent, 0, maxFDisplace*percent); box(125, 125, 0); popMatrix(); } void backL(float percent) { stroke(163, 221, 173); pushMatrix(); fill(117, 198, 131); translate(255, 289, -48); rotateX(radians(-15)); rotateY(radians(45)); translate(-(maxFDisplace*percent), 0, -(maxFDisplace*percent)); box(125, 125, 0); popMatrix(); } void backR(float percent) { stroke(163, 221, 173); pushMatrix(); fill(117, 198, 131); translate(344, 289, -48); rotateX(radians(-15)); rotateY(radians(45)); translate (maxFDisplace*percent, 0,maxFDisplace*percent); box(0, 125, 125); popMatrix(); } void cSphere(float percent) { fill(212, 125, 169); noStroke(); pushMatrix(); translate(width/2, height/2, 0); scale(1+percent, 1+percent,1+percent); sphere(56); popMatrix(); } //phase 2 and 3 void faces(float percent, float cPercent) { backL(percent); backR(percent); bottom(percent); cSphere(cPercent); top(percent); frontR(percent); frontL(percent); if (fDisplace == maxFDisplace && sDisplace == maxSDisplace) { phase2 = false; phase3 = true; } } void draw() { background(0); lights(); if(phase1) { //uncomment this line to record //if(firstRecord){bRecording = true;} background(0); cPercent = function_PennerEaseInQuartic (map(cDisplace, 0, maxCDisplace, 0.4, 1)); cubeExpand(cPercent); cDisplace ++; if(cDisplace >= maxCDisplace) {cDisplace = maxCDisplace;} } if (phase2) { fPercent = function_DoubleOddPolynomialOgee(map(fDisplace, 0, maxFDisplace, 0, 1),0.423,1,3); sPercent = function_DoubleOddPolynomialOgee(map(sDisplace, 0, maxSDisplace, 0, 1),0.423,1,3); faces(fPercent, sPercent); fDisplace += 1.5; sDisplace += 1.5; if (fDisplace >= maxFDisplace-70) {fDisplace = maxFDisplace;} if (sDisplace >= maxSDisplace-70) {sDisplace = maxSDisplace;} } if (phase3) { fPercent = function_DoubleOddPolynomialOgee(map(fDisplace, 0, maxFDisplace, 0, .24),0.24,1,3); sPercent = function_DoubleOddPolynomialOgee(map(sDisplace, 0, maxSDisplace, 0, 1),0.423,1,3); faces(fPercent, sPercent); if (fDisplace != 0) {fDisplace --;} if (sDisplace != 0) {sDisplace --;} if (fDisplace == 0 && sDisplace == 0) { phase3 = false; phase4 = true; } } if (phase4) { phase1 = phase2 = phase3 = false; background(0); cPercent = function_PennerEaseInQuartic(map(cDisplace, 0, maxCDisplace, 0.4, 1)); cubeExpand(cPercent); cDisplace --; if (cDisplace == 0) { phase4 = false; phase1 = true; int count = frameCount; println(count); } } //from Golan's template if (bRecording) { saveFrame("frames/" + myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png"); nElapsedFrames++; if (nElapsedFrames >= nFramesInLoop) { bRecording = false; firstRecord = false; } } } |