Skip to main content
Version: 10 Jul 2024

PlaneBoundary.cs

Source code

// %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
{
public class PlaneBoundary
{
private bool Valid => Polygon.VertexCountOutput > 0;

private static void AssignAtomicSafetyHandle<T>(ref NativeArray<T> 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
}

private unsafe void GetPolygon(Allocator allocator, ref NativeArray<Vector2> polygonOut)
{
if (!Valid)
{
throw new InvalidOperationException("This plane boundary is not valid.");
}

CreateOrResizeNativeArrayIfNecessary(PolygonVertexCount, allocator, ref polygonOut);
polygonOut = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Vector2>(Polygon.Vertices, PolygonVertexCount, allocator);
AssignAtomicSafetyHandle(ref polygonOut, allocator);
}

public int PolygonVertexCount => (int)Polygon.VertexCountOutput;

internal NativeArray<Vector2> GetPolygon(Allocator allocator)
{
var polygon = new NativeArray<Vector2>();
GetPolygon(allocator, ref polygon);
return polygon;
}

private int HoleCount => Holes.Length;

internal NativeArray<Vector2> GetHole(int index, Allocator allocator)
{
var hole = new NativeArray<Vector2>();
GetHole(index, allocator, ref hole);
return hole;
}

private unsafe void GetHole(int index, Allocator allocator, ref NativeArray<Vector2> 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<Vector2>(holes.Vertices, (int)holes.VertexCountOutput, allocator);
AssignAtomicSafetyHandle(ref polygonOut, allocator);
}


internal NativeArray<XrPlaneDetectorPolygonBuffer> Holes;
internal XrPlaneDetectorPolygonBuffer Polygon;
internal Pose PlanePose;
internal TrackableId Id;
}
}
}