Question

I'm currently on a BA course in Fine Art and I've recently started trying to learn programming by reading Greg Borenstein's 'Making Things See'.

The piece I'm developing is an attempt to track multiple centres of mass as the viewers move around the gallery space using the Kinect. I was hoping for the viewers to leave trails on screen and also when they come close to certain areas their proximity would be illustrated by a line or something. I've managed to make one trail but as soon as another person comes into view, their points are suddenly connected. The 'proximity line' also only seems to work for the current user and not the previous ones.

I guess my question really comes down to how to isolate each new user so that I can create functions or classes which apply to all of them but don't interfere with each other..?

Here's the program so far...

import processing.opengl.*;
import SimpleOpenNI.*;
import peasy.*;

PeasyCam cam;
SimpleOpenNI kinect;

ArrayList<PVector> trails;

Hotpoint piece;

PVector currentPosition;
PVector previousPosition;

int pieceX = 0;
int pieceY = 0;
int pieceZ = 2000;
int pieceSize = 500;

void setup() {
  size(1280, 680, OPENGL);
  kinect = new SimpleOpenNI(this);
  kinect.enableDepth();
  kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_NONE);
  kinect.setMirror(true);

  trails = new ArrayList();

  piece = new Hotpoint(pieceX, pieceY, pieceZ, pieceSize);

  cam = new PeasyCam(this, 0, 0, 0, 1000);
}

void draw() {
  background(255);
  kinect.update();
  rotateX(radians(180));

  lights();

  stroke(0);
  strokeWeight(3);

  IntVector userList = new IntVector();
  kinect.getUsers(userList);

  piece.draw();

  for (int i=0; i<userList.size(); i++) {
    int userId = userList.get(i);

    PVector positionCenter = new PVector();
    kinect.getCoM(userId, positionCenter);

    trails.add(positionCenter);

    createTrail();

    piece.check(positionCenter);

    if(piece.check(positionCenter) == true) {
      stroke(255, 0, 0);
      line(positionCenter.x, positionCenter.y, positionCenter.z,
           pieceX, pieceY, pieceZ);
      stroke(0);
    }
  }
}

void createTrail() {
  for (int e=1; e < trails.size(); e++) {
    currentPosition = trails.get(e);
    previousPosition = trails.get(e-1);
    if (currentPosition.z < 1) {
      trails.clear();
    } 
    else {
      stroke(0);
      line(previousPosition.x, previousPosition.y, previousPosition.z, 
      currentPosition.x, currentPosition.y, currentPosition.z);
    }
  }
}

And this is the Hotpoint class part...

class Hotpoint {
  PVector center;
  color fillColor;
  color strokeColor;
  int size;
  int pointsIncluded;
  int maxPoints;
  boolean wasJustHit;
  int threshold;


  Hotpoint(float centerX, float centerY, float centerZ, int boxSize) {
    center = new PVector(centerX, centerY, centerZ);
    size = boxSize;
    pointsIncluded = 0;
    maxPoints = 1000;
    threshold = 0;

    strokeColor = color(random(255), random(255), random(255));
    fillColor = 0;
  }

  void setThreshold( int newThreshold ){
    threshold = newThreshold;
  }

  void setMaxPoints( int newMaxPoints ){
    maxPoints = newMaxPoints;
  }

  void setColor(float red, float blue, float green){
    fillColor = strokeColor = color(red, blue, green);
  }

  boolean check(PVector point) {
    boolean result = false;

    if (point.x > center.x - size/2 && point.x < center.x + size/2) {
      if (point.y > center.y - size/2 && point.y < center.y + size/2) {
        if (point.z > center.z - size/2 && point.z < center.z + size/2) {
          result = true;
          pointsIncluded++;
        }
      }
    }

    return result;
  }

  void draw() {
    pushMatrix();
      translate(center.x, center.y, center.z);
      shapeMode(LINES);
      noFill();
      stroke(red(strokeColor), blue(strokeColor), green(strokeColor), 255);
      box(size);
    popMatrix();
  }


  float percentIncluded() {
    return map(pointsIncluded, 0, maxPoints, 0, 1);
  }


  boolean currentlyHit() {
    return (pointsIncluded > threshold);
  }


