fdata get_finger_positions() { Leap::Frame frame = control.frame(); Leap::FingerList fingers = frame.fingers(); Leap::ToolList tools = frame.tools(); Leap::HandList hands = frame.hands(); //std::vector<std::pair<cl_float4, int>> positions; fdata hand_data; int p = 0; for(int i=0; i<40; i++) { hand_data.fingers[i] = 0.0f; } ///will explode if more than 2 for(int i=0; i<hands.count(); i++) { const Leap::Hand hand = hands[i]; Leap::FingerList h_fingers = hand.fingers(); float grab_strength = hand.grabStrength(); hand_data.grab_confidence[i] = grab_strength; for(int j=0; j<h_fingers.count(); j++) { const Leap::Finger finger = h_fingers[j]; float mfingerposx = finger.tipPosition().x; float mfingerposy = finger.tipPosition().y; float mfingerposz = finger.tipPosition().z; //cl_float4 ps = {mfingerposx, mfingerposy, mfingerposz, 0.0f}; //cl_float4 ps = {mfingerposx, mfingerposy, mfingerposz, 0.0f}; int id = finger.id(); hand_data.fingers[p++] = mfingerposx; hand_data.fingers[p++] = mfingerposy; hand_data.fingers[p++] = mfingerposz; hand_data.fingers[p++] = 0.0f; //positions.push_back(std::pair<cl_float4, int>(ps, id)); } } return hand_data; }
void ManipTool::onLeapFrame( Leap::Frame const &aFrame ) { if( (aFrame.timestamp() - mLastExaminedFrame ) < 16*1000 ) return; if( aFrame.hands().count() > 2 ) return; mLastExaminedFrame = aFrame.timestamp(); U16 curFrame = getNextFrameNo( mLastStoredFrame ); Fingers &curFingers = mFingersPerFrame[ curFrame ]; U16 curFinger = 0; curFingers.clear(); curFingers.mTimestamp = mLastExaminedFrame; Leap::HandList hands = aFrame.hands(); for( int i = 0; i < hands.count(); ++i ) { for( int j = 0; j < hands[i].fingers().count(); ++j ) { Leap::Finger oFinger( hands[i].fingers()[j] ); Finger &oF = curFingers.mFingers[ curFinger++ ]; oF.mId = oFinger.id(); oF.mTimestamp = mLastExaminedFrame; copy( oFinger.direction(), oF.mDir ); copy( oFinger.tipPosition(), oF.mTip ); oF.mWidth = oFinger.width(); oF.mLength = oFinger.length(); } } curFingers.mStoredFingers = curFinger; if( mTotalStoredFrames > 0 ) { Fingers &prevFingers = mFingersPerFrame[ mLastStoredFrame ]; for( U16 i = 0; i < curFingers.mStoredFingers; ++i ) { Finger &curFinger = curFingers.mFingers[i]; Finger const *prevFinger = prevFingers.getFinger( curFinger.mId ); if( !prevFinger ) continue; subtract( curFinger.mTip, prevFinger->mTip, curFinger.mFromLast ); curFinger.mLenFromLast = normalize( curFinger.mFromLast ); } } mLastStoredFrame = curFrame; ++mTotalStoredFrames; }
void eleap::eleap_t::impl_t::onFrame(const Leap::Controller& controller) { const Leap::Frame frame = controller.frame(); if (frame.isValid()) { // send the known hands in this frame, this will handle hands coming and going const Leap::HandList hands = frame.hands(); { unsigned long long time_encoded = (0&0xffffffff)<<8 | (DATA_KNOWN_HANDS&0xff); float *f; unsigned char *dp; piw::data_nb_t d = ctx_.allocate_host(time_encoded,INT32_MAX,INT32_MIN,0,BCTVTYPE_INT,sizeof(int32_t),&dp,hands.count(),&f); memset(f,0,hands.count()*sizeof(int32_t)); *dp = 0; for(int i = 0; i < hands.count(); ++i) { const Leap::Hand hand = hands[i]; if(hand.isValid() && hand.fingers().count() > 1) { ((int32_t *)f)[i] = hand.id(); } } enqueue_fast(d,1); } // handle the actual data for the detected hands for(int i = 0; i < hands.count(); ++i) { const Leap::Hand hand = hands[i]; if(hand.isValid() && hand.fingers().count() > 1) { unsigned long long time_encoded = (hand.id()&0xffffffff)<<8 | (DATA_PALM_POSITION&0xff); const Leap::Vector palm_pos = hand.palmPosition(); float *f; unsigned char *dp; piw::data_nb_t d = ctx_.allocate_host(time_encoded,600,-600,0,BCTVTYPE_FLOAT,sizeof(float),&dp,3,&f); memset(f,0,3*sizeof(float)); *dp = 0; f[0] = piw::normalise(600,-600,0,palm_pos.x); f[1] = piw::normalise(600,-600,0,palm_pos.y); f[2] = piw::normalise(600,-600,0,palm_pos.z); enqueue_fast(d,1); } } } }
GestureFrame LMRecorder::prepareDataClone(const Leap::Frame frame, double timestamp) { GestureFrame outputFrame; outputFrame.setTimestamp(timestamp); Leap::HandList handsInFrame = frame.hands(); for(int handIndex=0; handIndex<handsInFrame.count(); handIndex++) { Leap::Hand currHand = handsInFrame[handIndex]; //create GestureHand GestureHand gestureHand( currHand.id(), Vertex(currHand.palmPosition().x, currHand.palmPosition().y, currHand.palmPosition().z), Vertex(0, 0, 0/*currHand.stabilizedPalmPosition().x, currHand.stabilizedPalmPosition().y, currHand.stabilizedPalmPosition().z*/), Vertex(currHand.palmNormal().x, currHand.palmNormal().y, currHand.palmNormal().z), Vertex(currHand.direction().x, currHand.direction().y, currHand.direction().z) ); gestureHand.setOrderValue(currHand.palmPosition().x); Vertex planeNormalVec = gestureHand.getDirection().crossProduct(gestureHand.getPalmNormal()).getNormalized(); Leap::FingerList fingersInCurrHand = currHand.fingers(); for (int fingerIndex=0; fingerIndex<fingersInCurrHand.count(); fingerIndex++) { Leap::Finger currFinger = fingersInCurrHand[fingerIndex]; Leap::Vector leapFingerTipPos = currFinger.tipPosition(); Vertex fingerTipPos(leapFingerTipPos.x, leapFingerTipPos.y, leapFingerTipPos.z); float distance = getPointDistanceFromPlane(fingerTipPos, gestureHand.getPalmPosition(), planeNormalVec); //create GestureFinger GestureFinger gestureFinger( currFinger.id(), fingerTipPos, Vertex(currFinger.stabilizedTipPosition().x, currFinger.stabilizedTipPosition().y, currFinger.stabilizedTipPosition(). z), Vertex(currFinger.direction().x, currFinger.direction().y, currFinger.direction().z), currFinger.length(), currFinger.width() ); gestureFinger.setOrderValue(distance); gestureHand.addFinger(gestureFinger); } gestureHand.sortFingers(); outputFrame.addHand(gestureHand); } outputFrame.sortHands(); }
// This experimental mode sends chat messages into SL on a back channel for LSL scripts // to intercept with a listen() event. This is experimental and not sustainable for // a production feature ... many avatars using this would flood the chat system and // hurt server performance. Depending on how useful this proves to be, a better // mechanism should be designed to stream data from the viewer into SL scripts. void LLLMImpl::modeStreamDataToSL(Leap::HandList & hands) { S32 numHands = hands.count(); if (numHands == 1 && mChatMsgTimer.checkExpirationAndReset(LLLEAP_CHAT_MSG_INTERVAL)) { // Get the first (and only) hand Leap::Hand hand = hands[0]; Leap::Vector palm_pos = hand.palmPosition(); Leap::Vector palm_normal = hand.palmNormal(); F32 ball_radius = (F32) hand.sphereRadius(); Leap::Vector ball_center = hand.sphereCenter(); // Chat message looks like "/2343 LM1,<palm pos>,<palm normal>,<sphere center>,<sphere radius>" LLVector3 vec; std::stringstream status_chat_msg; status_chat_msg << "/2343 LM,"; status_chat_msg << "<" << palm_pos.x << "," << palm_pos.y << "," << palm_pos.z << ">,"; status_chat_msg << "<" << palm_normal.x << "," << palm_normal.y << "," << palm_normal.z << ">,"; status_chat_msg << "<" << ball_center.x << "," << ball_center.y << "," << ball_center.z << ">," << ball_radius; FSNearbyChat::instance().sendChatFromViewer(status_chat_msg.str(), CHAT_TYPE_SHOUT, FALSE); } }
void MouseController::onFrame(const Leap::Controller &controller) { // get list of detected screens const Leap::ScreenList screens = controller.calibratedScreens(); // make sure we have a detected screen if (screens.empty()) return; const Leap::Screen screen = screens[0]; // find the first finger or tool const Leap::Frame frame = controller.frame(); const Leap::HandList hands = frame.hands(); if (hands.empty()) return; const Leap::PointableList pointables = hands[0].pointables(); if (pointables.empty()) return; const Leap::Pointable firstPointable = pointables[0]; // get x, y coordinates on the first screen const Leap::Vector intersection = screen.intersect( firstPointable, true, // normalize 1.0f // clampRatio ); // if the user is not pointing at the screen all components of // the returned vector will be Not A Number (NaN) // isValid() returns true only if all components are finite if (! intersection.isValid()) return; unsigned int x = screen.widthPixels() * intersection.x; // flip y coordinate to standard top-left origin unsigned int y = screen.heightPixels() * (1.0f - intersection.y); CGPoint destPoint = CGPointMake(x, y); CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, destPoint); }
string PalmsGesture::checkGesture(const Leap::HandList& hands) { string gesture_out = "NONE"; if (hands.count() !=2 ) { if (gestureBegin) { gestureBegin = false; gesture_out = "LOST_TWO_HANDS"; } return gesture_out; } else { gestureBegin = true; float ddiff = math<float>::abs(hands[0].palmPosition().x - hands[1].palmPosition().x); _diff = ddiff- _prevValue; _prevValue = ddiff; } if (_diff>2.3) { gesture_out = "BIGGER"; console()<<gesture_out<<std::endl; } else if (_diff<-2.3) { gesture_out = "SMALLER"; console()<<gesture_out<<std::endl; } return gesture_out; }
// This controller mode just dumps out a bunch of the Leap Motion device data, which can then be // analyzed for other use. void LLLMImpl::modeDumpDebugInfo(Leap::HandList & hands) { S32 numHands = hands.count(); if (numHands == 1) { // Get the first hand Leap::Hand hand = hands[0]; // Check if the hand has any fingers Leap::FingerList finger_list = hand.fingers(); S32 num_fingers = finger_list.count(); if (num_fingers >= 1) { // Calculate the hand's average finger tip position Leap::Vector pos(0, 0, 0); Leap::Vector direction(0, 0, 0); for (size_t i = 0; i < num_fingers; ++i) { Leap::Finger finger = finger_list[i]; pos += finger.tipPosition(); direction += finger.direction(); // Lots of log spam LL_INFOS("LeapMotion") << "Finger " << i << " string is " << finger.toString() << LL_ENDL; } pos = Leap::Vector(pos.x/num_fingers, pos.y/num_fingers, pos.z/num_fingers); direction = Leap::Vector(direction.x/num_fingers, direction.y/num_fingers, direction.z/num_fingers); LL_INFOS("LeapMotion") << "Hand has " << num_fingers << " fingers with average tip position" << " (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << " direction (" << direction.x << ", " << direction.y << ", " << direction.z << ")" << LL_ENDL; } Leap::Vector palm_pos = hand.palmPosition(); Leap::Vector palm_normal = hand.palmNormal(); LL_INFOS("LeapMotion") << "Palm pos " << palm_pos.x << ", " << palm_pos.y << ", " << palm_pos.z << ". Normal: " << palm_normal.x << ", " << palm_normal.y << ", " << palm_normal.z << LL_ENDL; F32 ball_radius = (F32) hand.sphereRadius(); Leap::Vector ball_center = hand.sphereCenter(); LL_INFOS("LeapMotion") << "Ball pos " << ball_center.x << ", " << ball_center.y << ", " << ball_center.z << ", radius " << ball_radius << LL_ENDL; } // dump_out_data }
bool handForId(int32 checkId, Leap::HandList hands, Leap::Hand& returnHand) { for (int i = 0; i < hands.count(); i++) { Leap::Hand hand = hands[i]; if (checkId == hand.id()){ returnHand = hand; return true; } } return false; }
bool FLeapMotionInputDevice::HandForId(int32 CheckId, Leap::HandList Hands, Leap::Hand& ReturnHand) { for (int i = 0; i < Hands.count(); i++) { Leap::Hand Hand = Hands[i]; if (CheckId == Hand.id()) { ReturnHand = Hand; return true; } } return false; }
void LeapMotionListener::onFrame(const Leap::Controller & controller) { const Leap::Frame frame = controller.frame(); Leap::HandList hands = frame.hands(); for (Leap::HandList::const_iterator hl = hands.begin(); hl!=hands.end();hl++) { const Leap::Hand hand = *hl; QString handType = hand.isLeft() ? "Left hand" : "Right hand"; qDebug()<<handType<<"id: "<<hand.id()<<"palm position: " <<hand.palmPosition().x<<hand.palmPosition().y<<hand.palmPosition().z; QFile f("share.dat"); if(!f.open(QIODevice::WriteOnly | QIODevice::Text)) return; QTextStream out(&f); out<<QString("%1 %2 %3").arg(hand.palmPosition().x) .arg(hand.palmPosition().y).arg(hand.palmPosition().z); f.close(); } }
//-------------------------------------------------------------- void testApp::update(){ Leap::Vector pNormal; Leap::Frame frame = leapController.frame(); Leap::HandList hands = frame.hands(); Leap::Vector pt0; Leap::Vector pt1; if (!hands.isEmpty()) { fingerPos.clear(); sphereSize.clear(); sphereNorm.clear(); spherePos.clear(); //ofLogNotice("hand detected"); //----------------------------------- data collection ------------------------------------------------------------- for (int i = 0; i<hands.count(); i++) { if (i>1) break; Leap::Hand tempHand = hands[i]; Leap::FingerList tempfinger = tempHand.fingers(); for (int j = 0; j <= tempfinger.count(); j++) { ofVec3f pt; Leap::Finger finger = hands[i].fingers()[j]; Leap::Vector tempPT=finger.tipPosition(); pt.x=tempPT.x;pt.y=tempPT.y;pt.z=tempPT.z; fingerPos.push_back(pt); } pt0 = tempHand.palmNormal(); Leap::Vector center = tempHand.sphereCenter(); ofVec3f sp; sp.x = center.x; sp.y = center.y; sp.z = center.z; float r = tempHand.sphereRadius(); spherePos.push_back(sp); sphereSize.push_back(r); sphereNorm.push_back(pt0); ofLogNotice("hand " +ofToString(i) + "normal", ofToString(pt0.x) + " " + ofToString(pt0.y) + " " + ofToString(pt0.z)); ofLogNotice("hand " + ofToString(i) + "center ", ofToString(sp.x) + " " + ofToString(sp.y) + " " + ofToString(sp.z)); } //---------------------------------- state machine ------------------------------------------------------------------ if(phase1==true && phase2 == false && phase3==false && phase4 == false && phase5==false && phase6 == false && phase7 == false && (!fingerPos.empty())) { phase2 = true; state = 1; } if (phase2 == true && (sphereNorm.size()>=2)) { pt0 = sphereNorm[0]; pt1 = sphereNorm[1]; if (abs(abs(pt0.x)-abs(pt1.x))<0.04 && abs(abs(pt0.y)-abs(pt1.y))<0.04) { phase3 = true; phase2 = false; } } } // ofLogNotice("phase1: ", ofToString(phase1)); // ofLogNotice("phase2: ", ofToString(phase2)); // ofLogNotice("phase3: ", ofToString(phase3)); // ofLogNotice("phase4: ", ofToString(phase4)); // ofLogNotice("phase5: ", ofToString(phase5)); // ofLogNotice("phase6: ", ofToString(phase6)); // ofLogNotice("phase7: ", ofToString(phase7)); oldFrame = frame; preId = frame.id(); }
// This controller mode is used to fly the avatar, going up, down, forward and turning. void LLLMImpl::modeFlyingControlTest(Leap::HandList & hands) { static S32 sLMFlyingHysteresis = 0; S32 numHands = hands.count(); BOOL agent_is_flying = gAgent.getFlying(); if (numHands == 0 && agent_is_flying && sLMFlyingHysteresis > 0) { sLMFlyingHysteresis--; if (sLMFlyingHysteresis == 0) { LL_INFOS("LeapMotion") << "LM stop flying - look ma, no hands!" << LL_ENDL; gAgent.setFlying(FALSE); } } else if (numHands == 1) { // Get the first hand Leap::Hand hand = hands[0]; // Check if the hand has any fingers Leap::FingerList finger_list = hand.fingers(); S32 num_fingers = finger_list.count(); Leap::Vector palm_pos = hand.palmPosition(); Leap::Vector palm_normal = hand.palmNormal(); F32 ball_radius = (F32) hand.sphereRadius(); Leap::Vector ball_center = hand.sphereCenter(); // Number of fingers controls flying on / off if (num_fingers == 0 && // To do - add hysteresis or data smoothing? agent_is_flying) { if (sLMFlyingHysteresis > 0) { sLMFlyingHysteresis--; } else { LL_INFOS("LeapMotion") << "LM stop flying" << LL_ENDL; gAgent.setFlying(FALSE); } } else if (num_fingers > 2 && !agent_is_flying) { LL_INFOS("LeapMotion") << "LM start flying" << LL_ENDL; gAgent.setFlying(TRUE); sLMFlyingHysteresis = 5; } // Radius of ball controls forward motion if (agent_is_flying) { if (ball_radius > 110.f) { // Open hand, move fast gAgent.setControlFlags(AGENT_CONTROL_AT_POS | AGENT_CONTROL_FAST_AT); } else if (ball_radius > 85.f) { // Partially open, move slow gAgent.setControlFlags(AGENT_CONTROL_AT_POS); } else { // Closed - stop gAgent.clearControlFlags(AGENT_CONTROL_AT_POS); } // Height of palm controls moving up and down if (palm_pos.y > 260.f) { // Go up fast gAgent.setControlFlags(AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP); } else if (palm_pos.y > 200.f) { // Go up gAgent.setControlFlags(AGENT_CONTROL_UP_POS); } else if (palm_pos.y < 60.f) { // Go down fast gAgent.setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_NEG); } else if (palm_pos.y < 120.f) { // Go down gAgent.setControlFlags(AGENT_CONTROL_UP_NEG); } else { // Clear up / down gAgent.clearControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_POS | AGENT_CONTROL_UP_NEG); } // Palm normal going left / right controls direction if (mYawTimer.checkExpirationAndReset(LLLEAP_YAW_INTERVAL)) { if (palm_normal.x > 0.4f) { // Go left fast gAgent.moveYaw(1.f); } else if (palm_normal.x < -0.4f) { // Go right fast gAgent.moveYaw(-1.f); } } } // end flying controls } }
void jester::LeapMotionImpl::processLeapFrame(Leap::Frame frame) { Leap::HandList handList = frame.hands(); std::vector<Leap::Hand> hands; Leap::Hand right, left; bool foundRight = false, foundLeft = false; clearJointData(); //put all of the hands in a std::vector for (Leap::HandList::const_iterator handsIter = handList.begin(); handsIter != handList.end(); handsIter++) hands.push_back(*handsIter); std::sort(hands.begin(), hands.end(), finger_count_comparator); //search to see if last known hand Ids are still available, assign hand, and delete from available hands // also, delete any unknown hands that have no fingers for (unsigned int i = 0; i < hands.size(); i++) if (hands[i].id() == kRightHandId) { foundRight = true; right = hands[i]; hands.erase(hands.begin() + i); } else if (hands[i].id() == kLeftHandId) { foundLeft = true; left = hands[i]; hands.erase(hands.begin() + i); } else if (hands[i].fingers().count() == 0){ hands.erase(hands.begin() + i); } //figure out how many hands we need int neededHands = 0; if (!foundLeft) neededHands++; if (!foundRight) neededHands++; //assume that the highest finger count objects are the most likely to be hands //only keep as many hands as we need (bounded by the number actually available) hands.erase(hands.begin() + std::min((int) hands.size(), neededHands), hands.end()); //sort by x coordinate std::sort(hands.begin(), hands.end(), hand_x_coordinate_comparator); if (hands.size() == 0 || neededHands == 0) { //if we have or need no hands, do nothing here } else if (neededHands > (int) hands.size()) { //if we need two and only have 1 //assume left side is left, right side is right if (hands[0].palmPosition()[0] < 0) { foundLeft = true; left = hands[0]; kLeftHandId = left.id(); } else { foundRight = true; right = hands[0]; kRightHandId = right.id(); } } else if (foundLeft == false && neededHands == 1) { //if we need left foundLeft = true; left = hands[0]; kLeftHandId = left.id(); } else if (foundRight == false && neededHands == 1) { //if we need right foundRight = true; right = hands[hands.size() - 1]; kRightHandId = right.id(); } else { //if we need both and have two foundLeft = foundRight = true; left = hands[0]; kLeftHandId = left.id(); right = hands[1]; kRightHandId = right.id(); } if (foundLeft) processHand(left, LeapHand::LEFT); if (foundRight) processHand(right, LeapHand::RIGHT); kController->suggestJointInfo(this, kJointData); }
//-------------------------------------------------------------- void testApp::draw(){ ofSetWindowTitle(ofToString(ofGetFrameRate())); //camera.begin(); float r0 = 30; Leap::Vector ptp; Leap::Vector ptp0; Leap::Vector pNormal; ofPushMatrix(); ofTranslate(ofGetWidth()/2, ofGetHeight()); //ofSetColor(255, 255, 255); Leap::Frame frame = leapController.frame(); Leap::HandList hands = frame.hands(); if (!hands.isEmpty()) { //ofLogNotice("hand detected"); int count = hands.count(); for (int i = 0; i<count; i++) { if (i>1) break; Leap::Hand tempHand = hands[i]; pNormal = tempHand.palmNormal(); ofLogNotice("hand " +ofToString(i) + "normal", ofToString(pNormal.x) + " " + ofToString(pNormal.y) + " " + ofToString(pNormal.z)); } Leap::Hand hand = hands[0]; Leap::Hand hand1 = hands[1]; double r = hand.sphereRadius(); //ofLogNotice("r is" + ofToString(r)); r0 = r * 5; ptp = hand1.palmNormal(); ptp0 = hand.palmNormal(); ofLogNotice("distance is ", ofToString(abs(ptp.x)-abs(pNormal.x)) + " " + ofToString(abs(ptp.y)-abs(pNormal.y))); if (abs(abs(ptp.x)-abs(pNormal.x))<0.04 && abs(abs(ptp.y)-abs(pNormal.y))<0.04) { phase1=false; phase2=true; ofLogNotice("phase 2 triggered", ofToString(phase1)); } } if(phase1){ ofSphere(ptp.x,-ptp.y,ptp.z, r0); } vector<Leap::FingerList> fingers = leap.getFingers(); if (!fingers.empty() && phase1==false && phase2 == false && phase3==false && phase4==false && phase5==false && phase6 == false && phase7 == false) { //ofLogNotice("finger detected"); //ofBox(100, -200, 4, 40, 40, 40); phase1 = true; } if (!fingers.empty()) { for (int cnt = 0; cnt < fingers.size(); cnt++) { for (int fingerNum = 0; fingerNum < fingers[cnt].count(); fingerNum++) { Leap::Vector pt = fingers[cnt][fingerNum].tipPosition(); Leap::Vector vpt = fingers[cnt][fingerNum].tipVelocity(); pt.x = pt.x*2; pt.y = (pt.y * -1)*2; pt.z = pt.z *2; //ofLogNotice("finger number is " + ofToString(cnt) + ofToString(fingerNum)); //ofSphere(pt.x,pt.y,pt.z, 10); //ofBox(pt.x, pt.y, pt.z, 10, 10, 10); //ofLogNotice("position is " + ofToString(pt.x) + " " + ofToString(pt.y) + " " + ofToString(pt.z)); //ofLogNotice("velocity is " + ofToString(vpt.x) + " " + ofToString(vpt.y) + " " + ofToString(vpt.z)); drawSphere(pt, 10); } } Leap::Vector tpt = fingers[0][0].tipPosition(); } ofPopMatrix(); camera.end(); }
void oleap_bang(t_oleap *x) { const Leap::Frame frame = x->leap->frame(); const int64_t frame_id = frame.id(); Leap::Controller controller; // ignore the same frame if (frame_id == x->frame_id_save) return; x->frame_id_save = frame_id; //outlet_anything(x->outlet, gensym("frame_start"), 0, nil); char buff[128]; const Leap::HandList hands = frame.hands(); const size_t numHands = hands.count(); const Leap::Hand leftmost = hands.leftmost(); const Leap::Hand rightmost = hands.rightmost(); t_osc_bundle_u *bundle = osc_bundle_u_alloc();//alloc creates memory for and initializes the bundle controller.enableGesture(Leap::Gesture::TYPE_CIRCLE); controller.enableGesture(Leap::Gesture::TYPE_KEY_TAP); controller.enableGesture(Leap::Gesture::TYPE_SCREEN_TAP); controller.enableGesture(Leap::Gesture::TYPE_SWIPE); // Get gestures const Leap::GestureList gestures = frame.gestures(); for (int g = 0; g < gestures.count(); ++g) { Leap::Gesture gesture = gestures[g]; switch (gesture.type()) { case Leap::Gesture::TYPE_CIRCLE: { Leap::CircleGesture circle = gesture; std::string clockwiseness; sprintf(buff,"/gesture/circle/center/x"); oleap_bundleMessage(bundle,buff,circle.center().x); sprintf(buff,"/gesture/circle/center/y"); oleap_bundleMessage(bundle,buff,circle.center().y); sprintf(buff,"/gesture/circle/center/z"); oleap_bundleMessage(bundle,buff,circle.center().z); sprintf(buff,"/gesture/circle/pitch"); oleap_bundleMessage(bundle,buff,circle.center().pitch()); sprintf(buff,"/gesture/circle/yaw"); oleap_bundleMessage(bundle,buff,circle.center().yaw()); sprintf(buff,"/gesture/circle/roll"); oleap_bundleMessage(bundle,buff,circle.center().roll()); sprintf(buff,"/gesture/circle/radius"); oleap_bundleMessage(bundle,buff,circle.radius()); sprintf(buff,"/gesture/circle/duration"); oleap_bundleMessage(bundle,buff,circle.duration()); if (circle.pointable().direction().angleTo(circle.normal()) <= Leap::PI/4) { clockwiseness = "clockwise"; sprintf(buff,"/gesture/circle/clockwiseness/"); oleap_bundleMessage(bundle,buff,1); } else { clockwiseness = "counterclockwise"; sprintf(buff,"/gesture/circle/clockwiseness/"); oleap_bundleMessage(bundle,buff,-1); } // Calculate angle swept since last frame float sweptAngle = 0; if (circle.state() != Leap::Gesture::STATE_START) { Leap::CircleGesture previousUpdate = Leap::CircleGesture(controller.frame(1).gesture(circle.id())); sweptAngle = (circle.progress() - previousUpdate.progress()) * 2 * Leap::PI; sprintf(buff,"/gesture/circle/angle/sweep"); oleap_bundleMessage(bundle,buff,sweptAngle); } } case Leap::Gesture::TYPE_SWIPE: { Leap::SwipeGesture swipe = gesture; int swipe_id = gesture.id(); int gesture_state = gesture.state(); Leap::Vector swipe_direction = swipe.direction(); float swipe_speed = swipe.speed(); ////////////////////////////////Swipe data sprintf(buff,"/gesture/swipe/direction/x"); oleap_bundleMessage(bundle,buff,swipe_direction.x); sprintf(buff,"/gesture/swipe/direction/x"); oleap_bundleMessage(bundle,buff,swipe_direction.y); sprintf(buff,"/gesture/swipe/direction/x"); oleap_bundleMessage(bundle,buff,swipe_direction.z); sprintf(buff,"/gesture/swipe/position/x"); oleap_bundleMessage(bundle,buff,swipe.position().x); sprintf(buff,"/gesture/swipe/position/y"); oleap_bundleMessage(bundle,buff,swipe.position().y); sprintf(buff,"/gesture/swipe/position/z"); oleap_bundleMessage(bundle,buff,swipe.position().z); sprintf(buff,"/gesture/swipe/pitch"); oleap_bundleMessage(bundle,buff,swipe.position().pitch()); sprintf(buff,"/gesture/swipe/yaw"); oleap_bundleMessage(bundle,buff,swipe.position().yaw()); sprintf(buff,"/gesture/swipe/roll"); oleap_bundleMessage(bundle,buff,swipe.position().roll()); sprintf(buff,"/gesture/swipe/position/start/x"); oleap_bundleMessage(bundle,buff,swipe.startPosition().x); sprintf(buff,"/gesture/swipe/position/start/y"); oleap_bundleMessage(bundle,buff,swipe.startPosition().y); sprintf(buff,"/gesture/swipe/position/start/z"); oleap_bundleMessage(bundle,buff,swipe.startPosition().z); sprintf(buff,"/gesture/swipe/speed"); oleap_bundleMessage(bundle,buff,swipe_speed); sprintf(buff,"/gesture/swipe/duration"); oleap_bundleMessage(bundle,buff,swipe.duration()); } case Leap::Gesture::TYPE_KEY_TAP: { Leap::KeyTapGesture tap = gesture; int tap_id = gesture.id(); int tap_state = gesture.state(); Leap::Vector tap_position = tap.position(); Leap::Vector tap_direction = tap.direction(); ////////////////////////////////Key tap data sprintf(buff,"/gesture/tap/down/position/x"); oleap_bundleMessage(bundle,buff,tap_position.x); sprintf(buff,"/gesture/tap/down/position/y"); oleap_bundleMessage(bundle,buff,tap_position.y); sprintf(buff,"/gesture/tap/down/position/z"); oleap_bundleMessage(bundle,buff,tap_position.z); sprintf(buff,"/gesture/tap/down/direction/x"); oleap_bundleMessage(bundle,buff,tap_direction.x); sprintf(buff,"/gesture/tap/down/direction/y"); oleap_bundleMessage(bundle,buff,tap_direction.y); sprintf(buff,"/gesture/tap/down/direction/z"); oleap_bundleMessage(bundle,buff,tap_direction.z); sprintf(buff,"/gesture/tap/down/duration"); oleap_bundleMessage(bundle,buff,tap.duration()); } case Leap::Gesture::TYPE_SCREEN_TAP: { Leap::ScreenTapGesture screentap = gesture; int screen_tap_id = gesture.id(); int screen_tap_state = gesture.state(); Leap::Vector screentap_position = screentap.position(); Leap::Vector screentap_direction = screentap.direction(); ////////////////////////////////Screen tap data sprintf(buff,"/gesture/tap/forward/position/x"); oleap_bundleMessage(bundle,buff,screentap_position.x); sprintf(buff,"/gesture/tap/forward/position/y"); oleap_bundleMessage(bundle,buff,screentap_position.y); sprintf(buff,"/gesture/tap/forward/position/z"); oleap_bundleMessage(bundle,buff,screentap_position.z); sprintf(buff,"/gesture/tap/forward/direction/x"); oleap_bundleMessage(bundle,buff,screentap_direction.x); sprintf(buff,"/gesture/tap/forward/direction/y"); oleap_bundleMessage(bundle,buff,screentap_direction.y); sprintf(buff,"/gesture/tap/forward/direction/z"); oleap_bundleMessage(bundle,buff,screentap_direction.z); sprintf(buff,"/gesture/tap/forward/duration"); oleap_bundleMessage(bundle,buff,screentap.duration()); } default: break; } } sprintf(buff,"/timeStamp"); oleap_bundleMessage(bundle,buff,frame.timestamp()); sprintf(buff,"/Hands"); oleap_bundleMessage(bundle,buff,numHands); sprintf(buff,"/hand/leftmost/id"); oleap_bundleMessage(bundle,buff,leftmost.id()); sprintf(buff,"/hand/leftmost/palm/positiony/x"); oleap_bundleMessage(bundle,buff,leftmost.palmPosition().x); sprintf(buff,"/hand/leftmost/palm/positiony/y"); oleap_bundleMessage(bundle,buff,leftmost.palmPosition().y); sprintf(buff,"/hand/leftmost/palm/positiony/z"); oleap_bundleMessage(bundle,buff,leftmost.palmPosition().z); sprintf(buff,"/hand/leftmost/direction/x"); oleap_bundleMessage(bundle,buff,leftmost.direction().x); sprintf(buff,"/hand/leftmost/direction/y"); oleap_bundleMessage(bundle,buff,leftmost.direction().y); sprintf(buff,"/hand/leftmost/direction/z"); oleap_bundleMessage(bundle,buff,leftmost.direction().z); sprintf(buff,"/hand/leftmost/pitch"); oleap_bundleMessage(bundle,buff,leftmost.palmPosition().pitch()); sprintf(buff,"/hand/leftmost/yaw"); oleap_bundleMessage(bundle,buff,leftmost.palmPosition().yaw()); sprintf(buff,"/hand/leftmost/roll"); oleap_bundleMessage(bundle,buff,leftmost.palmPosition().roll()); sprintf(buff,"/hand/leftmost/palm/velocity/x"); oleap_bundleMessage(bundle,buff,leftmost.palmVelocity().x); sprintf(buff,"/hand/leftmost/palm/velocity/y"); oleap_bundleMessage(bundle,buff,leftmost.palmVelocity().y); sprintf(buff,"/hand/leftmost/palm/velocity/z"); oleap_bundleMessage(bundle,buff,leftmost.palmVelocity().z); sprintf(buff,"/hand/leftmost/palm/sphere/center/x"); oleap_bundleMessage(bundle,buff,leftmost.sphereCenter().x); sprintf(buff,"/hand/leftmost/palm/sphere/center/y"); oleap_bundleMessage(bundle,buff,leftmost.sphereCenter().y); sprintf(buff,"/hand/leftmost/palm/sphere/center/z"); oleap_bundleMessage(bundle,buff,leftmost.sphereCenter().z); sprintf(buff,"/hand/leftmost/palm/sphere/radius"); oleap_bundleMessage(bundle,buff,leftmost.sphereRadius()); sprintf(buff,"/hand/leftmost/palm/normal/x"); oleap_bundleMessage(bundle,buff,leftmost.palmNormal().x); sprintf(buff,"/hand/leftmost/palm/normal/y"); oleap_bundleMessage(bundle,buff,leftmost.palmNormal().y); sprintf(buff,"/hand/leftmost/palm/normal/z"); oleap_bundleMessage(bundle,buff,leftmost.palmNormal().z); sprintf(buff,"/hand/leftmost/distance/from/rightmost"); oleap_bundleMessage(bundle,buff,leftmost.palmPosition().angleTo(rightmost.palmPosition())); const Leap::FingerList &fingers = leftmost.fingers(); const size_t numFingers = fingers.count(); for(size_t j = 0; j < numFingers; j++) { const Leap::Finger &finger = fingers[j]; const int32_t finger_id = finger.id(); //const Leap::Ray& tip = finger.tip(); const Leap::Vector direction = finger.direction(); const Leap::Vector position = finger.tipPosition(); const Leap::Vector velocity = finger.tipVelocity(); const double width = finger.width(); const double length = finger.length(); const bool isTool = finger.isTool(); sprintf(buff,"/hand/leftmost/finger/%d/hand_id",j+1); oleap_bundleMessage(bundle,buff,leftmost.id()); sprintf(buff,"/hand/leftmost/finger/%d/finger_id",j+1); oleap_bundleMessage(bundle,buff,finger.id()); sprintf(buff,"/hand/leftmost/finger/%d/position/x",j+1); oleap_bundleMessage(bundle,buff,position.x); sprintf(buff,"/hand/leftmost/finger/%d/position/y",j+1); oleap_bundleMessage(bundle,buff,position.y); sprintf(buff,"/hand/leftmost/finger/%d/position/z",j+1); oleap_bundleMessage(bundle,buff,position.z); sprintf(buff,"/hand/leftmost/finger/%d/direction/x",j+1); oleap_bundleMessage(bundle,buff,direction.x); sprintf(buff,"/hand/leftmost/finger/%d/direction/y",j+1); oleap_bundleMessage(bundle,buff,direction.y); sprintf(buff,"/hand/leftmost/finger/%d/direction/z",j+1); oleap_bundleMessage(bundle,buff,direction.z); sprintf(buff,"/hand/leftmost/finger/%d/velocity/x",j+1); oleap_bundleMessage(bundle,buff,velocity.x); sprintf(buff,"/hand/leftmost/finger/%d/velocity/y",j+1); oleap_bundleMessage(bundle,buff,velocity.y); sprintf(buff,"/hand/leftmost/finger/%d/velocity/z",j+1); oleap_bundleMessage(bundle,buff,velocity.z); sprintf(buff,"/hand/leftmost/finger/%d/direction/normalized/x",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().x); sprintf(buff,"/hand/leftmost/finger/%d/direction/normalized/y",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().y); sprintf(buff,"/hand/leftmost/finger/%d/direction/normalized/z",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().z); sprintf(buff,"/hand/leftmost/finger/%d/pitch/normalized/",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().pitch()); sprintf(buff,"/hand/leftmost/finger/%d/yaw/normalized/",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().yaw()); sprintf(buff,"/hand/leftmost/finger/%d/roll/normalized/",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().roll()); sprintf(buff,"/hand/leftmost/finger/%d/width",j+1); oleap_bundleMessage(bundle,buff,width); sprintf(buff,"/hand/leftmost/finger/%d/length",j+1); oleap_bundleMessage(bundle,buff,length); sprintf(buff,"/hand/leftmost/isTool",j+1); oleap_bundleMessage(bundle,buff,isTool); for(size_t i = j+1; i < numFingers; i++) { sprintf(buff,"/hand/leftmost/finger/%d/distance/to/finger/%d",j+1,i+1); oleap_bundleMessage(bundle,buff,fingers[j].direction().distanceTo(fingers[i].direction())); sprintf(buff,"/hand/leftmost/finger/%d/angle/to/finger/%d",j+1,i+1); oleap_bundleMessage(bundle,buff,fingers[j].direction().angleTo((fingers[i].direction()))); } } sprintf(buff,"/hand/rightmost/id"); oleap_bundleMessage(bundle,buff,rightmost.id()); sprintf(buff,"/hand/rightmost/palm/positiony/x"); oleap_bundleMessage(bundle,buff,rightmost.palmPosition().x); sprintf(buff,"/hand/rightmost/palm/positiony/y"); oleap_bundleMessage(bundle,buff,rightmost.palmPosition().y); sprintf(buff,"/hand/rightmost/palm/positiony/z"); oleap_bundleMessage(bundle,buff,rightmost.palmPosition().z); sprintf(buff,"/hand/rightmost/direction/x"); oleap_bundleMessage(bundle,buff,rightmost.direction().x); sprintf(buff,"/hand/rightmost/direction/y"); oleap_bundleMessage(bundle,buff,rightmost.direction().y); sprintf(buff,"/hand/rightmost/direction/z"); oleap_bundleMessage(bundle,buff,rightmost.direction().z); sprintf(buff,"/hand/rightmost/pitch"); oleap_bundleMessage(bundle,buff,rightmost.palmPosition().pitch()); sprintf(buff,"/hand/rightmost/yaw"); oleap_bundleMessage(bundle,buff,rightmost.palmPosition().yaw()); sprintf(buff,"/hand/rightmost/roll"); oleap_bundleMessage(bundle,buff,rightmost.palmPosition().roll()); sprintf(buff,"/hand/rightmost/palm/velocity/x"); oleap_bundleMessage(bundle,buff,rightmost.palmVelocity().x); sprintf(buff,"/hand/rightmost/palm/velocity/y"); oleap_bundleMessage(bundle,buff,rightmost.palmVelocity().y); sprintf(buff,"/hand/rightmost/palm/velocity/z"); oleap_bundleMessage(bundle,buff,rightmost.palmVelocity().z); sprintf(buff,"/hand/rightmost/palm/sphere/center/x"); oleap_bundleMessage(bundle,buff,rightmost.sphereCenter().x); sprintf(buff,"/hand/rightmost/palm/sphere/center/y"); oleap_bundleMessage(bundle,buff,rightmost.sphereCenter().y); sprintf(buff,"/hand/rightmost/palm/sphere/center/z"); oleap_bundleMessage(bundle,buff,rightmost.sphereCenter().z); sprintf(buff,"/hand/rightmost/palm/sphere/radius"); oleap_bundleMessage(bundle,buff,rightmost.sphereRadius()); sprintf(buff,"/hand/rightmost/palm/normal/x"); oleap_bundleMessage(bundle,buff,rightmost.palmNormal().x); sprintf(buff,"/hand/rightmost/palm/normal/y"); oleap_bundleMessage(bundle,buff,rightmost.palmNormal().y); sprintf(buff,"/hand/rightmost/palm/normal/z"); oleap_bundleMessage(bundle,buff,rightmost.palmNormal().z); sprintf(buff,"/hand/rightmost/distance/from/leftmost"); oleap_bundleMessage(bundle,buff,rightmost.palmPosition().angleTo(leftmost.palmPosition())); const Leap::FingerList &rightMostfingers = rightmost.fingers(); const size_t rightMostnNumFingers = fingers.count(); for(size_t j = 0; j < rightMostnNumFingers; j++) { const Leap::Finger &finger = rightMostfingers[j]; const int32_t finger_id = finger.id(); //const Leap::Ray& tip = finger.tip(); const Leap::Vector direction = finger.direction(); const Leap::Vector position = finger.tipPosition(); const Leap::Vector velocity = finger.tipVelocity(); const double width = finger.width(); const double length = finger.length(); const bool isTool = finger.isTool(); sprintf(buff,"/hand/rightmost/finger/%d/hand_id",j+1); oleap_bundleMessage(bundle,buff,rightmost.id()); sprintf(buff,"/hand/rightmost/finger/%d/finger_id",j+1); oleap_bundleMessage(bundle,buff,finger.id()); sprintf(buff,"/hand/rightmost/finger/%d/position/x",j+1); oleap_bundleMessage(bundle,buff,position.x); sprintf(buff,"/hand/rightmost/finger/%d/position/y",j+1); oleap_bundleMessage(bundle,buff,position.y); sprintf(buff,"/hand/rightmost/finger/%d/position/z",j+1); oleap_bundleMessage(bundle,buff,position.z); sprintf(buff,"/hand/rightmost/finger/%d/direction/x",j+1); oleap_bundleMessage(bundle,buff,direction.x); sprintf(buff,"/hand/rightmost/finger/%d/direction/y",j+1); oleap_bundleMessage(bundle,buff,direction.y); sprintf(buff,"/hand/rightmost/finger/%d/direction/z",j+1); oleap_bundleMessage(bundle,buff,direction.z); sprintf(buff,"/hand/rightmost/finger/%d/velocity/x",j+1); oleap_bundleMessage(bundle,buff,velocity.x); sprintf(buff,"/hand/rightmost/finger/%d/velocity/y",j+1); oleap_bundleMessage(bundle,buff,velocity.y); sprintf(buff,"/hand/rightmost/finger/%d/velocity/z",j+1); oleap_bundleMessage(bundle,buff,velocity.z); sprintf(buff,"/hand/rightmost/finger/%d/direction/normalized/x",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().x); sprintf(buff,"/hand/rightmost/finger/%d/direction/normalized/y",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().y); sprintf(buff,"/hand/rightmost/finger/%d/direction/normalized/z",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().z); sprintf(buff,"/hand/rightmost/finger/%d/pitch/normalized/",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().pitch()); sprintf(buff,"/hand/rightmost/finger/%d/yaw/normalized/",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().yaw()); sprintf(buff,"/hand/rightmost/finger/%d/roll/normalized/",j+1); oleap_bundleMessage(bundle,buff,direction.normalized().roll()); sprintf(buff,"/hand/rightmost/finger/%d/width",j+1); oleap_bundleMessage(bundle,buff,width); sprintf(buff,"/hand/rightmost/finger/%d/length",j+1); oleap_bundleMessage(bundle,buff,length); sprintf(buff,"/hand/rightmost/isTool",j+1); oleap_bundleMessage(bundle,buff,isTool); for(size_t i = j+1; i < numFingers; i++) { sprintf(buff,"/hand/rightmost/finger/%d/distance/to/finger/%d",j+1,i+1); oleap_bundleMessage(bundle,buff,fingers[j].direction().distanceTo(fingers[i].direction())); sprintf(buff,"/hand/rightmost/finger/%d/angle/to/finger/%d",j+1,i+1); oleap_bundleMessage(bundle,buff,fingers[j].direction().angleTo((fingers[i].direction()))); } } ////////////////////////// for(size_t i = 0; i < numHands; i++) { // Hand const Leap::Hand &hand = hands[i]; const int32_t hand_id = hand.id(); const Leap::FingerList &fingers = hand.fingers(); const size_t numFingers = fingers.count(); float pitch = hand.direction().pitch(); float yaw = hand.direction().yaw(); float roll = hand.palmNormal().roll(); //Leap::Hand leftmost = ; //t_osc_bundle_u *bundle, string address, float datum sprintf(buff,"/hand/%d/id",i+1); oleap_bundleMessage(bundle,buff,hand_id); sprintf(buff,"/hand/%d/fingers",i+1); oleap_bundleMessage(bundle,buff,numFingers); sprintf(buff,"/hand/%d/pitch",i+1); oleap_bundleMessage(bundle,buff,pitch); sprintf(buff,"/hand/%d/yaw",i+1); oleap_bundleMessage(bundle,buff,yaw); sprintf(buff,"/hand/%d/roll",i+1); oleap_bundleMessage(bundle,buff,roll); for(size_t j = 0; j < numFingers; j++) { // Finger const Leap::Finger &finger = fingers[j]; const int32_t finger_id = finger.id(); //const Leap::Ray& tip = finger.tip(); const Leap::Vector direction = finger.direction(); const Leap::Vector position = finger.tipPosition(); const Leap::Vector velocity = finger.tipVelocity(); const double width = finger.width(); const double length = finger.length(); const bool isTool = finger.isTool(); /* string names [14]= {“xpos”,”ypos”,”zpos”,”xdir”,”ydir”,”zdir”,”xvel”,”yvel”,”zvel,finger_length”,”istool_mes”}; for(LOOP OVER FINGERS “J”) { t_osc_message_u *handdata[14]; for(int i=0;i<14;i++) { handdata[i]=osc_message_u_alloc(); osc_message_u_setAddress(handdata[i], “/”+j.toString()+ ”/” +names[i]); } } */ sprintf(buff,"/hand/%d/finger/%d/hand_id",i+1,j+1); oleap_bundleMessage(bundle,buff,hand_id); sprintf(buff,"/hand/%d/finger/%d/finger_id",i+1,j+1); oleap_bundleMessage(bundle,buff,finger_id); sprintf(buff,"/hand/%d/finger/%d/position/x",i+1,j+1); oleap_bundleMessage(bundle,buff,position.x); sprintf(buff,"/hand/%d/finger/%d/position/y",i+1,j+1); oleap_bundleMessage(bundle,buff,position.y); sprintf(buff,"/hand/%d/finger/%d/position/z",i+1,j+1); oleap_bundleMessage(bundle,buff,position.z); sprintf(buff,"/hand/%d/finger/%d/direction/x",i+1,j+1); oleap_bundleMessage(bundle,buff,direction.x); sprintf(buff,"/hand/%d/finger/%d/direction/y",i+1,j+1); oleap_bundleMessage(bundle,buff,direction.y); sprintf(buff,"/hand/%d/finger/%d/direction/z",i+1,j+1); oleap_bundleMessage(bundle,buff,direction.z); sprintf(buff,"/hand/%d/finger/%d/velocity/x",i+1,j+1); oleap_bundleMessage(bundle,buff,velocity.x); sprintf(buff,"/hand/%d/finger/%d/velocity/y",i+1,j+1); oleap_bundleMessage(bundle,buff,velocity.y); sprintf(buff,"/hand/%d/finger/%d/velocity/z",i+1,j+1); oleap_bundleMessage(bundle,buff,velocity.z); sprintf(buff,"/hand/%d/finger/%d/width",i+1,j+1); oleap_bundleMessage(bundle,buff,width); sprintf(buff,"/hand/%d/finger/%d/length",i+1,j+1); oleap_bundleMessage(bundle,buff,length); sprintf(buff,"/hand/%d/tool",i+1,j+1); oleap_bundleMessage(bundle,buff,isTool); } const Leap::Vector position = hand.palmPosition(); const Leap::Vector direction = hand.direction(); const Leap::Vector velocity = hand.palmVelocity(); const Leap::Vector normal = hand.palmNormal(); const Leap::Vector sphereCenter = hand.sphereCenter(); const double sphereRadius = hand.sphereRadius(); ///////////////////////////Palm Data!!! sprintf(buff,"/hand/%d/palm/hand_id",i+1); oleap_bundleMessage(bundle,buff,hand_id); sprintf(buff,"/hand/%d/palm/frame_id",i+1); oleap_bundleMessage(bundle,buff,frame_id); sprintf(buff,"/hand/%d/palm/position/x",i+1); oleap_bundleMessage(bundle,buff,position.x); sprintf(buff,"/hand/%d/palm/position/y",i+1); oleap_bundleMessage(bundle,buff,position.y); sprintf(buff,"/hand/%d/palm/position/z",i+1); oleap_bundleMessage(bundle,buff,position.z); sprintf(buff,"/hand/%d/palm/direction/x",i+1); oleap_bundleMessage(bundle,buff,direction.x); sprintf(buff,"/hand/%d/palm/direction/y",i+1); oleap_bundleMessage(bundle,buff,direction.y); sprintf(buff,"/hand/%d/palm/direction/z",i+1); oleap_bundleMessage(bundle,buff,direction.z); sprintf(buff,"/hand/%d/palm/velocity/x",i+1); oleap_bundleMessage(bundle,buff,velocity.x); sprintf(buff,"/hand/%d/palm/velocity/x",i+1); oleap_bundleMessage(bundle,buff,velocity.y); sprintf(buff,"/hand/%d/palm/velocity/z",i+1); oleap_bundleMessage(bundle,buff,velocity.z); sprintf(buff,"/hand/%d/palm/normal/x",i+1); oleap_bundleMessage(bundle,buff,normal.x); sprintf(buff,"/hand/%d/palm/normal/y",i+1); oleap_bundleMessage(bundle,buff,normal.y); sprintf(buff,"/hand/%d/palm/normal/z",i+1); oleap_bundleMessage(bundle,buff,normal.z); sprintf(buff,"/hand/%d/sphere/id",i); oleap_bundleMessage(bundle,buff,hand_id); sprintf(buff,"/hand/%d/sphere/frame_id",i); oleap_bundleMessage(bundle,buff,frame_id); sprintf(buff,"/hand/%d/sphere/center/x",i+1); oleap_bundleMessage(bundle,buff,sphereCenter.x); sprintf(buff,"/hand/%d/sphere/center/y",i+1); oleap_bundleMessage(bundle,buff,sphereCenter.y); sprintf(buff,"/hand/%d/sphere/center/z",i+1); oleap_bundleMessage(bundle,buff,sphereCenter.z); sprintf(buff,"/hand/%d/sphere/radius",i+1); oleap_bundleMessage(bundle,buff,sphereRadius); const Leap::PointableList pointables = frame.pointables(); const int count = pointables.count(); for(size_t j = 0; j < count; j++){ sprintf(buff,"/hand/%d/pointable/%d/id",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).id()); sprintf(buff,"/hand/%d/pointable/%d/length",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).length()); sprintf(buff,"/hand/%d/pointable/%d/width",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).width()); sprintf(buff,"/hand/%d/pointable/%d/direction/x",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).direction().x); sprintf(buff,"/hand/%d/pointable/%d/direction/y",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).direction().y); sprintf(buff,"/hand/%d/pointable/%d/direction/z",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).direction().z); sprintf(buff,"/hand/%d/pointable/%d/isFinger",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).isFinger()); sprintf(buff,"/hand/%d/pointable/%d/isTool",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).isTool()); sprintf(buff,"/hand/%d/pointable/%d/position/tip/x",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).tipPosition().x); sprintf(buff,"/hand/%d/pointable/%d/position/tip/y",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).tipPosition().y); sprintf(buff,"/hand/%d/pointable/%d/position/tip/z",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).tipPosition().z); sprintf(buff,"/hand/%d/pointable/%d/velocity/tip/x",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).tipVelocity().x); sprintf(buff,"/hand/%d/pointable/%d/velocity/tip/y",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).tipVelocity().y); sprintf(buff,"/hand/%d/pointable/%d/velocity/tip/z",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).tipVelocity().z); sprintf(buff,"/hand/%d/pointable/%d/position/stabilized/x",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).stabilizedTipPosition().x); sprintf(buff,"/hand/%d/pointable/%d/position/stabilized/y",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).stabilizedTipPosition().y); sprintf(buff,"/hand/%d/pointable/%d/position/stabilized/z",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).stabilizedTipPosition().z); sprintf(buff,"/hand/%d/pointable/%d/touchZone/distance",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).touchDistance()); sprintf(buff,"/hand/%d/pointable/%d/touchZone",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).touchZone()); sprintf(buff,"/hand/%d/pointable/%d/touchZone/touching",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).ZONE_TOUCHING); sprintf(buff,"/hand/%d/pointable/%d/touchZone/hovering",i+1,j+1); oleap_bundleMessage(bundle,buff,pointables.operator[](j).ZONE_HOVERING); } const Leap::InteractionBox box = frame.interactionBox(); const Leap::Vector center = box.center(); const Leap::Vector normalizedPosition = box.normalizePoint(position); sprintf(buff,"/hand/%d/interactionBox/depth",i+1); oleap_bundleMessage(bundle,buff,box.depth()); sprintf(buff,"/hand/%d/interactionBox/center/x",i+1); oleap_bundleMessage(bundle,buff,center.x); sprintf(buff,"/hand/%d/interactionBox/center/y",i+1); oleap_bundleMessage(bundle,buff,center.y); sprintf(buff,"/hand/%d/interactionBox/center/z",i+1); oleap_bundleMessage(bundle,buff,center.z); sprintf(buff,"/hand/%d/interactionBox/position/normalized/x",i+1); oleap_bundleMessage(bundle,buff,normalizedPosition.x); sprintf(buff,"/hand/%d/interactionBox/position/normalized/y",i+1); oleap_bundleMessage(bundle,buff,normalizedPosition.y); sprintf(buff,"/hand/%d/interactionBox/position/normalized/z",i+1); oleap_bundleMessage(bundle,buff,normalizedPosition.z); sprintf(buff,"/hand/%d/interactionBox/width",i+1); oleap_bundleMessage(bundle,buff,box.width()); sprintf(buff,"/hand/%d/interactionBox/height",i+1); oleap_bundleMessage(bundle,buff,box.height()); } long bytes = 0;//length of byte array char* pointer = NULL; osc_bundle_u_serialize(bundle, &bytes, &pointer);//& is address of the variable //post("%ld %p", bytes,pointer); t_atom out[2]; atom_setlong(out, bytes); atom_setlong(out+1, (long)pointer); outlet_anything(x->outlet, gensym("FullPacket"), 2, out); osc_bundle_u_free(bundle);//get rid of stuff in osc message osc_mem_free(pointer);//marks pointer address as being free (clear if you want to keep using same) }
// This mode tries to detect simple hand motion and either triggers an avatar gesture or // sends a chat message into SL in response. It is very rough, hard-coded for detecting // a hand wave (a SL gesture) or the wiggling-thumb gun trigger (a chat message sent to a // special version of the popgun). void LLLMImpl::modeGestureDetection1(Leap::HandList & hands) { static S32 trigger_direction = -1; S32 numHands = hands.count(); if (numHands == 1) { // Get the first hand Leap::Hand hand = hands[0]; // Check if the hand has any fingers Leap::FingerList finger_list = hand.fingers(); S32 num_fingers = finger_list.count(); static S32 last_num_fingers = 0; if (num_fingers == 1) { // One finger ... possibly reset the Leap::Finger finger = finger_list[0]; Leap::Vector finger_dir = finger.direction(); // Negative Z is into the screen - check that it's the largest component S32 abs_z_dir = llabs(finger_dir.z); if (finger_dir.z < -0.5 && abs_z_dir > llabs(finger_dir.x) && abs_z_dir > llabs(finger_dir.y)) { Leap::Vector finger_pos = finger.tipPosition(); Leap::Vector finger_vel = finger.tipVelocity(); LL_INFOS("LeapMotion") << "finger direction is " << finger_dir.x << ", " << finger_dir.y << ", " << finger_dir.z << ", position " << finger_pos.x << ", " << finger_pos.y << ", " << finger_pos.z << ", velocity " << finger_vel.x << ", " << finger_vel.y << ", " << finger_vel.z << LL_ENDL; } if (trigger_direction != -1) { LL_INFOS("LeapMotion") << "Reset trigger_direction - one finger" << LL_ENDL; trigger_direction = -1; } } else if (num_fingers == 2) { Leap::Finger barrel_finger = finger_list[0]; Leap::Vector barrel_finger_dir = barrel_finger.direction(); // Negative Z is into the screen - check that it's the largest component F32 abs_z_dir = llabs(barrel_finger_dir.z); if (barrel_finger_dir.z < -0.5f && abs_z_dir > llabs(barrel_finger_dir.x) && abs_z_dir > llabs(barrel_finger_dir.y)) { Leap::Finger thumb_finger = finger_list[1]; Leap::Vector thumb_finger_dir = thumb_finger.direction(); Leap::Vector thumb_finger_pos = thumb_finger.tipPosition(); Leap::Vector thumb_finger_vel = thumb_finger.tipVelocity(); if ((thumb_finger_dir.x < barrel_finger_dir.x) ) { // Trigger gunfire if (trigger_direction < 0 && // Haven't fired thumb_finger_vel.x > 50.f && // Moving into screen thumb_finger_vel.z < -50.f && mChatMsgTimer.checkExpirationAndReset(LLLEAP_CHAT_MSG_INTERVAL)) { // Chat message looks like "/2343 LM2 gunfire" std::string gesture_chat_msg("/2343 LM2 gunfire"); //LLNearbyChatBar::sendChatFromViewer(gesture_chat_msg, CHAT_TYPE_SHOUT, FALSE); trigger_direction = 1; LL_INFOS("LeapMotion") << "Sent gunfire chat" << LL_ENDL; } else if (trigger_direction > 0 && // Have fired, need to pull thumb back thumb_finger_vel.x < -50.f && thumb_finger_vel.z > 50.f) // Moving out of screen { trigger_direction = -1; LL_INFOS("LeapMotion") << "Reset trigger_direction" << LL_ENDL; } } } else if (trigger_direction != -1) { LL_INFOS("LeapMotion") << "Reset trigger_direction - hand pos" << LL_ENDL; trigger_direction = -1; } } else if (num_fingers == 5 && num_fingers == last_num_fingers) { if (mGestureTimer.checkExpirationAndReset(LLLEAP_GESTURE_INTERVAL)) { // figure out a gesture to trigger std::string gestureString("/overhere"); LLGestureMgr::instance().triggerAndReviseString( gestureString ); } } last_num_fingers = num_fingers; } }
void MouseListener::onFrame(const Leap::Controller &controller) { // get list of detected screens const Leap::ScreenList screens = controller.calibratedScreens(); // make sure we have a detected screen if (screens.empty()) return; const Leap::Screen screen = screens[0]; // get hands const Leap::Frame frame = controller.frame(); const Leap::HandList hands = frame.hands(); if (hands.empty()) return; // which is the pointer hand and which is the clicker hand? // if there's only one hand it's the pointer hand. if there's two // then we'll use the user's primary hand. if ambidextrous, bail. Leap::Hand pointerHand, clickerHand; if (pointerHandID) { pointerHand = frame.hand(pointerHandID); if (! pointerHand.isValid()) pointerHand = hands[0]; } if (clickerHandID) clickerHand = frame.hand(clickerHandID); if (! clickerHand.isValid() && hands.count() == 2) { // figure out clicker and pointer hand // which hand is on the left and which is on the right? Leap::Hand leftHand, rightHand; if (hands[0].palmPosition()[0] <= hands[1].palmPosition()[0]) { leftHand = hands[0]; rightHand = hands[1]; } else { leftHand = hands[1]; rightHand = hands[0]; } // now that we know the left and right hands, determine // which is the clicker and which is the pointer if (leftHanded) { pointerHand = leftHand; clickerHand = rightHand; } else { pointerHand = rightHand; clickerHand = leftHand; } // keep track of which hands we decided on clickerHandID = clickerHand.id(); pointerHandID = pointerHand.id(); } // find the first finger or tool const Leap::PointableList pointables = pointerHand.pointables(); if (pointables.empty()) return; const Leap::Pointable firstPointable = pointables[0]; // get x, y coordinates on the first screen const Leap::Vector intersection = screen.intersect( firstPointable, true, // normalize 1.0f // clampRatio ); // if the user is not pointing at the screen all components of // the returned vector will be Not A Number (NaN) // isValid() returns true only if all components are finite if (! intersection.isValid()) return; unsigned int x = screen.widthPixels() * intersection.x; // flip y coordinate to standard top-left origin unsigned int y = screen.heightPixels() * (1.0f - intersection.y); // move cursor to location pointed at CGPoint destPoint = CGPointMake(x, y); CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, destPoint); // check for click gesture if (! clickerHand.isValid()) return; // click = two fingers on the clicker hand touching together const Leap::PointableList clickerFingers = clickerHand.pointables(); if (clickerFingers.count() != 2) return; // get finger distance float clickFingerDistance = clickerFingers[0].tipPosition().distanceTo( clickerFingers[1].tipPosition() ); cout << "distance: " << clickFingerDistance << endl; if (! clickActive && clickFingerDistance < clickActivationDistance) { clickActive = true; cout << "mouseDown\n"; postMouseDown(x, y); } else if (clickActive && clickFingerDistance > clickActivationDistance) { cout << "mouseUp\n"; clickActive = false; postMouseUp(x, y); } }
// This mode tries to move the avatar and camera in Second Life. It's pretty rough and needs a lot of work void LLLMImpl::modeMoveAndCamTest1(Leap::HandList & hands) { S32 numHands = hands.count(); if (numHands == 1) { // Get the first hand Leap::Hand hand = hands[0]; // Check if the hand has any fingers Leap::FingerList finger_list = hand.fingers(); S32 num_fingers = finger_list.count(); F32 orbit_rate = 0.f; Leap::Vector pos(0, 0, 0); for (size_t i = 0; i < num_fingers; ++i) { Leap::Finger finger = finger_list[i]; pos += finger.tipPosition(); } pos = Leap::Vector(pos.x/num_fingers, pos.y/num_fingers, pos.z/num_fingers); if (num_fingers == 1) { // 1 finger - move avatar if (pos.x < -LM_DEAD_ZONE) { // Move left gAgent.moveLeftNudge(1.f); } else if (pos.x > LM_DEAD_ZONE) { gAgent.moveLeftNudge(-1.f); } /* if (pos.z < -LM_DEAD_ZONE) { gAgent.moveAtNudge(1.f); } else if (pos.z > LM_DEAD_ZONE) { gAgent.moveAtNudge(-1.f); } */ if (pos.y < -LM_DEAD_ZONE) { gAgent.moveYaw(-1.f); } else if (pos.y > LM_DEAD_ZONE) { gAgent.moveYaw(1.f); } } // end 1 finger else if (num_fingers == 2) { // 2 fingers - move camera around // X values run from about -170 to +170 if (pos.x < -LM_DEAD_ZONE) { // Camera rotate left gAgentCamera.unlockView(); orbit_rate = (llabs(pos.x) - LM_DEAD_ZONE) / LM_ORBIT_RATE_FACTOR; gAgentCamera.setOrbitLeftKey(orbit_rate); } else if (pos.x > LM_DEAD_ZONE) { gAgentCamera.unlockView(); orbit_rate = (pos.x - LM_DEAD_ZONE) / LM_ORBIT_RATE_FACTOR; gAgentCamera.setOrbitRightKey(orbit_rate); } if (pos.z < -LM_DEAD_ZONE) { // Camera zoom in gAgentCamera.unlockView(); orbit_rate = (llabs(pos.z) - LM_DEAD_ZONE) / LM_ORBIT_RATE_FACTOR; gAgentCamera.setOrbitInKey(orbit_rate); } else if (pos.z > LM_DEAD_ZONE) { // Camera zoom out gAgentCamera.unlockView(); orbit_rate = (pos.z - LM_DEAD_ZONE) / LM_ORBIT_RATE_FACTOR; gAgentCamera.setOrbitOutKey(orbit_rate); } if (pos.y < -LM_DEAD_ZONE) { // Camera zoom in gAgentCamera.unlockView(); orbit_rate = (llabs(pos.y) - LM_DEAD_ZONE) / LM_ORBIT_RATE_FACTOR; gAgentCamera.setOrbitUpKey(orbit_rate); } else if (pos.y > LM_DEAD_ZONE) { // Camera zoom out gAgentCamera.unlockView(); orbit_rate = (pos.y - LM_DEAD_ZONE) / LM_ORBIT_RATE_FACTOR; gAgentCamera.setOrbitDownKey(orbit_rate); } } // end 2 finger } }
//function to get a frame and return it in the format acceptable to MATLAB //ie mxArray void loadFrame(mxArray *plhs[]) { //get current frame Leap::Frame frame = controller->frame(); //DEBUG: check if frame is valid if(!frame.isValid()) mexErrMsgTxt("Frame returned was not valid"); //wait for frame to be valid //while(!frame.isValid()) controller->frame(); Leap::HandList hands = frame.hands(); //import variables and create struct //number of hands int numHands = hands.count(); //if there are no hands return a null pointer if(!numHands){ plhs[0] = mxCreateDoubleScalar(0); return; } //fields returned to matlab in the struct: int numHandFields = 4; //change number of fields here**** const char *hand_field_names[] = { "position", "velocity", "direction", "pointables" //add new hand fields here**** }; //pointable temp values for a given hand int numPointables; Leap::PointableList pointList; int numPointFields = 3; //change number of pointable fields here**** const char *point_field_names[] = { "position", "velocity", "direction" //add new pointable fields here**** }; mxArray *p; //allocate the structure array to export to matlab mxArray *h = mxCreateStructMatrix(1, numHands, numHandFields, hand_field_names); //put vectors into structure array fields int i,j; //iterators for(i=0;i<numHands;i++){ //fill in hand information mxSetFieldByNumber(h,i,0,makeVector(hands[i].palmPosition())); mxSetFieldByNumber(h,i,1,makeVector(hands[i].palmVelocity())); mxSetFieldByNumber(h,i,2,makeVector(hands[i].direction())); // add new field information here**** //create pointable struct for this hand pointList = hands[i].pointables(); //get list of pointables for this hand numPointables = pointList.count(); //get number of pointables for this hand //build list of pointables p = mxCreateStructMatrix(1,numPointables,numPointFields,point_field_names); for(j=0;j<numPointables;j++){ mxSetFieldByNumber(p,j,0,makeVector(pointList[j].tipPosition())); mxSetFieldByNumber(p,j,1,makeVector(pointList[j].tipVelocity())); mxSetFieldByNumber(p,j,2,makeVector(pointList[j].direction())); //add new pointable fields here**** } //put pointable list into hand struct mxSetFieldByNumber(h,i,3,p); } plhs[0] = h; //set output return; }
// This controller mode is used to fly around with the camera void LLLMImpl::modeFlycam(Leap::HandList& hands) { static bool old_joystick_enabled=false; S32 numHands=hands.count(); if(numHands!=1) { if(mOverrideCamera) { mOverrideCamera=false; gSavedSettings.setBOOL("JoystickEnabled",old_joystick_enabled); gSavedSettings.setBOOL("JoystickFlycamEnabled",false); LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_FLYCAM); // make sure to keep the camera where we left it when we switch off flycam LLViewerJoystick::instance().setCameraNeedsUpdate(false); } } else { // Get the first hand Leap::Hand hand=hands[0]; // Check if the hand has at least 3 fingers Leap::FingerList finger_list=hand.fingers(); S32 num_fingers=finger_list.count(); static F32 y_rot=0.0f; static F32 z_rot=0.0f; if(!mOverrideCamera) { mOverrideCamera=true; old_joystick_enabled=gSavedSettings.getBOOL("JoystickEnabled"); gSavedSettings.setBOOL("JoystickEnabled",true); gSavedSettings.setBOOL("JoystickFlycamEnabled",true); mFlycamPos=LLViewerCamera::instance().getOrigin(); mFlycamDelta=LLVector3::zero; mFlycamFeatheredDelta=LLVector3::zero; mFlycamInitialRot=LLViewerCamera::instance().getQuaternion(); mFlycamRot=LLVector3::zero; mFlycamFeatheredRot=LLVector3::zero; y_rot=0.0f; z_rot=0.0f; LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_FLYCAM); } Leap::Vector palm_pos=hand.palmPosition(); Leap::Vector palm_normal=hand.palmNormal(); if(num_fingers<3) { mFlycamDelta=LLVector3::zero; mHandCenterPos=hand.palmPosition(); // auto leveling (not quite perfect yet) mFlycamRot=LLVector3(0.0f,y_rot,z_rot); } else { F32 delta=palm_pos.z-mHandCenterPos.z; if(fabsf(delta)>5.0f) { mFlycamDelta.mV[VX]=-delta*fabsf(delta)/1000.0f; } delta=palm_pos.y-mHandCenterPos.y; if(fabsf(delta)>5.0f) { mFlycamDelta.mV[VZ]=delta*fabsf(delta)/1000.0f; } delta=palm_pos.x-mHandCenterPos.x; if(fabsf(delta)>5.0f) { mFlycamDelta.mV[VY]=-delta*fabsf(delta)/1000.0f; } y_rot=palm_normal.z*150.0f; if(fabsf(palm_normal.x)>0.2f) { z_rot+=(palm_normal.x*fabsf(palm_normal.x)*50.0f); } // palm_normal.z = pitch // palm_normal.x = roll mFlycamRot=LLVector3(-palm_normal.x*60.0f,y_rot,z_rot); } } }
void SampleListener::onFrame(const Leap::Controller& controller) { // Get the most recent frame and report some basic information const Leap::Frame frame = controller.frame(); std::cout << "Frame id: " << frame.id() << ", timestamp: " << frame.timestamp() << ", hands: " << frame.hands().count() << ", extended fingers: " << frame.fingers().extended().count() << ", tools: " << frame.tools().count() << ", gestures: " << frame.gestures().count() << std::endl; Leap::HandList hands = frame.hands(); for (Leap::HandList::const_iterator hl = hands.begin(); hl != hands.end(); ++hl) { // Get the first hand const Leap::Hand hand = *hl; std::string handType = hand.isLeft() ? "Left hand" : "Right hand"; std::cout << std::string(2, ' ') << handType << ", id: " << hand.id() << ", palm position: " << hand.palmPosition() << std::endl; // Get the hand's normal vector and direction const Leap::Vector normal = hand.palmNormal(); const Leap::Vector direction = hand.direction(); // Calculate the hand's pitch, roll, and yaw angles std::cout << std::string(2, ' ') << "pitch: " << direction.pitch() * Leap::RAD_TO_DEG << " degrees, " << "roll: " << normal.roll() * Leap::RAD_TO_DEG << " degrees, " << "yaw: " << direction.yaw() * Leap::RAD_TO_DEG << " degrees" << std::endl; // Get the Arm bone Leap::Arm arm = hand.arm(); std::cout << std::string(2, ' ') << "Arm direction: " << arm.direction() << " wrist position: " << arm.wristPosition() << " elbow position: " << arm.elbowPosition() << std::endl; // Get fingers const Leap::FingerList fingers = hand.fingers(); for (Leap::FingerList::const_iterator fl = fingers.begin(); fl != fingers.end(); ++fl) { const Leap::Finger finger = *fl; std::cout << std::string(4, ' ') << fingerNames[finger.type()] << " finger, id: " << finger.id() << ", length: " << finger.length() << "mm, width: " << finger.width() << std::endl; // Get finger bones for (int b = 0; b < 4; ++b) { Leap::Bone::Type boneType = static_cast<Leap::Bone::Type>(b); Leap::Bone bone = finger.bone(boneType); std::cout << std::string(6, ' ') << boneNames[boneType] << " bone, start: " << bone.prevJoint() << ", end: " << bone.nextJoint() << ", direction: " << bone.direction() << std::endl; } } } // Get tools const Leap::ToolList tools = frame.tools(); for (Leap::ToolList::const_iterator tl = tools.begin(); tl != tools.end(); ++tl) { const Leap::Tool tool = *tl; std::cout << std::string(2, ' ') << "Tool, id: " << tool.id() << ", position: " << tool.tipPosition() << ", direction: " << tool.direction() << std::endl; } // Get gestures const Leap::GestureList gestures = frame.gestures(); for (int g = 0; g < gestures.count(); ++g) { Leap::Gesture gesture = gestures[g]; switch (gesture.type()) { case Leap::Gesture::TYPE_CIRCLE: { Leap::CircleGesture circle = gesture; std::string clockwiseness; if (circle.pointable().direction().angleTo(circle.normal()) <= Leap::PI/2) { clockwiseness = "clockwise"; } else { clockwiseness = "counterclockwise"; } // Calculate angle swept since last frame float sweptAngle = 0; if (circle.state() != Leap::Gesture::STATE_START) { Leap::CircleGesture previousUpdate = Leap::CircleGesture(controller.frame(1).gesture(circle.id())); sweptAngle = (circle.progress() - previousUpdate.progress()) * 2 * Leap::PI; } std::cout << std::string(2, ' ') << "Circle id: " << gesture.id() << ", state: " << stateNames[gesture.state()] << ", progress: " << circle.progress() << ", radius: " << circle.radius() << ", angle " << sweptAngle * Leap::RAD_TO_DEG << ", " << clockwiseness << std::endl; break; } case Leap::Gesture::TYPE_SWIPE: { Leap::SwipeGesture swipe = gesture; std::cout << std::string(2, ' ') << "Swipe id: " << gesture.id() << ", state: " << stateNames[gesture.state()] << ", direction: " << swipe.direction() << ", speed: " << swipe.speed() << std::endl; break; } case Leap::Gesture::TYPE_KEY_TAP: { Leap::KeyTapGesture tap = gesture; std::cout << std::string(2, ' ') << "Key Tap id: " << gesture.id() << ", state: " << stateNames[gesture.state()] << ", position: " << tap.position() << ", direction: " << tap.direction()<< std::endl; break; } case Leap::Gesture::TYPE_SCREEN_TAP: { Leap::ScreenTapGesture screentap = gesture; std::cout << std::string(2, ' ') << "Screen Tap id: " << gesture.id() << ", state: " << stateNames[gesture.state()] << ", position: " << screentap.position() << ", direction: " << screentap.direction()<< std::endl; break; } default: std::cout << std::string(2, ' ') << "Unknown gesture type." << std::endl; break; } } if (!frame.hands().isEmpty() || !gestures.isEmpty()) { std::cout << std::endl; } }