Willkommen auf unserem Seminar-Blog

Immer auf dem aktuellen Stand bleiben

Dieser Seminar-Blog befindet sich noch im Aufbau und wird in den kommenden Tagen entsprechend verfeinert.

Member Login

Lost your password?

Registration is closed

Sorry, you are not allowed to register by yourself on this site!

You must either be invited by one of our team member or request an invitation by email at viad.info {at} zhdk {dot} ch.

Draw with hands

9. Dezember 2011

A drawing program from Matthias Kappeler. Enhanced in collaboration, to work on Kinect.
import SimpleOpenNI.*;

PVector handPos;


HandCapture   handCapture;
boolean       drawFlag=false;

int start =0;
static int BRUSH_BRANCH  = 1<<0;
static int BRUSH_GEO     = 1<<1;
static int BRUSH_RECT    = 1<<2;
static int BRUSH_MESH    = 1<<3;
PShape brushPreview;

int r;
int g;
int b;
int s;
float colorRandom;
float colorRandomRange = 40;


Slider sliderR = null;
Slider sliderG = null;
Slider sliderB = null;
Slider sliderSat = null;
Checkbox checkbox = null;
Button buttonBranch = null;
Button buttonGeo = null;
Button buttonRect = null;
Button buttonMesh = null;

int brushType = BRUSH_BRANCH;
int dice;
String brush = "branch";
boolean colorOn = false;
float brushScale = 1;

void setup()
{
  handCapture = new HandCapture(this);
  
  sliderR = new Slider(365,15,100,.5,false);
  sliderG = new Slider(365,30,100,.5,false);
  sliderB = new Slider(365,45,100,.5,false);
  sliderSat = new Slider(365,60,100,.5,false);
  checkbox = new Checkbox(590,15,8);
  buttonBranch = new Button(600,25,20,60,"branch");
  buttonGeo = new Button(600,50,20,60,"geometry");
  buttonRect = new Button(700,25,20,60,"rectangle");
  buttonMesh = new Button(700,50,20,60,"mesh");
  
  PVector handPos = handCapture.handPos();
  
  addMouseWheelListener(new java.awt.event.MouseWheelListener() { 
    public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { 
      mouseWheel(evt.getWheelRotation());
  }}); 
  size(1440,900);      // def. fenstergroesse
  randomSeed(millis());  // seed random
  smooth();           // aktiviere antialiasing
  strokeWeight(1);    // linienbreite
  stroke(0,0,0,255);
  background(255);
}

void mouseWheel(int delta) {
  if(brushScale >= 0)
  brushScale = abs(brushScale+(delta*0.05));
}

void draw(){
  
  handPos = handCapture.handPos();
  
  if(handCapture.isHandTracked()&& handPos.z <= 1500 && handPos.z >=700)
    { 
      paint();
      println("HandPos: " + handCapture.handPos());
    }
    else
      println("no Hand");
    
  // update the hand tracking
  handCapture.update();
  
  colorRandom = random(-colorRandomRange,colorRandomRange);
  r = int(sliderR.pos() * 255 + colorRandom);
  g = int(sliderG.pos() * 255 + colorRandom);
  b = int(sliderB.pos() * 255 + colorRandom);
  s = int(sliderSat.pos() *255);
  menu();
 if(start ==0){
   start++;
 }
 else{
 }

}

void colorPreview(){
      int ra = int(sliderR.pos() * 255 );
      int ga = int(sliderG.pos() * 255 );
      int ba = int(sliderB.pos() * 255 );
      int sa = int(sliderSat.pos() *255);
      if(colorOn)
      fill(ra,ga,ba,sa);
      else
      fill(0);
    rect(500,30,40,40);
}


void paint(){
  brushScale = map(handPos.z,700,1500,0.3,2);
   handPos.x =  map(handPos.x,0,640,-50,width+50);
   handPos.y = map(handPos.y,0,480,0,height+50);
  dice = rollDice();
  if((brushType & BRUSH_RECT) != 0){
      int aeste = 3;
      int winkel = 360/ aeste;
    pushMatrix();
      translate(handPos.x,handPos.y);
      scale(brushScale*1.2);
      rotate(radians(random(360)));
      for(int i =0; i<=360; i+=winkel){
        rotate(radians(winkel));
        wurzel(3, brushType);
      }
    popMatrix();
    }
  else if((brushType & BRUSH_GEO) != 0){
    int aeste = (int)random(1,4);
    int winkel = 360/ aeste;
  pushMatrix();
    translate(handPos.x,handPos.y);
    scale(brushScale);
    for(int i =0; i<=360; i+=winkel){
      rotate(radians(random(i-winkel*.5,i+winkel*.5)));
      wurzel(6, brushType);
    }
  popMatrix();
 }
 
  else if((brushType & BRUSH_BRANCH) != 0){
    int aeste = (int)random(1,3);
    int winkel = 360/ aeste;
  pushMatrix();
    translate(handPos.x,handPos.y);
    scale(brushScale);
    for(int i =0; i<=360; i+=winkel){
      rotate(radians(random(i-winkel*.5,i+winkel*.5)));
      wurzel(6, brushType);
    }
  popMatrix();
}

  else if((brushType & BRUSH_MESH) != 0){
    int aeste = (int)random(1,4);
    int winkel = 360/ aeste;
  pushMatrix();
    translate(handPos.x,handPos.y);
    scale(brushScale);
    for(int i =0; i<=360; i+=winkel){
      rotate(radians(random(i-winkel*.5,i+winkel*.5)));
      
      if(dice<=1)
      wurzel(10, brushType);
      else
      wurzel(3, brushType);
    }
  popMatrix();
}
}

