You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
7.7 KiB
193 lines
7.7 KiB
using System.Runtime.InteropServices;
|
|
using Unity.Collections;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
using Unity.Jobs;
|
|
using UnityEngine.Scripting;
|
|
using UnityEngine.XR.ARSubsystems;
|
|
|
|
namespace UnityEngine.XR.ARKit
|
|
{
|
|
/// <summary>
|
|
/// The ARKit implementation of the <c>XRPlaneSubsystem</c>. Do not create this directly. Use the <c>SubsystemManager</c> instead.
|
|
/// </summary>
|
|
[Preserve]
|
|
public sealed class ARKitXRPlaneSubsystem : XRPlaneSubsystem
|
|
{
|
|
protected override Provider CreateProvider() => new ARKitProvider();
|
|
|
|
class ARKitProvider : Provider
|
|
{
|
|
public override void Destroy() => NativeApi.UnityARKit_planes_shutdown();
|
|
|
|
public override void Start() => NativeApi.UnityARKit_planes_start();
|
|
|
|
public override void Stop() => NativeApi.UnityARKit_planes_stop();
|
|
|
|
public override unsafe void GetBoundary(
|
|
TrackableId trackableId,
|
|
Allocator allocator,
|
|
ref NativeArray<Vector2> boundary)
|
|
{
|
|
int numPoints;
|
|
void* verticesPtr;
|
|
void* plane = NativeApi.UnityARKit_planes_acquireBoundary(
|
|
trackableId,
|
|
out verticesPtr,
|
|
out numPoints);
|
|
|
|
try
|
|
{
|
|
CreateOrResizeNativeArrayIfNecessary(numPoints, allocator, ref boundary);
|
|
var transformPositionsHandle = new TransformBoundaryPositionsJob
|
|
{
|
|
positionsIn = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Vector4>(verticesPtr, numPoints, Allocator.None),
|
|
positionsOut = boundary
|
|
}.Schedule(numPoints, 1);
|
|
|
|
new FlipBoundaryWindingJob
|
|
{
|
|
positions = boundary
|
|
}.Schedule(transformPositionsHandle).Complete();
|
|
}
|
|
finally
|
|
{
|
|
NativeApi.UnityARKit_planes_releaseBoundary(plane);
|
|
}
|
|
}
|
|
|
|
struct FlipBoundaryWindingJob : IJob
|
|
{
|
|
public NativeArray<Vector2> positions;
|
|
|
|
public void Execute()
|
|
{
|
|
var half = positions.Length / 2;
|
|
for (int i = 0; i < half; ++i)
|
|
{
|
|
var j = positions.Length - 1 - i;
|
|
var temp = positions[i];
|
|
positions[i] = positions[j];
|
|
positions[j] = temp;
|
|
}
|
|
}
|
|
}
|
|
|
|
struct TransformBoundaryPositionsJob : IJobParallelFor
|
|
{
|
|
[ReadOnly]
|
|
public NativeArray<Vector4> positionsIn;
|
|
|
|
[WriteOnly]
|
|
public NativeArray<Vector2> positionsOut;
|
|
|
|
public void Execute(int index)
|
|
{
|
|
positionsOut[index] = new Vector2(
|
|
// NB: https://developer.apple.com/documentation/arkit/arplanegeometry/2941052-boundaryvertices?language=objc
|
|
// "The owning plane anchor's transform matrix defines the coordinate system for these points."
|
|
// It doesn't explicitly state the y component is zero, but that must be the case if the
|
|
// boundary points are in plane-space. Emperically, it has been true for horizontal and vertical planes.
|
|
// This IS explicitly true for the extents (see above) and would follow the same logic.
|
|
//
|
|
// Boundary vertices are in right-handed coordinates and clockwise winding order. To convert
|
|
// to left-handed, we flip the Z coordinate, but that also flips the winding, so we have to
|
|
// flip the winding back to clockwise by reversing the polygon index (j).
|
|
positionsIn[index].x,
|
|
-positionsIn[index].z);
|
|
}
|
|
}
|
|
|
|
public override unsafe TrackableChanges<BoundedPlane> GetChanges(
|
|
BoundedPlane defaultPlane,
|
|
Allocator allocator)
|
|
{
|
|
int addedLength, updatedLength, removedLength, elementSize;
|
|
void* addedArrayPtr, updatedArrayPtr, removedArrayPtr;
|
|
var context = NativeApi.UnityARKit_planes_acquireChanges(
|
|
out addedArrayPtr, out addedLength,
|
|
out updatedArrayPtr, out updatedLength,
|
|
out removedArrayPtr, out removedLength,
|
|
out elementSize);
|
|
|
|
try
|
|
{
|
|
return new TrackableChanges<BoundedPlane>(
|
|
addedArrayPtr, addedLength,
|
|
updatedArrayPtr, updatedLength,
|
|
removedArrayPtr, removedLength,
|
|
defaultPlane, elementSize,
|
|
allocator);
|
|
}
|
|
finally
|
|
{
|
|
NativeApi.UnityARKit_planes_releaseChanges(context);
|
|
}
|
|
}
|
|
|
|
public override PlaneDetectionMode planeDetectionMode
|
|
{
|
|
set => NativeApi.UnityARKit_planes_setPlaneDetectionMode(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Container to wrap the native ARKit APIs needed at registration.
|
|
/// </summary>
|
|
static class NativeApi
|
|
{
|
|
[DllImport("__Internal")]
|
|
static internal extern unsafe bool UnityARKit_planes_SupportsClassification();
|
|
|
|
[DllImport("__Internal")]
|
|
static internal extern void UnityARKit_planes_shutdown();
|
|
|
|
[DllImport("__Internal")]
|
|
static internal extern void UnityARKit_planes_start();
|
|
|
|
[DllImport("__Internal")]
|
|
static internal extern void UnityARKit_planes_stop();
|
|
|
|
[DllImport("__Internal")]
|
|
static internal extern unsafe void* UnityARKit_planes_acquireChanges(
|
|
out void* addedPtr, out int addedLength,
|
|
out void* updatedPtr, out int updatedLength,
|
|
out void* removedPtr, out int removedLength,
|
|
out int elementSize);
|
|
|
|
[DllImport("__Internal")]
|
|
static internal extern unsafe void UnityARKit_planes_releaseChanges(void* changes);
|
|
|
|
[DllImport("__Internal")]
|
|
static internal extern void UnityARKit_planes_setPlaneDetectionMode(PlaneDetectionMode mode);
|
|
|
|
[DllImport("__Internal")]
|
|
static internal extern unsafe void* UnityARKit_planes_acquireBoundary(
|
|
TrackableId trackableId,
|
|
out void* verticiesPtr,
|
|
out int numPoints);
|
|
|
|
[DllImport("__Internal")]
|
|
static internal extern unsafe void UnityARKit_planes_releaseBoundary(
|
|
void* boundary);
|
|
}
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
|
static void RegisterDescriptor()
|
|
{
|
|
#if UNITY_IOS && !UNITY_EDITOR
|
|
var cinfo = new XRPlaneSubsystemDescriptor.Cinfo
|
|
{
|
|
id = "ARKit-Plane",
|
|
subsystemImplementationType = typeof(ARKitXRPlaneSubsystem),
|
|
supportsHorizontalPlaneDetection = true,
|
|
supportsVerticalPlaneDetection = true,
|
|
supportsArbitraryPlaneDetection = false,
|
|
supportsBoundaryVertices = true,
|
|
supportsClassification = NativeApi.UnityARKit_planes_SupportsClassification(),
|
|
};
|
|
|
|
XRPlaneSubsystemDescriptor.Create(cinfo);
|
|
#endif
|
|
}
|
|
}
|
|
}
|