• fullscreen
  • balls.pde
  • bands.pde
  • cilinders.pde
  • control.pde
  • controlP5.pde
  • floor.pde
  • hand.pde
  • kinect.pde
  • kinectUtilities.pde
  • lines.pde
  • particles.pde
  • class Ball{
      PVector pos;
      PVector vel;
      float rad;
        
      Ball(PVector tempPos, PVector tempVel, float tempRad){
        pos = tempPos.get();
        vel = tempVel.get();
        rad = tempRad;
      }
      
      void paint(color col){
        noStroke();
        fill(col);
        pushMatrix();
          translate(pos.x,pos.y,pos.z);
          sphere(rad);
        popMatrix();
      }
    
      void update(PVector g, float resistance){
        pos.add(vel);
        vel.mult(resistance);
        vel.add(g);
      }
    
      void contact(PVector[] map3D, boolean[] consImg, int xSize){
        float minDist = 10000;
        int minIndex = 0;
        
        for(int i = 0; i < consImg.length; i++){
          if(consImg[i]){
            PVector p = map3D[i];
            float distance = pos.dist(p) - rad;
            if((distance < minDist) && (distance > 0)){
              minDist = distance;
              minIndex = i;
            }
          }
        }
        if(minDist < 10){
          PVector closestPos = map3D[minIndex];
          PVector dir = PVector.sub(pos,closestPos);
          dir.normalize();
          dir.mult(25);
          vel.set(dir);
        }
      }
      
    }
    
    
    class Bands{
      PVector[] map3D;
      PImage rgbImg;
      boolean[] consImg; 
      PVector[] vel;
      int xSize;
      int ySize;
      int nPixels;
        
      Bands(PVector[] tempMap3D, PImage tempRGBimg, boolean[] tempConsImg, int tempXsize, int tempYsize){
        map3D = tempMap3D;
        rgbImg = tempRGBimg;
        consImg = tempConsImg;
        xSize = tempXsize;
        ySize = tempYsize;
        nPixels = consImg.length;
        vel = new PVector[nPixels];
        for(int i = 0; i < nPixels; i++){
          vel[i] = new PVector(0,0,0);
        }
      }
      
      void paint(color col, int gaps){
        noStroke();
        fill(col);
        PVector p, lp;
        int index, indexl;
        boolean started = false;
        PVector prevPoint = new PVector(0,0,0);
        float maxSep = 50;
        
        for(int y = 0; y < ySize-1; y+=(1+gaps)){
          for(int x = 0; x < xSize; x++){
            index = x + y*xSize;
            if(consImg[index]){
              p = map3D[index];
              if(!started){
                beginShape(TRIANGLE_STRIP);
                vertex(p.x,p.y,p.z);
                prevPoint.set(p);
                started = true;
              }
              else if(prevPoint.dist(p) < maxSep){  
                vertex(p.x,p.y,p.z);         
                prevPoint.set(p);
              }
              else{
                endShape();
                started = false;
                x--;
                continue;
              }           
              indexl = x + (y+1)*xSize;
              lp = map3D[indexl];
              if(consImg[indexl] && (p.dist(lp) < maxSep)){
                vertex(lp.x,lp.y,lp.z);
                if(x == xSize-1){
                  endShape();
                  started = false;
                }
              } 
              else{
                vertex(p.x,p.y,p.z);
                endShape();
                started = false;
              }
            }
            else if(started){
              endShape();
              started = false;
            }
          }
        }
      }
      
      void paint(int gaps){
        noStroke();
        PVector p, lp;
        int index, indexl;
        boolean started = false;
        PVector prevPoint = new PVector(0,0,0);
        float maxSep = 50;
    
        for(int y = 0; y < ySize-1; y+=(1+gaps)){
          for(int x = 0; x < xSize; x++){
            index = x + y*xSize;
            if(consImg[index]){
              p = map3D[index];
              fill(rgbImg.pixels[index]);
              if(!started){
                beginShape(TRIANGLE_STRIP);
                vertex(p.x,p.y,p.z);
                prevPoint.set(p);
                started = true;
              }
              else if(prevPoint.dist(p) < maxSep){  
                vertex(p.x,p.y,p.z);         
                prevPoint.set(p);
              }
              else{
                endShape();
                started = false;
                x--;
                continue;
              }           
              indexl = x + (y+1)*xSize;
              lp = map3D[indexl];
              if(consImg[indexl] && (p.dist(lp) < maxSep)){
                vertex(lp.x,lp.y,lp.z);
                if(x == xSize-1){
                  endShape();
                  started = false;
                }
              } 
              else{
                vertex(p.x,p.y,p.z);
                endShape();
                started = false;
              }
            }
            else if(started){
              endShape();
              started = false;
            }
          }
        }
      }
      
      void disolve(float yMin){
        PVector g = new PVector(0,-15,0);
    
        for(int i = 0; i < nPixels; i++){
          if(consImg[i] && ((map3D[i].y + vel[i].y) > yMin)){
            map3D[i].add(vel[i]);
            vel[i].add(g);
            //map3D[i].add(vel[i]);
            //vel[i].set(new PVector(0,map(p.y,yMin,900,-40,-4),0));
          }
        }
      }
      
      void explode(){
        PVector explodeAcc = new PVector(0,0,-10);
    
        for(int i = 0; i < nPixels; i++){
          if(consImg[i]){
            map3D[i].add(vel[i]);
            vel[i].add(explodeAcc);
          }
        }
      }
      
    }
    
    
    void cilinder(Vec3D p1, Vec3D p2, float rad1, float rad2, color col, float frac){
      int steps = 100;
      float ang = TWO_PI/float(steps);
      noStroke();
      fill(col);
    
      Vec3D v = p2.sub(p1).normalize();
      float a1 = atan2(v.z,sqrt(sq(v.x)+sq(v.y)));
      float a2 = atan2(v.y,v.x);
      Vec3D per = new Vec3D(-cos(a2)*sin(a1),-sin(a2)*sin(a1),cos(a1));
      Vec3D per1 = per.scale(rad1);
      Vec3D per2 = per.scale(rad2);
      Vec3D step = p2.sub(p1).scale(frac);
    
      beginShape(QUAD_STRIP);
        for(int i = 0; i <= steps; i++) {
          vertex(p1.x+step.x+per1.x,p1.y+step.y+per1.y,p1.z+step.z+per1.z);
          vertex(p2.x-step.x+per2.x,p2.y-step.y+per2.y,p2.z-step.z+per2.z);
          per1.rotateAroundAxis(v,ang);
          per2.rotateAroundAxis(v,ang);
        }
      endShape();
    }
    
    void connector(Vec3D p1, Vec3D p2, Vec3D p3, float rad1, float rad2, color col, float frac){
      int steps = 100;
      float ang = TWO_PI/float(steps);
      float angSecond = 0;
      noStroke();
      fill(col);
    
      Vec3D v1 = p2.sub(p1).normalize();
      float a1 = atan2(v1.z,sqrt(sq(v1.x)+sq(v1.y)));
      float a2 = atan2(v1.y,v1.x);
      Vec3D per1 = new Vec3D(-cos(a2)*sin(a1),-sin(a2)*sin(a1),cos(a1));
      per1.scaleSelf(rad1);
      Vec3D step1 = p2.sub(p1).scale(frac);
    
      Vec3D v2 = p3.sub(p2).normalize();
      a1 = atan2(v2.z,sqrt(sq(v2.x)+sq(v2.y)));
      a2 = atan2(v2.y,v2.x);
      Vec3D per2 = new Vec3D(-cos(a2)*sin(a1),-sin(a2)*sin(a1),cos(a1));
      per2.scaleSelf(rad2);
      Vec3D step2 = p3.sub(p2).scale(frac);
    
      float minDist = 100000;
      for(int i = 0; i <= steps; i++) {
        float d = per1.distanceTo(per2);
        if(d < minDist){
          minDist = d;
          angSecond = float(i)*ang;
        } 
        per2.rotateAroundAxis(v2,ang);
      }  
      
      per2 = new Vec3D(-cos(a2)*sin(a1),-sin(a2)*sin(a1),cos(a1));
      per2.scaleSelf(rad2);
      per2.rotateAroundAxis(v2,angSecond);
      
      beginShape(QUAD_STRIP);
        for(int i = 0; i <= steps; i++) {
          vertex(p2.x-step1.x+per1.x,p2.y-step1.y+per1.y,p2.z-step1.z+per1.z);
          vertex(p2.x+step2.x+per2.x,p2.y+step2.y+per2.y,p2.z+step2.z+per2.z);
          per1.rotateAroundAxis(v1,ang);
          per2.rotateAroundAxis(v2,ang);
        }
      endShape();
    }
    
    
    void keyPressed(){
      switch(keyCode){
        case LEFT:
          rotY += 0.1;
          break;
        case RIGHT:
          rotY -= 0.1;
          break;
        case UP:
          if(keyEvent.isShiftDown()){
            zoomF += 0.02;
          }  
          else{
            rotX += 0.1;
          }
          break;
        case DOWN:
          if(keyEvent.isShiftDown()){
            zoomF -= 0.02;
            if(zoomF < 0.04){
              zoomF = 0.04;
            }
          }
          else{
            rotX -= 0.1;
          }
          break;
      }
    }
    
    
    void controlPanel(){
      int deltaX = 20;
      int deltaY = 50;
      int stepX = 93;
      int stepY = 30;
      
      ControlP5 controlP5 = new ControlP5(this);
      //controlP5.setAutoDraw(false);
      
      ControlWindow cw = controlP5.addControlWindow("Kinect control",0,0,400,160);
      cw.hideCoordinates();
      cw.setBackground(color(0));
      cw.activateTab("Constrain control");
      
      Tab t1 = controlP5.addTab(cw,"default");
      t1.setLabel("Constrain control");
      //t1.activateEvent(true);
      t1.setHeight(20);
      t1.setWidth(96);
      t1.getCaptionLabel().align(CENTER,CENTER);
        
      Range xLimsRange = controlP5.addRange("xRange",-8000,8000,xmin,xmax,deltaX,deltaY,300,20);
      xLimsRange.setCaptionLabel("X limits");
      xLimsRange.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      xLimsRange.moveTo(t1);
    
      Range yLimsRange = controlP5.addRange("yRange",-8000,8000,ymin,ymax,deltaX,deltaY+stepY,300,20);
      yLimsRange.setCaptionLabel("Y limits");
      yLimsRange.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      yLimsRange.moveTo(t1);
    
      Range zLimsRange = controlP5.addRange("zRange",-8000,8000,zmin,zmax,deltaX,deltaY+2*stepY,300,20);
      zLimsRange.setCaptionLabel("Z limits");
      zLimsRange.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      zLimsRange.moveTo(t1);
    
    
      Tab t2 =  controlP5.addTab(cw,"Bands control");
      t2.activateEvent(true);
      t2.setHeight(20);
      t2.setWidth(96);
      t2.getCaptionLabel().align(CENTER,CENTER);
    
      Slider bandsResSlider = controlP5.addSlider("bandsResolution",1,10,resolution,deltaX,deltaY,300,20);
      bandsResSlider.setCaptionLabel("Resolution");
      bandsResSlider.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      bandsResSlider.setNumberOfTickMarks(10);
      bandsResSlider.showTickMarks(false);
      bandsResSlider.setBehavior(new UpdateResolution());
      bandsResSlider.moveTo(t2);
    
      Slider bandsSepSlider = controlP5.addSlider("bandsSeparation",0,10,bandsSeparation,deltaX,deltaY+stepY,300,20);
      bandsSepSlider.setCaptionLabel("Separation");
      bandsSepSlider.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      bandsSepSlider.setNumberOfTickMarks(11);
      bandsSepSlider.showTickMarks(false);
      bandsSepSlider.moveTo(t2);
    
      Toggle bandsRealToggle = controlP5.addToggle("bandsRealColor",realColor,deltaX,deltaY+2*stepY,20,20);
      bandsRealToggle.setCaptionLabel("Real color");
      bandsRealToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      bandsRealToggle.setBehavior(new UpdateRealColor());
      bandsRealToggle.moveTo(t2);
    
      Toggle followBandsToggle = controlP5.addToggle("followBands",follow,deltaX+stepX,deltaY+2*stepY,20,20);
      followBandsToggle.setCaptionLabel("Follow");
      followBandsToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      followBandsToggle.setBehavior(new UpdateFollow());
      followBandsToggle.moveTo(t2);
      
      Toggle explodeToggle = controlP5.addToggle("explode",explode,deltaX+2*stepX,deltaY+2*stepY,20,20);
      explodeToggle.setCaptionLabel("Explode");
      explodeToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      explodeToggle.moveTo(t2);
      
      Toggle disolveToggle = controlP5.addToggle("disolve",disolve,deltaX+3*stepX,deltaY+2*stepY,20,20);
      disolveToggle.setCaptionLabel("Disolve");
      disolveToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      disolveToggle.moveTo(t2);
    
    
      Tab t3 =  controlP5.addTab(cw,"Pixels control");
      t3.activateEvent(true);
      t3.setHeight(20);
      t3.setWidth(96);
      t3.getCaptionLabel().align(CENTER,CENTER);
    
      Slider pixelsResSlider = controlP5.addSlider("pixelsResolution",1,10,resolution,deltaX,deltaY,300,20);
      pixelsResSlider.setCaptionLabel("Resolution");
      pixelsResSlider.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      pixelsResSlider.setNumberOfTickMarks(10);
      pixelsResSlider.showTickMarks(false);
      pixelsResSlider.setBehavior(new UpdateResolution());
      pixelsResSlider.moveTo(t3);
    
      Slider pixelSizeSlider = controlP5.addSlider("pixelSize",1,10,pixelSize,deltaX,deltaY+stepY,300,20);
      pixelSizeSlider.setCaptionLabel("Pixel size");
      pixelSizeSlider.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      pixelSizeSlider.setNumberOfTickMarks(10);
      pixelSizeSlider.showTickMarks(false);
      pixelSizeSlider.moveTo(t3);
    
      Toggle pixelsRealToggle = controlP5.addToggle("pixelsRealColor",realColor,deltaX,deltaY+2*stepY,20,20);
      pixelsRealToggle.setCaptionLabel("Real color");
      pixelsRealToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      pixelsRealToggle.setBehavior(new UpdateRealColor());
      pixelsRealToggle.moveTo(t3);
    
      Toggle followPixelsToggle = controlP5.addToggle("followPixels",follow,deltaX+stepX,deltaY+2*stepY,20,20);
      followPixelsToggle.setCaptionLabel("Follow");
      followPixelsToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      followPixelsToggle.setBehavior(new UpdateFollow());
      followPixelsToggle.moveTo(t3);
    
      Toggle sandToggle = controlP5.addToggle("sandEffect",sandEffect,deltaX+2*stepX,deltaY+2*stepY,20,20);
      sandToggle.setCaptionLabel("Sand effect");
      sandToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      sandToggle.moveTo(t3);
      
    
      Tab t4 =  controlP5.addTab(cw,"Other options");
      //t4.activateEvent(true);
      t4.setHeight(20);
      t4.setWidth(96);
      t4.getCaptionLabel().align(CENTER,CENTER);
    
      Toggle sculptureToggle = controlP5.addToggle("drawSculpture",drawSculpture,deltaX,deltaY,20,20);
      sculptureToggle.setCaptionLabel("Sculpture");
      sculptureToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      sculptureToggle.moveTo(t4);
    
      Bang clearSculptureBang = controlP5.addBang("clearSculpture",deltaX+stepX,deltaY,20,20);
      clearSculptureBang.setCaptionLabel("Redraw sculpture");
      clearSculptureBang.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      clearSculptureBang.moveTo(t4);
        
      Toggle sphereToggle = controlP5.addToggle("drawSphere",drawSphere,deltaX,deltaY+stepY,20,20);
      sphereToggle.setCaptionLabel("Sphere");
      sphereToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      sphereToggle.moveTo(t4);
    
      Bang clearSphereBang = controlP5.addBang("clearSphere",deltaX+stepX,deltaY+stepY,20,20);
      clearSphereBang.setCaptionLabel("Redraw sphere");
      clearSphereBang.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      clearSphereBang.moveTo(t4);
        
      Toggle ballsToggle = controlP5.addToggle("drawBalls",drawBalls,deltaX,deltaY+2*stepY,20,20);
      ballsToggle.setCaptionLabel("Balls");
      ballsToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      ballsToggle.moveTo(t4);
    
      Toggle gridToggle = controlP5.addToggle("drawGrid",drawGrid,deltaX+stepX,deltaY+2*stepY,20,20);
      gridToggle.setCaptionLabel("Grid");
      gridToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      gridToggle.moveTo(t4);
        
      Toggle floorToggle = controlP5.addToggle("drawFloor",drawFloor,deltaX+2*stepX,deltaY+2*stepY,20,20);
      floorToggle.setCaptionLabel("Floor");
      floorToggle.getCaptionLabel().align(ControlP5.RIGHT_OUTSIDE,CENTER).setPaddingX(10);
      floorToggle.moveTo(t4);
    }
    
    class UpdateResolution extends ControlBehavior {
      public void update() {
        setValue(resolution); 
      }
    }
      
    class UpdateRealColor extends ControlBehavior {
      public void update() {
        setValue(int(realColor)); 
      }
    }
      
    class UpdateFollow extends ControlBehavior {
      public void update() {
        setValue(int(follow)); 
      }
    }
    
    void controlEvent(ControlEvent theControlEvent){
      if(theControlEvent.isFrom("xRange")){
        xmin = theControlEvent.getController().getArrayValue(0);
        xmax = theControlEvent.getController().getArrayValue(1);
      }
      if(theControlEvent.isFrom("yRange")){
        ymin = theControlEvent.getController().getArrayValue(0);
        ymax = theControlEvent.getController().getArrayValue(1);
      }
      if(theControlEvent.isFrom("zRange")){
        zmin = theControlEvent.getController().getArrayValue(0);
        zmax = theControlEvent.getController().getArrayValue(1);
      }
      if(theControlEvent.isFrom("bandsResolution") || theControlEvent.isFrom("pixelsResolution")){
        resolution = (int) theControlEvent.getController().getValue();
      }
      if(theControlEvent.isFrom("bandsRealColor") || theControlEvent.isFrom("pixelsRealColor")){
        int v = (int) theControlEvent.getController().getValue();
        realColor = boolean(v);
      }
      if(theControlEvent.isFrom("followBands") || theControlEvent.isFrom("followPixels")){
        int v = (int) theControlEvent.getController().getValue();
        follow = boolean(v);
      }
      if(theControlEvent.isFrom("Bands control")){
        drawBands = true;
        drawPixels = false;
      }
      if(theControlEvent.isFrom("Pixels control")){
        drawPixels = true;
        drawBands = false;
      }
      if(theControlEvent.isFrom("clearSculpture")){
        splinePoints = new Spline3D();
      }
      if(theControlEvent.isFrom("clearSphere")){
        PVector pos = new PVector(0,0,2000);
        PVector vel = new PVector(0,0,0);
        sph = new Ball(pos,vel,100);
      }
    }
    
    
    
    void drawFloor(color col, float xMin, float xMax, float yMin, float yMax, float zMin, float zMax){
      float deltaX = (xMax-xMin);
      float deltaZ = (zMax-zMin);
    
      noStroke();
      fill(col); 
      beginShape();
        vertex(xMin-0.1*deltaX,yMin,zMin-0.1*deltaZ);
        vertex(xMin-0.1*deltaX,yMin,zMax+0.1*deltaZ);
        vertex(xMax+0.1*deltaX,yMin,zMax+0.1*deltaZ);
        vertex(xMax+0.1*deltaX,yMin,zMin-0.1*deltaZ);
      endShape(CLOSE);
    }
    
    void drawGrid(color col, float xMin, float xMax, float yMin, float yMax, float zMin, float zMax){
      int steps = 10;
      float deltaX = (xMax-xMin)/steps;
      float deltaZ = (zMax-zMin)/steps;
    
      smooth();
      strokeWeight(1);
      stroke(col);
      for(int i = 0; i <= steps; i++){
        line(xMin+i*deltaX,yMin+10,zMin,xMin+i*deltaX,yMin+10,zMax);
        line(xMin,yMin+10,zMin+i*deltaZ,xMax,yMin+10,zMin+i*deltaZ);
      }
      noStroke();
      noSmooth();
    }
    
    
    String lastGesture;
    boolean track = false;
    
    void onRecognizeGesture(String strGesture, PVector idPosition, PVector endPosition){
      println("onRecognizeGesture - strGesture: " + strGesture + ", idPosition: " + idPosition + ", endPosition:" + endPosition);
      lastGesture = strGesture;
      context.removeGesture(strGesture);
      context.startTrackingHands(endPosition);
    }
    
    void onCreateHands(int handId, PVector pos, float time){
      println("onCreateHands - handId: " + handId + ", pos: " + pos + ", time:" + time);
      if(drawSculpture && (splinePoints.getPointList().size() == 0)){
        track = true;
      }
    }
    
    void onUpdateHands(int handId, PVector pos, float time){
      if(track){
        splinePoints.add(new Vec3D(pos.x,pos.y,pos.z));
      }
      if(drawBalls){
        float velMag = random(50,80);
        float ang1 = random(0,TWO_PI);
        float ang2 = random(0,HALF_PI/3);
        PVector vel = new PVector(velMag*cos(ang1)*sin(ang2),velMag*cos(ang2),velMag*sin(ang1)*sin(ang2));
        balls.add(new Ball(PVector.add(pos,new PVector(0,50,0)),vel,30));
      }
    }
    
    void onDestroyHands(int handId, float time){
      println("onDestroyHandsCb - handId: " + handId + ", time:" + time);
      context.addGesture(lastGesture);
      track = false;
    }
    
    
    //static public void main(String args[]){
    //  Frame frame = new Frame("testing");
    //  frame.setUndecorated(true);
    //  // The name "sketch_name" must match the name of your program
    //  PApplet applet = new kinect();
    //  frame.add(applet);
    //  applet.init();
    //  frame.setBounds(0, 0, 1440, 900); 
    //  frame.setVisible(true);
    //}
    
    import SimpleOpenNI.*;
    import controlP5.*;
    import toxi.geom.*;
    
    public float   xmin = -1000;
    public float   xmax = 1000;
    public float   ymin = -1000;
    public float   ymax = 1000;
    public float   zmin = -1000;
    public float   zmax = 1000;
    public int     resolution = 2;
    public int     bandsResolution;
    public int     pixelsResolution;
    public int     bandsSeparation = 0;
    public int     pixelSize = resolution;
    public boolean drawBands = true;
    public boolean drawPixels = false;
    public boolean realColor = true;
    public boolean explode = false;
    public boolean disolve = false;
    public boolean follow =  false;
    public boolean sandEffect = false;
    public boolean drawSculpture = false;
    public boolean drawSphere = false;
    public boolean drawBalls = false;
    public boolean drawGrid = false;
    public boolean drawFloor = false;
    
    SimpleOpenNI context;
    
    float zoomF = 0.35;
    float rotX  = PI;
    float rotY  = 0;
    
    Particles      par;
    Bands          band;
    ConnectedLines connectedLine;
    ArrayList      particlesList = new ArrayList();
    ArrayList      bandsList = new ArrayList();
    Spline3D       splinePoints = new Spline3D();
    ArrayList      balls = new ArrayList();
    Ball           sph = new Ball(new PVector(0,0,2000),new PVector(0,0,0),100);
    
    void setup(){
      //size(1440, 900,P3D);
      size(1024,768,P3D);
      frameRate(300);
      perspective(radians(45),float(width)/float(height),10.0,150000.0);
                             
      context = new SimpleOpenNI(this);
      context.setMirror(true);
      context.enableDepth();  
      context.enableRGB();
      context.alternativeViewPointDepthToImage();
      context.enableHands();
      context.enableGesture();
      context.addGesture("RaiseHand");
      context.update();
    
      calculateLimits(context.depthMap(),context.depthMapRealWorld());
      
      controlPanel();
    }
    
    void draw(){
      context.update();
      int[] depthMap = context.depthMap();
      PVector[] realWorldMap = context.depthMapRealWorld();
      PImage rgbImage = context.rgbImage();
    
      int[] resDepth = resizeDepth(depthMap,resolution);
      PVector[]resMap3D = resizeMap3D(realWorldMap,resolution);
      PImage resRGB = resizeRGB(rgbImage,resolution);
      boolean[] constrainedImg = constrainImg(resDepth,resMap3D,xmin,xmax,ymin,ymax,zmin,zmax);
      int resXsize = context.depthWidth()/resolution;
      int resYsize = context.depthHeight()/resolution;
      
      background(10);
      translate(width/2,height/2,0);
      rotateX(rotX);
      rotateY(rotY);
      scale(zoomF);
      translate(0,0,-1500);
      
      if(drawFloor){
        drawFloor(color(150),xmin,xmax,ymin,ymax,zmin,zmax);
      }
    
      if(drawGrid){
        drawGrid(color(255),xmin,xmax,ymin,ymax,zmin,zmax);
      }
      
      if(!realColor){
        directionalLight(255,255,255,0,-0.2,1); 
      }
    
      if(drawBands){
        if(!explode && !disolve){
          band = new Bands(resMap3D,resRGB,constrainedImg,resXsize,resYsize);
        }
        else if(explode){
          band.explode();
        }
        else if(disolve){
          band.disolve(ymin);
        }
        
        if(realColor){
          band.paint(bandsSeparation);
        }
        else{
          band.paint(color(50,50,255),bandsSeparation);
        }
        
        if(follow){
          bandsList.add(band);
          if(bandsList.size() > 30){
            Bands band1 = (Bands) bandsList.get(15);
            Bands band2 = (Bands) bandsList.get(0);
            if(realColor){
              band1.paint(bandsSeparation);
              band2.paint(bandsSeparation);
            }
            else{
              band1.paint(color(255,50,50),bandsSeparation);
              band2.paint(color(50,255,50),bandsSeparation);
            }
            bandsList.remove(0);
          }
        }
        else{
          bandsList.clear();
        }
      }
    
      if(drawPixels){
        par = new Particles(resMap3D,resRGB,constrainedImg);
        //connectedLine = new ConnectedLines(resMap3D,constrainedImg,resXsize,resYsize);
        if(realColor){
          par.paint(pixelSize);
          //connectedLine.paint(color(200));
        }
        else{
          par.paint(pixelSize,color(200));
          //connectedLine.paint(color(200));
        }
    
        if(follow){
          particlesList.add(par);
          if(sandEffect){
            for(int i = 0; i < particlesList.size()-1; i++){
              par = (Particles) particlesList.get(i);
              par.paint(pixelSize,color(200));
              par.update(ymin);
            }
            if(particlesList.size() > 30){
              particlesList.remove(0);
            }
          } 
          else{
            if(particlesList.size() > 30){
              Particles par1 = (Particles) particlesList.get(15);
              Particles par2 = (Particles) particlesList.get(0);
              if(realColor){
                par1.paint(pixelSize);
                par2.paint(pixelSize);
              }
              else{
                par1.paint(pixelSize,color(200));
                par2.paint(pixelSize,color(200));
              }
              particlesList.remove(0);
            }
          }
        }
        else{
          particlesList.clear();
        }
      }
    
      if(realColor){
        directionalLight(255,255,255,0,-0.2,1); 
      }
    
      if(drawSculpture){
        if(splinePoints.getPointList().size() > 2){
          splinePoints.setTightness(0.25);
          java.util.List vertices = splinePoints.computeVertices(4);
          for(int i = 0; i < vertices.size()-2; i++){
            Vec3D p1 = (Vec3D) vertices.get(i);
            Vec3D p2 = (Vec3D) vertices.get(i+1);
            Vec3D p3 = (Vec3D) vertices.get(i+2);
            float rad1 = 60; // + 20*noise(float(i)*0.1);
            float rad2 = 60; // + 20*noise((float(i)+0.5)*0.1);
            float rad3 = 60; // + 20*noise(float(i+1)*0.1);
            color col = color(255);
            float frac = 0.2;
          
            cilinder(p1,p2,rad1,rad2,col,frac);
            connector(p1,p2,p3,rad2,rad3,col,frac);
          }
        }
      }
      
      if(drawBalls){
        for(Iterator i = balls.iterator(); i.hasNext(); ){
          Ball b = (Ball) i.next();
          b.paint(color(255));
          b.update(new PVector(0,-15,0),1);
          if(b.pos.y < ymin){
            i.remove();
          }
        }  
      }
      
      if(drawSphere){
        color col = color(0,50+200*noise(frameCount*0.05),50+200*noise(200+frameCount*0.05));
        sph.paint(col);
        sph.contact(resMap3D,constrainedImg,resXsize);
        sph.update(new PVector(0,0,0),0.5);
      }
      
    }
    
    
    void calculateLimits(int[] depthImg, PVector[] map3D){
      float xMin, xMax, yMin, yMax, zMin, zMax;
      xMin = yMin = zMin = 10000;
      xMax = yMax = zMax = -10000;
      
      for(int i = 0; i < depthImg.length; i++){
        if(depthImg[i] > 0){
          PVector p = map3D[i];
          if(p.x < xMin){
            xMin = p.x;
          }
          if(p.x > xMax){
            xMax = p.x;
          }
          if(p.y < yMin){
            yMin = p.y;
          }
          if(p.y > yMax){
            yMax = p.y;
          }
          if(p.z < zMin){
            zMin = p.z;
          }
          if(p.z > zMax){
            zMax = p.z;
          }
        } 
      }
      xmin = xMin - 0.1*(xMax - xMin);
      xmax = xMax + 0.1*(xMax - xMin);
      ymin = yMin - 0.1*(yMax - yMin);
      ymax = yMax + 0.1*(yMax - yMin);
      zmin = zMin - 0.5*(zMax - zMin);
      zmax = zMax + 0.1*(zMax - zMin);
    }  
    
    int[] resizeDepth(int[] depthImg, int n){
      int xSizeOrig = context.depthWidth();
      int ySizeOrig = context.depthHeight();
      int xSize = xSizeOrig/n;
      int ySize = ySizeOrig/n;
      int[] resDepthImg = new int[xSize*ySize];
    
      for(int y = 0; y < ySize; y++){
        for(int x = 0; x < xSize; x++){
          resDepthImg[x + y*xSize] = depthImg[x*n + y*n*xSizeOrig];
        }
      }
      return resDepthImg;
    }
    
    PVector[] resizeMap3D(PVector[] map3D, int n){
      int xSizeOrig = context.depthWidth();
      int ySizeOrig = context.depthHeight();
      int xSize = xSizeOrig/n;
      int ySize = ySizeOrig/n;
      PVector[] resMap3D = new PVector[xSize*ySize];
    
      for(int y = 0; y < ySize; y++){
        for(int x = 0; x < xSize; x++){
          resMap3D[x + y*xSize] = map3D[x*n + y*n*xSizeOrig].get();
        }
      }
      return resMap3D;
    }
    
    PImage resizeRGB(PImage rgbImg, int n){
      int xSizeOrig = context.depthWidth();
      int ySizeOrig = context.depthHeight();
      int xSize = xSizeOrig/n;
      int ySize = ySizeOrig/n;
      PImage resRGB = createImage(xSize,ySize,RGB);
     
      for(int y = 0; y < ySize; y++){
        for(int x = 0; x < xSize; x++){
          resRGB.pixels[x + y*xSize] = rgbImg.pixels[x*n + y*n*xSizeOrig];
        }
      }
      return resRGB; 
    }
    
    boolean[] constrainImg(int[] depthImg, PVector[] map3D, float xMin, float xMax, float yMin, float yMax, float zMin, float zMax){
      boolean[] consImg = new boolean[depthImg.length];
    
      for(int i = 0; i < consImg.length; i++){
        PVector p = map3D[i];
        consImg[i] = (depthImg[i] > 0) && (p.x > xMin) && (p.x < xMax) && (p.y > yMin) && (p.y < yMax) && (p.z > zMin) && (p.z < zMax);
      } 
      return consImg; 
    }  
    
    
    class ConnectedLines{
      PVector[] map3D;
      boolean[] consImg; 
      int xSize;
      int ySize;
        
      ConnectedLines(PVector[] tempMap3D, boolean[] tempConsImg, int tempXsize, int tempYsize){
        map3D = tempMap3D;
        consImg = tempConsImg;
        xSize = tempXsize;
        ySize = tempYsize;
      }
      
      void paint(color col){
        stroke(col);
        float maxSep = 50;
        
        for(int y = 0; y < ySize-1; y++){
          for(int x = 0; x < xSize-1; x++){
            if(consImg[x + y*xSize]){
              PVector p1 = map3D[x + y*xSize];
              if(consImg[x+1 + y*xSize]){
                PVector p2 = map3D[x+1 + y*xSize];
                if(p2.dist(p1) < maxSep){
                  line(p1.x,p1.y,p1.z,p2.x,p2.y,p2.z);
                }
              }
              if(consImg[x + (y+1)*xSize]){
                PVector p3 = map3D[x + (y+1)*xSize];
                if(p3.dist(p1) < maxSep){
                  line(p1.x,p1.y,p1.z,p3.x,p3.y,p3.z);
                }
              }
            }
          }
        }  
      }
      
    }
    
    
    class Particles{
      PVector[] map3D;
      PImage rgbImg;
      boolean[] consImg;
      PVector[] vel;
      int nPar;
    
      Particles(PVector[] tempMap3D, PImage tempRGBimg, boolean[] tempConsImg){
        map3D = tempMap3D;
        rgbImg = tempRGBimg;
        consImg = tempConsImg;
        nPar = map3D.length;
        vel = new PVector[nPar];
        for(int i = 0; i < nPar; i++){
          vel[i] = new PVector(0,0,0);
        }
      }
      
      void paint(int pSize){
        strokeWeight(pSize);
    
        for(int i = 0; i < nPar; i++){
          if(consImg[i]){
            PVector p = map3D[i];
            stroke(rgbImg.pixels[i]);
            point(p.x,p.y,p.z);
          }  
        }
      }
      
      void paint(int pSize, color col){
        strokeWeight(pSize);
        stroke(col);
        
        for(int i = 0; i < nPar; i++){
          if(consImg[i]){ 
            PVector p = map3D[i];
            point(p.x,p.y,p.z);
          }  
        }
      }
      
      void update(float yMin){
        PVector g = new PVector(0,-5,0);
        
        for(int i = 0; i < nPar; i++){
          if(consImg[i]){
            if((map3D[i].y + vel[i].y) > yMin){
              map3D[i].add(vel[i]);
              vel[i].add(g);
            }
            else{
              map3D[i].y = yMin;
            } 
          }
        }
      }
      
    }
    
    

    code

    tweaks (2)

    about this sketch

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

    license

    advertisement

    Javier Graciá Carpio

    Kinect experiments

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

    Doesn't work in the browser. This video shows it in action:
    https://vimeo.com/41381966

    Buy a Kinect, download the code, install the latest simple-openni, controlP5 (version controlP5_1.5.1) and toxiclibs libraries and have fun!

    Tested in processing 1.5.1 under linux. Part of the code comes from the simple-openni examples. Many thanks to the processing community!!

    Brendan Flynn
    8 May 2012
    Would love to play with this, have a mac and all the libraries installed, it is bugging on me and im afraid I would not have level of programming needed to get into functioning proper (i did try) To beging with in the ControlP5.pde it says getCaptionLabel();setHeight(); and isFrom(string) do not exist a long with another, then in bands.pde it is expecting another if. Would be class if you could help out for it looks wicked and I would lve to give it a try, even make something nice from it, built a sweet installation with hotpoints just a few weeks ago, only new to this game. http://www.youtube.com/watch?v=sU6dgZINpco&list=UUt6_yMoj7035exM8AZdpajw&index=1&feature=plcp
    Hi Brendan, the ControlP5 problems are probably related to the library version. Update your controlP5 library to the very last one (from 04/09/2012). This may also fix the error is bands.pde.

    Tell me if it works!
    javier
    Brendan Flynn
    22 May 2012
    hey man,

    updated controlp5 and simple open ni libraries, works a charm, and very very cool, love switching all into cubes with the floor and grid active. Thanks for sharing this, will defo mess about with it if i do anything cool, our use it for anything cool. Will share it with you and give you credit where credit is due. Made me smile and I loved it, and when not so tired will give it better look for sure. thanks again dude very cool stuff.

    yours truly
    brendan flynn
    Hi Brendan! Nice to know that it finally worked for you and you like it! Yes, please, keep me posted with anything you do with it! I've been using/enjoying open source for years, and it was time to contribute sharing some of my code too. Have fun!
    BTW, I made some progress combining the kinect with the hemesh library
    https://vimeo.com/42342434
    I'll post the code in openprocessing tonight, if I find some time.
    Brendan Flynn
    23 May 2012
    Dude, I am sure there is more enjoying just not posting, as with the other one. Your work makes me smile which is a nice trait to have with something you create, to cause joy. I have seen so many different things and played with so much, still whatever it is your stuff is just neath as...mean that man. In case you havent seen this http://rgbdtoolkit.com/ I havent had a chance to calibrate all yet for just finished in college for this year and now wanna do some gardening (love it) Still will soon. Am going to build a pack to film with the kinect with ease, lots of cool ideas and working on lots. Also as far as open source is concerned once i build something smart I will be posting for sure. Also i will defo keep you posted on anything cool i do with our without your program. Actually while i have you and i think from looking at what you have done. Have you or do you know where I could get a program that does this. http://www.youtube.com/watch?v=1dnMsmajogA dont ask me why i am itching to see it in the flesh and mess with it if possible. Actually building 3d images from the old red green 3d pages soon, from dinosaur magazines i collected when i was a kid. any way thanks again man, that above program is very cool. and having the code is brillant, working together while all being watched over by the machines of loving grace :) you should check that crazy cool documentary (part 3 is wack) http://topdocumentaryfilms.com/all-watched-over-by-machines-of-loving-grace/
    HegerTechnik
    11 Jul 2012
    Thanks for your Work.

    I have a Error with win7:
    Display 0 does not exist, using the default display instead.
    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6e4f1ac5, pid=216, tid=5876
    #
    # JRE version: 6.0_29-b11
    # Java VM: Java HotSpot(TM) Client VM (20.4-b02 mixed mode windows-x86 )
    # Problematic frame:
    # C [OpenNI.dll+0x11ac5]


    Current thread (0x18d22000): JavaThread "Animation Thread" [_thread_in_native, id=5876, stack(0x19b20000,0x19b70000)]

    Have tested with Porcessing 1.5 and 2.0. Java 6 and 7. SimpleOpenni 26 and 27. Dont work.

    Kinect is working (nite samples)
    Unfortunately I have no real experience with Windows. Have you installed all the processing libraries (controlP5, simple-openni, toxiclibs) and checked that the processing examples work in your system? I'm not doing anything fancy in the sketch, so it should work if the libraries work.

    Cheers!
    Hi HegerTechnik,
    Your problem might be related with the controlP5 library version. Please, try the sketch with this version installed:
    http://code.google.com/p/controlp5/downloads/detail?name=controlP5-1.5.1.zip
    Let me know if it works!
    James
    27 Oct 2012
    Very Cool stuff! Do you know if it will be very difficult to take only your Balls pde and create particles instead? I'd like to be able to take something like this (click on the "fireball" button) http://www.escapemotions.com/experiments/fluid_fire_3/index.html and have that fireball come from the hand of the person. I'd probably only need the Kinect data to locate the hand, but I don't want the person to be seen at all.

    I would like to use something like that for a dance production on stage with a projector. But mostly I'm trying t find out how to make a particle generator with flames or just sparks come from the hand.

    Thanks for any suggestions.
    Hi James! It shouldn't be too difficult to include the fluid simulator to the kinect sketch. I think it's 2D, so you will have to make it 3D... One way would be to take the "x" and "y" coordinates from the fluid and give the particles the "z" that corresponds to the hand position.

    However, if you don't want the person to be seen, maybe is better if you take one of the simpleopenni examples to start with, i.e., the Hands3D example.

    Cheers!
    James
    1 Nov 2012
    Thanks Javier, I'll try experimenting some more. And thank you for offering the code!
    You're welcome, James! Keep us posted with your progress!
    Andy
    18 Feb 2013
    Hi Javier,

    Thank you very much for a wonderful looking sketch, however is not working here.

    Running:-

    - toxiclibs-complete-0020
    - controlP5 1.5.1
    - Processing 1.5.1
    - simple-openni 0.27


    Please help!
    Hi Andy! Can you post the error information?
    Andy
    23 Feb 2013
    Hmm, strangely if you drag the .pde files into the PDE - it seems to work.

    However, if you file -> open:

    NoSuchMethodError: You may using a library that's incompatible with this version of Processing
    ... No idea, Andy. Which method is it missing? Maybe it's related with the toxiclibs library, can't remember now which one was using, the sketch is almost 1yr old now :)
    Andy
    1 Mar 2013
    Hmm, not sure - it doesn't seem to highlight in the text at all.

    Here is the console output:

    Display 0 does not exist, using the default display instead.
    Exception in thread "Animation Thread" java.lang.NoSuchMethodError: SwigDirector_ContextWrapper_onExitUserCb
    at SimpleOpenNI.SimpleOpenNIJNI.swig_module_init(Native Method)
    at SimpleOpenNI.SimpleOpenNIJNI.<clinit>(SimpleOpenNIJNI.java:1553)
    at SimpleOpenNI.ContextWrapper.<init>(ContextWrapper.java:54)
    at SimpleOpenNI.SimpleOpenNI.<init>(SimpleOpenNI.java:209)
    at kinect.setup(kinect.java:103)
    at processing.core.PApplet.handleDraw(Unknown Source)
    at processing.core.PApplet.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:662)
    Andy
    1 Mar 2013
    [RESOLVED]

    I just re-saved it without the 'code' folder (removed the folder)!

    Thanks again .....

    All the best :)
    ashley alexander
    28 Mar 2013
    Hi Javier,
    this looks like such a fantastic sketch. I'm new to kinect programming and was hope to take experiment with this sketch. Unfortunately, I keep getting a NullPointerException in the ControlWindow cw. I am using processing 2.0b8, and ControlP5 2.0.4.
    Hi ashley. Unfortunately there is not an easy solution for that. If you really want to try the sketch you will have to install an older version of controlP5
    http://code.google.com/p/controlp5/downloads/detail?name=controlP5-1.5.1.zip

    I'm not sure if it's compatible with processing 2.0b8. If it doesn't work, install processing 1.5.1. You can have both version in your system if they are in different directories.

    In any case, the problem is only related with controlP5, the rest of the sketch should work fine if you remove the cP5 dependency.

    Good luck!
    Victoria
    22 Jun 2013
    Hola! Thank you for your code, i watched video, it looks amazing and really interesting!!=) i have tried it on my pc but it says "Can't find the SimpleOpenNI library (SimpleOpenNI32) : java.lang.UnsatisfiedLinkError: no SimpleOpenNI32 in java.library.path" SimpleOpenNI library works fine for other codes. I have
    - toxiclibs
    - controlP5 1.5.1
    - Processing 1.5.1
    - simple-openni 0.24 (lates version wants Processing 2 to be installed)
    maybe you know how it could be fixed?
    thank you=)
    shenlianzhi
    22 Dec 2013
    Hi,i got a question.
    I can run this sketch in processing well,
    but after i exported this sketch as an application, it dosent work
    double klick the exe or app ,nothing happened.(both in pc and mac)

    I can open other app without simpleopenni.

    thank u very much and sorry about my poor English.
    You need to login/register to comment.