186 lines
11 KiB
C#
186 lines
11 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using TrackableId = UnityEngine.XR.ARSubsystems.TrackableId;
|
|
|
|
namespace Microsoft.MixedReality.OpenXR
|
|
{
|
|
/// <summary>
|
|
/// Provides helper functions to convert an Unity Anchor object to underlying OpenXR anchor handle or SpatialAnchor COM object.
|
|
/// </summary>
|
|
public static class AnchorConverter
|
|
{
|
|
private static MixedRealityFeaturePlugin Feature => OpenXRFeaturePlugin<MixedRealityFeaturePlugin>.Feature;
|
|
|
|
/// <summary>
|
|
/// Get the OpenXR handle of the given nativePtr from ARAnchor or XRAnchor object if available, or return 0.
|
|
/// </summary>
|
|
/// <param name="nativePtr">The nativePtr obtained from either XRAnchor.nativePtr or ARAnchor.nativePtr.</param>
|
|
/// <returns>XrAnchorMSFT handle that represents the underlying OpenXR anchor of given nativePtr, or 0 when such associated handle cannot be found.</returns>
|
|
public static ulong ToOpenXRHandle(IntPtr nativePtr)
|
|
{
|
|
if (nativePtr == null)
|
|
return 0;
|
|
|
|
NativeAnchorData data = Marshal.PtrToStructure<NativeAnchorData>(nativePtr);
|
|
if (data.version == 1)
|
|
{
|
|
return data.anchorHandle;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a new ARAnchor from the given OpenXR XRSpatialAnchorMSFT handle.
|
|
/// </summary>
|
|
/// <param name="openxrAnchorHandle">A valid OpenXR XRSpatialAnchorMSFT handle.</param>
|
|
/// <returns>Returns the trackable id representing the Unity anchor or <see cref="TrackableId.invalidId"/> if the conversion was unsuccessful.</returns>
|
|
/// <remarks>The newly created TrackableId will not be added to <see cref="UnityEngine.XR.ARFoundation.ARTrackableManager{TSubsystem, TSubsystemDescriptor, TProvider, TSessionRelativeData, TTrackable}.trackables"/> collection until the next frame's Update.
|
|
/// The app should listen to the <see cref="UnityEngine.XR.ARFoundation.ARAnchorManager.anchorsChanged"/> event for the added ARAnchor object with the returned trackableId.</remarks>
|
|
public static TrackableId CreateFromOpenXRHandle(ulong openxrAnchorHandle)
|
|
{
|
|
if (Feature.IsValidAndEnabled() && openxrAnchorHandle != 0)
|
|
{
|
|
Guid guid = NativeLib.TryCreateARAnchorFromOpenXRHandle(openxrAnchorHandle);
|
|
return FeatureUtils.ToTrackableId(guid);
|
|
}
|
|
return TrackableId.invalidId;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a COM wrapper object of Windows.Perception.Spatial.SpatialAnchor from the given ARAnchor's nativePtr.
|
|
/// </summary>
|
|
/// <param name="nativePtr">The nativePtr obtained from either XRAnchor.nativePtr or ARAnchor.nativePtr.</param>
|
|
/// <returns>The COM wrapper object of Windows.Perception.Spatial.SpatialAnchor, or null when the conversion failed.</returns>
|
|
public static object ToPerceptionSpatialAnchor(IntPtr nativePtr)
|
|
{
|
|
if (Feature.IsValidAndEnabled() && nativePtr != IntPtr.Zero)
|
|
{
|
|
IntPtr unknown = NativeLib.TryAcquirePerceptionSpatialAnchor(ToOpenXRHandle(nativePtr));
|
|
if (unknown != IntPtr.Zero)
|
|
{
|
|
object result = Marshal.GetObjectForIUnknown(unknown);
|
|
Marshal.Release(unknown); // Balance the ref count because "feature.TryAcquire" increment it on return.
|
|
return result;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a COM wrapper object of Windows.Perception.Spatial.SpatialAnchor from the given TrackableId.
|
|
/// If failed, the function returns nullptr.
|
|
/// </summary>
|
|
/// <param name="trackableId">An existing XRAnchor or ARAnchor's ID.</param>
|
|
/// <returns>The COM wrapper object of Windows.Perception.Spatial.SpatialAnchor, or null when the conversion failed.</returns>
|
|
public static object ToPerceptionSpatialAnchor(TrackableId trackableId)
|
|
{
|
|
if (Feature.IsValidAndEnabled() && trackableId != TrackableId.invalidId)
|
|
{
|
|
IntPtr unknown = NativeLib.TryAcquirePerceptionSpatialAnchor(FeatureUtils.ToGuid(trackableId));
|
|
if (unknown != IntPtr.Zero)
|
|
{
|
|
object result = Marshal.GetObjectForIUnknown(unknown);
|
|
Marshal.Release(unknown); // Balance the ref count because "feature.TryAcquire" increment it on return.
|
|
return result;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creating a new ARAnchor from the given Windows.Perception.Spatial.SpatialAnchor.
|
|
/// If failed, the function returns TrackableId.invalidId.
|
|
/// Creates an OpenXR anchor from a Windows.Perception.Spatial.SpatialAnchor and reports it to Unity.
|
|
/// </summary>
|
|
/// <param name="spatialAnchor">Must be a Windows.Perception.Spatial.SpatialAnchor.</param>
|
|
/// <returns>Returns the trackable id representing the Unity anchor or <see cref="TrackableId.invalidId"/> if the conversion was unsuccessful.</returns>
|
|
/// <remarks>The newly created TrackableId will not be added to <see cref="UnityEngine.XR.ARFoundation.ARTrackableManager{TSubsystem, TSubsystemDescriptor, TProvider, TSessionRelativeData, TTrackable}.trackables"/> collection until the next frame's Update.
|
|
/// The app should listen to the <see cref="UnityEngine.XR.ARFoundation.ARAnchorManager.anchorsChanged"/> event for the added ARAnchor object with the returned trackableId.</remarks>
|
|
[Obsolete("Obsolete and will be removed in future releases. Use the `CreateFromPerceptionSpatialAnchor` function instead.")]
|
|
public static TrackableId FromPerceptionSpatialAnchor(object spatialAnchor)
|
|
{
|
|
return CreateFromPerceptionSpatialAnchor(spatialAnchor);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creating a new ARAnchor from the given Windows.Perception.Spatial.SpatialAnchor.
|
|
/// If failed, the function returns TrackableId.invalidId.
|
|
/// Creates an OpenXR anchor from a Windows.Perception.Spatial.SpatialAnchor and reports it to Unity.
|
|
/// </summary>
|
|
/// <param name="spatialAnchor">Must be a Windows.Perception.Spatial.SpatialAnchor.</param>
|
|
/// <returns>Returns the trackable id representing the Unity anchor or <see cref="TrackableId.invalidId"/> if the conversion was unsuccessful.</returns>
|
|
/// <remarks>The newly created TrackableId will not be added to <see cref="UnityEngine.XR.ARFoundation.ARTrackableManager{TSubsystem, TSubsystemDescriptor, TProvider, TSessionRelativeData, TTrackable}.trackables"/> collection until the next frame's Update.
|
|
/// The app should listen to the <see cref="UnityEngine.XR.ARFoundation.ARAnchorManager.anchorsChanged"/> event for the added ARAnchor object with the returned trackableId.</remarks>
|
|
public static TrackableId CreateFromPerceptionSpatialAnchor(object spatialAnchor)
|
|
{
|
|
if (Feature.IsValidAndEnabled() && spatialAnchor != null)
|
|
{
|
|
Guid guid = NativeLib.TryCreateARAnchorFromPerceptionAnchor(spatialAnchor);
|
|
return FeatureUtils.ToTrackableId(guid);
|
|
}
|
|
return TrackableId.invalidId;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Replaces the underlying platform anchor for an existing XRAnchor/ARAnchor represented by the
|
|
/// given TrackableId, so the Unity anchor will instead be located by the given SpatialAnchor.
|
|
/// </summary>
|
|
/// <remarks>Use this function instead of <see cref="FromPerceptionSpatialAnchor"/> to avoid creating new ARAnchor on every new platform anchor.</remarks>
|
|
/// <param name="spatialAnchor">Must be a Windows.Perception.Spatial.SpatialAnchor.</param>
|
|
/// <param name="existingId">An id representing an existing XRAnchor/ARAnchor.</param>
|
|
/// <returns>Returns the trackable id representing the Unity anchor or <see cref="TrackableId.invalidId"/> if the conversion was unsuccessful.</returns>
|
|
public static TrackableId ReplaceSpatialAnchor(object spatialAnchor, TrackableId existingId)
|
|
{
|
|
if (Feature.IsValidAndEnabled() && spatialAnchor != null)
|
|
{
|
|
Guid guid = NativeLib.TryAcquireAndReplaceXrSpatialAnchor(spatialAnchor, FeatureUtils.ToGuid(existingId));
|
|
return FeatureUtils.ToTrackableId(guid);
|
|
}
|
|
return TrackableId.invalidId;
|
|
}
|
|
}
|
|
|
|
namespace ARSubsystems
|
|
{
|
|
/// <summary>
|
|
/// Provides extension function to convert an XRAnchor object to underlying OpenXR anchor handle.
|
|
/// </summary>
|
|
[System.Obsolete("Obsolete and will be removed in future releases. Use AnchorConverter.ToOpenXRHandle() function instead.", true)]
|
|
public static class XRAnchorExtensions
|
|
{
|
|
/// <summary>
|
|
/// Get the native OpenXR handle of the given XRAnchor object if available, or return 0.
|
|
/// </summary>
|
|
/// <param name="anchor">A valid <see cref="UnityEngine.XR.ARSubsystems.XRAnchor"/> object.</param>
|
|
/// <returns>XrAnchorMSFT handle that represents the underlying OpenXR anchor, or 0 when such associated handle cannot be found.</returns>
|
|
public static ulong GetOpenXRHandle(this UnityEngine.XR.ARSubsystems.XRAnchor anchor)
|
|
{
|
|
return anchor == null ? 0 : AnchorConverter.ToOpenXRHandle(anchor.nativePtr);
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace ARFoundation
|
|
{
|
|
/// <summary>
|
|
/// Provides extension function to convert an ARAnchor object to underlying OpenXR anchor handle.
|
|
/// </summary>
|
|
[System.Obsolete("Obsolete and will be removed in future releases. Use AnchorConverter.ToOpenXRHandle() function instead.", true)]
|
|
public static class ARAnchorExtensions
|
|
{
|
|
/// <summary>
|
|
/// Get the native OpenXR handle of the given ARAnchor object if available, or return 0.
|
|
/// </summary>
|
|
/// <param name="anchor">A valid <see cref="UnityEngine.XR.ARFoundation.ARAnchor"/> object.</param>
|
|
/// <returns>XrAnchorMSFT handle that represents the underlying OpenXR anchor, or 0 when such associated handle cannot be found.</returns>
|
|
public static ulong GetOpenXRHandle(this UnityEngine.XR.ARFoundation.ARAnchor anchor)
|
|
{
|
|
return anchor == null ? 0 : AnchorConverter.ToOpenXRHandle(anchor.nativePtr);
|
|
}
|
|
}
|
|
}
|
|
}
|