leapMotionData.cpp 11 KB

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