3d universe simulation OpenGL

edited March 2015 in Share Your Work

I recently created this universe simulation after school at mcdonald's where it works as such: Matter isn't clumped into 1 3 dimensional area but is it's own dimension. In it particles don't move rather they copy a state of one location to another on that same matter dimension. Therefore the void can move to occupy matter. (its confusing but neet) It took about an hour and is 147 lines of code.universe copy

For a link to a video demo:

Code: http://pastebin.com/ukU7XDfh

Comments

  • edited March 2015

    Very nice simulation Alex! Tried my luck at trying to speed it up & trim it down a bit more. :P
    In my PC it still crawls a lot though. It can also be run even slower online below:
    http://studio.ProcessingTogether.com/sp/pad/export/ro.9cEyzu18dPQIG/latest

    And here's the tweaked version: :-\"

    /**
     * Simulation of a Universe (v2.06)
     * by  Alejandro Rodriguez (Aroxalot) (2015/Feb/28)
     * mod GoToLoop (2015/Mar/01)
     *
     * forum.Processing.org/two/discussion/9633/3d-universe-simulation-opengl
     * www.YouTube.com/watch?v=HR67FyqCwhw&feature=youtu.be
     * studio.ProcessingTogether.com/sp/pad/export/ro.9cEyzu18dPQIG/latest
     */
    
    static final short R = 0, G = 1, B = 2;
    static final short DIM = 150, NUM = 3, CHANCE = 1000, DIAM = 5, DIFF = 2, FPS = 60;
    static final float D = 2.5*DIM, RAD90 = 90*DEG_TO_RAD;
    
    static final color[] INKS = {
      #FF0000, #008000, #0000FF
    };
    
    final boolean matters[][][][] = new boolean[DIM][DIM][DIM][NUM];
    boolean isPaused, invertRot;
    
    void setup() {
      size(600, 600, P3D);
      noSmooth();
      noFill();
      frameRate(FPS);
      initUniverse();
    }
    
    void draw() {
      background(0);
      float xy = radians(frameCount) * (invertRot? -1 : 1);
      camera(3*DIM, D - 8*DIM*cos(xy), D - 8*DIM*sin(xy), 3*DIM, D, D, 1, 0, 0);
      renderUniverse();
    }
    
    void mousePressed() {
      if      (mouseButton == CENTER)  initUniverse();
      else if (mouseButton == RIGHT)   invertRot = !invertRot;
      else if (isPaused ^= true)       noLoop();
      else                             loop();
    }
    
    void renderUniverse() {
      for (int i = 0; i != DIM; ++i) {
        boolean[][][] mi = matters[i];
    
        for (int j = 0; j != DIM; ++j) {
          boolean[][] mj = mi[j];
    
          for (int k = 0; k != DIM; ++k) {
            boolean[] mk = mj[k];
    
            //if      (mk[R] & mk[G])  mk[B] = !(mk[R] = mk[G] = false);
            //else if (mk[G] & mk[B])  mk[R] = !(mk[G] = mk[B] = false);
            //else if (mk[B] & mk[R])  mk[G] = !(mk[B] = mk[R] = false);
    
            int x = i + (int)random(-DIFF, DIFF);
            int y = j + (int)random(-DIFF, DIFF);
            int z = k + (int)random(-DIFF, DIFF);
            int xyz = x|y|z, c = 0;
    
            if (xyz >= 0 & xyz < DIM)  while (c != NUM)  matters[x][y][z][c] = mk[c++];
    
            for (x = i*DIAM, y = j*DIAM, z = k*DIAM, c = 0; c != NUM; ++c)  if (mk[c]) {
              drawMatter(x, y, z, INKS[c]);
              break;
            }
          }
        }
      }
    }
    
    void drawMatter(int x, int y, int z, color c) {
      fill(c);
      pushMatrix();
      translate(x, y, z);
      rotateX(RAD90);
      box(DIAM);
      popMatrix();
    }
    
    void initUniverse() {
      for (boolean[][][] i : matters)  for (boolean[][] j : i)  for (boolean[] k : j) {
        int rnd = (int)random(CHANCE);
        for (int c = 0; c != NUM; k[c++] = rnd == c);
      }
    }
    
  • edited March 2015

    very nice! I will share your update on my channel!

  • UPDATE: I shared your code in my video here: I credited you for your nice work!

  • edited March 2015

    Wow, cool YouTube comparison review video, thx! <:-P
    Though you had some little problems finding out where the 2 implementations matched each other! ;)

  • thanks very much!

  • edited March 2015
    • Hello again! This time I've come up w/ 1 dimension less tweak! :)>-
    • The idea is rather than spreading the R, G, B states as 1 extra dim. we squash them together as 1 byte.
    • Now instead of boolean[][][][] we've got byte[][][]! \m/
    • On the other hand it's more complicated to code/decode the states from a byte via bitwise operators.
    • Also it seems they're dying out more quickly so we need to center-click in order to refill the universe w/ matter. :(

    http://studio.ProcessingTogether.com/sp/pad/export/ro.9cEyzu18dPQIG/latest

    /**
     * Simulation of a Universe (v3.02)
     * by  Alejandro Rodriguez (Aroxalot) (2015/Feb/28)
     * mod GoToLoop (2015/Mar/01)
     *
     * forum.Processing.org/two/discussion/9633/3d-universe-simulation-opengl
     * www.YouTube.com/watch?v=HR67FyqCwhw&feature=youtu.be
     * studio.ProcessingTogether.com/sp/pad/export/ro.9cEyzu18dPQIG/latest
     */
    
    static final int R = 1<<0, G = 1<<1, B = 1<<2;
    static final int DIM = 150, NUM = 3, CHANCE = 500, DIAM = 5, DIFF = 3, FPS = 15;
    static final float D = 2.5*DIM, RAD90 = 90*DEG_TO_RAD;
    
    static final color[] INKS = {
      #FF0000, #008000, #0000FF
    };
    
    final byte matters[][][] = new byte[DIM][DIM][DIM];
    boolean isPaused, invertRot;
    
    void setup() {
      size(800, 800, P3D);
      noSmooth();
      noFill();
      frameRate(FPS);
      initUniverse();
    }
    
    void draw() {
      background(0);
      float xy = radians(frameCount) * (invertRot? -1 : 1);
      camera(3*DIM, D - 8*DIM*cos(xy), D - 8*DIM*sin(xy), 3*DIM, D, D, 1, 0, 0);
      renderUniverse();
    }
    
    void mousePressed() {
      if      (mouseButton == CENTER)  initUniverse();
      else if (mouseButton == RIGHT)   invertRot = !invertRot;
      else if (isPaused ^= true)       noLoop();
      else                             loop();
    }
    
    void renderUniverse() {
      for (int i = 0; i != DIM; ++i) {
        byte[][] mi = matters[i];
    
        for (int j = 0; j != DIM; ++j) {
          byte[] mj = mi[j];
    
          for (int k = 0; k != DIM; ++k) {
            byte mk = mj[k];
    
            int x = constrain(i + (int)random(-DIFF, DIFF+1), 0, DIM-1);
            int y = constrain(j + (int)random(-DIFF, DIFF+1), 0, DIM-1);
            int z = constrain(k + (int)random(-DIFF, DIFF+1), 0, DIM-1);
    
            if ((matters[x][y][z] = mk) != 0)
              drawMatter(x*DIAM, y*DIAM, z*DIAM, INKS[7 - (86/(mk + 11) | 0)]);
          }
        }
      }
    }
    
    void drawMatter(int x, int y, int z, color c) {
      fill(c);
      pushMatrix();
      translate(x, y, z);
      rotateX(RAD90);
      box(DIAM);
      popMatrix();
    }
    
    void initUniverse() {
      for (byte[][] i : matters)  for (byte[] j : i)
        for (int rnd = (int)random(CHANCE), k = 0; k != DIM
          ; j[k++] = (byte)(rnd < NUM? 1<<rnd : 0));
    }
    

    P.S.: In the end, those else if ((mk & (G|B)) == (G|B)) mj[k] = R; check statements proved useless! :O)

    if (mk == 0);
    else if ((mk & (R|G)) == (R|G))  mj[k] = B;
    else if ((mk & (G|B)) == (G|B))  mj[k] = R;
    else if ((mk & (B|R)) == (B|R))  mj[k] = G;
    
  • edited March 2015

    Since we've never needed any bitwise checks b/c matters[][][] are never more than 1 color state at a single time, we can have a more direct approach, where a byte either represents an INKS[]'s index or -1: *-:)

    /**
     * Simulation of a Universe (v3.13)
     * by  Alejandro Rodriguez (Aroxalot) (2015/Feb/28)
     * mod GoToLoop (2015/Mar/01)
     *
     * forum.Processing.org/two/discussion/9633/3d-universe-simulation-opengl
     * www.YouTube.com/watch?v=HR67FyqCwhw&feature=youtu.be
     * studio.ProcessingTogether.com/sp/pad/export/ro.9cEyzu18dPQIG/latest
     */
    
    static final int DIM = 150, CHANCE = 500, DIAM = 5, DIFF = 3, FPS = 15;
    static final float D = 2.5*DIM, RAD90 = 90*DEG_TO_RAD;
    
    static final color[] INKS = {
      #FF0000, #008000, #0000FF
    };
    
    final byte matters[][][] = new byte[DIM][DIM][DIM];
    boolean isPaused, invertRot;
    
    void setup() {
      size(800, 800, P3D);
      noSmooth();
      noFill();
      frameRate(FPS);
      initUniverse();
    }
    
    void draw() {
      background(0);
      float xy = radians(frameCount) * (invertRot? -1 : 1);
      camera(3*DIM, D - 8*DIM*cos(xy), D - 8*DIM*sin(xy), 3*DIM, D, D, 1, 0, 0);
      renderUniverse();
    }
    
    void mousePressed() {
      if      (mouseButton == CENTER)  initUniverse();
      else if (mouseButton == RIGHT)   invertRot = !invertRot;
      else if (isPaused ^= true)       noLoop();
      else                             loop();
    }
    
    void renderUniverse() {
      for (int i = 0; i != DIM; ++i) {
        byte[][] mi = matters[i];
    
        for (int j = 0; j != DIM; ++j) {
          byte[] mj = mi[j];
    
          for (int k = 0; k != DIM; ++k) {
            byte mk = mj[k];
    
            int x = constrain(i + (int)random(-DIFF, DIFF), 0, DIM-1);
            int y = constrain(j + (int)random(-DIFF, DIFF), 0, DIM-1);
            int z = constrain(k + (int)random(-DIFF, DIFF), 0, DIM-1);
    
            if ((matters[x][y][z] = mk) >= 0)
              drawMatter(i*DIAM, j*DIAM, k*DIAM, INKS[mk]);
          }
        }
      }
    }
    
    void drawMatter(int x, int y, int z, color c) {
      fill(c);
      pushMatrix();
      translate(x, y, z);
      rotateX(RAD90);
      box(DIAM);
      popMatrix();
    }
    
    void initUniverse() {
      for (byte[][] i : matters)  for (byte[] j : i)
        for (int rnd = (int)random(CHANCE), k = 0; k != DIM
          ; j[k++] = (byte)(rnd < INKS.length? rnd : -1));
    }
    
  • That update improved performance on my machine significantly! Thanks for the shared code! As well I found that changing DIM to 50 or 75 performance increases. I also like how your mod prevents clumping of particles to the edge of the universe, it makes it look much cleaner. :)

Sign In or Register to comment.