Vuo  2.0.0
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  default:
78  case Leap::Pointable::ZONE_NONE:
79  return VuoLeapTouchZone_None;
80  }
81 }
82 
87 static VuoPoint3d VuoLeap_vuoPointFromLeapPosition(Leap::Vector position, Leap::InteractionBox ibox)
88 {
89  return VuoLeap_vuoPointFromLeapVector(position - ibox.center(), ibox);
90 }
91 
95 static VuoPoint3d VuoPoint3dWithLeapVector(Leap::Vector vector)
96 {
97  return VuoPoint3d_make(vector.x, vector.y, vector.z);
98 }
99 
103 class VuoLeapListener : public Leap::Listener {
104 public:
105 
110  (
111  void (*receivedFrame)(VuoLeapFrame frame)
112  )
113  {
114  this->receivedFrame = receivedFrame;
115  }
116 
117 private:
118  void (*receivedFrame)(VuoLeapFrame frame);
119 
120  virtual void onInit(const Leap::Controller&) {}
121  virtual void onDisconnect(const Leap::Controller&) {}
122  virtual void onExit(const Leap::Controller&) {}
123  virtual void onFocusGained(const Leap::Controller&) {}
124  virtual void onFocusLost(const Leap::Controller&) {}
125 
126  virtual void onConnect(const Leap::Controller &controller)
127  {
128  controller.enableGesture(Leap::Gesture::TYPE_CIRCLE);
129  controller.enableGesture(Leap::Gesture::TYPE_KEY_TAP);
130  controller.enableGesture(Leap::Gesture::TYPE_SCREEN_TAP);
131  controller.enableGesture(Leap::Gesture::TYPE_SWIPE);
132 
133  controller.setPolicyFlags(Leap::Controller::POLICY_BACKGROUND_FRAMES);
134  }
135 
136  virtual void onFrame(const Leap::Controller &controller)
137  {
138  const Leap::Frame frame = controller.frame();
139 
140  // used to normalize leap coordinates (the boolean parameter says 'no clamping' which allows for coordinates > 1)
141  // https://developer.leapmotion.com/documentation/Languages/Java/API/classcom_1_1leapmotion_1_1leap_1_1_interaction_box.html#details
142  Leap::InteractionBox interactionBox = frame.interactionBox();
143 
144  // https://developer.leapmotion.com/documentation/Languages/C++/Guides/Leap_Frames.html
145  if(!frame.isValid())
146  return;
147 
149 
150  Leap::HandList allHands = frame.hands();
151  Leap::PointableList allPointables = frame.pointables();
152 
153  for (Leap::PointableList::const_iterator pointable = allPointables.begin(); pointable != allPointables.end(); ++pointable)
154  {
155  VuoPoint3d position = VuoLeap_vuoPointFromLeapPosition((*pointable).tipPosition(), interactionBox);
156  VuoPoint3d stabilized = VuoLeap_vuoPointFromLeapPosition((*pointable).stabilizedTipPosition(), interactionBox);
157  VuoPoint3d tipPosition = VuoPoint3d_make(stabilized.x, stabilized.y, position.z);
158 
160  (*pointable).id(),
161  (*pointable).isFinger() ? VuoLeapPointableType_Finger : VuoLeapPointableType_Tool,
162  VuoLeap_vuoDistanceFromLeapMillimeters((*pointable).length(), interactionBox),
163  VuoLeap_vuoDistanceFromLeapMillimeters((*pointable).width(), interactionBox),
164  VuoPoint3dWithLeapVector( (*pointable).direction() ), // leave as is
165  tipPosition,
166  VuoLeap_vuoPointFromLeapVector((*pointable).tipVelocity(), interactionBox),
167  (*pointable).timeVisible(),
168  (*pointable).touchDistance(),
169  VuoLeap_vuoLeapTouchZoneFromLeapTouchZone((*pointable).touchZone()),
170  (*pointable).isExtended()
171  ));
172  }
173 
175 
176  for(Leap::HandList::const_iterator hand = allHands.begin(); hand != allHands.end(); ++hand)
177  {
179  Leap::FingerList fingers = (*hand).fingers();
180 
181  for (Leap::FingerList::const_iterator pointable = fingers.begin(); pointable != fingers.end(); ++pointable)
182  {
183  VuoPoint3d position = VuoLeap_vuoPointFromLeapPosition((*pointable).tipPosition(), interactionBox);
184  VuoPoint3d stabilized = VuoLeap_vuoPointFromLeapPosition((*pointable).stabilizedTipPosition(), interactionBox);
185  VuoPoint3d tipPosition = VuoPoint3d_make(stabilized.x, stabilized.y, position.z);
186 
188  (*pointable).id(),
189  VuoLeapPointableType_Finger,
190  VuoLeap_vuoDistanceFromLeapMillimeters((*pointable).length(), interactionBox),
191  VuoLeap_vuoDistanceFromLeapMillimeters((*pointable).width(), interactionBox),
192  VuoPoint3dWithLeapVector( (*pointable).direction() ),
193  tipPosition,
194  VuoLeap_vuoPointFromLeapVector((*pointable).tipVelocity(), interactionBox),
195  (*pointable).timeVisible(),
196  (*pointable).touchDistance(),
197  VuoLeap_vuoLeapTouchZoneFromLeapTouchZone((*pointable).touchZone()),
198  (*pointable).isExtended()
199  ));
200  }
201 
202  Leap::Matrix basis = (*hand).basis();
203  if ((*hand).isLeft())
204  {
205  // "the basis matrix will be left-handed for left hands"
206  // https://developer.leapmotion.com/documentation/skeletal/cpp/api/Leap.Hand.html#cppclass_leap_1_1_hand_1a4ff50b291a30106f8306ba26d55ada76
207  basis.xBasis *= -1;
208  }
209 
210  Leap::Matrix basisInverse = basis.rigidInverse();
211  VuoPoint3d basisPoint3d[3] = {
212  VuoPoint3dWithLeapVector(basisInverse.xBasis),
213  VuoPoint3dWithLeapVector(basisInverse.yBasis),
214  VuoPoint3dWithLeapVector(basisInverse.zBasis)
215  };
216 
217  VuoPoint3d position = VuoLeap_vuoPointFromLeapPosition((*hand).palmPosition(), interactionBox);
218  VuoPoint3d stabilized = VuoLeap_vuoPointFromLeapPosition((*hand).stabilizedPalmPosition(), interactionBox);
219  VuoPoint3d palmPosition = VuoPoint3d_make(stabilized.x, stabilized.y, position.z);
220 
222  (*hand).id(),
223  VuoTransform_quaternionFromBasis(basisPoint3d),
224  palmPosition,
225  VuoLeap_vuoPointFromLeapVector((*hand).palmVelocity(), interactionBox),
226  VuoLeap_vuoDistanceFromLeapMillimeters((*hand).sphereRadius(), interactionBox),
227  VuoLeap_vuoPointFromLeapPosition((*hand).sphereCenter(), interactionBox),
228  VuoLeap_vuoDistanceFromLeapMillimeters((*hand).palmWidth(), interactionBox),
229  VuoLeap_vuoPointFromLeapPosition( (*hand).wristPosition(), interactionBox ),
230  (*hand).pinchStrength(),
231  (*hand).grabStrength(),
232  (*hand).timeVisible(),
233  (*hand).isLeft(),
234  (*hand).confidence(),
235  handPointables));
236  }
237 
238  receivedFrame(VuoLeapFrame_make(frame.id(), hands, pointables));
239  }
240 };
241 
245 typedef struct _VuoLeapInternal
246 {
247  Leap::Controller *controller;
248  VuoLeapListener *listener;
249 } *VuoLeapInternal;
250 
259 (
260  VuoOutputTrigger(receivedFrame, VuoLeapFrame)
261 )
262 {
263  VuoLeapInternal leap = (VuoLeapInternal)malloc(sizeof(struct _VuoLeapInternal));
264 
265  leap->controller = new Leap::Controller;
266  leap->listener = new VuoLeapListener(receivedFrame);
267  leap->controller->addListener(*leap->listener);
268 
269  return (VuoLeap)leap;
270 }
271 
276 {
278 
279  leap->controller->removeListener(*leap->listener);
280 
281  delete leap->listener;
282  delete leap->controller;
283  delete leap;
284 }