SW 중심대학 OSS GIT 서버 박건태, 이승준, 고기완, 이준호 새로운 배포
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

595 lines
22 KiB

4 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.CompilerServices;
  4. #if ENABLE_VR || ENABLE_AR
  5. using UnityEngine.XR;
  6. using UnityEngine.Experimental.XR.Interaction;
  7. #endif
  8. #if ENABLE_AR
  9. using UnityEngine.XR.Tango;
  10. #endif
  11. [assembly: InternalsVisibleTo("UnityEditor.SpatialTracking")]
  12. namespace UnityEngine.SpatialTracking
  13. {
  14. internal class TrackedPoseDriverDataDescription
  15. {
  16. internal struct PoseData
  17. {
  18. public List<string> PoseNames;
  19. public List<TrackedPoseDriver.TrackedPose> Poses;
  20. }
  21. internal static List<PoseData> DeviceData = new List<PoseData>
  22. {
  23. // Generic XR Device
  24. new PoseData
  25. {
  26. PoseNames = new List<string>
  27. {
  28. "Left Eye", "Right Eye", "Center Eye - HMD Reference", "Head", "Color Camera"
  29. },
  30. Poses = new List<TrackedPoseDriver.TrackedPose>
  31. {
  32. TrackedPoseDriver.TrackedPose.LeftEye,
  33. TrackedPoseDriver.TrackedPose.RightEye,
  34. TrackedPoseDriver.TrackedPose.Center,
  35. TrackedPoseDriver.TrackedPose.Head,
  36. TrackedPoseDriver.TrackedPose.ColorCamera
  37. }
  38. },
  39. // generic controller
  40. new PoseData
  41. {
  42. PoseNames = new List<string>
  43. {
  44. "Left Controller", "Right Controller"
  45. },
  46. Poses = new List<TrackedPoseDriver.TrackedPose>
  47. {
  48. TrackedPoseDriver.TrackedPose.LeftPose,
  49. TrackedPoseDriver.TrackedPose.RightPose
  50. }
  51. },
  52. // generic remote
  53. new PoseData
  54. {
  55. PoseNames = new List<string>
  56. {
  57. "Device Pose"
  58. },
  59. Poses = new List<TrackedPoseDriver.TrackedPose>
  60. {
  61. TrackedPoseDriver.TrackedPose.RemotePose,
  62. }
  63. },
  64. };
  65. }
  66. /// <summary>
  67. /// Bitflag enum which represents what data was set on an associated Pose struct
  68. /// </summary>
  69. [Flags]
  70. public enum PoseDataFlags
  71. {
  72. /// <summary>
  73. /// No data was actually set on the pose
  74. /// </summary>
  75. NoData = 0,
  76. /// <summary>
  77. /// If this flag is set, position data was updated on the associated pose struct
  78. /// </summary>
  79. Position = 1 << 0,
  80. /// <summary>
  81. /// If this flag is set, rotation data was updated on the associated pose struct
  82. /// </summary>
  83. Rotation = 1 << 1,
  84. }
  85. /// <summary>
  86. /// The PoseDataSource class acts as a container for the GetDatafromSource method call that should be used by PoseProviders wanting to query data for a particular pose.
  87. /// </summary>
  88. static public class PoseDataSource
  89. {
  90. #if ENABLE_AR || ENABLE_VR
  91. static internal List<XR.XRNodeState> nodeStates = new List<XR.XRNodeState>();
  92. static internal PoseDataFlags GetNodePoseData(XR.XRNode node, out Pose resultPose)
  93. {
  94. PoseDataFlags retData = PoseDataFlags.NoData;
  95. XR.InputTracking.GetNodeStates(nodeStates);
  96. foreach (XR.XRNodeState nodeState in nodeStates)
  97. {
  98. if (nodeState.nodeType == node)
  99. {
  100. if(nodeState.TryGetPosition(out resultPose.position))
  101. {
  102. retData |= PoseDataFlags.Position;
  103. }
  104. if (nodeState.TryGetRotation(out resultPose.rotation))
  105. {
  106. retData |= PoseDataFlags.Rotation;
  107. }
  108. return retData;
  109. }
  110. }
  111. resultPose = Pose.identity;
  112. return retData;
  113. }
  114. #endif
  115. /// <summary>
  116. /// <signature><![CDATA[TryGetDataFromSource(TrackedPose,Pose)]]></signature>
  117. /// <summary>The GetDatafromSource method is used to query data from the XRNode subsystem based on the provided pose source.</summary>
  118. /// <param name = "poseSource" > The pose source to request data for.</param>
  119. /// <param name = "resultPose" > The resulting pose data.</param>
  120. /// <returns>True, if the pose source is valid, otherwise false.</returns>
  121. static public bool TryGetDataFromSource(TrackedPoseDriver.TrackedPose poseSource, out Pose resultPose)
  122. {
  123. return GetDataFromSource(poseSource, out resultPose) == (PoseDataFlags.Position | PoseDataFlags.Rotation);
  124. }
  125. /// <summary>
  126. /// <signature><![CDATA[GetDataFromSource(TrackedPose,Pose)]]></signature>
  127. /// <summary>The GetDatafromSource method is used to query data from the XRNode subsystem based on the provided pose source.</summary>
  128. /// <param name = "poseSource" > The pose source to request data for.</param>
  129. /// <param name = "resultPose" > The resulting pose data. This function will return the Center Eye pose if the Color Camera pose is not available. </param>
  130. /// <returns>Retuns a bitflag which represents which data has been retrieved from the provided pose source</returns>
  131. static public PoseDataFlags GetDataFromSource(TrackedPoseDriver.TrackedPose poseSource, out Pose resultPose)
  132. {
  133. #if ENABLE_AR || ENABLE_VR
  134. switch (poseSource)
  135. {
  136. case TrackedPoseDriver.TrackedPose.RemotePose:
  137. {
  138. PoseDataFlags retFlags = GetNodePoseData(XR.XRNode.RightHand, out resultPose);
  139. if (retFlags == PoseDataFlags.NoData)
  140. return GetNodePoseData(XR.XRNode.LeftHand, out resultPose);
  141. return retFlags;
  142. }
  143. case TrackedPoseDriver.TrackedPose.LeftEye:
  144. {
  145. return GetNodePoseData(XR.XRNode.LeftEye, out resultPose);
  146. }
  147. case TrackedPoseDriver.TrackedPose.RightEye:
  148. {
  149. return GetNodePoseData(XR.XRNode.RightEye, out resultPose);
  150. }
  151. case TrackedPoseDriver.TrackedPose.Head:
  152. {
  153. return GetNodePoseData(XR.XRNode.Head, out resultPose);
  154. }
  155. case TrackedPoseDriver.TrackedPose.Center:
  156. {
  157. return GetNodePoseData(XR.XRNode.CenterEye, out resultPose);
  158. }
  159. case TrackedPoseDriver.TrackedPose.LeftPose:
  160. {
  161. return GetNodePoseData(XR.XRNode.LeftHand, out resultPose);
  162. }
  163. case TrackedPoseDriver.TrackedPose.RightPose:
  164. {
  165. return GetNodePoseData(XR.XRNode.RightHand, out resultPose);
  166. }
  167. case TrackedPoseDriver.TrackedPose.ColorCamera:
  168. {
  169. PoseDataFlags retFlags = TryGetTangoPose(out resultPose);
  170. if(retFlags == PoseDataFlags.NoData)
  171. {
  172. // We fall back to CenterEye because we can't currently extend the XRNode structure, nor are we ready to replace it.
  173. return GetNodePoseData(XR.XRNode.CenterEye, out resultPose);
  174. }
  175. return retFlags;
  176. }
  177. default:
  178. {
  179. Debug.LogWarningFormat("Unable to retrieve pose data for poseSource: {0}", poseSource.ToString());
  180. break;
  181. }
  182. }
  183. #endif
  184. resultPose = Pose.identity;
  185. return PoseDataFlags.NoData;
  186. }
  187. static PoseDataFlags TryGetTangoPose(out Pose pose)
  188. {
  189. #if ENABLE_AR
  190. PoseData poseOut;
  191. if (TangoInputTracking.TryGetPoseAtTime(out poseOut) && poseOut.statusCode == PoseStatus.Valid)
  192. {
  193. pose.position = poseOut.position;
  194. pose.rotation = poseOut.rotation;
  195. return PoseDataFlags.Position | PoseDataFlags.Rotation; ;
  196. }
  197. #endif
  198. pose = Pose.identity;
  199. return PoseDataFlags.NoData;
  200. }
  201. }
  202. // The DefaultExecutionOrder is needed because TrackedPoseDriver does some
  203. // of its work in regular Update and FixedUpdate calls, but this needs to
  204. // be done before regular user scripts have their own Update and
  205. // FixedUpdate calls, in order that they correctly get the values for this
  206. // frame and not the previous.
  207. // -32000 is the minimal possible execution order value; -30000 makes it
  208. // is unlikely users chose lower values for their scripts by accident, but
  209. // still makes it possible.
  210. /// <summary>
  211. /// The TrackedPoseDriver component applies the current Pose value of a tracked device to the transform of the GameObject.
  212. /// TrackedPoseDriver can track multiple types of devices including XR HMDs, controllers, and remotes.
  213. /// </summary>
  214. [DefaultExecutionOrder(-30000)]
  215. [Serializable]
  216. [AddComponentMenu("XR/Tracked Pose Driver")]
  217. [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.legacyinputhelpers@2.1/manual/index.html")]
  218. public class TrackedPoseDriver : MonoBehaviour
  219. {
  220. /// <summary>
  221. /// The device being tracked by the tracked pose driver
  222. /// </summary>
  223. public enum DeviceType
  224. {
  225. /// <summary>
  226. /// An XR Controller, use this value for controllers
  227. /// </summary>
  228. GenericXRDevice = 0,
  229. /// <summary>
  230. /// An Generic XR Devices, use this value for HMD and AR Mobile device tracking
  231. /// </summary>
  232. GenericXRController = 1,
  233. /// <summary>
  234. /// An XR Remote, use this value for mobile remotes
  235. /// </summary>
  236. GenericXRRemote = 2
  237. }
  238. public enum TrackedPose
  239. {
  240. /// <summary>
  241. /// The left eye of a HMD style device
  242. /// </summary>
  243. LeftEye = 0,
  244. /// <summary>
  245. /// The right eye of a HMD style device
  246. /// </summary>
  247. RightEye = 1,
  248. /// <summary>
  249. /// The center eye of a HMD style device, this is usually the default for most HMDs
  250. /// </summary>
  251. Center = 2,
  252. /// <summary>
  253. /// The head eye of a HMD style device
  254. /// </summary>
  255. Head = 3,
  256. /// <summary>
  257. /// The left hand controller pose
  258. /// </summary>
  259. LeftPose = 4,
  260. /// <summary>
  261. /// The right hand controller pose
  262. /// </summary>
  263. RightPose = 5,
  264. /// <summary>
  265. /// The color camera of a mobile device
  266. /// </summary>
  267. ColorCamera = 6,
  268. /// <summary>
  269. /// No Longer Used
  270. /// </summary>
  271. DepthCameraDeprecated = 7,
  272. /// <summary>
  273. /// No Longer Used
  274. /// </summary>
  275. FisheyeCameraDeprected = 8,
  276. /// <summary>
  277. /// No Longer Used
  278. /// </summary>
  279. DeviceDeprecated = 9,
  280. /// <summary>
  281. /// The pose of a mobile remote
  282. /// </summary>
  283. RemotePose = 10,
  284. }
  285. [SerializeField]
  286. DeviceType m_Device;
  287. /// <summary>
  288. /// This is used to indicate which pose the TrackedPoseDriver is currently tracking.
  289. /// </summary>
  290. public DeviceType deviceType
  291. {
  292. get { return m_Device; }
  293. internal set { m_Device = value; }
  294. }
  295. [SerializeField]
  296. TrackedPose m_PoseSource = TrackedPoseDriver.TrackedPose.Center;
  297. /// <summary>
  298. /// The pose being tracked by the tracked pose driver
  299. /// </summary>
  300. public TrackedPose poseSource
  301. {
  302. get { return m_PoseSource; }
  303. internal set { m_PoseSource = value; }
  304. }
  305. /// <summary>
  306. /// This method is used to set the device / pose pair for the SpatialTracking.TrackedPoseDriver. setting an invalid combination of these values will return false.
  307. /// </summary>
  308. /// <param name="deviceType">The device type that we wish to track </param>
  309. /// <param name="pose">The pose source that we wish to track</param>
  310. /// <returns>true if the values provided are sensible, otherwise false</returns>
  311. public bool SetPoseSource(DeviceType deviceType, TrackedPose pose)
  312. {
  313. if ((int)deviceType < TrackedPoseDriverDataDescription.DeviceData.Count)
  314. {
  315. TrackedPoseDriverDataDescription.PoseData val = TrackedPoseDriverDataDescription.DeviceData[(int)deviceType];
  316. for (int i = 0; i < val.Poses.Count; ++i)
  317. {
  318. if (val.Poses[i] == pose)
  319. {
  320. this.deviceType = deviceType;
  321. poseSource = pose;
  322. return true;
  323. }
  324. }
  325. }
  326. return false;
  327. }
  328. #if ENABLE_VR || ENABLE_AR
  329. [SerializeField]
  330. BasePoseProvider m_PoseProviderComponent = null;
  331. /// <summary>
  332. /// Optional: This field holds the reference to the PoseProvider instance that, if set, will be used to override the behavior of
  333. /// the TrackedPoseDriver. When this field is empty, the TrackedPoseDriver will operate as per usual, with pose data being
  334. /// retrieved from the device or pose settings of the TrackedPoseDriver. When this field is set, the pose data will be
  335. /// provided by the attached PoseProvider. The device or pose fields will be hidden as they are no longer used to
  336. /// control the parent GameObject Transform.
  337. /// </summary>
  338. public BasePoseProvider poseProviderComponent
  339. {
  340. get { return m_PoseProviderComponent; }
  341. set
  342. {
  343. m_PoseProviderComponent = value;
  344. }
  345. }
  346. #endif
  347. PoseDataFlags GetPoseData(DeviceType device, TrackedPose poseSource, out Pose resultPose)
  348. {
  349. #if ENABLE_VR || ENABLE_AR
  350. if (m_PoseProviderComponent != null)
  351. {
  352. return m_PoseProviderComponent.GetPoseFromProvider(out resultPose);
  353. }
  354. #endif
  355. return PoseDataSource.GetDataFromSource(poseSource, out resultPose);
  356. }
  357. /// <summary>
  358. /// This enum is used to indicate which parts of the pose will be applied to the parent transform
  359. /// </summary>
  360. public enum TrackingType
  361. {
  362. /// <summary>
  363. /// With this setting, both the pose's rotation and position will be applied to the parent transform
  364. /// </summary>
  365. RotationAndPosition,
  366. /// <summary>
  367. /// With this setting, only the pose's rotation will be applied to the parent transform
  368. /// </summary>
  369. RotationOnly,
  370. /// <summary>
  371. /// With this setting, only the pose's position will be applied to the parent transform
  372. /// </summary>
  373. PositionOnly
  374. }
  375. [SerializeField]
  376. TrackingType m_TrackingType;
  377. /// <summary>
  378. /// The tracking type being used by the tracked pose driver
  379. /// </summary>
  380. public TrackingType trackingType
  381. {
  382. get { return m_TrackingType; }
  383. set { m_TrackingType = value; }
  384. }
  385. /// <summary>
  386. /// The update type being used by the tracked pose driver
  387. /// </summary>
  388. public enum UpdateType
  389. {
  390. /// <summary>
  391. /// Sample input at both update, and directly before rendering. For smooth head pose tracking,
  392. /// we recommend using this value as it will provide the lowest input latency for the device.
  393. /// This is the default value for the UpdateType option
  394. /// </summary>
  395. UpdateAndBeforeRender,
  396. /// <summary>
  397. /// Only sample input during the update phase of the frame.
  398. /// </summary>
  399. Update,
  400. /// <summary>
  401. /// Only sample input directly before rendering
  402. /// </summary>
  403. BeforeRender,
  404. }
  405. [SerializeField]
  406. UpdateType m_UpdateType = UpdateType.UpdateAndBeforeRender;
  407. /// <summary>
  408. /// The update type being used by the tracked pose driver
  409. /// </summary>
  410. public UpdateType updateType
  411. {
  412. get { return m_UpdateType; }
  413. set { m_UpdateType = value; }
  414. }
  415. [SerializeField]
  416. bool m_UseRelativeTransform = false;
  417. /// <summary>
  418. /// This is used to indicate whether the TrackedPoseDriver will use the object's original transform as its basis.
  419. /// </summary>
  420. public bool UseRelativeTransform
  421. {
  422. get { return m_UseRelativeTransform; }
  423. set { m_UseRelativeTransform = value; }
  424. }
  425. protected Pose m_OriginPose;
  426. // originPose is an offset applied to any tracking data read from this object.
  427. // Setting this value should be reserved for dealing with edge-cases, such as
  428. // achieving parity between room-scale (floor centered) and stationary (head centered)
  429. // tracking - without having to alter the transform hierarchy.
  430. // For user locomotion and gameplay purposes you are usually better off just
  431. // moving the parent transform of this object.
  432. public Pose originPose
  433. {
  434. get { return m_OriginPose; }
  435. set { m_OriginPose = value; }
  436. }
  437. private void CacheLocalPosition()
  438. {
  439. m_OriginPose.position = transform.localPosition;
  440. m_OriginPose.rotation = transform.localRotation;
  441. }
  442. private void ResetToCachedLocalPosition()
  443. {
  444. SetLocalTransform(m_OriginPose.position, m_OriginPose.rotation, PoseDataFlags.Position | PoseDataFlags.Rotation);
  445. }
  446. protected virtual void Awake()
  447. {
  448. CacheLocalPosition();
  449. #if UNITY_2019_3_OR_NEWER
  450. // deprecated functionality in 2020.1
  451. #else
  452. if (HasStereoCamera())
  453. {
  454. #if ENABLE_AR || ENABLE_VR
  455. XRDevice.DisableAutoXRCameraTracking(GetComponent<Camera>(), true);
  456. #endif
  457. }
  458. #endif
  459. }
  460. protected virtual void OnDestroy()
  461. {
  462. #if UNITY_2019_3_OR_NEWER
  463. // deprecated functionality in 2020.1
  464. #else
  465. if (HasStereoCamera())
  466. {
  467. #if ENABLE_AR || ENABLE_VR
  468. XRDevice.DisableAutoXRCameraTracking(GetComponent<Camera>(), false);
  469. #endif
  470. }
  471. #endif
  472. }
  473. protected virtual void OnEnable()
  474. {
  475. Application.onBeforeRender += OnBeforeRender;
  476. }
  477. protected virtual void OnDisable()
  478. {
  479. // remove delegate registration
  480. ResetToCachedLocalPosition();
  481. Application.onBeforeRender -= OnBeforeRender;
  482. }
  483. protected virtual void FixedUpdate()
  484. {
  485. if (m_UpdateType == UpdateType.Update ||
  486. m_UpdateType == UpdateType.UpdateAndBeforeRender)
  487. {
  488. PerformUpdate();
  489. }
  490. }
  491. protected virtual void Update()
  492. {
  493. if (m_UpdateType == UpdateType.Update ||
  494. m_UpdateType == UpdateType.UpdateAndBeforeRender)
  495. {
  496. PerformUpdate();
  497. }
  498. }
  499. protected virtual void OnBeforeRender()
  500. {
  501. if (m_UpdateType == UpdateType.BeforeRender ||
  502. m_UpdateType == UpdateType.UpdateAndBeforeRender)
  503. {
  504. PerformUpdate();
  505. }
  506. }
  507. protected virtual void SetLocalTransform(Vector3 newPosition, Quaternion newRotation, PoseDataFlags poseFlags)
  508. {
  509. if ((m_TrackingType == TrackingType.RotationAndPosition ||
  510. m_TrackingType == TrackingType.RotationOnly) &&
  511. (poseFlags & PoseDataFlags.Rotation) > 0)
  512. {
  513. transform.localRotation = newRotation;
  514. }
  515. if ((m_TrackingType == TrackingType.RotationAndPosition ||
  516. m_TrackingType == TrackingType.PositionOnly) &&
  517. (poseFlags & PoseDataFlags.Position) > 0)
  518. {
  519. transform.localPosition = newPosition;
  520. }
  521. }
  522. protected Pose TransformPoseByOriginIfNeeded(Pose pose)
  523. {
  524. if (m_UseRelativeTransform)
  525. {
  526. return pose.GetTransformedBy(m_OriginPose);
  527. }
  528. else
  529. {
  530. return pose;
  531. }
  532. }
  533. private bool HasStereoCamera()
  534. {
  535. Camera camera = GetComponent<Camera>();
  536. return camera != null && camera.stereoEnabled;
  537. }
  538. protected virtual void PerformUpdate()
  539. {
  540. if (!enabled)
  541. return;
  542. Pose currentPose = new Pose();
  543. currentPose = Pose.identity;
  544. PoseDataFlags poseFlags = GetPoseData(m_Device, m_PoseSource, out currentPose);
  545. if(poseFlags != PoseDataFlags.NoData)
  546. {
  547. Pose localPose = TransformPoseByOriginIfNeeded(currentPose);
  548. SetLocalTransform(localPose.position, localPose.rotation, poseFlags);
  549. }
  550. }
  551. }
  552. }