Week 12 | Kinetic Interfaces | Kate

I was  originally going to create some simple drawing thing where multiple people could send info in and draw, but was not quite sure how to send different types of info. I guess another solution for how I built mine would have been to restrict the coordinates each person could draw in. I ended up […]

// IMA NYU Shanghai
// Kinetic Interfaces
// MOQN
// Apr 19 2018

/**
 * based on oscP5sendreceive by andreas schlegel
 * oscP5 website at http://www.sojamo.de/oscP5
 */
 

import oscP5.*;
import netP5.*;


OscP5 oscP5;
NetAddress myRemoteLocation;
float x,y,r;
void setup() {
  size(400,400);
  
  oscP5 = new OscP5(this,12000);
  myRemoteLocation = new NetAddress("127.0.0.1",12000);
  rectMode(CENTER);
  x = width/2;
  y = height/2;
}


void draw() {
  background(0);
  rect(x,y,10,10);
  r = mouseX;
}

/*
void mousePressed() {
  OscMessage msg = new OscMessage("/test");
   
  // let's send mouseX&Y positions
  float x = map(mouseX, 0, width, 0, 1);
  float y = map(mouseY, 0, height, 0, 1);
  msg.add( x );
  msg.add( y );
  oscP5.send( msg, myRemoteLocation );
  
  ellipse(mouseX, mouseY, 10, 10);
}
*/
void keyPressed(){
  
  OscMessage msg = new OscMessage("/test");
  if(keyCode == LEFT){
    x -= 1;
    if(x<0){
      x= width;
    }
    msg.add(x);
    msg.add(y);
  }
  if(keyCode == RIGHT){
    x += 1;
    if(y>width){
      x = 0;
    }
    msg.add(x);
    msg.add(y);
  }
  if(keyCode == UP){
    y -= 1;
    if(y<0){
      y = height;
    }
    msg.add(x);
    msg.add(y);
  }
  if(keyCode == DOWN){
    y += 1;
    if(y>height){
      y = 0;
    }
    msg.add(x);
    msg.add(y);
  }
  msg.add(r);
  oscP5.send( msg, myRemoteLocation );
}
// IMA NYU Shanghai
// Kinetic Interfaces
// MOQN
// Apr 19 2018

/**
 * based on oscP5sendreceive by andreas schlegel
 * oscP5 website at http://www.sojamo.de/oscP5
 */
 

import oscP5.*;
import netP5.*;
PImage reflect;

OscP5 oscP5;

float x, y,x2,r;
float xValue = 0;
float yValue = 0;
float rValue = 0;
float d1,d2,d3,d4;

void setup() {
  size(800,800);
  
  oscP5 = new OscP5(this,12000);
  rectMode(CENTER);
  
  fill(255,0,0);
  rect(width/4,height/4,width/2,height/2);
  fill(0,255,255);
  rect(width/4,3*height/4,width/2,height/2);
  fill(255,255,0);
  rect(3*width/4,height/4,width/2,height/2);
  fill(0,0,255);
  rect(3*width/4,3*height/4,width/2,height/2);
}


void draw() {
  //background(0);
  r = map(rValue,0,width,0,TWO_PI);
  
  x = xValue;
  x2 = map(xValue,0,400,800,400);
  y = map(yValue,0,400,800,400);
  fill(255);
  pushMatrix();
  rotate(r);
  rect(xValue,yValue,10,10);
  rect(x,y,10,10);
  rect(x2,yValue,10,10);
  rect(x2,y,10,10);
  if(dist(xValue,yValue,width/2,height/2)<50){
  beginShape();
  d1 = dist(xValue,yValue,x2,yValue);
  for(int i = 0;i<d1-1;i++){
    float x1 = lerp(xValue,x2,i/d1);
    float y1 = lerp(yValue,yValue,i/d1);
    float n = noise(x*frameCount,y*frameCount);
    //y1 = map(y1*n,0,400,y1-50,y1+50);
    vertex(x1,y1);
  }
  endShape();
  
  beginShape();
  d2 = dist(x2,yValue,x2,y);
  for(int i = 0;i<d2-1;i+=3){
    float x3 = lerp(x2,x2,i/d2);
    float y3 = lerp(yValue,y,i/d2);
    vertex(x3,y3);
  }
  endShape();
  
  beginShape();
  d3 = dist(x2,y,x,y);
  for(int i = 0;i<d3-1;i+=3){
    float x4 = lerp(x2,x,i/d3);
    float y4 = lerp(y,y,i/d3);
    vertex(x4,y4);
  }
  endShape();
  
  beginShape();
  d4 = dist(x,y,xValue,yValue);
  for(int i = 0;i<d4-1;i+=3){
    float x5 = lerp(x,xValue,i/d4);
    float y5 = lerp(y,yValue,i/d4);
    vertex(x5,y5);
  }
  endShape();
  }
  popMatrix();
  /*
  noFill();
  if(dist(xValue,yValue,width/2,height/2)<50){
    beginShape();
    vertex(xValue,yValue);
    vertex(x2,yValue);
    vertex(x2,y);
    vertex(x,y);
    vertex(xValue,yValue);
    endShape();
  }
  */
}


