nannon-AnimatedLoop

end of semester edit:

I went back a couple times on this assignment and finally got it to be a bit closer to what I envisioned.

Final:

A few iterations:

 

-----------------------------------------------------------

I originally wanted to do something totally different (a set of eyes that opened into new eyes), but I eventually thought that it was too complicated and illustrative and decided to invest my time in doing something 3D instead. I saw this cool gif with rotating text in a cylinder in the spirit of Zach Lieberman the other day, and wanted to do something similar. Unfortunately, I decided all of the Wednesday night, and only had Thursday to do it. Having never worked in 3D before, this was really torturous, but still kind of rewarding. I'm disappointed I didn't get the final (as of now) to how I imagined it in my head, but I'm going to keep working on this. Ultimately, I want the text to actually be a coherent sentence, and have different text on the inside of the cylinder and out. A lot of time was spent figuring out Geomerative and cyinder geometry, but I did really learn a lot. I didn't have time to use p5_func, but hopefully will get around to it as I continue to flesh this guy out.

Thank you Golan  for taking the time to explain a ton mathematics.

// This is a template for creating a looping animation in Processing/Java. 
// When you press the 'F' key, this program will export a series of images
// into a "frames" directory located in its sketch folder. 
// These can then be combined into an animated gif. 
// Known to work with Processing 3.3.6
// Prof. Golan Levin, January 2018
import geomerative.*;
 
RFont f;
RShape fire;
RPoint[] points;
RShape[] letterShapes;
//===================================================
// Global variables. 
String  myNickname = "nannon"; 
int     nFramesInLoop = 120;
int     nElapsedFrames;
boolean bRecording; 
 
//===================================================
void setup() {
  size (640, 640, P3D); 
  lights();
  background(0);
  bRecording = false;
  nElapsedFrames = 0;
 
  RG.init(this);
  fire = RG.getText("x", "Optimo.ttf", 72, CENTER);
 
  RG.setPolygonizer(RG.UNIFORMLENGTH);
  RG.setPolygonizerLength(1);
  fill(255);
 
  letterShapes = fire.children;
 
 
  smooth();
}
//===================================================
void keyPressed() {
  if ((key == 'f') || (key == 'F')) {
    bRecording = true;
    nElapsedFrames = 0;
  }
}
 
//===================================================
void draw() {
 
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)nFramesInLoop;
  } else {
    percentCompleteFraction = (float) (frameCount % nFramesInLoop) / (float)nFramesInLoop;
  }
 
  // Render the design, based on that percentage. 
  renderMyDesign (percentCompleteFraction);
 
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    saveFrame("frames/" + myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames >= nFramesInLoop) {
      bRecording = false;
    }
  }
}
 
//===================================================
void renderMyDesign (float percent) {
  //
  background(0);
  translate(320, 320, 200);
  rotateX(PI);
  rotateY(map(percent,0,1,0,PI/2));
  rotateZ(sin(PI));
  stroke(255);
  noFill(); 
 
 
  int r= 100;
  int nSlices = 50;
  int zA = -20;
  int zB = 20;
 
 
 
 
 
  rotateY(PI/2);
  rotateX(PI/2);
  noFill();
 
  // draw a cylinder
  noFill(); 
  stroke(255); 
  beginShape(TRIANGLE_STRIP);
  for (int i=0; i<=nSlices; i++) {
    float theta = map(i, 0, nSlices, 0, 2*PI);
    float pX = r*cos(theta);
    float pY = r*sin(theta);
    vertex(pX, pY, zA);
    vertex(pX, pY, zB);
  }
  endShape();
 
  // print("x1:"+points[0].x+" "+"y:"+ points[0].y+"    ");
  // print("x2:"+points[points.length-1].x+" "+"y:"+ points[points.length-1].y+"    ");
 
 
 
   //beginShape();
   //for (int i=0; i<points.length; i++) {
   //  float newX = map(points[i].x, -187, 189, 0, 0.6*(2*PI));
   //  float newZ = map(points[i].y, -24, 0, 0, 0.6*(2*PI));
   //  vertex(r*cos(newX), points[i].y, abs(r*cos(newZ)));
 
   //  endShape();
   //}
 
 
 
  noFill(); 
  stroke(255); 
  //int nLetters = 16; 
  //for (int i=0; i<nLetters; i++) {
 
 
 
 
    //int nPointsInThisContour = 16;
    for (int k=0; k<10; k++) {
      pushMatrix();
      float letterTheta = k* radians(45.0);
 
 
      float letterX = r * cos(letterTheta);
      float letterY = r * sin(letterTheta); 
 
 
      //float eased = function_DoubleExponentialSigmoid(percent, 0.7);
      //float newletterY = map(eased, 0,1,0,PI);
 
      translate(letterX, letterY);
      rotateX( radians(90)); 
      rotateY(letterTheta+ radians(90));
 
      fill(255);
      stroke(255);
      beginShape();
      RPoint[] points = letterShapes[0].getPoints();
      for (int j=0; j<points.length; j++) {
 
        //print(points[j].x);
        //float ht = map(j, 0, nPointsInThisContour, 0, TWO_PI); 
        float hpx = points[j].x; 
        float hpy =  points[j].y; 
        float hpz =0;
 
 
        vertex(hpx, hpy, hpz);
 
        //ellipse(hpx,hpy,10,10);
      }
      endShape();
      popMatrix();
    }
 
}
float function_DoubleExponentialSigmoid (float x, float a) {
  // functionName = "Double-Exponential Sigmoid";
 
  float min_param_a = 0.0 + EPSILON;
  float max_param_a = 1.0 - EPSILON;
  a = constrain(a, min_param_a, max_param_a); 
  a = 1-a;
 
  float y = 0;
  if (x<=0.5) {
    y = (pow(2.0*x, 1.0/a))/2.0;
  } else {
    y = 1.0 - (pow(2.0*(1.0-x), 1.0/a))/2.0;
  }
  return y;
}