FAQ
 
 
Cover  \ Exhibition  \ Learning  \ Reference  \ Download  \ Discourse   
    Examples \ Tutorials \ Courses & Workshops
 
   
 
 
Examples for Processing (BETA) version 91+. If you have a previous version, use the examples included with your software. If you see any errors or have comments, please let us know.



Smoke Particle System
Daniel Shiffman <http://www.shiffman.net>

A basic smoke effect using a particle system Each particle is rendered as an alpha masked image

Created 2 May 2005

   
// Smoke Particle System 
// Daniel Shiffman <http://www.shiffman.net> 

ParticleSystem ps; 
Random generator; 
 
void setup() { 
  size(200,200); 
  framerate(30); 
  colorMode(RGB,255,255,255,100); 
  generator = new Random(); 
    
  // Create an alpha masked image to be applied as the particle's texture 
  PImage msk = loadImage("texture.gif"); 
  PImage img = new PImage(msk.width,msk.height); 
  for (int i = 0; i < img.pixels.length; i++) img.pixels[i] = color(255); 
  img.mask(msk); 
 
  ps = new ParticleSystem(0,new Vector3D(width/2,height-20),img); 
  smooth(); 
} 
 
void draw() { 
  background(0); 
  
  // Calculate a "wind" force based on mouse horizontal position 
  float dx = (mouseX - width/2) / 1000.0; 
  Vector3D wind = new Vector3D(dx,0,0); 
  ps.add_force(wind); 
  ps.run(); 
  for (int i = 0; i < 2; i++) { 
    ps.addParticle(); 
  } 
  
  // Draw an arrow representing the wind force 
  drawVector(wind, new Vector3D(width/2,50,0),500); 
 
} 
 
// Renders a vector object 'v' as an arrow and a location 'loc' 
void drawVector(Vector3D v, Vector3D loc, float scayl) { 
  pushMatrix(); 
  float arrowsize = 4; 
  // Translate to location to render vector 
  translate(loc.x,loc.y); 
  stroke(255); 
  // Call vector heading function to get direction (note that pointing up is a heading of 0) and rotate 
  rotate(v.heading2D()); 
  // Calculate length of vector & scale it to be bigger or smaller if necessary 
  float len = v.magnitude()*scayl; 
  // Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction) 
  line(0,0,len,0); 
  line(len,0,len-arrowsize,+arrowsize/2); 
  line(len,0,len-arrowsize,-arrowsize/2); 
  popMatrix(); 
} 
 
 
 
// A simple Particle class, renders the particle as an image 
 
class Particle { 
  Vector3D loc; 
  Vector3D vel; 
  Vector3D acc; 
  float timer; 
  PImage img; 
 
  // One constructor 
  Particle(Vector3D a, Vector3D v, Vector3D l, PImage img_) { 
    acc = a.copy(); 
    vel = v.copy(); 
    loc = l.copy(); 
    timer = 100.0; 
    img = img_; 
  } 
 
  // Another constructor (the one we are using here) 
  Particle(Vector3D l,PImage img_) { 
    acc = new Vector3D(0.0,0.0,0.0); 
    float x = (float) generator.nextGaussian()*0.3f; 
    float y = (float) generator.nextGaussian()*0.3f - 1.0f; 
    vel = new Vector3D(x,y,0); 
    loc = l.copy(); 
    timer = 100.0; 
    img = img_; 
  } 
 
  void run() { 
    update(); 
    render(); 
  } 
  
  // Method to apply a force vector to the Particle object 
  // Note we are ignoring "mass" here 
  void add_force(Vector3D f) { 
    acc.add(f); 
  }  
 
  // Method to update location 
  void update() { 
    vel.add(acc); 
    loc.add(vel); 
    timer -= 2.5; 
    acc.setXY(0,0); 
  } 
 
  // Method to display 
  void render() { 
    imageMode(CORNER); 
    tint(255,timer); 
    image(img,loc.x-img.width/2,loc.y-img.height/2); 
  } 
 
  // Is the particle still useful? 
  boolean dead() { 
    if (timer <= 0.0) { 
      return true; 
    } else { 
      return false; 
    } 
  } 
} 
 
 
// A class to describe a group of Particles 
// An ArrayList is used to manage the list of Particles 
 
class ParticleSystem { 
 
  ArrayList particles;    // An arraylist for all the particles 
  Vector3D origin;        // An origin point for where particles are birthed 
  PImage img; 
  
  ParticleSystem(int num, Vector3D v, PImage img_) { 
    particles = new ArrayList();              // Initialize the arraylist 
    origin = v.copy();                        // Store the origin point 
    img = img_; 
    for (int i = 0; i < num; i++) { 
      particles.add(new Particle(origin, img));    // Add "num" amount of particles to the arraylist 
    } 
  } 
 
