private static bool CompositorReadyCheck() { var isCompositorReady = false; UnityFuncs.IsCompositorReady(ref isCompositorReady); return(isCompositorReady); }
internal static void UnregisterInterface(FoveInterface xface) { var unregisteredMatch = m_sUnregisteredInterfaces.FirstOrDefault(i => i.xface == xface); if (unregisteredMatch != null) { m_sUnregisteredInterfaces.Remove(unregisteredMatch); } var layerIds = m_sInterfaceStacks.Keys.ToList(); foreach (var layerId in layerIds) { var interfaces = m_sInterfaceStacks[layerId]; var registeredMatch = interfaces.FirstOrDefault(i => i.xface == xface); if (registeredMatch != null) { interfaces.Remove(registeredMatch); } if (interfaces.Count == 0) { UnityFuncs.DeleteLayer(layerId); m_sInterfaceStacks.Remove(layerId); } } }
private static void RegisterHelper(InterfaceInfo reg) { var layerId = UnityFuncs.GetLayerForCreateInfo(reg.info); if (!m_sInterfaceStacks.ContainsKey(layerId)) { m_sInterfaceStacks.Add(layerId, new List <InterfaceInfo>()); } var theStack = m_sInterfaceStacks[layerId]; if (theStack.Contains(reg)) { return; } int idx = theStack.Count; for (int i = 0; i < theStack.Count; ++i) { if (theStack[i].xface.Camera.depth > reg.xface.Camera.depth) { idx = i; break; } } theStack.Insert(idx, reg); }
private EyeTextures GetEyeTextures(int layerId) { EyeTextures result; Vec2i dims = new Vec2i(1, 1); UnityFuncs.GetIdealLayerDimensions(layerId, ref dims); dims.x = (int)(dims.x * renderScale); dims.y = (int)(dims.y * renderScale); if (eyeTextures.ContainsKey(layerId)) { result = eyeTextures[layerId]; if (dims.x != result.left.width || dims.y != result.left.height) { result = MakeNewEyeTextures(layerId, dims); } } else { result = MakeNewEyeTextures(layerId, dims); } return(result); }
void Awake() { worldScale = FoveSettings.WorldScale; renderScale = FoveSettings.RenderScale; headset.GazeCastPolicy = FoveSettings.GazeCastPolicy; UnityFuncs.ResetNativeState(); screenBlitMaterial = new Material(Shader.Find("Fove/EyeShader")); if (FoveSettings.AutomaticObjectRegistration) { GazableObject.CreateFromSceneColliders(); } }
/*******************************************************************************\ * MonoBehaviour / instance methods * \*******************************************************************************/ private FoveManager() { if (sInstance != null) { Debug.LogError("Found an existing instance"); } var logSinkDelegatePtr = Marshal.GetFunctionPointerForDelegate(logSinkDelegate); UnityFuncs.SetLogSinkFunction(logSinkDelegatePtr); headset = new Headset(currentCapabilities); submitNativeFunc = UnityFuncs.GetSubmitFunctionPtr(); wfrpNativeFunc = UnityFuncs.GetWfrpFunctionPtr(); updateMirrorTexNativeFunc = UnityFuncs.GetUpdateMirrorTexPtrFunctionPtr(); }
private void UpdateCapabilities() { var newCapabilities = ComputeInterfacesCapabilities() | enforcedCapabilities; if (currentCapabilities != newCapabilities) { var removedCaps = currentCapabilities & ~newCapabilities; if (removedCaps != ClientCapabilities.None) { UnityFuncs.UnregisterCapabilities(removedCaps); Headset.UnregisterCapabilities(removedCaps); } var addedCaps = newCapabilities & ~currentCapabilities; if (addedCaps != ClientCapabilities.None) { UnityFuncs.RegisterCapabilities(addedCaps); Headset.RegisterCapabilities(addedCaps); } currentCapabilities = newCapabilities; } }
private bool UpdateHmdDataInternal() { var isHmdConnectedChanged = false; // First chech and update the HMD connection status // If the HMD happens to be disconnected we trigger the associated event and abort the update process // If the HMD status changed to connected, we delay the trigger of the associated event after the update of other data { var isHmdConnected = Headset.IsHardwareConnected(); if (isHmdConnected.error == ErrorCode.Hardware_Disconnected) // this returns an error whereas it is was we are querying, so we just ignore it... { isHmdConnected.error = ErrorCode.None; } if (isHmdConnected != wasHardwareConnected) { isHmdConnectedChanged = true; wasHardwareConnected = isHmdConnected; if (!isHmdConnected) { // trigger the hmd disconnected event before returning var handler = HardwareDisconnected; if (handler != null) { handler.Invoke(); } return(false); // abort the update and mark it as failure } } } // Fetch the new eye tracking data from the service var fetchResult = Headset.FetchEyeTrackingData(); if (fetchResult.error == ErrorCode.Connect_NotConnected) { return(false); } // Fetch the new pose data from the service fetchResult = Headset.FetchPoseData(); if (fetchResult.error == ErrorCode.Connect_NotConnected) { return(false); } // HMD pose // It is taken from the UnityFunction native plugin to be sure to return // the same pose as the one used to perform the rendering hmdPose = UnityFuncs.GetLastPose(); headPosition = hmdPose.position.ToVector3() * worldScale; standingPosition = hmdPose.standingPosition.ToVector3() * worldScale; headRotation = hmdPose.orientation.ToQuaternion(); // Update the eyes & position textures TryUpdateTexture(Headset.GetEyesImage, ref eyesImage, ref eyesTexture); TryUpdateTexture(Headset.GetPositionImage, ref positionImage, ref positionTexture); // update the mirror texture native pointer if is exists // we need this update because of the rolling buffer if (mirrorTexture.value != null) { int dummy; IntPtr texPtr; GetMirrorTexturePtr(out texPtr, out dummy, out dummy); mirrorTexture.value.UpdateExternalTexture(texPtr); } // Call user custom data update callbacks var addInUpdateCallback = AddInUpdate; if (addInUpdateCallback != null) { addInUpdateCallback(); } // Trigger the event callbacks now that have updated all the HMD data if (isHmdConnectedChanged) { if (!wasHardwareConnected) { throw new Exception("Internal error: Unexpected hmd connection status"); } var handler = HardwareConnected; if (handler != null) { handler.Invoke(); } } var hwdReady = IsHardwareReady(); if (hwdReady.IsValid && wasHardwareReady != hwdReady) { wasHardwareReady = hwdReady; var handler = hwdReady ? HardwareIsReady : null; if (handler != null) { handler.Invoke(); } } var isCalibrating = IsEyeTrackingCalibrating(); if (isCalibrating.IsValid && isCalibrating != wasCalibrating) { if (wasCalibrating) { var handler = EyeTrackingCalibrationStarted; if (handler != null) { handler.Invoke(); } } else { var handler = EyeTrackingCalibrationEnded; if (handler != null) { handler.Invoke(GetEyeTrackingCalibrationState()); } } wasCalibrating = isCalibrating; } var userAttention = IsUserShiftingAttention(); if (userAttention.IsValid && wasShiftingAttention != userAttention) { wasShiftingAttention = userAttention; var handler = IsUserShiftingAttentionChanged; if (handler != null) { handler.Invoke(wasShiftingAttention); } } UpdateEyeState(Eye.Left); UpdateEyeState(Eye.Right); var userPresent = IsUserPresent(); if (userPresent.IsValid && wasUserPresent != userPresent) { wasUserPresent = userPresent; var handler = UserPresenceChanged; if (handler != null) { handler.Invoke(wasUserPresent); } } var adjusmentGuiVisible = IsHmdAdjustmentGuiVisible(); if (adjusmentGuiVisible.IsValid && wasHmdAdjustmentVisible != adjusmentGuiVisible) { wasHmdAdjustmentVisible = adjusmentGuiVisible; var handler = HmdAdjustmentGuiVisibilityChanged; if (handler != null) { handler.Invoke(wasHmdAdjustmentVisible); } } return(true); }
private IEnumerator FoveUpdateCoroutine() { if (FoveSettings.ShouldForceCalibration) { StartEyeTrackingCalibration(new CalibrationOptions { lazy = true }); } var endOfFrameWait = new WaitForEndOfFrame(); while (Application.isPlaying) { // update the headset capabilities if changed UpdateCapabilities(); if (!UpdateHmdDataInternal()) // hmd got disconnected { break; } // Don't do any rendering code (below) if the compositor isn't ready if (!CompositorReadyCheck()) { yield return(endOfFrameWait); continue; } // On first run and in case any new FoveInterfaces have been created if (m_sUnregisteredInterfaces.Count > 0) { foreach (var reg in m_sUnregisteredInterfaces) { RegisterHelper(reg); } m_sUnregisteredInterfaces.Clear(); } // Render all cameras, one eye at a time RenderTexture oldCurrent = RenderTexture.active; foreach (var list in m_sInterfaceStacks) { if (list.Value.Count == 0) { continue; } int layerId = list.Key; var eyeTx = GetEyeTextures(layerId); UnityFuncs.SetPoseForSubmit(layerId, hmdPose); if (eyeTx.areNew) { var texPtrLeft = eyeTx.left.GetNativeTexturePtr(); var texPtrRight = eyeTx.right.GetNativeTexturePtr(); // texture native ptr get valid only after first flush if (texPtrLeft != IntPtr.Zero && texPtrRight != IntPtr.Zero) { UnityFuncs.SetLeftEyeTexture(layerId, texPtrLeft); UnityFuncs.SetRightEyeTexture(layerId, texPtrRight); eyeTx.areNew = false; } else { // force the creation of the new render targets Graphics.SetRenderTarget(eyeTx.left); Graphics.SetRenderTarget(eyeTx.right); GL.Flush(); break; } } Graphics.SetRenderTarget(eyeTx.left); GL.Clear(true, true, Color.clear); Graphics.SetRenderTarget(eyeTx.right); GL.Clear(true, true, Color.clear); foreach (var interfaceInfo in list.Value) { interfaceInfo.xface.RenderEye(Eye.Left, eyeTx.left); interfaceInfo.xface.RenderEye(Eye.Right, eyeTx.right); } GL.Flush(); GL.IssuePluginEvent(submitNativeFunc, layerId); isBackendInitialized = true; // Submit implicitly initializes the backend if (!FoveSettings.CustomDesktopView) { // this code works only because we only have one single layer (base) allowed for the moment // TODO: Adapt this code as soon as we allow several layers RenderTexture.active = oldCurrent; screenBlitMaterial.SetTexture("_TexLeft", eyeTx.left); screenBlitMaterial.SetTexture("_TexRight", eyeTx.right); Graphics.Blit(null, screenBlitMaterial); } } GL.Flush(); if (!isBackendInitialized && isMirrorRequested) { InitBackendExplicit(); isBackendInitialized = true; } // Wait for render pose GL.IssuePluginEvent(updateMirrorTexNativeFunc, 0); GL.IssuePluginEvent(wfrpNativeFunc, 0); yield return(endOfFrameWait); } StartCoroutine(CheckForHeadsetCoroutine()); }
private void OnDestroy() { headset.Dispose(); UnityFuncs.DestroyNativeResources(); }