leapMotionFrame.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  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/leapMotionFrame.h"
  23. #include "platform/input/leapMotion/leapMotionUtil.h"
  24. #include "console/engineAPI.h"
  25. #include "math/mAngAxis.h"
  26. #include "math/mTransform.h"
  27. U32 LeapMotionFrame::smNextInternalFrameId = 0;
  28. IMPLEMENT_CONOBJECT(LeapMotionFrame);
  29. ImplementEnumType( LeapMotionFramePointableType,
  30. "Leap Motion pointable type.\n\n")
  31. { LeapMotionFrame::PT_UNKNOWN, "Unknown", "Unknown pointable type.\n" },
  32. { LeapMotionFrame::PT_FINGER, "Finger", "Finger pointable type.\n" },
  33. { LeapMotionFrame::PT_TOOL, "Tool", "Tool pointable type.\n" },
  34. EndImplementEnumType;
  35. LeapMotionFrame::LeapMotionFrame()
  36. {
  37. clear();
  38. }
  39. LeapMotionFrame::~LeapMotionFrame()
  40. {
  41. clear();
  42. }
  43. void LeapMotionFrame::initPersistFields()
  44. {
  45. Parent::initPersistFields();
  46. }
  47. bool LeapMotionFrame::onAdd()
  48. {
  49. if (!Parent::onAdd())
  50. return false;
  51. return true;
  52. }
  53. void LeapMotionFrame::onRemove()
  54. {
  55. Parent::onRemove();
  56. }
  57. void LeapMotionFrame::clear()
  58. {
  59. mFrameValid = false;
  60. mHandCount = 0;
  61. mHandValid.clear();
  62. mHandId.clear();
  63. mHandRawPos.clear();
  64. mHandPos.clear();
  65. mHandRot.clear();
  66. mHandRotQuat.clear();
  67. mHandRotAxis.clear();
  68. mHandPointablesCount.clear();
  69. mPointableCount = 0;
  70. mPointableValid.clear();
  71. mPointableId.clear();
  72. mPointableHandIndex.clear();
  73. mPointableType.clear();
  74. mPointableRawPos.clear();
  75. mPointablePos.clear();
  76. mPointableRot.clear();
  77. mPointableRotQuat.clear();
  78. mPointableLength.clear();
  79. mPointableWidth.clear();
  80. }
  81. void LeapMotionFrame::copyFromFrame(const Leap::Frame& frame, const F32& maxHandAxisRadius)
  82. {
  83. // This also resets all counters
  84. clear();
  85. // Retrieve frame information
  86. mFrameValid = frame.isValid();
  87. mFrameId = frame.id();
  88. mFrameTimeStamp = frame.timestamp();
  89. mFrameInternalId = smNextInternalFrameId;
  90. ++smNextInternalFrameId;
  91. mFrameSimTime = Sim::getCurrentTime();
  92. mFrameRealTime = Platform::getRealMilliseconds();
  93. if(!mFrameValid)
  94. {
  95. return;
  96. }
  97. // Retrieve hand information
  98. mHandCount = frame.hands().count();
  99. if(mHandCount > 0)
  100. {
  101. copyFromFrameHands(frame.hands(), maxHandAxisRadius);
  102. }
  103. // Retrieve pointable information
  104. mPointableCount = frame.pointables().count();
  105. if(mPointableCount > 0)
  106. {
  107. copyFromFramePointables(frame.pointables());
  108. }
  109. }
  110. void LeapMotionFrame::copyFromFrameHands(const Leap::HandList& hands, const F32& maxHandAxisRadius)
  111. {
  112. // Set up Vectors
  113. mHandValid.increment(mHandCount);
  114. mHandId.increment(mHandCount);
  115. mHandRawPos.increment(mHandCount);
  116. mHandPos.increment(mHandCount);
  117. mHandRot.increment(mHandCount);
  118. mHandRotQuat.increment(mHandCount);
  119. mHandRotAxis.increment(mHandCount);
  120. mHandPointablesCount.increment(mHandCount);
  121. // Copy data
  122. for(U32 i=0; i<mHandCount; ++i)
  123. {
  124. const Leap::Hand& hand = hands[i];
  125. mHandValid[i] = hand.isValid();
  126. mHandId[i] = hand.id();
  127. // Position
  128. LeapMotionUtil::convertPosition(hand.palmPosition(), mHandRawPos[i]);
  129. mHandPos[i].x = (S32)mFloor(mHandRawPos[i].x);
  130. mHandPos[i].y = (S32)mFloor(mHandRawPos[i].y);
  131. mHandPos[i].z = (S32)mFloor(mHandRawPos[i].z);
  132. // Rotation
  133. LeapMotionUtil::convertHandRotation(hand, mHandRot[i]);
  134. mHandRotQuat[i].set(mHandRot[i]);
  135. // Thumb stick axis rotation
  136. LeapMotionUtil::calculateHandAxisRotation(mHandRot[i], maxHandAxisRadius, mHandRotAxis[i]);
  137. // Pointables
  138. mHandPointablesCount[i] = hand.pointables().count();
  139. }
  140. }
  141. void LeapMotionFrame::copyFromFramePointables(const Leap::PointableList& pointables)
  142. {
  143. // Set up Vectors
  144. mPointableValid.increment(mPointableCount);
  145. mPointableId.increment(mPointableCount);
  146. mPointableHandIndex.increment(mPointableCount);
  147. mPointableType.increment(mPointableCount);
  148. mPointableRawPos.increment(mPointableCount);
  149. mPointablePos.increment(mPointableCount);
  150. mPointableRot.increment(mPointableCount);
  151. mPointableRotQuat.increment(mPointableCount);
  152. mPointableLength.increment(mPointableCount);
  153. mPointableWidth.increment(mPointableCount);
  154. // Copy data
  155. for(U32 i=0; i<mPointableCount; ++i)
  156. {
  157. const Leap::Pointable& pointable = pointables[i];
  158. mPointableValid[i] = pointable.isValid();
  159. mPointableId[i] = pointable.id();
  160. mPointableLength[i] = pointable.length();
  161. mPointableWidth[i] = pointable.width();
  162. mPointableType[i] = PT_UNKNOWN;
  163. if(pointable.isFinger())
  164. {
  165. mPointableType[i] = PT_FINGER;
  166. }
  167. else if(pointable.isTool())
  168. {
  169. mPointableType[i] = PT_TOOL;
  170. }
  171. // Which hand, if any
  172. const Leap::Hand& hand = pointable.hand();
  173. if(hand.isValid())
  174. {
  175. bool found = false;
  176. S32 handId = hand.id();
  177. for(U32 j=0; j<mHandCount; ++j)
  178. {
  179. if(mHandId[j] == handId)
  180. {
  181. mPointableHandIndex[i] = j;
  182. found = true;
  183. break;
  184. }
  185. }
  186. if(!found)
  187. {
  188. mPointableHandIndex[i] = -1;
  189. }
  190. }
  191. else
  192. {
  193. mPointableHandIndex[i] = -1;
  194. }
  195. // Position
  196. LeapMotionUtil::convertPosition(pointable.tipPosition(), mPointableRawPos[i]);
  197. mPointablePos[i].x = (S32)mFloor(mPointableRawPos[i].x);
  198. mPointablePos[i].y = (S32)mFloor(mPointableRawPos[i].y);
  199. mPointablePos[i].z = (S32)mFloor(mPointableRawPos[i].z);
  200. // Rotation
  201. LeapMotionUtil::convertPointableRotation(pointable, mPointableRot[i]);
  202. mPointableRotQuat[i].set(mPointableRot[i]);
  203. }
  204. }
  205. //-----------------------------------------------------------------------------
  206. DefineEngineMethod( LeapMotionFrame, isFrameValid, bool, ( ),,
  207. "@brief Checks if this frame is valid.\n\n"
  208. "@return True if the frame is valid.\n\n")
  209. {
  210. return object->isFrameValid();
  211. }
  212. DefineEngineMethod( LeapMotionFrame, getFrameInternalId, S32, ( ),,
  213. "@brief Provides the internal ID for this frame.\n\n"
  214. "@return Internal ID of this frame.\n\n")
  215. {
  216. return object->getFrameInternalId();
  217. }
  218. DefineEngineMethod( LeapMotionFrame, getFrameSimTime, S32, ( ),,
  219. "@brief Get the sim time that this frame was generated.\n\n"
  220. "@return Sim time of this frame in milliseconds.\n\n")
  221. {
  222. return object->getFrameSimTime();
  223. }
  224. DefineEngineMethod( LeapMotionFrame, getFrameRealTime, S32, ( ),,
  225. "@brief Get the real time that this frame was generated.\n\n"
  226. "@return Real time of this frame in milliseconds.\n\n")
  227. {
  228. return object->getFrameRealTime();
  229. }
  230. DefineEngineMethod( LeapMotionFrame, getHandCount, S32, ( ),,
  231. "@brief Get the number of hands defined in this frame.\n\n"
  232. "@return The number of defined hands.\n\n")
  233. {
  234. return object->getHandCount();
  235. }
  236. DefineEngineMethod( LeapMotionFrame, getHandValid, bool, ( S32 index ),,
  237. "@brief Check if the requested hand is valid.\n\n"
  238. "@param index The hand index to check.\n"
  239. "@return True if the hand is valid.\n\n")
  240. {
  241. return object->getHandValid(index);
  242. }
  243. DefineEngineMethod( LeapMotionFrame, getHandId, S32, ( S32 index ),,
  244. "@brief Get the ID of the requested hand.\n\n"
  245. "@param index The hand index to check.\n"
  246. "@return ID of the requested hand.\n\n")
  247. {
  248. return object->getHandId(index);
  249. }
  250. DefineEngineMethod( LeapMotionFrame, getHandRawPos, Point3F, ( S32 index ),,
  251. "@brief Get the raw position of the requested hand.\n\n"
  252. "The raw position is the hand's floating point position converted to "
  253. "Torque 3D coordinates (in millimeters).\n"
  254. "@param index The hand index to check.\n"
  255. "@return Raw position of the requested hand.\n\n")
  256. {
  257. return object->getHandRawPos(index);
  258. }
  259. DefineEngineMethod( LeapMotionFrame, getHandPos, Point3I, ( S32 index ),,
  260. "@brief Get the position of the requested hand.\n\n"
  261. "The position is the hand's integer position converted to "
  262. "Torque 3D coordinates (in millimeters).\n"
  263. "@param index The hand index to check.\n"
  264. "@return Integer position of the requested hand (in millimeters).\n\n")
  265. {
  266. return object->getHandPos(index);
  267. }
  268. DefineEngineMethod( LeapMotionFrame, getHandRot, AngAxisF, ( S32 index ),,
  269. "@brief Get the rotation of the requested hand.\n\n"
  270. "The Leap Motion hand rotation as converted into the Torque 3D"
  271. "coordinate system.\n"
  272. "@param index The hand index to check.\n"
  273. "@return Rotation of the requested hand.\n\n")
  274. {
  275. AngAxisF aa(object->getHandRot(index));
  276. return aa;
  277. }
  278. DefineEngineMethod( LeapMotionFrame, getHandRawTransform, TransformF, ( S32 index ),,
  279. "@brief Get the raw transform of the requested hand.\n\n"
  280. "@param index The hand index to check.\n"
  281. "@return The raw position and rotation of the requested hand (in Torque 3D coordinates).\n\n")
  282. {
  283. const Point3F& pos = object->getHandRawPos(index);
  284. const QuatF& qa = object->getHandRotQuat(index);
  285. AngAxisF aa(qa);
  286. aa.axis.normalize();
  287. TransformF trans(pos, aa);
  288. return trans;
  289. }
  290. DefineEngineMethod( LeapMotionFrame, getHandTransform, TransformF, ( S32 index ),,
  291. "@brief Get the transform of the requested hand.\n\n"
  292. "@param index The hand index to check.\n"
  293. "@return The position and rotation of the requested hand (in Torque 3D coordinates).\n\n")
  294. {
  295. const Point3I& pos = object->getHandPos(index);
  296. const QuatF& qa = object->getHandRotQuat(index);
  297. AngAxisF aa(qa);
  298. aa.axis.normalize();
  299. TransformF trans;
  300. trans.mPosition = Point3F(pos.x, pos.y, pos.z);
  301. trans.mOrientation = aa;
  302. return trans;
  303. }
  304. DefineEngineMethod( LeapMotionFrame, getHandRotAxis, Point2F, ( S32 index ),,
  305. "@brief Get the axis rotation of the requested hand.\n\n"
  306. "This is the axis rotation of the hand as if the hand were a gamepad thumb stick. "
  307. "Imagine a stick coming out the top of the hand and tilting the hand front, back, "
  308. "left and right controls that stick. The values returned along the x and y stick "
  309. "axis are normalized from -1.0 to 1.0 with the maximum hand tilt angle for these "
  310. "values as defined by $LeapMotion::MaximumHandAxisAngle.\n"
  311. "@param index The hand index to check.\n"
  312. "@return Axis rotation of the requested hand.\n\n"
  313. "@see LeapMotion::MaximumHandAxisAngle\n")
  314. {
  315. return object->getHandRotAxis(index);
  316. }
  317. DefineEngineMethod( LeapMotionFrame, getHandPointablesCount, S32, ( S32 index ),,
  318. "@brief Get the number of pointables associated with this hand.\n\n"
  319. "@param index The hand index to check.\n"
  320. "@return Number of pointables that belong with this hand.\n\n")
  321. {
  322. return object->getHandPointablesCount(index);
  323. }
  324. DefineEngineMethod( LeapMotionFrame, getPointablesCount, S32, ( ),,
  325. "@brief Get the number of pointables defined in this frame.\n\n"
  326. "@return The number of defined pointables.\n\n")
  327. {
  328. return object->getPointablesCount();
  329. }
  330. DefineEngineMethod( LeapMotionFrame, getPointableValid, bool, ( S32 index ),,
  331. "@brief Check if the requested pointable is valid.\n\n"
  332. "@param index The pointable index to check.\n"
  333. "@return True if the pointable is valid.\n\n")
  334. {
  335. return object->getPointableValid(index);
  336. }
  337. DefineEngineMethod( LeapMotionFrame, getPointableId, S32, ( S32 index ),,
  338. "@brief Get the ID of the requested pointable.\n\n"
  339. "@param index The pointable index to check.\n"
  340. "@return ID of the requested pointable.\n\n")
  341. {
  342. return object->getPointableId(index);
  343. }
  344. DefineEngineMethod( LeapMotionFrame, getPointableHandIndex, S32, ( S32 index ),,
  345. "@brief Get the index of the hand that this pointable belongs to, if any.\n\n"
  346. "@param index The pointable index to check.\n"
  347. "@return Index of the hand this pointable belongs to, or -1 if there is no associated hand.\n\n")
  348. {
  349. return object->getPointableHandIndex(index);
  350. }
  351. DefineEngineMethod( LeapMotionFrame, getPointableType, LeapMotionFramePointableType, ( S32 index ),,
  352. "@brief Get the type of the requested pointable.\n\n"
  353. "@param index The pointable index to check.\n"
  354. "@return Type of the requested pointable.\n\n")
  355. {
  356. return object->getPointableType(index);
  357. }
  358. DefineEngineMethod( LeapMotionFrame, getPointableRawPos, Point3F, ( S32 index ),,
  359. "@brief Get the raw position of the requested pointable.\n\n"
  360. "The raw position is the pointable's floating point position converted to "
  361. "Torque 3D coordinates (in millimeters).\n"
  362. "@param index The pointable index to check.\n"
  363. "@return Raw position of the requested pointable.\n\n")
  364. {
  365. return object->getPointableRawPos(index);
  366. }
  367. DefineEngineMethod( LeapMotionFrame, getPointablePos, Point3I, ( S32 index ),,
  368. "@brief Get the position of the requested pointable.\n\n"
  369. "The position is the pointable's integer position converted to "
  370. "Torque 3D coordinates (in millimeters).\n"
  371. "@param index The pointable index to check.\n"
  372. "@return Integer position of the requested pointable (in millimeters).\n\n")
  373. {
  374. return object->getPointablePos(index);
  375. }
  376. DefineEngineMethod( LeapMotionFrame, getPointableRot, AngAxisF, ( S32 index ),,
  377. "@brief Get the rotation of the requested pointable.\n\n"
  378. "The Leap Motion pointable rotation as converted into the Torque 3D"
  379. "coordinate system.\n"
  380. "@param index The pointable index to check.\n"
  381. "@return Rotation of the requested pointable.\n\n")
  382. {
  383. AngAxisF aa(object->getPointableRot(index));
  384. return aa;
  385. }
  386. DefineEngineMethod( LeapMotionFrame, getPointableRawTransform, TransformF, ( S32 index ),,
  387. "@brief Get the raw transform of the requested pointable.\n\n"
  388. "@param index The pointable index to check.\n"
  389. "@return The raw position and rotation of the requested pointable (in Torque 3D coordinates).\n\n")
  390. {
  391. const Point3F& pos = object->getPointableRawPos(index);
  392. const QuatF& qa = object->getPointableRotQuat(index);
  393. AngAxisF aa(qa);
  394. aa.axis.normalize();
  395. TransformF trans(pos, aa);
  396. return trans;
  397. }
  398. DefineEngineMethod( LeapMotionFrame, getPointableTransform, TransformF, ( S32 index ),,
  399. "@brief Get the transform of the requested pointable.\n\n"
  400. "@param index The pointable index to check.\n"
  401. "@return The position and rotation of the requested pointable (in Torque 3D coordinates).\n\n")
  402. {
  403. const Point3I& pos = object->getPointablePos(index);
  404. const QuatF& qa = object->getPointableRotQuat(index);
  405. AngAxisF aa(qa);
  406. aa.axis.normalize();
  407. TransformF trans;
  408. trans.mPosition = Point3F(pos.x, pos.y, pos.z);
  409. trans.mOrientation = aa;
  410. return trans;
  411. }
  412. DefineEngineMethod( LeapMotionFrame, getPointableLength, F32, ( S32 index ),,
  413. "@brief Get the length of the requested pointable.\n\n"
  414. "@param index The pointable index to check.\n"
  415. "@return Length of the requested pointable (in millimeters).\n\n")
  416. {
  417. return object->getPointableLength(index);
  418. }
  419. DefineEngineMethod( LeapMotionFrame, getPointableWidth, F32, ( S32 index ),,
  420. "@brief Get the width of the requested pointable.\n\n"
  421. "@param index The pointable index to check.\n"
  422. "@return Width of the requested pointable (in millimeters).\n\n")
  423. {
  424. return object->getPointableWidth(index);
  425. }