PXR_EyeTracking.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  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 System.Collections.Generic;
  12. using UnityEngine;
  13. using UnityEngine.XR;
  14. namespace Unity.XR.PXR
  15. {
  16. public class PXR_EyeTracking
  17. {
  18. /// <summary>
  19. /// Gets the PosMatrix of the head.
  20. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  21. /// </summary>
  22. /// <param name="matrix">A Matrix4x4 value returned by the result.</param>
  23. /// <returns>
  24. /// * `true`: success
  25. /// * `false`: failure
  26. /// </returns>
  27. public static bool GetHeadPosMatrix(out Matrix4x4 matrix)
  28. {
  29. matrix = Matrix4x4.identity;
  30. if (!PXR_Manager.Instance.eyeTracking)
  31. return false;
  32. if (!GetEyeTrackingDevice(out InputDevice device))
  33. return false;
  34. Vector3 headPos = Vector3.zero;
  35. if (!device.TryGetFeatureValue(CommonUsages.devicePosition, out headPos))
  36. {
  37. Debug.LogError("PXRLog Failed at GetHeadPosMatrix Pos");
  38. return false;
  39. }
  40. Quaternion headRot = Quaternion.identity;
  41. if (!device.TryGetFeatureValue(CommonUsages.deviceRotation, out headRot))
  42. {
  43. Debug.LogError("PXRLog Failed at GetHeadPosMatrix Rot");
  44. return false;
  45. }
  46. matrix = Matrix4x4.TRS(headPos, headRot, Vector3.one);
  47. return true;
  48. }
  49. static InputDevice curDevice;
  50. /// <summary>
  51. /// Gets the input device for eye tracking data.
  52. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  53. /// </summary>
  54. /// <param name="device">The input device returned by the result.</param>
  55. /// <returns>
  56. /// * `true`: success
  57. /// * `false`: failure
  58. /// </returns>
  59. static bool GetEyeTrackingDevice(out InputDevice device)
  60. {
  61. if (curDevice!= null&& curDevice.isValid)
  62. {
  63. device = curDevice;
  64. return true;
  65. }
  66. device = default;
  67. if (!PXR_Manager.Instance.eyeTracking)
  68. return false;
  69. List<InputDevice> devices = new List<InputDevice>();
  70. InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.EyeTracking | InputDeviceCharacteristics.HeadMounted, devices);
  71. if (devices.Count == 0)
  72. {
  73. Debug.LogError("PXRLog Failed at GetEyeTrackingDevice devices.Count");
  74. return false;
  75. }
  76. device = devices[0];
  77. curDevice = device;
  78. if (!device.isValid)
  79. {
  80. Debug.LogError("PXRLog Failed at GetEyeTrackingDevice device.isValid");
  81. }
  82. return device.isValid;
  83. }
  84. /// <summary>
  85. /// Gets the position of the center of the eyes in the Unity camera coordinate system (unit: meter).
  86. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  87. /// </summary>
  88. /// <param name="point">Returns a vector3 value which is divided by 1000.
  89. /// To get the original value, multiply the returned value by 1000. Unit: millimeter.
  90. /// </param>
  91. /// <returns>
  92. /// * `true`: success
  93. /// * `false`: failure
  94. /// </returns>
  95. public static bool GetCombineEyeGazePoint(out Vector3 point)
  96. {
  97. point = Vector3.zero;
  98. if (!PXR_Manager.Instance.eyeTracking)
  99. return false;
  100. if (!GetEyeTrackingDevice(out InputDevice device))
  101. return false;
  102. if (!device.TryGetFeatureValue(PXR_Usages.combineEyePoint, out point))
  103. {
  104. Debug.Log("PXRLog Failed at GetCombineEyeGazePoint point");
  105. return false;
  106. }
  107. return true;
  108. }
  109. /// <summary>
  110. /// Gets the direction of binocular combined gaze in the Unity camera coordinate system.
  111. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  112. /// </summary>
  113. /// <param name="vector">Returns a vector3 value which is divided by 1000.
  114. /// To get the original value, multiply the returned value by 1000. Unit: millimeter.
  115. /// </param>
  116. /// <returns>
  117. /// * `true`: success
  118. /// * `false`: failure
  119. /// </returns>
  120. public static bool GetCombineEyeGazeVector(out Vector3 vector)
  121. {
  122. vector = Vector3.zero;
  123. if (!PXR_Manager.Instance.eyeTracking)
  124. return false;
  125. if (!GetEyeTrackingDevice(out InputDevice device))
  126. return false;
  127. if (!device.TryGetFeatureValue(PXR_Usages.combineEyeVector, out vector))
  128. {
  129. Debug.LogError("PXRLog Failed at GetCombineEyeGazeVector vector");
  130. return false;
  131. }
  132. return true;
  133. }
  134. /// <summary>
  135. /// Gets the openness/closeness of the left eye.
  136. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  137. /// </summary>
  138. /// <param name="openness">A float value returned by the result. The value ranges from `0.0` to `1.0`. `0.0` incicates completely closed, `1.0` indicates completely open.</param>
  139. /// <returns>
  140. /// * `true`: success
  141. /// * `false`: failure
  142. /// </returns>
  143. public static bool GetLeftEyeGazeOpenness(out float openness)
  144. {
  145. openness = 0;
  146. if (!PXR_Manager.Instance.eyeTracking)
  147. return false;
  148. if (!GetEyeTrackingDevice(out InputDevice device))
  149. return false;
  150. if (!device.TryGetFeatureValue(PXR_Usages.leftEyeOpenness, out openness))
  151. {
  152. Debug.LogError("PXRLog Failed at GetLeftEyeGazeOpenness openness");
  153. return false;
  154. }
  155. return true;
  156. }
  157. /// <summary>
  158. /// Gets the openness/closeness of the right eye.
  159. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  160. /// </summary>
  161. /// <param name="openness">A float value returned by the result. The value ranges from `0.0` to `1.0`. `0.0` indicates completely closed, `1.0` indicates completely open.</param>
  162. /// <returns>
  163. /// * `true`: success
  164. /// * `false`: failure
  165. /// </returns>
  166. public static bool GetRightEyeGazeOpenness(out float openness)
  167. {
  168. openness = 0;
  169. if (!PXR_Manager.Instance.eyeTracking)
  170. return false;
  171. if (!GetEyeTrackingDevice(out InputDevice device))
  172. return false;
  173. if (!device.TryGetFeatureValue(PXR_Usages.rightEyeOpenness, out openness))
  174. {
  175. Debug.LogError("PXRLog Failed at GetRightEyeGazeOpenness openness");
  176. return false;
  177. }
  178. return true;
  179. }
  180. /// <summary>
  181. /// Gets whether the data of the current left eye is available.
  182. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  183. /// </summary>
  184. /// <param name="status">An int value returned by the result. Below are the EyePoseStatus enumerations:
  185. /// * `GazePointValid` = (1 << 0),
  186. /// * `GazeVectorValid` = (1 << 1),
  187. /// * `EyeOpennessValid` = (1 << 2),
  188. /// * `EyePupilDilationValid` = (1 << 3),
  189. /// * `EyePositionGuideValid` = (1 << 4),
  190. /// * `EyePupilPositionValid` = (1 << 5),
  191. /// * `EyeConvergenceDistanceValid` = (1 << 6),
  192. /// * `EyeGazePointValid` = (1 << 7),
  193. /// * `EyeGazeVectorValid` = (1 << 8),
  194. /// * `PupilDistanceValid` = (1 << 9),
  195. /// * `ConvergenceDistanceValid` = (1 << 10),
  196. /// * `PupilDiameterValid` = (1 << 11),
  197. /// </param>
  198. /// <returns>
  199. /// * `true`: success
  200. /// * `false`: failure
  201. /// </returns>
  202. public static bool GetLeftEyePoseStatus(out uint status)
  203. {
  204. status = 0;
  205. if (!PXR_Manager.Instance.eyeTracking)
  206. return false;
  207. if (!GetEyeTrackingDevice(out InputDevice device))
  208. return false;
  209. if (!device.TryGetFeatureValue(PXR_Usages.leftEyePoseStatus, out status))
  210. {
  211. Debug.LogError("PXRLog Failed at GetLeftEyePoseStatus status");
  212. return false;
  213. }
  214. return true;
  215. }
  216. /// <summary>
  217. /// Gets whether the data of the current right eye is available.
  218. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  219. /// </summary>
  220. /// <param name="status">An int value returned by the result:
  221. /// * `0`: not available
  222. /// * `1`: available
  223. /// </param>
  224. /// <returns>
  225. /// * `true`: success
  226. /// * `false`: failure
  227. /// </returns>
  228. public static bool GetRightEyePoseStatus(out uint status)
  229. {
  230. status = 0;
  231. if (!PXR_Manager.Instance.eyeTracking)
  232. return false;
  233. if (!GetEyeTrackingDevice(out InputDevice device))
  234. return false;
  235. if (!device.TryGetFeatureValue(PXR_Usages.rightEyePoseStatus, out status))
  236. {
  237. Debug.LogError("PXRLog Failed at GetRightEyePoseStatus status");
  238. return false;
  239. }
  240. return true;
  241. }
  242. /// <summary>
  243. /// Gets whether the data of the combined eye is available.
  244. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  245. /// </summary>
  246. /// <param name="status">An int value returned by the result:
  247. /// `0`: not available
  248. /// `1`: available
  249. /// </param>
  250. /// <returns>
  251. /// * `true`: success
  252. /// * `false`: failure
  253. /// </returns>
  254. public static bool GetCombinedEyePoseStatus(out uint status)
  255. {
  256. status = 0;
  257. if (!PXR_Manager.Instance.eyeTracking)
  258. return false;
  259. if (!GetEyeTrackingDevice(out InputDevice device))
  260. return false;
  261. if (!device.TryGetFeatureValue(PXR_Usages.combinedEyePoseStatus, out status))
  262. {
  263. Debug.LogError("PXRLog Failed at GetCombinedEyePoseStatus status");
  264. return false;
  265. }
  266. return true;
  267. }
  268. /// <summary>
  269. /// Gets the coordinate of the left eye's inner eye corner in the image coordinate system, where the top left corner is (0,0) and the bottom right corner is (1,1).
  270. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  271. /// </summary>
  272. /// <param name="position">A vector3 value returned by the result.</param>
  273. /// <returns>
  274. /// * `true`: success
  275. /// * `false`: failure
  276. /// </returns>
  277. public static bool GetLeftEyePositionGuide(out Vector3 position)
  278. {
  279. position = Vector3.zero;
  280. if (!PXR_Manager.Instance.eyeTracking)
  281. return false;
  282. if (!GetEyeTrackingDevice(out InputDevice device))
  283. return false;
  284. if (!device.TryGetFeatureValue(PXR_Usages.leftEyePositionGuide, out position))
  285. {
  286. Debug.LogError("PXRLog Failed at GetLeftEyePositionGuide pos");
  287. return false;
  288. }
  289. return true;
  290. }
  291. /// <summary>
  292. /// Gets the coordinate of the right eye's inner eye corner in the image coordinate system, where the top left corner is (0,0) and the bottom right corner is (1,1).
  293. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  294. /// </summary>
  295. /// <param name="position">A vector3 value returned by the result.</param>
  296. /// <returns>
  297. /// * `true`: success
  298. /// * `false`: failure
  299. /// </returns>
  300. public static bool GetRightEyePositionGuide(out Vector3 position)
  301. {
  302. position = Vector3.zero;
  303. if (!PXR_Manager.Instance.eyeTracking)
  304. return false;
  305. if (!GetEyeTrackingDevice(out InputDevice device))
  306. return false;
  307. if (!device.TryGetFeatureValue(PXR_Usages.rightEyePositionGuide, out position))
  308. {
  309. Debug.LogError("PXRLog Failed at GetRightEyePositionGuide pos");
  310. return false;
  311. }
  312. return true;
  313. }
  314. /// <summary>
  315. /// Gets the direction of binocular combined gaze in the View coordinate system (i.e., OpenXR right-handed coordinate system).
  316. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  317. /// </summary>
  318. /// <param name="direction">A vector3 value returned by the result.</param>
  319. /// <returns>
  320. /// * `true`: success
  321. /// * `false`: failure
  322. /// </returns>
  323. public static bool GetFoveatedGazeDirection(out Vector3 direction)
  324. {
  325. direction = Vector3.zero;
  326. if (!PXR_Manager.Instance.eyeTracking)
  327. return false;
  328. if (!GetEyeTrackingDevice(out InputDevice device))
  329. return false;
  330. if (!device.TryGetFeatureValue(PXR_Usages.foveatedGazeDirection, out direction))
  331. {
  332. Debug.LogError("PXRLog Failed at GetFoveatedGazeDirection direction");
  333. return false;
  334. }
  335. return true;
  336. }
  337. /// <summary>
  338. /// Gets whether the current foveated gaze tracking data is available.
  339. /// @note Only supported by PICO Neo3 Pro Eye, PICO 4 Pro, and PICO 4 Enterprise.
  340. /// </summary>
  341. /// <param name="status">An int value returned by the result:
  342. /// * `0`: not available
  343. /// * `1`: available
  344. /// </param>
  345. /// <returns>
  346. /// * `true`: success
  347. /// * `false`: failure
  348. /// </returns>
  349. public static bool GetFoveatedGazeTrackingState(out uint state)
  350. {
  351. state = 0;
  352. if (!PXR_Manager.Instance.eyeTracking)
  353. return false;
  354. if (!GetEyeTrackingDevice(out InputDevice device))
  355. return false;
  356. if (!device.TryGetFeatureValue(PXR_Usages.foveatedGazeTrackingState, out state))
  357. {
  358. Debug.LogError("PXRLog Failed at GetFoveatedGazeTrackingState state");
  359. return false;
  360. }
  361. return true;
  362. }
  363. }
  364. }
粤ICP备19079148号