We are about to switch to a new forum software. Until then we have removed the registration on this forum.
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
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.