void mouseDragged(){  
   if(mouseY >= 80)
   paint();
   else{
   sliderR.mousePos(mouseX,mouseY,true);
   sliderG.mousePos(mouseX,mouseY,true);
   sliderB.mousePos(mouseX,mouseY,true);
   sliderSat.mousePos(mouseX,mouseY,true);
   }
}

void mousePressed(){
  if(mouseY >= 80)
  paint();
  else{
  sliderR.mousePos(mouseX,mouseY,true);
  sliderG.mousePos(mouseX,mouseY,true);
  sliderB.mousePos(mouseX,mouseY,true);
  sliderSat.mousePos(mouseX,mouseY,true);
  checkbox.mousePos(mouseX,mouseY,true);
  buttonBranch.mousePos(mouseX,mouseY,true);
  buttonGeo.mousePos(mouseX,mouseY,true);
  buttonRect.mousePos(mouseX,mouseY,true);
  buttonMesh.mousePos(mouseX,mouseY,true);
  }
}
 
void wurzel(int tiefe, int brushType)
{
   
    
    if((brushType & BRUSH_RECT) != 0){
     if(tiefe <=0)   {
       
     pushStyle();
       if(colorOn)
        fill(r,g,b,s);
       else
        fill(0,random(0,50));
       noStroke();
       rect(0,0,30,30);
     popStyle();
     
     return;
     }
      int x;
      int y;
      int count = (int)random(1,3);
      for(int i = 0; i < count;i++){
        x = (int)random(5,60); 
        y = 90;
       
        pushMatrix();
          translate(0,x);
          rotate(radians(y));
          scale(random(.4,1));
          wurzel(tiefe-1, brushType);
         popMatrix();
  }
 
    }
    
    else if((brushType & BRUSH_GEO) != 0){
      if(tiefe <=0)   {
     return;
    }
      
      int x;
      int y;
      int rand = (int)random(0,10);
      int count;
      if(rand<2)
      count = (int)random(1,5);
      else
      count = 1;
      for(int i = 0; i < count;i++){
        x = (int)random(5,100);
        
        if(rand<5)
        y = 90;
        else
        y = -90;
        strokeWeight(.5);
        if(colorOn)
          stroke(r,g,b,s);
        else
          stroke(0,150);
        line(0,0,0,x);
        pushMatrix();
          translate(0,x);
          rotate(radians(y));
          scale(random(.3,.7));
          wurzel(tiefe-1, brushType);
         popMatrix();
  }
    }
    
    else if((brushType & BRUSH_BRANCH) != 0){
      if(tiefe <=0)   {
      pushStyle();
       noFill();
       strokeWeight(random(10,15));
       stroke(0,200);
       stroke(random(100,255));
     popStyle();
     return;
      }
        int x;
        int y;
        int count = (int)random(1,4);
      
        for(int i = 0; i < count;i++)
        {
          x = (int)random(10,40);
          y = (int)random(-45,45);
        if(colorOn)
          stroke(r,g,b,s);
        else
          stroke(0,150);;

    line(0,0,0,x);
 
    pushMatrix();
      translate(0,x);
      rotate(radians(y));
      scale(random(.5,.8));
      wurzel(tiefe-1, brushType);
     popMatrix();
      }
    }
    
  else if((brushType & BRUSH_MESH) != 0){
   if(tiefe <=0) {
     return;
   }
 
  // zeichne zweige
      int x;
      int y;
      int count = (int)random(0,3);
      for(int i = 0; i < count;i++){
   
      if(dice<=1){
        x = (int)random(30,100);
        y = (int)random(-40,40);}
        else{
        x = (int)random(40);
        y = (int)random(-40,40);}
      strokeWeight(.5);
      if(colorOn)
        stroke(r,g,b,s);
      else
        stroke(0,150);
      line(0,0,x,y);
      fill(255,100);
      ellipse(0,0,10,10);
      strokeWeight(1);
      pushMatrix();
        
        translate(x,y);
        rotate(radians(y));
        if(dice<=1){
        scale(random(.8,1));}
        else{
        scale(random(.6,.95));}
        
        wurzel(tiefe-1, brushType);
     popMatrix();
    }
   }
}
 


