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); } } } }
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; }
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 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(); } }
//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); } } } }
void FLeapMotionInputDevice::ParseEvents() { //Optimization: If we don't have any delegates, skip if (EventDelegates.Num() == 0) { return; } //Pointers Leap::Frame Frame = ControllerData.LeapController.frame(); Leap::Frame PastFrame = ControllerData.LeapController.frame(1); //Calculate HMD Timewarp if valid if (GEngine->HMDDevice.IsValid() && ControllerData.bTimeWarpEnabled) { LeapHMDSnapshot ThenSnapshot = HMDSamples->HMDSampleClosestToTimestamp(Frame.timestamp()); LeapHMDSnapshot NowSnapShot = HMDSamples->CurrentHMDSample(); LeapHMDSnapshot HistorySnapshot = HMDSamples->LastHMDSample(); //reduce jitter //ControllerData.TimeWarpSnapshot = NowSnapShot.Difference(ThenSnapshot, ControllerData.TimeWarpFactor);// * ControllerData.TimeWarpFactor; FQuat WarpQuat = NowSnapShot.Orientation;//FQuat::Slerp(NowSnapShot.Orientation, HistorySnapshot.Orientation, ControllerData.TimeWarpTween); FQuat ThenTweened = FQuat::Slerp(ThenSnapshot.Orientation, HistorySnapshot.Orientation, ControllerData.TimeWarpTween); ControllerData.TimeWarpSnapshot.Orientation = (WarpQuat.Inverse() * ControllerData.TimeWarpFactor) * ThenTweened; ControllerData.TimeWarpAmountMs = (ControllerData.TimeWarpSnapshot.Timestamp) / 1000.f; } //-Hands- //Hand Count int HandCount = Frame.hands().count(); if (PastState->HandCount != HandCount) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_HandCountChanged(EventDelegate, 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 = PastState->StateForId(Hand.id()); //we use a custom class to hold reliable state tracking based on id's //Make a ULeapHand if (PEventHand == nullptr) { PEventHand = NewObject<ULeapHand>(); PEventHand->AddToRoot(); } PEventHand->SetHand(Hand); //Emit hand CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandMoved(EventDelegate, PEventHand); }); //Left/Right hand forwarding if (Hand.isRight()) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapRightHandMoved(EventDelegate, PEventHand); }); //Input Mapping FRotator PalmOrientation = PEventHand->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()) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapLeftHandMoved(EventDelegate, PEventHand); }); //Input Mapping FRotator PalmOrientation = PEventHand->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) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandGrabbing(EventDelegate, GrabStrength, PEventHand); }); } if (Grabbed && !PastHandState.Grabbed) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandGrabbed(EventDelegate, GrabStrength, PEventHand); }); //input mapping if (PEventHand->HandType == LeapHandType::HAND_LEFT) { EmitKeyDownEventForKey(EKeysLeap::LeapLeftGrab, 0, 0); } else { EmitKeyDownEventForKey(EKeysLeap::LeapRightGrab, 0, 0); } } else if (!Grabbed && PastHandState.Grabbed) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandReleased(EventDelegate, GrabStrength, PEventHand); }); //input mapping if (PEventHand->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) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandPinching(EventDelegate, PinchStrength, PEventHand); }); } if (Pinched && !PastHandState.Pinched) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandPinched(EventDelegate, PinchStrength, PEventHand); }); //input mapping if (PEventHand->HandType == LeapHandType::HAND_LEFT) { EmitKeyDownEventForKey(EKeysLeap::LeapLeftPinch, 0, 0); } else { EmitKeyDownEventForKey(EKeysLeap::LeapRightPinch, 0, 0); } } else if (!Pinched && PastHandState.Pinched) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandUnpinched(EventDelegate, PinchStrength, PEventHand); }); //input mapping if (PEventHand->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)) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_FingerCountChanged(EventDelegate, FingerCount); }); } if (PEventFinger == nullptr) { PEventFinger = NewObject<ULeapFinger>(); PEventFinger->AddToRoot(); } Leap::Finger Finger; //Cycle through each finger for (int j = 0; j < FingerCount; j++) { Finger = Fingers[j]; PEventFinger->SetFinger(Finger); //Finger Moved if (Finger.isValid()) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapFingerMoved(EventDelegate, PEventFinger); }); } } //Do these last so we can easily override debug shapes //Leftmost Finger = Fingers.leftmost(); PEventFinger->SetFinger(Finger); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapLeftMostFingerMoved(EventDelegate, PEventFinger); }); //Rightmost Finger = Fingers.rightmost(); PEventFinger->SetFinger(Finger); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapRightMostFingerMoved(EventDelegate, PEventFinger); }); //Frontmost Finger = Fingers.frontmost(); PEventFinger->SetFinger(Finger); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapFrontMostFingerMoved(EventDelegate, PEventFinger); }); //touch only for front-most finger, most common use case float touchDistance = Finger.touchDistance(); if (touchDistance <= 0.f) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapFrontFingerTouch(EventDelegate, PEventFinger); }); } //Set the state data for next cycle PastHandState.Grabbed = Grabbed; PastHandState.Pinched = Pinched; PastHandState.FingerCount = FingerCount; PastState->SetStateForId(PastHandState, Hand.id()); } 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 (PEventCircleGesture == nullptr) { PEventCircleGesture = NewObject<ULeapCircleGesture>(); PEventCircleGesture->AddToRoot(); } PEventCircleGesture->SetGesture(Leap::CircleGesture(Gesture)); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_CircleGestureDetected(EventDelegate, PEventCircleGesture); }); PEventGesture = PEventCircleGesture; break; case Leap::Gesture::TYPE_KEY_TAP: if (PEventKeyTapGesture == nullptr) { PEventKeyTapGesture = NewObject<ULeapKeyTapGesture>(); PEventKeyTapGesture->AddToRoot(); } PEventKeyTapGesture->SetGesture(Leap::KeyTapGesture(Gesture)); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_KeyTapGestureDetected(EventDelegate, PEventKeyTapGesture); }); PEventGesture = PEventKeyTapGesture; break; case Leap::Gesture::TYPE_SCREEN_TAP: if (PEventScreenTapGesture == nullptr) { PEventScreenTapGesture = NewObject<ULeapScreenTapGesture>(); PEventScreenTapGesture->AddToRoot(); } PEventScreenTapGesture->SetGesture(Leap::ScreenTapGesture(Gesture)); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_ScreenTapGestureDetected(EventDelegate, PEventScreenTapGesture); }); PEventGesture = PEventScreenTapGesture; break; case Leap::Gesture::TYPE_SWIPE: if (PEventSwipeGesture == nullptr) { PEventSwipeGesture = NewObject<ULeapSwipeGesture>(); PEventSwipeGesture->AddToRoot(); } PEventSwipeGesture->SetGesture(Leap::SwipeGesture(Gesture)); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_SwipeGestureDetected(EventDelegate, PEventSwipeGesture); }); PEventGesture = PEventSwipeGesture; break; default: break; } //emit gesture if (Type != Leap::Gesture::TYPE_INVALID) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_GestureDetected(EventDelegate, PEventGesture); }); } } //Image if (ControllerData.bAllowImageEvents && ControllerData.bImageEventsEnabled) { int ImageCount = Frame.images().count(); //We only support getting both images if (ImageCount >= 2) { Leap::Image Image1 = Frame.images()[0]; if (PEventImage1 == nullptr) { PEventImage1 = NewObject<ULeapImage>(); PEventImage1->AddToRoot(); } PEventImage1->UseGammaCorrection = ControllerData.bUseGammaCorrection; PEventImage1->SetLeapImage(Image1); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_RawImageReceived(EventDelegate, PEventImage1->Texture(), PEventImage1); }); Leap::Image Image2 = Frame.images()[1]; if (PEventImage2 == nullptr) { PEventImage2 = NewObject<ULeapImage>(); PEventImage2->AddToRoot(); } PEventImage2->UseGammaCorrection = ControllerData.bUseGammaCorrection; PEventImage2->SetLeapImage(Image2); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_RawImageReceived(EventDelegate, PEventImage2->Texture(), PEventImage2); }); } } }
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) }
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; } }