2021년 4학년 1학기 기업연계프로젝트2 컴퓨터소프트웨어공학과 <원광투어팀> 팀장 : 송유진 팀원 : 김나영, 이경희, 한유진
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.

327 lines
13 KiB

5 years ago
  1. //========= Copyright 2016-2020, HTC Corporation. All rights reserved. ===========
  2. #pragma warning disable 0618
  3. #if UNITY_2017_1_OR_NEWER
  4. using HTC.UnityPlugin.Utility;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. #if UNITY_2017_2_OR_NEWER
  8. using UnityEngine.XR;
  9. #else
  10. using UnityEngine.VR;
  11. using XRSettings = UnityEngine.VR.VRSettings;
  12. using XRDevice = UnityEngine.VR.VRDevice;
  13. using XRNodeState = UnityEngine.VR.VRNodeState;
  14. using XRNode = UnityEngine.VR.VRNode;
  15. #endif
  16. #endif
  17. namespace HTC.UnityPlugin.VRModuleManagement
  18. {
  19. public sealed partial class UnityEngineVRModule : VRModule.ModuleBase
  20. {
  21. #if UNITY_2017_1_OR_NEWER && !UNITY_2020_1_OR_NEWER
  22. private static readonly VRModuleDeviceClass[] s_nodeType2DeviceClass;
  23. private uint m_leftIndex = INVALID_DEVICE_INDEX;
  24. private uint m_rightIndex = INVALID_DEVICE_INDEX;
  25. private List<XRNodeState> m_nodeStateList = new List<XRNodeState>();
  26. private Dictionary<ulong, uint> m_node2Index = new Dictionary<ulong, uint>();
  27. private ulong[] m_index2nodeID;
  28. private bool[] m_index2nodeValidity;
  29. private bool[] m_index2nodeTouched;
  30. private TrackingSpaceType m_prevTrackingSpace;
  31. static UnityEngineVRModule()
  32. {
  33. s_nodeType2DeviceClass = new VRModuleDeviceClass[EnumUtils.GetMaxValue(typeof(XRNode)) + 1];
  34. for (int i = 0; i < s_nodeType2DeviceClass.Length; ++i) { s_nodeType2DeviceClass[i] = VRModuleDeviceClass.Invalid; }
  35. s_nodeType2DeviceClass[(int)XRNode.Head] = VRModuleDeviceClass.HMD;
  36. s_nodeType2DeviceClass[(int)XRNode.RightHand] = VRModuleDeviceClass.Controller;
  37. s_nodeType2DeviceClass[(int)XRNode.LeftHand] = VRModuleDeviceClass.Controller;
  38. s_nodeType2DeviceClass[(int)XRNode.GameController] = VRModuleDeviceClass.Controller;
  39. s_nodeType2DeviceClass[(int)XRNode.HardwareTracker] = VRModuleDeviceClass.GenericTracker;
  40. s_nodeType2DeviceClass[(int)XRNode.TrackingReference] = VRModuleDeviceClass.TrackingReference;
  41. }
  42. public override void OnActivated()
  43. {
  44. m_prevTrackingSpace = XRDevice.GetTrackingSpaceType();
  45. UpdateTrackingSpaceType();
  46. EnsureDeviceStateLength(16);
  47. m_index2nodeID = new ulong[GetDeviceStateLength()];
  48. m_index2nodeValidity = new bool[GetDeviceStateLength()];
  49. m_index2nodeTouched = new bool[GetDeviceStateLength()];
  50. }
  51. public override void OnDeactivated()
  52. {
  53. m_rightIndex = INVALID_DEVICE_INDEX;
  54. m_leftIndex = INVALID_DEVICE_INDEX;
  55. RemoveAllValidNodes();
  56. XRDevice.SetTrackingSpaceType(m_prevTrackingSpace);
  57. }
  58. public override uint GetLeftControllerDeviceIndex() { return m_leftIndex; }
  59. public override uint GetRightControllerDeviceIndex() { return m_rightIndex; }
  60. public override void UpdateTrackingSpaceType()
  61. {
  62. switch (VRModule.trackingSpaceType)
  63. {
  64. case VRModuleTrackingSpaceType.Stationary:
  65. XRDevice.SetTrackingSpaceType(TrackingSpaceType.Stationary);
  66. break;
  67. case VRModuleTrackingSpaceType.RoomScale:
  68. #if UNITY_2019_2_OR_NEWER && !UNITY_2019_3_OR_NEWER
  69. var prev_trackingOrigin = XRDevice.trackingOriginMode;
  70. XRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale);
  71. if (prev_trackingOrigin == XRDevice.trackingOriginMode)
  72. {
  73. XRDevice.SetTrackingSpaceType(TrackingSpaceType.Stationary);
  74. }
  75. #else
  76. XRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale);
  77. #endif
  78. break;
  79. }
  80. }
  81. private bool IsTrackingDeviceNode(XRNodeState nodeState)
  82. {
  83. switch (nodeState.nodeType)
  84. {
  85. case XRNode.Head:
  86. case XRNode.RightHand:
  87. case XRNode.LeftHand:
  88. case XRNode.GameController:
  89. case XRNode.HardwareTracker:
  90. case XRNode.TrackingReference:
  91. return true;
  92. default:
  93. return false;
  94. }
  95. }
  96. private bool TryGetAndTouchNodeDeviceIndex(XRNodeState nodeState, out uint deviceIndex)
  97. {
  98. // only tracking certain type of node (some nodes share same uniqueID)
  99. if (!IsTrackingDeviceNode(nodeState)) { deviceIndex = INVALID_DEVICE_INDEX; return false; }
  100. //Debug.Log(Time.frameCount + " TryGetNodeDeviceIndex " + nodeState.nodeType + " tracked=" + nodeState.tracked + " id=" + nodeState.uniqueID + " name=" + (InputTracking.GetNodeName(nodeState.uniqueID) ?? string.Empty));
  101. if (!m_node2Index.TryGetValue(nodeState.uniqueID, out deviceIndex))
  102. {
  103. // FIXME: 0ul is invalid id?
  104. if (nodeState.uniqueID == 0ul) { return false; }
  105. var validIndexFound = false;
  106. if (nodeState.nodeType == XRNode.Head)
  107. {
  108. if (m_index2nodeValidity[0])
  109. {
  110. //Debug.LogWarning("[" + Time.frameCount + "] Multiple Head node found! drop node id:" + nodeState.uniqueID.ToString("X8") + " type:" + nodeState.nodeType + " name:" + InputTracking.GetNodeName(nodeState.uniqueID) + " tracked=" + nodeState.tracked);
  111. deviceIndex = INVALID_DEVICE_INDEX;
  112. return false;
  113. }
  114. validIndexFound = true;
  115. m_index2nodeID[0] = nodeState.uniqueID;
  116. m_index2nodeValidity[0] = true;
  117. m_node2Index.Add(nodeState.uniqueID, 0u);
  118. deviceIndex = 0;
  119. }
  120. else
  121. {
  122. for (uint i = 1u, imax = (uint)m_index2nodeValidity.Length; i < imax; ++i)
  123. {
  124. if (!m_index2nodeValidity[i])
  125. {
  126. validIndexFound = true;
  127. m_index2nodeID[i] = nodeState.uniqueID;
  128. m_index2nodeValidity[i] = true;
  129. m_node2Index.Add(nodeState.uniqueID, i);
  130. deviceIndex = i;
  131. break;
  132. }
  133. }
  134. }
  135. if (!validIndexFound)
  136. {
  137. Debug.LogWarning("[" + Time.frameCount + "] XRNode added, but device index out of range, drop the node id:" + nodeState.uniqueID.ToString("X8") + " type:" + nodeState.nodeType + " name:" + InputTracking.GetNodeName(nodeState.uniqueID) + " tracked=" + nodeState.tracked);
  138. deviceIndex = INVALID_DEVICE_INDEX;
  139. return false;
  140. }
  141. //Debug.Log("[" + Time.frameCount + "] Add node device index [" + deviceIndex + "] id=" + nodeState.uniqueID.ToString("X8") + " type=" + nodeState.nodeType + " tracked=" + nodeState.tracked);
  142. }
  143. m_index2nodeTouched[deviceIndex] = true;
  144. return true;
  145. }
  146. private void TrimUntouchedNodes(System.Action<uint> onTrimmed)
  147. {
  148. for (uint i = 0u, imax = (uint)m_index2nodeValidity.Length; i < imax; ++i)
  149. {
  150. if (!m_index2nodeTouched[i])
  151. {
  152. if (m_index2nodeValidity[i])
  153. {
  154. m_node2Index.Remove(m_index2nodeID[i]);
  155. //m_index2nodeID[i] = 0;
  156. m_index2nodeValidity[i] = false;
  157. onTrimmed(i);
  158. }
  159. }
  160. else
  161. {
  162. Debug.Assert(m_index2nodeValidity[i]);
  163. m_index2nodeTouched[i] = false;
  164. }
  165. }
  166. }
  167. private void RemoveAllValidNodes()
  168. {
  169. for (int i = 0, imax = m_index2nodeValidity.Length; i < imax; ++i)
  170. {
  171. if (m_index2nodeValidity[i])
  172. {
  173. m_node2Index.Remove(m_index2nodeID[i]);
  174. m_index2nodeID[i] = 0;
  175. m_index2nodeValidity[i] = false;
  176. m_index2nodeTouched[i] = false;
  177. }
  178. }
  179. }
  180. public override void BeforeRenderUpdate()
  181. {
  182. var roleChanged = false;
  183. var rightIndex = INVALID_DEVICE_INDEX;
  184. var leftIndex = INVALID_DEVICE_INDEX;
  185. FlushDeviceState();
  186. if (XRSettings.isDeviceActive && XRDevice.isPresent)
  187. {
  188. InputTracking.GetNodeStates(m_nodeStateList);
  189. }
  190. for (int i = 0, imax = m_nodeStateList.Count; i < imax; ++i)
  191. {
  192. uint deviceIndex;
  193. if (!TryGetAndTouchNodeDeviceIndex(m_nodeStateList[i], out deviceIndex)) { continue; }
  194. switch (m_nodeStateList[i].nodeType)
  195. {
  196. case XRNode.RightHand: rightIndex = deviceIndex; break;
  197. case XRNode.LeftHand: leftIndex = deviceIndex; break;
  198. }
  199. IVRModuleDeviceState prevState;
  200. IVRModuleDeviceStateRW currState;
  201. EnsureValidDeviceState(deviceIndex, out prevState, out currState);
  202. if (m_rightIndex != rightIndex || m_leftIndex != leftIndex)
  203. {
  204. m_rightIndex = rightIndex;
  205. m_leftIndex = leftIndex;
  206. roleChanged = true;
  207. }
  208. if (!prevState.isConnected)
  209. {
  210. currState.isConnected = true;
  211. currState.deviceClass = s_nodeType2DeviceClass[(int)m_nodeStateList[i].nodeType];
  212. // FIXME: getting wrong name in Unity 2017.1f1
  213. //currDeviceState.serialNumber = InputTracking.GetNodeName(m_nodeStateList[i].uniqueID) ?? string.Empty;
  214. //Debug.Log("connected " + InputTracking.GetNodeName(m_nodeStateList[i].uniqueID));
  215. if (!XRDevice.model.Equals("None"))
  216. {
  217. currState.serialNumber = XRDevice.model + " " + m_nodeStateList[i].uniqueID.ToString("X8");
  218. currState.modelNumber = XRDevice.model + " " + m_nodeStateList[i].nodeType;
  219. currState.renderModelName = XRDevice.model + " " + m_nodeStateList[i].nodeType;
  220. }
  221. else
  222. {
  223. currState.serialNumber = XRSettings.loadedDeviceName + " " + m_nodeStateList[i].uniqueID.ToString("X8");
  224. currState.modelNumber = XRSettings.loadedDeviceName + " " + m_nodeStateList[i].nodeType;
  225. currState.renderModelName = XRSettings.loadedDeviceName + " " + m_nodeStateList[i].nodeType;
  226. }
  227. SetupKnownDeviceModel(currState);
  228. }
  229. // update device status
  230. currState.isPoseValid = m_nodeStateList[i].tracked;
  231. var velocity = default(Vector3);
  232. if (m_nodeStateList[i].TryGetVelocity(out velocity)) { currState.velocity = velocity; }
  233. var position = default(Vector3);
  234. if (m_nodeStateList[i].TryGetPosition(out position)) { currState.position = position; }
  235. var rotation = default(Quaternion);
  236. if (m_nodeStateList[i].TryGetRotation(out rotation)) { currState.rotation = rotation; }
  237. #if UNITY_2017_2_OR_NEWER
  238. var angularVelocity = default(Vector3);
  239. if (m_nodeStateList[i].TryGetAngularVelocity(out angularVelocity)) { currState.angularVelocity = angularVelocity; }
  240. #endif
  241. }
  242. m_nodeStateList.Clear();
  243. // update right hand input
  244. if (VRModule.IsValidDeviceIndex(rightIndex))
  245. {
  246. IVRModuleDeviceState rightPrevState;
  247. IVRModuleDeviceStateRW rightCurrState;
  248. EnsureValidDeviceState(rightIndex, out rightPrevState, out rightCurrState);
  249. UpdateRightControllerInput(rightPrevState, rightCurrState);
  250. }
  251. //// update left hand input
  252. if (VRModule.IsValidDeviceIndex(leftIndex))
  253. {
  254. IVRModuleDeviceState leftPrevState;
  255. IVRModuleDeviceStateRW leftCurrState;
  256. EnsureValidDeviceState(leftIndex, out leftPrevState, out leftCurrState);
  257. UpdateLeftControllerInput(leftPrevState, leftCurrState);
  258. }
  259. TrimUntouchedNodes(trimmedIndex =>
  260. {
  261. IVRModuleDeviceState ps;
  262. IVRModuleDeviceStateRW cs;
  263. if (TryGetValidDeviceState(trimmedIndex, out ps, out cs))
  264. {
  265. cs.Reset();
  266. }
  267. });
  268. ProcessConnectedDeviceChanged();
  269. if (roleChanged)
  270. {
  271. InvokeControllerRoleChangedEvent();
  272. }
  273. ProcessDevicePoseChanged();
  274. ProcessDeviceInputChanged();
  275. }
  276. #endif
  277. }
  278. }