/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * Licensed under the Oculus SDK License Agreement (the "License"); * you may not use the Oculus SDK except in compliance with the License, * which is provided at the time of installation or download, or which * otherwise accompanies this software in either electronic or hard copy form. * * You may obtain a copy of the License at * * https://developer.oculus.com/licenses/oculussdk/ * * Unless required by applicable law or agreed to in writing, the Oculus SDK * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using Meta.XR.Util; using UnityEngine; using UnityEngine.Assertions; using UnityEngine.Serialization; using UnityEngine.XR; namespace Oculus.Interaction.Input { [Feature(Feature.Interaction)] public class FromOVRHmdDataSource : DataSource { [Header("OVR Data Source")] [SerializeField, Interface(typeof(IOVRCameraRigRef))] private UnityEngine.Object _cameraRigRef; public IOVRCameraRigRef CameraRigRef { get; private set; } [SerializeField] private bool _processLateUpdates = false; [SerializeField] [Tooltip("If true, uses OVRManager.headPoseRelativeOffset rather than sensor data for " + "HMD pose.")] private bool _useOvrManagerEmulatedPose = false; [Header("Shared Configuration")] [SerializeField, Interface(typeof(ITrackingToWorldTransformer))] private UnityEngine.Object _trackingToWorldTransformer; private ITrackingToWorldTransformer TrackingToWorldTransformer; public bool ProcessLateUpdates { get { return _processLateUpdates; } set { _processLateUpdates = value; } } private HmdDataAsset _hmdDataAsset = new HmdDataAsset(); private HmdDataSourceConfig _config; protected void Awake() { CameraRigRef = _cameraRigRef as IOVRCameraRigRef; TrackingToWorldTransformer = _trackingToWorldTransformer as ITrackingToWorldTransformer; } protected override void Start() { this.BeginStart(ref _started, () => base.Start()); this.AssertField(CameraRigRef, nameof(CameraRigRef)); this.AssertField(TrackingToWorldTransformer, nameof(TrackingToWorldTransformer)); this.EndStart(ref _started); } protected override void OnEnable() { base.OnEnable(); if (_started) { CameraRigRef.WhenInputDataDirtied += HandleInputDataDirtied; } } protected override void OnDisable() { if (_started) { CameraRigRef.WhenInputDataDirtied -= HandleInputDataDirtied; } base.OnDisable(); MarkInputDataRequiresUpdate(); } private void HandleInputDataDirtied(bool isLateUpdate) { if (isLateUpdate && !_processLateUpdates) { return; } MarkInputDataRequiresUpdate(); } private HmdDataSourceConfig Config { get { if (_config != null) { return _config; } _config = new HmdDataSourceConfig() { TrackingToWorldTransformer = TrackingToWorldTransformer }; return _config; } } protected override void UpdateData() { _hmdDataAsset.Config = Config; bool hmdPresent = OVRNodeStateProperties.IsHmdPresent() && this.isActiveAndEnabled; ref var centerEyePose = ref _hmdDataAsset.Root; if (_useOvrManagerEmulatedPose) { Quaternion emulatedRotation = Quaternion.Euler( -OVRManager.instance.headPoseRelativeOffsetRotation.x, -OVRManager.instance.headPoseRelativeOffsetRotation.y, OVRManager.instance.headPoseRelativeOffsetRotation.z); centerEyePose.rotation = emulatedRotation; centerEyePose.position = OVRManager.instance.headPoseRelativeOffsetTranslation; hmdPresent = true; } else { var previousEyePose = Pose.identity; if (_hmdDataAsset.IsTracked) { previousEyePose = _hmdDataAsset.Root; } if (hmdPresent) { // These are already in Unity's coordinate system (LHS) if (!OVRNodeStateProperties.GetNodeStatePropertyVector3(XRNode.CenterEye, NodeStatePropertyType.Position, OVRPlugin.Node.EyeCenter, OVRPlugin.Step.Render, out centerEyePose.position)) { centerEyePose.position = previousEyePose.position; } if (!OVRNodeStateProperties.GetNodeStatePropertyQuaternion(XRNode.CenterEye, NodeStatePropertyType.Orientation, OVRPlugin.Node.EyeCenter, OVRPlugin.Step.Render, out centerEyePose.rotation)) { centerEyePose.rotation = previousEyePose.rotation; } } else { centerEyePose = previousEyePose; } } _hmdDataAsset.IsTracked = hmdPresent; _hmdDataAsset.FrameId = Time.frameCount; } protected override HmdDataAsset DataAsset => _hmdDataAsset; #region Inject public void InjectAllFromOVRHmdDataSource(UpdateModeFlags updateMode, IDataSource updateAfter, bool useOvrManagerEmulatedPose, ITrackingToWorldTransformer trackingToWorldTransformer) { base.InjectAllDataSource(updateMode, updateAfter); InjectUseOvrManagerEmulatedPose(useOvrManagerEmulatedPose); InjectTrackingToWorldTransformer(trackingToWorldTransformer); } public void InjectUseOvrManagerEmulatedPose(bool useOvrManagerEmulatedPose) { _useOvrManagerEmulatedPose = useOvrManagerEmulatedPose; } public void InjectTrackingToWorldTransformer(ITrackingToWorldTransformer trackingToWorldTransformer) { _trackingToWorldTransformer = trackingToWorldTransformer as UnityEngine.Object; TrackingToWorldTransformer = trackingToWorldTransformer; } #endregion } }