PXR_HandSubsystem.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*******************************************************************************
  2. Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
  3. NOTICE:All information contained herein is, and remains the property of
  4. PICO Technology Co., Ltd. The intellectual and technical concepts
  5. contained herein are proprietary to PICO Technology Co., Ltd. and may be
  6. covered by patents, patents in process, and are protected by trade secret or
  7. copyright law. Dissemination of this information or reproduction of this
  8. material is strictly forbidden unless prior written permission is obtained from
  9. PICO Technology Co., Ltd.
  10. *******************************************************************************/
  11. using Unity.Collections;
  12. using UnityEngine;
  13. using UnityEngine.Scripting;
  14. using System.Runtime.CompilerServices;
  15. #if XR_HANDS
  16. using UnityEngine.XR.Hands;
  17. using UnityEngine.XR.Hands.ProviderImplementation;
  18. namespace Unity.XR.PXR
  19. {
  20. [Preserve]
  21. /// <summary>
  22. /// Implement Unity XRHandSubSystem
  23. /// Reference: https://docs.unity3d.com/Packages/com.unity.xr.hands@1.1/manual/implement-a-provider.html
  24. /// </summary>
  25. public class PXR_HandSubSystem : XRHandSubsystem
  26. {
  27. XRHandProviderUtility.SubsystemUpdater m_Updater;
  28. // This method registers the subsystem descriptor with the SubsystemManager
  29. [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
  30. static void RegisterDescriptor()
  31. {
  32. var handsSubsystemCinfo = new XRHandSubsystemDescriptor.Cinfo
  33. {
  34. id = "PICO Hands",
  35. providerType = typeof(PXRHandSubsystemProvider),
  36. subsystemTypeOverride = typeof(PXR_HandSubSystem)
  37. };
  38. XRHandSubsystemDescriptor.Register(handsSubsystemCinfo);
  39. }
  40. protected override void OnCreate()
  41. {
  42. base.OnCreate();
  43. m_Updater = new XRHandProviderUtility.SubsystemUpdater(this);
  44. }
  45. protected override void OnStart()
  46. {
  47. Debug.Log("PXR_HandSubSystem Start");
  48. m_Updater.Start();
  49. base.OnStart();
  50. }
  51. protected override void OnStop()
  52. {
  53. m_Updater.Stop();
  54. base.OnStop();
  55. }
  56. protected override void OnDestroy()
  57. {
  58. m_Updater.Destroy();
  59. m_Updater = null;
  60. base.OnDestroy();
  61. }
  62. class PXRHandSubsystemProvider : XRHandSubsystemProvider
  63. {
  64. HandJointLocations jointLocations = new HandJointLocations();
  65. readonly HandLocationStatus AllStatus = HandLocationStatus.PositionTracked | HandLocationStatus.PositionValid |
  66. HandLocationStatus.OrientationTracked | HandLocationStatus.OrientationValid;
  67. bool isValid = false;
  68. public override void Start()
  69. {
  70. }
  71. public override void Stop()
  72. {
  73. }
  74. public override void Destroy()
  75. {
  76. }
  77. /// <summary>
  78. /// Mapping the PICO Joint Index To Unity Joint Index
  79. /// </summary>
  80. static int[] pxrJointIndexToUnityJointIndexMapping;
  81. static void Initialize()
  82. {
  83. if (pxrJointIndexToUnityJointIndexMapping == null)
  84. {
  85. pxrJointIndexToUnityJointIndexMapping = new int[(int)HandJoint.JointMax];
  86. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointPalm] = XRHandJointID.Palm.ToIndex();
  87. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointWrist] = XRHandJointID.Wrist.ToIndex();
  88. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointThumbMetacarpal] = XRHandJointID.ThumbMetacarpal.ToIndex();
  89. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointThumbProximal] = XRHandJointID.ThumbProximal.ToIndex();
  90. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointThumbDistal] = XRHandJointID.ThumbDistal.ToIndex();
  91. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointThumbTip] = XRHandJointID.ThumbTip.ToIndex();
  92. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointIndexMetacarpal] = XRHandJointID.IndexMetacarpal.ToIndex();
  93. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointIndexProximal] = XRHandJointID.IndexProximal.ToIndex();
  94. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointIndexIntermediate] = XRHandJointID.IndexIntermediate.ToIndex();
  95. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointIndexDistal] = XRHandJointID.IndexDistal.ToIndex();
  96. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointIndexTip] = XRHandJointID.IndexTip.ToIndex();
  97. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointMiddleMetacarpal] = XRHandJointID.MiddleMetacarpal.ToIndex();
  98. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointMiddleProximal] = XRHandJointID.MiddleProximal.ToIndex();
  99. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointMiddleIntermediate] = XRHandJointID.MiddleIntermediate.ToIndex();
  100. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointMiddleDistal] = XRHandJointID.MiddleDistal.ToIndex();
  101. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointMiddleTip] = XRHandJointID.MiddleTip.ToIndex();
  102. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointRingMetacarpal] = XRHandJointID.RingMetacarpal.ToIndex();
  103. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointRingProximal] = XRHandJointID.RingProximal.ToIndex();
  104. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointRingIntermediate] = XRHandJointID.RingIntermediate.ToIndex();
  105. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointRingDistal] = XRHandJointID.RingDistal.ToIndex();
  106. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointRingTip] = XRHandJointID.RingTip.ToIndex();
  107. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointLittleMetacarpal] = XRHandJointID.LittleMetacarpal.ToIndex();
  108. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointLittleProximal] = XRHandJointID.LittleProximal.ToIndex();
  109. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointLittleIntermediate] = XRHandJointID.LittleIntermediate.ToIndex();
  110. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointLittleDistal] = XRHandJointID.LittleDistal.ToIndex();
  111. pxrJointIndexToUnityJointIndexMapping[(int)HandJoint.JointLittleTip] = XRHandJointID.LittleTip.ToIndex();
  112. }
  113. }
  114. /// <summary>
  115. /// Gets the layout of hand joints for this provider, by having the
  116. /// provider mark each index corresponding to a <see cref="XRHandJointID"/>
  117. /// get marked as <see langword="true"/> if the provider attempts to track
  118. /// that joint.
  119. /// </summary>
  120. /// <remarks>
  121. /// Called once on creation so that before the subsystem is even started,
  122. /// so the user can immediately create a valid hierarchical structure as
  123. /// soon as they get a reference to the subsystem without even needing to
  124. /// start it.
  125. /// </remarks>
  126. /// <param name="handJointsInLayout">
  127. /// Each index corresponds to a <see cref="XRHandJointID"/>. For each
  128. /// joint that the provider will attempt to track, mark that spot as
  129. /// <see langword="true"/> by calling <c>.ToIndex()</c> on that ID.
  130. /// </param>
  131. public override void GetHandLayout(NativeArray<bool> handJointsInLayout)
  132. {
  133. Initialize();
  134. handJointsInLayout[XRHandJointID.Palm.ToIndex()] = true;
  135. handJointsInLayout[XRHandJointID.Wrist.ToIndex()] = true;
  136. handJointsInLayout[XRHandJointID.ThumbMetacarpal.ToIndex()] = true;
  137. handJointsInLayout[XRHandJointID.ThumbProximal.ToIndex()] = true;
  138. handJointsInLayout[XRHandJointID.ThumbDistal.ToIndex()] = true;
  139. handJointsInLayout[XRHandJointID.ThumbTip.ToIndex()] = true;
  140. handJointsInLayout[XRHandJointID.IndexMetacarpal.ToIndex()] = true;
  141. handJointsInLayout[XRHandJointID.IndexProximal.ToIndex()] = true;
  142. handJointsInLayout[XRHandJointID.IndexIntermediate.ToIndex()] = true;
  143. handJointsInLayout[XRHandJointID.IndexDistal.ToIndex()] = true;
  144. handJointsInLayout[XRHandJointID.IndexTip.ToIndex()] = true;
  145. handJointsInLayout[XRHandJointID.MiddleMetacarpal.ToIndex()] = true;
  146. handJointsInLayout[XRHandJointID.MiddleProximal.ToIndex()] = true;
  147. handJointsInLayout[XRHandJointID.MiddleIntermediate.ToIndex()] = true;
  148. handJointsInLayout[XRHandJointID.MiddleDistal.ToIndex()] = true;
  149. handJointsInLayout[XRHandJointID.MiddleTip.ToIndex()] = true;
  150. handJointsInLayout[XRHandJointID.RingMetacarpal.ToIndex()] = true;
  151. handJointsInLayout[XRHandJointID.RingProximal.ToIndex()] = true;
  152. handJointsInLayout[XRHandJointID.RingIntermediate.ToIndex()] = true;
  153. handJointsInLayout[XRHandJointID.RingDistal.ToIndex()] = true;
  154. handJointsInLayout[XRHandJointID.RingTip.ToIndex()] = true;
  155. handJointsInLayout[XRHandJointID.LittleMetacarpal.ToIndex()] = true;
  156. handJointsInLayout[XRHandJointID.LittleProximal.ToIndex()] = true;
  157. handJointsInLayout[XRHandJointID.LittleIntermediate.ToIndex()] = true;
  158. handJointsInLayout[XRHandJointID.LittleDistal.ToIndex()] = true;
  159. handJointsInLayout[XRHandJointID.LittleTip.ToIndex()] = true;
  160. isValid = true;
  161. }
  162. /// <summary>
  163. /// Attempts to retrieve current hand-tracking data from the provider.
  164. /// </summary>
  165. public override XRHandSubsystem.UpdateSuccessFlags TryUpdateHands(
  166. XRHandSubsystem.UpdateType updateType,
  167. ref UnityEngine.Pose leftHandRootPose,
  168. NativeArray<XRHandJoint> leftHandJoints,
  169. ref UnityEngine.Pose rightHandRootPose,
  170. NativeArray<XRHandJoint> rightHandJoints)
  171. {
  172. if (!isValid)
  173. return XRHandSubsystem.UpdateSuccessFlags.None;
  174. XRHandSubsystem.UpdateSuccessFlags ret = UpdateSuccessFlags.None;
  175. const int handRootIndex = (int)HandJoint.JointWrist;
  176. if (PXR_HandTracking.GetJointLocations(HandType.HandLeft, ref jointLocations))
  177. {
  178. if (jointLocations.isActive != 0U)
  179. {
  180. for (int index = 0, jointCount = (int)jointLocations.jointCount; index < jointCount; ++index)
  181. {
  182. ref HandJointLocation joint = ref jointLocations.jointLocations[index];
  183. int unityHandJointIndex = pxrJointIndexToUnityJointIndexMapping[index];
  184. leftHandJoints[unityHandJointIndex] = CreateXRHandJoint(Handedness.Left, unityHandJointIndex, joint);
  185. if (index == handRootIndex)
  186. {
  187. leftHandRootPose = PXRPosefToUnityPose(joint.pose);
  188. ret |= UpdateSuccessFlags.LeftHandRootPose;
  189. }
  190. }
  191. ret |= UpdateSuccessFlags.LeftHandJoints;
  192. }
  193. }
  194. if (PXR_HandTracking.GetJointLocations(HandType.HandRight, ref jointLocations))
  195. {
  196. if (jointLocations.isActive != 0U)
  197. {
  198. for (int index = 0, jointCount = (int)jointLocations.jointCount; index < jointCount; ++index)
  199. {
  200. ref HandJointLocation joint = ref jointLocations.jointLocations[index];
  201. int unityHandJointIndex = pxrJointIndexToUnityJointIndexMapping[index];
  202. rightHandJoints[unityHandJointIndex] = CreateXRHandJoint(Handedness.Right, unityHandJointIndex, joint);
  203. if (index == handRootIndex)
  204. {
  205. rightHandRootPose = PXRPosefToUnityPose(joint.pose);
  206. ret |= UpdateSuccessFlags.RightHandRootPose;
  207. }
  208. }
  209. ret |= UpdateSuccessFlags.RightHandJoints;
  210. }
  211. }
  212. return ret;
  213. }
  214. /// <summary>
  215. /// Create Unity XRHandJoint From PXR HandJointLocation
  216. /// </summary>
  217. /// <param name="handedness"></param>
  218. /// <param name="unityHandJointIndex"></param>
  219. /// <param name="joint"></param>
  220. /// <returns></returns>
  221. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  222. XRHandJoint CreateXRHandJoint(Handedness handedness, int unityHandJointIndex, in HandJointLocation joint)
  223. {
  224. UnityEngine.Pose pose = UnityEngine.Pose.identity;
  225. XRHandJointTrackingState state = XRHandJointTrackingState.None;
  226. if ((joint.locationStatus & AllStatus) == AllStatus)
  227. {
  228. state = (XRHandJointTrackingState.Pose | XRHandJointTrackingState.Radius);
  229. pose = PXRPosefToUnityPose(joint.pose);
  230. }
  231. return XRHandProviderUtility.CreateJoint(handedness,
  232. state,
  233. XRHandJointIDUtility.FromIndex(unityHandJointIndex),
  234. pose, joint.radius
  235. );
  236. }
  237. /// <summary>
  238. /// PXR's Posef to Unity'Pose
  239. /// </summary>
  240. /// <param name="pxrPose"></param>
  241. /// <returns></returns>
  242. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  243. UnityEngine.Pose PXRPosefToUnityPose(in Unity.XR.PXR.Posef pxrPose)
  244. {
  245. Vector3 position = pxrPose.Position.ToVector3();
  246. Quaternion orientation = pxrPose.Orientation.ToQuat();
  247. return new UnityEngine.Pose(position, orientation);
  248. }
  249. }
  250. }
  251. }
  252. #endif //XR_HANDS
粤ICP备19079148号