Pixel Flow - Spout

edited June 2017 in Library Questions

Hi guys... just wondering if anyone could point me in the right direction so I can use a Spout receiver as input for Fluid density etc with the amazing PixelFlow lib?

Answers

  • T_DT_D
    edited June 2017

    Here is a short sender/receiver demo using Spout and PixelFlow for adding density from an external app (in this case just another processing sketch) to a fluid simulation (other sketch).

    1) Sketch: Spout Sender

    import spout.*;
    
    // Demo: Spout sender, just some simple drawing
    
    Spout spout;
    
    public void settings() {
      size(800, 600, P2D);
      smooth(8);
    }
    
    public void setup() {
      surface.setLocation(1080, 0);
      spout = new Spout(this);
      background(0);
      frameRate(120);
    }
    
    public void draw() {
      float velocity = min(max(dist(mouseX, mouseY, pmouseX, pmouseY) / 5f, 2), 8);
      float radius = mousePressed ? 50 : velocity * 10;
      
      strokeWeight(1);
      stroke(0);
      fill(color(mousePressed ? 0 : 255));
      ellipse(mouseX, mouseY, radius, radius );
      
      if(frameCount % 10 == 0){
        radius = random(10,40);
        float r = random(128,255);
        fill(r, r*0.75f, r*0.5f);
        ellipse(random(width), random(height), radius, radius );
      }
      
      spout.sendTexture();
    }
    
    public void keyReleased(){
      if(key == 'r') background(0);
    }
    

    2) Sketch: Spout Receiver, PixelFlow fluid simulation

    import com.thomasdiewald.pixelflow.java.DwPixelFlow;
    import com.thomasdiewald.pixelflow.java.dwgl.DwGLTexture;
    import com.thomasdiewald.pixelflow.java.fluid.DwFluid2D;
    import com.thomasdiewald.pixelflow.java.fluid.DwFluidParticleSystem2D;
    import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwFilter;
    
    import spout.Spout;
    
    // Density is fed by a PGraphics object each frame.
    // Spout is used to receive texture data from any external sender.
    //
    // controls:
    //
    // LMB: add Velocity
    // MMB: add Density
    // RMB: add Temperature
    
    
    private class MyFluidData implements DwFluid2D.FluidData{
      
      public void update(DwFluid2D fluid) {
      
        if(mousePressed ){
          float vscale = 15;
          float px     = mouseX;
          float py     = height - 1 - mouseY;
          float vx     = (mouseX - pmouseX) * +vscale;
          float vy     = (mouseY - pmouseY) * -vscale;
          
          if(mouseButton == LEFT){
            fluid.addVelocity(px, py, 20, vx, vy);
          }
          if(mouseButton == CENTER){
            fluid.addDensity(px, py, 50, 1,1,1,1, 1);
          }
          if(mouseButton == RIGHT){
            fluid.addTemperature(px, py, 15, 10);
          }
        }
        
        
        fluid.addTemperature(0, 0, 50, 10);
        fluid.addTemperature(fluid.fluid_w, 0, 50, 10);
        
        //
        // ADD DENSITY FROM TEXTURE:
        // pg_image              ... contains our current density input
        // fluid.tex_density.dst ... density render target
        // fluid.tex_density.src ... density from previous fluid update step
        
        // mix value
        float mix = (fluid.simulation_step == 0) ? 1.0f : 0.01f;
        
        // copy pg_density_input to temporary fluid texture
        DwFilter.get(context).copy.apply(pg_density_input, fluid.tex_density.dst);
        
        // mix both textures
        DwGLTexture[] tex = {fluid.tex_density.src, fluid.tex_density.dst};
        float[]       mad = {1f-mix, 0f, mix, 0f};
        DwFilter.get(context).merge.apply(fluid.tex_density.dst, tex, mad);
        
        // swap, dst becomes src, src is used as input for the next fluid update step
        fluid.tex_density.swap();
      }
    }
    
    
    
    Spout spout;
    
    DwPixelFlow context;
    
    DwFluid2D fluid;
    DwFluidParticleSystem2D particles;
    
    PGraphics2D pg_fluid;         // primary fluid render target
    PGraphics2D pg_density_input; // texture buffer for adding density
    
    
    public void settings() {
      size(800, 600, P2D);
      smooth(8);
    }
    
    
    public void setup() {
      
      surface.setLocation(250, 0);
      
      // main library context
      context = new DwPixelFlow(this);
      context.print();
      context.printGL();
      
      // fluid simulation
      fluid = new DwFluid2D(context, width, height, 1);
      
      // some fluid parameters
      fluid.param.dissipation_density     = 0.99f;
      fluid.param.dissipation_velocity    = 0.95f;
      fluid.param.dissipation_temperature = 0.70f;
      fluid.param.vorticity               = 0.50f;
      
      // interface for adding data to the fluid simulation
      MyFluidData cb_fluid_data = new MyFluidData();
      fluid.addCallback_FluiData(cb_fluid_data);
      
      // fluid render target
      pg_fluid = (PGraphics2D) createGraphics(width, height, P2D);
      pg_fluid.smooth(8);
      
      // particles
      particles = new DwFluidParticleSystem2D();
      particles.resize(context, width/4, height/4);
      
      // image/buffer that will be used as density input
      pg_density_input = (PGraphics2D) createGraphics(width, height, P2D);
      pg_density_input.smooth(0);
      pg_density_input.beginDraw();
      pg_density_input.clear();
      pg_density_input.endDraw();
      
      // spout
      spout = new Spout(this);
      
      frameRate(60);
    }
    
    
    public void draw() {
      
      // get density input from spout
      spout.receiveTexture(pg_density_input);
     
      // update fluid
      fluid.update();
      particles.update(fluid);
    
      // render fluid
      pg_fluid.beginDraw();
      pg_fluid.background(0);
      pg_fluid.endDraw();
      
      fluid.renderFluidTextures(pg_fluid, 0);
      // particles.render(pg_fluid, null, 2);
    
      // display result
      image(pg_fluid, 0, 0);
    }
    
    public void keyReleased(){
      if(key == 'r') fluid.reset();
    }
    

    This is the result.
    Left ... Reveiver, Fluid Sim
    Right ... Sender

  • This has now blown my mind.Thankyou

  • Hi, Trying to saveframes as pngs but wondering if it's possible to save frames that are smooth regardless of Framerate playback?In touchdesigner there's a button for this called "realtime" just wondering if you think this is possible using your awesome implementation?

  • What about syphon/spout the fluid image OUT? i haven't been able to get that to work in processing.

Sign In or Register to comment.