void keyPressed()
{
  switch(key)
  {
  case 's':
    saveFrame("screenShot-###.png");
    println("save the screen to screenShot.bmp");
    break;
    
  case 'n':
    restart();
    break;
    
  case '1':
    brushType = BRUSH_BRANCH;
    brush = "  branch";
    break;
    
  case '2':
    brushType = BRUSH_GEO;
    brush = "  geometry";
    break;
    
  case '3':
    brushType = BRUSH_RECT;
    brush = "  rectangles";
    break;
    
  case '4':
    brushType = BRUSH_MESH;
    brush = "  mesh";
    break;
    
   case 'c':
    if(colorOn)
    colorOn=false;
    else
    colorOn=true;
    break;
  }
}

void restart(){
  background(255);
  start = 0;
  redraw();
}

int rollDice(){
  int dice = (int)random(0,50);
  return dice;
}

void menu(){
  fill(240);
  noStroke();
  rect(0,0,width,80);
  fill(0);
  int brushSc = (int)(brushScale*100);
   text("change brushes: 1-4  ", 25,20);
  text("active brush: " + brush , 25,35);
  text("brush scale:  " + brushSc + "%",25,50);
//  text("new sheet: 'n' ", 25,55);
  text("save: 's' " + "new sheet: 'n' ", 25,65);
  text("color on/off: ", 500, 20);
  text("read: ", 300, 20);
  text("green: ", 300,35);
  text("blue: ", 300, 50);
  text("alpha: ", 300, 65);
  colorPreview();
//    fill(r,b,g,s);
//    rect(800,20,20,20);
//    rect(800,40,20,20);
//    rect(820,20,20,20);
//    rect(820,40,20,20);

  sliderR.draw();
  sliderG.draw();
  sliderB.draw();
  sliderSat.draw();
  checkbox.draw();
  buttonBranch.draw();
  buttonGeo.draw();
  buttonMesh.draw();
  buttonRect.draw();
  
}

class Checkbox
{
  int _x;
  int _y;
  int _h;
  boolean _check;
  
  Checkbox(int x, int y, int h)
  {
   _x = x;
   _y = y;
   _h = h;
   _check = colorOn;
  
  }
  
  void draw(){
    stroke(0);  
    if(_check)
    fill(0);
    else
    noFill();
    ellipse(_x,_y,_h,_h);
  }
  
  void mousePos(int x,int y,boolean pressed)
  {
    if(pressed)
    {
      if(x >= _x && x <= _x+_h && y>= _y && y <= _y+_h){
        if(_check){
        _check = false;
        colorOn = false;
        }
        else{
        _check = true;
        colorOn = true;
        }
      }
    }
  }
}

class Slider
{
  PVector _p1;
  PVector _p2;
 
  
  float   _pos;
  boolean _vert;
 
  Slider(int x,int y,int w,float pos, boolean vert)
  {
    _vert = vert;
    if(_vert){
    _p1 = new PVector(x,y);
    _p2 = new PVector(x,y+w);
    }
    else{
    _p1 = new PVector(x,y);
    _p2 = new PVector(x+w,y);
    }
 
    
 
    _pos = pos;

  }
 
  float pos()
  {
    return _pos;
  }
 
  boolean isHit(int x,int y)
  { 
    
    if(_vert){
      if(y > _p1.y && x < _p2.y &&
         x > _p1.x - 5 && x < _p1.x + 5)
        return true;
      else
        return false;
    
    }
    else{ 
      if(x > _p1.x && x < _p2.x &&
       y > _p1.y - 5 && y < _p1.y + 5)
      return true;
    else
      return false;
    }
  }
 
  void draw()
  {
    pushStyle();
     drawSlider();
     drawKnob();
    popStyle();
  }
 
  void drawSlider()
  {
    stroke(0);
    line(_p1.x,_p1.y,_p2.x,_p2.y);
  }
  void resetPos(){
    _pos = 0.5;
  }
  void drawKnob()
  {
    noStroke();
    fill(0);
    PVector dir = PVector.sub(_p2,_p1);
    PVector pos = PVector.add( _p1 , PVector.mult(dir,_pos));

    ellipse(pos.x,pos.y,8,8);
 
  }
 
