SW 중심대학 OSS GIT 서버 박건태, 이승준, 고기완, 이준호 새로운 배포
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

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
}
}
}