[discussion] main elements are to produce something like this (included code & image)

edited January 2015 in How To...

So this isn't my code, but I'm very interested in creating imagery like this.

Note, there should be an abstraction from this exact piece to pieces of this nature, I'm sure that people on here are familiar with this type of thing as it's not uncommon. I would say that it's generally filed under 'geometrical gifs'.

So the obvious things to learn would be geometry and code... I'm currently self learning code and maths, my maths isn't great. As I'm self learning I'm able to focus on certain areas and tasks more than a course though, so perhaps there are some suggestions as to how one would build towards this kind of imagery. I don't comprehend the level of math that is involved with this - it could be pretty basic or quite tricky, neither do I understand whether the weight lies in the geometry of this piece or its coding.

So any suggested learning paths to this kind of thing would be interesting to hear, sorry if this seems like a daft question

Here is a link to the image

here is the code (and here is his twitter page ):

    int[][] result;
    float t;

    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);

    void setup() {
      setup_();
      result = new int[width*height][3];
    }

    void draw() {

      if (!recording) {
        t = mouseX*1.0/width;
        draw_();
      } else {
        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(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();

        saveFrame("f###.gif");
        if (frameCount==numFrames)
          exit();
      }
    }

    //////////////////////////////////////////////////////////////////////////////

    int samplesPerFrame = 16;
    int numFrames = 120;        
    float shutterAngle = .6;

    boolean recording = false;

    void setup_() {
      size(500, 500, P3D);
      smooth(8);
      rectMode(CENTER);
      stroke(255);
      strokeWeight(3);
      noFill();
    }

    float x, y, z, tt;
    int N = 720;
    float r = 180;
    float th, ph;
    float ii;

    void draw_() {
      background(0); 
      pushMatrix();
      translate(width/2, height/2);
      rotateY(PI*.75);
      beginShape();
      for (int i=0; i<N; i++) {
        ii = i-N+2*N*t;
        th = map(ii, 0, N, -HALF_PI, HALF_PI);
        z = r*sin(th);
        ph = 24*th + 2*TWO_PI*t;
        x = r*cos(th)*cos(ph);
        y = r*cos(th)*sin(ph);
        strokeWeight(map(cos(TWO_PI*i/N),1,-1,0,4));
        if (0<ii & ii<N)
          vertex(x, y, z);
      }
      endShape();
      popMatrix();
    }

Answers

  • This type of question is a bit hard to answer, because there isn't just one single path. That's part of what makes programming so fun- you have to carve out your own style based on what makes sense to you.

    I suggest you start much smaller. If your end goal is to create a looping animation, can you do the simplest version of that? Get a ball bouncing back and forth. Now make it move in a circle. Now make it move in a figure eight. Work your way up by making small incremental changes.

    Sure, math, geometry, trigonometry, etc. are all going to come in handy for stuff like this. But even a math expert can't come in and create these types of animations- you need experience for that. And the best way to get experience is to just start with something small and work your way up.

  • i'd say to start with everything you need for a still image, the geometry.

    the animation is then either tweaking the parameters from frame to frame or, as in the above, partially drawing the object.

    (that said, good animation is an art. you'll notice the ease() method code in that example - that's what gives it that pleasing smoothness)

    (and THAT said, geometry can be pleasing on its own, even without animation. who doesn't like a good dodecahedron?)

  • I think koogs just proved my point, that there is no one correct way to approach the problem.

    I said that you should ignore the geometry and start with the animation. Koogs said you should ignore the animation and start with the geometry.

    Neither one of us is wrong. Neither one of us is right. But what you should do really depends on YOU, what you're familiar with, how stuff fits into your brain, etc. Nobody can tell you what will work for you. The best we can do is tell you what worked for us.

  • Yep to both. I know it's a hard question to answer and probably one that can't be answered in the sense of 2 + 2 = ? , which Is why I labeled it discussion. I can do some basics, shape , colour and what not. I'm working my way through the Learn Processing book at the moment, I self taught myself music production to a high standard years back so I like to think I have an appreciation for learning that would transpose to this.

    Can you make sense of this code? To me it's a jumble.

    Re what to do, I was thinking that some physics might be interesting for this type of thing as well, ho hum...

    Cheers though, I know there's no 'answer' here just a general post really :)

  • @koogs -> any simple way of explaining the ease float and why it makes things smoother? And why it would be chosen over smooth()

    thanks

    NOTE -> I'm not getting emails for posts in this forum, I'm not too sure why though? I've changed the settings to these (image link)

  • the easing is to do with the movement, not the image.

    things don't just start and immediately reach their final speed - they accelerate at the beginning, decelerate at the end. the easing makes it look more natural.

  • that code is a bit odd looking, especially the setup_ and draw_ methods, which i think are related to the saving of the animation.

    the draw_ method is the thing that is actually drawing the shape. you can probably take everything below the separator line, rename setup_ and draw_ and run that itself, see what it does...

  • yeah I tried that it wouldn't work for me though (just copying beneath the separator)

  • The code works perfectly, you just have to move your mouse slowly from the very left to the very right to see the entire animation.

  • edited January 2015

    this is the entire sketch without recording, just mouse function

    // move mouse over it 
    
    float t;
    
    
    float x, y, z;
    int N = 720;
    float r = 180;
    float th, ph;
    float ii;
    
    // -------------------------------------------
    
    void setup() {
      size(500, 500, OPENGL);
      // smooth(8);
      // rectMode(CENTER);
      stroke(255);
      strokeWeight(3);
      noFill();
    }
    
    void draw() {
      background(0);
      t = mouseX*1.0/width;
      pushMatrix();
      translate(width/2, height/2);
      rotateY(PI*.75);
      beginShape();
      for (int i=0; i<N; i++) {
        ii = i-N+2*N*t;
        th = map(ii, 0, N, -HALF_PI, HALF_PI);
        z = r*sin(th);
        ph = 24*th + 2*TWO_PI*t;
        x = r*cos(th)*cos(ph);
        y = r*cos(th)*sin(ph);
        strokeWeight(map(cos(TWO_PI*i/N), 1, -1, 0, 4));
        if (0<ii & ii<N)
          vertex(x, y, z);
      } // for 
      endShape();
      popMatrix();
    } // draw() 
    // -------------------------------------
    
  • this is a simple ellipse in 2D (NB, the other sketch is in 3D... it's pretty awesome actually...)

    but this is 2D:

    float x, y;
    int N = 730;
    float r = 0;
    
    float a1, b1, i;
    
    // -------------------------------------------
    
    void setup() {
      size(500, 500);
      smooth(8);
      // rectMode(CENTER);
      stroke(255);
      strokeWeight(1);
      noFill();
      noLoop();
    }
    
    void draw() {
    
      for (int i2=0; i2<N; i2++) {
    
        r = map (i, 0, N, 1, 1100);
    
        x = r*cos(i) + width/2;
        y = r*sin(i) + height/2;
    
        if (a1!=0)
          line (x, y, a1, b1);
    
        // point (x, y);
    
        // store these point 
        a1=x;
        b1=y;
    
        i+=0.1;
        //
      } // for
      //
    } // draw() 
    // -----------------------------------
    
  • hey Chrisir (I'm still not getting notifications :( )

    yeah moving my mouse across the whole code worked, but just copying the bottom half didn't... I'm not sure how the animation was exported (he obviously didn't record a perfectly smooth take of the mouse). Though this is getting a bit outside the scope of the post, as it was more relating to knowledge foundation recommended for this manner of work. (I know that's a bit vague though!)

    cheers :)

  • edited January 2015

    I don't get notifications either

  • edited January 2015

    just copying the bottom half didn't (work)

    No, 2nd half alone won't, because bottom half is

    • setup_ and not setup and

    • draw() and not draw

    But: where I wrote

    this is the entire sketch without recording, just mouse function

    It is essentially a stripped down version of the 2nd half of the sketch.

    recording

    the recording is decided by the var recording. When you write false in the code, it reacts on mouse, write true in it and it records. It's line 63 and then line 24.

    draw() has 2 main parts depending on the boolean var recording: first when you don't record it's mouse input:

    if (!recording) {
        t = mouseX*1.0/width;
        draw_();
      } else {
    

    here mouse is read, then draw_() in the 2nd half takes over.

    When recording is true, the 2nd half of draw() [without the underscore _ ] kicks in.

    } else {
        for (int i=0; i<width*height; i++)
    

    It also calls draw_() with underscore _ but instead of reading mouse, the t-value (which stand in maths and physics for time and is just the time that has run from the beginning of an experiment or interval like here) is derived from for-loop with the var sa.

    he obviously didn't record a perfectly smooth take of the mouse

    As I said, he is not recording the mouse in the 1st place; he is replacing the mouse-X value by getting t from for-loop sa (see line 32 and 33). To make it more smooth you probably you have to increase how many frames he is using for the movie, making it very big....

    So he decided to make the movie smaller (and less smooth) with these consts:

    int samplesPerFrame = 16;
    int numFrames = 120;       
    float shutterAngle = .6;
    

    So draw_() with underscore _ is the core of the program and of the graphic.

    ;-)

  • edited January 2015 Answer ✓

    I made some comments

    just change values like for N or for r to find out what they do.

    Or enter a fixed value (line 39) instead of using the mouse

    // enter value OR move mouse over it 
    
    float t;  // this is time or just how many steps since start.
    // in our case it is calculated from the mouse-X position. 
    // we can also calculated it from a fixed number like 300.
    // see line 38 / 39. 
    
    float x, y, z;   // coords in space: x and y and z. Represents our result we show with vertex. Line 57. 
    
    
    
    int N = 720;  // 720 makes the circle soft, 42 circle is with hard edges 
    
    
    
    float r = 180; // maximal radius; 180 is good, 80 is pretty small. 
    float th, ph;  // two angles: theta and phi. They are often used for angles in a circle. http:  //en.wikipedia.org/wiki/Theta#Lower_case   
    // all angles are in radians. There are 360 degrees in a circle and 2*PI radians in a circle. 
    float ii;      // we use this ii as a 2nd i  
    
    // -------------------------------------------
    
    void setup() {
    
      size(500, 500, OPENGL);  // 3D space 
    
      // smooth(8);
      rectMode(CENTER);
      stroke(255);
      strokeWeight(3);        // quite thick stroke 
      noFill();
    }
    
    void draw() {
      background(0);  // clear canvas 
      // t is derived from how far we are from left border (it goes from 0 (for 0) to 1 (for width))
    
      // t = mouseX*1.0/width;
      t = 300 * 1.0/width;        
      println (t);
    
      // pushMatrix();
      translate(width/2, height/2);  // move all to the middle, so we can work around 0 later 
      // rotateY(PI*.75);     // rotate it, we want to see it from the side 
      rotateY(frameCount*.01);  // rotate it, we want to see it from all the sides 
    
      beginShape();  
      for (int i=0; i<N; i++) {      // loop: how many steps per image - for N see above 
        ii = i-N+2*N*t;  // we derive a ii from N,i and t
        th = map(ii, 0, N, -HALF_PI, HALF_PI);   // we get theta, for map see reference 
        z = r*sin(th);   // we get a Z value 
        ph = 24*th + 2*TWO_PI*t;  // and phi 
        x = r*cos(th)*cos(ph);  // now x
        y = r*cos(th)*sin(ph);  // and y 
        strokeWeight(map(cos(TWO_PI*i/N), 1, -1, 0, 4));
        if (0<ii & ii<N)
          vertex(x, y, z);
      } // for 
      endShape();
      // popMatrix();
    } // draw() 
    // ----------------------------------
    
  • oh right, I changed the settings and it said about email notifications and what not. Is there a 'message the moderator' section or is that just how it is..?

    Nice one for the above - It's a bit much for me at the moment I think... I need to do some trigonometry !

  • yes, I don't understand the math either.

Sign In or Register to comment.