void oscEvent(OscMessage msg) {
  println("___");
  println("Pattern: " + msg.addrPattern() );
  println("Typetag: " + msg.typetag() );
  
  xValue = msg.get(0).floatValue();
  yValue = msg.get(1).floatValue();
  rValue = msg.get(2).floatValue();
  println("x: " + rValue );
  //println("y: " + yValue );
  println();
}

Kinetic Interfaces: OSC Communication(Billy Zou)

I created a simple Gomoku game using OSC communication. Different from the server-client mode introduced in the class. In my game, both hosts are server and both are clients. It is similar to the peer-to-peer mode. The “server” in my game means the host that initialize the game and the “client” is the one that […]

/* Server side */
import oscP5.*;
import netP5.*;

boolean mouseIsReleased = false;
boolean online = false;
int winner = -1;

OscP5 oscP5;
GameBoard board;
Player server;
Player client;
NetAddress remoteAddr;

void setup() {
  size(1000, 800);
  oscP5 = new OscP5(this, 9000);
  board = new GameBoard();
  remoteAddr = new NetAddress("127.0.0.1", 8000);
  server = new Player("Billy", 0); // Put your own name here
  client = new Player("[Waiting...]", 1); // Don't change this name, it will be updated automatically
}

void draw() {
  background(200);
  board.display();
  server.display();
  client.display();
  if (winner != -1) {
    fill(0);
    textSize(24);
    text((winner == 0 ? "Black" : "White") + " wins!", 780, 400);
    return;
  }
  if (online) {
    fill(0);
    textSize(24);
    text((server.isActive() ? server.name : client.name) + "'s turn to go", 780, 400);
    if (server.isActive()) {
      int[] pos = board.detectMouse(mouseX, mouseY);
      if (board.place(pos, server.clr, mouseIsReleased)) {
        OscMessage msg = new OscMessage("/Server");
        msg.add(pos[0] + "," + pos[1]);
        oscP5.send(msg, remoteAddr);
        server.deactivate();
        client.activate();
        if (board.judge(pos) == server.clr) {
          winner = server.clr;
          return;
        }
      }
    }
  }


  mouseIsReleased = false;
}

void mouseReleased() {
  mouseIsReleased = true;
}

void oscEvent(OscMessage msg) {
  if (winner != -1) return;
  String type = msg.typetag();
  if (type.equals("si")) {
    String name = msg.get(0).stringValue();
    client = new Player(name, 1);
    online = true;
    server.activate();
    OscMessage msgSent = new OscMessage("/Server");
    msgSent.add(server.name);
    msgSent.add(0);
    oscP5.send(msgSent, remoteAddr);
    
  } else {
    String[] posStr = msg.get(0).stringValue().split(",");
    int x = Integer.parseInt(posStr[0]);
    int y = Integer.parseInt(posStr[1]);
    int[] pos = {x, y};
    board.place(pos, client.clr, true);
    if (board.judge(pos) == client.clr) {
      winner = client.clr;
      return;
    }
    client.deactivate();
    server.activate();
  }
}


/* Client side */
import oscP5.*;
import netP5.*;

boolean mouseIsReleased = false;
boolean online = false;
int winner = -1;

OscP5 oscP5;
GameBoard board;
Player server;
Player client;
NetAddress remoteAddr;

void setup() {
  size(1000, 800);
  oscP5 = new OscP5(this, 8000);
  board = new GameBoard();
  remoteAddr = new NetAddress("127.0.0.1", 9000);
  server = new Player("[Waiting...]", 0); // Don't change this name, it will be updated automatically
  client = new Player("Yijie", 1); // Put your own name here
  OscMessage msg = new OscMessage("/Client");
  msg.add(client.name);
  msg.add(0);
  oscP5.send(msg, remoteAddr);
}

