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.

375 lines
14 KiB

5 years ago
  1. //========= Copyright 2016-2020, HTC Corporation. All rights reserved. ===========
  2. using HTC.UnityPlugin.Utility;
  3. using HTC.UnityPlugin.VRModuleManagement;
  4. using System;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. namespace HTC.UnityPlugin.Vive
  8. {
  9. /// <summary>
  10. /// Defines roles for those devices that have buttons
  11. /// </summary>
  12. [ViveRoleEnum((int)HandRole.Invalid)]
  13. public enum HandRole
  14. {
  15. Invalid = -1,
  16. RightHand,
  17. LeftHand,
  18. ExternalCamera,
  19. Controller3 = ExternalCamera,
  20. Controller4,
  21. Controller5,
  22. Controller6,
  23. Controller7,
  24. Controller8,
  25. Controller9,
  26. Controller10,
  27. Controller11,
  28. Controller12,
  29. Controller13,
  30. Controller14,
  31. Controller15,
  32. }
  33. public static class ConvertRoleExtension
  34. {
  35. [Obsolete("HandRole and DeviceRole are not related now")]
  36. public static DeviceRole ToDeviceRole(this HandRole role)
  37. {
  38. switch (role)
  39. {
  40. case HandRole.RightHand: return DeviceRole.RightHand;
  41. case HandRole.LeftHand: return DeviceRole.LeftHand;
  42. case HandRole.Controller3: return DeviceRole.Controller3;
  43. case HandRole.Controller4: return DeviceRole.Controller4;
  44. case HandRole.Controller5: return DeviceRole.Controller5;
  45. case HandRole.Controller6: return DeviceRole.Controller6;
  46. case HandRole.Controller7: return DeviceRole.Controller7;
  47. case HandRole.Controller8: return DeviceRole.Controller8;
  48. case HandRole.Controller9: return DeviceRole.Controller9;
  49. case HandRole.Controller10: return DeviceRole.Controller10;
  50. case HandRole.Controller11: return DeviceRole.Controller11;
  51. case HandRole.Controller12: return DeviceRole.Controller12;
  52. case HandRole.Controller13: return DeviceRole.Controller13;
  53. case HandRole.Controller14: return DeviceRole.Controller14;
  54. case HandRole.Controller15: return DeviceRole.Controller15;
  55. default: return (DeviceRole)((int)DeviceRole.Hmd - 1); // returns invalid value
  56. }
  57. }
  58. }
  59. public class HandRoleHandler : ViveRole.MapHandler<HandRole>
  60. {
  61. #if __VIU_STEAMVR
  62. private uint[] m_sortedDevices = new uint[VRModule.MAX_DEVICE_COUNT];
  63. #endif
  64. private List<uint> m_sortedDeviceList = new List<uint>();
  65. // HandRole only tracks controllers
  66. private bool IsController(uint deviceIndex)
  67. {
  68. return IsController(VRModule.GetCurrentDeviceState(deviceIndex).deviceClass);
  69. }
  70. private bool IsController(VRModuleDeviceClass deviceClass)
  71. {
  72. return deviceClass == VRModuleDeviceClass.Controller;
  73. }
  74. private bool IsTracker(uint deviceIndex)
  75. {
  76. return IsTracker(VRModule.GetCurrentDeviceState(deviceIndex).deviceClass);
  77. }
  78. private bool IsTracker(VRModuleDeviceClass deviceClass)
  79. {
  80. return deviceClass == VRModuleDeviceClass.GenericTracker;
  81. }
  82. public override void OnAssignedAsCurrentMapHandler() { Refresh(); }
  83. public override void OnTrackedDeviceRoleChanged() { Refresh(); }
  84. public override void OnConnectedDeviceChanged(uint deviceIndex, VRModuleDeviceClass deviceClass, string deviceSN, bool connected)
  85. {
  86. if (!RoleMap.IsDeviceBound(deviceSN) && !IsController(deviceClass) && !IsTracker(deviceClass)) { return; }
  87. Refresh();
  88. }
  89. public override void OnBindingChanged(string deviceSN, bool previousIsBound, HandRole previousRole, bool currentIsBound, HandRole currentRole)
  90. {
  91. uint deviceIndex;
  92. if (!VRModule.TryGetConnectedDeviceIndex(deviceSN, out deviceIndex)) { return; }
  93. Refresh();
  94. }
  95. public void Refresh()
  96. {
  97. MappingLeftRightHands();
  98. MappingOtherControllers();
  99. }
  100. private void MappingLeftRightHands()
  101. {
  102. // assign left/right controllers according to the hint
  103. var rightIndex = VRModule.GetRightControllerDeviceIndex();
  104. var leftIndex = VRModule.GetLeftControllerDeviceIndex();
  105. if (VRModule.GetCurrentDeviceState(rightIndex).isConnected)
  106. {
  107. MappingRoleIfUnbound(HandRole.RightHand, rightIndex);
  108. rightIndex = RoleMap.GetMappedDeviceByRole(HandRole.RightHand);
  109. }
  110. else if (RoleMap.IsRoleBound(HandRole.RightHand))
  111. {
  112. rightIndex = RoleMap.GetMappedDeviceByRole(HandRole.RightHand);
  113. }
  114. else
  115. {
  116. rightIndex = VRModule.INVALID_DEVICE_INDEX;
  117. }
  118. if (VRModule.GetCurrentDeviceState(leftIndex).isConnected && leftIndex != rightIndex)
  119. {
  120. MappingRoleIfUnbound(HandRole.LeftHand, leftIndex);
  121. leftIndex = RoleMap.GetMappedDeviceByRole(HandRole.LeftHand);
  122. }
  123. else if (RoleMap.IsRoleBound(HandRole.LeftHand))
  124. {
  125. leftIndex = RoleMap.GetMappedDeviceByRole(HandRole.LeftHand);
  126. }
  127. else
  128. {
  129. leftIndex = VRModule.INVALID_DEVICE_INDEX;
  130. }
  131. // if not both left/right controllers are assigned, find and assign them with left/right most controller
  132. if (!VRModule.IsValidDeviceIndex(rightIndex) || !VRModule.IsValidDeviceIndex(leftIndex))
  133. {
  134. // find right to left sorted controllers
  135. // FIXME: GetSortedTrackedDeviceIndicesOfClass doesn't return correct devices count right after device connected
  136. #if __VIU_STEAMVR
  137. if (VRModule.activeModule == SupportedVRModule.SteamVR)
  138. {
  139. var count = 0;
  140. var system = Valve.VR.OpenVR.System;
  141. if (system != null)
  142. {
  143. count = (int)system.GetSortedTrackedDeviceIndicesOfClass(Valve.VR.ETrackedDeviceClass.Controller, m_sortedDevices, Valve.VR.OpenVR.k_unTrackedDeviceIndex_Hmd);
  144. }
  145. foreach (var deviceIndex in m_sortedDevices)
  146. {
  147. if (m_sortedDeviceList.Count >= count) { break; }
  148. if (IsController(deviceIndex) && deviceIndex != rightIndex && deviceIndex != leftIndex && !RoleMap.IsDeviceConnectedAndBound(deviceIndex))
  149. {
  150. m_sortedDeviceList.Add(deviceIndex);
  151. }
  152. }
  153. }
  154. else
  155. #endif
  156. {
  157. for (uint deviceIndex = 1u, imax = VRModule.GetDeviceStateCount(); deviceIndex < imax; ++deviceIndex)
  158. {
  159. if (IsController(deviceIndex) && deviceIndex != rightIndex && deviceIndex != leftIndex && !RoleMap.IsDeviceConnectedAndBound(deviceIndex))
  160. {
  161. m_sortedDeviceList.Add(deviceIndex);
  162. }
  163. }
  164. if (m_sortedDeviceList.Count > 1)
  165. {
  166. SortDeviceIndicesByDirection(m_sortedDeviceList, VRModule.GetCurrentDeviceState(VRModule.HMD_DEVICE_INDEX).pose);
  167. }
  168. }
  169. if (m_sortedDeviceList.Count > 0 && !VRModule.IsValidDeviceIndex(rightIndex))
  170. {
  171. rightIndex = m_sortedDeviceList[0];
  172. m_sortedDeviceList.RemoveAt(0);
  173. // mapping right most controller
  174. MappingRole(HandRole.RightHand, rightIndex);
  175. }
  176. if (m_sortedDeviceList.Count > 0 && !VRModule.IsValidDeviceIndex(leftIndex))
  177. {
  178. leftIndex = m_sortedDeviceList[m_sortedDeviceList.Count - 1];
  179. // mapping left most controller
  180. MappingRole(HandRole.LeftHand, leftIndex);
  181. }
  182. m_sortedDeviceList.Clear();
  183. }
  184. if (!VRModule.IsValidDeviceIndex(rightIndex)) { UnmappingRole(HandRole.RightHand); }
  185. if (!VRModule.IsValidDeviceIndex(leftIndex)) { UnmappingRole(HandRole.LeftHand); }
  186. }
  187. private void MappingOtherControllers()
  188. {
  189. // mapping other controllers in order of device index
  190. var deviceIndex = 0u;
  191. var firstFoundTracker = VRModule.INVALID_DEVICE_INDEX;
  192. var rightIndex = RoleMap.GetMappedDeviceByRole(HandRole.RightHand);
  193. var leftIndex = RoleMap.GetMappedDeviceByRole(HandRole.LeftHand);
  194. for (var role = RoleInfo.MinValidRole; role <= RoleInfo.MaxValidRole; ++role)
  195. {
  196. if (!RoleInfo.IsValidRole(role)) { continue; }
  197. if (role == HandRole.RightHand || role == HandRole.LeftHand) { continue; }
  198. if (RoleMap.IsRoleBound(role)) { continue; }
  199. // find next valid device
  200. if (VRModule.IsValidDeviceIndex(deviceIndex))
  201. {
  202. while (!IsController(deviceIndex) || RoleMap.IsDeviceConnectedAndBound(deviceIndex) || deviceIndex == rightIndex || deviceIndex == leftIndex)
  203. {
  204. if (!VRModule.IsValidDeviceIndex(firstFoundTracker) && IsTracker(deviceIndex)) { firstFoundTracker = deviceIndex; }
  205. if (!VRModule.IsValidDeviceIndex(++deviceIndex)) { break; }
  206. }
  207. }
  208. if (VRModule.IsValidDeviceIndex(deviceIndex))
  209. {
  210. MappingRole(role, deviceIndex++);
  211. }
  212. else
  213. {
  214. UnmappingRole(role);
  215. }
  216. }
  217. // if external camera is not mapped, try mapping first found tracker
  218. if (!RoleMap.IsRoleMapped(HandRole.ExternalCamera) && VRModule.IsValidDeviceIndex(firstFoundTracker) && !RoleMap.IsDeviceConnectedAndBound(firstFoundTracker))
  219. {
  220. MappingRole(HandRole.ExternalCamera, firstFoundTracker);
  221. }
  222. }
  223. private static readonly float[] s_deviceDirPoint = new float[VRModule.MAX_DEVICE_COUNT];
  224. public static void SortDeviceIndicesByDirection(List<uint> deviceList, RigidPose sortingReference)
  225. {
  226. if (deviceList == null || deviceList.Count == 0) { return; }
  227. for (int i = 0, imax = deviceList.Count; i < imax; ++i)
  228. {
  229. var deviceIndex = deviceList[i];
  230. if (!VRModule.IsValidDeviceIndex(deviceIndex)) { continue; }
  231. var deviceState = VRModule.GetCurrentDeviceState(deviceIndex);
  232. if (deviceState.isConnected)
  233. {
  234. var localPos = sortingReference.InverseTransformPoint(deviceState.pose.pos);
  235. s_deviceDirPoint[deviceIndex] = GetDirectionPoint(new Vector2(localPos.x, localPos.z));
  236. }
  237. else
  238. {
  239. s_deviceDirPoint[deviceIndex] = -1f;
  240. }
  241. }
  242. deviceList.Sort(CompareDirection);
  243. }
  244. [Obsolete]
  245. public static void SortDeviceIndicesByDirection(List<uint> deviceList, PoseTracker.Pose sortingReference)
  246. {
  247. SortDeviceIndicesByDirection(deviceList, sortingReference);
  248. }
  249. private static int CompareDirection(uint d1, uint d2)
  250. {
  251. var d1Point = s_deviceDirPoint[d1];
  252. var d2Point = s_deviceDirPoint[d2];
  253. var d1Valid = VRModule.IsValidDeviceIndex(d1) && d1Point >= 0f;
  254. var d2Valid = VRModule.IsValidDeviceIndex(d2) && d2Point >= 0f;
  255. if (!d1Valid || !d2Valid)
  256. {
  257. if (d1Valid) { return -1; }
  258. if (d2Valid) { return 1; }
  259. if (d1 < d2) { return -1; }
  260. if (d1 > d2) { return 1; }
  261. return 0;
  262. }
  263. if (d1Point < d2Point) { return -1; }
  264. if (d1Point > d2Point) { return 1; }
  265. return 0;
  266. }
  267. // Y+
  268. // ||
  269. // \\ 4 || 3 //
  270. // \\ || //
  271. // 5 \\ ^^ // 2
  272. // =========[]========= X+
  273. // 6 // || \\ 1
  274. // // || \\
  275. // // 7 || 0 \\
  276. // ||
  277. // less point => right side
  278. public static float GetDirectionPoint(Vector2 pos)
  279. {
  280. var ax = Mathf.Abs(pos.x);
  281. var ay = Mathf.Abs(pos.y);
  282. if (pos.x > 0f)
  283. {
  284. if (pos.y < 0f)
  285. {
  286. if (ax < ay)
  287. {
  288. return 0f + (ax / ay);
  289. }
  290. else
  291. {
  292. return 1f + (1f - ay / ax);
  293. }
  294. }
  295. else
  296. {
  297. if (ax > ay)
  298. {
  299. return 2f + (ay / ax);
  300. }
  301. else
  302. {
  303. return 3f + (1f - ax / ay);
  304. }
  305. }
  306. }
  307. else
  308. {
  309. if (pos.y > 0f)
  310. {
  311. if (ax < ay)
  312. {
  313. return 4f + (ax / ay);
  314. }
  315. else
  316. {
  317. return 5f + (1f - ay / ax);
  318. }
  319. }
  320. else
  321. {
  322. if (ax > ay)
  323. {
  324. return 6f + (ay / ax);
  325. }
  326. else
  327. {
  328. return 7f + (1 - ax / ay);
  329. }
  330. }
  331. }
  332. }
  333. }
  334. }