  void run() { 
    // Cycle through the ArrayList backwards b/c we are deleting 
    for (int i = particles.size()-1; i >= 0; i--) { 
      Particle p = (Particle) particles.get(i); 
      p.run(); 
      if (p.dead()) { 
        particles.remove(i); 
      } 
    } 
  } 
  
  // Method to add a force vector to all particles currently in the system 
  void add_force(Vector3D dir) { 
    for (int i = particles.size()-1; i >= 0; i--) { 
      Particle p = (Particle) particles.get(i); 
      p.add_force(dir); 
    } 
  
  }  
 
  void addParticle() { 
    particles.add(new Particle(origin,img)); 
  } 
 
  void addParticle(Particle p) { 
    particles.add(p); 
  } 
 
  // A method to test if the particle system still has particles 
  boolean dead() { 
    if (particles.isEmpty()) { 
      return true; 
    } else { 
      return false; 
    } 
  } 
 
} 
 
 
public class Vector3D { 
  public float x; 
  public float y; 
  public float z; 
 
  Vector3D(float x_, float y_, float z_) { 
    x = x_; y = y_; z = z_; 
  } 
 
  Vector3D(float x_, float y_) { 
    x = x_; y = y_; z = 0f; 
  } 
  
  Vector3D() { 
    x = 0f; y = 0f; z = 0f; 
  } 
 
  void setX(float x_) { 
    x = x_; 
  } 
 
  void setY(float y_) { 
    y = y_; 
  } 
 
  void setZ(float z_) { 
    z = z_; 
  } 
  
  void setXY(float x_, float y_) { 
    x = x_; 
    y = y_; 
  } 
  
  void setXYZ(float x_, float y_, float z_) { 
    x = x_; 
    y = y_; 
    z = z_; 
  } 
 
  void setXYZ(Vector3D v) { 
    x = v.x; 
    y = v.y; 
    z = v.z; 
  } 
  public float magnitude() { 
    return (float) Math.sqrt(x*x + y*y + z*z); 
  } 
 
  public Vector3D copy() { 
    return new Vector3D(x,y,z); 
  } 
 
  public Vector3D copy(Vector3D v) { 
    return new Vector3D(v.x, v.y,v.z); 
  } 
  
  public void add(Vector3D v) { 
    x += v.x; 
    y += v.y; 
    z += v.z; 
  } 
 
  public void sub(Vector3D v) { 
    x -= v.x; 
    y -= v.y; 
    z -= v.z; 
  } 
 
  public void mult(float n) { 
    x *= n; 
    y *= n; 
    z *= n; 
  } 
 
  public void div(float n) { 
    x /= n; 
    y /= n; 
    z /= n; 
  } 
  
  /*public float dot(Vector3D v) { 
    //implement DOT product 
  }*/ 
  
  /*public Vector3D cross(Vector3D v) { 
    //implement CROSS product 
  }*/ 
 
  public void normalize() { 
    float m = magnitude(); 
    if (m > 0) { 
       div(m); 
    } 
  } 
 
  public void limit(float max) { 
    if (magnitude() > max) { 
      normalize(); 
      mult(max); 
    } 
  } 
 
  public float heading2D() { 
    float angle = (float) Math.atan2(-y, x); 
    return -1*angle; 
  } 
 
  public Vector3D add(Vector3D v1, Vector3D v2) { 
    Vector3D v = new Vector3D(v1.x + v2.x,v1.y + v2.y, v1.z + v2.z); 
    return v; 
  } 
 
  public Vector3D sub(Vector3D v1, Vector3D v2) { 
    Vector3D v = new Vector3D(v1.x - v2.x,v1.y - v2.y,v1.z - v2.z); 
    return v; 
  } 
 
  public Vector3D div(Vector3D v1, float n) { 
    Vector3D v = new Vector3D(v1.x/n,v1.y/n,v1.z/n); 
    return v; 
  } 
 
  public Vector3D mult(Vector3D v1, float n) { 
    Vector3D v = new Vector3D(v1.x*n,v1.y*n,v1.z*n); 
    return v; 
  } 
 
  public float distance (Vector3D v1, Vector3D v2) { 
    float dx = v1.x - v2.x; 
    float dy = v1.y - v2.y; 
    float dz = v1.z - v2.z; 
    return (float) Math.sqrt(dx*dx + dy*dy + dz*dz); 
  } 
 
} 
 
 
 
 
 
 







   
  Processing is an open project initiated by Ben Fry and Casey Reas  
  © Info