void draw() {
  background(200);
  board.display();
  server.display();
  client.display();
  if (winner != -1) {
    fill(0);
    textSize(24);
    text((winner == 0 ? "Black" : "White") + " wins!", 780, 400);
    return;
  }
  if (online) {
    fill(0);
    textSize(24);
    text((client.isActive() ? client.name : server.name) + "'s turn to go", 780, 400);
    if (client.isActive()) {
      int[] pos = board.detectMouse(mouseX, mouseY);
      if (board.place(pos, client.clr, mouseIsReleased)) {
        OscMessage msg = new OscMessage("/Client");
        msg.add(pos[0] + "," + pos[1]);
        oscP5.send(msg, remoteAddr);
        client.deactivate();
        server.activate();
        if (board.judge(pos) == client.clr) {
          winner = client.clr;
          return;
        }
      }
    }
  }


  mouseIsReleased = false;
}

void mouseReleased() {
  mouseIsReleased = true;
}

void oscEvent(OscMessage msg) {
  if (winner != -1) return;
  String type = msg.typetag();
  if (type.equals("si")) {
    String name = msg.get(0).stringValue();
    server = new Player(name, 0);
    online = true;
    server.activate();
  } else {
    String[] posStr = msg.get(0).stringValue().split(",");
    int x = Integer.parseInt(posStr[0]);
    int y = Integer.parseInt(posStr[1]);
    int[] pos = {x, y};
    board.place(pos, server.clr, true);
    if (board.judge(pos) == server.clr) {
      winner = server.clr;
      return;
    }
    server.deactivate();
    client.activate();
  }
}

/* Board class */
class GameBoard {
  int startX, startY;
  int endX, endY;
  int gap;
  int[][] board;

  GameBoard() {
    this.board = new int[15][15];
    for (int i = 0; i < 15; i++) {
      for (int j = 0; j < 15; j++) {
        this.board[i][j] = -1;
      }
    }
    this.startX = 50;
    this.startY = 50;
    this.gap = 50;
    this.endX = this.startX + this.gap * 14;
    this.endY = this.startY + this.gap * 14;
  }

  int[] detectMouse(int mx, int my) {
    int[] result = {-1, -1};
    int dx = mx - this.startX;
    int dy = my - this.startY;
    int ix = dx / this.gap;
    int iy = dy / this.gap;
    int diffX = dx % this.gap;
    int diffY = dy % this.gap;
    if (diffX > 40) ix++;
    if (diffY > 40) iy++;
    if (mx < this.startX - 10 || mx > this.endX + 10 || my < this.startY - 10 || my > this.endY + 10 || (diffX > 10 && diffX < 40) || (diffY > 10 && diffY < 40)) {
      cursor(ARROW);
      return result;
    } else {
      if (this.board[ix][iy] != -1) {
        cursor(ARROW); 
        return result;
      }
      cursor(HAND);
      result[0] = ix;
      result[1] = iy;
      return result;
    }
  }
  
  int maxConnection(int x, int y, int clr) {
    int result = 0;
    
    /* horizontal */
    int tmp = 0;
    for (int i = 1; i <= 4; i++) {
      if (x + i > 14 || this.board[x + i][y] != clr) break;
      tmp++;
    }
    for (int i = 1; i <= 4; i++) {
      if (x - i < 0 || this.board[x - i][y] != clr) break;
      tmp++;
    }
    if (tmp > result) result = tmp;
    
    
    /* vertical */
    tmp = 0;
    for (int i = 1; i <= 4; i++) {
      if (y + i > 14 || this.board[x][y + i] != clr) break;
      tmp++;
    }
    for (int i = 1; i <= 4; i++) {
      if (y - i < 0 || this.board[x][y - i] != clr) break;
      tmp++;
    }
    if (tmp > result) result = tmp;
    
    
    /* left-bottom */
    tmp = 0;
    for (int i = 1; i <= 4; i++) {
      if (y + i > 14 || x - i < 0 || this.board[x - i][y + i] != clr) break;
      tmp++;
    }
    for (int i = 1; i <= 4; i++) {
      if (y - i < 0 || x + i > 14 || this.board[x + i][y - i] != clr) break;
      tmp++;
    }
    if (tmp > result) result = tmp;
    
    /* left-top */
    tmp = 0;
    for (int i = 1; i <= 4; i++) {
      if (y + i > 14 || x + i > 14 || this.board[x + i][y + i] != clr) break;
      tmp++;
    }
    for (int i = 1; i <= 4; i++) {
      if (y - i < 0 || x - i < 0 || this.board[x - i][y - i] != clr) break;
      tmp++;
    }
    if (tmp > result) result = tmp;
    
    return result + 1;
  }
  