  boolean isHit() {
    return currentlyHit() && !wasJustHit;
  }

  void clear() {
    wasJustHit = currentlyHit();
    pointsIncluded = 0;
  }
}

Any help would be appreciated immensely!


EDIT:

Thank you so much for your time and your answer @jesses.co.tt but I've been having trouble understanding it... For example, is the loop over the userList not the same thing as an array of users? I'm worried I'm asking more than one thing at a time, so I've broken it down to try and understand firstly the drawing of multiple trails without people being linked.

import processing.opengl.*;
import SimpleOpenNI.*;
import peasy.*;

SimpleOpenNI kinect;
PeasyCam cam;

ArrayList<PVector> trails1;
ArrayList<PVector> trails2;

PVector currentPosition;
PVector previousPosition;

void setup() {
  size(1280, 800, OPENGL);

  kinect = new SimpleOpenNI(this);
  kinect.enableDepth();
  kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_NONE);
  kinect.setMirror(true);

  trails1 = new ArrayList();
  trails2 = new ArrayList();

  cam = new PeasyCam(this, 0, 0, 0, 1000);
}

void draw() {
  kinect.update();
  rotateX(radians(180));
  background(255);

  IntVector userList = new IntVector();
  kinect.getUsers(userList);

  //println(userList);

  for (int i=0; i<userList.size(); i++) {
    int userId = userList.get(i);
    //println(userId);
    PVector positionCenter = new PVector();
    kinect.getCoM(userId, positionCenter);

    stroke(0);
    strokeWeight(10);
    point(positionCenter.x, positionCenter.y, positionCenter.z);

    if (userId == 1) {

      trails1.add(positionCenter);
      createTrail1();
    } 
    else if (userId == 2) {
      trails2.add(positionCenter);
      createTrail2();
    }
  }
}

void createTrail1() {
  for (int e=1; e < trails1.size(); e++) {
    currentPosition = trails1.get(e);
    previousPosition = trails1.get(e-1);
    if (currentPosition.z < 1) { // [possibly x or y or all?]
      trails1.clear();
    } 
    else {
      // if (currentPosition.x != 0 || previousPosition.x != 0) { // [not working]
      stroke(0);
      line(previousPosition.x, previousPosition.y, previousPosition.z, 
      currentPosition.x, currentPosition.y, currentPosition.z);
      //trails.clear();
    }
  }
}

void createTrail2() {
  for (int e=1; e < trails2.size(); e++) {
    currentPosition = trails2.get(e);
    previousPosition = trails2.get(e-1);
    if (currentPosition.z < 1) { // [possibly x or y or all?]
      trails2.clear();
    } 
    else {
      // if (currentPosition.x != 0 || previousPosition.x != 0) { // [not working]
      stroke(0);
      line(previousPosition.x, previousPosition.y, previousPosition.z, 
      currentPosition.x, currentPosition.y, currentPosition.z);
      //trails.clear();
    }
  }
}

So, this would work for two people, and I could write a horrendously long program to work for a large finite number of people, but what I really would like is for it to be dynamic... Where it is 'if (userId == 1) {', I'd want that to work for everyone, then in the trail part, there'd need to be a new array of trails so that every time a new person came into view I'd use the 'void onNewUser(int userId) {' or something..?

Was it helpful?

Solution

As far as I can tell, you need to make a resizable list of Users - which is provided to you by SimpleOpenNI already - and make a new instance of your HotPoint Class for each new user you find (or delete it for each user that disappears)...

You're almost there, as you are iterating properly over the list of known Users...

You need to add an ArrayList of HotPoints that is resized according to the number of users found... then create a new instance of point when a new user is found. The way you have it right now, you only ever have one instance, so if there are two users, it will connect them - which is what you are seeing.

Make sure to delete items from the ArrayList as needed too !

You're really close... ;-)

So...

// Global Variables
ArrayList users;

Then, in your for loop over the users...

// Add a new HotPoint if we have more users than Points
if(i > users.size()) {
  users.add(new HotPoint(...));
}
// Delete From ArrayList if we have too many... 
else if(users.size() > userList.size()) {
  users.remove(...);
} 

// Cast and call methods
HotPoint piece = (HotPoint) users.get(i);
piece.check(positionCenter);
piece.draw();
etc...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top