NREmulatorHandStatesService.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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.Generic;
  12. using UnityEngine;
  13. public class NREmulatorHandStatesService : IHandStatesService
  14. {
  15. public bool IsRunning { protected set; get; }
  16. private Dictionary<KeyCode, HandState> m_TestHandStatesDict;
  17. private HandState m_TargetHandState;
  18. private HandState m_DefaultLostHandState;
  19. private HandState m_DefaultTrackedHandState;
  20. private Pose m_HandRootPose = Pose.identity;
  21. private float m_CurrentHandRootFowardOffset;
  22. private float m_TargetHandRootFowardOffset;
  23. private Vector2 m_HandRootMovedAngles;
  24. private bool m_Inited;
  25. private const string MOUSE_AXIS_MOUSE_X = "Mouse X";
  26. private const string MOUSE_AXIS_MOUSE_Y = "Mouse Y";
  27. private const string MOUSE_AXIS_MOUSE_SCROLLWHEEL = "Mouse ScrollWheel";
  28. private const float MAX_MOVED_ANGLE_X = 90f;
  29. private const float MAX_MOVED_ANGLE_Y = 90f;
  30. private const float MOUSE_MOVE_SENSITIVITY = 500f;
  31. private const float MOUSE_SCROLL_SENSITIVITY = 45f;
  32. private const float HAND_ROOT_LERP_SPEED = 12f;
  33. private static Vector3 HAND_ROOT_DEFAULT_LOCAL_POSITION = new Vector3(0.06f, -0.1f, 0.2f);
  34. public virtual bool RunService()
  35. {
  36. Init();
  37. IsRunning = true;
  38. return true;
  39. }
  40. public virtual bool StopService()
  41. {
  42. Init();
  43. IsRunning = false;
  44. return true;
  45. }
  46. public virtual void UpdateStates(HandState[] handStates)
  47. {
  48. if (!IsRunning)
  49. return;
  50. handStates[1].Reset();
  51. var currentHandState = handStates[0];
  52. bool isTracked = (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift));
  53. if (isTracked)
  54. {
  55. m_TargetHandState = m_DefaultTrackedHandState;
  56. foreach (KeyValuePair<KeyCode, HandState> kvPair in m_TestHandStatesDict)
  57. {
  58. if (Input.GetKey(kvPair.Key))
  59. {
  60. m_TargetHandState = kvPair.Value;
  61. break;
  62. }
  63. }
  64. }
  65. else
  66. {
  67. m_TargetHandState = m_DefaultLostHandState;
  68. }
  69. ApplyToTargetHandState(currentHandState, m_TargetHandState);
  70. }
  71. public virtual void PauseService()
  72. {
  73. IsRunning = false;
  74. }
  75. public virtual void ResumeService()
  76. {
  77. IsRunning = true;
  78. }
  79. public virtual void DestroyService()
  80. {
  81. IsRunning = false;
  82. }
  83. protected virtual void Init()
  84. {
  85. if (m_Inited)
  86. return;
  87. m_DefaultLostHandState = CreateTestHandState_Lost_None(HandEnum.RightHand);
  88. m_DefaultTrackedHandState = CreateTestHandState_Found_OpenHand(HandEnum.RightHand);
  89. m_TestHandStatesDict = new Dictionary<KeyCode, HandState>()
  90. {
  91. {KeyCode.Mouse0, CreateTestHandState_Found_Pinch(HandEnum.RightHand)},
  92. {KeyCode.Mouse1, CreateTestHandState_Found_Point(HandEnum.RightHand)},
  93. {KeyCode.Mouse2, CreateTestHandState_Found_SystemGesture(HandEnum.RightHand)}
  94. };
  95. m_Inited = true;
  96. }
  97. protected void SetHandJointPose(HandState handState, HandJointID jointID, Pose pose)
  98. {
  99. if (handState.jointsPoseDict.ContainsKey(jointID))
  100. {
  101. handState.jointsPoseDict[jointID] = pose;
  102. }
  103. else
  104. {
  105. handState.jointsPoseDict.Add(jointID, pose);
  106. }
  107. }
  108. private void UpdateHandRootPose(HandState handState)
  109. {
  110. var cameraCenter = NRInput.CameraCenter;
  111. if (handState.isTracked)
  112. {
  113. m_TargetHandRootFowardOffset += Input.GetAxis(MOUSE_AXIS_MOUSE_SCROLLWHEEL) * MOUSE_SCROLL_SENSITIVITY * Time.deltaTime;
  114. m_TargetHandRootFowardOffset = Mathf.Clamp(m_TargetHandRootFowardOffset, -0.15f, 0.3f);
  115. m_CurrentHandRootFowardOffset = Mathf.Lerp(m_CurrentHandRootFowardOffset, m_TargetHandRootFowardOffset, HAND_ROOT_LERP_SPEED * Time.deltaTime);
  116. m_HandRootPose.position = cameraCenter.TransformPoint(HAND_ROOT_DEFAULT_LOCAL_POSITION) + m_HandRootPose.forward * m_CurrentHandRootFowardOffset;
  117. float delta_angle_x = Input.GetAxis(MOUSE_AXIS_MOUSE_X) * MOUSE_MOVE_SENSITIVITY * Time.deltaTime;
  118. float delat_angle_y = Input.GetAxis(MOUSE_AXIS_MOUSE_Y) * MOUSE_MOVE_SENSITIVITY * Time.deltaTime;
  119. m_HandRootMovedAngles += new Vector2(delta_angle_x, -delat_angle_y);
  120. m_HandRootMovedAngles.x = Mathf.Clamp(m_HandRootMovedAngles.x, -MAX_MOVED_ANGLE_X, MAX_MOVED_ANGLE_X);
  121. m_HandRootMovedAngles.y = Mathf.Clamp(m_HandRootMovedAngles.y, -MAX_MOVED_ANGLE_Y, MAX_MOVED_ANGLE_Y);
  122. var localRotation = Quaternion.Euler(Vector3.up * m_HandRootMovedAngles.x + Vector3.right * m_HandRootMovedAngles.y);
  123. m_HandRootPose.rotation = cameraCenter.rotation * localRotation;
  124. }
  125. else
  126. {
  127. m_CurrentHandRootFowardOffset = m_TargetHandRootFowardOffset = 0f;
  128. m_HandRootPose.position = cameraCenter.TransformPoint(HAND_ROOT_DEFAULT_LOCAL_POSITION);
  129. m_HandRootPose.rotation = cameraCenter.rotation;
  130. m_HandRootMovedAngles = Vector2.zero;
  131. }
  132. }
  133. private void ApplyToTargetHandState(HandState currentHandState, HandState targetHandState)
  134. {
  135. UpdateHandRootPose(targetHandState);
  136. currentHandState.isTracked = targetHandState.isTracked;
  137. currentHandState.currentGesture = targetHandState.currentGesture;
  138. Quaternion handRootQuation = m_HandRootPose.rotation;
  139. foreach (var jointPoseItem in targetHandState.jointsPoseDict)
  140. {
  141. var relativePosition = jointPoseItem.Value.position - HAND_ROOT_DEFAULT_LOCAL_POSITION;
  142. var relativePoseToRoot = new Pose(relativePosition, jointPoseItem.Value.rotation);
  143. var jointPosition = m_HandRootPose.position + handRootQuation * relativePoseToRoot.position;
  144. var jointRotation = handRootQuation * relativePoseToRoot.rotation;
  145. SetHandJointPose(currentHandState, jointPoseItem.Key, new Pose(jointPosition, jointRotation));
  146. }
  147. }
  148. #region Methods To Create Preset HandStates
  149. private HandState CreateTestHandState_Lost_None(HandEnum handEnum)
  150. {
  151. var handState = new HandState(handEnum);
  152. handState.isTracked = false;
  153. handState.currentGesture = HandGesture.None;
  154. return handState;
  155. }
  156. private HandState CreateTestHandState_Found_OpenHand(HandEnum handEnum)
  157. {
  158. var handState = new HandState(handEnum);
  159. handState.isTracked = true;
  160. handState.currentGesture = HandGesture.OpenHand;
  161. HandJointPoseDataUtility.JsonToDict(HandJointsArrayData.HandJointsArrayData_Right_OpenHand_Json, handState.jointsPoseDict);
  162. return handState;
  163. }
  164. private HandState CreateTestHandState_Found_Pinch(HandEnum handEnum)
  165. {
  166. var handState = new HandState(handEnum);
  167. handState.isTracked = true;
  168. handState.currentGesture = HandGesture.Grab;
  169. HandJointPoseDataUtility.JsonToDict(HandJointsArrayData.HandJointsArrayData_Right_Grab_Json, handState.jointsPoseDict);
  170. return handState;
  171. }
  172. private HandState CreateTestHandState_Found_Point(HandEnum handEnum)
  173. {
  174. var handState = new HandState(handEnum);
  175. handState.isTracked = true;
  176. handState.currentGesture = HandGesture.Point;
  177. HandJointPoseDataUtility.JsonToDict(HandJointsArrayData.HandJointsArrayData_Right_Point_Json, handState.jointsPoseDict);
  178. return handState;
  179. }
  180. private HandState CreateTestHandState_Found_SystemGesture(HandEnum handEnum)
  181. {
  182. var handState = new HandState(handEnum);
  183. handState.isTracked = true;
  184. handState.currentGesture = HandGesture.None;
  185. HandJointPoseDataUtility.JsonToDict(HandJointsArrayData.HandJointsArrayData_Right_SystemGesture_Json, handState.jointsPoseDict);
  186. return handState;
  187. }
  188. #endregion
  189. }
  190. }