/*
* 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;
}
}