Framingham

This example is for Processing (BETA) version 149+. 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.

HSV Space by Ben Fry.

Arrange the pixels from live video into the HSV Color Cone.

 
 
import processing.opengl.*;
import processing.video.*;

Capture video;
int count;
boolean cheatScreen = true;

static final float BOX_SIZE        = 0.75;
static final float CONE_HEIGHT     = 1.2;
static final float MAX_RADIUS      = 10;
static final float ROT_INCREMENT   = 3.0;
static final float TRANS_INCREMENT = 1;
static final float STEP_AMOUNT     = 0.1;

Tuple[] farbe;
Tuple[] trans;

float[] hsb = new float[3];

float leftRightAngle;
float upDownAngle;
float fwdBackTrans;
float upDownTrans;
float leftRightTrans;
boolean motion;

boolean blobby = false;


public void setup() {
  size(640, 480, P3D);
  //size(screen.width, screen.height, OPENGL);

  video = new Capture(this, 40, 30, 15);
  count = video.width * video.height;

  sphereDetail(60);

  upDownTrans = 0;
  leftRightTrans = 0;
  motion = false;

  leftRightAngle = 101.501297;
  upDownAngle = -180.098694;
  fwdBackTrans = 14.800003;

  farbe = new Tuple[count];
  trans = new Tuple[count];
  for (int i = 0; i < count; i++) {
    farbe[i] = new Tuple();
    trans[i] = new Tuple();
  }
}


void draw() {
  background(0);

  if (!blobby) lights();

  pushMatrix();
  translate(width/2, height/2);
  scale(min(width, height) / 10.0);

  translate(0, 0, -20 + fwdBackTrans);
  rotateY(radians(36 + leftRightAngle)); //, 0, 1, 0);
  rotateX(radians(-228 + upDownAngle)); //, 1, 0, 0);

  if (blobby) {
    stroke(0.35, 0.35, 0.25, 0.15);
    wireCone(MAX_RADIUS, MAX_RADIUS * CONE_HEIGHT, 18, 18);
  } 
  else {
    stroke(0.35, 0.35, 0.25, 0.25);
    wireCone(MAX_RADIUS, MAX_RADIUS * CONE_HEIGHT, 180, 18);
  }

  noStroke();
  for (int i = 0; i < count; i++) {
    int pixelColor = video.pixels[i];
    int r = (pixelColor >> 16) & 0xff;
    int g = (pixelColor >> 8) & 0xff;
    int b = pixelColor & 0xff;
    Color.RGBtoHSB(r, g, b, hsb);

    float radius = hsb[1] * hsb[2];
    float angle = hsb[0] * 360.0 * DEG_TO_RAD;
    float nx = MAX_RADIUS * radius * cos(angle);
    float ny = MAX_RADIUS * radius * sin(angle);
    float nz = hsb[2] * MAX_RADIUS * CONE_HEIGHT;

    trans[i].set(trans[i].x - (trans[i].x - nx)*STEP_AMOUNT,
                 trans[i].y - (trans[i].y - ny)*STEP_AMOUNT,
                 trans[i].z - (trans[i].z - nz)*STEP_AMOUNT);

    farbe[i].set(farbe[i].x - (farbe[i].x - r)*STEP_AMOUNT,
                 farbe[i].y - (farbe[i].y - g)*STEP_AMOUNT,
                 farbe[i].z - (farbe[i].z - b)*STEP_AMOUNT);

    pushMatrix();
    farbe[i].phil();
    trans[i].tran();

    rotate(radians(45), 1, 1, 0);
    if (blobby) {
      sphere(BOX_SIZE * 2); //, 20, 20);
    } else {
      box(BOX_SIZE);
    }

    popMatrix();
  }
  popMatrix();

  if (motion) {
    upDownAngle--;
    leftRightAngle--;
  }

  if (cheatScreen) {
    image(video, 0, height - video.height);
  }
}


void captureEvent(Capture c) {
  c.read();
  c.loadPixels();
}


void keyPressed() {
  switch (key) {
  case 'g': 
    saveFrame(); 
    break;
  case 'c': 
    cheatScreen = !cheatScreen; 
    break;

  case 'm': 
    motion = !motion; 
    break;
  case '=': 
    fwdBackTrans += TRANS_INCREMENT; 
    break;
  case '-': 
    fwdBackTrans -= TRANS_INCREMENT; 
    break;
  case 'b': 
    blobby = !blobby; 
    break;
  }
}


void mouseDragged() {
  float dX, dY;

  switch (mouseButton) {
  case LEFT:  // left right up down
    dX = pmouseX - mouseX;
    dY = pmouseY - mouseY;
    leftRightAngle -= dX * 0.2;
    upDownAngle += dY * 0.4;
    break;

  case CENTER:
    dX = pmouseX - mouseX;
    dY = pmouseY - mouseY;
    leftRightTrans -= TRANS_INCREMENT * dX;
    upDownTrans -= TRANS_INCREMENT * dY;
    break;

  case RIGHT:  // in and out
    dY = (float) (pmouseY - mouseY);
    fwdBackTrans -= TRANS_INCREMENT * dY;
    break;
  }
}


void wireCone(float radius, float height, int stepX, int stepY) {
  int steps = 10;
  stroke(40);
  for (int i = 0; i < steps; i++) {
    float angle = map(i, 0, steps, 0, TWO_PI);
    float x = radius * cos(angle);
    float y = radius * sin(angle);
    line(x, y, height, 0, 0, 0);
  }
  noFill();
  pushMatrix();
  translate(0, 0, height);
  ellipseMode(CENTER_RADIUS);
  ellipse(0, 0, radius, radius);
  popMatrix();
}



// Simple vector class that holds an x,y,z position.

class Tuple {
  float x, y, z;

  public Tuple() { }

  public Tuple(float x, float y, float z) {
    set(x, y, z);
  }

  public void set(float x, float y, float z) {
    this.x = x;
    this.y = y;
    this.z = z;
  }
  
  public void target(Tuple another, float amount) {
    float amount1 = 1.0 - amount;
    x = x*amount1 + another.x*amount;
    y = y*amount1 + another.y*amount;
    z = z*amount1 + another.z*amount;
  }
  
  public void phil() {
    fill(x, y, z);
  }
  
  public void tran() {
    translate(x, y, z);
  }
}