HandStateUtility.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /****************************************************************************
  2. * Copyright 2019 Nreal Techonology Limited. All rights reserved.
  3. *
  4. * This file is part of NRSDK.
  5. *
  6. * https://www.nreal.ai/
  7. *
  8. *****************************************************************************/
  9. namespace NRKernal
  10. {
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using UnityEngine;
  14. public class HandStateUtility
  15. {
  16. public static float GetIndexFingerCurlStrength(HandState handState)
  17. {
  18. Pose wristPose;
  19. Pose fingerTipPose;
  20. Pose fingerProximal;
  21. if (handState.jointsPoseDict.TryGetValue(HandJointID.Wrist, out wristPose) &&
  22. handState.jointsPoseDict.TryGetValue(HandJointID.IndexTip, out fingerTipPose) &&
  23. handState.jointsPoseDict.TryGetValue(HandJointID.IndexProximal, out fingerProximal))
  24. {
  25. return CalculateCurl(wristPose.position, fingerProximal.position, fingerTipPose.position);
  26. }
  27. return 0f;
  28. }
  29. public static float GetMiddleFingerCurlStrength(HandState handState)
  30. {
  31. Pose wristPose;
  32. Pose fingerTipPose;
  33. Pose fingerProximal;
  34. if (handState.jointsPoseDict.TryGetValue(HandJointID.Wrist, out wristPose) &&
  35. handState.jointsPoseDict.TryGetValue(HandJointID.MiddleTip, out fingerTipPose) &&
  36. handState.jointsPoseDict.TryGetValue(HandJointID.MiddleProximal, out fingerProximal))
  37. {
  38. return CalculateCurl(wristPose.position, fingerProximal.position, fingerTipPose.position);
  39. }
  40. return 0f;
  41. }
  42. public static float GetRingFingerCurlStrength(HandState handState)
  43. {
  44. Pose wristPose;
  45. Pose fingerTipPose;
  46. Pose fingerProximal;
  47. if (handState.jointsPoseDict.TryGetValue(HandJointID.Wrist, out wristPose) &&
  48. handState.jointsPoseDict.TryGetValue(HandJointID.RingTip, out fingerTipPose) &&
  49. handState.jointsPoseDict.TryGetValue(HandJointID.RingProximal, out fingerProximal))
  50. {
  51. return CalculateCurl(wristPose.position, fingerProximal.position, fingerTipPose.position);
  52. }
  53. return 0f;
  54. }
  55. public static float GetPinkyFingerCurlStrength(HandState handState)
  56. {
  57. Pose wristPose;
  58. Pose fingerTipPose;
  59. Pose fingerProximal;
  60. if (handState.jointsPoseDict.TryGetValue(HandJointID.Wrist, out wristPose) &&
  61. handState.jointsPoseDict.TryGetValue(HandJointID.PinkyTip, out fingerTipPose) &&
  62. handState.jointsPoseDict.TryGetValue(HandJointID.PinkyProximal, out fingerProximal))
  63. {
  64. return CalculateCurl(wristPose.position, fingerProximal.position, fingerTipPose.position);
  65. }
  66. return 0f;
  67. }
  68. /// <summary>
  69. /// Curl calculation of a finger based on the angle made by vectors wristToFingerKuncle and fingerKuckleToFingerTip.
  70. /// </summary>
  71. private static float CalculateCurl(Vector3 wristPosition, Vector3 fingerKnucklePosition, Vector3 fingerTipJoint)
  72. {
  73. var palmToFinger = (fingerKnucklePosition - wristPosition).normalized;
  74. var fingerKnuckleToTip = (fingerKnucklePosition - fingerTipJoint).normalized;
  75. var curl = Vector3.Dot(fingerKnuckleToTip, palmToFinger);
  76. // Redefining the range from [-1,1] to [0,1]
  77. curl = (curl + 1) / 2.0f;
  78. return curl;
  79. }
  80. /*
  81. * System gesture should satisfy these conditions below:
  82. * 1,Palm face to camera
  83. * 2,Keep thumb finger curl to palm, other fingers straight
  84. * 3,If left hand, fingers should point to right. If right hand, to left.
  85. */
  86. public static bool IsSystemGesture(HandState handState)
  87. {
  88. if ((!handState.isTracked) || handState.isPinching || handState.pointerPoseValid)
  89. {
  90. return false;
  91. }
  92. //palm should face to camera
  93. var palmPose = handState.GetJointPose(HandJointID.Palm);
  94. Vector3 palmBackward = -palmPose.forward;
  95. Transform cameraTransform = NRInput.CameraCenter;
  96. bool isPalmFacingCamera = Vector3.Angle(palmBackward, cameraTransform.forward) < 35f;
  97. if (!isPalmFacingCamera)
  98. {
  99. return false;
  100. }
  101. //fingers should point to right or left
  102. var fingersShouldPointTo = cameraTransform.right * (handState.handEnum == HandEnum.RightHand ? -1f : 1f);
  103. var fingersNowPointTo = palmPose.up;
  104. var isPointToCorrect = Vector3.Angle(fingersShouldPointTo, fingersNowPointTo) < 35f;
  105. if (!isPointToCorrect)
  106. {
  107. return false;
  108. }
  109. //thumb should curl to palm
  110. var thumbToward = handState.GetJointPose(HandJointID.ThumbDistal).up;
  111. var indexToward = handState.GetJointPose(HandJointID.IndexProximal).up;
  112. var planeNormal = Vector3.Cross(thumbToward, indexToward);
  113. var signByHand = handState.handEnum == HandEnum.RightHand ? 1f : -1f;
  114. if (Vector3.Dot(planeNormal, palmPose.forward * signByHand) < 0f)
  115. {
  116. return false;
  117. }
  118. //other fingers should be straight
  119. float indexCurlStr = GetIndexFingerCurlStrength(handState);
  120. float middleCurlStr = GetMiddleFingerCurlStrength(handState);
  121. float ringCurlStr = GetRingFingerCurlStrength(handState);
  122. if (indexCurlStr < 0.2f
  123. && middleCurlStr < 0.2f
  124. && ringCurlStr < 0.2f)
  125. {
  126. return true;
  127. }
  128. return false;
  129. }
  130. }
  131. }