  int judge(int[] pos) {
    int x = pos[0];
    int y = pos[1];
    if (x == -1 || y == -1) return -1;
    
    int clr = this.board[x][y];
    int maxCon = this.maxConnection(x, y, clr);
    if (maxCon >= 5) return clr;
    return -1;
  }

  boolean place(int[] pos, int player, boolean valid) {
    if (!valid) return false;
    if (pos[0] == -1 || pos[1] == -1) return false;
    if (player == 0) {
      this.board[pos[0]][pos[1]] = 0;
    } else {
      this.board[pos[0]][pos[1]] = 1;
    }
    return true;
  }

  void display() {
    fill(215, 188, 156);
    noStroke();
    rect(this.startX, this.startY, this.gap * 14, this.gap * 14);
    fill(0);
    stroke(0);
    strokeWeight(3);
    for (int i = 0; i < 15; i++) {
      line(this.startX + i * this.gap, this.startY, this.startX + i * this.gap, this.endY);
      line(this.startX, this.startY + i * this.gap, this.endX, this.startY + i * this.gap);
    }
    ellipse(this.startX + this.gap * 3, this.startY + this.gap * 3, 10, 10);
    ellipse(this.startX + this.gap * 11, this.startY + this.gap * 3, 10, 10);
    ellipse(this.startX + this.gap * 3, this.startY + this.gap * 11, 10, 10);
    ellipse(this.startX + this.gap * 11, this.startY + this.gap * 11, 10, 10);
    ellipse(this.startX + this.gap * 7, this.startY + this.gap * 7, 10, 10);
    for (int i = 0; i < 15; i++) {
      for (int j = 0; j < 15; j++) {
        int pt = this.board[i][j];
        if (pt == -1) continue;
        noStroke();
        fill(pt == 0 ? 0 : 255);
        ellipse(this.startX + i * this.gap, this.startY + j * this.gap, 25, 25);
      }
    }
  }
}

/* Player class */
class Player {
  String name;
  boolean inTurn;
  int clr;

  Player(String _name, int _clr) {
    this.name = _name;
    this.clr = _clr;
    this.inTurn = false;
  }
  
  boolean isActive() {
    return this.inTurn;
  }
  
  void activate() {
    this.inTurn = true;
  }
  
  void deactivate() {
    this.inTurn = false;
  }

  void display() {
    fill(this.clr == 0 ? 0 : 255);
    textSize(40);
    if (this.clr == 0) {
      text(this.name, 780, 100);
    } else {
      text(this.name, 780, 700);
    }
  }
}

Kinetic Interfaces: W12 | Kevin Xu (Moon)

For this project I wanted to be able to use the X Y of the closest point to move around an ellipse on the screen. At first I used a series of if-else statements stating that if the closest point was approaching from one side then it would push the ball the opposite direction. This […]

import KinectPV2.*;
import controlP5.*;
ControlP5 cp5;
KinectPV2 kinect2;
PImage depthImg;
float ballX = 266;
float ballY = 212;
float diffX, diffY;
int thresholdMin = 0;
int thresholdMax = 4499;
float closestX = 0;
float closestY = 0;
void setup() {
  size(512, 424, P2D);
  kinect2 = new KinectPV2(this);
  kinect2.enableDepthImg(true);
  kinect2.init();
  depthImg = new PImage(KinectPV2.WIDTHDepth, KinectPV2.HEIGHTDepth, ARGB);
  int sliderW = 100;
  int sliderH = 20;
  cp5 = new ControlP5( this );
  cp5.addSlider("thresholdMin")
    .setPosition(10, 40)
    .setSize(sliderW, sliderH)
    .setRange(1, 4499)
    .setValue(0)
    ;
  cp5.addSlider("thresholdMax")
    .setPosition(10, 70)
    .setSize(sliderW, sliderH)
    .setRange(1, 4499)
    .setValue(4499)
    ;
}

void draw() {
  background(0);
  int depthMin = 4499;
  int[] rawDepth = kinect2.getRawDepthData();
  depthImg.loadPixels();
  for (int i=0; i < rawDepth.length; i++) {
    int depth = rawDepth[i];
    if (depth >= thresholdMin
      && depth <= thresholdMax
      && depth != 0) {
      int x = i % KinectPV2.WIDTHDepth;
      int y = floor(i / KinectPV2.WIDTHDepth);
      float r = map(depth, thresholdMin, thresholdMax, 255, 0);
      float b = map(depth, thresholdMin, thresholdMax, 0, 255);
      depthImg.pixels[i] = color(r, 0, b);

      if (depthMin > depth){
        depthMin = depth;
        closestX = x;
        closestY = y;
      }
    } else {
      depthImg.pixels[i] = color(0, 0);
    }
  }
  depthImg.updatePixels();
  image(kinect2.getDepthImage(), 0, 0);
  image(depthImg, 0, 0);
  if (closestX<=ballX+23 && closestX>=ballX-23 && closestY<=ballY+23 && closestY>=ballY-23) {
    diffX = (closestX-ballX)/10;
    diffY = (closestY-ballY)/10;
    ballX-=diffX;
    ballY-=diffY;
    ballX = constrain(ballX, 25, width-25);
    ballY = constrain(ballY, 25, height-25);
  }
  ellipseMode(CENTER);
  pushStyle();
  noStroke();
  fill(0, 255, 0);
  ellipse(ballX, ballY, 50, 50);
  popStyle();
}

