Skip to content

Commit

Permalink
small update to ofxLeapMotion added ofxLeapMotionSimpleHand with fing…
Browse files Browse the repository at this point in the history
…er velocity and palm position and normal. added debugDraw which shows hand position.
  • Loading branch information
ofTheo committed Jan 9, 2013
1 parent ec5bb07 commit 5e7ea21
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 64 deletions.
6 changes: 4 additions & 2 deletions ofxLeapMotion.xcodeproj/project.pbxproj
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */;
buildSettings = { buildSettings = {
ARCHS = "$(NATIVE_ARCH)"; ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = i386;
CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/"; CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
Expand Down Expand Up @@ -432,7 +433,8 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */;
buildSettings = { buildSettings = {
ARCHS = "$(NATIVE_ARCH)"; ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = i386;
CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/"; CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/";
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
Expand Down
119 changes: 103 additions & 16 deletions src/ofxLeapMotion/src/ofxLeapMotion.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -10,27 +10,69 @@


using namespace Leap; using namespace Leap;


class ofxLeapMotionSimpleHand{
public:

typedef struct{
ofPoint pos;
ofPoint vel;
int64_t id;
}simpleFinger;

vector <simpleFinger> fingers;

ofPoint handPos;
ofPoint handNormal;

void debugDraw(){
ofPushStyle();

ofSetColor(190);
ofSetLineWidth(2);

ofEnableLighting();
ofPushMatrix();
ofTranslate(handPos);
//rotate the hand by the downwards normal
ofQuaternion q;
q.makeRotate(ofPoint(0, -1, 0), handNormal);
ofMatrix4x4 m;
q.get(m);
glMultMatrixf(m.getPtr());


//scale it to make it not a box
ofScale(1, 0.35, 1.0);
ofBox(0, 0, 0, 60);
ofPopMatrix();


for(int i = 0; i < fingers.size(); i++){
ofDrawArrow(handPos, fingers[i].pos, 10);
}

ofSetColor(220, 220, 0);
for(int i = 0; i < fingers.size(); i++){
ofDrawArrow(fingers[i].pos + fingers[i].vel/20, fingers[i].pos + fingers[i].vel/10, 10);
}

ofPopStyle();
}
};

class ofxLeapMotion : public Listener{ class ofxLeapMotion : public Listener{
public: public:


ofxLeapMotion(){ ofxLeapMotion(){
currentFrameID = 0; reset();
preFrameId = -1; resetMapping();

xOffsetIn = 0;
yOffsetIn = 0;
zOffsetIn = 0;

xOffsetOut = 0;
yOffsetOut = 0;
zOffsetOut = 0;

xScale = 1;
yScale = 1;
zScale = 1;

ourController = new Leap::Controller(); ourController = new Leap::Controller();
} }

void reset(){
currentFrameID = 0;
preFrameId = -1;
}


~ofxLeapMotion(){ ~ofxLeapMotion(){
//note we don't delete the controller as it causes a crash / mutex exception. //note we don't delete the controller as it causes a crash / mutex exception.
Expand All @@ -45,6 +87,7 @@ class ofxLeapMotion : public Listener{


//-------------------------------------------------------------- //--------------------------------------------------------------
void open(){ void open(){
reset();
ourController->addListener(*this); ourController->addListener(*this);
} }


Expand Down Expand Up @@ -74,7 +117,7 @@ class ofxLeapMotion : public Listener{


//Simple access to the hands //Simple access to the hands
//-------------------------------------------------------------- //--------------------------------------------------------------
vector <Hand> getHands(){ vector <Hand> getLeapHands(){


vector <Hand> handsCopy; vector <Hand> handsCopy;
if( ourMutex.tryLock(2000) ){ if( ourMutex.tryLock(2000) ){
Expand All @@ -85,6 +128,35 @@ class ofxLeapMotion : public Listener{
return handsCopy; return handsCopy;
} }


//--------------------------------------------------------------
vector <ofxLeapMotionSimpleHand> getSimpleHands(){

vector <ofxLeapMotionSimpleHand> simpleHands;
vector <Hand> leapHands = getLeapHands();

for(int i = 0; i < leapHands.size(); i++){
ofxLeapMotionSimpleHand curHand;

curHand.handPos = getMappedofPoint( leapHands[i].palmPosition() );
curHand.handNormal = getofPoint( leapHands[i].palmNormal() );

for(int j = 0; j < leapHands[i].fingers().count(); j++){
const Finger & finger = hands[i].fingers()[j];

ofxLeapMotionSimpleHand::simpleFinger f;
f.pos = getMappedofPoint( finger.tipPosition() );
f.vel = getMappedofPoint(finger.tipVelocity());
f.id = finger.id();

curHand.fingers.push_back( f );
}

simpleHands.push_back( curHand );
}

return simpleHands;
}

//-------------------------------------------------------------- //--------------------------------------------------------------
bool isFrameNew(){ bool isFrameNew(){
return currentFrameID != preFrameId; return currentFrameID != preFrameId;
Expand All @@ -99,6 +171,21 @@ class ofxLeapMotion : public Listener{
int64_t getCurrentFrameID(){ int64_t getCurrentFrameID(){
return currentFrameID; return currentFrameID;
} }

//--------------------------------------------------------------
void resetMapping(){
xOffsetIn = 0;
yOffsetIn = 0;
zOffsetIn = 0;

xOffsetOut = 0;
yOffsetOut = 0;
zOffsetOut = 0;

xScale = 1;
yScale = 1;
zScale = 1;
}


//-------------------------------------------------------------- //--------------------------------------------------------------
void setMappingX(float minX, float maxX, float outputMinX, float outputMaxX){ void setMappingX(float minX, float maxX, float outputMinX, float outputMaxX){
Expand Down
130 changes: 85 additions & 45 deletions src/testApp.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ void testApp::setup(){
cam.setOrientation(ofPoint(-20, 0, 0)); cam.setOrientation(ofPoint(-20, 0, 0));


glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
} }




Expand All @@ -29,53 +30,86 @@ void testApp::update(){


//if instead you want to get the data as it comes in then you can inherit ofxLeapMotion and implement the onFrame method. //if instead you want to get the data as it comes in then you can inherit ofxLeapMotion and implement the onFrame method.
//there you can work with the frame data directly. //there you can work with the frame data directly.

vector <Hand> hands = leap.getHands();

if( leap.isFrameNew() && hands.size() ){


//leap returns data in mm - lets set a mapping to our world space.
//you can get back a mapped point by using ofxLeapMotion::getMappedofPoint with the Leap::Vector that tipPosition returns
leap.setMappingX(-230, 230, -ofGetWidth()/2, ofGetWidth()/2);
leap.setMappingY(90, 490, -ofGetHeight()/2, ofGetHeight()/2);
leap.setMappingZ(-150, 150, -200, 200);

for(int i = 0; i < hands.size(); i++){
for(int j = 0; j < hands[i].fingers().count(); j++){
ofPoint pt;

const Finger & finger = hands[i].fingers()[j];

cout << "pos is " << finger.tipPosition() << endl;

//here we convert the Leap point to an ofPoint - with mapping of coordinates
//if you just want the raw point - use ofxLeapMotion::getofPoint
pt = leap.getMappedofPoint( finger.tipPosition() );

//lets get the correct trail (ofPolyline) out of our map - using the finger id as the key
ofPolyline & polyline = fingerTrails[finger.id()];

//if the distance between the last point and the current point is too big - lets clear the line
//this stops us connecting to an old drawing
if( polyline.size() && (pt-polyline[polyline.size()-1] ).length() > 50 ){
polyline.clear();
}

//add our point to our trail
polyline.addVertex(pt);

//store fingers seen this frame for drawing
fingersFound.push_back(finger.id());
}
}


}

//tell ofxLeapMotion that the frame is no longer new.
leap.markFrameAsOld();




//Option 1: Use the simple ofxLeapMotionSimpleHand - this gives you quick access to fingers and palms.

simpleHands = leap.getSimpleHands();

if( leap.isFrameNew() && simpleHands.size() ){

leap.setMappingX(-230, 230, -ofGetWidth()/2, ofGetWidth()/2);
leap.setMappingY(90, 490, -ofGetHeight()/2, ofGetHeight()/2);
leap.setMappingZ(-150, 150, -200, 200);

for(int i = 0; i < simpleHands.size(); i++){

for(int j = 0; j < simpleHands[i].fingers.size(); j++){
int id = simpleHands[i].fingers[j].id;

ofPolyline & polyline = fingerTrails[id];
ofPoint pt = simpleHands[i].fingers[j].pos;

//if the distance between the last point and the current point is too big - lets clear the line
//this stops us connecting to an old drawing
if( polyline.size() && (pt-polyline[polyline.size()-1] ).length() > 50 ){
polyline.clear();
}

//add our point to our trail
polyline.addVertex(pt);

//store fingers seen this frame for drawing
fingersFound.push_back(id);
}
}
}


// Option 2: Work with the leap data / sdk directly - gives you access to more properties than the simple approach
// uncomment code below and comment the code above to use this approach. You can also inhereit ofxLeapMotion and get the data directly via the onFrame callback.

// vector <Hand> hands = leap.getLeapHands();
// if( leap.isFrameNew() && hands.size() ){
//
// //leap returns data in mm - lets set a mapping to our world space.
// //you can get back a mapped point by using ofxLeapMotion::getMappedofPoint with the Leap::Vector that tipPosition returns
// leap.setMappingX(-230, 230, -ofGetWidth()/2, ofGetWidth()/2);
// leap.setMappingY(90, 490, -ofGetHeight()/2, ofGetHeight()/2);
// leap.setMappingZ(-150, 150, -200, 200);
//
// for(int i = 0; i < hands.size(); i++){
// for(int j = 0; j < hands[i].fingers().count(); j++){
// ofPoint pt;
//
// const Finger & finger = hands[i].fingers()[j];
//
// //here we convert the Leap point to an ofPoint - with mapping of coordinates
// //if you just want the raw point - use ofxLeapMotion::getofPoint
// pt = leap.getMappedofPoint( finger.tipPosition() );
//
// //lets get the correct trail (ofPolyline) out of our map - using the finger id as the key
// ofPolyline & polyline = fingerTrails[finger.id()];
//
// //if the distance between the last point and the current point is too big - lets clear the line
// //this stops us connecting to an old drawing
// if( polyline.size() && (pt-polyline[polyline.size()-1] ).length() > 50 ){
// polyline.clear();
// }
//
// //add our point to our trail
// polyline.addVertex(pt);
//
// //store fingers seen this frame for drawing
// fingersFound.push_back(finger.id());
// }
// }
// }
//

//IMPORTANT! - tell ofxLeapMotion that the frame is no longer new.
leap.markFrameAsOld();
} }


//-------------------------------------------------------------- //--------------------------------------------------------------
Expand Down Expand Up @@ -112,6 +146,12 @@ void testApp::draw(){
strip.getMesh().draw(); strip.getMesh().draw();
} }


l2.disable();

for(int i = 0; i < simpleHands.size(); i++){
simpleHands[i].debugDraw();
}

m1.end(); m1.end();
cam.end(); cam.end();


Expand Down
3 changes: 2 additions & 1 deletion src/testApp.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class testApp : public ofBaseApp{
void gotMessage(ofMessage msg); void gotMessage(ofMessage msg);


ofxLeapMotion leap; ofxLeapMotion leap;

vector <ofxLeapMotionSimpleHand> simpleHands;

vector <int> fingersFound; vector <int> fingersFound;
ofEasyCam cam; ofEasyCam cam;
ofLight l1; ofLight l1;
Expand Down

0 comments on commit 5e7ea21

Please sign in to comment.