comparison Orchestland/Assets/OVR/Scripts/OVRManager.cs @ 1:f7675884f2a1

Add Orchestland project
author Daiki OYAKAWA <e135764@ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2015 23:09:20 +0900
parents
children
comparison
equal deleted inserted replaced
0:347d21cdfc22 1:f7675884f2a1
1 /************************************************************************************
2
3 Copyright : Copyright 2014 Oculus VR, LLC. All Rights reserved.
4
5 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
6 you may not use the Oculus VR Rift SDK except in compliance with the License,
7 which is provided at the time of installation or download, or which
8 otherwise accompanies this software in either electronic or hard copy form.
9
10 You may obtain a copy of the License at
11
12 http://www.oculusvr.com/licenses/LICENSE-3.2
13
14 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19
20 ************************************************************************************/
21
22 using System;
23 using System.Collections;
24 using System.Runtime.InteropServices;
25 using System.Linq;
26 using System.Text.RegularExpressions;
27 using UnityEngine;
28 using Ovr;
29
30 /// <summary>
31 /// Configuration data for Oculus virtual reality.
32 /// </summary>
33 public class OVRManager : MonoBehaviour
34 {
35 /// <summary>
36 /// Contains information about the user's preferences and body dimensions.
37 /// </summary>
38 public struct Profile
39 {
40 public float ipd;
41 public float eyeHeight;
42 public float eyeDepth;
43 public float neckHeight;
44 }
45
46 /// <summary>
47 /// Gets the singleton instance.
48 /// </summary>
49 public static OVRManager instance { get; private set; }
50
51 /// <summary>
52 /// Gets a reference to the low-level C API Hmd Wrapper
53 /// </summary>
54 private static Hmd _capiHmd;
55 public static Hmd capiHmd
56 {
57 get {
58 #if !UNITY_ANDROID || UNITY_EDITOR
59 if (_capiHmd == null)
60 {
61 IntPtr hmdPtr = IntPtr.Zero;
62 OVR_GetHMD(ref hmdPtr);
63 _capiHmd = (hmdPtr != IntPtr.Zero) ? new Hmd(hmdPtr) : null;
64 }
65 #else
66 _capiHmd = null;
67 #endif
68 return _capiHmd;
69 }
70 }
71
72 /// <summary>
73 /// Gets a reference to the active OVRDisplay
74 /// </summary>
75 public static OVRDisplay display { get; private set; }
76
77 /// <summary>
78 /// Gets a reference to the active OVRTracker
79 /// </summary>
80 public static OVRTracker tracker { get; private set; }
81
82 /// <summary>
83 /// Gets the current profile, which contains information about the user's settings and body dimensions.
84 /// </summary>
85 private static bool _profileIsCached = false;
86 private static Profile _profile;
87 public static Profile profile
88 {
89 get {
90 if (!_profileIsCached)
91 {
92 #if !UNITY_ANDROID || UNITY_EDITOR
93 float ipd = capiHmd.GetFloat(Hmd.OVR_KEY_IPD, Hmd.OVR_DEFAULT_IPD);
94 float eyeHeight = capiHmd.GetFloat(Hmd.OVR_KEY_EYE_HEIGHT, Hmd.OVR_DEFAULT_EYE_HEIGHT);
95 float[] defaultOffset = new float[] { Hmd.OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, Hmd.OVR_DEFAULT_NECK_TO_EYE_VERTICAL };
96 float[] neckToEyeOffset = capiHmd.GetFloatArray(Hmd.OVR_KEY_NECK_TO_EYE_DISTANCE, defaultOffset);
97 float neckHeight = eyeHeight - neckToEyeOffset[1];
98
99 _profile = new Profile
100 {
101 ipd = ipd,
102 eyeHeight = eyeHeight,
103 eyeDepth = neckToEyeOffset[0],
104 neckHeight = neckHeight,
105 };
106 #else
107 float ipd = 0.0f;
108 OVR_GetInterpupillaryDistance(ref ipd);
109
110 float eyeHeight = 0.0f;
111 OVR_GetPlayerEyeHeight(ref eyeHeight);
112
113 _profile = new Profile
114 {
115 ipd = ipd,
116 eyeHeight = eyeHeight,
117 eyeDepth = 0f, //TODO
118 neckHeight = 0.0f, // TODO
119 };
120 #endif
121 _profileIsCached = true;
122 }
123
124 return _profile;
125 }
126 }
127
128 /// <summary>
129 /// Occurs when an HMD attached.
130 /// </summary>
131 public static event Action HMDAcquired;
132
133 /// <summary>
134 /// Occurs when an HMD detached.
135 /// </summary>
136 public static event Action HMDLost;
137
138 /// <summary>
139 /// Occurs when the tracker gained tracking.
140 /// </summary>
141 public static event Action TrackingAcquired;
142
143 /// <summary>
144 /// Occurs when the tracker lost tracking.
145 /// </summary>
146 public static event Action TrackingLost;
147
148 /// <summary>
149 /// Occurs when HSW dismissed.
150 /// </summary>
151 public static event Action HSWDismissed;
152
153 /// <summary>
154 /// If true, then the Oculus health and safety warning (HSW) is currently visible.
155 /// </summary>
156 public static bool isHSWDisplayed
157 {
158 get {
159 #if !UNITY_ANDROID || UNITY_EDITOR
160 return capiHmd.GetHSWDisplayState().Displayed;
161 #else
162 return false;
163 #endif
164 }
165 }
166
167 /// <summary>
168 /// If the HSW has been visible for the necessary amount of time, this will make it disappear.
169 /// </summary>
170 public static void DismissHSWDisplay()
171 {
172 #if !UNITY_ANDROID || UNITY_EDITOR
173 capiHmd.DismissHSWDisplay();
174 #endif
175 }
176
177 /// <summary>
178 /// Gets the current battery level.
179 /// </summary>
180 /// <returns><c>battery level in the range [0.0,1.0]</c>
181 /// <param name="batteryLevel">Battery level.</param>
182 public static float batteryLevel
183 {
184 get {
185 #if !UNITY_ANDROID || UNITY_EDITOR
186 return 1.0f;
187 #else
188 return OVR_GetBatteryLevel();
189 #endif
190 }
191 }
192
193 /// <summary>
194 /// Gets the current battery temperature.
195 /// </summary>
196 /// <returns><c>battery temperature in Celsius</c>
197 /// <param name="batteryTemperature">Battery temperature.</param>
198 public static float batteryTemperature
199 {
200 get {
201 #if !UNITY_ANDROID || UNITY_EDITOR
202 return 0.0f;
203 #else
204 return OVR_GetBatteryTemperature();
205 #endif
206 }
207 }
208
209 /// <summary>
210 /// Gets the current battery status.
211 /// </summary>
212 /// <returns><c>battery status</c>
213 /// <param name="batteryStatus">Battery status.</param>
214 public static int batteryStatus
215 {
216 get {
217 #if !UNITY_ANDROID || UNITY_EDITOR
218 return 0;
219 #else
220 return OVR_GetBatteryStatus();
221 #endif
222 }
223 }
224
225 /// <summary>
226 /// Controls the size of the eye textures.
227 /// Values must be above 0.
228 /// Values below 1 permit sub-sampling for improved performance.
229 /// Values above 1 permit super-sampling for improved sharpness.
230 /// </summary>
231 public float nativeTextureScale = 1.0f;
232
233 /// <summary>
234 /// Controls the size of the rendering viewport.
235 /// Values must be between 0 and 1.
236 /// Values below 1 permit dynamic sub-sampling for improved performance.
237 /// </summary>
238 public float virtualTextureScale = 1.0f;
239
240 /// <summary>
241 /// If true, head tracking will affect the orientation of each OVRCameraRig's cameras.
242 /// </summary>
243 public bool usePositionTracking = true;
244
245 /// <summary>
246 /// The format of each eye texture.
247 /// </summary>
248 public RenderTextureFormat eyeTextureFormat = RenderTextureFormat.Default;
249
250 /// <summary>
251 /// The depth of each eye texture in bits.
252 /// </summary>
253 public int eyeTextureDepth = 24;
254
255 /// <summary>
256 /// If true, TimeWarp will be used to correct the output of each OVRCameraRig for rotational latency.
257 /// </summary>
258 public bool timeWarp = true;
259
260 /// <summary>
261 /// If this is true and TimeWarp is true, each OVRCameraRig will stop tracking and only TimeWarp will respond to head motion.
262 /// </summary>
263 public bool freezeTimeWarp = false;
264
265 /// <summary>
266 /// If true, each scene load will cause the head pose to reset.
267 /// </summary>
268 public bool resetTrackerOnLoad = true;
269
270 /// <summary>
271 /// If true, the eyes see the same image, which is rendered only by the left camera.
272 /// </summary>
273 public bool monoscopic = false;
274
275 /// <summary>
276 /// True if the current platform supports virtual reality.
277 /// </summary>
278 public bool isSupportedPlatform { get; private set; }
279
280 private static bool usingPositionTracking = false;
281 private static bool wasHmdPresent = false;
282 private static bool wasPositionTracked = false;
283 private static WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
284
285 #if UNITY_ANDROID && !UNITY_EDITOR
286 // Get this from Unity on startup so we can call Activity java functions
287 private static bool androidJavaInit = false;
288 private static AndroidJavaObject activity;
289 private static AndroidJavaClass javaVrActivityClass;
290 internal static int timeWarpViewNumber = 0;
291 public static event Action OnCustomPostRender;
292 #else
293 private static bool ovrIsInitialized;
294 private static bool isQuitting;
295 #endif
296
297 public static bool isPaused
298 {
299 get { return _isPaused; }
300 set
301 {
302 #if UNITY_ANDROID && !UNITY_EDITOR
303 RenderEventType eventType = (value) ? RenderEventType.Pause : RenderEventType.Resume;
304 OVRPluginEvent.Issue(eventType);
305 #endif
306 _isPaused = value;
307 }
308 }
309 private static bool _isPaused;
310
311 #region Unity Messages
312
313 private void Awake()
314 {
315 // Only allow one instance at runtime.
316 if (instance != null)
317 {
318 enabled = false;
319 DestroyImmediate(this);
320 return;
321 }
322
323 instance = this;
324
325 #if !UNITY_ANDROID || UNITY_EDITOR
326 if (!ovrIsInitialized)
327 {
328 OVR_Initialize();
329 OVRPluginEvent.Issue(RenderEventType.Initialize);
330
331 ovrIsInitialized = true;
332 }
333
334 var netVersion = new System.Version(Ovr.Hmd.OVR_VERSION_STRING);
335 var ovrVersion = new System.Version(Ovr.Hmd.GetVersionString());
336 if (netVersion > ovrVersion)
337 Debug.LogWarning("Using an older version of LibOVR.");
338 #endif
339
340 // Detect whether this platform is a supported platform
341 RuntimePlatform currPlatform = Application.platform;
342 isSupportedPlatform |= currPlatform == RuntimePlatform.Android;
343 isSupportedPlatform |= currPlatform == RuntimePlatform.LinuxPlayer;
344 isSupportedPlatform |= currPlatform == RuntimePlatform.OSXEditor;
345 isSupportedPlatform |= currPlatform == RuntimePlatform.OSXPlayer;
346 isSupportedPlatform |= currPlatform == RuntimePlatform.WindowsEditor;
347 isSupportedPlatform |= currPlatform == RuntimePlatform.WindowsPlayer;
348 if (!isSupportedPlatform)
349 {
350 Debug.LogWarning("This platform is unsupported");
351 return;
352 }
353
354 #if UNITY_ANDROID && !UNITY_EDITOR
355 Application.targetFrameRate = 60;
356 // don't allow the app to run in the background
357 Application.runInBackground = false;
358 // Disable screen dimming
359 Screen.sleepTimeout = SleepTimeout.NeverSleep;
360
361 if (!androidJavaInit)
362 {
363 AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
364 activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
365 javaVrActivityClass = new AndroidJavaClass("com.oculusvr.vrlib.VrActivity");
366 // Prepare for the RenderThreadInit()
367 SetInitVariables(activity.GetRawObject(), javaVrActivityClass.GetRawClass());
368
369 androidJavaInit = true;
370 }
371
372 // We want to set up our touchpad messaging system
373 OVRTouchpad.Create();
374 // This will trigger the init on the render thread
375 InitRenderThread();
376 #else
377 SetEditorPlay(Application.isEditor);
378 #endif
379
380 if (display == null)
381 display = new OVRDisplay();
382 if (tracker == null)
383 tracker = new OVRTracker();
384
385 if (resetTrackerOnLoad)
386 display.RecenterPose();
387
388 // Except for D3D9, SDK rendering forces vsync unless you pass ovrHmdCap_NoVSync to Hmd.SetEnabledCaps().
389 if (timeWarp)
390 {
391 bool useUnityVSync = SystemInfo.graphicsDeviceVersion.Contains("Direct3D 9");
392 QualitySettings.vSyncCount = useUnityVSync ? 1 : 0;
393 }
394
395 #if (UNITY_STANDALONE_WIN && (UNITY_4_6 || UNITY_4_5))
396 bool unity_4_6 = false;
397 bool unity_4_5_2 = false;
398 bool unity_4_5_3 = false;
399 bool unity_4_5_4 = false;
400 bool unity_4_5_5 = false;
401
402 #if (UNITY_4_6)
403 unity_4_6 = true;
404 #elif (UNITY_4_5_2)
405 unity_4_5_2 = true;
406 #elif (UNITY_4_5_3)
407 unity_4_5_3 = true;
408 #elif (UNITY_4_5_4)
409 unity_4_5_4 = true;
410 #elif (UNITY_4_5_5)
411 unity_4_5_5 = true;
412 #endif
413
414 // Detect correct Unity releases which contain the fix for D3D11 exclusive mode.
415 string version = Application.unityVersion;
416 int releaseNumber;
417 bool releaseNumberFound = Int32.TryParse(Regex.Match(version, @"\d+$").Value, out releaseNumber);
418
419 // Exclusive mode was broken for D3D9 in Unity 4.5.2p2 - 4.5.4 and 4.6 builds prior to beta 21
420 bool unsupportedExclusiveModeD3D9 = (unity_4_6 && version.Last(char.IsLetter) == 'b' && releaseNumberFound && releaseNumber < 21)
421 || (unity_4_5_2 && version.Last(char.IsLetter) == 'p' && releaseNumberFound && releaseNumber >= 2)
422 || (unity_4_5_3)
423 || (unity_4_5_4);
424
425 // Exclusive mode was broken for D3D11 in Unity 4.5.2p2 - 4.5.5p2 and 4.6 builds prior to f1
426 bool unsupportedExclusiveModeD3D11 = (unity_4_6 && version.Last(char.IsLetter) == 'b')
427 || (unity_4_5_2 && version.Last(char.IsLetter) == 'p' && releaseNumberFound && releaseNumber >= 2)
428 || (unity_4_5_3)
429 || (unity_4_5_4)
430 || (unity_4_5_5 && version.Last(char.IsLetter) == 'f')
431 || (unity_4_5_5 && version.Last(char.IsLetter) == 'p' && releaseNumberFound && releaseNumber < 3);
432
433 if (unsupportedExclusiveModeD3D9 && !display.isDirectMode && SystemInfo.graphicsDeviceVersion.Contains("Direct3D 9"))
434 {
435 MessageBox(0, "Direct3D 9 extended mode is not supported in this configuration. "
436 + "Please use direct display mode, a different graphics API, or rebuild the application with a newer Unity version."
437 , "VR Configuration Warning", 0);
438 }
439
440 if (unsupportedExclusiveModeD3D11 && !display.isDirectMode && SystemInfo.graphicsDeviceVersion.Contains("Direct3D 11"))
441 {
442 MessageBox(0, "Direct3D 11 extended mode is not supported in this configuration. "
443 + "Please use direct display mode, a different graphics API, or rebuild the application with a newer Unity version."
444 , "VR Configuration Warning", 0);
445 }
446 #endif
447 }
448
449 #if !UNITY_ANDROID || UNITY_EDITOR
450 private void OnApplicationQuit()
451 {
452 isQuitting = true;
453 }
454
455 private void OnDisable()
456 {
457 if (!isQuitting)
458 return;
459
460 if (ovrIsInitialized)
461 {
462 OVR_Destroy();
463 OVRPluginEvent.Issue(RenderEventType.Destroy);
464 _capiHmd = null;
465
466 ovrIsInitialized = false;
467 }
468 }
469 #endif
470
471 private void Start()
472 {
473 #if !UNITY_ANDROID || UNITY_EDITOR
474 Camera cam = GetComponent<Camera>();
475 if (cam == null)
476 {
477 // Ensure there is a non-RT camera in the scene to force rendering of the left and right eyes.
478 cam = gameObject.AddComponent<Camera>();
479 cam.cullingMask = 0;
480 cam.clearFlags = CameraClearFlags.SolidColor;
481 cam.backgroundColor = new Color(0.0f, 0.0f, 0.0f);
482 cam.renderingPath = RenderingPath.Forward;
483 cam.orthographic = true;
484 cam.useOcclusionCulling = false;
485 }
486 #endif
487
488 bool isD3d = SystemInfo.graphicsDeviceVersion.Contains("Direct3D") ||
489 Application.platform == RuntimePlatform.WindowsEditor &&
490 SystemInfo.graphicsDeviceVersion.Contains("emulated");
491 display.flipInput = isD3d;
492
493 StartCoroutine(CallbackCoroutine());
494 }
495
496 private void Update()
497 {
498 if (usePositionTracking != usingPositionTracking)
499 {
500 tracker.isEnabled = usePositionTracking;
501 usingPositionTracking = usePositionTracking;
502 }
503
504 // Dispatch any events.
505 if (HMDLost != null && wasHmdPresent && !display.isPresent)
506 HMDLost();
507
508 if (HMDAcquired != null && !wasHmdPresent && display.isPresent)
509 HMDAcquired();
510
511 wasHmdPresent = display.isPresent;
512
513 if (TrackingLost != null && wasPositionTracked && !tracker.isPositionTracked)
514 TrackingLost();
515
516 if (TrackingAcquired != null && !wasPositionTracked && tracker.isPositionTracked)
517 TrackingAcquired();
518
519 wasPositionTracked = tracker.isPositionTracked;
520
521 if (isHSWDisplayed && Input.anyKeyDown)
522 {
523 DismissHSWDisplay();
524
525 if (HSWDismissed != null)
526 HSWDismissed();
527 }
528
529 display.timeWarp = timeWarp;
530
531 #if (!UNITY_ANDROID || UNITY_EDITOR)
532 display.Update();
533 #endif
534 }
535
536 #if (UNITY_EDITOR_OSX)
537 private void OnPreCull() // TODO: Fix Mac Unity Editor memory corruption issue requiring OnPreCull workaround.
538 #else
539 private void LateUpdate()
540 #endif
541 {
542 #if (!UNITY_ANDROID || UNITY_EDITOR)
543 display.BeginFrame();
544 #endif
545 }
546
547 private IEnumerator CallbackCoroutine()
548 {
549 while (true)
550 {
551 yield return waitForEndOfFrame;
552
553 #if UNITY_ANDROID && !UNITY_EDITOR
554 OVRManager.DoTimeWarp(timeWarpViewNumber);
555 #else
556 display.EndFrame();
557 #endif
558 }
559 }
560
561 #if UNITY_ANDROID && !UNITY_EDITOR
562 private void OnPause()
563 {
564 isPaused = true;
565 }
566
567 private void OnApplicationPause(bool pause)
568 {
569 Debug.Log("OnApplicationPause() " + pause);
570 if (pause)
571 {
572 OnPause();
573 }
574 else
575 {
576 StartCoroutine(OnResume());
577 }
578 }
579
580 void OnDisable()
581 {
582 StopAllCoroutines();
583 }
584
585 private IEnumerator OnResume()
586 {
587 yield return null; // delay 1 frame to allow Unity enough time to create the windowSurface
588
589 isPaused = false;
590 }
591
592 /// <summary>
593 /// Leaves the application/game and returns to the launcher/dashboard
594 /// </summary>
595 public void ReturnToLauncher()
596 {
597 // show the platform UI quit prompt
598 OVRManager.PlatformUIConfirmQuit();
599 }
600
601 private void OnPostRender()
602 {
603 // Allow custom code to render before we kick off the plugin
604 if (OnCustomPostRender != null)
605 {
606 OnCustomPostRender();
607 }
608
609 EndEye(OVREye.Left, display.GetEyeTextureId(OVREye.Left));
610 EndEye(OVREye.Right, display.GetEyeTextureId(OVREye.Right));
611 }
612 #endif
613 #endregion
614
615 public static void SetEditorPlay(bool isEditor)
616 {
617 #if !UNITY_ANDROID || UNITY_EDITOR
618 OVR_SetEditorPlay(isEditor);
619 #endif
620 }
621
622 public static void SetDistortionCaps(uint distortionCaps)
623 {
624 #if !UNITY_ANDROID || UNITY_EDITOR
625 OVR_SetDistortionCaps(distortionCaps);
626 #endif
627 }
628
629 public static void SetInitVariables(IntPtr activity, IntPtr vrActivityClass)
630 {
631 #if UNITY_ANDROID && !UNITY_EDITOR
632 OVR_SetInitVariables(activity, vrActivityClass);
633 #endif
634 }
635
636 public static void PlatformUIConfirmQuit()
637 {
638 #if UNITY_ANDROID && !UNITY_EDITOR
639 OVRPluginEvent.Issue(RenderEventType.PlatformUIConfirmQuit);
640 #endif
641 }
642
643 public static void PlatformUIGlobalMenu()
644 {
645 #if UNITY_ANDROID && !UNITY_EDITOR
646 OVRPluginEvent.Issue(RenderEventType.PlatformUI);
647 #endif
648 }
649
650 public static void DoTimeWarp(int timeWarpViewNumber)
651 {
652 #if UNITY_ANDROID && !UNITY_EDITOR
653 OVRPluginEvent.IssueWithData(RenderEventType.TimeWarp, timeWarpViewNumber);
654 #endif
655 }
656
657 public static void EndEye(OVREye eye, int eyeTextureId)
658 {
659 #if UNITY_ANDROID && !UNITY_EDITOR
660 RenderEventType eventType = (eye == OVREye.Left) ?
661 RenderEventType.LeftEyeEndFrame :
662 RenderEventType.RightEyeEndFrame;
663
664 OVRPluginEvent.IssueWithData(eventType, eyeTextureId);
665 #endif
666 }
667
668 public static void InitRenderThread()
669 {
670 #if UNITY_ANDROID && !UNITY_EDITOR
671 OVRPluginEvent.Issue(RenderEventType.InitRenderThread);
672 #endif
673 }
674
675 private const string LibOVR = "OculusPlugin";
676
677 #if !UNITY_ANDROID || UNITY_EDITOR
678 [DllImport(LibOVR, CallingConvention = CallingConvention.Cdecl)]
679 private static extern void OVR_GetHMD(ref IntPtr hmdPtr);
680 [DllImport(LibOVR, CallingConvention = CallingConvention.Cdecl)]
681 private static extern void OVR_SetEditorPlay(bool isEditorPlay);
682 [DllImport(LibOVR, CallingConvention = CallingConvention.Cdecl)]
683 private static extern void OVR_SetDistortionCaps(uint distortionCaps);
684 [DllImport(LibOVR, CallingConvention = CallingConvention.Cdecl)]
685 private static extern void OVR_Initialize();
686 [DllImport(LibOVR, CallingConvention = CallingConvention.Cdecl)]
687 private static extern void OVR_Destroy();
688
689 #if UNITY_STANDALONE_WIN
690 [DllImport("user32", EntryPoint = "MessageBoxA", CharSet = CharSet.Ansi)]
691 public static extern bool MessageBox(int hWnd,
692 [MarshalAs(UnmanagedType.LPStr)]string text,
693 [MarshalAs(UnmanagedType.LPStr)]string caption, uint type);
694 #endif
695
696 #else
697 [DllImport(LibOVR)]
698 private static extern void OVR_SetInitVariables(IntPtr activity, IntPtr vrActivityClass);
699 [DllImport(LibOVR)]
700 private static extern float OVR_GetBatteryLevel();
701 [DllImport(LibOVR)]
702 private static extern int OVR_GetBatteryStatus();
703 [DllImport(LibOVR)]
704 private static extern float OVR_GetBatteryTemperature();
705
706 [DllImport(LibOVR)]
707 private static extern bool OVR_GetPlayerEyeHeight(ref float eyeHeight);
708 [DllImport(LibOVR)]
709 private static extern bool OVR_GetInterpupillaryDistance(ref float interpupillaryDistance);
710 #endif
711 }