Kinetic Interfaces: Kinect Interaction (Phyllis)

I created a simple interaction with Kinect by making a comparison the center position and the width of the sketch. When the center position is between 1/3 width and 2/3 width, the body within that area will change into a colorful one.When part of you are out of that area, you will get the depth image […]

import org.openkinect.freenect.*;
import org.openkinect.freenect2.*;
import org.openkinect.processing.*;
import gab.opencv.*;
import controlP5.*;

OpenCV opencv;
ControlP5 cp5;

Kinect2 kinect2;
PImage depthImg;
PImage colorImg;

int thresholdMin = 0;
int thresholdMax = 4499;
int depth;

float avgX = 0;
float avgY = 0;


void setup() {
  size(512, 424, P2D);

  kinect2 = new Kinect2(this);
  kinect2.initDepth();
  kinect2.initDevice();

  // Blank image
  depthImg = new PImage(kinect2.depthWidth, kinect2.depthHeight, ARGB);
  colorImg = new PImage(kinect2.depthWidth, kinect2.depthHeight, ARGB);

  // Blank OpenCV Image
  opencv = new OpenCV(this, depthImg);

  // add gui
  int sliderW = 100;
  int sliderH = 20;
  cp5 = new ControlP5( this );
  cp5.addSlider("thresholdMin")
    .setPosition(10, 40)
    .setSize(sliderW, sliderH)
    .setRange(1, 4499)
    .setValue(0)
    ;
  cp5.addSlider("thresholdMax")
    .setPosition(10, 70)
    .setSize(sliderW, sliderH)
    .setRange(1, 4499)
    .setValue(4499)
    ;
}


void draw() {
  background(0);

  int[] rawDepth = kinect2.getRawDepth();
  depthImg.loadPixels();
  colorImg.loadPixels();

  // 1. process the raw depth
  for (int i=0; i < rawDepth.length; i++) {
    depth = rawDepth[i];

    if (depth >= thresholdMin
      && depth <= thresholdMax
      && depth != 0) {

      // depthImage for tracking
      float w = map(depth, thresholdMin, thresholdMax, 255, 100);
      depthImg.pixels[i] = color(w);

      // colorImage to just show
      if (avgX > width/3 && avgX < 2*width/3) {
        float r = map(depth, thresholdMin, thresholdMax, 255, 0);
        float b = map(depth, thresholdMin, thresholdMax, 0, 255);
        colorImg.pixels[i] = color(r, 0, b);
      }
      
      // ok
      
    } else {
      // transparent
      depthImg.pixels[i] = color(0, 0);
      colorImg.pixels[i] = color(0, 0);
    }
  }
  depthImg.updatePixels();
  colorImg.updatePixels();

  // 2. raw depth --> openCV --> improving the sensing quality
  opencv.loadImage(depthImg);
  opencv.gray();
  opencv.threshold(50); // to make the image binary
  opencv.erode();
  opencv.dilate();
  opencv.dilate();
  opencv.erode();

  // 3. get the center position
  float sumX = 0;
  float sumY = 0;
  int count = 0;

  PImage img = opencv.getSnapshot();
  img.loadPixels();

  for (int y = 0; y < img.height; y++) {
    for (int x = 0; x < img.width; x++) {
      int index = x + y * img.width;
      float w = red(img.pixels[index]);

      if (w > 100) {
        sumX += x;
        sumY += y;
        count++;
      }
    }
  }
  

  // get the center position
  if (count > 0) {
    avgX = sumX / count;
    avgY = sumY / count;
  }
  
  //image(img, 0, 0);
  image(kinect2.getDepthImage(), 0, 0);
  image(colorImg, 0, 0);

  // draw the center position
  stroke(0, 255, 0);
  line(avgX, 0, avgX, height);
  line(0, avgY, width, avgY);


  fill(255);
  text(frameRate, 10, 20);
}