Confetti? (Lasercut Screen)

Screen

./wp-content/uploads/sites/2/2013/10/frame-0070.pdf
Confetti Screen 1

./wp-content/uploads/sites/2/2013/10/frame-0082.pdf
Confetti Screen 2

Description

This screen design was mostly just an interesting mistake that came about while I was working on my original screen concept. The basic way that the sketch works is that a set of uniform particles are placed at random locations in the window. Then, a repulsive force between the particles gradually pushes them apart. The particles draw their own trails as paths, and the stroke outliner helper function turns those paths into wider strokes. The sketch stops when the user presses ‘d’ and is recorded when the user presses ‘r’.

Code

Main

import oscP5.*;
import netP5.*;
import processing.pdf.*;

ArrayList myParticles;
boolean doneDrawing = false;

int margin;
boolean record = false;

void setup() {
  size(864, 864);
  myParticles = new ArrayList();

  margin = 50;

  for (int i=0; i<900; i++) {
    float rx = random(margin, width-margin);
    float ry = random(margin, height-margin);
    myParticles.add( new Particle(rx, ry));
  }
  smooth();
}

void mousePressed() {
  noLoop();
}
void mouseReleased() {
  loop();
}
void keyPressed() {
  if (key == 'd') {
    doneDrawing = true;
  }
  if (key == 'r') {
    record = true;
  }
}

void draw() {
  if (record) {
    // Note that #### will be replaced with the frame number. Fancy!
    beginRecord(PDF, "frame-####.pdf");
  }

  // background (255);
  float gravityForcex = 0;
  float gravityForcey = 0.02;
  float mutualRepulsionAmount = 3.0;

  if (doneDrawing == false) {
    // calculating repulsion and updating particles
    for (int i=0; i 1.0) {

          float componentInX = dx/dh;
          float componentInY = dy/dh;
          float proportionToDistanceSquared = 1.0/(dh*dh);

          float repulsionForcex = mutualRepulsionAmount * componentInX * proportionToDistanceSquared;
          float repulsionForcey = mutualRepulsionAmount * componentInY * proportionToDistanceSquared;

          ithParticle.addForce( repulsionForcex, repulsionForcey); // add in forces
          jthParticle.addForce(-repulsionForcex, -repulsionForcey); // add in forces
        }
      }
    }

    for (int i=0; i

Particle

class Particle {
  //float px;
  //float py;
  float vx;
  float vy;
  PVector currentPosition;
  ArrayList trail;
  int trailWidth;
  float damping;
  float mass;
  boolean bLimitVelocities = true;
  boolean bPeriodicBoundaries = false;

  // Constructor for the Particle
  Particle (float x, float y) {
    currentPosition = new PVector(x, y);
    vx = vy = 0;
    damping = 0.96;
    mass = 1.0;
    trail = new ArrayList();
    trailWidth = 5;
  }

  // Add a force in. One step of Euler integration.
  void addForce (float fx, float fy) {
    float ax = fx / mass;
    float ay = fy / mass;
    vx += ax;
    vy += ay;
  }

  // Update the position. Another step of Euler integration.
  void update() {
    vx *= damping;
    vy *= damping;
    limitVelocities();
    handleBoundaries();
    currentPosition.x += vx;
    currentPosition.y += vy;
    PVector logPosition = new PVector(currentPosition.x, currentPosition.y);
    trail.add(logPosition);
    println(trail.size());
  }

  void limitVelocities(){
    if (bLimitVelocities){
      float speed = sqrt(vx*vx + vy*vy);
      float maxSpeed = 10;
      if (speed > maxSpeed){
        vx *= maxSpeed/speed;
        vy *= maxSpeed/speed;
      }
    }
  }

  void handleBoundaries() {
    // wraparound
    if (bPeriodicBoundaries) {
      if (currentPosition.x > width - margin ) currentPosition.x -= width;
      if (currentPosition.x < margin     ) currentPosition.x += width;
      if (currentPosition.y > height - margin) currentPosition.y -= height;
      if (currentPosition.y < margin     ) currentPosition.y += height;
    }
    // bounce
    else {
      if (currentPosition.x > width - margin ) vx = -vx;
      if (currentPosition.x < margin     ) vx = -vx;
      if (currentPosition.y > height - margin) vy = -vy;
      if (currentPosition.y < margin     ) vy = -vy;
    }
  }

 /* I want my particles to draw their trails but can't figure out how. Thoughts? */
  void render() {
    drawStrokeOutline(trail, trailWidth);
  }
}

Simple Stroke Outliner

void drawStrokeOutline(ArrayList points, int strokeWidth) {
  noFill();
  stroke(0);
  strokeWeight(1);

  beginShape();
  // iterate over points in array going from to back, drawing shape
  for (int i=0; i < points.size(); i++) {
    PVector currentPoint = points.get(i);
    vertex(currentPoint.x, currentPoint.y);
  }
  endShape();

  beginShape();
  // then go backwards, and shift all points down by strokeWidth, 
  // continuing the same shape
  int lastIndex = points.size() - 1;
  for (int i=lastIndex; i >=0; i--) {
    PVector currentPoint = points.get(i);
    vertex(currentPoint.x - strokeWidth, currentPoint.y + (strokeWidth*0.5));
  }
  endShape();

  /* delete later
   stroke(0);
   PVector sPoint = points.get(points.size() - 1);
   line(sPoint.x, sPoint.y, sPoint.x - strokeWidth, sPoint.y + (strokeWidth*0.5));
  */

  if (doneDrawing) {  // draw start cap
    stroke(0);
    PVector startPoint = points.get(0);
    line(startPoint.x, startPoint.y, startPoint.x - strokeWidth, startPoint.y + (strokeWidth*0.5));

    // close line by drawing caps
    PVector endPoint = points.get(lastIndex);
    line(endPoint.x, endPoint.y, endPoint.x - strokeWidth, endPoint.y + (strokeWidth*0.5));
  }
}

Comments are closed.