Results 1 to 8 of 8

Thread: some lovely lissajous inspiration

  1. #1
    swamidog's Avatar
    swamidog is offline Jr. Woodchuckington Janitor III, Esq.
    Join Date
    Nov 2006
    Location
    santa fe, nm
    Posts
    1,545,365

    Default some lovely lissajous inspiration

    suppose you're thinkin' about a plate o' shrimp. Suddenly someone'll say, like, plate, or shrimp, or plate o' shrimp out of the blue, no explanation. No point in lookin' for one, either. It's all part of a cosmic unconciousness.

  2. #2
    Join Date
    Jul 2008
    Location
    My momentum is too precisely determined :S
    Posts
    1,764

    Default

    I had a look at the source code. It's written in processing. Coincidentally I'm developing a library for processing that can convert such sketches to Ilda. Should just be a couple of modified lines to get it working...

  3. #3
    Join Date
    Feb 2015
    Location
    San Francisco
    Posts
    59

    Default

    I'd love to see what you come up with. I've played with Processing to do animations for some physics talks I have given. Very useful language.

    Quote Originally Posted by colouredmirrorball View Post
    I had a look at the source code. It's written in processing. Coincidentally I'm developing a library for processing that can convert such sketches to Ilda. Should just be a couple of modified lines to get it working...

  4. #4
    swamidog's Avatar
    swamidog is offline Jr. Woodchuckington Janitor III, Esq.
    Join Date
    Nov 2006
    Location
    santa fe, nm
    Posts
    1,545,365

    Default

    Quote Originally Posted by ronhip View Post
    I'd love to see what you come up with. I've played with Processing to do animations for some physics talks I have given. Very useful language.
    i made the cut template fractals for these with processing.

    suppose you're thinkin' about a plate o' shrimp. Suddenly someone'll say, like, plate, or shrimp, or plate o' shrimp out of the blue, no explanation. No point in lookin' for one, either. It's all part of a cosmic unconciousness.

  5. #5
    Join Date
    Jul 2008
    Location
    My momentum is too precisely determined :S
    Posts
    1,764

    Default

    "Couple of modified lines" was a bit of an optimistic guess...

    But it works! Though it doesn't look as great as on the screen because a lot of the effect is because of the simulated persistence of vision.

    Here's my modified code. I added comments to clarify my modifications.

    Code:
    import Ilda.*;
    
    /*
     * Lissajous Oscillation
     * Original sketch by Beautiful Programming
     * http://beautifulprogramming.com/lissajous-oscillation/
     * 
     * Modified by CMB so it exports laser art
     * Happy lasing!
     */
    
    
    
    Ilda ilda;
    
    PFont font;
    Part part;
    int time = 1;
    float r1, r2, r3, r4;
    int numAxis = 1;
    color bgColor;
    boolean showsFPS = true;
    boolean doesPaint = true;
    boolean autoplay = true;
    boolean isPaused = false;
    ColorPalette cp;
    float spread = 5;
    float osc1, osc2;
    
    PGraphics overlay;    //Displays the text
    PGraphics abstr;      //Displays the abstract as found on the web
    PGraphics laser;      //Display the abstract as rendered to ilda
    IldaRenderer r;       //Renders ilda points, works in the same way as a PGraphics
    
    boolean renderToLaser = false;
    boolean displayLaserError = false;
    boolean displayLaser = false;
    
    void setup()
    {
      size(940, 540, P2D);
      ilda = new Ilda(this);                     //As for now the library needs a reference to this PApplet but it should be possible to remove that in the future
      r = new IldaRenderer(ilda, 540, 540);      //
      r.setOptimise(false);                      //Assume the software the ilda file ends up has optimisation built in... (also optimisation is still in beta)
      overlay = createGraphics(940, 540);
      abstr = createGraphics(940, 540);
      laser = createGraphics(540, 540, P3D);     //To render an ilda frame to a PGraphics it has to be 3D
    
        colorMode(HSB);
      background(0);
      strokeWeight(0.5);
      font = createFont("Helvetica", 18);
      overlay.textFont(font, 18);
      bgColor = color(0, 10);
      randomize();
      part = new Part(0, 0);
    }
    
    void draw()
    { 
      background(bgColor);
      if (!isPaused)
      {
        //The abstract is now rendered to a separate PGraphics
        abstr.beginDraw();
        if (!doesPaint)
        {
          abstr.fill(bgColor);
          abstr.noStroke();
          abstr.rect(0, 0, width, height);
        }
    
        if (autoplay)
        {
          time++;
          if (time > 700) randomize();
        }
    
        abstr.translate(width/2, height/2);
        r.translate(r.width/2, r.height/2);      
        abstr.noFill();
    
        osc1 += 0.0011;
        osc2 += 0.0013;
    
        r1 = abs(sin(osc1) * 0.009) + 0.001;
        r2 = abs(sin(osc2) * 0.009) + 0.001;
        if (renderToLaser) r.beginDraw();      //Don't forget this!
    
        part.draw();
        abstr.endDraw();
        if (renderToLaser) r.endDraw();
      }
      if (!displayLaser && abstr != null ) image(abstr, 0, 0);
      if (displayLaser && renderToLaser) 
      {
        IldaFrame frame = r.getCurrentFrame();
        image(frame.renderFrame(laser, true), 200, 0);        //This is how you render an Ilda frame to a PGraphics. Easy!
      }
      if (showsFPS) displayFPS();
    }
    
    void randomize()
    {
      time = 1;
      if (doesPaint) background(0);
      randomizeColor();
      randomizeShape();
      randomizeAxis();
    }
    
    void randomizeShape()
    {
      if (doesPaint) abstr.background(0);
      float bottom = 0.001;
      float top = 0.01;
      r1 = random(bottom, top); 
      r2 = random(bottom, top); 
      r3 = random(bottom, top); 
      r4 = random(bottom, top);
      spread = random(1, 20);
    }
    
    void randomizeAxis()
    {
      if (doesPaint) abstr.background(0);
      numAxis = round(random(2, 30));
    }
    
    void randomizeColor()
    {
      cp = new ColorPalette();
    }
    
    void finishRenderingToLaser()
    {
      if (renderToLaser)
      {
        renderToLaser = false;
        selectOutput("Select where to output ilda file to", "outputSelected");
      } else
      {
        showsFPS = true;
        displayLaserError = true;
      }
    }
    
    void outputSelected(File selection)
    {
      if (selection == null)
      {
        println("Wrong file");
        return;
      }
      ilda.writeFile(r.getFrames(), selection.getAbsolutePath());    //This is how you export an ilda file. Can it be easier? (Format 4 by default)
    }
    
    void mouseClicked()
    {
      randomize();
      autoplay = false;
    }
    
    void keyPressed()
    {
      if (key == 'o') showsFPS = !showsFPS;
      if (key == 'd')
      {
        float a = alpha(bgColor);
        if (a == 10) a = 40;
        else a = 10;
        bgColor = color(0, a);
      }
    
      if (key == 'p') doesPaint = !doesPaint;
      if (key == 'a') autoplay = !autoplay;
      if (key == ' ') isPaused = !isPaused;
      if (key == 'c') randomizeColor();
      if (key == 'h') randomizeShape();
      if (key == 'x') randomizeAxis();
      if (key == 'b') abstr.background(0);
      if (key == 'r') 
      {
        renderToLaser = true;
        displayLaserError = false;
        r.clearAllFrames();
      }
      if (key == 's') finishRenderingToLaser();
      if (key == 't') displayLaser = !displayLaser;
    
      if (key == '=') 
      {
        numAxis++;
        if (doesPaint) abstr.background(0);
      }
      if (key == '-') 
      {
        numAxis--;
        if (doesPaint) abstr.background(0);
      }
      if (numAxis < 1) numAxis = 1;
      if (numAxis > 30) numAxis = 30;
    }
    
    void displayFPS()
    {
      overlay.beginDraw();
      overlay.background(0, 1);
      overlay.fill(255);
      String output = "fps=";
      output += (int) frameRate;
      overlay.textAlign(LEFT);
      overlay.text(output, 10, 30);
      overlay.text("This overlay: o [ON]", 10, 60);
      overlay.text("Toggle background paint: p [" + (doesPaint ? "ON" : "OFF") + "]", 10, 90);
      overlay.text("Decay length when background paint toggled off: d", 10, 120);
      overlay.text("Auto-randomizing: a [" + (autoplay ? "ON" : "OFF") + "]", 10, 150);
      overlay.text("Pause: spacebar [" + (isPaused ? "ON" : "OFF") + "]", 10, 180);
      overlay.text("Randomize colour: c", 10, 210);
      overlay.text("Randomize shape: h", 10, 240);
      overlay.text("Randomize axis: x", 10, 270);
      overlay.text("Clear background: b", 10, 300);
      overlay.text("Change number of axes: +/- [" + numAxis + "]", 10, 330);
      overlay.text("Toggle laser view (only when recording): t [" + (displayLaser ? "LASER" : "PIXELS") + "]", 10, 360);
    
    
    
      if (displayLaserError) overlay.text("Error: must record before saving. Hit r before hitting s.", 10, overlay.height-90);
      overlay.text("Start recording Ilda file: r [" + (renderToLaser ? "RECORDING: " + r.getFrames().size() + " frames" : "IDLE") + "]", 10, overlay.height-60);
      overlay.text("Finish recording Ilda frames and save to file: s", 10, overlay.height-30);
      overlay.endDraw();
    
      image(overlay, 0, 0);
    }
    
    class ColorPalette
    {
      PGraphics pg;
      int w = 300;
      color[] allColors;
    
      ColorPalette()
      {
        createPalette();
    
        allColors = new color[w];
        for (int i=0; i<w; i++)
        {
          allColors[i] = pg.get(i, 0);
        }
      }
    
      color getColorAtRatio(float _ratio)
      {
        int index = min(w-1, floor(w * _ratio));
        return allColors[index];
      }
    
      void createPalette()
      {
        pg = createGraphics(w, 1);
        pg.colorMode(HSB);
        pg.beginDraw();
    
        pg.noStroke();
    
        color baseColor = color(random(255), random(255, 255), random(255, 255));
        pg.background(baseColor);
    
        int numColors = 6;
        for (int i=0; i<numColors; i++)
        {
          addColor();
        }
    
        pg.endDraw();
      }
    
      void addColor()
      {
        color c = color(random(255), random(0, 255), random(150, 255));
        float pos = random(w);
        float size = w/4;
    
        for (int i=0; i<w; i++)
        {
          float ratio = 0;
          float d = abs(i-pos);
          if (d < size)
          {
            ratio = 1.0 - (d/size);
          }
          pg.fill(hue(c), saturation(c), brightness(c), (ratio)*255);
          pg.rect(i, 0, 1, 1);
        }
      }
    
      void draw()
      {
        image(pg, 0, height/2, width, 10);
      }
    }
    
    class Part
    {
      PVector pos[];
      int trailLength = 100;
      float speed = 0.03;
      float o1, o2, o3, o4;
    
      Part(float _x, float _y)
      {
        pos = new PVector[trailLength+1];
    
        for (int i=0; i<=trailLength; i++)
        {
          pos[i] = new PVector(0, 0);
        }
      }
    
      void draw()
      {
        float step = radians(360/numAxis);
        float x, y;
    
        for (int i=0; i<=trailLength; i++)
        {
          o1 += r1*speed;
          o2 += r2*speed;
          o3 += r3*speed;
          o4 += r4*speed;
    
          x = sin(o1 + i*spread*r1) * 125;
          y = cos(o2 + i*spread*r2) * 50;
          x += sin(o3 + i*spread*r3) * 125;
          y += cos(o4 + i*spread*r4) * 50;
          pos[i].x += (x - pos[i].x) * 0.1;
          pos[i].y += (y - pos[i].y) * 0.1;
        }
    
        for (int i=1; i<=trailLength; i++)
        {  
          abstr.stroke(cp.getColorAtRatio(i/trailLength));
          abstr.pushMatrix();
    
          for (int j=0; j<numAxis; j++)
          {
            abstr.rotate(step);
            abstr.line(pos[i].x, pos[i].y, pos[i-1].x, pos[i-1].y);
          }
          abstr.popMatrix();
        }
    
    
    
        //I had to reorder the loops otherwise it would be a mess...
        if (renderToLaser)
        {
          for (int j=0; j<numAxis; j++)
          {
            r.rotate(step);
            r.beginShape(LINES);                //Using shape and vertex instead of line as this gives better results
            for (int i=1; i<=trailLength; i++)  //Line works as well but would result in two points per vertex, one of them blanked (not optimal of course)
            { 
              r.stroke(cp.getColorAtRatio(i/trailLength));
              r.vertex(pos[i].x, pos[i].y);
            }
            r.endShape();
          }
        }
      }
    }
    Download:

    The application: lissajous_oscillation.rar
    The library (not required for application): Ilda.rar


    How to use:

    Minimum requirements: Windows 64 bit (32 bit, OSX and Linux: compile your own!) and OpenGL 2.0

    For the application:

    Important: the resulting ilda file is not optimised and can be point heavy. Always review the file before sending to scanners. There are about 200 points per axis (the amount of axes is visible in the o display) so it's up to you to know what point count your scanners can handle. The blanked line between two segments is not optimised so this might result in a lot of stress on your scanners having to make too big jumps! You should make sure your laser program takes care of that.

    Unpack lissajous_oscillator.rar and double click the .exe. Hopefully a window appears where some abstract starts playing. There are letters on the screen (which you can hide with the o key) with hotkeys, in Laserboy style. The bit you're probably interested in is recording to ilda: to do this, simply hit r, wait until you're satisfied and then hit s. A dialog should pop up where you can enter a file name and that should result in an ilda file. While rendering you can hit t to see what the ilda file looks like.

    Compiling from scratch:

    Download and install Processing from processing.org (I used version 2.2.1 but version 3.0 beta was just released, don't know if my library is compatible with 3.0 but feel free to test). Once you have the IDE up and running, paste my code in there. You'll also need to include my library, either by dragging and dropping Ilda.jar to the IDE or by unpacking ilda.rar in a folder named Ilda in your libraries folder: /Your Processing sketchbook/libraries/Ilda/lib/Ilda.jar (it might be necessary to restart the IDE after this). Click the play button (or ctrl+r) and this should run the sketch.

    Using the library:

    People who feel adventurous might want to use my library to generate their own Ilda files straight from Processing. My library isn't released so it requires a manual install. Simply unpack the contents of Ilda.rar in a new folder named Ilda in the libraries folder of your Processing sketchbook. After a restart of the IDE you can now do Sketch >> Import library >> Ilda and start using the library. Example sketches are being polished up but you can use this sketch as a start. There is also a javadoc inside the reference folder of the library with plenty of comments. I'll gladly answer any questions.

    The library's code is also on Github: https://github.com/colouredmirrorball/Ilda
    Feel free to look for improvements!
    Last edited by colouredmirrorball; 08-09-2015 at 14:48. Reason: Don't break your scanners

  6. #6
    Join Date
    Feb 2015
    Location
    San Francisco
    Posts
    59

    Default

    CMB,

    Which version of Processing were you using?

    Ron

  7. #7
    Join Date
    Jul 2008
    Location
    My momentum is too precisely determined :S
    Posts
    1,764

    Default

    2.2.1, are there any incompatibilities with 3.0? I haven't tested with 3.0... Good point, maybe I should give 3 a go and see how it goes.

  8. #8
    Join Date
    Apr 2010
    Location
    Grand Rapids, Mi
    Posts
    2,433

    Default

    Thanks for sharing the program / code
    leading in trailing technology

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •