Skip to content

Instantly share code, notes, and snippets.

@tildebyte
Last active August 29, 2015 14:02
Show Gist options
  • Save tildebyte/2410e1ce7fb3894fafa3 to your computer and use it in GitHub Desktop.
Save tildebyte/2410e1ce7fb3894fafa3 to your computer and use it in GitHub Desktop.
/***********************************************************************
MSAFluidDemo.pde
Demo of the MSAFluid library (www.memo.tv/msafluid_for_processing)
Move mouse to add dye and forces to the fluid.
Click mouse to turn off fluid rendering seeing only particles and their paths.
Demonstrates feeding input into the fluid and reading data back (to update the particles).
Also demonstrates using Vertex Arrays for particle rendering.
/***********************************************************************
Copyright (c) 2008, 2009, Memo Akten, www.memo.tv
*** The Mega Super Awesome Visuals Company ***
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of MSA Visuals nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***********************************************************************/
import msafluid.*;
import processing.opengl.*;
import javax.media.opengl.*;
final float FLUID_WIDTH = 120;
float invWidth, invHeight; // inverse of screen dimensions
float aspectRatio, aspectRatio2;
MSAFluidSolver2D fluidSolver;
ParticleSystem particleSystem;
PImage imgFluid;
boolean drawFluid = true;
void setup() {
size(960, 640, OPENGL);
frameRate(30);
invWidth = 1.0f/width;
invHeight = 1.0f/height;
aspectRatio = width * invHeight;
aspectRatio2 = aspectRatio * aspectRatio;
// create fluid and set options
fluidSolver = new MSAFluidSolver2D((int)(FLUID_WIDTH), (int)(FLUID_WIDTH * height/width));
fluidSolver.enableRGB(true).setFadeSpeed(0.003).setDeltaT(0.5).setVisc(0.0001);
// create image to hold fluid picture
imgFluid = createImage(fluidSolver.getWidth(), fluidSolver.getHeight(), RGB);
// create particle system
particleSystem = new ParticleSystem();
}
void mouseMoved() {
float mouseNormX = mouseX * invWidth;
float mouseNormY = mouseY * invHeight;
float mouseVelX = (mouseX - pmouseX) * invWidth;
float mouseVelY = (mouseY - pmouseY) * invHeight;
addForce(mouseNormX, mouseNormY, mouseVelX, mouseVelY);
}
void draw() {
fluidSolver.update();
if(drawFluid) {
for(int i=0; i<fluidSolver.getNumCells(); i++) {
int d = 2;
imgFluid.pixels[i] = color(fluidSolver.r[i] * d, fluidSolver.g[i] * d, fluidSolver.b[i] * d);
}
imgFluid.updatePixels();// fastblur(imgFluid, 2);
image(imgFluid, 0, 0, width, height);
}
particleSystem.updateAndDraw();
}
void mousePressed() {
drawFluid ^= true;
}
// add force and dye to fluid, and create particles
void addForce(float x, float y, float dx, float dy) {
float speed = dx * dx + dy * dy * aspectRatio2; // balance the x and y components of speed with the screen aspect ratio
if(speed > 0) {
if(x<0) x = 0;
else if(x>1) x = 1;
if(y<0) y = 0;
else if(y>1) y = 1;
float colorMult = 5;
float velocityMult = 30.0f;
int index = fluidSolver.getIndexForNormalizedPosition(x, y);
color drawColor;
colorMode(HSB, 360, 1, 1);
float hue = ((x + y) * 180 + frameCount) % 360;
drawColor = color(hue, 1, 1);
colorMode(RGB, 1);
fluidSolver.rOld[index] += red(drawColor) * colorMult;
fluidSolver.gOld[index] += green(drawColor) * colorMult;
fluidSolver.bOld[index] += blue(drawColor) * colorMult;
particleSystem.addParticles(x * width, y * height, 10);
fluidSolver.uOld[index] += dx * velocityMult;
fluidSolver.vOld[index] += dy * velocityMult;
}
}
/***********************************************************************
Particle.pde
Copyright (c) 2008, 2009, Memo Akten, www.memo.tv
*** The Mega Super Awesome Visuals Company ***
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of MSA Visuals nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***********************************************************************/
class Particle {
final static float MOMENTUM = 0.5;
final static float FLUID_FORCE = 0.6;
float x, y;
float vx, vy;
float radius; // particle's size
float alpha;
float mass;
void init(float x, float y) {
this.x = x;
this.y = y;
vx = 0;
vy = 0;
radius = 5;
alpha = random(0.3, 1);
mass = random(0.1, 1);
}
void update() {
// only update if particle is visible
if(alpha == 0) return;
// read fluid info and add to velocity
int fluidIndex = fluidSolver.getIndexForNormalizedPosition(x * invWidth, y * invHeight);
vx = fluidSolver.u[fluidIndex] * width * mass * FLUID_FORCE + vx * MOMENTUM;
vy = fluidSolver.v[fluidIndex] * height * mass * FLUID_FORCE + vy * MOMENTUM;
// update position
x += vx;
y += vy;
// bounce of edges
if(x<0) {
x = 0;
vx *= -1;
}
else if(x > width) {
x = width;
vx *= -1;
}
if(y<0) {
y = 0;
vy *= -1;
}
else if(y > height) {
y = height;
vy *= -1;
}
// hackish way to make particles glitter when the slow down a lot
if(vx * vx + vy * vy < 1) {
vx = random(-1, 1);
vy = random(-1, 1);
}
// fade out a bit (and kill if alpha == 0);
alpha *= 0.999;
if(alpha < 0.01) alpha = 0;
}
void drawOldSchool(GL2 gl) {
gl.glColor3f(alpha, alpha, alpha);
gl.glVertex2f(x-vx, y-vy);
gl.glVertex2f(x, y);
}
}
/***********************************************************************
ParticleSystem.pde
Copyright (c) 2008, 2009, Memo Akten, www.memo.tv
*** The Mega Super Awesome Visuals Company ***
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of MSA Visuals nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***********************************************************************/
import javax.media.opengl.*;
import java.nio.*;
void fadeToColor(GL2 gl, float r, float g, float b, float speed) {
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
gl.glColor4f(r, g, b, speed);
gl.glBegin(gl.GL_QUADS);
gl.glVertex2f(0, 0);
gl.glVertex2f(width, 0);
gl.glVertex2f(width, height);
gl.glVertex2f(0, height);
gl.glEnd();
}
class ParticleSystem {
FloatBuffer posArray;
FloatBuffer colArray;
final static int maxParticles = 5000;
int curIndex;
Particle[] particles;
ParticleSystem() {
particles = new Particle[maxParticles];
for(int i=0; i<maxParticles; i++) particles[i] = new Particle();
curIndex = 0;
posArray = ByteBuffer.allocateDirect(maxParticles * 2 * 2).order(ByteOrder.nativeOrder()).asFloatBuffer();// 2 coordinates per point, 2 points per particle (current and previous)
colArray = ByteBuffer.allocateDirect(maxParticles * 3 * 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
}
void updateAndDraw(){
//OPENGL Processing 2.0
GL2 gl2 = ((PJOGL)beginPGL()).gl.getGL2();
gl2.glEnable( GL.GL_BLEND ); // enable blending
if(!drawFluid) fadeToColor(gl2, 0, 0, 0, 0.05);
gl2.glBlendFunc(gl2.GL_ONE, GL.GL_ONE); // additive blending (ignore alpha)
gl2.glEnable(gl2.GL_LINE_SMOOTH); // make points round
gl2.glLineWidth(1);
gl2.glBegin(gl2.GL_LINES); // start drawing points
for(int i=0; i<maxParticles; i++) {
if(particles[i].alpha > 0) {
particles[i].update();
particles[i].drawOldSchool(gl2); // use oldschool renderng
}
}
gl2.glEnd();
gl2.glDisable(GL.GL_BLEND);
endPGL();
}
void addParticles(float x, float y, int count ){
for(int i=0; i<count; i++) addParticle(x + random(-15, 15), y + random(-15, 15));
}
void addParticle(float x, float y) {
particles[curIndex].init(x, y);
curIndex++;
if(curIndex >= maxParticles) curIndex = 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment