• fullscreen
  • filledMesh.pde
  • floorSlabs.pde
  • fuzzy.pde
  • gui.pde
  • saturation.pde
  • updateMesh.pde
  • //this is part of toxi's "box fluid demo" modified for purposes of extracting vertex colors from volumetric color data
    
    void drawFilledMesh() {
      noStroke();
      int num=mesh.getNumFaces();
      mesh.computeVertexNormals();
      beginShape(TRIANGLES);
      for (int i=0; i<num; i++) {
        Face f=mesh.faces.get(i);
        fill(colors[(int)map(f.a.x, -scs/2, scs/2, 0, dimX)][(int)map(f.a.y, -scs, scs, 0, dimY)][(int)map(f.a.z, -scs/2, scs/2, 0, dimZ)]);
        normal(f.a.normal);
        vertex(f.a);
        fill(colors[(int)map(f.b.x, -scs/2, scs/2, 0, dimX)][(int)map(f.b.y, -scs, scs, 0, dimY)][(int)map(f.b.z, -scs/2, scs/2, 0, dimZ)]);
        normal(f.b.normal);
        vertex(f.b);
        fill(colors[(int)map(f.c.x, -scs/2, scs/2, 0, dimX)][(int)map(f.c.y, -scs, scs, 0, dimY)][(int)map(f.c.z, -scs/2, scs/2, 0, dimZ)]);
        normal(f.c.normal);
        vertex(f.c);
      }
      endShape();
    }
    
    
    void normal(Vec3D v) {
      normal(v.x, v.y, v.z);
    }
    
    void vertex(Vec3D v) {
      vertex(v.x, v.y, v.z);
    }
    
    void vertex(Vec3D v, float _u, float _v) {
      vertex(v.x, v.y, v.z, _u, _v);
    }
    
    
    //this part comes from "scalar field polygonisation" by Shane Nelson http://www.openprocessing.org/visuals/?visualID=49742
    
    int gridres =dimX, oldgridres = 0;
    float[][][] input;
    boolean fill = false;
    
    float slabTreshold=0.2;
    int floorDensity=8;
    
    int slabColor=200;
    
    void drawSlice(float[][][] input, int sliceY) {
      stroke(0);
      strokeWeight(2);
      fill(slabColor);
      for (int k=0;k<gridres-1;k++)for (int j=0;j<gridres-1;j++) {
        float a = input[sliceY][j][k], b = input[sliceY][j+1][k], 
        c = input[sliceY][j][k+1], d = input[sliceY][j+1][k+1];
    
        if (a < slabTreshold && b < slabTreshold && c < slabTreshold && d < slabTreshold && fill) continue;
        float ab = (slabTreshold - a) / (b - a), 
        cd = (slabTreshold - c) / (d - c), 
        ac = (slabTreshold - a) / (c - a), 
        bd = (slabTreshold - b) / (d - b);
    
        beginShape();
        if (a < slabTreshold) vertex(j, 0, k);
        if (ab > 0 && ab < 1) vertex(j+ab, 0, k);
        if (b < slabTreshold) vertex(j+1, 0, k);
        if (bd > 0 && bd < 1) vertex(j+1, 0, k+bd);
        if (d < slabTreshold) vertex(j+1, 0, k+1);
        if (cd > 0 && cd < 1) vertex(j+cd, 0, k+1);
        if (c < slabTreshold) vertex(j, 0, k+1);
        if (ac > 0 && ac < 1) vertex(j, 0, k+ac);
        endShape(CLOSE);
      }
    }
    
    
    //fuzzy logic: http://en.wikipedia.org/wiki/Fuzzy_logic
    
    float fTrp(float value, float x0, float x1,float x2, float x3) {//fuzzy trapezoid function
      float result=0;
      float x=value;
      if(x<=x0)result=0;
      else if((x>=x1)&&(x<=x2))result=1;
      else if((x>x0)&&(x<x1))result=(x/(x1-x0))-(x0/(x1-x0));
      else result=constrain((-x/(x3-x2))+(x3/(x3-x2)),0,1);
      return result;
    }
    
    float fGrade(float value, float x0, float x1){//fuzzy grade function
      float result=0;
      float x=value;
       if(x<=x0)result=0;
      else if(x>=x1)result=1;
     else{
      result=(x/(x1-x0))-(x0/(x1-x0));
     }
    return result; 
    }
    
    //fuzzy logical operators:
    
    float fAND(float A, float B) {
      return min(A,B);
    }
    float fOR(float A, float B) {
      return max(A,B);
    }
    float fNOT(float A) {
      return 1.0-A;
    }
    
    
    
    ControlP5 gui;
    ControlWindow controlWindow;
    
    void initGUI() {
      gui = new ControlP5(this);
      gui.setAutoDraw(false);
      controlWindow = gui.addControlWindow("controlP5window", 100, 100, 400, 500);
      controlWindow.hideCoordinates();  
      controlWindow.setBackground(color(40));
      Controller mySlider1 = gui.addSlider("rFreq", 0, 20, 15, 20, 200, 10);
      Controller mySlider2 = gui.addSlider("gFreq", 0, 20, 15, 40, 200, 10);
      Controller mySlider3 = gui.addSlider("bFreq", 0, 20, 15, 60, 200, 10);
      Controller mySlider4 = gui.addSlider("rIntens", 0, 255, 20, 100, 200, 10);
      Controller mySlider5 = gui.addSlider("gIntens", 0, 255, 20, 120, 200, 10);
      Controller mySlider6 = gui.addSlider("bIntens", 0, 255, 20, 140, 200, 10);
      Controller mySlider7 = gui.addSlider("bcgColor", 0, 255, 20, 180, 200, 10);
      Controller mySlider8 = gui.addSlider("slabTreshold", 0.001, 0.3, 20, 220, 200, 10);
      Controller mySlider9 = gui.addSlider("slabColor", 0, 255, 20, 200, 200, 10);
      Controller myButton1 = gui.addButton("runReaction", 0, 290, 300, 50, 20);
      Controller myButton2 = gui.addButton("updateColor", 0, 260, 20, 80, 20);
      Controller myButton3 = gui.addButton("randomFreq", 0, 260, 60, 80, 10);
      Controller myButton4 = gui.addButton("randomIntens", 0, 260, 100, 80, 10);
      Controller myButton5 = gui.addButton("smoothIt", 0, 290, 180, 50, 50);
      Controller myToggle1 = gui.addToggle("colorIndexing", true, 290, 240, 50, 20);
      mySlider1.setWindow(controlWindow);
      mySlider2.setWindow(controlWindow);
      mySlider3.setWindow(controlWindow);
      mySlider4.setWindow(controlWindow);
      mySlider5.setWindow(controlWindow);
      mySlider6.setWindow(controlWindow);
      mySlider7.setWindow(controlWindow);
      mySlider8.setWindow(controlWindow);
      mySlider9.setWindow(controlWindow);
      myButton1.setWindow(controlWindow);
      myButton2.setWindow(controlWindow);
      myButton3.setWindow(controlWindow);
      myButton4.setWindow(controlWindow);
      myButton5.setWindow(controlWindow);
      myToggle1.setWindow(controlWindow);
    }
    
    public void runReaction() {
      runReaction = !runReaction;
    }
    public void randomFreq() {
      rFreq = (int)random(20);
      gFreq = (int)random(20);
      bFreq = (int)random(20); 
      gui.controller("rFreq").setValue(rFreq);
      gui.controller("gFreq").setValue(gFreq);
      gui.controller("bFreq").setValue(bFreq);
      updateColors();
    }
    
    public void randomIntens() {
      rIntens =(int)random(255);
      gIntens =(int)random(255);
      bIntens =(int)random(255);
      gui.controller("rIntens").setValue(rIntens);
      gui.controller("gIntens").setValue(gIntens);
      gui.controller("bIntens").setValue(bIntens);
      updateColors();
    }
    
    public void updateColor() {
      updateColors();
    }
    
    public void smoothIt() {
      new LaplacianSmooth().filter(mesh, 1);
    }
    
    void colorIndexing(boolean theFlag) {
      uniform=theFlag;
    }
    
    
    //  SPECULATIVE APPS 001: 'saturation' by echoechonoisenoise
    //  architecture uses sketches to communicate and discuss ideas. what happens, when they become operative and anyone can modify them?
    
    //  echoechonoisenoise added: fuzzy control, volumeutils mesh, colors and floor slabs :) using Shane Nelson's http://www.openprocessing.org/visuals/?visualID=49742
    
    //  3d Belousov-Zhabotinsky reaction _ Tommaso Casucci
    //  http://www.openprocessing.org/visuals/?visualID=38850
    
    //  expansion of Alasdair Turner code
    //  http://www.openprocessing.org/visuals/?visualID=1263
    
    import peasy.*;
    import toxi.volume.*;
    import toxi.geom.*;
    import toxi.geom.mesh.*;
    import toxi.processing.*; 
    import controlP5.*;
    
    PeasyCam cam;
    
    ToxiclibsSupport gfx;
    
    int dimX = 35;
    int dimY = 70;
    int dimZ = 35;
    
    int scs=100;
    float ISO_THRESHOLD = 0.5;
    Vec3D sc=new Vec3D(1, 2, 1).scaleSelf(scs);
    VolumetricSpaceArray volume=new VolumetricSpaceArray(sc, dimX, dimY, dimZ);
    IsoSurface surface=new HashIsoSurface(volume);
    WETriangleMesh mesh;
    
    int rFreq = 10;
    int gFreq = 9;
    int bFreq = 9;
    
    int rIntens =255;
    int gIntens =255;
    int bIntens =255;
    
    int bcgColor=60;
    
    float [][][][] a;
    float [][][][] b;
    float [][][][] c;
    
    int p = 0, q = 1;
    
    boolean runReaction=false;
    boolean uniform=true;
    
    void setup () {
      size(900, 900, P3D);
      cam = new PeasyCam(this, 250);
      cam.rotateX(0.5);
      cam.rotateY(0.3);
      cam.rotateZ(-0.17);
    
      initGUI();
    
      initMeshColors();
      initReaction();
      for (int i=0;i<50;i++)updateReaction();
      updateMesh();
      updateColors();
      for (int i=0;i<4;i++)new LaplacianSmooth().filter(mesh, 2);
    }
    
    
    void draw () {
      background(bcgColor);
      pointLight(255, 255, 255, 300, -400, 300);
      pointLight(155, 155, 155, -300, -200, -300);
      pointLight(200, 200, 220, 300, 500, -300);
    
      drawFilledMesh();
      translate(-scs/2, 0, -scs/2);
    
      for (int y=0;y<dimY;y++) {
        pushMatrix();
        translate(0, map(y, 0, dimY, -scs, scs), 0);
        scale(2.9);//very amateur way... didn't spent time on translating Shane's code into toxi.geom.mesh; although would be great to make further operations with it...
        if (y%floorDensity==0&&y!=0&&y!=dimY)drawSlice(input, y);
        popMatrix();
      }
    
    
      if (runReaction) {
        updateReaction();
        updateMesh();
        updateColors();
      }
    }
    
    
    float[][][][] colorspace;
    color[][][] colors;
    
    void initMeshColors() {
      colorspace=new float[dimX][dimY][dimZ][3];  
      colors=new color[dimX][dimY][dimZ];
    }
    
    //this part is mostly Alasdair Turner' code made 3d by Tomasso Casucci
    
    void initReaction() {
      a = new float [dimX ][ dimY ][ dimZ ][2];
      b = new float [dimX ][ dimY ][ dimZ ][2];
      c = new float [dimX ][ dimY ][ dimZ ][2];
    
      for (int x = 0; x < dimX; x++) {
        for (int y = 0; y < dimY; y++) {
          for (int z = 0; z< dimZ; z++) {
            a[x][y][z][p] = random (1);
            b[x][y][z][p] = random (1);
            c[x][y][z][p] = random (1);
          }
        }
      }
    }
    
    void updateReaction() {
      if (gridres != oldgridres) {
        input = new float[dimY][gridres][gridres];
        oldgridres = gridres;
      }
      for (int x = 0; x < dimX; x++) {
        for (int y = 0; y < dimY; y++) {
          for (int z = 0; z < dimZ; z++) {
            float c_a = 0.0;
            float c_b = 0.0;
            float c_c = 0.0;
    
            for (int i = x - 1; i <= x+1; i++) {
              for (int j = y - 1; j <= y+1; j++) {
                for (int k = z - 1; k <= z+1; k++) {
                  c_a += a[(i+dimX )% dimX ][(j+dimY )% dimY ][(k+dimZ )% dimZ ][p];
                  c_b += b[(i+dimX )% dimX ][(j+dimY )% dimY ][(k+dimZ )% dimZ ][p];
                  c_c += c[(i+dimX )% dimX ][(j+dimY )% dimY ][(k+dimZ )% dimZ ][p];
                }
              }
            }
    
            c_a /= 27.0;
            c_b /= 27.0;
            c_c /= 27.0;
            // adjust these values to alter behaviour
            a[x][y][z][q] = constrain(c_a + c_a * (c_b - c_c), 0, 1);
            b[x][y][z][q] = constrain(c_b + c_b * (c_c - c_a), 0, 1);
            c[x][y][z][q] = constrain(c_c + c_c * (c_a - c_b), 0, 1);
    
    
            float vValue=fTrp(map(sin(a[x][y][z][q]*9), -1, 1, 0, 1), -0.5, -0.4, 0.4, 0.5);
            volume.setVoxelAt(x, y, z, vValue);
    
            colorspace[x][y][z][0]=a[x][y][z][q];
            colorspace[x][y][z][1]=b[x][y][z][q];
            colorspace[x][y][z][2]=c[x][y][z][q];
    
            if (y%floorDensity==0)input[y][x][z] = a[x][y][z][q];//update floor slab input array
          }
        }
      }
      if (p == 0) {
        p = 1; 
        q = 0;
      }
      else {
        p = 0; 
        q = 1;
      }
    }
    
    void updateMesh() {
      volume.closeSides();
      mesh=new WETriangleMesh("iso"); 
      IsoSurface surface=new HashIsoSurface(volume, 0.333333);
      surface.computeSurfaceMesh(mesh, ISO_THRESHOLD);
      new LaplacianSmooth().filter(mesh, 1);
    }
    
    void updateColors() {
      if (uniform) {
        for (int x = 0; x < dimX; x++) {
          for (int y = 0; y < dimY; y++) {
            for (int z = 0; z < dimZ; z++) {
              colors[x][y][z]=color(map(sin(colorspace[x][y][z][0]*rFreq), -1, 1, 0, rIntens), map(sin(colorspace[x][y][z][0]*gFreq), -1, 1, 0, gIntens), map(sin(colorspace[x][y][z][0]*bFreq), -1, 1, 0, bIntens));
            }
          }
        }
      }
      else {
        for (int x = 0; x < dimX; x++) {
          for (int y = 0; y < dimY; y++) {
            for (int z = 0; z < dimZ; z++) {
              colors[x][y][z]=color(map(sin(colorspace[x][y][z][0]*rFreq), -1, 1, 0, rIntens), map(sin(colorspace[x][y][z][1]*gFreq), -1, 1, 0, gIntens), map(sin(colorspace[x][y][z][2]*bFreq), -1, 1, 0, bIntens));
            }
          }
        }
      }
    }
    
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement


    echoechonoisenoise
    sam ng
    22 Oct 2012
    Wonderful....!!!
    Eduardo Obieta
    23 Oct 2012
    Wow, so nice¡¡¡¡
    thx guys.
    You need to login/register to comment.