Vuo  2.1.1
VuoLeap.cc
Go to the documentation of this file.
1 
10 #include "VuoLeap.h"
11 #include "VuoLeapHand.h"
12 #include "VuoLeapPointable.h"
13 #include "VuoList_VuoLeapHand.h"
15 
16 #pragma clang diagnostic push
17 #pragma clang diagnostic ignored "-Wdocumentation"
18 #include <Leap.h>
19 #pragma clang diagnostic pop
20 
21 #include "module.h"
22 
23 extern "C"
24 {
25 #ifdef VUO_COMPILER
27  "title" : "VuoLeap",
28  "dependencies" : [
29  "VuoLeapFrame",
30  "VuoLeapHand",
31  "VuoLeapPointable",
32  "VuoList_VuoLeapHand",
33  "VuoList_VuoLeapPointable",
34  "VuoTransform",
35  "Leap"
36  ]
37  });
38 #endif
39 }
40 
41 
46 static double VuoLeap_vuoDistanceFromLeapMillimeters(double millimeters, Leap::InteractionBox ibox)
47 {
48  return (millimeters / ibox.width()) * 2.;
49 }
50 
55 static VuoPoint3d VuoLeap_vuoPointFromLeapVector(Leap::Vector vector, Leap::InteractionBox ibox)
56 {
57  return VuoPoint3d_make(
61  );
62 }
63 
68 {
69  switch(zone)
70  {
71  case Leap::Pointable::ZONE_TOUCHING:
72  return VuoLeapTouchZone_Touching;
73 
74  case Leap::Pointable::ZONE_HOVERING:
75  return VuoLeapTouchZone_Hovering;
76 
77  case Leap::Pointable::ZONE_NONE:
78  return VuoLeapTouchZone_None;
79  }
80 }
81 
86 static VuoPoint3d VuoLeap_vuoPointFromLeapPosition(Leap::Vector position, Leap::InteractionBox ibox)
87 {
88  return VuoLeap_vuoPointFromLeapVector(position - ibox.center(), ibox);
89 }
90 
94 static VuoPoint3d VuoPoint3dWithLeapVector(Leap::Vector vector)
95 {
96  return VuoPoint3d_make(vector.x, vector.y, vector.z);
97 }
98 
102 class VuoLeapListener : public Leap::Listener {
103 public:
104 
109  (
110  void (*receivedFrame)(VuoLeapFrame frame)
111  )
112  {
113  this->receivedFrame = receivedFrame;
114  }
115 
116 private:
117  void (*receivedFrame)(VuoLeapFrame frame);
118 
119  virtual void onInit(const Leap::Controller&) {}
120  virtual void onDisconnect(const Leap::Controller&) {}
121  virtual void onExit(const Leap::Controller&) {}
122  virtual void onFocusGained(const Leap::Controller&) {}
123  virtual void onFocusLost(const Leap::Controller&) {}
124 
125  virtual void onConnect(const Leap::Controller &controller)
126  {
127  controller.enableGesture(Leap::Gesture::TYPE_CIRCLE);
128  controller.enableGesture(Leap::Gesture::TYPE_KEY_TAP);
129  controller.enableGesture(Leap::Gesture::TYPE_SCREEN_TAP);
130  controller.enableGesture(Leap::Gesture::TYPE_SWIPE);
131 
132  controller.setPolicyFlags(Leap::Controller::POLICY_BACKGROUND_FRAMES);
133  }
134 
135  virtual void onFrame(const Leap::Controller &controller)
136  {
137  const Leap::Frame frame = controller.frame();
138 
139  // used to normalize leap coordinates (the boolean parameter says 'no clamping' which allows for coordinates > 1)
140  // https://developer.leapmotion.com/documentation/Languages/Java/API/classcom_1_1leapmotion_1_1leap_1_1_interaction_box.html#details
141  Leap::InteractionBox interactionBox = frame.interactionBox();
142 
143  // https://developer.leapmotion.com/documentation/Languages/C++/Guides/Leap_Frames.html
144  if(!frame.isValid())
145  return;
146 
148 
149  Leap::HandList allHands = frame.hands();
150  Leap::PointableList allPointables = frame.pointables();
151 
152  for (Leap::PointableList::const_iterator pointable = allPointables.begin(); pointable != allPointables.end(); ++pointable)
153  {
154  VuoPoint3d position = VuoLeap_vuoPointFromLeapPosition((*pointable).tipPosition(), interactionBox);
155  VuoPoint3d stabilized = VuoLeap_vuoPointFromLeapPosition((*pointable).stabilizedTipPosition(), interactionBox);
156  VuoPoint3d tipPosition = VuoPoint3d_make(stabilized.x, stabilized.y, position.z);
157 
159  (*pointable).id(),
160  (*pointable).isFinger() ? VuoLeapPointableType_Finger : VuoLeapPointableType_Tool,
161  VuoLeap_vuoDistanceFromLeapMillimeters((*pointable).length(), interactionBox),
162  VuoLeap_vuoDistanceFromLeapMillimeters((*pointable).width(), interactionBox),
163  VuoPoint3dWithLeapVector( (*pointable).direction() ), // leave as is
164  tipPosition,
165  VuoLeap_vuoPointFromLeapVector((*pointable).tipVelocity(), interactionBox),
166  (*pointable).timeVisible(),
167  (*pointable).touchDistance(),
168  VuoLeap_vuoLeapTouchZoneFromLeapTouchZone((*pointable).touchZone()),
169  (*pointable).isExtended()
170  ));
171  }
172 
174 
175  for(Leap::HandList::const_iterator hand = allHands.begin(); hand != allHands.end(); ++hand)
176  {
178  Leap::FingerList fingers = (*hand).fingers();
179 
180  for (Leap::FingerList::const_iterator pointable = fingers.begin(); pointable != fingers.end(); ++pointable)
181  {
182  VuoPoint3d position = VuoLeap_vuoPointFromLeapPosition((*pointable).tipPosition(), interactionBox);
183  VuoPoint3d stabilized = VuoLeap_vuoPointFromLeapPosition((*pointable).stabilizedTipPosition(), interactionBox);
184  VuoPoint3d tipPosition = VuoPoint3d_make(stabilized.x, stabilized.y, position.z);
185 
187  (*pointable).id(),
188  VuoLeapPointableType_Finger,
189  VuoLeap_vuoDistanceFromLeapMillimeters((*pointable).length(), interactionBox),
190  VuoLeap_vuoDistanceFromLeapMillimeters((*pointable).width(), interactionBox),
191  VuoPoint3dWithLeapVector( (*pointable).direction() ),
192  tipPosition,
193  VuoLeap_vuoPointFromLeapVector((*pointable).tipVelocity(), interactionBox),
194  (*pointable).timeVisible(),
195  (*pointable).touchDistance(),
196  VuoLeap_vuoLeapTouchZoneFromLeapTouchZone((*pointable).touchZone()),
197  (*pointable).isExtended()
198  ));
199  }
200 
201  Leap::Matrix basis = (*hand).basis();
202  if ((*hand).isLeft())
203  {
204  // "the basis matrix will be left-handed for left hands"
205  // https://developer.leapmotion.com/documentation/skeletal/cpp/api/Leap.Hand.html#cppclass_leap_1_1_hand_1a4ff50b291a30106f8306ba26d55ada76
206  basis.xBasis *= -1;
207  }
208 
209  Leap::Matrix basisInverse = basis.rigidInverse();
210  VuoPoint3d basisPoint3d[3] = {
211  VuoPoint3dWithLeapVector(basisInverse.xBasis),
212  VuoPoint3dWithLeapVector(basisInverse.yBasis),
213  VuoPoint3dWithLeapVector(basisInverse.zBasis)
214  };
215 
216  VuoPoint3d position = VuoLeap_vuoPointFromLeapPosition((*hand).palmPosition(), interactionBox);
217  VuoPoint3d stabilized = VuoLeap_vuoPointFromLeapPosition((*hand).stabilizedPalmPosition(), interactionBox);
218  VuoPoint3d palmPosition = VuoPoint3d_make(stabilized.x, stabilized.y, position.z);
219 
221  (*hand).id(),
222  VuoTransform_quaternionFromBasis(basisPoint3d),
223  palmPosition,
224  VuoLeap_vuoPointFromLeapVector((*hand).palmVelocity(), interactionBox),
225  VuoLeap_vuoDistanceFromLeapMillimeters((*hand).sphereRadius(), interactionBox),
226  VuoLeap_vuoPointFromLeapPosition((*hand).sphereCenter(), interactionBox),
227  VuoLeap_vuoDistanceFromLeapMillimeters((*hand).palmWidth(), interactionBox),
228  VuoLeap_vuoPointFromLeapPosition( (*hand).wristPosition(), interactionBox ),
229  (*hand).pinchStrength(),
230  (*hand).grabStrength(),
231  (*hand).timeVisible(),
232  (*hand).isLeft(),
233  (*hand).confidence(),
234  handPointables));
235  }
236 
237  receivedFrame(VuoLeapFrame_make(frame.id(), hands, pointables));
238  }
239 };
240 
244 typedef struct _VuoLeapInternal
245 {
246  Leap::Controller *controller;
247  VuoLeapListener *listener;
249 
258 (
259  VuoOutputTrigger(receivedFrame, VuoLeapFrame)
260 )
261 {
262  VuoLeapInternal leap = (VuoLeapInternal)malloc(sizeof(struct _VuoLeapInternal));
263 
264  leap->controller = new Leap::Controller;
265  leap->listener = new VuoLeapListener(receivedFrame);
266  leap->controller->addListener(*leap->listener);
267 
268  return (VuoLeap)leap;
269 }
270 
275 {
277 
278  leap->controller->removeListener(*leap->listener);
279 
280  delete leap->listener;
281  delete leap->controller;
282  delete leap;
283 }