[LEAP motion used] Elipse react to hand position (and the physics add on of punktierd)

The theremin we build using Leap Motion and processing is pretty far, now we are trying to make a visual enhancement accompany the build.

I made the visual part based on a punktierd example called behavior attractor. I basically reversed the process and made it a behavior DEtractor.

Now i'd like to combine the two together. First by adapting the mousx, mousy to righthandx and righthandy. But for some reason it's not working correctly yet using this approach. It might the fault of the code being in the wrong order. Any ideas or suggestions?

Here's the code we are working with (note that both the mouse and hands in leap motion are enabled) (for some reason the forum is not showing the code correctly using the coding raster, so i used the quoting tool but it's still a bit of a mess... excuse me).

import de.voidplus.leapmotion.*; import processing.sound.*; import punktiert.math.Vec; import punktiert.physics.*;

LeapMotion leap; SinOsc sine; Hand leftHand; Hand rightHand;

float freq; float amp; float pos; PVector hL; PVector hR;

int teller = 0; int amount = 100;

// world object VPhysics physics;

// attractor BAttraction attr;

void setup() { size(displayWidth, 700);

leap = new LeapMotion(this); sine = new SinOsc(this);

//Start the Sine Oscillator. sine.play(); sine.amp(amp);

noStroke(); background (#57385c); frameRate (30); smooth();

//set up physics physics = new VPhysics(); physics.setfriction(.4f);

// new AttractionForce: (Vec pos, radius, strength) attr = new BAttraction(new Vec(width * .5f, height * .5f), 400, .01f); physics.addBehavior(attr);

//

// val for arbitrary radius float rad = attr.getRadius()/4; // vector for position Vec pos = new Vec (random(rad, width/2 - rad), random(rad, height/2 - rad)); // create particle (Vec pos, mass, radius) VParticle particle = new VParticle(pos, 9, rad); // add Collision Behavior particle.addBehavior(new BCollision()); // add particle to world physics.addParticle(particle);

for (int i = 1; i < amount; i++) { // val for arbitrary radius float rad2 = random(2, 20); // vector for position Vec pos2 = new Vec(random(rad2, width - rad2), random(rad2, height - rad2)); // create particle (Vec pos, mass, radius) VParticle particle2 = new VParticle(pos2, 8, rad2); // add Collision Behavior particle2.addBehavior(new BCollision()); // add particle to world physics.addParticle(particle2); } }

void draw() { background(255); smooth();

for (Hand hand : leap.getHands()) { boolean handIsLeft = hand.isLeft(); boolean handIsRight = hand.isRight();

leftHand = leap.getLeftHand(); hL = leftHand.getPosition(); rightHand = leap.getRightHand(); hR = rightHand.getPosition(); //----------------------- LEFT HAND ----------------------------------

if (handIsLeft) {
  text("leftHand-X=" +hL.x, 10, 15); //shows hL.x in sketch
  text("leftHand-Y=" +hL.y, 10, 30); //shows hL.y in sketch
  text("leftHand-Z=" +hL.z, 10, 45); //shows hL.z in sketch
  text("volume(in %)= " +nf(amp*100, 1, -3), 10, 60);

  leftHand.draw();
  // Map leftHandY van 0.0 to 1.0 voor amplitude (volume)
  amp=map(hL.y, 0, height, 1.0, 0.0);
} 

sine.amp(amp);

//----------------------- RIGHT HAND ----------------------------------  
if (handIsRight) {
  text("rightHand-X= " +hR.x, width-160, 15); //shows hL.x in sketch
  text("rightHand-Y= " +hR.y, width-160, 30); //shows hL.y in sketch
  text("rightHand-Z= " +hR.z, width-160, 45); //shows hL.z in sketch
  text("freq(in Hz)= " +nf(freq, 3, -3), width-160, 60);

  rightHand.draw();
  // Map rightHandX van 100Hz to 800Hz voor frequency
  freq=map(hR.x, 0, width, 100.0, 800.0);
}
if (!handIsLeft && handIsRight) {
  amp = 0;
}
sine.freq(freq);

} physics.update();

noFill(); stroke(200, 0, 0); // set pos to mousePosition attr.setAttractor(new Vec(hR.x, hR.y)); //ellipse(attr.getAttractor().x, attr.getAttractor().y, attr.getRadius(), attr.getRadius());

noStroke(); fill(0, 125);

teller = 0; for (VParticle p : physics.particles) { println(teller);

if (teller == 0) {
  p.set(mouseX, mouseY);
  ellipse(p.x, p.y, p.getRadius() * 2, p.getRadius() * 2);
  teller++;
}
if (teller == 1);
{
  ellipse(p.x, p.y, p.getRadius() * 2, p.getRadius() * 2);
}

} }

Answers

  • I have been playing with the Leap Motion for the last couple of days ever since I discovered the "Leap Motion for Processing" library.

    The biggest problem that you have is that sometimes the Leap Motion library does not immediately provide data. To demonstrate this I modified example sketch "LM_1_Basics". It can take up to 99 msecs for the Leap Motion to connect, that's a really long time from the sketches point of view.

    In your original code you were assuming the the right-hand's position data was available from the very first iteration of the draw(). Unfortunately, initially it isn't, I modified your code to illustrate this problem:

    import de.voidplus.leapmotion.*; 
    import processing.sound.*; 
    import punktiert.math.Vec; 
    import punktiert.physics.*;
    
    LeapMotion leap; 
    SinOsc sine; 
    Hand leftHand; 
    Hand rightHand;
    
    float freq; 
    float amp; 
    float pos; 
    PVector hL; 
    PVector hR;
    
    int teller = 0; 
    int amount = 100;
    
    // world object
    VPhysics physics;
    
    // attractor
    BAttraction attr;
    
    void setup() { 
      //size(displayWidth, 700);
      size(1280, 720); // HD 720P
    
      leap = new LeapMotion(this); 
      sine = new SinOsc(this);
    
      //Start the Sine Oscillator.
      sine.play();
      sine.amp(amp);
    
      noStroke(); 
      background(#57385c); 
      //frameRate(30); 
      smooth();
    
      //set up physics
      physics = new VPhysics();
      physics.setfriction(0.4f);
    
      // new AttractionForce: (Vec pos, radius, strength)
      attr = new BAttraction(new Vec(width * .5f, height * .5f), 400, .01f);
      physics.addBehavior(attr);
      //
      // val for arbitrary radius
      float rad = attr.getRadius()/4;
      // vector for position
      Vec pos = new Vec (random(rad, width/2 - rad), random(rad, height/2 - rad));
      // create particle (Vec pos, mass, radius)
      VParticle particle = new VParticle(pos, 9, rad);
      // add Collision Behavior
      particle.addBehavior(new BCollision());
      // add particle to world
      physics.addParticle(particle);
    
      for (int i = 1; i < amount; i++) {
        // val for arbitrary radius
        float rad2 = random(2, 20);
        // vector for position
        Vec pos2 = new Vec(random(rad2, width - rad2), random(rad2, height - rad2));
        // create particle (Vec pos, mass, radius)
        VParticle particle2 = new VParticle(pos2, 8, rad2);
        // add Collision Behavior
        particle2.addBehavior(new BCollision());
        // add particle to world
        physics.addParticle(particle2);
      }
    }
    
    void draw() { 
      background(255); 
      smooth();
    
      for (Hand hand : leap.getHands()) { 
        boolean handIsLeft = hand.isLeft(); 
        boolean handIsRight = hand.isRight();
    
        leftHand = leap.getLeftHand(); 
        hL = leftHand.getPosition();
        if (hL == null) println("No LH data!");
    
        rightHand = leap.getRightHand(); 
        hR = rightHand.getPosition();
        if (hR == null) println("No RH data!");
    
        //----------------------- LEFT HAND ----------------------------------
        if (handIsLeft) {
          text("leftHand-X=" + hL.x, 10, 15); //shows hL.x in sketch
          text("leftHand-Y=" + hL.y, 10, 30); //shows hL.y in sketch
          text("leftHand-Z=" + hL.z, 10, 45); //shows hL.z in sketch
          text("volume(in %)= " + nf(amp*100, 1, -3), 10, 60);
    
          leftHand.draw();
          // Map leftHandY van 0.0 to 1.0 voor amplitude (volume)
          amp = map(hL.y, 0, height, 1.0, 0.0);
        } 
    
        sine.amp(amp);
    
        //----------------------- RIGHT HAND ----------------------------------  
        if (handIsRight) {
          text("rightHand-X= " + hR.x, width-160, 15); // shows hL.x in sketch
          text("rightHand-Y= " + hR.y, width-160, 30); // shows hL.y in sketch
          text("rightHand-Z= " + hR.z, width-160, 45); // shows hL.z in sketch
          text("freq(in Hz)= " + nf(freq, 3, -3), width-160, 60);
    
          rightHand.draw();
          // Map rightHandX van 100Hz to 800Hz voor frequency
          freq = map(hR.x, 0, width, 100.0, 800.0);
        }
    
        if (!handIsLeft && handIsRight) {
          amp = 0;
        }
    
        sine.freq(freq);
      } // end for - hand
    
      physics.update();
    
      noFill(); 
      stroke(200, 0, 0);
    
      // set pos to mousePosition
      Vec mousePos;
    
      // Deal with right-hand position not yet ready?
      // Note: The Leap Motion can take a fraction of a second to start providing data and
      //       this code is outside the "for (Hand hand : leap.getHands())" for-loop ;-)
      if (hR == null) {
        println("hR is null!");
        mousePos = new Vec(mouseX, mouseY); // Added by Niels
      } else {
        println("hand x,y = " + hR.x + "," + hR.y);
        mousePos = new Vec(hR.x, hR.y); // Added by Niels
      }
    
      attr.setAttractor(mousePos);
    
      //ellipse(attr.getAttractor().x, attr.getAttractor().y, attr.getRadius(), attr.getRadius());
    
      noStroke(); 
      fill(0, 125);
    
      teller = 0; 
      for (VParticle p : physics.particles) { 
        //println("teller= " + teller);
    
        if (teller == 0) {
          p.set(mouseX, mouseY);
          ellipse(p.x, p.y, p.getRadius() * 2, p.getRadius() * 2);
          teller++;
        }
    
        if (teller == 1); {
          ellipse(p.x, p.y, p.getRadius() * 2, p.getRadius() * 2);
        }
      } // end for - p
    }
    

    With no call to frameRate() specified Processing will call draw() as quickly as it can. When I run the modified sketch I see the following in the console window:

    # Leap Motion Library v2.3.1.6 - Leap Motion SDK v2.3.1+31549 - https://github.com/nok/leap-motion-processing hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! hR is null! translate(), or this particular variation of it, is not available with this renderer. hand x,y = 647.9134,592.4121 hand x,y = 786.3234,530.3577 hand x,y = 767.5345,525.84015 hand x,y = 745.8991,519.5922

    So you see you need to handle the situation where you don't immediately get data from the Leap Motion.

Sign In or Register to comment.