• fullscreen
  • CloudsAreLooming.pde
  • Controls.pde
  • Particle.pde
  • import peasy.*;
    import toxi.geom.*;
    
    Vec3D globalOffset, avg, cameraCenter;
    public float neighborhood, viscosity, speed, turbulence, cameraRate, rebirthRadius, spread, independence, dofRatio;
    public int n, rebirth;
    public boolean averageRebirth, paused;
    Vector particles;
    
    Plane focalPlane;
    
    PeasyCam cam;
    
    boolean recording;
    
    void setup() {
      size(720, 480, P3D);
      cam = new PeasyCam(this, 1600);
      
      setParameters();
      makeControls();
      
      cameraCenter = new Vec3D();
      avg = new Vec3D();
      globalOffset = new Vec3D(0, 1. / 3, 2. / 3);
      
      particles = new Vector();
      for(int i = 0; i < n; i++)
        particles.add(new Particle());
    }
    
    void draw() {  
      avg = new Vec3D();
      for(int i = 0; i < particles.size(); i++) {
        Particle cur = ((Particle) particles.get(i));
        avg.addSelf(cur.position);
      }
      avg.scaleSelf(1. / particles.size());
      
      cameraCenter.scaleSelf(1 - cameraRate);
      cameraCenter.addSelf(avg.scale(cameraRate));
      
      translate(-cameraCenter.x, -cameraCenter.y, -cameraCenter.z);
      
      float[] camPosition = cam.getPosition();
      focalPlane = new Plane(avg, new Vec3D(camPosition[0], camPosition[1], camPosition[2]));
    
      background(0);
      noFill();
      hint(DISABLE_DEPTH_TEST);
      for(int i = 0; i < particles.size(); i++) {
        Particle cur = ((Particle) particles.get(i));
        if(!paused)
          cur.update();
        cur.draw();
      }
      
      for(int i = 0; i < rebirth; i++)
        randomParticle().resetPosition();
      
      if(particles.size() > n)
        particles.setSize(n);
      while(particles.size() < n)
        particles.add(new Particle());
        
      globalOffset.addSelf(
        turbulence / neighborhood,
        turbulence / neighborhood,
        turbulence / neighborhood);
    }
    
    Particle randomParticle() {
      return ((Particle) particles.get((int) random(particles.size())));
    }
    
    void keyPressed() {
      if(key == 'p')
        paused = !paused;
    }
    
    import controlP5.*;
    
    public ControlP5 control;
    public ControlWindow w;
    
    void setParameters() {
      n = 10000;
      dofRatio = 50;
      neighborhood = 700;
      speed = 24;
      viscosity = .1;
      spread = 100;
      independence = .15;
      rebirth = 0;
      rebirthRadius = 250;
      turbulence = 1.3;
      cameraRate = .1;
      averageRebirth = false;
    }
    
    void makeControls() {
      control = new ControlP5(this);
      
      w = control.addControlWindow("controlWindow", 10, 10, 350, 140);
      w.hideCoordinates();
      w.setTitle("Flocking Parameters");
      
      int y = 0;
      control.addSlider("n", 1, 20000, n, 10, y += 10, 256, 9).setWindow(w);
      control.addSlider("dofRatio", 1, 200, dofRatio, 10, y += 10, 256, 9).setWindow(w);
      control.addSlider("neighborhood", 1, width * 2, neighborhood, 10, y += 10, 256, 9).setWindow(w);
      control.addSlider("speed", 0, 100, speed, 10, y += 10, 256, 9).setWindow(w);
      control.addSlider("viscosity", 0, 1, viscosity, 10, y += 10, 256, 9).setWindow(w);
      control.addSlider("spread", 50, 200, spread, 10, y += 10, 256, 9).setWindow(w);
      control.addSlider("independence", 0, 1, independence, 10, y += 10, 256, 9).setWindow(w);
      control.addSlider("rebirth", 0, 100, rebirth, 10, y += 10, 256, 9).setWindow(w);
      control.addSlider("rebirthRadius", 1, width, rebirthRadius, 10, y += 10, 256, 9).setWindow(w);
      control.addSlider("turbulence", 0, 4, turbulence, 10, y += 10, 256, 9).setWindow(w);
      control.addToggle("paused", false, 10, y += 11, 9, 9).setWindow(w);
      control.setAutoInitialization(true);
    }
    
    
    Vec3D centeringForce = new Vec3D();
    
    class Particle {
      Vec3D position, velocity, force;
      Vec3D localOffset;
      Particle() {
        resetPosition();
        velocity = new Vec3D();
        force = new Vec3D();
        localOffset = Vec3D.randomVector();
      }
      void resetPosition() {
        position = Vec3D.randomVector();
        position.scaleSelf(random(rebirthRadius));
        if(particles.size() == 0)
          position.addSelf(avg);
        else
          position.addSelf(randomParticle().position);
      }
      void draw() {
        float distanceToFocalPlane = focalPlane.getDistanceToPoint(position);
        distanceToFocalPlane *= 1 / dofRatio;
        distanceToFocalPlane = constrain(distanceToFocalPlane, 1, 15);
        strokeWeight(distanceToFocalPlane);
        stroke(255, constrain(255 / (distanceToFocalPlane * distanceToFocalPlane), 1, 255));
        point(position.x, position.y, position.z);
      }
      void applyFlockingForce() {
        force.addSelf(
          noise(
            position.x / neighborhood + globalOffset.x + localOffset.x * independence,
            position.y / neighborhood,
            position.z / neighborhood)
            - .5,
          noise(
            position.x / neighborhood,
            position.y / neighborhood + globalOffset.y  + localOffset.y * independence,
            position.z / neighborhood)
            - .5,
          noise(
            position.x / neighborhood,
            position.y / neighborhood,
            position.z / neighborhood + globalOffset.z + localOffset.z * independence)
            - .5);
      }
      void applyViscosityForce() {
        force.addSelf(velocity.scale(-viscosity));
      }
      void applyCenteringForce() {
        centeringForce.set(position);
        centeringForce.subSelf(avg);
        float distanceToCenter = centeringForce.magnitude();
        centeringForce.normalize();
        centeringForce.scaleSelf(-distanceToCenter / (spread * spread));
        force.addSelf(centeringForce);
      }
      void update() {
        force.clear();
        applyFlockingForce();
        applyViscosityForce();
        applyCenteringForce();
        velocity.addSelf(force); // mass = 1
        position.addSelf(velocity.scale(speed));
      }
    }
    

    code

    tweaks (0)

    about this sketch

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

    license

    advertisement

    Kyle McDonald

    Clouds Are Looming

    Add to Faves Me Likey@! 238
    You must login/register to add this sketch to your favorites.

    Noise-based flocking with depth of field.

    'p' pauses the particles, mouse for rotation/translation/zoom. All other controls in the control window.

    Also on Vimeo http://www.vimeo.com/8479763

    dotlassie
    1 Jan 2010
    Would you kindly create a cross eye/parallel eye 3d version? :)
    Kyle McDonald
    1 Jan 2010
    That would be great! Is there a trick to doing this in Processing? If I were in OpenGL I would use two viewports or FBOs. In P3D I'm not quite sure how to approach it.
    Antoine Bonnin
    2 Jan 2010
    This is beautiful!
    amazing!
    excelent!
    Steven Kay
    4 Jan 2010
    great work!

    just stumbled across a cross-eye viewer on the hacks list...(both P3D and OpenGL versions) here:

    http://processing.org/hacks/hacks:stereo_viewing
    James Andino
    6 Jan 2010
    damit! its people like you and all your awsomilatude that keeps me.
    this is reeeely nice
    inspiring! the depth of field is really lovely.
    blaireko
    22 Nov 2010
    SO COOL!! and the Paramenter controllor window`s cool also!
    Eduardo Obieta
    17 Sep 2011
    wooow nice¡¡¡¡
    wow. i love the focus. totally awesome. camera lens swivel control to change focus would blow my mind... even more.
    Josue Page
    30 Jan 2012
    nice work!
    Very cool. I wondered what this would look like from the point of view of one of the particles, so I created this variation, "Flying with the Flock":

    http://openprocessing.org/visuals/?visualID=51963
    Yes the parameter panel helps a lot
    Matthew Pearson
    18 Apr 2012
    Nice, love the DOF effect! Looks like a pre-rendered effect, it's awesome that it's real time.
    Luiz Zanotello
    9 May 2012
    Splendid! Thanks for sharing this!
    L B
    7 Jun 2012
    Is it possible to add colour to it?
    Gottfried
    13 May 2013
    hello LB

    yes you can go to the "particle" sub sketch to line 27 and change the three colour values:

    void draw() {
    float distanceToFocalPlane = focalPlane.getDistanceToPoint(position);
    distanceToFocalPlane *= 1 / dofRatio;
    distanceToFocalPlane = constrain(distanceToFocalPlane, 1, 15);
    strokeWeight(distanceToFocalPlane);

    stroke(255, constrain(255 / (distanceToFocalPlane * distanceToFocalPlane), 1, 255));
    stroke(240,196,39);//change colour here+for instance (240,19,39)++it will be red++
    Gottfried
    13 May 2013
    hello Kyle
    formidable:

    i want to make use of my own image.jpg to become "my particles" instead of the yellow ones...

    i tried out solutions, but "my particle" is slowing the whole sketch down untile "my particles"
    got of the screen and it would never come back.....

    any better solutions ?
    Brent
    21 Oct 2013
    This is such an excellent sketch! I'm just beginning to learn / hack my way through Processing. How would one go about changing the particle system to respond to variables based on mouseX and mouseY instead of the controls in the controlP5 library? Thanks!
    Ian Pilon
    7 Dec 2013
    I can hardly wait until I can code something as fun as this! I really like Josh's remix on this sketch too.
    So glad I'm learning Processing, nice work Kyle!
    Ingo Butsch
    19 Mar 2014
    Hey guys,

    the sketch is not working in processing 2.0.3
    it prints: "Cannot find a class or type named "Vector"

    can somebody probably help me with this?
    Thx.
    Ingo Butsch
    26 Mar 2014
    UPDATE:

    import java.util.*;
    solved the problem
    jude
    26 Mar 2014
    Hellloo

    I keep on getting

    SetParameter ()

    "The Function setParameter () does not exist."

    anyone know what I can do to sort this.

    thanks.
    You need to login/register to comment.