25 #include "sLeapMotion.h" 27 extern int LEAPMOTION_CONNECTED_CB;
28 extern int LEAPMOTION_DISCONNECTED_CB;
30 extern int LEAPMOTION_CIRCLE_CB;
31 extern int LEAPMOTION_SWIPE_CB;
32 extern int LEAPMOTION_KEYTAP_CB;
33 extern int LEAPMOTION_SCREENTAP_CB;
41 std::vector<int> fids;
42 mLastPointableIds.resize(16, fids);
43 mLastHandIds.resize(2, -1);
44 mLastToolsIds.resize(2, -1);
55 mController.removeListener(*
this);
61 void sLeapMotion::Init()
63 mController.addListener(*
this);
67 void sLeapMotion::onInit(
const Controller& controller)
72 void sLeapMotion::onConnect(
const Controller& controller)
74 controller.enableGesture(Gesture::TYPE_CIRCLE);
75 controller.enableGesture(Gesture::TYPE_KEY_TAP);
76 controller.enableGesture(Gesture::TYPE_SCREEN_TAP);
77 controller.enableGesture(Gesture::TYPE_SWIPE);
78 Leap::Controller::PolicyFlag flags = (mTopTracking) ? Controller::POLICY_OPTIMIZE_HMD : Controller::POLICY_DEFAULT;
79 controller.setPolicy(flags);
83 OBJpostEvent(LEAPMOTION_CONNECTED_CB, SCOL_PTR
this, 0);
88 void sLeapMotion::onDisconnect(
const Controller& controller)
93 OBJpostEvent(LEAPMOTION_DISCONNECTED_CB, SCOL_PTR
this, 0);
96 void sLeapMotion::onExit(
const Controller& controller)
101 void sLeapMotion::DetectHands(
const HandList hands)
104 for (
int i = 0; i < hands.count(); ++i)
107 const Hand hand = hands[i];
127 void sLeapMotion::DetectFingers(
const Hand hand)
130 const FingerList fingers = hand.fingers();
131 if (!fingers.isEmpty())
135 for (
int i = 0; i < fingers.count(); ++i)
137 avgPos += fingers[i].tipPosition();
139 avgPos /= (float)fingers.count();
143 void sLeapMotion::DetectTools(
const ToolList tools)
147 void sLeapMotion::DetectGestures(
const GestureList gestures)
149 int ltick = GetTickCount() - mLastGestureTick;
150 for (
int g = 0; g < gestures.count(); ++g)
152 Gesture gesture = gestures[g];
153 HandList hands = gesture.hands();
156 if (!gesture.isValid())
160 if (gesture.state() == Gesture::STATE_START || (gesture.type() == Gesture::TYPE_KEY_TAP) || (gesture.type() == Gesture::TYPE_SCREEN_TAP))
163 int pointableId = -1;
165 if (hands.isEmpty() || !hands[0].isValid())
168 if (std::find(mLastHandIds.begin(), mLastHandIds.end(), hands[0].id()) == mLastHandIds.end())
171 for (
unsigned int i = 0; i < mLastHandIds.size(); ++i)
173 if (mLastHandIds[i] == hands[0].
id())
177 if (hands[0].
id() >= (int)mLastPointableIds.size())
180 PointableList pointables = gesture.pointables();
182 for (
unsigned int j = 0; j < mLastPointableIds[hands[0].id()].size(); j++)
184 if (mLastPointableIds[hands[0].
id()][j] == pointables[0].id())
187 sgesture =
SGesture(gesture.id(), handIndex, pointableId);
189 if ((gesture.type() == Gesture::TYPE_CIRCLE) || (gesture.type() == Gesture::TYPE_SWIPE))
190 mGestureList.push_back(sgesture);
194 if (sgesture.id == -1)
196 for (
unsigned int i = 0; (i < mGestureList.size()) && (sgesture.id == -1); i++)
198 if (mGestureList[i].
id == gesture.id())
200 sgesture = mGestureList[i];
207 if (sgesture.id == -1)
211 if (gesture.state() == Gesture::STATE_STOP && ((gesture.type() == Gesture::TYPE_CIRCLE) || (gesture.type() == Gesture::TYPE_SWIPE)))
213 mGestureList.erase(mGestureList.begin() + sgesturepos);
217 if ((ltick < 16) && gesture.state() == Gesture::STATE_UPDATE)
220 switch (gesture.type())
222 case Gesture::TYPE_CIRCLE:
225 CircleGesture circle = gesture;
227 if (circle.pointable().direction().angleTo(circle.normal()) <= PI/4)
237 float sweptAngle = 0;
238 if (circle.state() != Gesture::STATE_START)
240 CircleGesture previousUpdate = CircleGesture(mController.frame(1).gesture(circle.id()));
241 sweptAngle = (circle.progress() - previousUpdate.progress()) * 2 * PI;
244 data->progress = circle.progress();
246 data->handId = sgesture.handId;
247 data->id = sgesture.pointableId;
249 data->fparam = circle.radius();
251 data->state = (int)gesture.state();
253 if (gesture.state() != Gesture::STATE_INVALID)
254 OBJpostEvent(LEAPMOTION_CIRCLE_CB, SCOL_PTR
this, (
int)data);
259 case Gesture::TYPE_SWIPE:
262 SwipeGesture swipe = gesture;
264 data->progress = ((float)swipe.duration() / 1000);
266 data->handId = sgesture.handId;
267 data->id = sgesture.pointableId;
269 data->vDir = swipe.direction();
270 data->fparam = swipe.speed();
271 data->svec = swipe.startPosition();
273 data->state = (int)gesture.state();
275 if (gesture.state() != Gesture::STATE_INVALID)
276 OBJpostEvent(LEAPMOTION_SWIPE_CB, SCOL_PTR
this, (
int)data);
281 case Gesture::TYPE_KEY_TAP:
284 KeyTapGesture tap = gesture;
286 data->progress = tap.progress();
287 data->vDir = tap.direction();
288 data->svec = tap.position();
290 data->handId = sgesture.handId;
291 data->id = sgesture.pointableId;
293 data->state = (int)gesture.state();
295 if (gesture.state() == Gesture::STATE_STOP)
296 OBJpostEvent(LEAPMOTION_KEYTAP_CB, SCOL_PTR
this, (
int)data);
301 case Gesture::TYPE_SCREEN_TAP:
303 ScreenTapGesture screentap = gesture;
306 data->progress = ((float)screentap.duration() / 1000);
307 data->vDir = screentap.direction();
308 data->svec = screentap.position();
310 data->handId = sgesture.handId;
311 data->id = sgesture.pointableId;
313 data->state = (int)gesture.state();
315 if (gesture.state() == Gesture::STATE_STOP)
316 OBJpostEvent(LEAPMOTION_SCREENTAP_CB, SCOL_PTR
this, (
int)data);
325 mLastGestureTick = GetTickCount();
328 void sLeapMotion::onFrame(
const Controller& controller)
330 Frame lframe(controller.frame());
331 DetectGestures(lframe.gestures());
335 boost::mutex::scoped_lock l(mMutex);
343 void sLeapMotion::onFocusGained(
const Controller& controller)
348 void sLeapMotion::onFocusLost(
const Controller& controller)
354 bool sLeapMotion::GetHand(
int id, Hand &hand)
358 boost::mutex::scoped_lock l(mMutex);
359 if (!mConnected || !mLastFrame.isValid() || mLastFrame.hands().count() < id)
362 hands = mLastFrame.hands();
365 if (
id >= (
int)mLastHandIds.size())
366 mLastHandIds.resize(
id+1, -1);
368 if (mLastHandIds[
id] != -1)
370 for (
int i = 0; i < hands.count(); ++i)
372 Hand fhand = hands[i];
374 if (mLastHandIds[
id] == fhand.id())
382 bool foundnew =
false;
383 for (
int i = 0; i < hands.count() && !foundnew; ++i)
386 if (hand.isValid() && (((
id == 0) && hand.isLeft()) || ((
id == 1) && (hand.isRight()))))
388 std::vector<int>::iterator vit = std::find(mLastHandIds.begin(), mLastHandIds.end(), hand.id());
389 if (vit != mLastHandIds.end())
390 mLastHandIds[vit-mLastHandIds.begin()] = -1;
394 else if (((
id > 1)) && hand.isValid() && std::find(mLastHandIds.begin(), mLastHandIds.end(), hand.id()) == mLastHandIds.end())
401 mLastHandIds[id] = hand.id();
405 if (hand.id() >= (int)mLastPointableIds.size())
407 std::vector<int> fids;
408 mLastPointableIds.resize(hand.id()+1, fids);
417 bool sLeapMotion::GetLeftHand(Hand &hand)
419 boost::mutex::scoped_lock l(mMutex);
420 if (!mConnected || !mLastFrame.isValid())
423 hand = mLastFrame.hands().leftmost();
430 bool sLeapMotion::GetRightHand(Hand &hand)
432 boost::mutex::scoped_lock l(mMutex);
433 if (!mConnected || !mLastFrame.isValid())
436 hand = mLastFrame.hands().rightmost();
443 bool sLeapMotion::GetHandPosition(
const Hand hand,
bool optim, Vector &vec)
446 vec = hand.stabilizedPalmPosition();
448 vec = hand.palmPosition();
452 vec -= hand.direction();
459 bool sLeapMotion::GetHandOrientation(
const Hand hand, Vector &vec)
461 const Vector normal = hand.palmNormal();
462 const Vector direction = hand.direction();
464 vec.x = direction.pitch();
465 vec.y = direction.yaw();
466 vec.z = normal.roll();
474 bool sLeapMotion::GetHandPalmNormal(
const Hand hand, Vector &vec)
476 vec = hand.palmNormal();
484 bool sLeapMotion::GetHandDirection(
const Hand hand, Vector &vec)
486 vec = hand.direction();
494 bool sLeapMotion::GetHandVelocity(
const Hand hand, Vector &vec)
496 vec = hand.palmVelocity();
504 std::vector<SCbData> sLeapMotion::GetHandFingers(
const Hand hand,
bool optim)
506 boost::mutex::scoped_lock l(mMutex);
507 std::vector<SCbData> lfingers;
511 if (hand.id() >= (int)mLastPointableIds.size())
513 std::vector<int> fids;
514 mLastPointableIds.resize(hand.id()+1, fids);
517 if (mLastPointableIds[hand.id()].empty())
519 std::vector<int> fids;
521 mLastPointableIds[hand.id()] = fids;
524 const FingerList fingers = hand.fingers();
526 for (
int i = 0; i < 5; ++i)
528 Finger finger = fingers[i];
531 mLastPointableIds[hand.id()][i] = finger.id();
533 Vector screenPos(0.0f, 0.0f, 0.0f);
535 if (finger.isValid())
537 ScreenList screens = mController.locatedScreens();
538 Screen screen = screens.closestScreenHit(finger);
539 if (screen.isValid() && finger.isExtended())
540 screenPos = screen.intersect(finger,
true);
542 data.svec = optim ? finger.stabilizedTipPosition() : finger.tipPosition();
543 data.evec = data.svec - finger.direction() * -0.25f;
544 data.screenPos = screenPos;
545 Vector dir = finger.direction();
546 data.pyr.x = dir.pitch();
547 data.pyr.y = dir.yaw();
548 data.pyr.z = dir.roll();
550 for (
unsigned int joint = 0; joint < 4; joint++)
551 data.subVecs.push_back(finger.jointPosition((Leap::Finger::Joint)joint));
553 data.id = finger.id();
563 bool sLeapMotion::GetTool(
int id, Tool &tool)
565 boost::mutex::scoped_lock l(mMutex);
566 if (!mConnected || !mLastFrame.isValid() || mLastFrame.tools().count() < id)
569 ToolList tools = mLastFrame.tools();
571 if (
id >= (
int)mLastToolsIds.size())
572 mLastToolsIds.resize(
id+1, -1);
574 if (mLastToolsIds[
id] != -1)
576 for (
int i = 0; i < tools.count(); ++i)
578 Tool ftool = tools[i];
580 if (mLastToolsIds[
id] == ftool.id())
588 bool foundnew =
false;
589 for (
int i = 0; i < tools.count() && !foundnew; ++i)
592 if (tool.isValid() && std::find(mLastToolsIds.begin(), mLastToolsIds.end(), tool.id()) == mLastToolsIds.end())
599 mLastToolsIds[id] = tool.id();
608 bool sLeapMotion::GetToolPosition(
const Tool tool,
bool optim, Vector &vec)
611 vec = tool.stabilizedTipPosition();
613 vec = tool.tipPosition();
621 bool sLeapMotion::GetToolOrientation(
const Tool tool, Vector &vec)
623 const Vector direction = tool.direction();
625 vec.x = direction.pitch();
626 vec.y = direction.yaw();
627 vec.z = direction.roll();
632 bool sLeapMotion::GetToolVelocity(
const Tool tool, Vector &vec)
634 vec = tool.tipVelocity();
642 void sLeapMotion::SetTopTrackingEnable(
bool state)
644 mTopTracking = state;
647 mController.setPolicy(Controller::POLICY_OPTIMIZE_HMD);
649 mController.clearPolicy(Controller::POLICY_OPTIMIZE_HMD);
652 bool sLeapMotion::GetTopTrackingEnable()