void HandController::drawHands() { glPushMatrix(); glTranslatef(translation_); glScalef(scale_, scale_, scale_); Leap::Frame frame = controller_.frame(); for (int h = 0; h < frame.hands().count(); ++h) { Leap::Hand hand = frame.hands()[h]; for (int f = 0; f < hand.fingers().count(); ++f) { Leap::Finger finger = hand.fingers()[f]; // Draw first joint inside hand. Leap::Bone mcp = finger.bone(Leap::Bone::Type::TYPE_METACARPAL); drawJoint(mcp.prevJoint()); for (int b = 0; b < 4; ++b) { Leap::Bone bone = finger.bone(static_cast<Leap::Bone::Type>(b)); drawJoint(bone.nextJoint()); drawBone(bone); } } } glPopMatrix(); }
void Quickstart::onFrame(const Leap::Controller &controller) { // returns the most recent frame. older frames can be accessed by passing in // a "history" parameter to retrieve an older frame, up to about 60 // (exact number subject to change) const Leap::Frame frame = controller.frame(); // do nothing unless hands are detected if (frame.hands().empty()) return; // first detected hand const Leap::Hand firstHand = frame.hands()[0]; // first pointable object (finger or tool) const Leap::PointableList pointables = firstHand.pointables(); if (pointables.empty()) return; const Leap::Pointable firstPointable = pointables[0]; // print velocity on the X axis cout << "Pointable X velocity: " << firstPointable.tipVelocity()[0] << endl; const Leap::FingerList fingers = firstHand.fingers(); if (fingers.empty()) return; for (int i = 0; i < fingers.count(); i++) { const Leap::Finger finger = fingers[i]; std::cout << "Detected finger " << i << " at position (" << finger.tipPosition().x << ", " << finger.tipPosition().y << ", " << finger.tipPosition().z << ")" << std::endl; } }
// 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); } }
/** Returns 1 if abs(xvel) <= 1/2 abs(yvel) 0 otherwise */ virtual int evaluate(const Leap::Frame &frame, const std::string& nodeid) { Leap::Hand h = frame.hand(0); if (h.isValid()) { Leap::Vector vel = h.palmVelocity(); return (abs(vel.x) <= 0.5 * abs(vel.y)) ? 1 : 0; } else return 0; }
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; }
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; }
virtual void onFrame (const Leap::Controller&) { const Leap::Frame frame(m_Controller.frame(0)); const Leap::Hand hand(frame.hands().rightmost()); if (!hand.isValid()) { m_LastNormalizedPos.reset(); return; } const Leap::Vector pos(hand.palmPosition()); m_LastNormalizedPos = frame.interactionBox().normalizePoint(pos); }
void jester::LeapMotionImpl::processHand(Leap::Hand hand, LeapHand whichHand) { Bone::JointId toSet = (whichHand == LeapHand::LEFT ? Bone::JointId::WRIST_L : Bone::JointId::WRIST_R); Bone::BoneId firstFinger = (whichHand == LeapHand::LEFT ? Bone::BoneId::PHALANX_L_1 : Bone::BoneId::PHALANX_R_1); JointFusionData wristData; wristData.confidence = LeapConfidence; wristData.position = glm::vec3(hand.palmPosition()[0] / LeapMeasurmentScalingFactor, hand.palmPosition()[1] / LeapMeasurmentScalingFactor, hand.palmPosition()[2] / LeapMeasurmentScalingFactor); wristData.id = toSet; kJointData.insert(std::pair<Bone::JointId, JointFusionData>(toSet, wristData)); processFingers(hand, firstFinger, whichHand); }
int StateKen::eventShake(StateContext& context, const Leap::Controller& controller) { std::cout << "けん\n" << std::endl; const Leap::Frame frame = controller.frame(); const Leap::Hand hand = frame.hands()[0]; Leap::Vector position = hand.palmPosition(); JankenApp::getInstance()->setShakeStartPosition(position); int ret = context.changeState(StatePon::getInstance()); return ret; }
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); } } } }
void convertHandRotation(const Leap::Hand& hand, MatrixF& outRotation) { // We need to convert from Motion coordinates to // Torque coordinates. The conversion is: // // Motion Torque // a b c a b c a -c b // d e f --> -g -h -i --> -g i -h // g h i d e f d -f e const Leap::Vector& handToFingers = hand.direction(); Leap::Vector handFront = -handToFingers; const Leap::Vector& handDown = hand.palmNormal(); Leap::Vector handUp = -handDown; Leap::Vector handRight = handUp.cross(handFront); outRotation.setColumn(0, Point4F( handRight.x, -handRight.z, handRight.y, 0.0f)); outRotation.setColumn(1, Point4F( -handFront.x, handFront.z, -handFront.y, 0.0f)); outRotation.setColumn(2, Point4F( handUp.x, -handUp.z, handUp.y, 0.0f)); outRotation.setPosition(Point3F::Zero); }
void LeapListener::onFrame(const Controller& controller) { const Frame frame = controller.frame(); static int64_t lastFrameID = 0; if(frame.id() < lastFrameID+10) return; Leap::HandList hands = frame.hands(); Leap::Hand hand = hands[0]; if(hand.isValid()) { float pitch = hand.direction().pitch(); float yaw = hand.direction().yaw(); float roll = hand.palmNormal().roll(); float height = hand.palmPosition().y; std::cout << "Pitch: " << RAD_TO_DEG*pitch << " Yaw: " << RAD_TO_DEG*yaw << " Roll: " << RAD_TO_DEG*roll << " Height: " << height << " Frame: " << frame.id() << std::endl; // switch(gest.type()) { // case Gesture::TYPE_CIRCLE: // std::cout << "Takeoff" << std::endl; // if (jakopter_takeoff() < 0) // return; // break; // case Gesture::TYPE_SWIPE: // std::cout << "Land" << std::endl; // if (jakopter_land() < 0) // return; // break; // default: // break; // } char c = 's'; if (height > 300) c = 'u'; else if(height < 75) c = 'k'; else if (height < 150) c = 'd'; if (roll > 0.7) c = 'l'; else if (roll < -0.7) c = 'r'; if (pitch > 0.7) c = 'b'; else if (pitch < -0.7) c = 'f'; FILE *cmd = fopen(CMDFILENAME,"w"); fprintf(cmd, "%c\n", c); fclose(cmd); } lastFrameID = frame.id(); }
void BallGesture::recognizedControls(const Leap::Controller &controller, std::vector<ControlPtr> &controls) { Leap::Frame frame = controller.frame(); // hands detected? if (frame.hands().isEmpty()) return; for (int i = 0; i < frame.hands().count(); i++) { // gonna assume the user only has two hands. sometimes leap thinks otherwise. if (i > 1) break; Leap::Hand hand = frame.hands()[i]; double radius = hand.sphereRadius(); // in mm if (! radius) continue; BallRadiusPtr bc = make_shared<BallRadius>(radius, i); ControlPtr cptr = dynamic_pointer_cast<Control>(bc); controls.push_back(cptr); } }
void MenuController::leapMenuClosed(const Leap::Controller& controller, const Leap::Frame& frame) { Leap::GestureList gestures = frame.gestures(); for (const Leap::Gesture& g : gestures) { if (g.type() == Leap::Gesture::TYPE_CIRCLE) { Leap::CircleGesture circle(g); bool xyPlane = abs(circle.normal().dot(Leap::Vector(0, 0, 1))) > 0.8f; if (circle.progress() > 1.0f && xyPlane && circle.radius() > 35.0f) { Leap::Hand hand = circle.hands().frontmost(); Leap::FingerList fingers = hand.fingers(); if (fingers[1].isValid()) { pointer_ = fingers[1]; } else if (fingers[2].isValid()) { pointer_ = fingers[2]; } bool main = pointer_.isValid() && fingers.extended().count() <= 2; bool secondary = fingers[Leap::Finger::TYPE_INDEX].isExtended() && fingers[Leap::Finger::TYPE_THUMB].isExtended() && fingers[Leap::Finger::TYPE_MIDDLE].isExtended() && fingers.extended().count() == 3; if (main) { leap_state_ = LeapState::triggered_main; } else if (secondary && MainController::getInstance().focusLayer() && MainController::getInstance().focusLayer()->contextMenu()) { leap_state_ = LeapState::triggered_context; } } } } }
// 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 }
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 LeapListener::onFrame(const Controller& controller) { const Frame frame = controller.frame(); Leap::HandList hands = frame.hands(); Leap::Hand hand = hands[0]; if(hand.isValid()){ leapData.pitch = hand.direction().pitch(); leapData.yaw = hand.direction().yaw(); leapData.roll = hand.palmNormal().roll(); leapData.height = hand.palmPosition().y; std::cout << "Frame id: " << frame.id() << ", timestamp: " << frame.timestamp() << ", height: " << leapData.height << ", pitch: " << RAD_TO_DEG * leapData.pitch << ", yaw: " << RAD_TO_DEG * leapData.yaw << ", roll: " << RAD_TO_DEG * leapData.roll << std::endl; } }
// 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 } }
// 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 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 } }
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(); }
bool hand_x_coordinate_comparator (Leap::Hand a, Leap::Hand b) { return a.palmPosition()[0] < b.palmPosition()[0]; }
bool finger_count_comparator (Leap::Hand a, Leap::Hand b) { return a.fingers().count() > b.fingers().count(); }
void jester::LeapMotionImpl::processFingers(Leap::Hand hand, Bone::BoneId fingerOne, LeapHand whichHand) { Leap::FingerList fingerList = hand.fingers(); std::vector<Leap::Finger> fingers; FingerData *fingerIds = (whichHand == LeapHand::LEFT ? kLeftFingerIds : kRightFingerIds); bool fingersFound[] = {false, false, false, false, false}; //project finger tip positions onto palm plane and calculate angle for (Leap::FingerList::const_iterator fingerIter = fingerList.begin(); fingerIter != fingerList.end(); fingerIter++) { fingers.push_back(*fingerIter); } //if this is the first time we've seen the full hand, calibrate the finger lengths if (fingerIds[0].id == -1 && fingers.size() == 5) { if (whichHand == LeapHand::LEFT) std::sort(fingers.begin(), fingers.end(), left_hand_finger_x_coordinate_comparator); else if (whichHand == LeapHand::RIGHT) std::sort(fingers.begin(), fingers.end(), right_hand_finger_x_coordinate_comparator); else return; fingersFound[0] = fingersFound[1] = fingersFound[2] = fingersFound[3] = fingersFound[4] = true; for (int i = 0; i < 5; i++) { fingerIds[i].id = fingers[i].id(); fingerIds[i].length = fingers[i].length(); } } else if (fingerIds[0].id == -1) return; //search for all of the known finger ids for (unsigned int i = 0; i < 5; i++) { for (unsigned int j = 0; j < fingers.size(); j++) { if (fingers[j].id() == fingerIds[i].id) { fingersFound[i] = true; setFingerInJointData(fingers[j], static_cast<Bone::BoneId>(fingerOne + i)); fingers.erase(fingers.begin() + j); } } } //match all unclaimed fingers based on closest size for (unsigned int i = 0; i < fingers.size(); i++) { float closestLengthDelta = FLT_MAX; int closestFingerIx = -1; for (int j = 0; j < 5; j++) { if (!fingersFound[j]) { float lengthDelta = abs(fingerIds[j].length - fingers[i].length()); if (lengthDelta < closestLengthDelta) { closestLengthDelta = lengthDelta; closestFingerIx = j; } } } if (closestFingerIx >= 0) { fingersFound[closestFingerIx] = true; fingerIds[closestFingerIx].id = fingers[i].id(); setFingerInJointData(fingers[i], static_cast<Bone::BoneId>(fingerOne + closestFingerIx)); } } }
void Output::PrintHand(Leap::Hand hand){ Leap::Vector handCenter = hand.palmPosition(); std::cout << "Hand " << std::endl; PrintVector(handCenter); std::cout<< std::endl; }
void LeapListener::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() << ", fingers: " << frame.fingers().count() << ", tools: " << frame.tools().count() << ", gestures: " << frame.gestures().count(); */ if (!frame.hands().isEmpty()) { // Get the first hand const Leap::Hand hand = frame.hands()[0]; qDebug() << "Radius: " << hand.sphereRadius(); // Grab if(hand.sphereRadius() < 50.0 && hand.translationProbability(controller.frame(1)) > 0.6){ Leap::Vector v = hand.translation(controller.frame(1)); v = 0.1 * v; glwidget_->camera_.translate(v.x, v.y, v.z); glwidget_->update(); } qDebug() << "Hand pos" << hand.palmPosition().x << hand.palmPosition().y << hand.palmPosition().z; if(frame.fingers().count() > 200 && frame.hands().count() == 1){ Leap::Vector trans = hand.translation(controller.frame(1)); //int dir = trans.y > 0 ? 1 : -1; trans = 0.1 * trans; //glwidget_->camera_.translate(0, 0, dir*0.1); //Leap::Vector rot = hand.rotationAxis(controller.frame()); float yaw = hand.rotationAngle(controller.frame(1), Leap::Vector(1, 0, 0)); float pitch = hand.rotationAngle(controller.frame(1), Leap::Vector(1, 0, 0)); // works float roll = hand.rotationAngle(controller.frame(1), Leap::Vector(0, 0, 1)); //qDebug() << yaw << pitch << roll; glwidget_->camera_.rotate3D(yaw, pitch, roll); //glwidget_->camera_.rotate2D(0.01 * trans.x, 0.01 * trans.y); glwidget_->update(); } /* // Check if the hand has any fingers const Leap::FingerList fingers = hand.fingers(); if (!fingers.empty()) { // Calculate the hand's average finger tip position Leap::Vector avgPos; for (int i = 0; i < fingers.count(); ++i) { avgPos += fingers[i].tipPosition(); } avgPos /= (float)fingers.count(); std::cout << "Hand has " << fingers.count() << " fingers, average finger tip position" << avgPos<< std::endl; } // Get the hand's sphere radius and palm position std::cout << "Hand sphere radius: " << hand.sphereRadius() << " mm, 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 << "Hand 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 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()) <= M_PI/4) { 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().gesture(circle.id())); sweptAngle = (circle.progress() - previousUpdate.progress()) * 2 * M_PI; } std::cout << "Circle id: " << gesture.id() << ", state: " << 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 << "Swipe id: " << gesture.id() << ", state: " << gesture.state() << ", direction: " << swipe.direction() << ", speed: " << swipe.speed() << std::endl; break; } case Leap::Gesture::TYPE_KEY_TAP: { Leap::KeyTapGesture tap = gesture; std::cout << "Key Tap id: " << gesture.id() << ", state: " << gesture.state() << ", position: " << tap.position() << ", direction: " << tap.direction()<< std::endl; break; } case Leap::Gesture::TYPE_SCREEN_TAP: { Leap::ScreenTapGesture screentap = gesture; std::cout << "Screen Tap id: " << gesture.id() << ", state: " << gesture.state() << ", position: " << screentap.position() << ", direction: " << screentap.direction()<< std::endl; break; } default: std::cout << "Unknown gesture type."; break; } */ } }
//-------------------------------------------------------------- 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(); }
//Main Event driven tick void ULeapController::InterfaceEventTick(float DeltaTime) { //This is our tick event that is forwarded from the delegate, check validity if (!_private->interfaceDelegate) return; //Pointers Leap::Frame frame = _private->leap.frame(); Leap::Frame pastFrame = _private->leap.frame(1); //-Hands- //Hand Count int handCount = frame.hands().count(); if (_private->pastState.handCount != handCount) { ILeapEventInterface::Execute_HandCountChanged(_private->interfaceDelegate, handCount); //Zero our input mapping orientations (akin to letting go of a joystick) if (handCount == 0) { EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmPitch, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmYaw, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmRoll, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmPitch, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmYaw, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmRoll, 0, 0, 0); } } //Cycle through each hand for (int i = 0; i < handCount; i++) { Leap::Hand hand = frame.hands()[i]; LeapHandStateData pastHandState = _private->pastState.stateForId(hand.id()); //we use a custom class to hold reliable state tracking based on id's //Make a ULeapHand if (_private->eventHand == NULL) { _private->eventHand = NewObject<ULeapHand>(this); _private->eventHand->SetFlags(RF_RootSet); } _private->eventHand->setHand(hand); //Emit hand ILeapEventInterface::Execute_LeapHandMoved(_private->interfaceDelegate, _private->eventHand); //Left/Right hand forwarding if (hand.isRight()) { ILeapEventInterface::Execute_LeapRightHandMoved(_private->interfaceDelegate, _private->eventHand); //Input Mapping FRotator palmOrientation = _private->eventHand->PalmOrientation; EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmPitch, palmOrientation.Pitch * LEAP_IM_SCALE, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmYaw, palmOrientation.Yaw * LEAP_IM_SCALE, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmRoll, palmOrientation.Roll * LEAP_IM_SCALE, 0, 0); } else if (hand.isLeft()) { ILeapEventInterface::Execute_LeapLeftHandMoved(_private->interfaceDelegate, _private->eventHand); //Input Mapping FRotator palmOrientation = _private->eventHand->PalmOrientation; EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmPitch, palmOrientation.Pitch * LEAP_IM_SCALE, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmYaw, palmOrientation.Yaw * LEAP_IM_SCALE, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmRoll, palmOrientation.Roll * LEAP_IM_SCALE, 0, 0); } //Grabbing float grabStrength = hand.grabStrength(); bool grabbed = handClosed(grabStrength); if (grabbed) ILeapEventInterface::Execute_LeapHandGrabbing(_private->interfaceDelegate, grabStrength, _private->eventHand); if (grabbed && !pastHandState.grabbed) { ILeapEventInterface::Execute_LeapHandGrabbed(_private->interfaceDelegate, grabStrength, _private->eventHand); //input mapping if (_private->eventHand->HandType == LeapHandType::HAND_LEFT) EmitKeyDownEventForKey(EKeysLeap::LeapLeftGrab, 0, 0); else EmitKeyDownEventForKey(EKeysLeap::LeapRightGrab, 0, 0); }else if (!grabbed && pastHandState.grabbed) { ILeapEventInterface::Execute_LeapHandReleased(_private->interfaceDelegate, grabStrength, _private->eventHand); //input mapping if (_private->eventHand->HandType == LeapHandType::HAND_LEFT) EmitKeyUpEventForKey(EKeysLeap::LeapLeftGrab, 0, 0); else EmitKeyUpEventForKey(EKeysLeap::LeapRightGrab, 0, 0); } //Pinching float pinchStrength = hand.pinchStrength(); bool pinched = handPinched(pinchStrength); //While grabbing disable pinching detection, this helps to reduce spam as pose confidence plummets if (grabbed) pinched = pastHandState.pinched; else { if (pinched) ILeapEventInterface::Execute_LeapHandPinching(_private->interfaceDelegate, pinchStrength, _private->eventHand); if (pinched && !pastHandState.pinched) { ILeapEventInterface::Execute_LeapHandPinched(_private->interfaceDelegate, pinchStrength, _private->eventHand); //input mapping if (_private->eventHand->HandType == LeapHandType::HAND_LEFT) EmitKeyDownEventForKey(EKeysLeap::LeapLeftPinch, 0, 0); else EmitKeyDownEventForKey(EKeysLeap::LeapRightPinch, 0, 0); } else if (!pinched && pastHandState.pinched) { ILeapEventInterface::Execute_LeapHandUnpinched(_private->interfaceDelegate, pinchStrength, _private->eventHand); //input mapping if (_private->eventHand->HandType == LeapHandType::HAND_LEFT) EmitKeyUpEventForKey(EKeysLeap::LeapLeftPinch, 0, 0); else EmitKeyUpEventForKey(EKeysLeap::LeapRightPinch, 0, 0); } } //-Fingers- Leap::FingerList fingers = hand.fingers(); //Count int fingerCount = fingers.count(); if ((pastHandState.fingerCount != fingerCount)) ILeapEventInterface::Execute_FingerCountChanged(_private->interfaceDelegate, fingerCount); if (_private->eventFinger == NULL) { _private->eventFinger = NewObject<ULeapFinger>(this); _private->eventFinger->SetFlags(RF_RootSet); } Leap::Finger finger; //Cycle through each finger for (int j = 0; j < fingerCount; j++) { finger = fingers[j]; _private->eventFinger->setFinger(finger); //Finger Moved if (finger.isValid()) ILeapEventInterface::Execute_LeapFingerMoved(_private->interfaceDelegate, _private->eventFinger); } //Do these last so we can easily override debug shapes //Leftmost finger = fingers.leftmost(); _private->eventFinger->setFinger(finger); ILeapEventInterface::Execute_LeapLeftMostFingerMoved(_private->interfaceDelegate, _private->eventFinger); //Rightmost finger = fingers.rightmost(); _private->eventFinger->setFinger(finger); ILeapEventInterface::Execute_LeapRightMostFingerMoved(_private->interfaceDelegate, _private->eventFinger); //Frontmost finger = fingers.frontmost(); _private->eventFinger->setFinger(finger); ILeapEventInterface::Execute_LeapFrontMostFingerMoved(_private->interfaceDelegate, _private->eventFinger); //touch only for front-most finger, most common use case float touchDistance = finger.touchDistance(); if (touchDistance <= 0.f) ILeapEventInterface::Execute_LeapFrontFingerTouch(_private->interfaceDelegate, _private->eventFinger); //Set the state data for next cycle pastHandState.grabbed = grabbed; pastHandState.pinched = pinched; pastHandState.fingerCount = fingerCount; _private->pastState.setStateForId(pastHandState, hand.id()); } _private->pastState.handCount = handCount; //Gestures for (int i = 0; i < frame.gestures().count(); i++) { Leap::Gesture gesture = frame.gestures()[i]; Leap::Gesture::Type type = gesture.type(); switch (type) { case Leap::Gesture::TYPE_CIRCLE: if (_private->eventCircleGesture == NULL){ _private->eventCircleGesture = NewObject<ULeapCircleGesture>(this); _private->eventCircleGesture->SetFlags(RF_RootSet); } _private->eventCircleGesture->setGesture(Leap::CircleGesture(gesture)); ILeapEventInterface::Execute_CircleGestureDetected(_private->interfaceDelegate, _private->eventCircleGesture); _private->eventGesture = _private->eventCircleGesture; break; case Leap::Gesture::TYPE_KEY_TAP: if (_private->eventKeyTapGesture == NULL) { _private->eventKeyTapGesture = NewObject<ULeapKeyTapGesture>(this); _private->eventKeyTapGesture->SetFlags(RF_RootSet); } _private->eventKeyTapGesture->setGesture(Leap::KeyTapGesture(gesture)); ILeapEventInterface::Execute_KeyTapGestureDetected(_private->interfaceDelegate, _private->eventKeyTapGesture); _private->eventGesture = _private->eventKeyTapGesture; break; case Leap::Gesture::TYPE_SCREEN_TAP: if (_private->eventScreenTapGesture == NULL) { _private->eventScreenTapGesture = NewObject<ULeapScreenTapGesture>(this); _private->eventScreenTapGesture->SetFlags(RF_RootSet); } _private->eventScreenTapGesture->setGesture(Leap::ScreenTapGesture(gesture)); ILeapEventInterface::Execute_ScreenTapGestureDetected(_private->interfaceDelegate, _private->eventScreenTapGesture); _private->eventGesture = _private->eventScreenTapGesture; break; case Leap::Gesture::TYPE_SWIPE: if (_private->eventSwipeGesture == NULL) { _private->eventSwipeGesture = NewObject<ULeapSwipeGesture>(this); _private->eventSwipeGesture->SetFlags(RF_RootSet); } _private->eventSwipeGesture->setGesture(Leap::SwipeGesture(gesture)); ILeapEventInterface::Execute_SwipeGestureDetected(_private->interfaceDelegate, _private->eventSwipeGesture); _private->eventGesture = _private->eventSwipeGesture; break; default: break; } //emit gesture if (type != Leap::Gesture::TYPE_INVALID) { ILeapEventInterface::Execute_GestureDetected(_private->interfaceDelegate, _private->eventGesture); } } //Image if (_private->allowImages && _private->imageEventsEnabled) { int imageCount = frame.images().count(); for (int i = 0; i < imageCount; i++) { Leap::Image image = frame.images()[i]; //Loop modification - Only emit 0 and 1, use two different pointers so we can get different images if (i == 0) { if (_private->eventImage1 == NULL) { _private->eventImage1 = NewObject<ULeapImage>(this); _private->eventImage1->SetFlags(RF_RootSet); } _private->eventImage1->setLeapImage(image); ILeapEventInterface::Execute_RawImageReceived(_private->interfaceDelegate, _private->eventImage1->Texture(), _private->eventImage1); } else if (i == 1) { if (_private->eventImage2 == NULL) { _private->eventImage2 = NewObject<ULeapImage>(this); _private->eventImage2->SetFlags(RF_RootSet); } _private->eventImage2->setLeapImage(image); ILeapEventInterface::Execute_RawImageReceived(_private->interfaceDelegate, _private->eventImage2->Texture(), _private->eventImage2); } } } }