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(); }
void jester::LeapMotionImpl::setFingerInJointData(Leap::Finger finger, Bone::BoneId bone) { std::pair<Bone::JointId, Bone::JointId> joints = Bone::BoneToJointsMap.find(bone)->second; glm::vec3 fingerTip(finger.tipPosition()[0], finger.tipPosition()[1], finger.tipPosition()[2]); glm::vec3 fingerDir(finger.direction()[0], finger.direction()[1], finger.direction()[2]); float fingerLength = finger.length(); JointFusionData fingerStartData; JointFusionData fingerEndData; fingerDir = glm::normalize(fingerDir); glm::vec3 fingerStart = fingerTip - fingerLength * fingerDir; glm::vec3 boneStart = glm::vec3(fingerStart / LeapMeasurmentScalingFactor); glm::vec3 boneEnd = glm::vec3(fingerTip / LeapMeasurmentScalingFactor); fingerStartData.position = boneStart; fingerEndData.position = boneEnd; fingerStartData.id = joints.first; fingerEndData.id = joints.second; fingerStartData.confidence = fingerEndData.confidence = LeapConfidence; kJointData.insert(std::pair<Bone::JointId, JointFusionData>(joints.first, fingerStartData)); kJointData.insert(std::pair<Bone::JointId, JointFusionData>(joints.second, fingerEndData)); }
void LeapManager::nextFrame(Avatar& avatar) { // Apply the frame data directly to the avatar. Hand& hand = avatar.getHand(); // If we actually get valid Leap data, this will be set to true; bool gotRealData = false; if (controllersExist()) { _listener->onFrame(*_controller); } #ifndef LEAP_STUBS if (controllersExist()) { gotRealData = true; // First, see which palms and fingers are still valid. Leap::Frame& frame = _listener->lastFrame; // Note that this is O(n^2) at worst, but n is very small. // After this many frames of no data, assume the digit is lost. const int assumeLostAfterFrameCount = 10; // Increment our frame data counters for (size_t i = 0; i < hand.getNumPalms(); ++i) { PalmData& palm = hand.getPalms()[i]; palm.incrementFramesWithoutData(); if (palm.getFramesWithoutData() > assumeLostAfterFrameCount) { palm.setActive(false); } for (size_t f = 0; f < palm.getNumFingers(); ++f) { FingerData& finger = palm.getFingers()[f]; finger.incrementFramesWithoutData(); if (finger.getFramesWithoutData() > assumeLostAfterFrameCount) { finger.setActive(false); } } } size_t numLeapHands = frame.hands().count(); std::vector<PalmData*> palmAssignment(numLeapHands); // Look for matches for (size_t index = 0; index < numLeapHands; ++index) { PalmData* takeoverCandidate = NULL; palmAssignment[index] = NULL; Leap::Hand leapHand = frame.hands()[index]; int id = leapHand.id(); if (leapHand.isValid()) { for (size_t i = 0; i < hand.getNumPalms() && palmAssignment[index] == NULL; ++i) { PalmData& palm = hand.getPalms()[i]; if (palm.getLeapID() == id) { // Found hand with the same ID. We're set! palmAssignment[index] = &palm; palm.resetFramesWithoutData(); } else if (palm.getFramesWithoutData() > assumeLostAfterFrameCount) { takeoverCandidate = &palm; } } if (palmAssignment[index] == NULL) { palmAssignment[index] = takeoverCandidate; } if (palmAssignment[index] == NULL) { palmAssignment[index] = &hand.addNewPalm(); } } } // Apply the assignments for (size_t index = 0; index < numLeapHands; ++index) { if (palmAssignment[index]) { Leap::Hand leapHand = frame.hands()[index]; PalmData& palm = *(palmAssignment[index]); palm.resetFramesWithoutData(); palm.setLeapID(leapHand.id()); palm.setActive(true); const Leap::Vector pos = leapHand.palmPosition(); const Leap::Vector normal = leapHand.palmNormal(); palm.setRawPosition(glm::vec3(pos.x, pos.y, pos.z)); palm.setRawNormal(glm::vec3(normal.x, normal.y, normal.z)); } } // Look for fingers per palm for (size_t i = 0; i < hand.getNumPalms(); ++i) { PalmData& palm = hand.getPalms()[i]; if (palm.isActive()) { Leap::Hand leapHand = frame.hand(palm.getLeapID()); if (leapHand.isValid()) { int numLeapFingers = leapHand.fingers().count(); std::vector<FingerData*> fingerAssignment(numLeapFingers); // Look for matches for (size_t index = 0; index < numLeapFingers; ++index) { FingerData* takeoverCandidate = NULL; fingerAssignment[index] = NULL; Leap::Finger leapFinger = leapHand.fingers()[index]; int id = leapFinger.id(); if (leapFinger.isValid()) { for (size_t f = 0; f < palm.getNumFingers() && fingerAssignment[index] == NULL; ++f) { FingerData& finger = palm.getFingers()[f]; if (finger.getLeapID() == id) { // Found hand with the same ID. We're set! fingerAssignment[index] = &finger; } else if (finger.getFramesWithoutData() > assumeLostAfterFrameCount) { takeoverCandidate = &finger; } } // If we didn't find a match, but we found an unused finger, us it. if (fingerAssignment[index] == NULL) { fingerAssignment[index] = takeoverCandidate; } } } // Apply the assignments for (size_t index = 0; index < numLeapFingers; ++index) { if (fingerAssignment[index]) { Leap::Finger leapFinger = leapHand.fingers()[index]; FingerData& finger = *(fingerAssignment[index]); finger.resetFramesWithoutData(); finger.setLeapID(leapFinger.id()); finger.setActive(true); #ifdef USE_STABILIZED_DATA const Leap::Vector tip = leapFinger.stabilizedTipPosition(); #else const Leap::Vector tip = leapFinger.tipPosition(); #endif const Leap::Vector root = tip - leapFinger.direction() * leapFinger.length(); finger.setRawTipPosition(glm::vec3(tip.x, tip.y, tip.z)); finger.setRawRootPosition(glm::vec3(root.x, root.y, root.z)); } } } } } } #endif if (!gotRealData) { if (_doFakeFingers) { // There's no real Leap data and we need to fake it. for (size_t i = 0; i < hand.getNumPalms(); ++i) { static const glm::vec3 fakeHandOffsets[] = { glm::vec3( -500.0f, 50.0f, 50.0f), glm::vec3( 0.0f, 50.0f, 50.0f) }; static const glm::vec3 fakeHandFingerMirrors[] = { glm::vec3( -1.0f, 1.0f, 1.0f), glm::vec3( 1.0f, 1.0f, 1.0f) }; static const glm::vec3 fakeFingerPositions[] = { glm::vec3( -60.0f, 0.0f, -40.0f), glm::vec3( -20.0f, 0.0f, -60.0f), glm::vec3( 20.0f, 0.0f, -60.0f), glm::vec3( 60.0f, 0.0f, -40.0f), glm::vec3( -50.0f, 0.0f, 30.0f) }; PalmData& palm = hand.getPalms()[i]; palm.setActive(true); // Simulated data palm.setRawPosition(glm::vec3( 0.0f, 0.0f, 0.0f) + fakeHandOffsets[i]); palm.setRawNormal(glm::vec3(0.0f, 1.0f, 0.0f)); for (size_t f = 0; f < palm.getNumFingers(); ++f) { FingerData& finger = palm.getFingers()[f]; finger.setActive(true); const float tipScale = 1.5f; const float rootScale = 0.75f; glm::vec3 fingerPos = fakeFingerPositions[f] * fakeHandFingerMirrors[i]; finger.setRawTipPosition(fingerPos * tipScale + fakeHandOffsets[i]); finger.setRawRootPosition(fingerPos * rootScale + fakeHandOffsets[i]); } } } else { // Just deactivate everything. for (size_t i = 0; i < hand.getNumPalms(); ++i) { PalmData& palm = hand.getPalms()[i]; palm.setActive(false); for (size_t f = 0; f < palm.getNumFingers(); ++f) { FingerData& finger = palm.getFingers()[f]; finger.setActive(false); } } } } hand.updateFingerTrails(); }
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; } }