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.
-----------------------------------------------------------
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; } |