Torque3D Documentation / _generateds / leapMotionData.cpp

leapMotionData.cpp

Engine/source/platform/input/leapMotion/leapMotionData.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/input/leapMotion/leapMotionData.h"
 25#include "platform/input/leapMotion/leapMotionUtil.h"
 26
 27LeapMotionDeviceData::LeapMotionDeviceData()
 28{
 29   reset();
 30}
 31
 32void LeapMotionDeviceData::reset()
 33{
 34   mDataSet = false;
 35
 36   mIsValid = false;
 37
 38   mHasTrackingData = false;
 39
 40   for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
 41   {
 42      mHandValid[i] = false;
 43
 44      for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
 45      {
 46         mPointableValid[i][j] = false;
 47      }
 48   }
 49}
 50
 51void LeapMotionDeviceData::setData(const Leap::Frame& frame, LeapMotionDeviceData* prevData, bool keepHandIndexPersistent, bool keepPointableIndexPersistent, const F32& maxHandAxisRadius)
 52{
 53   mIsValid = frame.isValid();
 54   if(!mIsValid)
 55      return;
 56
 57   // Determine if there is any valid tracking data
 58   mHasTrackingData = frame.hands().count() > 0 || frame.pointables().count() > 0;
 59
 60   const Leap::HandList hands = frame.hands();
 61
 62   // Check if the hand index needs to persist between frames, but only if the
 63   // previous data is valid
 64   if(keepHandIndexPersistent && prevData && prevData->mDataSet && prevData->mIsValid)
 65   {
 66      processPersistentHands(frame.hands(), keepPointableIndexPersistent, prevData);
 67   }
 68   else
 69   {
 70      processHands(frame.hands());
 71   }
 72
 73   // Single hand rotation as axis
 74   if(mHandValid[0])
 75   {
 76      Point2F axis;
 77      LeapMotionUtil::calculateHandAxisRotation(mHandRot[0], maxHandAxisRadius, axis);
 78
 79      mHandRotAxis[0] = axis.x;
 80      mHandRotAxis[1] = axis.y;
 81   }
 82   else
 83   {
 84      // The first hand is not valid so we reset the axis rotation to none
 85      mHandRotAxis[0] = 0.0f;
 86      mHandRotAxis[1] = 0.0f;
 87   }
 88
 89   // Store the current sequence number
 90   mSequenceNum = frame.id();
 91
 92   mDataSet = true;
 93}
 94
 95void LeapMotionDeviceData::processPersistentHands(const Leap::HandList& hands, bool keepPointableIndexPersistent, LeapMotionDeviceData* prevData)
 96{
 97   S32 numHands = hands.count();
 98
 99   static S32 handDataIndex[LeapMotionConstants::MaxHands];
100   static bool handIndexUsed[LeapMotionConstants::MaxHands];
101   static Vector<S32> frameHandFound;
102
103   // Clear out our lookup arrays
104   for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
105   {
106      handDataIndex[i] = -1;
107      handIndexUsed[i] = false;
108   }
109   frameHandFound.setSize(numHands);
110   for(U32 i=0; i<numHands; ++i)
111   {
112      frameHandFound[i] = -1;
113   }
114
115   // Check if any hands this frame were picked up last frame
116   for(U32 i=0; i<numHands; ++i)
117   {
118      const Leap::Hand& hand = hands[i];
119      for(U32 j=0; j<LeapMotionConstants::MaxHands; ++j)
120      {
121         if(prevData && prevData->mHandValid[j] && hand.id() == prevData->mHandID[j])
122         {
123            handDataIndex[j] = i;
124            frameHandFound[i] = j;
125         }
126      }
127   }
128
129   // Process all hands that were present in the last frame
130   for(U32 i=0; i<numHands; ++i)
131   {
132      if(frameHandFound[i] != -1)
133      {
134         processHand(hands[i], frameHandFound[i], keepPointableIndexPersistent, prevData);
135         handIndexUsed[frameHandFound[i]] = true;
136      }
137   }
138
139   // Process all hands that were not present in the last frame
140   for(U32 i=0; i<numHands; ++i)
141   {
142      if(frameHandFound[i] != -1)
143         continue;
144
145      // Find the first hand data that has not yet been used
146      for(U32 j=0; j<LeapMotionConstants::MaxHands; ++j)
147      {
148         if(!handIndexUsed[j])
149         {
150            // Process this hand
151            processHand(hands[i], j, keepPointableIndexPersistent, prevData);
152            handIndexUsed[j] = true;
153            break;
154         }
155      }
156   }
157
158   // Finally, mark all hand data that has not been processed this frame as invalid
159   for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
160   {
161      if(!handIndexUsed[i])
162      {
163         mHandValid[i] = false;
164      }
165   }
166}
167
168void LeapMotionDeviceData::processHands(const Leap::HandList& hands)
169{
170   S32 numHands = hands.count();
171
172   // Process all valid hands
173   S32 handsToProcess = getMin(numHands, LeapMotionConstants::MaxHands);
174   for(U32 i=0; i<handsToProcess; ++i)
175   {
176      processHand(hands[i], i, false, NULL);
177   }
178
179   // Take care of any hands that do not exist this frame
180   for(U32 i=handsToProcess; i<LeapMotionConstants::MaxHands; ++i)
181   {
182      mHandValid[i] = false;
183   }
184}
185
186void LeapMotionDeviceData::processHand(const Leap::Hand& hand, U32 handIndex, bool keepPointableIndexPersistent, LeapMotionDeviceData* prevData)
187{
188   mHandValid[handIndex] = true;
189
190   mHandID[handIndex] = hand.id();
191
192   // Set the hand position
193   LeapMotionUtil::convertPosition(hand.palmPosition(), mHandRawPos[handIndex][0], mHandRawPos[handIndex][1], mHandRawPos[handIndex][2]);
194   mHandPos[handIndex][0] = (S32)mFloor(mHandRawPos[handIndex][0]);
195   mHandPos[handIndex][1] = (S32)mFloor(mHandRawPos[handIndex][1]);
196   mHandPos[handIndex][2] = (S32)mFloor(mHandRawPos[handIndex][2]);
197
198   mHandPosPoint[handIndex].set(mHandPos[handIndex][0], mHandPos[handIndex][1], mHandPos[handIndex][2]);
199
200   // Set the hand rotation
201   LeapMotionUtil::convertHandRotation(hand, mHandRot[handIndex]);
202   mHandRotQuat[handIndex].set(mHandRot[handIndex]);
203
204   // Process the pointables associated with this hand
205   if(keepPointableIndexPersistent)
206   {
207      processPersistentHandPointables(hand.pointables(), handIndex, prevData);
208   }
209   else
210   {
211      processHandPointables(hand.pointables(), handIndex);
212   }
213}
214
215void LeapMotionDeviceData::processPersistentHandPointables(const Leap::PointableList& pointables, U32 handIndex, LeapMotionDeviceData* prevData)
216{
217   S32 numPointables = pointables.count();
218
219   static S32 pointableDataIndex[LeapMotionConstants::MaxPointablesPerHand];
220   static bool pointableIndexUsed[LeapMotionConstants::MaxPointablesPerHand];
221   static Vector<S32> framePointableFound;
222
223   // Clear out our lookup arrays
224   for(U32 i=0; i<LeapMotionConstants::MaxPointablesPerHand; ++i)
225   {
226      pointableDataIndex[i] = -1;
227      pointableIndexUsed[i] = false;
228   }
229   framePointableFound.setSize(numPointables);
230   for(U32 i=0; i<numPointables; ++i)
231   {
232      framePointableFound[i] = -1;
233   }
234
235   // Check if any pointables for this hand during this frame were picked
236   // up last frame
237   for(U32 i=0; i<numPointables; ++i)
238   {
239      const Leap::Pointable& pointable = pointables[i];
240      for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
241      {
242         if(prevData && prevData->mPointableValid[handIndex][j] && pointable.id() == prevData->mPointableID[handIndex][j])
243         {
244            pointableDataIndex[j] = i;
245            framePointableFound[i] = j;
246         }
247      }
248   }
249
250   // Process all hand pointables that were present in the last frame
251   for(U32 i=0; i<numPointables; ++i)
252   {
253      if(framePointableFound[i] != -1)
254      {
255         processHandPointable(pointables[i], handIndex, framePointableFound[i]);
256         pointableIndexUsed[framePointableFound[i]] = true;
257      }
258   }
259
260   // Process all hand pointables that were not present in the last frame
261   for(U32 i=0; i<numPointables; ++i)
262   {
263      if(framePointableFound[i] != -1)
264         continue;
265
266      // Find the first hand pointable data that has not yet been used
267      for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
268      {
269         if(!pointableIndexUsed[j])
270         {
271            // Process the pointable
272            processHandPointable(pointables[i], handIndex, j);
273            pointableIndexUsed[j] = true;
274            break;
275         }
276      }
277   }
278
279   // Finally, mark all hand pointable data that has not been process this frame as invalid
280   for(U32 i=0; i<LeapMotionConstants::MaxPointablesPerHand; ++i)
281   {
282      if(!pointableIndexUsed[i])
283      {
284         mPointableValid[handIndex][i] = false;
285      }
286   }
287}
288
289void LeapMotionDeviceData::processHandPointables(const Leap::PointableList& pointables, U32 handIndex)
290{
291   // Process all pointables attached to the hand
292   S32 numPointables = pointables.count();
293   S32 pointablesToProcess = getMin(numPointables, LeapMotionConstants::MaxPointablesPerHand);
294   for(U32 i=0; i<pointablesToProcess; ++i)
295   {
296      processHandPointable(pointables[i], handIndex, i);
297   }
298
299   // Take care of any pointables that do not exist this frame
300   for(U32 i=pointablesToProcess; i<LeapMotionConstants::MaxPointablesPerHand; ++i)
301   {
302      mPointableValid[handIndex][i] = false;
303   }
304}
305
306void LeapMotionDeviceData::processHandPointable(const Leap::Pointable& pointable, U32 handIndex, U32 handPointableIndex)
307{
308   mPointableValid[handIndex][handPointableIndex] = true;
309
310   mPointableID[handIndex][handPointableIndex] = pointable.id();
311   mPointableLength[handIndex][handPointableIndex] = pointable.length();
312   mPointableWidth[handIndex][handPointableIndex] = pointable.width();
313
314   // Set the pointable position
315   LeapMotionUtil::convertPosition(pointable.tipPosition(), mPointableRawPos[handIndex][handPointableIndex][0], mPointableRawPos[handIndex][handPointableIndex][1], mPointableRawPos[handIndex][handPointableIndex][2]);
316   mPointablePos[handIndex][handPointableIndex][0] = (S32)mFloor(mPointableRawPos[handIndex][handPointableIndex][0]);
317   mPointablePos[handIndex][handPointableIndex][1] = (S32)mFloor(mPointableRawPos[handIndex][handPointableIndex][1]);
318   mPointablePos[handIndex][handPointableIndex][2] = (S32)mFloor(mPointableRawPos[handIndex][handPointableIndex][2]);
319
320   mPointablePosPoint[handIndex][handPointableIndex].set(mPointablePos[handIndex][handPointableIndex][0], mPointablePos[handIndex][handPointableIndex][1], mPointablePos[handIndex][handPointableIndex][2]);
321
322   // Set the pointable rotation
323   LeapMotionUtil::convertPointableRotation(pointable, mPointableRot[handIndex][handPointableIndex]);
324   mPointableRotQuat[handIndex][handPointableIndex].set(mPointableRot[handIndex][handPointableIndex]);
325}
326
327U32 LeapMotionDeviceData::compare(LeapMotionDeviceData* other)
328{
329   S32 result = DIFF_NONE;
330
331   // Check hand rotation as axis
332   if(mHandRotAxis[0] != other->mHandRotAxis[0] || !mDataSet)
333   {
334      result |= DIFF_HANDROTAXISX;
335   }
336   if(mHandRotAxis[1] != other->mHandRotAxis[1] || !mDataSet)
337   {
338      result |= DIFF_HANDROTAXISY;
339   }
340
341   return result;
342}
343
344U32 LeapMotionDeviceData::compareMeta(LeapMotionDeviceData* other)
345{
346   S32 result = DIFF_NONE;
347
348   if(mHasTrackingData != other->mHasTrackingData || !mDataSet)
349   {
350      result |= METADIFF_FRAME_VALID_DATA;
351   }
352
353   return result;
354}
355