/* * 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 Unity.Collections; using UnityEngine; /// /// Represents a plane described by its and boundary points. /// /// /// This component can be accessed from an that supports it by calling /// from the anchor. /// /// /// /// public readonly partial struct OVRBounded2D : IOVRAnchorComponent, IEquatable { /// /// Bounding Box /// /// /// representing the 2D Bounding Box of the Anchor this component is attached to. /// /// If it fails to retrieve the Bounding Box. public Rect BoundingBox => OVRPlugin.GetSpaceBoundingBox2D(Handle, out var rectf) ? ConvertRect(rectf) : throw new InvalidOperationException("Could not get BoundingBox"); private Rect ConvertRect(OVRPlugin.Rectf openXrRect) { // OpenXR Rects describe a rectangle by its position (or offset) and its size (or extents) // https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrRect2Df.html // Unity Rects describe a rectangle by its position and its size (or extents) // https://docs.unity3d.com/ScriptReference/Rect.html var extents = openXrRect.Size.FromSizef(); // OpenXR uses a right-handed coordinate system // Unity uses left-handed coordinate system // There is a design assumption that plane's normal should coincide with +z // We therefore need to rotate the plane 180° around +y axis // We therefore need to flip the x axis. var offset = openXrRect.Pos.FromFlippedXVector2f(); // When flipping one axis, position doesn't point to a min corner any more offset.x -= extents.x; return new Rect(offset, extents); } /// /// Retrieves the number of boundary points contained in an Anchor with an enabled Bounded2D component. /// /// The number of boundary points contained in the Bounded2D component of the Anchor, as an out parameter. /// true if it successfully retrieves the count, false otherwise. /// This is the first part of the two-calls idiom for retrieving boundary points. to actually get those points. /// public bool TryGetBoundaryPointsCount(out int count) => OVRPlugin.GetSpaceBoundary2DCount(Handle, out count); /// /// Retrieves the boundary points contained in an Anchor with an enabled Bounded2D component. /// /// The array that will get populated with the boundary points contained in the Bounded2D component of the Anchor. /// true if it successfully populates the array with the boundary points. /// Thrown when has not been created. /// This is the second part of the two-calls idiom for retrieving boundary points. /// It is expected for the to be created and with enough capacity to contain the boundary points. /// public bool TryGetBoundaryPoints(NativeArray positions) { if (!positions.IsCreated) throw new ArgumentException("NativeArray is not created", nameof(positions)); if (!OVRPlugin.GetSpaceBoundary2D(Handle, positions, out var count)) return false; var low = 0; var high = count - 1; for (; low <= high; low++, high--) { var swapTemporaryPositionHigh = positions[high]; var swapTemporaryPositionLow = positions[low]; positions[low] = new Vector2(-swapTemporaryPositionHigh.x, swapTemporaryPositionHigh.y); positions[high] = new Vector2(-swapTemporaryPositionLow.x, swapTemporaryPositionLow.y); } return true; } }