Files
VIVE-OpenXR-Unity/com.htc.upm.vive.openxr/Runtime/Toolkits/Anchor/AnchorManager.cs
Sean Lu(呂祥榮) 7f2a459592 version 2.3.0
2024-05-15 14:09:18 +08:00

180 lines
6.1 KiB
C#

// Copyright HTC Corporation All Rights Reserved.
using System;
using UnityEngine;
using UnityEngine.XR.OpenXR;
using VIVE.OpenXR.Feature;
using VIVE.OpenXR.Anchor;
using static VIVE.OpenXR.Anchor.ViveAnchor;
namespace VIVE.OpenXR.Toolkits.Anchor
{
public static class AnchorManager
{
static ViveAnchor feature = null;
static bool isSupported = false;
static void CheckFeature()
{
if (feature != null) return;
feature = OpenXRSettings.Instance.GetFeature<ViveAnchor>();
if (feature == null)
throw new NotSupportedException("ViveAnchor feature is not enabled");
}
/// <summary>
/// Helper to get the extention feature instance.
/// </summary>
/// <returns></returns>
public static ViveAnchor GetFeature()
{
try
{
CheckFeature();
}
catch (NotSupportedException)
{
Debug.LogWarning("ViveAnchor feature is not enabled");
return null;
}
return feature;
}
/// <summary>
/// Check if the extension is supported.
/// </summary>
/// <returns></returns>
public static bool IsSupported()
{
if (GetFeature() == null) return false;
if (isSupported) return true;
var ret = false;
if (feature.GetProperties(out XrSystemAnchorPropertiesHTC properties) == XrResult.XR_SUCCESS)
{
Debug.Log("Anchor: IsSupported() properties.supportedFeatures: " + properties.supportsAnchor);
ret = properties.supportsAnchor;
isSupported = ret;
}
else
{
Debug.Log("Anchor: IsSupported() GetSystemProperties failed.");
}
return ret;
}
/// <summary>
/// Create a spatial anchor at tracking space (Camera Rig).
/// </summary>
/// <param name="pose">The related pose to the tracking space (Camera Rig)</param>
/// <returns>Anchor container</returns>
public static Anchor CreateAnchor(Pose pose, string name)
{
try
{
CheckFeature();
XrSpace baseSpace = feature.GetTrackingSpace();
XrSpatialAnchorCreateInfoHTC createInfo = new XrSpatialAnchorCreateInfoHTC();
createInfo.type = XrStructureType.XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_HTC;
createInfo.poseInSpace = new XrPosef();
createInfo.poseInSpace.position = pose.position.ToOpenXRVector();
createInfo.poseInSpace.orientation = pose.rotation.ToOpenXRQuaternion();
createInfo.name.name = name;
createInfo.space = baseSpace;
if (feature.CreateSpatialAnchor(createInfo, out XrSpace anchor) == XrResult.XR_SUCCESS)
{
return new Anchor(anchor, name);
}
} catch (Exception) { }
return null;
}
public static bool GetSpatialAnchorName(Anchor anchor, out string name)
{
return GetSpatialAnchorName(anchor.GetXrSpace(), out name);
}
public static bool GetSpatialAnchorName(XrSpace anchor, out string name)
{
name = "";
CheckFeature();
XrResult ret = feature.GetSpatialAnchorName(anchor, out XrSpatialAnchorNameHTC xrName);
if (ret == XrResult.XR_SUCCESS)
name = xrName.name;
return ret == XrResult.XR_SUCCESS;
}
/// <summary>
/// Get the XrSpace stand for current tracking space.
/// </summary>
/// <returns></returns>
public static XrSpace GetTrackingSpace()
{
CheckFeature();
return feature.GetTrackingSpace();
}
/// <summary>
/// Get the pose related to current tracking space. Only when position and orientation are both valid, the pose is valid.
/// </summary>
/// <param name="anchor"></param>
/// <param name="pose"></param>
/// <returns>true if both position and rotation are valid.</returns>
public static bool GetTrackingSpacePose(Anchor anchor, out Pose pose)
{
var sw = SpaceWrapper.Instance;
return anchor.GetRelatedPose(feature.GetTrackingSpace(), ViveInterceptors.Instance.GetPredictTime(), out pose);
}
/// <summary>
/// Anchor is a named Space. It can be used to create a spatial anchor, or get the anchor's name.
/// After use it, you should call Dispose() to release the anchor.
/// </summary>
public class Anchor : VIVE.OpenXR.Feature.Space
{
/// <summary>
/// The anchor's name
/// </summary>
string name;
/// <summary>
/// The anchor's name
/// </summary>
public string Name
{
get
{
if (string.IsNullOrEmpty(name))
name = GetSpatialAnchorName();
return name;
}
}
internal Anchor(XrSpace anchor, string name) : base(anchor)
{
// Get the current tracking space.
this.name = name;
}
internal Anchor(Anchor other) : base(other.space)
{
// Get the current tracking space.
name = other.name;
}
/// <summary>
/// Get the anchor's name by using this anchor's handle, instead of the anchor's Name. This will update the anchor's Name.
/// </summary>
/// <returns></returns>
public string GetSpatialAnchorName()
{
AnchorManager.CheckFeature();
if (AnchorManager.GetSpatialAnchorName(this, out string name))
return name;
return null;
}
}
}
}