/* * 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 UnityEngine; /// /// Represents the Pose of the anchor. Enabling it will localize the anchor. /// /// /// This component can be accessed from an that supports it by calling /// from the anchor. /// This component needs to be enabled before requesting its Pose. See and /// /// /// /// /// public readonly partial struct OVRLocatable : IOVRAnchorComponent, IEquatable { /// /// Tracking space position and rotation of the anchor /// /// /// Position and rotation are both nullable and /// and might be null independently if one of them or both are invalid. /// /// /// /// /// /// /// public readonly struct TrackingSpacePose { /// /// Position in tracking space of the anchor /// /// /// Null if and when the position is invalid /// /// /// /// public Vector3? Position { get; } /// /// Rotation in tracking space of the Anchor /// /// /// Null if and when the rotation is invalid /// /// /// /// public Quaternion? Rotation { get; } /// /// Indicates whether or not the position is currently tracked /// public bool IsPositionTracked => _flags.IsPositionTracked(); /// /// Indicates whether or not the rotation is currently tracked /// public bool IsRotationTracked => _flags.IsOrientationTracked(); private readonly OVRPlugin.SpaceLocationFlags _flags; internal TrackingSpacePose(Vector3 position, Quaternion rotation, OVRPlugin.SpaceLocationFlags flags) { _flags = flags; Position = _flags.IsPositionValid() ? position : default(Vector3?); Rotation = _flags.IsOrientationValid() ? rotation : default(Quaternion?); } /// /// Computes the world space position of the anchor /// /// A component that will be use to compute the transform to world space /// /// The nullable position in world space which may be /// null if and when is invalid or head pose is invalid. /// /// /// /// /// If is null public Vector3? ComputeWorldPosition(Camera camera) { if (camera == null) throw new ArgumentNullException(nameof(camera)); if (!Position.HasValue) return null; var headPose = OVRPose.identity; if (!OVRNodeStateProperties.GetNodeStatePropertyVector3(UnityEngine.XR.XRNode.Head, NodeStatePropertyType.Position, OVRPlugin.Node.Head, OVRPlugin.Step.Render, out headPose.position)) return null; if (!OVRNodeStateProperties.GetNodeStatePropertyQuaternion(UnityEngine.XR.XRNode.Head, NodeStatePropertyType.Orientation, OVRPlugin.Node.Head, OVRPlugin.Step.Render, out headPose.orientation)) return null; headPose = headPose.Inverse(); var headTrackingPosition = headPose.position + headPose.orientation * Position.Value; return camera.transform.localToWorldMatrix.MultiplyPoint(headTrackingPosition); } /// /// Computes the world space rotation of the anchor /// /// A component that will be use to compute the transform to world space /// /// The nullable rotation in world space which may be /// null if and when is invalid or if head rotation is invalid. /// /// /// /// /// If is null public Quaternion? ComputeWorldRotation(Camera camera) { if (camera == null) throw new ArgumentNullException(nameof(camera)); if (!Rotation.HasValue) return null; if (!OVRNodeStateProperties.GetNodeStatePropertyQuaternion(UnityEngine.XR.XRNode.Head, NodeStatePropertyType.Orientation, OVRPlugin.Node.Head, OVRPlugin.Step.Render, out var headPoseRotation)) return null; headPoseRotation = Quaternion.Inverse(headPoseRotation); var headTrackingOrientation = headPoseRotation * Rotation.Value; return camera.transform.rotation * headTrackingOrientation; } } /// /// Tries to get the representing the position and rotation of this anchor, treated as a scene anchor, in tracking space. /// /// The out which will get filled in. /// /// True if the request was successful, False otherwise. /// /// /// Although the request may succeed and provide a valid , actual Position and Rotation provided /// may not be valid and/or tracked, see for more information on how to use its data. /// Scene anchors follow a different transform from the raw OpenXR data than spatial anchors'. /// public bool TryGetSceneAnchorPose(out TrackingSpacePose pose) { if (!OVRPlugin.TryLocateSpace(Handle, OVRPlugin.GetTrackingOriginType(), out var posef, out var locationFlags)) { pose = default; return false; } // Transform from OpenXR Right-handed coordinate system // to Unity Left-handed coordinate system with additional 180 rotation around +y var position = posef.Position.FromFlippedZVector3f(); var rotation = new Quaternion(-posef.Orientation.z, posef.Orientation.w, -posef.Orientation.x, posef.Orientation.y); pose = new TrackingSpacePose(position, rotation, locationFlags); return true; } /// /// Tries to get the representing the position and rotation of this anchor, treated as a spatial anchor, in tracking space. /// /// The out which will get filled in. /// /// True if the request was successful, False otherwise. /// /// /// Although the request may succeed and provide a valid , actual position and rotation provided /// may not be valid and/or tracked, see for more information on how to use its data. /// Spatial anchors follow a different transform from the raw OpenXR data than scene anchors'. /// public bool TryGetSpatialAnchorPose(out TrackingSpacePose pose) { if (!OVRPlugin.TryLocateSpace(Handle, OVRPlugin.GetTrackingOriginType(), out var posef, out var locationFlags)) { pose = default; return false; } // Transform from OpenXR Right-handed coordinate system // to Unity Left-handed coordinate system var position = posef.Position.FromFlippedZVector3f(); var rotation = posef.Orientation.FromFlippedZQuatf(); pose = new TrackingSpacePose(position, rotation, locationFlags); return true; } }