class CreditsScreen{
int frame = 0;
int frames = 22 * rate;
boolean alive = true;
int a1,a2,a3 = 0;
int scrollRate = 1;
PImage cred1, cred2, cred3;
CreditsScreen(){
alive = true;
cred1 = loadImage("images/Creds1.jpg");
cred2 = loadImage("images/Creds2.jpg");
cred3 = loadImage("images/Creds3.jpg");
}
void update(){
a1+=10;
if(frame>=40){
a2+=10;
}
if(frame>=80){
a3+=10;
}
if(frame>=400){
//scrollY-=scrollRate;
}
fill(0, a1);
rect(0,0,width,height);
image(cred1, 0, 0);
fill(0, a2);
rect(0,0,width,height);
image(cred2, 0, 0);
fill(0, a3);
rect(0,0,width,height);
image(cred3, 0, 0);
if(frame<frames){
frame++;
}else{
/// kill(); end of show resart
}
}
void kill(){
alive = false;
//clear it
}
}
// ****** IMPORTANCE OF KINECTION v1.0 *****
// RHYS TURNER | www.aenigma.com.au | rhys@aenigma.com.au
// AMNESIA | RAZORFISH
// Part of a bumper video for TedX Sydney 2012 using croud
// recording to create particle could interactions.
//
// ****** NOTES ******
//
// Contributed Processing libraries required include Kinect OoenCV
// IMPORT ARE IN IMPORT TAB
// PROPERTIES ARE IN PROPERTIES TAB
//
// ****** KEYBOARD CONTROLS *********
//
// a - increase maximum & minimum kinect distance
// z - decrease maximum & minimum kinect distqance
// s - increase minimum OpenCV blob size
// x - decrease minimum OpenCV blob size
// d - increase max OpenCV blob size
// c - decrease max OpenCV blob size
// i - start stop save image sequence
// q - show hide settings & output window
// n - start record frame particle and blob data
// m - stop record frame particle and blob data
//
//
import processing.opengl.*;
import processing.video.*;
import hypermedia.video.*;
import librarytests.*;
import org.openkinect.*;
import org.openkinect.processing.*;
import java.awt.*;
import toxi.physics2d.constraints.*;
import toxi.physics2d.behaviors.*;
import toxi.physics2d.*;
import toxi.geom.*;
import toxi.math.*;
import ddf.minim.*;
import controlP5.*;
String now;
//MODE
boolean PLAYBACK_MODE = true;
float blobProximity = width;
boolean finalSoundPlayed = false;
///
//save
PrintWriter output;
///ROPE COUNT
int ropesNum = 10;
int ropesTotal = 50;
///////////////
// INIT STAGES
boolean titleStarted = false;
boolean kinectStarted = false;
boolean ropesStarted = false;
boolean spotsStarted = false;
boolean physicsStarted = false;
boolean soundStarted = false;
boolean finalStarted = false;
boolean creditsStarted = false;
boolean saveStarted = false;
boolean moreRopesStarted = false;
boolean kinected = false;
boolean recordMode = true;
int currentFrame = 0;
int soundFrame = 0;
int playSoundRate = 20;
int soundGain = -16;
////////////////
//TITLE SCREEN
PFont titleFont;
TitleScreen titleScreen;
PFont creditsFont;
CreditsScreen creditsScreen;
////////////////
///MODE/STAGE/SCREES
int mode = 0;
////////////////
//XML
XMLElement frames;
////////////////
//FRAME RATE
int rate = 20;
////////////////////////
// Kinect Library object
Kinect kinect;
OpenCV cv;
PImage img;
ArrayList<PVector> pointCloudLow = new ArrayList<PVector>();
ArrayList<PVector> pointCloudHigh = new ArrayList<PVector>();
ArrayList<PVector> pointCloudFinal = new ArrayList<PVector>();
ArrayList<Point> hands = new ArrayList<Point>();
ArrayList<Rect> hands_rect = new ArrayList<Rect>();
ArrayList<Rope> ropes = new ArrayList<Rope>();
//float a = 0;
// Size of kinect image
int w = 640;
int h = 480;
///SIZE OF OUTPUT IAMGE
//int OUTPUT_W = 1280;
//int OUTPUT_H = 720;
int OUTPUT_W = 640;
int OUTPUT_H = 480;
//UPSCALE FACTOR
float factorAv = (float(OUTPUT_H/h) + float(OUTPUT_W/w))/2;
float factorX = float(OUTPUT_W/w);
float factorY = float(OUTPUT_H/h);
///DISTANCE THREASHOD
int minDist = 800;
int maxDist = 1000;
int minBlobSize = 16000;
int maxBlobSize = 32000;
// We'll use a lookup table so that we don't have to repeat the math over and over
float[] depthLookUp = new float[2048];
int NUM_PARTICLES = 20;
int REST_LENGTH = 5;
VerletPhysics2D physics;
VerletParticle2D head,tail;
VerletPhysics2D finalPhysics;
//////////////////
// The Minim Stuff
AudioPlayer player1;
Minim minim;
AudioSample sample1, sample2, sample3, sample4, sample5, sample6, sample7, sample8, sample9, sample10, sampleExplosion1, sampleExplosion2;
boolean playSample = false;
int coundDelay = 0;
boolean RECORDING = false;
boolean SAVING;
int saveCount;
int tension = 1;
boolean SETTINGS = false;
boolean SAVING_VIDEO;
Point BLOB_CENTOID;
Point[] BLOB_POINTS;
float BLOB_AREA;
float BLOB_PIXELS;
Rect BLOB_RECT;
int ropesCount = 4;
int cloudRes = 10;
///////////////////////////////////////////////////////
//// ----------- PROCESSING SCREEN : INIT -----------
///////////////////////////////////////////////////////
void initProcessing(){
size(640,480,P3D);
textMode(SCREEN);
frameRate(rate);
}
///////////////////////////////////////////////////////
//// ----------- FONTS : INIT -----------
///////////////////////////////////////////////////////
void initFonts(){
titleFont = loadFont("fonts/Serif-28.vlw");
creditsFont = loadFont("fonts/Serif-20.vlw");
}
///////////////////////////////////////////////////////
//// ----------- TITLE SCREEN : INIT -----------
///////////////////////////////////////////////////////
void initTitleScreen(){
//init title screen
titleScreen = new TitleScreen();
}
void initCreditsScreen(){
//init title screen
creditsScreen = new CreditsScreen();
}
///////////////////////////////////////////////////////
//// ----------- PHYSICS : INIT -----------
///////////////////////////////////////////////////////
void initPhysics(){
physics = new VerletPhysics2D();
physics.setDrag(0.05f);
physics.setWorldBounds(new Rect(0, 0, width, height));
// the NEW way to add gravity to the simulation, using behaviors
physics.addBehavior(new GravityBehavior(new Vec2D(0, 0.15f)));
}
///////////////////////////////////////////////////////
//// ----------- STRINGS : INIT -----------
///////////////////////////////////////////////////////
void initRopes(){
for (int i = 0; i < ropesTotal; i++) {
ropes.add(new Rope(physics, new Vec2D(),i));
}
}
///////////////////////////////////////////////////////
//// ----------- KINECT AND CV : INIT -----------
///////////////////////////////////////////////////////
void initKinectCV(){
kinect = new Kinect(this);
try {
kinect.start();
kinect.enableDepth(true);
// We don't need the grayscale image in this example
// so this makes it more efficient
kinect.processDepthImage(false);
kinected = true;
} catch (NullPointerException ex) {
println("Please plug your kinect!!!");
kinected = false;
}
// Lookup table for all possible depth values (0 - 2047)
for (int i = 0; i < depthLookUp.length; i++) {
depthLookUp[i] = rawDepthToMeters(i);
}
cv = new OpenCV(this);
cv.allocate(width,height);
}
///////////////////////////////////////////////////////
//// ----------- SOUND : INIT -----------
///////////////////////////////////////////////////////
void initSound(){
minim = new Minim(this);
//out = minim.getLineOut();
sample1 = minim.loadSample("wav/10.wav", 2048);
sample2 = minim.loadSample("wav/ab_foursteps-1.wav", 2048);
sample3 = minim.loadSample("wav/ab_foursteps-2.wav", 2048);
sample4 = minim.loadSample("wav/ab_foursteps-3.wav", 2048);
sample5 = minim.loadSample("wav/ab_foursteps-4.wav", 2048);
sample6 = minim.loadSample("wav/CrackleAdjusting.wav", 2048);
sample7 = minim.loadSample("wav/CrackleCrunch.wav", 2048);
sample8 = minim.loadSample("wav/Crackles1.wav",2048);
sample9 = minim.loadSample("wav/STATIC-EMF_1.wav", 2048);
sample10 = minim.loadSample("wav/STATIC-EMF_2.wav", 2048);
sampleExplosion1 = minim.loadSample("wav/CrackleCrunch.wav", 2048);
sampleExplosion2 = minim.loadSample("wav/jh_elek808.wav", 2048);
sample1.setGain(soundGain);
sample2.setGain(soundGain);
sample3.setGain(soundGain);
sample4.setGain(soundGain);
sample5.setGain(soundGain);
sample6.setGain(soundGain);
sample7.setGain(soundGain);
sample8.setGain(soundGain);
sample9.setGain(soundGain);
sample10.setGain(soundGain);
}
void initSave(){
// Create a new file in the sketch directory for each frame particle data
int s = second(); // Values from 0 - 59
int m = minute(); // Values from 0 - 59
int h = hour(); // Values from 0 - 23
int d = day(); // Values from 1 - 31
int mo = month(); // Values from 1 - 12
int y = year(); // 2003, 2004, 2005, etc.
now = new String(y+""+mo+""+d+""+h+""+m+""+s+"");
println("now = "+now);
String saveName = new String(now);
output = createWriter("images/"+mode+"_frames_"+now+".xml");
output.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
output.println("<frames>");
}
void setup() {
initProcessing();
initFonts();
initTitleScreen();
initCreditsScreen();
initSound();
}
void draw() {
currentFrame ++;
//print(" currentFrame: "+currentFrame/rate);
background(0);
img = new PImage(width,height);
fill(255);
modeSwitch();
saveImgSeq();
startRec();
//saveVideoSeq();
//stage 2 sound @48 seconds
//stage 3 sound @140 seconds
//stage 4 sound @200 seconds
if(PLAYBACK_MODE){
if(currentFrame/rate==48){
mode = 2;
}
if(currentFrame/rate==140){
mode = 3;
}
if(currentFrame/rate==200){
mode = 4;
}
}else{
if(blobProximity<width && blobProximity>500){
mode = 1;
}
if(blobProximity<500 && blobProximity>300){
mode = 2;
}
if(blobProximity<300 && blobProximity>100){
mode = 3;
}
if(blobProximity<100 && blobProximity>0){
mode = 4;
}
}
}
void modeSwitch(){
//play.setVolume(0.5);
switch(mode){
case 0:
//TITLE SCREEN LOOP
if(!titleStarted){
titleStarted = true;
//kinectStarted = false;
ropesStarted = false;
moreRopesStarted = false;
finalStarted = false;
creditsStarted = false;
println("mode:"+mode+" titleStarted "+titleStarted);
}
titleScreenUpdate();
break;
case 1:
if(!kinectStarted){
titleStarted = false;
kinectStarted = true;
ropesStarted = false;
moreRopesStarted = false;
finalStarted = false;
creditsStarted = false;
println("mode:"+mode+" kinectStarted "+kinectStarted);
initKinectCV();
}
ropesNum = 1;
update1();
break;
case 2:
if(!ropesStarted){
titleStarted = false;
//kinectStarted = false;
ropesStarted = true;
moreRopesStarted = false;
creditsStarted = false;
finalStarted = false;
println("mode:"+mode+" ropesStarted "+ropesStarted);
initPhysics();
initRopes();
playSoundRate = 20;
}
ropesNum = 1;
update2();
break;
case 3:
if(!moreRopesStarted){
titleStarted = false;
// kinectStarted = false;
ropesStarted = false;
moreRopesStarted = true;
creditsStarted = false;
finalStarted = false;
println("mode:"+mode+" stage 3");
playSoundRate = 5;
ropesNum = 10;
}
update3();
break;
case 4:
//EXPLODE
if(!finalStarted){
titleStarted = false;
//kinectStarted = false;
ropesStarted = false;
moreRopesStarted = false;
creditsStarted = false;
finalStarted = true;
println("mode:"+mode+" finalStarted "+finalStarted);
getPointsFinal();
sampleExplosion2.trigger();
}
update4();
break;
case 5:
//CREDIT SCREEN LOOP
if(!creditsStarted){
creditsStarted = true;
titleStarted = false;
ropesStarted = false;
moreRopesStarted = false;
finalStarted = true;
println("mode:"+mode+" creditsStarted "+creditsStarted);
}
creditsScreenUpdate();
break;
}
}
///////////////////////////////////////
// -------- UPDATE LOOPS -------- /////
///////////////////////////////////////////////////////
//// --------- titleScreenUpdate : LOOP -------
///////////////////////////////////////////////////////
void titleScreenUpdate(){
if(titleScreen.alive){
titleScreen.update();
////println(titleScreen.frame);
}else{
mode = 1;
titleScreen = null;
}
}
void creditsScreenUpdate(){
if(creditsScreen.alive){
creditsScreen.update();
////println(titleScreen.frame);
}else{
//mode = 1;
creditsScreen = null;
}
}
///////////////////////////////////////////////////////
//// --------- UPDATE : LOOP -------
///////////////////////////////////////////////////////
void update1(){
if(!kinected){
textFont(titleFont);
fill(255);
text("Please plug your kinect and refresh.", 100, 100, 400, 200, 0);
}else{
update();
updateCloud();
}
}
///////////////////////////////////////////////////////
//// --------- UPDATE : LOOP -------
///////////////////////////////////////////////////////
void update2(){
//ropesCount = 1;
update();
updateCloud();
updateStrings();
}
///////////////////////////////////////////////////////
//// --------- UPDATE : LOOP -------
///////////////////////////////////////////////////////
void update3(){
//ropesCount = 10;
update();
updateCloud();
updateStrings();
}
///////////////////////////////////////////////////////
//// --------- UPDATE : LOOP -------
///////////////////////////////////////////////////////
void update4(){
//update();
coundDelay++;
//if(coundDelay == 1*rate){
if(!finalSoundPlayed){
finalSoundPlayed = true;
sampleExplosion1.trigger();
}
//print(" coundDelay : "+coundDelay);
finalPhysics.update();
for(Iterator i=finalPhysics.particles.iterator(); i.hasNext();) {
VerletParticle2D p=(VerletParticle2D)i.next();
point(p.x,p.y);
}
}
void update(){
settingsWin();
background(0);
}
void updateCloud(){
getPoints();
pushMatrix();
translate(width/2, height/2, 0);
//// --------- DRAW MAIN LOW POINT CLOUD
stroke(255);
////print("----- new low point cloud -----");
int factor = 600;
for(int i = 0; i < pointCloudLow.size();i++) {
PVector v = pointCloudLow.get(i);
pushMatrix();
translate(v.x*factor, v.y*factor, factor-v.z*factor);
point(0,0);
popMatrix();
}
popMatrix();
}
void updateStrings(){
//// --------- use "hands" to mark hands with circles
fill(200);
noStroke();
for(int i=0; i < hands.size(); i++){
Point pt = hands.get(i);
pushMatrix();
translate(pt.x*OUTPUT_W/w, pt.y*OUTPUT_H/h);
float xpos = pt.x;
float ypos = pt.y;
if(i==0){
fill(255,0,0);
ellipse(0,0,5,5);
}else if(i==1){
fill(255,0,0);
ellipse(0,0,5,5);
}else{
for (int j = 0; j < 10; j++) {
}
}
popMatrix();
// MAKE SOUND
triggerSound();
}
//DRAW ROPES
if(hands.size()>1){
for (int j = 0; j < ropes.size(); j++) {
if(j<ropesNum){
PVector pt1 = new PVector(hands.get(0).x, hands.get(0).y, 0);
PVector pt2 = new PVector(hands.get(1).x ,hands.get(1).y, 0);
ropes.get(j).updateHead(new Vec2D(pt1.x + j*-random(0,3), pt1.y + j*-random(0,3)));
ropes.get(j).updateTail(new Vec2D(pt2.x + j*-random(0,3), pt2.y + j*-random(0,3)));
blobProximity = getProximity(pt1.y, pt2.y);//absolute value of the two points
}
}
}else{
blobProximity = width;
}
updatePhysics();
}
void updatePhysics(){
//// --------- UPDATE PHYSICS
physics.update();
}
///////////////////////////////////////////////////////
//// ----------- POINTS : LOOP -----------
///////////////////////////////////////////////////////
void getPoints(){
int[] depth = kinect.getRawDepth();
pointCloudLow.clear();
//// ----------- POINTS : LOOP -----------
for(int x=0; x<w; x+=cloudRes) {
for(int y=0; y<h; y+=cloudRes) {
int offset = w-x-1+y*w;
// Convert kinect data to world xyz coordinate
int rawDepth = depth[offset];
if(rawDepth>minDist && rawDepth<maxDist){
PVector v = depthToWorld(x, y, rawDepth);
pointCloudLow.add(v);
}
}
}
pointCloudHigh.clear();
/// blob track ---
for(int x=0; x<w; x++) {
for(int y=0; y<h; y++) {
int offset = w-x-1+y*w;
int rawDepth = depth[offset];
if(rawDepth>minDist && rawDepth<maxDist){
PVector v = depthToWorld(x, y, rawDepth);
pointCloudHigh.add(v);
img.set(x,y,255);
}
}
}
//------------------------- Blob extraction -----------------------------
cv.copy(img);
Blob[] blobs = cv.blobs(minBlobSize,maxBlobSize*2,5,false);
hands.clear();
hands_rect.clear();
for(int i = 0; i < blobs.length; i++){
BLOB_RECT = new Rect(blobs[i].rectangle.x, blobs[i].rectangle.y, blobs[i].rectangle.width, blobs[i].rectangle.height);
BLOB_POINTS = blobs[i].points;
BLOB_AREA = blobs[i].area;
Point centroid = blobs[i].centroid;
hands.add(centroid);
hands_rect.add(BLOB_RECT);
}
}
void getPointsFinal(){
pointCloudFinal.clear();
int[] depth = kinect.getRawDepth();
//// ----------- POINTS : FINAL -----------
for(int x=0; x<w; x+=cloudRes) {
for(int y=0; y<h; y+=cloudRes) {
int offset = w-x-1+y*w;
//Convert kinect data to world xyz coordinate
int rawDepth = depth[offset];
if(rawDepth>minDist && rawDepth<maxDist){
//PVector v = new PVector(x, y, rawDepth);
PVector v = depthToWorld(x, y, rawDepth);
pointCloudFinal.add(v);
}
}
}
//println("pointCloudFinal pointCloudFinal "+pointCloudFinal);
finalPhysics = new VerletPhysics2D();
finalPhysics.setWorldBounds(new Rect(0,0,width,height));
finalPhysics.addBehavior(new GravityBehavior(new Vec2D(50, 0.15f)));
for(int i=0; i<pointCloudFinal.size(); i++) {
VerletParticle2D p = new VerletParticle2D((pointCloudFinal.get(i).x*300)+(width/2), (pointCloudFinal.get(i).y*300)+(height/2));
finalPhysics.addBehavior(new AttractionBehavior(p, 20, -1.2f, 0.1f));
finalPhysics.addParticle(p);
}
}
///////////////////////////////////////////////////////
//// --------- STRINGS DRAW -----------
///////////////////////////////////////////////////////
void drawRopes(){
stroke(255,255,255);
noFill();
beginShape();
pushMatrix();
translate(0,0);
for(Iterator i = physics.particles.iterator(); i.hasNext();){
VerletParticle2D p = (VerletParticle2D)i.next();
vertex(p.x, p.y);
}
popMatrix();
endShape();
}
///////////////////////////////////////////////////////
//// save img
///////////////////////////////////////////////////////
void startRec(){
if( RECORDING ){
if(!saveStarted){
saveStarted = true;
saveCount ++;
}
}
}
void stopRec(){
if( RECORDING ){
RECORDING = false;
if(saveStarted){
saveStarted = false;
}
}
}
///////////////////////////////////////////////////////
//// save img
///////////////////////////////////////////////////////
void saveImgSeq(){
if( SAVING ){
saveFrame( "img/image_" + saveCount + ".png" );
saveCount ++;
}
}
///////////////////////////////////////////////////////
//// SEWTTINGS WIN : LOOP
///////////////////////////////////////////////////////
void settingsWin(){
if( SETTINGS ){
fill(255, 100);
noStroke();
rect(0,0,width,100);
debug();
}
}
///////////////////////////////////////////////////////
//// DEBUG : LOOP
///////////////////////////////////////////////////////
void debug(){
text("Kinect FR: " + (int)kinect.getDepthFPS()+" Processing FR: " + (int)frameRate+" Factor: "+factorAv+" h:"+h+" | w:"+w+" OUTPUT_H:"+OUTPUT_H+" | OUTPUT_W:"+OUTPUT_W
+"\nBLOB_CENTOID:"+BLOB_CENTOID+"\nBLOB_RECT:"+BLOB_RECT+"\nBLOB_POINTS:"+BLOB_POINTS+"\nBLOB_AREA:"+BLOB_AREA+"\nBLOB_PIXELS:"+BLOB_PIXELS+" blobProximity "+blobProximity,10,16);
}
///////////////////////////////////////////////////////
//// ----------- SOUND : TRIGGER -----------
///////////////////////////////////////////////////////
void triggerSound(){
int ranSound = (int)random(0, 11);
soundFrame++;
if(soundFrame>playSoundRate){
playSample = true;
soundFrame = 0;
}else{
playSample = false;
}
if(playSample){
switch(ranSound){
case 1:
sample1.trigger();
break;
case 2:
sample2.trigger();
break;
case 3:
sample3.trigger();
break;
case 4:
sample4.trigger();
break;
case 5:
sample5.trigger();
break;
case 6:
sample6.trigger();
break;
case 7:
sample7.trigger();
break;
case 8:
sample6.trigger();
break;
case 9:
sample9.trigger();
break;
case 10:
sample10.trigger();
break;
case 11:
//do nothing
}
}
}
////////////////////////////////////////////
/////// ---- HANDLERS -------//////////////
float getProximity(float p1y, float p2y){
return abs(p1y - p2y);
}
///////////////////////////////////////////////////////
//// -------- rawDepthToMeters : GETTER ----------
///////////////////////////////////////////////////////
// These functions come from: http://graphics.stanford.edu/~mdfisher/Kinect.html
float rawDepthToMeters(int depthValue) {
if (depthValue < 2047) {
return (float)(1.0 / ((double)(depthValue) * -0.0030711016 + 3.3309495161));
}
return 0.0f;
}
///////////////////////////////////////////////////////
//// -------- depthToWorld : GETTER --------------
///////////////////////////////////////////////////////
PVector depthToWorld(int x, int y, int depthValue) {
final double fx_d = 1.0 / 5.9421434211923247e+02;
final double fy_d = 1.0 / 5.9104053696870778e+02;
final double cx_d = 3.3930780975300314e+02;
final double cy_d = 2.4273913761751615e+02;
PVector result = new PVector();
double depth = depthLookUp[depthValue];//rawDepthToMeters(depthValue);
result.x = (float)((x - cx_d) * depth * fx_d);
result.y = (float)((y - cy_d) * depth * fy_d);
result.z = (float)(depth);
return result;
}
///////////////////////////////////////////////////////
//// ----------- stop : HANDLER -----------
///////////////////////////////////////////////////////
void stop() {
kinect.quit();
super.stop();
}
///////////////////////////////////////////////////////
//// ----------- keyPressed : HANDLER -----------
///////////////////////////////////////////////////////
void keyPressed() {
switch(key) {
case 'a'://increasse the max & min dist
minDist+=5;
maxDist+=5;
println("a - minDist:"+minDist+" maxDist:"+maxDist);
break;
case 'z'://decrease max & min dist
minDist-=5;
maxDist-=5;
println("z - minDist:"+minDist+" maxDist:"+maxDist);
break;
case 's':
minBlobSize+=100;
println("s - minBlobSize:"+minBlobSize);
break;
case 'x':
minBlobSize-=100;
println("x - minBlobSize:"+minBlobSize);
break;
case 'd':
maxBlobSize+=100;
println("d - maxBlobSize:"+maxBlobSize);
break;
case 'c':
maxBlobSize-=100;
println("c - maxBlobSize:"+maxBlobSize);
break;
case 'i'://save img bool
SAVING = !SAVING;
println("i - SAVING:"+SAVING);
break;
case 'q'://settings bool
SETTINGS = !SETTINGS;
break;
case '0':
mode = 0;
break;
case '1':
mode = 1;
break;
case '2':
mode = 2;
break;
case '3':
mode = 3;
break;
case '4':
mode = 4;
break;
case '5':
mode = 5;
break;
case 'n'://save bool
RECORDING = true;
//startRec();
println("startRec");
break;
case 'm'://stop bool
stopRec();
println("stopRec");
break;
}
}
class Rope{
int id;
VerletPhysics2D physics;
VerletParticle2D head,tail;
int NUM_PARTICLES = 20;
int REST_LENGTH = 10;
Boolean isAlive = false;
Rope(VerletPhysics2D _physics, Vec2D startPoint, int i){
id = i;
/// physics = _physics;
physics = new VerletPhysics2D();
physics.setDrag(0.05f);
physics.setWorldBounds(new Rect(0, 0, width, height));
head = new VerletParticle2D(startPoint.x,startPoint.y);
tail = new VerletParticle2D(random(-startPoint.x, startPoint.y), random(-startPoint.x, startPoint.y));
Vec2D stepDir = new Vec2D(1,1).normalizeTo(REST_LENGTH);
ParticleString2D s = new ParticleString2D(physics, startPoint, stepDir, NUM_PARTICLES, 1, 0.1);
head = s.getHead();
tail = s.getTail();
isAlive = true;
}
void updateHead(Vec2D headPoint){
head.set(headPoint.x, headPoint.y);
if(isAlive){
drawRope();
}
physics.update();
}
void updateTail(Vec2D tailPoint){
tail.set(tailPoint.x, tailPoint.y);
if(isAlive){
//drawRope();
}
// physics.update();
}
///////////////////////////////////////////////////////
//// --------- STRINGS DRAW -----------
///////////////////////////////////////////////////////
void drawRope(){
stroke(255,255,255);
noFill();
//line(head.x, head.y, tail.x, tail.y);
//noStroke();
beginShape();
for(Iterator i = physics.particles.iterator(); i.hasNext();){
VerletParticle2D p = (VerletParticle2D)i.next();
//print("Rope: {"+p.x+","+p.x+"}");
vertex(p.x, p.y);
}
endShape();
}
void kill(){
isAlive = false;
}
}
class TitleScreen{
int frame = 0;
int frames = 22 * rate;
float a = 0.0;
boolean alive = true;
int a1,a2,a3 = 0;
PImage title1, title2, title3, title4;
TitleScreen(){
alive = true;
title1 = loadImage("images/Title1.jpg");
}
void update(){
a1+=10;
if(frame>=40){
a2+=10;
}
if(frame>=80){
a3+=10;
}
if(frame>=400){
a += 10;
}
fill(0, a1);
rect(0,0,width,height);
image(title1, 0, 0);
if(frame<frames){
frame++;
}else{
kill();
}
}
void kill(){
alive = false;
//clear it
}
}
Part of a bumper video for TedX Sydney 2012 using crowd recording to create particle could interactions.
View the video here:
http://vimeo.com/43440340
Kinect based on examples & libs:
http://www.shiffman.net/p5/kinect/
http://ubaa.net/shared/processing/opencv/
Requires an XBox Kinect.