ARHandManager.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. using EZXR.Glass.Core;
  2. using EZXR.Glass.Simulator.Hand;
  3. using EZXR.Glass.SixDof;
  4. using System.Collections;
  5. using UnityEngine;
  6. namespace EZXR.Glass.Inputs
  7. {
  8. [ScriptExecutionOrder(-49)]
  9. public class ARHandManager : MonoBehaviour
  10. {
  11. #region singleton
  12. private static ARHandManager instance;
  13. public static ARHandManager Instance
  14. {
  15. get
  16. {
  17. return instance;
  18. }
  19. }
  20. #endregion
  21. public enum HandTrackingMode
  22. {
  23. HighPrecision,//GPU
  24. HighEfficiency,//DSP
  25. }
  26. HandTrackingMode handTrackingMode = HandTrackingMode.HighPrecision;
  27. public bool enableHandSimulatorInEditor = true;
  28. ///// <summary>
  29. ///// 是否显示球棍手
  30. ///// </summary>
  31. //public bool ShowHandJoint = true;
  32. /// <summary>
  33. /// 头部坐标系所在的物体
  34. /// </summary>
  35. public static Transform head;
  36. /// <summary>
  37. /// 实例化出来作为所有手的根节点
  38. /// </summary>
  39. GameObject prefab_handRoot;
  40. Transform handRoot;
  41. /// <summary>
  42. /// 记录了左手的所有信息,包括当前有没有捏合,有没有握持物体等等
  43. /// </summary>
  44. public static HandInfo leftHand;
  45. /// <summary>
  46. /// 记录了右手的所有信息,包括当前有没有捏合,有没有握持物体等等
  47. /// </summary>
  48. public static HandInfo rightHand;
  49. /// <summary>
  50. /// 由外部逻辑控制手的射线的方向
  51. /// </summary>
  52. /// <param name="handInfo"></param>
  53. /// <param name="rayDir"></param>
  54. /// <returns></returns>
  55. public delegate bool Delegate_SetRayDataByExternal(HandInfo handInfo, ref Vector3 value);
  56. public static Delegate_SetRayDataByExternal SetRayDirByExternal;
  57. public static Delegate_SetRayDataByExternal SetRayStartPointByExternal;
  58. private void Awake()
  59. {
  60. instance = this;
  61. gameObject.AddComponent<NativeSwapManager>();
  62. if (Application.isEditor)
  63. {
  64. if (enableHandSimulatorInEditor)
  65. {
  66. gameObject.AddComponent<HandSimulator>();
  67. }
  68. }
  69. StartCoroutine(enableHandDetecting());
  70. //注册回调,以得到HandTrackingData的数据更新
  71. NativeSwapManager.OnHandTrackingDataUpdated += OnHandTrackingDataUpdated;
  72. //if (ShowHandJoint)
  73. //{
  74. // gameObject.AddComponent<HandsVisualization>();
  75. //}
  76. head = HMDPoseTracker.Instance.Head;
  77. Transform handRoot_Left = transform.Find("Left");
  78. Transform handRoot_Right = transform.Find("Right");
  79. #region 兼容旧版
  80. if (handRoot_Left == null || handRoot_Right == null)
  81. {
  82. handRoot = transform.Find("HandRoot");
  83. handRoot_Left = handRoot.Find("HandRoot_Left");
  84. handRoot_Right = handRoot.Find("HandRoot_Right");
  85. }
  86. #endregion
  87. //初始化HandInfo,以指定HandInfo是左手还是右手
  88. leftHand = handRoot_Left.GetComponent<HandInfo>();
  89. leftHand.Init(HandType.Left);
  90. rightHand = handRoot_Right.GetComponent<HandInfo>();
  91. rightHand.Init(HandType.Right);
  92. //拇指和食指之间用来触发近距离捏合的区域
  93. GameObject prefab_TriggerBetweenDaddyAndMommyFinger = ResourcesManager.Load<GameObject>("Triggers/TriggerBetweenDaddyAndMommyFinger");
  94. TriggerForPinch interactWithFingerTip_Left = Instantiate(prefab_TriggerBetweenDaddyAndMommyFinger, leftHand.root).GetComponent<TriggerForPinch>();
  95. interactWithFingerTip_Left.SetUp(leftHand.root);
  96. TriggerForPinch interactWithFingerTip_Right = Instantiate(prefab_TriggerBetweenDaddyAndMommyFinger, rightHand.root).GetComponent<TriggerForPinch>();
  97. interactWithFingerTip_Right.SetUp(rightHand.root);
  98. //手部的预触发区,用于切换近距离和远距离交互
  99. GameObject prefab_TriggerForFarNearSwitch = ResourcesManager.Load<GameObject>("Triggers/TriggerForFarNearSwitch");
  100. TriggerForFarNearSwitch triggerForFarNearSwitch_Left = Instantiate(prefab_TriggerForFarNearSwitch, leftHand.root).GetComponent<TriggerForFarNearSwitch>();
  101. triggerForFarNearSwitch_Left.SetUp(leftHand.root);
  102. TriggerForFarNearSwitch triggerForFarNearSwitch_Right = Instantiate(prefab_TriggerForFarNearSwitch, rightHand.root).GetComponent<TriggerForFarNearSwitch>();
  103. triggerForFarNearSwitch_Right.SetUp(rightHand.root);
  104. }
  105. private void OnApplicationPause(bool pause)
  106. {
  107. if (!pause)
  108. {
  109. if (!Application.isEditor)
  110. {
  111. StartCoroutine(enableHandDetecting());
  112. }
  113. }
  114. }
  115. private void OnDestroy()
  116. {
  117. disableHandDetecting();
  118. }
  119. public void changeHandRunMode(HandTrackingMode mode)
  120. {
  121. handTrackingMode = mode;
  122. StartCoroutine(enableHandDetecting());
  123. }
  124. // 控制器统一管理时,激活手势功能
  125. public void SetActive(bool value)
  126. {
  127. //StartCoroutine(enableHandDetecting());
  128. //transform.GetComponent<NativeSwapManager>().enabled = true;
  129. //for (int i = 0; i < transform.childCount; i++)
  130. //{
  131. // transform.GetChild(i).gameObject.SetActive(true);
  132. //}
  133. gameObject.SetActive(value);
  134. }
  135. private IEnumerator resetHandRunMode(HandTrackingMode mode)
  136. {
  137. yield return new WaitUntil(() => SessionManager.Instance != null && SessionManager.Instance.IsInited);
  138. NativeSwapManager.setHandRunMode((int)handTrackingMode);
  139. }
  140. private IEnumerator enableHandDetecting()
  141. {
  142. yield return new WaitUntil(() => SessionManager.Instance != null && SessionManager.Instance.IsInited);
  143. if (handTrackingMode == HandTrackingMode.HighEfficiency)
  144. {
  145. SessionManager.Instance.ARInitConfig.HandsFindingMode = HandsFindingMode.Enable_HighEfficiency;
  146. }
  147. else if (handTrackingMode == HandTrackingMode.HighPrecision)
  148. {
  149. SessionManager.Instance.ARInitConfig.HandsFindingMode = HandsFindingMode.Enable_HighPrecision;
  150. }
  151. SessionManager.Instance.ResumeSession();
  152. }
  153. private void disableHandDetecting()
  154. {
  155. SessionManager.Instance.ARInitConfig.HandsFindingMode = HandsFindingMode.Disable;
  156. SessionManager.Instance.ResumeSession();
  157. }
  158. public void UpdateHandTrackingDataManually(NativeSwapManager.HandTrackingData[] handTrackingData)
  159. {
  160. OnHandTrackingDataUpdated(handTrackingData);
  161. }
  162. private void OnHandTrackingDataUpdated(NativeSwapManager.HandTrackingData[] handTrackingData)
  163. {
  164. NativeSwapManager.HandTrackingData handTrackingData_Left, handTrackingData_Right;
  165. handTrackingData_Left = handTrackingData[0];
  166. handTrackingData_Right = handTrackingData[1];
  167. //开启或关闭虚拟手物体(直接关闭手GameObject的原因是当手不存在的时候不应该执行任何逻辑)
  168. leftHand.root.gameObject.SetActive(handTrackingData_Left.isTracked);
  169. rightHand.root.gameObject.SetActive(handTrackingData_Right.isTracked);
  170. //刷新手的数据
  171. leftHand.UpdateHandInfoData(handTrackingData_Left);
  172. rightHand.UpdateHandInfoData(handTrackingData_Right);
  173. }
  174. public HandInfo GetHand(HandType handedness)
  175. {
  176. if (handedness == HandType.Left)
  177. {
  178. return leftHand;
  179. }
  180. else
  181. {
  182. return rightHand;
  183. }
  184. }
  185. }
  186. }