Class/Object as a PVector for Kinect repelling


#1

Hi! First time posting on here.
I’m writing a Sketch for a Kinect camera to make an attractor/repeller for some particles.
I started out with an attraction/repelling tutorial from Daniel Shiffmann and tried to combine it with his Kinect series.
My main issue right now is that the Particle Class needs a PVector as an argument for the attracted function, but as I want the Attractor object to be that argument, I don’t know where to go from here. Can a class/object be a PVector, or should I approach it completely different? The Kinect stuff and getting the Attractor to be in the average position of the Kinect pixels work. And if I make the argument for the attracted function the mouse as a new PVector, it works as well.
There are three documents, I’ll post them here. I’ll appreciate any help. Thanks!

main sketch

import java.util.*;
import org.openkinect.processing.*;

// Call kinect object
Kinect kinect;

// Kinect view area depth
float minThresh = 0;
float maxThresh = 600;

// The kinect video feed
PImage img;

// Arrays for attractors / repellers and particles
//List<PVector> attractors = new ArrayList<PVector>();
// New attractor object
Attractor attractor;
List<Particle> particles = new ArrayList<Particle>();

void setup() {
  size(640, 480);
  kinect = new Kinect(this);
  kinect.initDepth();
  kinect.enableMirror(true);
  img = createImage(kinect.width, kinect.height, RGB);

  for (int i = 0; i < 200; i++) {
    particles.add(new Particle(random((width-15) + 15), random((height - 15) + 15)));
  }
}

//void mousePressed() {
//  attractors.add(new PVector(mouseX, mouseY));
//}

void draw() {
  background(120);
  stroke(255);
  strokeWeight(4);

  img.loadPixels();

  int[] depth = kinect.getRawDepth();

  float sumX = 0;
  float sumY = 0;
  float totalPixels = 0;

  for (int x = 0; x < kinect.width; x++) {
    for (int y = 0; y < kinect.height; y++) {
      int offset = x + y * kinect.width;
      int d = depth[offset];
      int index = x + y * kinect.width;

      if (d > minThresh && d < maxThresh) {
        // What happens inside depth vield field
        img.pixels[index] = color(255, 0, 150);

        sumX += x;
        sumY += y;
        totalPixels++;
      } else {
        // what happens outside depth view field
        img.pixels[index] = color(0, 0, 0, 0);
      }
    }
  }

  img.updatePixels();
  image(img, 0, 0);

  float avgX = sumX / totalPixels;
  float avgY = sumY / totalPixels;
  PVector avgSum = new PVector(avgX, avgY);

  attractor = new Attractor(avgSum);
  attractor.show();

  //attractors.add(new PVector(avgX, avgY));

  // Create attractors
  //for (int i = 0; i < attractors.size(); i++) {
  //  stroke(0, 255, 0);
  //  point(attractors.get(i).x, attractors.get(i).y);
  //}

  // Create Particles
  for (int i = 0; i < particles.size(); i++) {
    Particle particle = particles.get(i);
    //for (int j = 0; j < attractors.size(); j++) {
    //particle.attracted();
    //}
    particle.update();
    particle.show();
  }
}

Attractor

class Attractor {
  PVector pos;
  PVector prev;

  Attractor(PVector position) {
    pos = new PVector(position.x, position.y);
    prev = new PVector(position.x, position.y);
  }

  void show() {
    stroke(0, 255, 0, 255);
    strokeWeight(8);
    
    line(this.pos.x, this.pos.y, this.prev.x, this.prev.y);

    prev.x = pos.x;
    prev.y = pos.y;
  }
}

Particle

class Particle {
  PVector pos;
  PVector prev;
  PVector vel;
  PVector acc;

  Particle(float x, float y) {
    pos = new PVector(x, y);
    prev = new PVector(x, y);
    vel = new PVector(); //p5.Vector.random2D();
    //vel = PVector.random2D();
    //vel.setMag(random(2, 5));
    acc = new PVector();
  }

  void update() {
    vel.add(acc);
    vel.limit(5);
    pos.add(vel);
    acc.mult(0);
    
    if(pos.x + 10 > width || pos.x - 10 < 0) {
      vel.x = -vel.x;
    }
    if(pos.y + 10 > height || pos.y - 10 < 0) {
      vel.y = -vel.y;
    }
  }

  void show() {
    stroke(255, 255);
    strokeWeight(4);
    line(this.pos.x, this.pos.y, this.prev.x, this.prev.y);

    prev.x = pos.x;
    prev.y = pos.y;
  }

  void attracted(PVector target) {
    // PVector dir = target - pos
    PVector force = PVector.sub(target, pos);
    float d = force.mag();
    d = constrain(d, 1, 50);
    float G = 50;
    float strength = G / (d * d);
    force.setMag(strength);
    force.mult(-1);
    //if (d < 40) {
    //  force.mult(-20);
    //}
    acc.add(force);
  }
};

#2

If I understand your problem correctly you want the attracted method to take an Attractor object as the parameter instead of a PVector. Please clarify if I misunderstood. But if that’s the case you have a couple different options. First is to just use the pos variable of the attractor when calling the attracted method. Like:

for (int j = 0; j < attractors.size(); j++) {
  particle.attracted(attractors.get(j).pos);
}

This option will leave you with flexibility but you can’t access other parts of the of the Attractor within the attracted() method. A simple way to streamline this is with method overloading. Where you have multiple methods with the same name but different parameters. Like:

// in Particle class
void attracted(Attractor attractor) {
  attracted(attractor.pos);
}

// if you did this the code from above would be
particle.attracted(attractors.get(j));

If you need to use some parts of the Attractor in the attracted() method you could modify your attracted() method to just take in an Attractor instead of a PVector. Which would look something like:

void attracted(Attractor attractor) {
  PVector target = attractor.pos;
  PVector force = PVector.sub(target, pos);
  float d = force.mag();
  // ... the rest of the method
}

Let me know if that doesn’t make sense because I feel like I jump around a fair amount and might be making it overly complicated.


#3

Hi @figraham
Thank you so much for the reply! I’ll try out the methods you described and return and see what results I get.
I’m sorry if my post wasn’t clear. What I basically want is the attractor to be in the avgX and avgY position, so that the object follows my hand around with the kinect, and pushed away the particles as I do so.

I’ll get back to this post when I’ve tried it and will tell about results and errors.