version 2.5.0
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
// Remove FAKE_DATA if editor or windows is supported.
|
||||
#if UNITY_EDITOR
|
||||
@@ -10,222 +10,666 @@ using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using VIVE.OpenXR.Feature;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.Anchor
|
||||
namespace VIVE.OpenXR.Feature
|
||||
{
|
||||
using XrPersistedAnchorCollectionHTC = System.IntPtr;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Anchor",
|
||||
Desc = "VIVE's implementaion of the XR_HTC_anchor.",
|
||||
Company = "HTC",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionString,
|
||||
Version = "1.0.0",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
FeatureId = featureId
|
||||
)]
|
||||
[OpenXRFeature(UiName = "VIVE XR Anchor (Beta)",
|
||||
Desc = "VIVE's implementaion of the XR_HTC_anchor.",
|
||||
Company = "HTC",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionString,
|
||||
Version = "1.0.0",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android, BuildTargetGroup.Standalone },
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class ViveAnchor : OpenXRFeature
|
||||
{
|
||||
public const string kOpenxrExtensionString = "XR_HTC_anchor";
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "vive.wave.openxr.feature.htcanchor";
|
||||
private XrInstance m_XrInstance = 0;
|
||||
private XrSession session = 0;
|
||||
private XrSystemId m_XrSystemId = 0;
|
||||
public class ViveAnchor : OpenXRFeature
|
||||
{
|
||||
public const string kOpenxrExtensionString = "XR_HTC_anchor XR_EXT_future XR_HTC_anchor_persistence";
|
||||
|
||||
#region struct, enum, const of this extensions
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "vive.openxr.feature.htcanchor";
|
||||
|
||||
public struct XrSystemAnchorPropertiesHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
public XrBool32 supportsAnchor;
|
||||
}
|
||||
/// <summary>
|
||||
/// Enable or disable the persisted anchor feature. Set it only valid in feature settings.
|
||||
/// </summary>
|
||||
public bool enablePersistedAnchor = true;
|
||||
private XrInstance m_XrInstance = 0;
|
||||
private XrSession session = 0;
|
||||
private XrSystemId m_XrSystemId = 0;
|
||||
private bool IsInited = false;
|
||||
private bool IsPAInited = false;
|
||||
private bool useFakeData = false;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct XrSpatialAnchorNameHTC
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string name;
|
||||
}
|
||||
#region struct, enum, const of this extensions
|
||||
|
||||
public struct XrSpatialAnchorCreateInfoHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
public XrSpace space;
|
||||
public XrPosef poseInSpace;
|
||||
public XrSpatialAnchorNameHTC name;
|
||||
}
|
||||
/// <summary>
|
||||
/// An application can inspect whether the system is capable of anchor functionality by
|
||||
/// chaining an XrSystemAnchorPropertiesHTC structure to the XrSystemProperties when calling
|
||||
/// xrGetSystemProperties.The runtime must return XR_ERROR_FEATURE_UNSUPPORTED if
|
||||
/// XrSystemAnchorPropertiesHTC::supportsAnchor was XR_FALSE.
|
||||
/// supportsAnchor indicates if current system is capable of anchor functionality.
|
||||
/// </summary>
|
||||
public struct XrSystemAnchorPropertiesHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
public XrBool32 supportsAnchor;
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// name is a null-terminated UTF-8 string whose length is less than or equal to XR_MAX_SPATIAL_ANCHOR_NAME_SIZE_HTC.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrSpatialAnchorNameHTC
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
|
||||
public byte[] name;
|
||||
|
||||
#region delegates and delegate instances
|
||||
delegate XrResult DelegateXrCreateSpatialAnchorHTC(XrSession session, ref XrSpatialAnchorCreateInfoHTC createInfo, ref XrSpace anchor);
|
||||
delegate XrResult DelegateXrGetSpatialAnchorNameHTC(XrSpace anchor, ref XrSpatialAnchorNameHTC name);
|
||||
public XrSpatialAnchorNameHTC(string anchorName)
|
||||
{
|
||||
name = new byte[256];
|
||||
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(anchorName);
|
||||
Array.Copy(utf8Bytes, name, Math.Min(utf8Bytes.Length, 255));
|
||||
name[255] = 0;
|
||||
}
|
||||
|
||||
DelegateXrCreateSpatialAnchorHTC XrCreateSpatialAnchorHTC;
|
||||
DelegateXrGetSpatialAnchorNameHTC XrGetSpatialAnchorNameHTC;
|
||||
#endregion delegates and delegate instances
|
||||
public XrSpatialAnchorNameHTC(XrSpatialAnchorNameHTC anchorName)
|
||||
{
|
||||
name = new byte[256];
|
||||
Array.Copy(anchorName.name, name, 256);
|
||||
name[255] = 0;
|
||||
}
|
||||
|
||||
#region override functions
|
||||
/// <inheritdoc />
|
||||
protected override IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
{
|
||||
Debug.Log("ViveAnchor HookGetInstanceProcAddr() ");
|
||||
return ViveInterceptors.Instance.HookGetInstanceProcAddr(func);
|
||||
}
|
||||
public override readonly string ToString() {
|
||||
if (name == null)
|
||||
return string.Empty;
|
||||
return System.Text.Encoding.UTF8.GetString(name).TrimEnd('\0');
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
//Debug.Log("VIVEAnchor OnInstanceCreate() ");
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
{
|
||||
Debug.LogWarning("ViveAnchor OnInstanceCreate() " + kOpenxrExtensionString + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
public struct XrSpatialAnchorCreateInfoHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
public XrSpace space;
|
||||
public XrPosef poseInSpace;
|
||||
public XrSpatialAnchorNameHTC name;
|
||||
}
|
||||
|
||||
m_XrInstance = xrInstance;
|
||||
//Debug.Log("OnInstanceCreate() " + m_XrInstance);
|
||||
CommonWrapper.Instance.OnInstanceCreate(xrInstance, xrGetInstanceProcAddr);
|
||||
SpaceWrapper.Instance.OnInstanceCreate(xrInstance, CommonWrapper.Instance.GetInstanceProcAddr);
|
||||
public struct XrPersistedAnchorCollectionAcquireInfoHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
}
|
||||
|
||||
return GetXrFunctionDelegates(m_XrInstance);
|
||||
}
|
||||
public struct XrPersistedAnchorCollectionAcquireCompletionHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
public XrResult futureResult;
|
||||
public System.IntPtr persistedAnchorCollection;
|
||||
}
|
||||
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
CommonWrapper.Instance.OnInstanceDestroy();
|
||||
SpaceWrapper.Instance.OnInstanceDestroy();
|
||||
}
|
||||
public struct XrSpatialAnchorPersistInfoHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
public XrSpace anchor;
|
||||
public XrSpatialAnchorNameHTC persistedAnchorName;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
Debug.Log("ViveAnchor OnSessionCreate() ");
|
||||
public struct XrSpatialAnchorFromPersistedAnchorCreateInfoHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
public System.IntPtr persistedAnchorCollection;
|
||||
public XrSpatialAnchorNameHTC persistedAnchorName;
|
||||
public XrSpatialAnchorNameHTC spatialAnchorName;
|
||||
}
|
||||
|
||||
// here's one way you can grab the session
|
||||
Debug.Log($"EXT: Got xrSession: {xrSession}");
|
||||
session = xrSession;
|
||||
}
|
||||
public struct XrSpatialAnchorFromPersistedAnchorCreateCompletionHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
public XrResult futureResult;
|
||||
public XrSpace anchor;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnSessionBegin(ulong xrSession)
|
||||
{
|
||||
Debug.Log("ViveAnchor OnSessionBegin() ");
|
||||
Debug.Log($"EXT: xrBeginSession: {xrSession}");
|
||||
}
|
||||
public struct XrPersistedAnchorPropertiesGetInfoHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public System.IntPtr next;
|
||||
public uint maxPersistedAnchorCount;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnSessionEnd(ulong xrSession)
|
||||
{
|
||||
Debug.Log("ViveAnchor OnSessionEnd() ");
|
||||
Debug.Log($"EXT: about to xrEndSession: {xrSession}");
|
||||
}
|
||||
#endregion
|
||||
|
||||
// XXX Every millisecond the AppSpace switched from one space to another space. I don't know what is going on.
|
||||
//private ulong appSpace;
|
||||
//protected override void OnAppSpaceChange(ulong space)
|
||||
//{
|
||||
// //Debug.Log($"VIVEAnchor OnAppSpaceChange({appSpace} -> {space})");
|
||||
// appSpace = space;
|
||||
//}
|
||||
#region delegates and delegate instances
|
||||
public delegate XrResult DelegateXrCreateSpatialAnchorHTC(XrSession session, ref XrSpatialAnchorCreateInfoHTC createInfo, ref XrSpace anchor);
|
||||
public delegate XrResult DelegateXrGetSpatialAnchorNameHTC(XrSpace anchor, ref XrSpatialAnchorNameHTC name);
|
||||
public delegate XrResult DelegateXrAcquirePersistedAnchorCollectionAsyncHTC(XrSession session, ref XrPersistedAnchorCollectionAcquireInfoHTC acquireInfo, out IntPtr future);
|
||||
public delegate XrResult DelegateXrAcquirePersistedAnchorCollectionCompleteHTC(IntPtr future, out XrPersistedAnchorCollectionAcquireCompletionHTC completion);
|
||||
public delegate XrResult DelegateXrReleasePersistedAnchorCollectionHTC(IntPtr persistedAnchorCollection);
|
||||
public delegate XrResult DelegateXrPersistSpatialAnchorAsyncHTC(XrPersistedAnchorCollectionHTC persistedAnchorCollection, ref XrSpatialAnchorPersistInfoHTC persistInfo, out IntPtr future);
|
||||
public delegate XrResult DelegateXrPersistSpatialAnchorCompleteHTC(IntPtr future, out FutureWrapper.XrFutureCompletionEXT completion);
|
||||
public delegate XrResult DelegateXrUnpersistSpatialAnchorHTC(IntPtr persistedAnchorCollection, ref XrSpatialAnchorNameHTC persistedAnchorName);
|
||||
public delegate XrResult DelegateXrEnumeratePersistedAnchorNamesHTC( IntPtr persistedAnchorCollection, uint persistedAnchorNameCapacityInput, ref uint persistedAnchorNameCountOutput, [Out] XrSpatialAnchorNameHTC[] persistedAnchorNames);
|
||||
public delegate XrResult DelegateXrCreateSpatialAnchorFromPersistedAnchorAsyncHTC(XrSession session, ref XrSpatialAnchorFromPersistedAnchorCreateInfoHTC spatialAnchorCreateInfo, out IntPtr future);
|
||||
public delegate XrResult DelegateXrCreateSpatialAnchorFromPersistedAnchorCompleteHTC(IntPtr future, out XrSpatialAnchorFromPersistedAnchorCreateCompletionHTC completion);
|
||||
public delegate XrResult DelegateXrClearPersistedAnchorsHTC(IntPtr persistedAnchorCollection);
|
||||
public delegate XrResult DelegateXrGetPersistedAnchorPropertiesHTC(IntPtr persistedAnchorCollection, ref XrPersistedAnchorPropertiesGetInfoHTC getInfo);
|
||||
public delegate XrResult DelegateXrExportPersistedAnchorHTC(IntPtr persistedAnchorCollection, ref XrSpatialAnchorNameHTC persistedAnchorName, uint dataCapacityInput, ref uint dataCountOutput, [Out] byte[] data);
|
||||
public delegate XrResult DelegateXrImportPersistedAnchorHTC(IntPtr persistedAnchorCollection, uint dataCount, [In] byte[] data);
|
||||
public delegate XrResult DelegateXrGetPersistedAnchorNameFromBufferHTC(IntPtr persistedAnchorCollection, uint bufferCount, byte[] buffer, ref XrSpatialAnchorNameHTC name);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
m_XrSystemId = xrSystem;
|
||||
Debug.Log("ViveAnchor OnSystemChange() " + m_XrSystemId);
|
||||
}
|
||||
DelegateXrCreateSpatialAnchorHTC XrCreateSpatialAnchorHTC;
|
||||
DelegateXrGetSpatialAnchorNameHTC XrGetSpatialAnchorNameHTC;
|
||||
DelegateXrAcquirePersistedAnchorCollectionAsyncHTC XrAcquirePersistedAnchorCollectionAsyncHTC;
|
||||
DelegateXrAcquirePersistedAnchorCollectionCompleteHTC XrAcquirePersistedAnchorCollectionCompleteHTC;
|
||||
DelegateXrReleasePersistedAnchorCollectionHTC XrReleasePersistedAnchorCollectionHTC;
|
||||
DelegateXrPersistSpatialAnchorAsyncHTC XrPersistSpatialAnchorAsyncHTC;
|
||||
DelegateXrPersistSpatialAnchorCompleteHTC XrPersistSpatialAnchorCompleteHTC;
|
||||
DelegateXrUnpersistSpatialAnchorHTC XrUnpersistSpatialAnchorHTC;
|
||||
DelegateXrEnumeratePersistedAnchorNamesHTC XrEnumeratePersistedAnchorNamesHTC;
|
||||
DelegateXrCreateSpatialAnchorFromPersistedAnchorAsyncHTC XrCreateSpatialAnchorFromPersistedAnchorAsyncHTC;
|
||||
DelegateXrCreateSpatialAnchorFromPersistedAnchorCompleteHTC XrCreateSpatialAnchorFromPersistedAnchorCompleteHTC;
|
||||
DelegateXrClearPersistedAnchorsHTC XrClearPersistedAnchorsHTC;
|
||||
DelegateXrGetPersistedAnchorPropertiesHTC XrGetPersistedAnchorPropertiesHTC;
|
||||
DelegateXrExportPersistedAnchorHTC XrExportPersistedAnchorHTC;
|
||||
DelegateXrImportPersistedAnchorHTC XrImportPersistedAnchorHTC;
|
||||
DelegateXrGetPersistedAnchorNameFromBufferHTC XrGetPersistedAnchorNameFromBufferHTC;
|
||||
|
||||
#endregion delegates and delegate instances
|
||||
|
||||
#endregion override functions
|
||||
#region override functions
|
||||
|
||||
private bool GetXrFunctionDelegates(XrInstance xrInstance)
|
||||
{
|
||||
Debug.Log("ViveAnchor GetXrFunctionDelegates() ");
|
||||
protected override IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
{
|
||||
// For LocateSpace, need WaitFrame's predictedDisplayTime.
|
||||
ViveInterceptors.Instance.AddRequiredFunction("xrWaitFrame");
|
||||
return ViveInterceptors.Instance.HookGetInstanceProcAddr(func);
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate GetAddr = CommonWrapper.Instance.GetInstanceProcAddr; // shorter name
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, xrInstance, "xrCreateSpatialAnchorHTC", out XrCreateSpatialAnchorHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, xrInstance, "xrGetSpatialAnchorNameHTC", out XrGetSpatialAnchorNameHTC);
|
||||
/// <inheritdoc />
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
#if FAKE_DATA
|
||||
Debug.LogError("ViveAnchor OnInstanceCreate() Use FakeData");
|
||||
useFakeData = true;
|
||||
#endif
|
||||
IsInited = false;
|
||||
bool ret = true;
|
||||
ret &= CommonWrapper.Instance.OnInstanceCreate(xrInstance, xrGetInstanceProcAddr);
|
||||
ret &= SpaceWrapper.Instance.OnInstanceCreate(xrInstance, xrGetInstanceProcAddr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
if (!ret)
|
||||
{
|
||||
Debug.LogError("ViveAnchor OnInstanceCreate() failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
#region functions of extension
|
||||
/// <summary>
|
||||
/// Helper function to get this feature' properties.
|
||||
/// See <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystemProperties">xrGetSystemProperties</see>
|
||||
/// </summary>
|
||||
public XrResult GetProperties(out XrSystemAnchorPropertiesHTC anchorProperties)
|
||||
{
|
||||
anchorProperties = new XrSystemAnchorPropertiesHTC();
|
||||
anchorProperties.type = XrStructureType.XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC;
|
||||
//Debug.Log("VIVEAnchor OnInstanceCreate() ");
|
||||
if (!OpenXRRuntime.IsExtensionEnabled("XR_HTC_anchor") && !useFakeData)
|
||||
{
|
||||
Debug.LogWarning("ViveAnchor OnInstanceCreate() XR_HTC_anchor is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
IsInited = GetXrFunctionDelegates(xrInstance);
|
||||
|
||||
if (!IsInited)
|
||||
{
|
||||
Debug.LogError("ViveAnchor OnInstanceCreate() failed to get function delegates.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_XrInstance = xrInstance;
|
||||
|
||||
bool hasFuture = FutureWrapper.Instance.OnInstanceCreate(xrInstance, xrGetInstanceProcAddr);
|
||||
// No error log because future will print.
|
||||
#if FAKE_DATA
|
||||
hasFuture = true;
|
||||
#endif
|
||||
IsPAInited = false;
|
||||
bool hasPersistedAnchor = false;
|
||||
do
|
||||
{
|
||||
if (!hasFuture)
|
||||
{
|
||||
Debug.LogWarning("ViveAnchor OnInstanceCreate() XR_HTC_anchor_persistence is NOT enabled because no XR_EXT_future.");
|
||||
hasPersistedAnchor = false;
|
||||
break;
|
||||
}
|
||||
|
||||
hasPersistedAnchor = enablePersistedAnchor && OpenXRRuntime.IsExtensionEnabled("XR_HTC_anchor_persistence");
|
||||
#if FAKE_DATA
|
||||
hasPersistedAnchor = enablePersistedAnchor;
|
||||
#endif
|
||||
} while(false);
|
||||
|
||||
//Debug.Log("OnInstanceCreate() " + m_XrInstance);
|
||||
if (hasPersistedAnchor)
|
||||
IsPAInited = GetXrFunctionDelegatesPersistance(xrInstance);
|
||||
if (!IsPAInited)
|
||||
Debug.LogWarning("ViveAnchor OnInstanceCreate() XR_HTC_anchor_persistence is NOT enabled.");
|
||||
|
||||
return IsInited;
|
||||
}
|
||||
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
m_XrInstance = 0;
|
||||
|
||||
IsInited = false;
|
||||
IsPAInited = false;
|
||||
|
||||
CommonWrapper.Instance.OnInstanceDestroy();
|
||||
SpaceWrapper.Instance.OnInstanceDestroy();
|
||||
FutureWrapper.Instance.OnInstanceDestroy();
|
||||
Debug.Log("ViveAnchor: OnInstanceDestroy()");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
//Debug.Log("ViveAnchor OnSessionCreate() ");
|
||||
session = xrSession;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
//Debug.Log("ViveAnchor OnSessionDestroy() ");
|
||||
session = 0;
|
||||
}
|
||||
|
||||
// XXX Every millisecond the AppSpace switched from one space to another space. I don't know what is going on.
|
||||
//private ulong appSpace;
|
||||
//protected override void OnAppSpaceChange(ulong space)
|
||||
//{
|
||||
// //Debug.Log($"VIVEAnchor OnAppSpaceChange({appSpace} -> {space})");
|
||||
// appSpace = space;
|
||||
//}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
m_XrSystemId = xrSystem;
|
||||
//Debug.Log("ViveAnchor OnSystemChange() " + m_XrSystemId);
|
||||
}
|
||||
|
||||
#endregion override functions
|
||||
|
||||
private bool GetXrFunctionDelegates(XrInstance inst)
|
||||
{
|
||||
Debug.Log("ViveAnchor GetXrFunctionDelegates() ");
|
||||
|
||||
bool ret = true;
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate GetAddr = CommonWrapper.Instance.GetInstanceProcAddr; // shorter name
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrCreateSpatialAnchorHTC", out XrCreateSpatialAnchorHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrGetSpatialAnchorNameHTC", out XrGetSpatialAnchorNameHTC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool GetXrFunctionDelegatesPersistance(XrInstance inst)
|
||||
{
|
||||
Debug.Log("ViveAnchor GetXrFunctionDelegatesPersistance() ");
|
||||
bool ret = true;
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate GetAddr = CommonWrapper.Instance.GetInstanceProcAddr; // shorter name
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrAcquirePersistedAnchorCollectionAsyncHTC", out XrAcquirePersistedAnchorCollectionAsyncHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrAcquirePersistedAnchorCollectionCompleteHTC", out XrAcquirePersistedAnchorCollectionCompleteHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrReleasePersistedAnchorCollectionHTC", out XrReleasePersistedAnchorCollectionHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrPersistSpatialAnchorAsyncHTC", out XrPersistSpatialAnchorAsyncHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrPersistSpatialAnchorCompleteHTC", out XrPersistSpatialAnchorCompleteHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrUnpersistSpatialAnchorHTC", out XrUnpersistSpatialAnchorHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrEnumeratePersistedAnchorNamesHTC", out XrEnumeratePersistedAnchorNamesHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrCreateSpatialAnchorFromPersistedAnchorAsyncHTC", out XrCreateSpatialAnchorFromPersistedAnchorAsyncHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrCreateSpatialAnchorFromPersistedAnchorCompleteHTC", out XrCreateSpatialAnchorFromPersistedAnchorCompleteHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrClearPersistedAnchorsHTC", out XrClearPersistedAnchorsHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrGetPersistedAnchorPropertiesHTC", out XrGetPersistedAnchorPropertiesHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrExportPersistedAnchorHTC", out XrExportPersistedAnchorHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrImportPersistedAnchorHTC", out XrImportPersistedAnchorHTC);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, inst, "xrGetPersistedAnchorNameFromBufferHTC", out XrGetPersistedAnchorNameFromBufferHTC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#region functions of extension
|
||||
/// <summary>
|
||||
/// Helper function to get this feature's properties.
|
||||
/// See <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystemProperties">xrGetSystemProperties</see>
|
||||
/// </summary>
|
||||
/// <param name="anchorProperties">Output parameter to hold anchor properties.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult GetProperties(out XrSystemAnchorPropertiesHTC anchorProperties)
|
||||
{
|
||||
anchorProperties = new XrSystemAnchorPropertiesHTC();
|
||||
anchorProperties.type = XrStructureType.XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC;
|
||||
|
||||
#if FAKE_DATA
|
||||
if (Application.isEditor)
|
||||
{
|
||||
anchorProperties.type = XrStructureType.XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC;
|
||||
anchorProperties.supportsAnchor = true;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
if (Application.isEditor)
|
||||
{
|
||||
anchorProperties.type = XrStructureType.XR_TYPE_SYSTEM_ANCHOR_PROPERTIES_HTC;
|
||||
anchorProperties.supportsAnchor = true;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
return CommonWrapper.Instance.GetProperties(m_XrInstance, m_XrSystemId, ref anchorProperties);
|
||||
}
|
||||
return CommonWrapper.Instance.GetProperties(m_XrInstance, m_XrSystemId, ref anchorProperties);
|
||||
}
|
||||
|
||||
public XrResult CreateSpatialAnchor(XrSpatialAnchorCreateInfoHTC createInfo, out XrSpace anchor)
|
||||
{
|
||||
anchor = default;
|
||||
#if FAKE_DATA
|
||||
if (Application.isEditor)
|
||||
return XrResult.XR_SUCCESS;
|
||||
#endif
|
||||
var ret = XrCreateSpatialAnchorHTC(session, ref createInfo, ref anchor);
|
||||
Debug.Log("ViveAnchor CreateSpatialAnchor() r=" + ret + ", a=" + anchor + ", bs=" + createInfo.space +
|
||||
", pos=(" + createInfo.poseInSpace.position.x + "," + createInfo.poseInSpace.position.y + "," + createInfo.poseInSpace.position.z +
|
||||
"), rot=(" + createInfo.poseInSpace.orientation.x + "," + createInfo.poseInSpace.orientation.y + "," + createInfo.poseInSpace.orientation.z + "," + createInfo.poseInSpace.orientation.w +
|
||||
"), n=" + createInfo.name.name);
|
||||
return ret;
|
||||
}
|
||||
/// <summary>
|
||||
/// The CreateSpatialAnchor function creates a spatial anchor with specified base space and pose in the space.
|
||||
/// The anchor is represented by an XrSpace and its pose can be tracked via xrLocateSpace.
|
||||
/// Once the anchor is no longer needed, call xrDestroySpace to erase the anchor.
|
||||
/// </summary>
|
||||
/// <param name="createInfo">Information required to create the spatial anchor.</param>
|
||||
/// <param name="anchor">Output parameter to hold the created anchor.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult CreateSpatialAnchor(XrSpatialAnchorCreateInfoHTC createInfo, out XrSpace anchor)
|
||||
{
|
||||
anchor = default;
|
||||
if (!IsInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
if (session == 0)
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
|
||||
public XrResult GetSpatialAnchorName(XrSpace anchor, out XrSpatialAnchorNameHTC name)
|
||||
{
|
||||
name = default;
|
||||
#if FAKE_DATA
|
||||
if (Application.isEditor)
|
||||
{
|
||||
name.name = "fake anchor";
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
return XrGetSpatialAnchorNameHTC(anchor, ref name);
|
||||
}
|
||||
var ret = XrCreateSpatialAnchorHTC(session, ref createInfo, ref anchor);
|
||||
//Debug.Log("ViveAnchor CreateSpatialAnchor() r=" + ret + ", a=" + anchor + ", bs=" + createInfo.space +
|
||||
// ", pos=(" + createInfo.poseInSpace.position.x + "," + createInfo.poseInSpace.position.y + "," + createInfo.poseInSpace.position.z +
|
||||
// "), rot=(" + createInfo.poseInSpace.orientation.x + "," + createInfo.poseInSpace.orientation.y + "," + createInfo.poseInSpace.orientation.z + "," + createInfo.poseInSpace.orientation.w +
|
||||
// "), n=" + createInfo.name.name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// The GetSpatialAnchorName function retrieves the name of the spatial anchor.
|
||||
/// </summary>
|
||||
/// <param name="anchor">The XrSpace representing the anchor.</param>
|
||||
/// <param name="name">Output parameter to hold the name of the anchor.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult GetSpatialAnchorName(XrSpace anchor, out XrSpatialAnchorNameHTC name)
|
||||
{
|
||||
name = new XrSpatialAnchorNameHTC();
|
||||
if (!IsInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
return XrGetSpatialAnchorNameHTC(anchor, ref name);
|
||||
}
|
||||
|
||||
#region tools for user
|
||||
/// <summary>
|
||||
/// If the extension is supported and enabled, return true.
|
||||
/// </summary>
|
||||
/// <returns>True if persisted anchor extension is supported, false otherwise.</returns>
|
||||
public bool IsPersistedAnchorSupported()
|
||||
{
|
||||
return IsPAInited;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// According to XRInputSubsystem's tracking origin mode, return the corresponding XrSpace.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public XrSpace GetTrackingSpace()
|
||||
{
|
||||
var s = GetCurrentAppSpace();
|
||||
Debug.Log("ViveAnchor GetTrackingSpace() s=" + s);
|
||||
return s;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a persisted anchor collection. This collection can be used to persist spatial anchors across sessions.
|
||||
/// Many persisted anchor APIs need a persisted anchor collection to operate.
|
||||
/// </summary>
|
||||
/// <param name="future">Output the async future handle. Check the future to get the PersitedAnchorCollection handle.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult AcquirePersistedAnchorCollectionAsync(out IntPtr future)
|
||||
{
|
||||
future = IntPtr.Zero;
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
if (session == 0)
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
|
||||
XrPersistedAnchorCollectionAcquireInfoHTC acquireInfo = new XrPersistedAnchorCollectionAcquireInfoHTC
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_PERSISTED_ANCHOR_COLLECTION_ACQUIRE_INFO_HTC,
|
||||
next = IntPtr.Zero,
|
||||
};
|
||||
|
||||
return XrAcquirePersistedAnchorCollectionAsyncHTC(session, ref acquireInfo, out future);
|
||||
}
|
||||
|
||||
public XrResult AcquirePersistedAnchorCollectionComplete(IntPtr future, out XrPersistedAnchorCollectionAcquireCompletionHTC completion)
|
||||
{
|
||||
completion = new XrPersistedAnchorCollectionAcquireCompletionHTC();
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
|
||||
return XrAcquirePersistedAnchorCollectionCompleteHTC(future, out completion);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the persisted anchor collection.
|
||||
/// </summary>
|
||||
/// <param name="persistedAnchorCollection">The persisted anchor collection to be destroyed.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult ReleasePersistedAnchorCollection(IntPtr persistedAnchorCollection)
|
||||
{
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
|
||||
return XrReleasePersistedAnchorCollectionHTC(persistedAnchorCollection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Persists a spatial anchor with the given name. The name should be unique.
|
||||
/// </summary>
|
||||
/// <param name="persistedAnchorCollection">The persisted anchor collection to operate.</param>
|
||||
/// <param name="anchor">The spatial anchor to be persisted.</param>
|
||||
/// <param name="name">The name of the persisted anchor.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult PersistSpatialAnchorAsync(IntPtr persistedAnchorCollection, XrSpace anchor, XrSpatialAnchorNameHTC name, out IntPtr future)
|
||||
{
|
||||
future = IntPtr.Zero;
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
|
||||
XrSpatialAnchorPersistInfoHTC persistInfo = new XrSpatialAnchorPersistInfoHTC
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_SPATIAL_ANCHOR_PERSIST_INFO_HTC,
|
||||
anchor = anchor,
|
||||
persistedAnchorName = name
|
||||
};
|
||||
return XrPersistSpatialAnchorAsyncHTC(persistedAnchorCollection, ref persistInfo, out future);
|
||||
}
|
||||
|
||||
public XrResult PersistSpatialAnchorComplete(IntPtr future, out FutureWrapper.XrFutureCompletionEXT completion)
|
||||
{
|
||||
completion = new FutureWrapper.XrFutureCompletionEXT() {
|
||||
type = XrStructureType.XR_TYPE_FUTURE_COMPLETION_EXT,
|
||||
next = IntPtr.Zero,
|
||||
futureResult = XrResult.XR_SUCCESS
|
||||
};
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
|
||||
return XrPersistSpatialAnchorCompleteHTC(future, out completion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpersists the anchor with the given name.
|
||||
/// </summary>
|
||||
/// <param name="persistedAnchorCollection">The persisted anchor collection to operate.</param>
|
||||
/// <param name="name">The name of the anchor to be unpersisted.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult UnpersistSpatialAnchor(IntPtr persistedAnchorCollection, XrSpatialAnchorNameHTC name)
|
||||
{
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
|
||||
return XrUnpersistSpatialAnchorHTC(persistedAnchorCollection, ref name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates all persisted anchor names.
|
||||
/// </summary>
|
||||
/// <param name="persistedAnchorCollection">The persisted anchor collection to operate.</param>
|
||||
/// <param name="persistedAnchorNameCapacityInput">The capacity of the input buffer.</param>
|
||||
/// <param name="persistedAnchorNameCountOutput">Output parameter to hold the count of persisted anchor names.</param>
|
||||
/// <param name="persistedAnchorNames">Output parameter to hold the names of persisted anchors.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult EnumeratePersistedAnchorNames(IntPtr persistedAnchorCollection, uint persistedAnchorNameCapacityInput,
|
||||
ref uint persistedAnchorNameCountOutput, ref XrSpatialAnchorNameHTC[] persistedAnchorNames)
|
||||
{
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
|
||||
return XrEnumeratePersistedAnchorNamesHTC(persistedAnchorCollection, persistedAnchorNameCapacityInput, ref persistedAnchorNameCountOutput, persistedAnchorNames);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a spatial anchor from a persisted anchor.
|
||||
/// </summary>
|
||||
/// <param name="spatialAnchorCreateInfo">Information required to create the spatial anchor from persisted anchor.</param>
|
||||
/// <param name="anchor">Output parameter to hold the created spatial anchor.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult CreateSpatialAnchorFromPersistedAnchorAsync(XrSpatialAnchorFromPersistedAnchorCreateInfoHTC spatialAnchorCreateInfo, out IntPtr future)
|
||||
{
|
||||
future = IntPtr.Zero;
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
if (session == 0)
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
return XrCreateSpatialAnchorFromPersistedAnchorAsyncHTC(session, ref spatialAnchorCreateInfo, out future);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the future is ready, call this function to get the result.
|
||||
/// </summary>
|
||||
/// <param name="future"></param>
|
||||
/// <param name="completion"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult CreateSpatialAnchorFromPersistedAnchorComplete(IntPtr future, out XrSpatialAnchorFromPersistedAnchorCreateCompletionHTC completion)
|
||||
{
|
||||
completion = new XrSpatialAnchorFromPersistedAnchorCreateCompletionHTC()
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_COMPLETION_HTC,
|
||||
next = IntPtr.Zero,
|
||||
futureResult = XrResult.XR_SUCCESS,
|
||||
anchor = 0
|
||||
};
|
||||
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
return XrCreateSpatialAnchorFromPersistedAnchorCompleteHTC(future, out completion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all persisted anchors.
|
||||
/// </summary>
|
||||
/// <param name="persistedAnchorCollection">The persisted anchor collection to operate.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult ClearPersistedAnchors(IntPtr persistedAnchorCollection)
|
||||
{
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
return XrClearPersistedAnchorsHTC(persistedAnchorCollection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the properties of the persisted anchor.
|
||||
/// </summary>
|
||||
/// <param name="persistedAnchorCollection">The persisted anchor collection to operate.</param>
|
||||
/// <param name="getInfo">Output parameter to hold the properties of the persisted anchor.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult GetPersistedAnchorProperties(IntPtr persistedAnchorCollection, out XrPersistedAnchorPropertiesGetInfoHTC getInfo)
|
||||
{
|
||||
getInfo = new XrPersistedAnchorPropertiesGetInfoHTC
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_PERSISTED_ANCHOR_PROPERTIES_GET_INFO_HTC
|
||||
};
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
return XrGetPersistedAnchorPropertiesHTC(persistedAnchorCollection, ref getInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports the persisted anchor to a buffer. The buffer can be used to import the anchor later or save to a file.
|
||||
/// </summary>
|
||||
/// <param name="persistedAnchorCollection">The persisted anchor collection to operate.</param>
|
||||
/// <param name="persistedAnchorName">The name of the persisted anchor to be exported.</param>
|
||||
/// <param name="data">Output parameter to hold the buffer containing the exported anchor.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult ExportPersistedAnchor(IntPtr persistedAnchorCollection, XrSpatialAnchorNameHTC persistedAnchorName, out byte[] data)
|
||||
{
|
||||
data = null;
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
uint dataCountOutput = 0;
|
||||
uint dataCapacityInput = 0;
|
||||
XrResult ret = XrExportPersistedAnchorHTC(persistedAnchorCollection, ref persistedAnchorName, dataCapacityInput, ref dataCountOutput, null);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
{
|
||||
Debug.LogError("ExportPersistedAnchor failed to get data size. ret=" + ret);
|
||||
data = null;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dataCapacityInput = dataCountOutput;
|
||||
data = new byte[dataCountOutput];
|
||||
ret = XrExportPersistedAnchorHTC(persistedAnchorCollection, ref persistedAnchorName, dataCapacityInput, ref dataCountOutput, data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports the persisted anchor from a buffer. The buffer should be created by ExportPersistedAnchor.
|
||||
/// </summary>
|
||||
/// <param name="persistedAnchorCollection">The persisted anchor collection to operate.</param>
|
||||
/// <param name="data">The buffer containing the persisted anchor data.</param>
|
||||
/// <returns>XrResult indicating success or failure.</returns>
|
||||
public XrResult ImportPersistedAnchor(IntPtr persistedAnchorCollection, byte[] data)
|
||||
{
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
|
||||
return XrImportPersistedAnchorHTC(persistedAnchorCollection, (uint)data.Length, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the persisted anchor from a buffer. The buffer should be created by ExportPersistedAnchor.
|
||||
/// </summary>
|
||||
/// <param name="persistedAnchorCollection"></param>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult GetPersistedAnchorNameFromBuffer(IntPtr persistedAnchorCollection, byte[] buffer, out XrSpatialAnchorNameHTC name)
|
||||
{
|
||||
name = new XrSpatialAnchorNameHTC();
|
||||
if (!IsPAInited)
|
||||
return XrResult.XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||
|
||||
if (buffer == null)
|
||||
return XrResult.XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
return XrGetPersistedAnchorNameFromBufferHTC(persistedAnchorCollection, (uint)buffer.Length, buffer, ref name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region tools for user
|
||||
|
||||
/// <summary>
|
||||
/// According to XRInputSubsystem's tracking origin mode, return the corresponding XrSpace.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public XrSpace GetTrackingSpace()
|
||||
{
|
||||
var s = GetCurrentAppSpace();
|
||||
//Debug.Log("ViveAnchor GetTrackingSpace() s=" + s);
|
||||
return s;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user