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.

437 lines
17 KiB

5 years ago
  1. //========= Copyright 2016-2020, HTC Corporation. All rights reserved. ===========
  2. using HTC.UnityPlugin.Utility;
  3. #if VIU_STEAMVR && UNITY_STANDALONE
  4. using HTC.UnityPlugin.Vive;
  5. using HTC.UnityPlugin.Vive.SteamVRExtension;
  6. using System.Text;
  7. using UnityEngine;
  8. using Valve.VR;
  9. #if UNITY_2017_2_OR_NEWER
  10. using UnityEngine.XR;
  11. #elif UNITY_5_4_OR_NEWER
  12. using XRSettings = UnityEngine.VR.VRSettings;
  13. #endif
  14. #endif
  15. namespace HTC.UnityPlugin.VRModuleManagement
  16. {
  17. public partial class VRModule : SingletonBehaviour<VRModule>
  18. {
  19. public static readonly bool isSteamVRPluginDetected =
  20. #if VIU_STEAMVR
  21. true;
  22. #else
  23. false;
  24. #endif
  25. public static readonly bool isOpenVRSupported =
  26. #if VIU_OPENVR_SUPPORT
  27. true;
  28. #else
  29. false;
  30. #endif
  31. }
  32. public sealed partial class SteamVRModule : VRModule.ModuleBase
  33. {
  34. public override int moduleOrder { get { return (int)DefaultModuleOrder.SteamVR; } }
  35. public override int moduleIndex { get { return (int)VRModuleSelectEnum.SteamVR; } }
  36. #if VIU_STEAMVR && UNITY_STANDALONE
  37. private class CameraCreator : VRCameraHook.CameraCreator
  38. {
  39. public override bool shouldActive { get { return s_moduleInstance == null ? false : s_moduleInstance.isActivated; } }
  40. public override void CreateCamera(VRCameraHook hook)
  41. {
  42. #if UNITY_2019_3_OR_NEWER && VIU_XR_GENERAL_SETTINGS
  43. if (hook.GetComponent<UnityEngine.SpatialTracking.TrackedPoseDriver>() == null)
  44. {
  45. hook.gameObject.AddComponent<UnityEngine.SpatialTracking.TrackedPoseDriver>();
  46. }
  47. #else
  48. if (hook.GetComponent<SteamVR_Camera>() == null)
  49. {
  50. hook.gameObject.AddComponent<SteamVR_Camera>();
  51. }
  52. #endif
  53. }
  54. }
  55. private class RenderModelCreator : RenderModelHook.RenderModelCreator
  56. {
  57. private uint m_index = INVALID_DEVICE_INDEX;
  58. private VIUSteamVRRenderModel m_model;
  59. public override bool shouldActive { get { return s_moduleInstance == null ? false : s_moduleInstance.isActivated; } }
  60. public override void UpdateRenderModel()
  61. {
  62. if (!ChangeProp.Set(ref m_index, hook.GetModelDeviceIndex())) { return; }
  63. if (VRModule.IsValidDeviceIndex(m_index))
  64. {
  65. // create object for render model
  66. if (m_model == null)
  67. {
  68. var go = new GameObject("Model");
  69. go.transform.SetParent(hook.transform, false);
  70. m_model = go.AddComponent<VIUSteamVRRenderModel>();
  71. }
  72. // set render model index
  73. m_model.gameObject.SetActive(true);
  74. m_model.shaderOverride = hook.overrideShader;
  75. m_model.SetDeviceIndex(m_index);
  76. }
  77. else
  78. {
  79. // deacitvate object for render model
  80. if (m_model != null)
  81. {
  82. m_model.gameObject.SetActive(false);
  83. }
  84. }
  85. }
  86. public override void CleanUpRenderModel()
  87. {
  88. if (m_model != null)
  89. {
  90. Object.Destroy(m_model.gameObject);
  91. m_model = null;
  92. m_index = INVALID_DEVICE_INDEX;
  93. }
  94. }
  95. }
  96. private static SteamVRModule s_moduleInstance;
  97. #endif
  98. #if VIU_STEAMVR && !VIU_STEAMVR_2_0_0_OR_NEWER
  99. private static readonly uint s_sizeOfControllerStats = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t));
  100. private ETrackingUniverseOrigin m_prevTrackingSpace;
  101. private bool m_hasInputFocus = true;
  102. public override bool ShouldActiveModule()
  103. {
  104. #if UNITY_5_4_OR_NEWER
  105. return VIUSettings.activateSteamVRModule && XRSettings.enabled && XRSettings.loadedDeviceName == "OpenVR";
  106. #else
  107. return VIUSettings.activateSteamVRModule && SteamVR.enabled;
  108. #endif
  109. }
  110. public override void OnActivated()
  111. {
  112. // Make sure SteamVR_Render instance exist. It Polls New Poses Event
  113. if (SteamVR_Render.instance == null) { }
  114. // setup tracking space
  115. m_prevTrackingSpace = trackingSpace;
  116. UpdateTrackingSpaceType();
  117. EnsureDeviceStateLength(OpenVR.k_unMaxTrackedDeviceCount);
  118. m_hasInputFocus = inputFocus;
  119. #if VIU_STEAMVR_1_2_1_OR_NEWER
  120. SteamVR_Events.NewPoses.AddListener(OnSteamVRNewPose);
  121. SteamVR_Events.InputFocus.AddListener(OnInputFocus);
  122. SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).AddListener(OnTrackedDeviceRoleChanged);
  123. #elif VIU_STEAMVR_1_2_0_OR_NEWER
  124. SteamVR_Events.NewPoses.AddListener(OnSteamVRNewPose);
  125. SteamVR_Events.InputFocus.AddListener(OnInputFocus);
  126. SteamVR_Events.System("TrackedDeviceRoleChanged").AddListener(OnTrackedDeviceRoleChanged);
  127. #elif VIU_STEAMVR_1_1_1
  128. SteamVR_Utils.Event.Listen("new_poses", OnSteamVRNewPoseArgs);
  129. SteamVR_Utils.Event.Listen("input_focus", OnInputFocusArgs);
  130. SteamVR_Utils.Event.Listen("TrackedDeviceRoleChanged", OnTrackedDeviceRoleChangedArgs);
  131. #endif
  132. s_moduleInstance = this;
  133. }
  134. public override void OnDeactivated()
  135. {
  136. trackingSpace = m_prevTrackingSpace;
  137. #if VIU_STEAMVR_1_2_1_OR_NEWER
  138. SteamVR_Events.NewPoses.RemoveListener(OnSteamVRNewPose);
  139. SteamVR_Events.InputFocus.RemoveListener(OnInputFocus);
  140. SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).RemoveListener(OnTrackedDeviceRoleChanged);
  141. #elif VIU_STEAMVR_1_2_0_OR_NEWER
  142. SteamVR_Events.NewPoses.RemoveListener(OnSteamVRNewPose);
  143. SteamVR_Events.InputFocus.RemoveListener(OnInputFocus);
  144. SteamVR_Events.System("TrackedDeviceRoleChanged").RemoveListener(OnTrackedDeviceRoleChanged);
  145. #elif VIU_STEAMVR_1_1_1
  146. SteamVR_Utils.Event.Remove("new_poses", OnSteamVRNewPoseArgs);
  147. SteamVR_Utils.Event.Remove("input_focus", OnInputFocusArgs);
  148. SteamVR_Utils.Event.Remove("TrackedDeviceRoleChanged", OnTrackedDeviceRoleChangedArgs);
  149. #endif
  150. s_moduleInstance = null;
  151. }
  152. public override void Update()
  153. {
  154. if (SteamVR.active)
  155. {
  156. SteamVR_Render.instance.lockPhysicsUpdateRateToRenderFrequency = VRModule.lockPhysicsUpdateRateToRenderFrequency;
  157. }
  158. UpdateDeviceInput();
  159. ProcessDeviceInputChanged();
  160. }
  161. private void UpdateConnectedDevice(TrackedDevicePose_t[] poses)
  162. {
  163. IVRModuleDeviceState prevState;
  164. IVRModuleDeviceStateRW currState;
  165. var system = OpenVR.System;
  166. if (system == null)
  167. {
  168. for (uint i = 0, imax = GetDeviceStateLength(); i < imax; ++i)
  169. {
  170. if (TryGetValidDeviceState(i, out prevState, out currState) && currState.isConnected)
  171. {
  172. currState.Reset();
  173. }
  174. }
  175. return;
  176. }
  177. for (uint i = 0u, imax = (uint)poses.Length; i < imax; ++i)
  178. {
  179. if (!poses[i].bDeviceIsConnected)
  180. {
  181. if (TryGetValidDeviceState(i, out prevState, out currState) && prevState.isConnected)
  182. {
  183. currState.Reset();
  184. }
  185. }
  186. else
  187. {
  188. EnsureValidDeviceState(i, out prevState, out currState);
  189. if (!prevState.isConnected)
  190. {
  191. currState.isConnected = true;
  192. currState.deviceClass = (VRModuleDeviceClass)system.GetTrackedDeviceClass(i);
  193. currState.serialNumber = QueryDeviceStringProperty(system, i, ETrackedDeviceProperty.Prop_SerialNumber_String);
  194. currState.modelNumber = QueryDeviceStringProperty(system, i, ETrackedDeviceProperty.Prop_ModelNumber_String);
  195. currState.renderModelName = QueryDeviceStringProperty(system, i, ETrackedDeviceProperty.Prop_RenderModelName_String);
  196. SetupKnownDeviceModel(currState);
  197. }
  198. }
  199. }
  200. }
  201. private void UpdateDevicePose(TrackedDevicePose_t[] poses)
  202. {
  203. IVRModuleDeviceState prevState;
  204. IVRModuleDeviceStateRW currState;
  205. for (uint i = 0u, imax = (uint)poses.Length; i < imax; ++i)
  206. {
  207. if (!TryGetValidDeviceState(i, out prevState, out currState) || !currState.isConnected) { continue; }
  208. // update device status
  209. currState.isPoseValid = poses[i].bPoseIsValid;
  210. currState.isOutOfRange = poses[i].eTrackingResult == ETrackingResult.Running_OutOfRange || poses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange;
  211. currState.isCalibrating = poses[i].eTrackingResult == ETrackingResult.Calibrating_InProgress || poses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange;
  212. currState.isUninitialized = poses[i].eTrackingResult == ETrackingResult.Uninitialized;
  213. currState.velocity = new Vector3(poses[i].vVelocity.v0, poses[i].vVelocity.v1, -poses[i].vVelocity.v2);
  214. currState.angularVelocity = new Vector3(-poses[i].vAngularVelocity.v0, -poses[i].vAngularVelocity.v1, poses[i].vAngularVelocity.v2);
  215. // update poses
  216. if (poses[i].bPoseIsValid)
  217. {
  218. var rigidTransform = new SteamVR_Utils.RigidTransform(poses[i].mDeviceToAbsoluteTracking);
  219. currState.position = rigidTransform.pos;
  220. currState.rotation = rigidTransform.rot;
  221. }
  222. else if (prevState.isPoseValid)
  223. {
  224. currState.pose = RigidPose.identity;
  225. }
  226. }
  227. }
  228. private void UpdateDeviceInput()
  229. {
  230. IVRModuleDeviceState prevState;
  231. IVRModuleDeviceStateRW currState;
  232. VRControllerState_t ctrlState;
  233. var system = OpenVR.System;
  234. for (uint i = 0; i < OpenVR.k_unMaxTrackedDeviceCount; ++i)
  235. {
  236. if (!TryGetValidDeviceState(i, out prevState, out currState) || !currState.isConnected) { continue; }
  237. // get device state from openvr api
  238. GetConrollerState(system, i, out ctrlState);
  239. // update device input button
  240. currState.buttonPressed = ctrlState.ulButtonPressed;
  241. currState.buttonTouched = ctrlState.ulButtonTouched;
  242. // update device input axis
  243. currState.SetAxisValue(VRModuleRawAxis.Axis0X, ctrlState.rAxis0.x);
  244. currState.SetAxisValue(VRModuleRawAxis.Axis0Y, ctrlState.rAxis0.y);
  245. currState.SetAxisValue(VRModuleRawAxis.Axis1X, ctrlState.rAxis1.x);
  246. currState.SetAxisValue(VRModuleRawAxis.Axis1Y, ctrlState.rAxis1.y);
  247. currState.SetAxisValue(VRModuleRawAxis.Axis2X, ctrlState.rAxis2.x);
  248. currState.SetAxisValue(VRModuleRawAxis.Axis2Y, ctrlState.rAxis2.y);
  249. currState.SetAxisValue(VRModuleRawAxis.Axis3X, ctrlState.rAxis3.x);
  250. currState.SetAxisValue(VRModuleRawAxis.Axis3Y, ctrlState.rAxis3.y);
  251. currState.SetAxisValue(VRModuleRawAxis.Axis4X, ctrlState.rAxis4.x);
  252. currState.SetAxisValue(VRModuleRawAxis.Axis4Y, ctrlState.rAxis4.y);
  253. }
  254. }
  255. private void UpdateInputFocusState()
  256. {
  257. if (ChangeProp.Set(ref m_hasInputFocus, inputFocus))
  258. {
  259. InvokeInputFocusEvent(m_hasInputFocus);
  260. }
  261. }
  262. private static ETrackingUniverseOrigin trackingSpace
  263. {
  264. get
  265. {
  266. var compositor = OpenVR.Compositor;
  267. if (compositor == null) { return default(ETrackingUniverseOrigin); }
  268. return compositor.GetTrackingSpace();
  269. }
  270. set
  271. {
  272. var compositor = OpenVR.Compositor;
  273. if (compositor == null) { return; }
  274. compositor.SetTrackingSpace(value);
  275. }
  276. }
  277. private static bool inputFocus
  278. {
  279. get
  280. {
  281. var system = OpenVR.System;
  282. if (system == null) { return false; }
  283. #if VIU_STEAMVR_1_2_3_OR_NEWER
  284. return system.IsInputAvailable();
  285. #else
  286. return !system.IsInputFocusCapturedByAnotherProcess();
  287. #endif
  288. }
  289. }
  290. public override void UpdateTrackingSpaceType()
  291. {
  292. switch (VRModule.trackingSpaceType)
  293. {
  294. case VRModuleTrackingSpaceType.RoomScale:
  295. trackingSpace = ETrackingUniverseOrigin.TrackingUniverseStanding;
  296. break;
  297. case VRModuleTrackingSpaceType.Stationary:
  298. trackingSpace = ETrackingUniverseOrigin.TrackingUniverseSeated;
  299. break;
  300. }
  301. }
  302. private static void GetConrollerState(CVRSystem system, uint index, out VRControllerState_t ctrlState)
  303. {
  304. ctrlState = default(VRControllerState_t);
  305. if (system != null)
  306. {
  307. #if VIU_STEAMVR_1_2_0_OR_NEWER
  308. system.GetControllerState(index, ref ctrlState, s_sizeOfControllerStats);
  309. #else
  310. system.GetControllerState(index, ref ctrlState);
  311. #endif
  312. }
  313. }
  314. private void OnSteamVRNewPoseArgs(params object[] args) { OnSteamVRNewPose((TrackedDevicePose_t[])args[0]); }
  315. private void OnSteamVRNewPose(TrackedDevicePose_t[] poses)
  316. {
  317. FlushDeviceState();
  318. UpdateConnectedDevice(poses);
  319. ProcessConnectedDeviceChanged();
  320. UpdateDevicePose(poses);
  321. ProcessDevicePoseChanged();
  322. UpdateInputFocusState();
  323. }
  324. private void OnInputFocusArgs(params object[] args) { OnInputFocus((bool)args[0]); }
  325. private void OnInputFocus(bool value)
  326. {
  327. m_hasInputFocus = value;
  328. InvokeInputFocusEvent(value);
  329. }
  330. private void OnTrackedDeviceRoleChangedArgs(params object[] args) { OnTrackedDeviceRoleChanged((VREvent_t)args[0]); }
  331. private void OnTrackedDeviceRoleChanged(VREvent_t arg)
  332. {
  333. InvokeControllerRoleChangedEvent();
  334. }
  335. public override bool HasInputFocus()
  336. {
  337. return m_hasInputFocus;
  338. }
  339. public override uint GetLeftControllerDeviceIndex()
  340. {
  341. var system = OpenVR.System;
  342. return system == null ? INVALID_DEVICE_INDEX : system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
  343. }
  344. public override uint GetRightControllerDeviceIndex()
  345. {
  346. var system = OpenVR.System;
  347. return system == null ? INVALID_DEVICE_INDEX : system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand);
  348. }
  349. public override void TriggerViveControllerHaptic(uint deviceIndex, ushort durationMicroSec = 500)
  350. {
  351. var system = OpenVR.System;
  352. if (system != null)
  353. {
  354. system.TriggerHapticPulse(deviceIndex, (uint)EVRButtonId.k_EButton_SteamVR_Touchpad - (uint)EVRButtonId.k_EButton_Axis0, (char)durationMicroSec);
  355. }
  356. }
  357. private StringBuilder m_sb;
  358. private string QueryDeviceStringProperty(CVRSystem system, uint deviceIndex, ETrackedDeviceProperty prop)
  359. {
  360. var error = default(ETrackedPropertyError);
  361. var capacity = (int)system.GetStringTrackedDeviceProperty(deviceIndex, prop, null, 0, ref error);
  362. if (capacity <= 1 || capacity > 128) { return string.Empty; }
  363. if (m_sb == null) { m_sb = new StringBuilder(capacity); }
  364. else { m_sb.EnsureCapacity(capacity); }
  365. system.GetStringTrackedDeviceProperty(deviceIndex, prop, m_sb, (uint)m_sb.Capacity, ref error);
  366. if (error != ETrackedPropertyError.TrackedProp_Success) { return string.Empty; }
  367. var result = m_sb.ToString();
  368. m_sb.Length = 0;
  369. return result;
  370. }
  371. #endif
  372. }
  373. }