// %BANNER_BEGIN% // --------------------------------------------------------------------- // %COPYRIGHT_BEGIN% // Copyright (c) (2021-2022) Magic Leap, Inc. All Rights Reserved. // Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2 // Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein. // %COPYRIGHT_END% // --------------------------------------------------------------------- // %BANNER_END% using System; using MagicLeap.OpenXR.Features.Planes; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using UnityEngine; using UnityEngine.XR.ARSubsystems; namespace MagicLeap.OpenXR.Subsystems { public partial class MLXrPlaneSubsystem { /// /// Container for the boundary of a detected planar surface. This is specific /// to Magic Leap because the polygon describing the boundary may be concave, /// and may contain holes. /// public class PlaneBoundary { /// /// Whether this is valid. You should check /// for validity before invoking /// , or /// private bool Valid => Polygon.VertexCountOutput > 0; private static void AssignAtomicSafetyHandle(ref NativeArray array, Allocator allocator) where T : struct { #if ENABLE_UNITY_COLLECTIONS_CHECKS var safetyHandle = allocator == Allocator.Temp ? AtomicSafetyHandle.GetTempUnsafePtrSliceHandle() : AtomicSafetyHandle.Create(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref array, safetyHandle); #endif } /// /// Gets the polygon representing a plane's boundary, and, if successful, copies it to . /// is resized or created using if necessary. /// The 2D vertices are in plane-space. /// /// /// The Allocator to use if must be recreated. /// Must be Allocator.TempJob or Allocator.Persistent. /// /// /// A NativeArray to fill with boundary points. If the array is not the correct size, it is /// disposed and recreated. /// /// Thrown if is false. /// /// Thrown if is Allocator.Temp or /// Allocator.None. /// private unsafe void GetPolygon(Allocator allocator, ref NativeArray polygonOut) { if (!Valid) { throw new InvalidOperationException("This plane boundary is not valid."); } CreateOrResizeNativeArrayIfNecessary(PolygonVertexCount, allocator, ref polygonOut); polygonOut = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(Polygon.Vertices, PolygonVertexCount, allocator); AssignAtomicSafetyHandle(ref polygonOut, allocator); } /// /// The number of vertices in this boundary's polygon. /// public int PolygonVertexCount => (int)Polygon.VertexCountOutput; /// /// Gets the polygon representing this boundary. The 2D vertices are in plane-space. /// /// /// The allocator to use for the returned NativeArray. Must be Allocator.TempJob or /// Allocator.Persistent. /// /// /// A new NativeArray containing a set of 2D points in plane-space representing a boundary for a plane. /// The caller is responsible for disposing the NativeArray. /// /// Thrown if is false. /// /// Thrown if is Allocator.Temp or /// Allocator.None. /// internal NativeArray GetPolygon(Allocator allocator) { var polygon = new NativeArray(); GetPolygon(allocator, ref polygon); return polygon; } /// /// The number of holes in this boundary. /// private int HoleCount => Holes.Length; /// /// Get the polygon representing a hole in this boundary. The 2D vertices are in plane-space. /// /// The index of the hole. Must be less than . /// /// The allocator to use for the returned NativeArray. /// Must be Allocator.TempJob or Allocator.Persistent. /// /// /// A new NativeArray allocated with containing a set of 2D vertices /// in plane-space describing the hole at . /// /// Thrown if is false. /// /// Thrown if is Allocator.Temp or /// Allocator.None. /// /// /// Thrown if is less than 0 or greater than /// or equal to . /// internal NativeArray GetHole(int index, Allocator allocator) { var hole = new NativeArray(); GetHole(index, allocator, ref hole); return hole; } /// /// Get the polygon representing a hole in this boundary. The 2D vertices are in plane-space. /// /// The index of the hole. Must be less than . /// /// The allocator to use if must be resized. /// Must be Allocator.TempJob or Allocator.Persistent. /// /// The resulting polygon describing the hole at . /// Thrown if is false. /// /// Thrown if is Allocator.Temp or /// Allocator.None. /// /// /// Thrown if is less than 0 or greater than /// or equal to . /// private unsafe void GetHole(int index, Allocator allocator, ref NativeArray polygonOut) { if (!Valid) throw new InvalidOperationException("This plane boundary is not valid."); if (index < 0) { throw new ArgumentOutOfRangeException(nameof(index), "Hole index must be greater than zero."); } if (index >= HoleCount) { throw new ArgumentOutOfRangeException(nameof(index), $"Hole index must be less than or equal to holeCount ({HoleCount})."); } var holes = Holes[index]; CreateOrResizeNativeArrayIfNecessary((int)holes.VertexCountOutput, allocator,ref polygonOut); polygonOut = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(holes.Vertices, (int)holes.VertexCountOutput, allocator); AssignAtomicSafetyHandle(ref polygonOut, allocator); } internal NativeArray Holes; internal XrPlaneDetectorPolygonBuffer Polygon; internal Pose PlanePose; internal TrackableId Id; } } }