Assignment for RMIT Mixed Reality in 2020
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.

406 lines
9.8 KiB

  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: Player interface used to query HMD transforms and VR hands
  4. //
  5. //=============================================================================
  6. using UnityEngine;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. namespace Valve.VR.InteractionSystem
  10. {
  11. //-------------------------------------------------------------------------
  12. // Singleton representing the local VR player/user, with methods for getting
  13. // the player's hands, head, tracking origin, and guesses for various properties.
  14. //-------------------------------------------------------------------------
  15. public class Player : MonoBehaviour
  16. {
  17. [Tooltip( "Virtual transform corresponding to the meatspace tracking origin. Devices are tracked relative to this." )]
  18. public Transform trackingOriginTransform;
  19. [Tooltip( "List of possible transforms for the head/HMD, including the no-SteamVR fallback camera." )]
  20. public Transform[] hmdTransforms;
  21. [Tooltip( "List of possible Hands, including no-SteamVR fallback Hands." )]
  22. public Hand[] hands;
  23. [Tooltip( "Reference to the physics collider that follows the player's HMD position." )]
  24. public Collider headCollider;
  25. [Tooltip( "These objects are enabled when SteamVR is available" )]
  26. public GameObject rigSteamVR;
  27. [Tooltip( "These objects are enabled when SteamVR is not available, or when the user toggles out of VR" )]
  28. public GameObject rig2DFallback;
  29. [Tooltip( "The audio listener for this player" )]
  30. public Transform audioListener;
  31. public bool allowToggleTo2D = true;
  32. //-------------------------------------------------
  33. // Singleton instance of the Player. Only one can exist at a time.
  34. //-------------------------------------------------
  35. private static Player _instance;
  36. public static Player instance
  37. {
  38. get
  39. {
  40. if ( _instance == null )
  41. {
  42. _instance = FindObjectOfType<Player>();
  43. }
  44. return _instance;
  45. }
  46. }
  47. //-------------------------------------------------
  48. // Get the number of active Hands.
  49. //-------------------------------------------------
  50. public int handCount
  51. {
  52. get
  53. {
  54. int count = 0;
  55. for ( int i = 0; i < hands.Length; i++ )
  56. {
  57. if ( hands[i].gameObject.activeInHierarchy )
  58. {
  59. count++;
  60. }
  61. }
  62. return count;
  63. }
  64. }
  65. //-------------------------------------------------
  66. // Get the i-th active Hand.
  67. //
  68. // i - Zero-based index of the active Hand to get
  69. //-------------------------------------------------
  70. public Hand GetHand( int i )
  71. {
  72. for ( int j = 0; j < hands.Length; j++ )
  73. {
  74. if ( !hands[j].gameObject.activeInHierarchy )
  75. {
  76. continue;
  77. }
  78. if ( i > 0 )
  79. {
  80. i--;
  81. continue;
  82. }
  83. return hands[j];
  84. }
  85. return null;
  86. }
  87. //-------------------------------------------------
  88. public Hand leftHand
  89. {
  90. get
  91. {
  92. for ( int j = 0; j < hands.Length; j++ )
  93. {
  94. if ( !hands[j].gameObject.activeInHierarchy )
  95. {
  96. continue;
  97. }
  98. if ( hands[j].GuessCurrentHandType() != Hand.HandType.Left )
  99. {
  100. continue;
  101. }
  102. return hands[j];
  103. }
  104. return null;
  105. }
  106. }
  107. //-------------------------------------------------
  108. public Hand rightHand
  109. {
  110. get
  111. {
  112. for ( int j = 0; j < hands.Length; j++ )
  113. {
  114. if ( !hands[j].gameObject.activeInHierarchy )
  115. {
  116. continue;
  117. }
  118. if ( hands[j].GuessCurrentHandType() != Hand.HandType.Right )
  119. {
  120. continue;
  121. }
  122. return hands[j];
  123. }
  124. return null;
  125. }
  126. }
  127. //-------------------------------------------------
  128. public SteamVR_Controller.Device leftController
  129. {
  130. get
  131. {
  132. Hand h = leftHand;
  133. if ( h )
  134. {
  135. return h.controller;
  136. }
  137. return null;
  138. }
  139. }
  140. //-------------------------------------------------
  141. public SteamVR_Controller.Device rightController
  142. {
  143. get
  144. {
  145. Hand h = rightHand;
  146. if ( h )
  147. {
  148. return h.controller;
  149. }
  150. return null;
  151. }
  152. }
  153. //-------------------------------------------------
  154. // Get the HMD transform. This might return the fallback camera transform if SteamVR is unavailable or disabled.
  155. //-------------------------------------------------
  156. public Transform hmdTransform
  157. {
  158. get
  159. {
  160. for ( int i = 0; i < hmdTransforms.Length; i++ )
  161. {
  162. if ( hmdTransforms[i].gameObject.activeInHierarchy )
  163. return hmdTransforms[i];
  164. }
  165. return null;
  166. }
  167. }
  168. //-------------------------------------------------
  169. // Height of the eyes above the ground - useful for estimating player height.
  170. //-------------------------------------------------
  171. public float eyeHeight
  172. {
  173. get
  174. {
  175. Transform hmd = hmdTransform;
  176. if ( hmd )
  177. {
  178. Vector3 eyeOffset = Vector3.Project( hmd.position - trackingOriginTransform.position, trackingOriginTransform.up );
  179. return eyeOffset.magnitude / trackingOriginTransform.lossyScale.x;
  180. }
  181. return 0.0f;
  182. }
  183. }
  184. //-------------------------------------------------
  185. // Guess for the world-space position of the player's feet, directly beneath the HMD.
  186. //-------------------------------------------------
  187. public Vector3 feetPositionGuess
  188. {
  189. get
  190. {
  191. Transform hmd = hmdTransform;
  192. if ( hmd )
  193. {
  194. return trackingOriginTransform.position + Vector3.ProjectOnPlane( hmd.position - trackingOriginTransform.position, trackingOriginTransform.up );
  195. }
  196. return trackingOriginTransform.position;
  197. }
  198. }
  199. //-------------------------------------------------
  200. // Guess for the world-space direction of the player's hips/torso. This is effectively just the gaze direction projected onto the floor plane.
  201. //-------------------------------------------------
  202. public Vector3 bodyDirectionGuess
  203. {
  204. get
  205. {
  206. Transform hmd = hmdTransform;
  207. if ( hmd )
  208. {
  209. Vector3 direction = Vector3.ProjectOnPlane( hmd.forward, trackingOriginTransform.up );
  210. if ( Vector3.Dot( hmd.up, trackingOriginTransform.up ) < 0.0f )
  211. {
  212. // The HMD is upside-down. Either
  213. // -The player is bending over backwards
  214. // -The player is bent over looking through their legs
  215. direction = -direction;
  216. }
  217. return direction;
  218. }
  219. return trackingOriginTransform.forward;
  220. }
  221. }
  222. //-------------------------------------------------
  223. void Awake()
  224. {
  225. if ( trackingOriginTransform == null )
  226. {
  227. trackingOriginTransform = this.transform;
  228. }
  229. }
  230. //-------------------------------------------------
  231. void OnEnable()
  232. {
  233. _instance = this;
  234. if ( SteamVR.instance != null )
  235. {
  236. ActivateRig( rigSteamVR );
  237. }
  238. else
  239. {
  240. #if !HIDE_DEBUG_UI
  241. ActivateRig( rig2DFallback );
  242. #endif
  243. }
  244. }
  245. //-------------------------------------------------
  246. void OnDrawGizmos()
  247. {
  248. if ( this != instance )
  249. {
  250. return;
  251. }
  252. //NOTE: These gizmo icons don't work in the plugin since the icons need to exist in a specific "Gizmos"
  253. // folder in your Asset tree. These icons are included under Core/Icons. Moving them into a
  254. // "Gizmos" folder should make them work again.
  255. Gizmos.color = Color.white;
  256. Gizmos.DrawIcon( feetPositionGuess, "vr_interaction_system_feet.png" );
  257. Gizmos.color = Color.cyan;
  258. Gizmos.DrawLine( feetPositionGuess, feetPositionGuess + trackingOriginTransform.up * eyeHeight );
  259. // Body direction arrow
  260. Gizmos.color = Color.blue;
  261. Vector3 bodyDirection = bodyDirectionGuess;
  262. Vector3 bodyDirectionTangent = Vector3.Cross( trackingOriginTransform.up, bodyDirection );
  263. Vector3 startForward = feetPositionGuess + trackingOriginTransform.up * eyeHeight * 0.75f;
  264. Vector3 endForward = startForward + bodyDirection * 0.33f;
  265. Gizmos.DrawLine( startForward, endForward );
  266. Gizmos.DrawLine( endForward, endForward - 0.033f * ( bodyDirection + bodyDirectionTangent ) );
  267. Gizmos.DrawLine( endForward, endForward - 0.033f * ( bodyDirection - bodyDirectionTangent ) );
  268. Gizmos.color = Color.red;
  269. int count = handCount;
  270. for ( int i = 0; i < count; i++ )
  271. {
  272. Hand hand = GetHand( i );
  273. if ( hand.startingHandType == Hand.HandType.Left )
  274. {
  275. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_left_hand.png" );
  276. }
  277. else if ( hand.startingHandType == Hand.HandType.Right )
  278. {
  279. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_right_hand.png" );
  280. }
  281. else
  282. {
  283. Hand.HandType guessHandType = hand.GuessCurrentHandType();
  284. if ( guessHandType == Hand.HandType.Left )
  285. {
  286. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_left_hand_question.png" );
  287. }
  288. else if ( guessHandType == Hand.HandType.Right )
  289. {
  290. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_right_hand_question.png" );
  291. }
  292. else
  293. {
  294. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_unknown_hand.png" );
  295. }
  296. }
  297. }
  298. }
  299. //-------------------------------------------------
  300. public void Draw2DDebug()
  301. {
  302. if ( !allowToggleTo2D )
  303. return;
  304. if ( !SteamVR.active )
  305. return;
  306. int width = 100;
  307. int height = 25;
  308. int left = Screen.width / 2 - width / 2;
  309. int top = Screen.height - height - 10;
  310. string text = ( rigSteamVR.activeSelf ) ? "2D Debug" : "VR";
  311. if ( GUI.Button( new Rect( left, top, width, height ), text ) )
  312. {
  313. if ( rigSteamVR.activeSelf )
  314. {
  315. ActivateRig( rig2DFallback );
  316. }
  317. else
  318. {
  319. ActivateRig( rigSteamVR );
  320. }
  321. }
  322. }
  323. //-------------------------------------------------
  324. private void ActivateRig( GameObject rig )
  325. {
  326. rigSteamVR.SetActive( rig == rigSteamVR );
  327. rig2DFallback.SetActive( rig == rig2DFallback );
  328. if ( audioListener )
  329. {
  330. audioListener.transform.parent = hmdTransform;
  331. audioListener.transform.localPosition = Vector3.zero;
  332. audioListener.transform.localRotation = Quaternion.identity;
  333. }
  334. }
  335. //-------------------------------------------------
  336. public void PlayerShotSelf()
  337. {
  338. //Do something appropriate here
  339. }
  340. }
  341. }