  void mousePos(int x,int y,boolean pressed)
  {
    if(pressed)
    {
      if(isHit(x,y))
      {  // move knob
        PVector dir = PVector.sub(_p2,_p1);
        if(_vert){
        _pos = 1.0 / dir.mag() * (y - _p1.y);
            if(_pos > 1.0)
            _pos = 1.0;
            else if(_pos < 0.0)
             _pos = 0.0;
          }
        else{
         _pos = 1.0 / dir.mag() * (x - _p1.x);
            if(_pos > 1.0)
            _pos = 1.0;
            else if(_pos < 0.0)
            _pos = 0.0;
        }
      }
    }
  }
}

class Button
{
  int _x;
  int _y;
  int _h;
  int _w;
  boolean _check;
  String _function;
  
  Button(int x, int y, int h, int w, String function)
  {
   _x = x;
   _y = y;
   _h = h;
   _w = w;
   _check = colorOn;
   _function = function;
  
  }
  
  void draw(){
    stroke(0);  
    if(_check)
    fill(0);
    else
    noFill();
    rect(_x,_y,_w,_h);
    text(_function, _x+5,_y+_h-5);
  }
  
  void mousePos(int x,int y,boolean pressed)
  {
    if(pressed)
    {
        if(x >= _x && x <= _x+_w && y>= _y && y <= _y+_h){
        if(_function == "save")
          saveFrame("screenShot-###.png");
          
        else if(_function == "new")
          restart();
     
        else if(_function == "branch"){
          brushType = BRUSH_BRANCH;
          brush = "  branch";
        }
        
        else if(_function == "geometry"){
          brushType = BRUSH_GEO;
          brush = "  geometry";
        }
        
        else if(_function == "rectangle"){
          brushType = BRUSH_RECT;
          brush = "  rectangles";
        }
        
        else if(_function == "mesh"){
          brushType = BRUSH_MESH;
          brush = "  mesh";
        }
        else{
        } 
        }       
       }
       
       
    }
}

// -----------------------------------------------------------------
// hand events
 
void onCreateHands(int handId,PVector pos,float time)
{
  handCapture.onCreateHands(handId,pos,time);
}
 
void onUpdateHands(int handId,PVector pos,float time)
{
  handCapture.onUpdateHands(handId,pos,time);
}
 
void onDestroyHands(int handId,float time)
{
  handCapture.onDestroyHands(handId,time);
}
 
void onRecognizeGesture(String strGesture, PVector idPosition, PVector endPosition)
{
  handCapture.onRecognizeGesture(strGesture,idPosition,endPosition);
}
 
void onProgressGesture(String strGesture, PVector position,float progress)
{
  handCapture.onProgressGesture(strGesture,position,progress);
}

Classes:
import SimpleOpenNI.*;

class HandCapture
{
  SimpleOpenNI  _context;
  boolean       _drawFlag=false;
  PVector       _handVec = new PVector();
  String        _lastGesture = "";
  PVector       _screenPos = new PVector();
  PApplet       _parent;
  boolean       _handsTrackFlag = false;

  HandCapture(PApplet parent)
  {
    _parent = parent;

    _context = new SimpleOpenNI(_parent);

    // mirror is by default enabled
    _context.setMirror(true);

    // enable depthMap 
    _context.enableDepth();

    // enable camera
    _context.enableRGB();

    _context.enableHands();  
    _context.enableGesture();

    _context.addGesture("RaiseHand");

    // align depth data to image data
    _context.alternativeViewPointDepthToImage();

  }

  boolean isHandTracked() { return _handsTrackFlag; } 
  
  PVector handPos() { return _screenPos; }
  PVector handPos3d() { return _handVec; }
  
  PImage depthImage() { return _context.depthImage(); }
  PImage rgbImage() { return _context.rgbImage(); }
  

  int width() { return _context.depthWidth(); }
  int height() { return _context.depthHeight(); }
  
  void update()
  {
    _context.update();
    
    _context.convertRealWorldToProjective(_handVec,_screenPos);
  }

  void onCreateHands(int handId, PVector pos, float time)
  {
    _handsTrackFlag = true;
    _handVec = pos;
  }

  void onUpdateHands(int handId, PVector pos, float time)
  {
    _handVec = pos;
  }

  void onDestroyHands(int handId, float time)
  {
    _handsTrackFlag = false;
    _context.addGesture(_lastGesture);
  }

  void onRecognizeGesture(String strGesture, PVector idPosition, PVector endPosition)
  {
    _lastGesture = strGesture;
    _context.removeGesture(strGesture); 
    _context.startTrackingHands(endPosition);
  }

  void onProgressGesture(String strGesture, PVector position, float progress)
  {
  }
}