version 2.0.0
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4126580e0f3096546977cff4f5203eb1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1850b50609fc1db458be9f8f11c62852
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
# 12.7. XR_KHR_composition_layer_cylinder
|
||||
## Name String
|
||||
XR_KHR_composition_layer_cylinder
|
||||
## Revision
|
||||
4
|
||||
## New Object Types
|
||||
## New Enum Constants
|
||||
[XrStructureType](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrStructureType) enumeration is extended with:
|
||||
- XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR
|
||||
## New Enums
|
||||
## New Structures
|
||||
- [XrCompositionLayerCylinderKHR ](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrCompositionLayerCylinderKHR)
|
||||
## New Functions
|
||||
|
||||
## VIVE Plugin
|
||||
|
||||
Enable "VIVE XR Composition Layer" in "Project Settings > XR Plugin-in Management > OpenXR > Android Tab > OpenXR Feature Groups" in order to use the Composition Layer feature provided by the VIVE plugin.
|
||||
|
||||
The plugin provides scripts and resources for setting up Composition Layers quickly and easily.
|
||||
There are two scripts which can be attached to **GameObjects**:
|
||||
- CompositionLayer: For setting up a basic Composition Layer. Located at: *\<VIVE OpenXR path\>/Runtime/CompositionLayer/Scripts/CompositionLayer.cs*
|
||||
- CompositionLayerUICanvas: For setting up a Composition Layer which renders a Unity UI Canvas. Located at: *\<VIVE OpenXR path\>/Runtime/CompositionLayer/Scripts/CompositionLayerUICanvas.cs*
|
||||
|
||||
To see how the two scripts above can be used, refer to the samples located at: *\<VIVE OpenXR sample path\>/CompositionLayer/Scenes*
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbab5ef182d5d34438925945775e2443
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f29d9246fa53ed5469160eb0ec165fb8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,509 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using AOT;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Composition Layer",
|
||||
Desc = "Enable this feature to use the Composition Layer.",
|
||||
Company = "HTC",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionStrings,
|
||||
Version = "1.0.0",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class ViveCompositionLayer : OpenXRFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.ViveCompositionLayer";
|
||||
static void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
static void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
static void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <summary>
|
||||
/// Enable auto fallback or Not.
|
||||
/// </summary>
|
||||
public bool enableAutoFallback = false;
|
||||
|
||||
/// <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.compositionlayer";
|
||||
|
||||
public const string kOpenxrExtensionStrings = "";
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
private bool m_XrInstanceCreated = false;
|
||||
public bool XrInstanceCreated
|
||||
{
|
||||
get { return m_XrInstanceCreated; }
|
||||
}
|
||||
private XrInstance m_XrInstance = 0;
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
//foreach (string kOpenxrExtensionString in kOpenxrExtensionStrings.Split(' '))
|
||||
//{
|
||||
// if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
// {
|
||||
// WARNING("OnInstanceCreate() " + kOpenxrExtensionString + " is NOT enabled.");
|
||||
// }
|
||||
//}
|
||||
|
||||
m_XrInstanceCreated = true;
|
||||
m_XrInstance = xrInstance;
|
||||
DEBUG("OnInstanceCreate() " + m_XrInstance);
|
||||
|
||||
return GetXrFunctionDelegates(m_XrInstance);
|
||||
}
|
||||
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
m_XrInstanceCreated = false;
|
||||
DEBUG("OnInstanceDestroy() " + m_XrInstance);
|
||||
}
|
||||
|
||||
private XrSystemId m_XrSystemId = 0;
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
m_XrSystemId = xrSystem;
|
||||
DEBUG("OnSystemChange() " + m_XrSystemId);
|
||||
}
|
||||
|
||||
private bool m_XrSessionCreated = false;
|
||||
public bool XrSessionCreated
|
||||
{
|
||||
get { return m_XrSessionCreated; }
|
||||
}
|
||||
private XrSession m_XrSession = 0;
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
m_XrSession = xrSession;
|
||||
m_XrSessionCreated = true;
|
||||
DEBUG("OnSessionCreate() " + m_XrSession);
|
||||
}
|
||||
|
||||
private bool m_XrSessionEnding = false;
|
||||
public bool XrSessionEnding
|
||||
{
|
||||
get { return m_XrSessionEnding; }
|
||||
}
|
||||
|
||||
private XrSpace m_WorldLockSpaceOriginOnHead = 0, m_WorldLockSpaceOriginOnFloor = 0, m_HeadLockSpace = 0;
|
||||
public XrSpace WorldLockSpaceOriginOnHead
|
||||
{
|
||||
get { return m_WorldLockSpaceOriginOnHead; }
|
||||
}
|
||||
public XrSpace WorldLockSpaceOriginOnFloor
|
||||
{
|
||||
get { return m_WorldLockSpaceOriginOnFloor; }
|
||||
}
|
||||
public XrSpace HeadLockSpace
|
||||
{
|
||||
get { return m_HeadLockSpace; }
|
||||
}
|
||||
|
||||
protected override void OnSessionBegin(ulong xrSession)
|
||||
{
|
||||
m_XrSessionEnding = false;
|
||||
DEBUG("OnSessionBegin() " + m_XrSession);
|
||||
|
||||
// Enumerate supported reference space types and create the XrSpace.
|
||||
XrReferenceSpaceType[] spaces = new XrReferenceSpaceType[Enum.GetNames(typeof(XrReferenceSpaceType)).Count()];
|
||||
UInt32 spaceCountOutput;
|
||||
if (EnumerateReferenceSpaces(
|
||||
spaceCapacityInput: 0,
|
||||
spaceCountOutput: out spaceCountOutput,
|
||||
spaces: out spaces[0]) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
//DEBUG("spaceCountOutput: " + spaceCountOutput);
|
||||
|
||||
Array.Resize(ref spaces, (int)spaceCountOutput);
|
||||
if (EnumerateReferenceSpaces(
|
||||
spaceCapacityInput: spaceCountOutput,
|
||||
spaceCountOutput: out spaceCountOutput,
|
||||
spaces: out spaces[0]) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (spaces.Contains(XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_LOCAL))
|
||||
{
|
||||
XrReferenceSpaceCreateInfo referenceSpaceCreateInfoWorldLock;
|
||||
referenceSpaceCreateInfoWorldLock.type = XrStructureType.XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
referenceSpaceCreateInfoWorldLock.next = IntPtr.Zero;
|
||||
referenceSpaceCreateInfoWorldLock.referenceSpaceType = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||
referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1);
|
||||
referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.position = new XrVector3f(0, 0, 0);
|
||||
|
||||
if (CreateReferenceSpace(
|
||||
createInfo: ref referenceSpaceCreateInfoWorldLock,
|
||||
space: out m_WorldLockSpaceOriginOnHead) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
//DEBUG("CreateReferenceSpace: " + m_WorldLockSpaceOriginOnHead);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace for world lock layers on head failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace no space type for world lock on head layers.");
|
||||
}
|
||||
|
||||
if (spaces.Contains(XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_STAGE))
|
||||
{
|
||||
XrReferenceSpaceCreateInfo referenceSpaceCreateInfoWorldLock;
|
||||
referenceSpaceCreateInfoWorldLock.type = XrStructureType.XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
referenceSpaceCreateInfoWorldLock.next = IntPtr.Zero;
|
||||
referenceSpaceCreateInfoWorldLock.referenceSpaceType = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_STAGE;
|
||||
referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1);
|
||||
referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.position = new XrVector3f(0, 0, 0);
|
||||
|
||||
if (CreateReferenceSpace(
|
||||
createInfo: ref referenceSpaceCreateInfoWorldLock,
|
||||
space: out m_WorldLockSpaceOriginOnFloor) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
//DEBUG("CreateReferenceSpace: " + m_WorldLockSpaceOriginOnFloor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace for world lock layers on floor failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace no space type for world lock on floor layers.");
|
||||
}
|
||||
|
||||
if (spaces.Contains(XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_VIEW))
|
||||
{
|
||||
XrReferenceSpaceCreateInfo referenceSpaceCreateInfoHeadLock;
|
||||
referenceSpaceCreateInfoHeadLock.type = XrStructureType.XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
referenceSpaceCreateInfoHeadLock.next = IntPtr.Zero;
|
||||
referenceSpaceCreateInfoHeadLock.referenceSpaceType = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_VIEW;
|
||||
referenceSpaceCreateInfoHeadLock.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1);
|
||||
referenceSpaceCreateInfoHeadLock.poseInReferenceSpace.position = new XrVector3f(0, 0, 0);
|
||||
|
||||
if (CreateReferenceSpace(
|
||||
createInfo: ref referenceSpaceCreateInfoHeadLock,
|
||||
space: out m_HeadLockSpace) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
//DEBUG("CreateReferenceSpace: " + m_HeadLockSpace);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace for head lock layers failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace no space type for head lock layers.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("EnumerateReferenceSpaces(" + spaceCountOutput + ") failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("EnumerateReferenceSpaces(0) failed.");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnSessionEnd(ulong xrSession)
|
||||
{
|
||||
m_XrSessionEnding = true;
|
||||
DEBUG("OnSessionEnd() " + m_XrSession);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
m_XrSessionCreated = false;
|
||||
DEBUG("OnSessionDestroy() " + xrSession);
|
||||
|
||||
if (m_HeadLockSpace != 0)
|
||||
{
|
||||
DestroySpace(m_HeadLockSpace);
|
||||
m_HeadLockSpace = 0;
|
||||
}
|
||||
if (m_WorldLockSpaceOriginOnFloor != 0)
|
||||
{
|
||||
DestroySpace(m_WorldLockSpaceOriginOnFloor);
|
||||
m_WorldLockSpaceOriginOnFloor = 0;
|
||||
}
|
||||
if (m_WorldLockSpaceOriginOnHead != 0)
|
||||
{
|
||||
DestroySpace(m_WorldLockSpaceOriginOnHead);
|
||||
m_WorldLockSpaceOriginOnHead = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public XrSessionState XrSessionCurrentState
|
||||
{
|
||||
get { return m_XrSessionNewState; }
|
||||
}
|
||||
private XrSessionState m_XrSessionNewState = XrSessionState.XR_SESSION_STATE_UNKNOWN;
|
||||
private XrSessionState m_XrSessionOldState = XrSessionState.XR_SESSION_STATE_UNKNOWN;
|
||||
protected override void OnSessionStateChange(int oldState, int newState)
|
||||
{
|
||||
DEBUG("OnSessionStateChange() oldState: " + oldState + " newState:" + newState);
|
||||
|
||||
if (Enum.IsDefined(typeof(XrSessionState), oldState))
|
||||
{
|
||||
m_XrSessionOldState = (XrSessionState)oldState;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG("OnSessionStateChange() oldState undefined");
|
||||
}
|
||||
|
||||
if (Enum.IsDefined(typeof(XrSessionState), newState))
|
||||
{
|
||||
m_XrSessionNewState = (XrSessionState)newState;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG("OnSessionStateChange() newState undefined");
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OpenXR function delegates
|
||||
/// xrGetInstanceProcAddr
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr;
|
||||
|
||||
/// xrGetSystemProperties
|
||||
OpenXRHelper.xrGetSystemPropertiesDelegate xrGetSystemProperties;
|
||||
public XrResult GetSystemProperties(ref XrSystemProperties properties)
|
||||
{
|
||||
if (m_XrInstanceCreated)
|
||||
{
|
||||
return xrGetSystemProperties(m_XrInstance, m_XrSystemId, ref properties);
|
||||
}
|
||||
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
/// xrEnumerateReferenceSpaces
|
||||
OpenXRHelper.xrEnumerateReferenceSpacesDelegate xrEnumerateReferenceSpaces;
|
||||
public XrResult EnumerateReferenceSpaces(UInt32 spaceCapacityInput, out UInt32 spaceCountOutput, out XrReferenceSpaceType spaces)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
spaceCountOutput = 0;
|
||||
spaces = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT;
|
||||
return XrResult.XR_ERROR_SESSION_NOT_RUNNING;
|
||||
}
|
||||
|
||||
return xrEnumerateReferenceSpaces(m_XrSession, spaceCapacityInput, out spaceCountOutput, out spaces);
|
||||
}
|
||||
|
||||
/// xrCreateReferenceSpace
|
||||
OpenXRHelper.xrCreateReferenceSpaceDelegate xrCreateReferenceSpace;
|
||||
public XrResult CreateReferenceSpace(ref XrReferenceSpaceCreateInfo createInfo, out XrSpace space)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
space = 0;
|
||||
return XrResult.XR_ERROR_SESSION_NOT_RUNNING;
|
||||
}
|
||||
|
||||
return xrCreateReferenceSpace(m_XrSession, ref createInfo, out space);
|
||||
}
|
||||
|
||||
/// xrDestroySpace
|
||||
OpenXRHelper.xrDestroySpaceDelegate xrDestroySpace;
|
||||
public XrResult DestroySpace(XrSpace space)
|
||||
{
|
||||
if (space != 0)
|
||||
{
|
||||
return xrDestroySpace(space);
|
||||
}
|
||||
return XrResult.XR_ERROR_REFERENCE_SPACE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
private bool GetXrFunctionDelegates(XrInstance xrInstance)
|
||||
{
|
||||
/// xrGetInstanceProcAddr
|
||||
if (xrGetInstanceProcAddr != null && xrGetInstanceProcAddr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetInstanceProcAddr.");
|
||||
XrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(
|
||||
xrGetInstanceProcAddr,
|
||||
typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate)) as OpenXRHelper.xrGetInstanceProcAddrDelegate;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetInstanceProcAddr");
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
/// xrGetSystemProperties
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrGetSystemProperties", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetSystemProperties.");
|
||||
xrGetSystemProperties = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrGetSystemPropertiesDelegate)) as OpenXRHelper.xrGetSystemPropertiesDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetSystemProperties");
|
||||
return false;
|
||||
}
|
||||
/// xrEnumerateReferenceSpaces
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrEnumerateReferenceSpaces", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrEnumerateReferenceSpaces.");
|
||||
xrEnumerateReferenceSpaces = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrEnumerateReferenceSpacesDelegate)) as OpenXRHelper.xrEnumerateReferenceSpacesDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrEnumerateReferenceSpaces");
|
||||
return false;
|
||||
}
|
||||
/// xrCreateReferenceSpace
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrCreateReferenceSpace", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrCreateReferenceSpace.");
|
||||
xrCreateReferenceSpace = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrCreateReferenceSpaceDelegate)) as OpenXRHelper.xrCreateReferenceSpaceDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrCreateReferenceSpace");
|
||||
return false;
|
||||
}
|
||||
/// xrDestroySpace
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrDestroySpace", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrDestroySpace.");
|
||||
xrDestroySpace = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrDestroySpaceDelegate)) as OpenXRHelper.xrDestroySpaceDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrDestroySpace");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CompositionLayer_GetFuncAddrs(xrInstance, xrGetInstanceProcAddr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
DEBUG("Get function pointers in native.");
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CompositionLayer_GetFuncAddrs");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Wrapper Functions
|
||||
private const string ExtLib = "viveopenxr";
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "compositionlayer_Init")]
|
||||
public static extern int VIVEOpenXR_CompositionLayer_Init(XrSession session, uint textureWidth, uint textureHeight, GraphicsAPI graphicsAPI, bool isDynamic, bool isProtected, out uint imageCount);
|
||||
public int CompositionLayer_Init(uint textureWidth, uint textureHeight, GraphicsAPI graphicsAPI, bool isDynamic, bool isProtected, out uint imageCount)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("Xr Session not found");
|
||||
imageCount = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_CompositionLayer_Init(m_XrSession, textureWidth, textureHeight, graphicsAPI, isDynamic, isProtected, out imageCount);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "compositionlayer_GetTexture")]
|
||||
public static extern IntPtr VIVEOpenXR_CompositionLayer_GetTexture(int layerID, out uint imageIndex);
|
||||
public IntPtr CompositionLayer_GetTexture(int layerID, out uint imageIndex)
|
||||
{
|
||||
return VIVEOpenXR_CompositionLayer_GetTexture(layerID, out imageIndex);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "compositionlayer_ReleaseTexture")]
|
||||
public static extern bool VIVEOpenXR_CompositionLayer_ReleaseTexture(int layerID);
|
||||
public bool CompositionLayer_ReleaseTexture(int layerID)
|
||||
{
|
||||
return VIVEOpenXR_CompositionLayer_ReleaseTexture(layerID);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "compositionlayer_Destroy")]
|
||||
public static extern bool VIVEOpenXR_CompositionLayer_Destroy(int layerID);
|
||||
public bool CompositionLayer_Destroy(int layerID)
|
||||
{
|
||||
return VIVEOpenXR_CompositionLayer_Destroy(layerID);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "submit_CompositionLayerQuad")]
|
||||
public static extern void VIVEOpenXR_Submit_CompositionLayerQuad(XrCompositionLayerQuad quad, LayerType layerType, uint compositionDepth, int layerID);
|
||||
public void Submit_CompositionLayerQuad(XrCompositionLayerQuad quad, LayerType layerType, uint compositionDepth, int layerID)
|
||||
{
|
||||
VIVEOpenXR_Submit_CompositionLayerQuad(quad, layerType, compositionDepth, layerID);
|
||||
return;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Hook native functions
|
||||
protected override IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
{
|
||||
DEBUG("CompositionLayer_GetInstanceProcAddr");
|
||||
return CompositionLayer_GetInstanceProcAddr(func);
|
||||
}
|
||||
|
||||
[DllImport(ExtLib, EntryPoint = "compositionlayer_intercept_xrGetInstanceProcAddr")]
|
||||
private static extern IntPtr CompositionLayer_GetInstanceProcAddr(IntPtr func);
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "compositionlayer_GetFuncAddrs")]
|
||||
public static extern XrResult VIVEOpenXR_CompositionLayer_GetFuncAddrs(XrInstance xrInstance, IntPtr xrGetInstanceProcAddrFuncPtr);
|
||||
public XrResult CompositionLayer_GetFuncAddrs(XrInstance xrInstance, IntPtr xrGetInstanceProcAddrFuncPtr)
|
||||
{
|
||||
return VIVEOpenXR_CompositionLayer_GetFuncAddrs(xrInstance, xrGetInstanceProcAddrFuncPtr);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b06faf09f93c35b4b83640fd9908b630
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,91 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using AOT;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Composition Layer (Color Scale Bias)",
|
||||
Desc = "Enable this feature to enable the Composition Layer Color Scale Bias Extension",
|
||||
Company = "HTC",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenXRColorScaleBiasExtensionString,
|
||||
Version = "1.0.0",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class ViveCompositionLayerColorScaleBias : OpenXRFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.ViveCompositionLayer.ColorScaleBias";
|
||||
static void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
static void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
static void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <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.compositionlayer.colorscalebias";
|
||||
|
||||
private const string kOpenXRColorScaleBiasExtensionString = "XR_KHR_composition_layer_color_scale_bias";
|
||||
|
||||
private bool m_ColorScaleBiasExtensionEnabled = true;
|
||||
public bool ColorScaleBiasExtensionEnabled
|
||||
{
|
||||
get { return m_ColorScaleBiasExtensionEnabled; }
|
||||
}
|
||||
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenXRColorScaleBiasExtensionString))
|
||||
{
|
||||
WARNING("OnInstanceCreate() " + kOpenXRColorScaleBiasExtensionString + " is NOT enabled.");
|
||||
|
||||
m_ColorScaleBiasExtensionEnabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Wrapper Functions
|
||||
private const string ExtLib = "viveopenxr";
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "submit_CompositionLayerColorBias")]
|
||||
public static extern void VIVEOpenXR_Submit_CompositionLayerColorBias(XrCompositionLayerColorScaleBiasKHR colorBias, int layerID);
|
||||
public void Submit_CompositionLayerColorBias(XrCompositionLayerColorScaleBiasKHR colorBias, int layerID)
|
||||
{
|
||||
if (!ColorScaleBiasExtensionEnabled)
|
||||
{
|
||||
ERROR("Submit_CompositionLayerColorBias: " + kOpenXRColorScaleBiasExtensionString + " is not enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
VIVEOpenXR_Submit_CompositionLayerColorBias(colorBias, layerID);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5621f5c5156e7648a0c3a1fa86497a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using AOT;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Composition Layer (Cylinder)",
|
||||
Desc = "Enable this feature to enable the Composition Layer Cylinder Extension",
|
||||
Company = "HTC",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenXRCylinderExtensionString,
|
||||
Version = "1.0.0",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class ViveCompositionLayerCylinder : OpenXRFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.ViveCompositionLayer.Cylinder";
|
||||
static void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
static void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
static void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <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.compositionlayer.cylinder";
|
||||
|
||||
private const string kOpenXRCylinderExtensionString = "XR_KHR_composition_layer_cylinder";
|
||||
|
||||
private bool m_CylinderExtensionEnabled = true;
|
||||
public bool CylinderExtensionEnabled
|
||||
{
|
||||
get { return m_CylinderExtensionEnabled; }
|
||||
}
|
||||
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenXRCylinderExtensionString))
|
||||
{
|
||||
WARNING("OnInstanceCreate() " + kOpenXRCylinderExtensionString + " is NOT enabled.");
|
||||
|
||||
m_CylinderExtensionEnabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Wrapper Functions
|
||||
private const string ExtLib = "viveopenxr";
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "submit_CompositionLayerCylinder")]
|
||||
public static extern void VIVEOpenXR_Submit_CompositionLayerCylinder(XrCompositionLayerCylinderKHR cylinder, LayerType layerType, uint compositionDepth, int layerID);
|
||||
public void Submit_CompositionLayerCylinder(XrCompositionLayerCylinderKHR cylinder, LayerType layerType, uint compositionDepth, int layerID)
|
||||
{
|
||||
if (!CylinderExtensionEnabled)
|
||||
{
|
||||
ERROR("Submit_CompositionLayerCylinder: " + kOpenXRCylinderExtensionString + " is NOT enabled.");
|
||||
}
|
||||
|
||||
VIVEOpenXR_Submit_CompositionLayerCylinder(cylinder, layerType, compositionDepth, layerID);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abd96d069ecb9b243a69661e0bffdfab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,334 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
public struct XrSwapchain : IEquatable<ulong>
|
||||
{
|
||||
private readonly ulong value;
|
||||
|
||||
public XrSwapchain(ulong u)
|
||||
{
|
||||
value = u;
|
||||
}
|
||||
|
||||
public static implicit operator ulong(XrSwapchain xrBool)
|
||||
{
|
||||
return xrBool.value;
|
||||
}
|
||||
public static implicit operator XrSwapchain(ulong u)
|
||||
{
|
||||
return new XrSwapchain(u);
|
||||
}
|
||||
|
||||
public bool Equals(XrSwapchain other)
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
public bool Equals(ulong other)
|
||||
{
|
||||
return value == other;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is XrSwapchain && Equals((XrSwapchain)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
public static bool operator ==(XrSwapchain a, XrSwapchain b) { return a.Equals(b); }
|
||||
public static bool operator !=(XrSwapchain a, XrSwapchain b) { return !a.Equals(b); }
|
||||
public static bool operator >=(XrSwapchain a, XrSwapchain b) { return a.value >= b.value; }
|
||||
public static bool operator <=(XrSwapchain a, XrSwapchain b) { return a.value <= b.value; }
|
||||
public static bool operator >(XrSwapchain a, XrSwapchain b) { return a.value > b.value; }
|
||||
public static bool operator <(XrSwapchain a, XrSwapchain b) { return a.value < b.value; }
|
||||
public static XrSwapchain operator +(XrSwapchain a, XrSwapchain b) { return a.value + b.value; }
|
||||
public static XrSwapchain operator -(XrSwapchain a, XrSwapchain b) { return a.value - b.value; }
|
||||
public static XrSwapchain operator *(XrSwapchain a, XrSwapchain b) { return a.value * b.value; }
|
||||
public static XrSwapchain operator /(XrSwapchain a, XrSwapchain b)
|
||||
{
|
||||
if (b.value == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
return a.value / b.value;
|
||||
}
|
||||
|
||||
}
|
||||
public struct XrCompositionLayerFlags : IEquatable<UInt64>
|
||||
{
|
||||
private readonly UInt64 value;
|
||||
|
||||
public XrCompositionLayerFlags(UInt64 u)
|
||||
{
|
||||
value = u;
|
||||
}
|
||||
|
||||
public static implicit operator UInt64(XrCompositionLayerFlags xrBool)
|
||||
{
|
||||
return xrBool.value;
|
||||
}
|
||||
public static implicit operator XrCompositionLayerFlags(UInt64 u)
|
||||
{
|
||||
return new XrCompositionLayerFlags(u);
|
||||
}
|
||||
|
||||
public bool Equals(XrCompositionLayerFlags other)
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
public bool Equals(UInt64 other)
|
||||
{
|
||||
return value == other;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is XrCompositionLayerFlags && Equals((XrCompositionLayerFlags)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
public static bool operator ==(XrCompositionLayerFlags a, XrCompositionLayerFlags b) { return a.Equals(b); }
|
||||
public static bool operator !=(XrCompositionLayerFlags a, XrCompositionLayerFlags b) { return !a.Equals(b); }
|
||||
public static bool operator >=(XrCompositionLayerFlags a, XrCompositionLayerFlags b) { return a.value >= b.value; }
|
||||
public static bool operator <=(XrCompositionLayerFlags a, XrCompositionLayerFlags b) { return a.value <= b.value; }
|
||||
public static bool operator >(XrCompositionLayerFlags a, XrCompositionLayerFlags b) { return a.value > b.value; }
|
||||
public static bool operator <(XrCompositionLayerFlags a, XrCompositionLayerFlags b) { return a.value < b.value; }
|
||||
public static XrCompositionLayerFlags operator +(XrCompositionLayerFlags a, XrCompositionLayerFlags b) { return a.value + b.value; }
|
||||
public static XrCompositionLayerFlags operator -(XrCompositionLayerFlags a, XrCompositionLayerFlags b) { return a.value - b.value; }
|
||||
public static XrCompositionLayerFlags operator *(XrCompositionLayerFlags a, XrCompositionLayerFlags b) { return a.value * b.value; }
|
||||
public static XrCompositionLayerFlags operator /(XrCompositionLayerFlags a, XrCompositionLayerFlags b)
|
||||
{
|
||||
if (b.value == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
return a.value / b.value;
|
||||
}
|
||||
}
|
||||
|
||||
public struct XrSwapchainCreateFlags : IEquatable<UInt64>
|
||||
{
|
||||
private readonly UInt64 value;
|
||||
|
||||
public XrSwapchainCreateFlags(UInt64 u)
|
||||
{
|
||||
value = u;
|
||||
}
|
||||
|
||||
public static implicit operator UInt64(XrSwapchainCreateFlags xrBool)
|
||||
{
|
||||
return xrBool.value;
|
||||
}
|
||||
public static implicit operator XrSwapchainCreateFlags(UInt64 u)
|
||||
{
|
||||
return new XrSwapchainCreateFlags(u);
|
||||
}
|
||||
|
||||
public bool Equals(XrSwapchainCreateFlags other)
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
public bool Equals(UInt64 other)
|
||||
{
|
||||
return value == other;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is XrSwapchainCreateFlags && Equals((XrSwapchainCreateFlags)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
public static bool operator ==(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b) { return a.Equals(b); }
|
||||
public static bool operator !=(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b) { return !a.Equals(b); }
|
||||
public static bool operator >=(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b) { return a.value >= b.value; }
|
||||
public static bool operator <=(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b) { return a.value <= b.value; }
|
||||
public static bool operator >(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b) { return a.value > b.value; }
|
||||
public static bool operator <(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b) { return a.value < b.value; }
|
||||
public static XrSwapchainCreateFlags operator +(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b) { return a.value + b.value; }
|
||||
public static XrSwapchainCreateFlags operator -(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b) { return a.value - b.value; }
|
||||
public static XrSwapchainCreateFlags operator *(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b) { return a.value * b.value; }
|
||||
public static XrSwapchainCreateFlags operator /(XrSwapchainCreateFlags a, XrSwapchainCreateFlags b)
|
||||
{
|
||||
if (b.value == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
return a.value / b.value;
|
||||
}
|
||||
}
|
||||
|
||||
public struct XrSwapchainUsageFlags : IEquatable<UInt64>
|
||||
{
|
||||
private readonly UInt64 value;
|
||||
|
||||
public XrSwapchainUsageFlags(UInt64 u)
|
||||
{
|
||||
value = u;
|
||||
}
|
||||
|
||||
public static implicit operator UInt64(XrSwapchainUsageFlags xrBool)
|
||||
{
|
||||
return xrBool.value;
|
||||
}
|
||||
public static implicit operator XrSwapchainUsageFlags(UInt64 u)
|
||||
{
|
||||
return new XrSwapchainUsageFlags(u);
|
||||
}
|
||||
|
||||
public bool Equals(XrSwapchainUsageFlags other)
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
public bool Equals(UInt64 other)
|
||||
{
|
||||
return value == other;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is XrSwapchainUsageFlags && Equals((XrSwapchainUsageFlags)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
public static bool operator ==(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b) { return a.Equals(b); }
|
||||
public static bool operator !=(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b) { return !a.Equals(b); }
|
||||
public static bool operator >=(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b) { return a.value >= b.value; }
|
||||
public static bool operator <=(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b) { return a.value <= b.value; }
|
||||
public static bool operator >(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b) { return a.value > b.value; }
|
||||
public static bool operator <(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b) { return a.value < b.value; }
|
||||
public static XrSwapchainUsageFlags operator +(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b) { return a.value + b.value; }
|
||||
public static XrSwapchainUsageFlags operator -(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b) { return a.value - b.value; }
|
||||
public static XrSwapchainUsageFlags operator *(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b) { return a.value * b.value; }
|
||||
public static XrSwapchainUsageFlags operator /(XrSwapchainUsageFlags a, XrSwapchainUsageFlags b)
|
||||
{
|
||||
if (b.value == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
return a.value / b.value;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrCompositionLayerQuad
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrCompositionLayerFlags layerFlags;
|
||||
public XrSpace space;
|
||||
public XrEyeVisibility eyeVisibility;
|
||||
public XrSwapchainSubImage subImage;
|
||||
public XrPosef pose;
|
||||
public XrExtent2Df size;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrCompositionLayerCylinderKHR
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrCompositionLayerFlags layerFlags;
|
||||
public XrSpace space;
|
||||
public XrEyeVisibility eyeVisibility;
|
||||
public XrSwapchainSubImage subImage;
|
||||
public XrPosef pose;
|
||||
public float radius;
|
||||
public float centralAngle;
|
||||
public float aspectRatio;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrSwapchainSubImage
|
||||
{
|
||||
public XrSwapchain swapchain;
|
||||
public XrRect2Di imageRect;
|
||||
public uint imageArrayIndex;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrCompositionLayerColorScaleBiasKHR
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrColor4f colorScale;
|
||||
public XrColor4f colorBias;
|
||||
}
|
||||
public enum GraphicsAPI
|
||||
{
|
||||
GLES3 = 1,
|
||||
Vulkan = 2
|
||||
}
|
||||
public enum LayerType
|
||||
{
|
||||
///<summary> Overlays are composition layers rendered after the projection layer </summary>
|
||||
Overlay = 1,
|
||||
///<summary> Underlays are composition layers rendered before the projection layer </summary>
|
||||
Underlay = 2
|
||||
}
|
||||
|
||||
public static class ViveCompositionLayerHelper
|
||||
{
|
||||
// Flag bits for XrCompositionLayerFlags
|
||||
public static XrCompositionLayerFlags XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT = 0x00000001;
|
||||
public static XrCompositionLayerFlags XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT = 0x00000002;
|
||||
public static XrCompositionLayerFlags XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT = 0x00000004;
|
||||
|
||||
// Flag bits for XrSwapchainCreateFlags
|
||||
public static XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT = 0x00000001;
|
||||
public static XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT = 0x00000002;
|
||||
|
||||
// Flag bits for XrSwapchainUsageFlags
|
||||
public static XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT = 0x00000001;
|
||||
public static XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000002;
|
||||
public static XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT = 0x00000004;
|
||||
public static XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT = 0x00000008;
|
||||
public static XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT = 0x00000010;
|
||||
public static XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_SAMPLED_BIT = 0x00000020;
|
||||
public static XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT = 0x00000040;
|
||||
public static XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND = 0x00000080;
|
||||
public static XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_KHR = 0x00000080;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7dfb147f98026e44786fda53bb2aeb18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,682 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using AOT;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
using UnityEngine.XR;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Composition Layer (Passthrough)",
|
||||
Desc = "Enable this feature to use the HTC Passthrough feature.",
|
||||
Company = "HTC",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionStrings,
|
||||
Version = "1.0.0",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class ViveCompositionLayerPassthrough : OpenXRFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.ViveCompositionLayerPassthrough";
|
||||
static void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
static void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
static void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); }
|
||||
|
||||
private List<int> passthroughIDList = new List<int>();
|
||||
public List<int> PassthroughIDList { get{ return new List<int>(passthroughIDList); } }
|
||||
|
||||
private List<XRInputSubsystem> inputSubsystems = new List<XRInputSubsystem>();
|
||||
|
||||
/// <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.compositionlayer.passthrough";
|
||||
|
||||
public const string kOpenxrExtensionStrings = "XR_HTC_passthrough";
|
||||
|
||||
private bool m_HTCPassthroughExtensionEnabled = true;
|
||||
public bool HTCPassthroughExtensionEnabled
|
||||
{
|
||||
get { return m_HTCPassthroughExtensionEnabled; }
|
||||
}
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
private bool m_XrInstanceCreated = false;
|
||||
public bool XrInstanceCreated
|
||||
{
|
||||
get { return m_XrInstanceCreated; }
|
||||
}
|
||||
private XrInstance m_XrInstance = 0;
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
foreach (string kOpenxrExtensionString in kOpenxrExtensionStrings.Split(' '))
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
{
|
||||
WARNING("OnInstanceCreate() " + kOpenxrExtensionString + " is NOT enabled.");
|
||||
|
||||
m_HTCPassthroughExtensionEnabled = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_XrInstanceCreated = true;
|
||||
m_XrInstance = xrInstance;
|
||||
DEBUG("OnInstanceCreate() " + m_XrInstance);
|
||||
|
||||
return GetXrFunctionDelegates(m_XrInstance);
|
||||
}
|
||||
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
m_XrInstanceCreated = false;
|
||||
DEBUG("OnInstanceDestroy() " + m_XrInstance);
|
||||
}
|
||||
|
||||
private XrSystemId m_XrSystemId = 0;
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
m_XrSystemId = xrSystem;
|
||||
DEBUG("OnSystemChange() " + m_XrSystemId);
|
||||
}
|
||||
|
||||
private bool m_XrSessionCreated = false;
|
||||
public bool XrSessionCreated
|
||||
{
|
||||
get { return m_XrSessionCreated; }
|
||||
}
|
||||
private XrSession m_XrSession = 0;
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
m_XrSession = xrSession;
|
||||
m_XrSessionCreated = true;
|
||||
DEBUG("OnSessionCreate() " + m_XrSession);
|
||||
}
|
||||
|
||||
private bool m_XrSessionEnding = false;
|
||||
public bool XrSessionEnding
|
||||
{
|
||||
get { return m_XrSessionEnding; }
|
||||
}
|
||||
|
||||
private XrSpace m_WorldLockSpaceOriginOnHead = 0, m_WorldLockSpaceOriginOnFloor = 0, m_HeadLockSpace = 0;
|
||||
private XrSpace WorldLockSpaceOriginOnHead
|
||||
{
|
||||
get { return m_WorldLockSpaceOriginOnHead; }
|
||||
}
|
||||
private XrSpace WorldLockSpaceOriginOnFloor
|
||||
{
|
||||
get { return m_WorldLockSpaceOriginOnFloor; }
|
||||
}
|
||||
private XrSpace HeadLockSpace
|
||||
{
|
||||
get { return m_HeadLockSpace; }
|
||||
}
|
||||
|
||||
protected override void OnSessionBegin(ulong xrSession)
|
||||
{
|
||||
m_XrSessionEnding = false;
|
||||
DEBUG("OnSessionBegin() " + m_XrSession);
|
||||
|
||||
// Enumerate supported reference space types and create the XrSpace.
|
||||
XrReferenceSpaceType[] spaces = new XrReferenceSpaceType[Enum.GetNames(typeof(XrReferenceSpaceType)).Count()];
|
||||
UInt32 spaceCountOutput;
|
||||
if (EnumerateReferenceSpaces(
|
||||
spaceCapacityInput: 0,
|
||||
spaceCountOutput: out spaceCountOutput,
|
||||
spaces: out spaces[0]) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
//DEBUG("spaceCountOutput: " + spaceCountOutput);
|
||||
|
||||
Array.Resize(ref spaces, (int)spaceCountOutput);
|
||||
if (EnumerateReferenceSpaces(
|
||||
spaceCapacityInput: spaceCountOutput,
|
||||
spaceCountOutput: out spaceCountOutput,
|
||||
spaces: out spaces[0]) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (spaces.Contains(XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_LOCAL))
|
||||
{
|
||||
XrReferenceSpaceCreateInfo referenceSpaceCreateInfoWorldLock;
|
||||
referenceSpaceCreateInfoWorldLock.type = XrStructureType.XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
referenceSpaceCreateInfoWorldLock.next = IntPtr.Zero;
|
||||
referenceSpaceCreateInfoWorldLock.referenceSpaceType = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||
referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1);
|
||||
referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.position = new XrVector3f(0, 0, 0);
|
||||
|
||||
if (CreateReferenceSpace(
|
||||
createInfo: ref referenceSpaceCreateInfoWorldLock,
|
||||
space: out m_WorldLockSpaceOriginOnHead) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
//DEBUG("CreateReferenceSpace: " + m_WorldLockSpaceOriginOnHead);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace for world lock layers on head failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace no space type for world lock on head layers.");
|
||||
}
|
||||
|
||||
if (spaces.Contains(XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_STAGE))
|
||||
{
|
||||
XrReferenceSpaceCreateInfo referenceSpaceCreateInfoWorldLock;
|
||||
referenceSpaceCreateInfoWorldLock.type = XrStructureType.XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
referenceSpaceCreateInfoWorldLock.next = IntPtr.Zero;
|
||||
referenceSpaceCreateInfoWorldLock.referenceSpaceType = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_STAGE;
|
||||
referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1);
|
||||
referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.position = new XrVector3f(0, 0, 0);
|
||||
|
||||
if (CreateReferenceSpace(
|
||||
createInfo: ref referenceSpaceCreateInfoWorldLock,
|
||||
space: out m_WorldLockSpaceOriginOnFloor) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
//DEBUG("CreateReferenceSpace: " + m_WorldLockSpaceOriginOnFloor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace for world lock layers on floor failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace no space type for world lock on floor layers.");
|
||||
}
|
||||
|
||||
if (spaces.Contains(XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_VIEW))
|
||||
{
|
||||
XrReferenceSpaceCreateInfo referenceSpaceCreateInfoHeadLock;
|
||||
referenceSpaceCreateInfoHeadLock.type = XrStructureType.XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
referenceSpaceCreateInfoHeadLock.next = IntPtr.Zero;
|
||||
referenceSpaceCreateInfoHeadLock.referenceSpaceType = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_VIEW;
|
||||
referenceSpaceCreateInfoHeadLock.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1);
|
||||
referenceSpaceCreateInfoHeadLock.poseInReferenceSpace.position = new XrVector3f(0, 0, 0);
|
||||
|
||||
if (CreateReferenceSpace(
|
||||
createInfo: ref referenceSpaceCreateInfoHeadLock,
|
||||
space: out m_HeadLockSpace) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
//DEBUG("CreateReferenceSpace: " + m_HeadLockSpace);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace for head lock layers failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("CreateReferenceSpace no space type for head lock layers.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("EnumerateReferenceSpaces(" + spaceCountOutput + ") failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("EnumerateReferenceSpaces(0) failed.");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnSessionEnd(ulong xrSession)
|
||||
{
|
||||
m_XrSessionEnding = true;
|
||||
DEBUG("OnSessionEnd() " + m_XrSession);
|
||||
}
|
||||
|
||||
public delegate void OnPassthroughSessionDestroyDelegate(int passthroughID);
|
||||
private Dictionary<int, OnPassthroughSessionDestroyDelegate> OnPassthroughSessionDestroyHandlerDictionary = new Dictionary<int, OnPassthroughSessionDestroyDelegate>();
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
m_XrSessionCreated = false;
|
||||
DEBUG("OnSessionDestroy() " + xrSession);
|
||||
|
||||
//Notify that all passthrough layers should be destroyed
|
||||
List<int> currentPassthroughIDs = PassthroughIDList;
|
||||
foreach (int passthroughID in currentPassthroughIDs)
|
||||
{
|
||||
OnPassthroughSessionDestroyDelegate OnPassthroughSessionDestroyHandler = OnPassthroughSessionDestroyHandlerDictionary[passthroughID];
|
||||
|
||||
OnPassthroughSessionDestroyHandler?.Invoke(passthroughID);
|
||||
}
|
||||
|
||||
if (m_HeadLockSpace != 0)
|
||||
{
|
||||
DestroySpace(m_HeadLockSpace);
|
||||
m_HeadLockSpace = 0;
|
||||
}
|
||||
if (m_WorldLockSpaceOriginOnFloor != 0)
|
||||
{
|
||||
DestroySpace(m_WorldLockSpaceOriginOnFloor);
|
||||
m_WorldLockSpaceOriginOnFloor = 0;
|
||||
}
|
||||
if (m_WorldLockSpaceOriginOnHead != 0)
|
||||
{
|
||||
DestroySpace(m_WorldLockSpaceOriginOnHead);
|
||||
m_WorldLockSpaceOriginOnHead = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public XrSessionState XrSessionCurrentState
|
||||
{
|
||||
get { return m_XrSessionNewState; }
|
||||
}
|
||||
private XrSessionState m_XrSessionNewState = XrSessionState.XR_SESSION_STATE_UNKNOWN;
|
||||
private XrSessionState m_XrSessionOldState = XrSessionState.XR_SESSION_STATE_UNKNOWN;
|
||||
protected override void OnSessionStateChange(int oldState, int newState)
|
||||
{
|
||||
DEBUG("OnSessionStateChange() oldState: " + oldState + " newState:" + newState);
|
||||
|
||||
if (Enum.IsDefined(typeof(XrSessionState), oldState))
|
||||
{
|
||||
m_XrSessionOldState = (XrSessionState)oldState;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG("OnSessionStateChange() oldState undefined");
|
||||
}
|
||||
|
||||
if (Enum.IsDefined(typeof(XrSessionState), newState))
|
||||
{
|
||||
m_XrSessionNewState = (XrSessionState)newState;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG("OnSessionStateChange() newState undefined");
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OpenXR function delegates
|
||||
/// xrGetInstanceProcAddr
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr;
|
||||
|
||||
/// xrGetSystemProperties
|
||||
OpenXRHelper.xrGetSystemPropertiesDelegate xrGetSystemProperties;
|
||||
public XrResult GetSystemProperties(ref XrSystemProperties properties)
|
||||
{
|
||||
if (m_XrInstanceCreated)
|
||||
{
|
||||
return xrGetSystemProperties(m_XrInstance, m_XrSystemId, ref properties);
|
||||
}
|
||||
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
/// xrEnumerateReferenceSpaces
|
||||
OpenXRHelper.xrEnumerateReferenceSpacesDelegate xrEnumerateReferenceSpaces;
|
||||
public XrResult EnumerateReferenceSpaces(UInt32 spaceCapacityInput, out UInt32 spaceCountOutput, out XrReferenceSpaceType spaces)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
spaceCountOutput = 0;
|
||||
spaces = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT;
|
||||
return XrResult.XR_ERROR_SESSION_NOT_RUNNING;
|
||||
}
|
||||
|
||||
return xrEnumerateReferenceSpaces(m_XrSession, spaceCapacityInput, out spaceCountOutput, out spaces);
|
||||
}
|
||||
|
||||
/// xrCreateReferenceSpace
|
||||
OpenXRHelper.xrCreateReferenceSpaceDelegate xrCreateReferenceSpace;
|
||||
public XrResult CreateReferenceSpace(ref XrReferenceSpaceCreateInfo createInfo, out XrSpace space)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
space = 0;
|
||||
return XrResult.XR_ERROR_SESSION_NOT_RUNNING;
|
||||
}
|
||||
|
||||
return xrCreateReferenceSpace(m_XrSession, ref createInfo, out space);
|
||||
}
|
||||
|
||||
/// xrDestroySpace
|
||||
OpenXRHelper.xrDestroySpaceDelegate xrDestroySpace;
|
||||
private XrResult DestroySpace(XrSpace space)
|
||||
{
|
||||
if (space != 0)
|
||||
{
|
||||
return xrDestroySpace(space);
|
||||
}
|
||||
return XrResult.XR_ERROR_REFERENCE_SPACE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
private bool GetXrFunctionDelegates(XrInstance xrInstance)
|
||||
{
|
||||
/// xrGetInstanceProcAddr
|
||||
if (xrGetInstanceProcAddr != null && xrGetInstanceProcAddr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetInstanceProcAddr.");
|
||||
XrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(
|
||||
xrGetInstanceProcAddr,
|
||||
typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate)) as OpenXRHelper.xrGetInstanceProcAddrDelegate;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetInstanceProcAddr");
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
/// xrGetSystemProperties
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrGetSystemProperties", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetSystemProperties.");
|
||||
xrGetSystemProperties = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrGetSystemPropertiesDelegate)) as OpenXRHelper.xrGetSystemPropertiesDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetSystemProperties");
|
||||
return false;
|
||||
}
|
||||
/// xrEnumerateReferenceSpaces
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrEnumerateReferenceSpaces", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrEnumerateReferenceSpaces.");
|
||||
xrEnumerateReferenceSpaces = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrEnumerateReferenceSpacesDelegate)) as OpenXRHelper.xrEnumerateReferenceSpacesDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrEnumerateReferenceSpaces");
|
||||
return false;
|
||||
}
|
||||
/// xrCreateReferenceSpace
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrCreateReferenceSpace", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrCreateReferenceSpace.");
|
||||
xrCreateReferenceSpace = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrCreateReferenceSpaceDelegate)) as OpenXRHelper.xrCreateReferenceSpaceDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrCreateReferenceSpace");
|
||||
return false;
|
||||
}
|
||||
/// xrDestroySpace
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrDestroySpace", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrDestroySpace.");
|
||||
xrDestroySpace = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrDestroySpaceDelegate)) as OpenXRHelper.xrDestroySpaceDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrDestroySpace");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HTCPassthrough_GetFuncAddrs(xrInstance, xrGetInstanceProcAddr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
DEBUG("Get function pointers in native.");
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("HTCPassthrough_GetFuncAddrs");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Wrapper Functions
|
||||
private const string ExtLib = "viveopenxr";
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_CreatePassthrough")]
|
||||
private static extern int VIVEOpenXR_HTCPassthrough_CreatePassthrough(XrSession session, LayerType layerType, PassthroughLayerForm layerForm, uint compositionDepth = 0);
|
||||
public int HTCPassthrough_CreatePassthrough(LayerType layerType, PassthroughLayerForm layerForm, OnPassthroughSessionDestroyDelegate onDestroyPassthroughHandler, uint compositionDepth = 0)
|
||||
{
|
||||
if (!m_XrSessionCreated || m_XrSession == 0)
|
||||
{
|
||||
ERROR("Xr Session not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_CreatePassthrough: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int passthroughID = VIVEOpenXR_HTCPassthrough_CreatePassthrough(m_XrSession, layerType, layerForm, compositionDepth);
|
||||
|
||||
if (passthroughID != 0)
|
||||
{
|
||||
passthroughIDList.Add(passthroughID);
|
||||
OnPassthroughSessionDestroyHandlerDictionary.Add(passthroughID, onDestroyPassthroughHandler);
|
||||
}
|
||||
|
||||
return passthroughID;
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_SetAlpha")]
|
||||
private static extern bool VIVEOpenXR_HTCPassthrough_SetAlpha(int passthroughID, float alpha);
|
||||
public bool HTCPassthrough_SetAlpha(int passthroughID, float alpha)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_SetAlpha: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_HTCPassthrough_SetAlpha(passthroughID, alpha);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_SetLayerType")]
|
||||
private static extern bool VIVEOpenXR_HTCPassthrough_SetLayerType(int passthroughID, LayerType layerType, uint compositionDepth = 0);
|
||||
public bool HTCPassthrough_SetLayerType(int passthroughID, LayerType layerType, uint compositionDepth = 0)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_SetLayerType: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_HTCPassthrough_SetLayerType(passthroughID, layerType, compositionDepth);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_SetMesh")]
|
||||
private static extern bool VIVEOpenXR_HTCPassthrough_SetMesh(int passthroughID, uint vertexCount, [In, Out] XrVector3f[] vertexBuffer, uint indexCount, [In, Out] uint[] indexBuffer);
|
||||
public bool HTCPassthrough_SetMesh(int passthroughID, uint vertexCount, [In, Out] XrVector3f[] vertexBuffer, uint indexCount, [In, Out] uint[] indexBuffer)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_SetMesh: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_HTCPassthrough_SetMesh(passthroughID, vertexCount, vertexBuffer, indexCount, indexBuffer);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransform")]
|
||||
private static extern bool VIVEOpenXR_HTCPassthrough_SetMeshTransform(int passthroughID, XrSpace meshSpace, XrPosef meshPose, XrVector3f meshScale);
|
||||
public bool HTCPassthrough_SetMeshTransform(int passthroughID, XrSpace meshSpace, XrPosef meshPose, XrVector3f meshScale)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_SetMeshTransform: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_HTCPassthrough_SetMeshTransform(passthroughID, meshSpace, meshPose, meshScale);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransformSpace")]
|
||||
private static extern bool VIVEOpenXR_HTCPassthrough_SetMeshTransformSpace(int passthroughID, XrSpace meshSpace);
|
||||
public bool HTCPassthrough_SetMeshTransformSpace(int passthroughID, XrSpace meshSpace)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_SetMeshTransformSpace: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_HTCPassthrough_SetMeshTransformSpace(passthroughID, meshSpace);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransformPosition")]
|
||||
private static extern bool VIVEOpenXR_HTCPassthrough_SetMeshTransformPosition(int passthroughID, XrVector3f meshPosition);
|
||||
public bool HTCPassthrough_SetMeshTransformPosition(int passthroughID, XrVector3f meshPosition)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_SetMeshTransformPosition: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_HTCPassthrough_SetMeshTransformPosition(passthroughID, meshPosition);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransformOrientation")]
|
||||
private static extern bool VIVEOpenXR_HTCPassthrough_SetMeshTransformOrientation(int passthroughID, XrQuaternionf meshOrientation);
|
||||
public bool HTCPassthrough_SetMeshTransformOrientation(int passthroughID, XrQuaternionf meshOrientation)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_SetMeshTransformOrientation: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_HTCPassthrough_SetMeshTransformOrientation(passthroughID, meshOrientation);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransformScale")]
|
||||
private static extern bool VIVEOpenXR_HTCPassthrough_SetMeshTransformScale(int passthroughID, XrVector3f meshScale);
|
||||
public bool HTCPassthrough_SetMeshTransformScale(int passthroughID, XrVector3f meshScale)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_SetMeshTransformScale: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_HTCPassthrough_SetMeshTransformScale(passthroughID, meshScale);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_DestroyPassthrough")]
|
||||
private static extern bool VIVEOpenXR_HTCPassthrough_DestroyPassthrough(int passthroughID);
|
||||
public bool HTCPassthrough_DestroyPassthrough(int passthroughID)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("HTCPassthrough_DestroyPassthrough: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool destroyed = VIVEOpenXR_HTCPassthrough_DestroyPassthrough(passthroughID);
|
||||
|
||||
if (destroyed)
|
||||
{
|
||||
passthroughIDList.Remove(passthroughID);
|
||||
OnPassthroughSessionDestroyHandlerDictionary.Remove(passthroughID);
|
||||
}
|
||||
|
||||
return destroyed;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Hook native functions
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "htcpassthrough_GetFuncAddrs")]
|
||||
private static extern XrResult VIVEOpenXR_HTCPassthrough_GetFuncAddrs(XrInstance xrInstance, IntPtr xrGetInstanceProcAddrFuncPtr);
|
||||
private XrResult HTCPassthrough_GetFuncAddrs(XrInstance xrInstance, IntPtr xrGetInstanceProcAddrFuncPtr)
|
||||
{
|
||||
if (!HTCPassthroughExtensionEnabled)
|
||||
{
|
||||
ERROR("VIVEOpenXR_HTCPassthrough_GetFuncAddrs: " + kOpenxrExtensionStrings + " is NOT enabled.");
|
||||
return XrResult.XR_ERROR_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return VIVEOpenXR_HTCPassthrough_GetFuncAddrs(xrInstance, xrGetInstanceProcAddrFuncPtr);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Funcs
|
||||
|
||||
public XrSpace GetXrSpaceFromSpaceType(ProjectedPassthroughSpaceType spaceType)
|
||||
{
|
||||
XrSpace meshSpace = 0;
|
||||
switch (spaceType)
|
||||
{
|
||||
case ProjectedPassthroughSpaceType.Headlock:
|
||||
meshSpace = HeadLockSpace;
|
||||
break;
|
||||
case ProjectedPassthroughSpaceType.Worldlock:
|
||||
default:
|
||||
XRInputSubsystem subsystem = null;
|
||||
SubsystemManager.GetInstances(inputSubsystems);
|
||||
if (inputSubsystems.Count > 0)
|
||||
{
|
||||
subsystem = inputSubsystems[0];
|
||||
}
|
||||
|
||||
if (subsystem != null)
|
||||
{
|
||||
TrackingOriginModeFlags trackingOriginMode = subsystem.GetTrackingOriginMode();
|
||||
|
||||
switch (trackingOriginMode)
|
||||
{
|
||||
default:
|
||||
case TrackingOriginModeFlags.Floor:
|
||||
meshSpace = WorldLockSpaceOriginOnFloor;
|
||||
break;
|
||||
case TrackingOriginModeFlags.Device:
|
||||
meshSpace = WorldLockSpaceOriginOnHead;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meshSpace = WorldLockSpaceOriginOnFloor;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return meshSpace;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e78888b9743d564482402fe284c9126
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
{
|
||||
//[StructLayout(LayoutKind.Sequential)]
|
||||
public enum XrStructureTypeHTC
|
||||
{
|
||||
XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC = 1000317001,
|
||||
XR_TYPE_PASSTHROUGH_COLOR_HTC = 1000317002,
|
||||
XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC = 1000317003,
|
||||
XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC = 1000317004,
|
||||
}
|
||||
|
||||
public enum PassthroughLayerForm
|
||||
{
|
||||
///<summary> Fullscreen Passthrough Form</summary>
|
||||
Planar = 0,
|
||||
///<summary> Projected Passthrough Form</summary>
|
||||
Projected = 1
|
||||
}
|
||||
|
||||
public enum ProjectedPassthroughSpaceType
|
||||
{
|
||||
///<summary>
|
||||
/// XR_REFERENCE_SPACE_TYPE_VIEW at (0,0,0) with orientation (0,0,0,1)
|
||||
///</summary>
|
||||
Headlock = 0,
|
||||
///<summary>
|
||||
/// When TrackingOriginMode is TrackingOriginModeFlags.Floor:
|
||||
/// XR_REFERENCE_SPACE_TYPE_STAGE at (0,0,0) with orientation (0,0,0,1)
|
||||
///
|
||||
/// When TrackingOriginMode is TrackingOriginModeFlags.Device:
|
||||
/// XR_REFERENCE_SPACE_TYPE_LOCAL at (0,0,0) with orientation (0,0,0,1)
|
||||
///
|
||||
///</summary>
|
||||
Worldlock = 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58a0974face1c1b448dab924ce82c5ee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: beb3432f6f958f94bb911a9b9b4174e1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR {
|
||||
public class DisableVisibilityMask
|
||||
{
|
||||
static GameObject Provider;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
static void Start()
|
||||
{
|
||||
Provider = new GameObject();
|
||||
Provider.AddComponent<VisibilityMaskDisabler>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f48023d9309a7f4bb46ff61a3b9523f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public class VisibilityMaskDisabler : MonoBehaviour
|
||||
{
|
||||
const string TAG = "VisibilityMaskDisabler";
|
||||
void Enable()
|
||||
{
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (NeedWorkAround() && XRSettings.occlusionMaskScale != 0.0f)
|
||||
{
|
||||
Debug.Log(TAG + "Try set scale to 0");
|
||||
XRSettings.occlusionMaskScale = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
bool NeedWorkAround()
|
||||
{
|
||||
if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Vulkan && (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePass || XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassMultiview))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9a8ed5424d972e42a118a829088c5f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 248e0c72c6c43ef4b8f2bef4f4a5901a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fd4c5098d66cc74294f6c590e9e24cb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,206 @@
|
||||
# 12.54. XR_FB_display_refresh_rate
|
||||
## Name String
|
||||
XR_FB_display_refresh_rate
|
||||
## Revision
|
||||
1
|
||||
## Overview
|
||||
|
||||
On platforms which support dynamically adjusting the display refresh rate, application developers may request a specific display refresh rate in order to improve the overall user experience, examples include:
|
||||
|
||||
A video application may choose a display refresh rate which better matches the video content playback rate in order to achieve smoother video frames.
|
||||
|
||||
An application which can support a higher frame rate may choose to render at the higher rate to improve the overall perceptual quality, for example, lower latency and less flicker.
|
||||
|
||||
This extension allows:
|
||||
|
||||
An application to identify what display refresh rates the session supports and the current display refresh rate.
|
||||
|
||||
An application to request a display refresh rate to indicate its preference to the runtime.
|
||||
|
||||
An application to receive notification of changes to the display refresh rate which are delivered via events.
|
||||
|
||||
In order to enable the functionality of this extension, the application must pass the name of the extension into xrCreateInstance via the XrInstanceCreateInfo::enabledExtensionNames parameter as indicated in the Extensions section.
|
||||
|
||||
New Object Types
|
||||
|
||||
New Flag Types
|
||||
|
||||
New Enum Constants
|
||||
|
||||
XrStructureType enumeration is extended with:
|
||||
|
||||
XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB
|
||||
|
||||
XrResult enumeration is extended with:
|
||||
|
||||
XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB
|
||||
|
||||
New Enums
|
||||
|
||||
New Structures
|
||||
|
||||
Receiving the XrEventDataDisplayRefreshRateChangedFB event structure indicates that the display refresh rate has changed.
|
||||
|
||||
The XrEventDataDisplayRefreshRateChangedFB structure is defined as:
|
||||
|
||||
// Provided by XR_FB_display_refresh_rate
|
||||
typedef struct XrEventDataDisplayRefreshRateChangedFB {
|
||||
XrStructureType type;
|
||||
const void* next;
|
||||
float fromDisplayRefreshRate;
|
||||
float toDisplayRefreshRate;
|
||||
} XrEventDataDisplayRefreshRateChangedFB;
|
||||
Member Descriptions
|
||||
type is the XrStructureType of this structure.
|
||||
|
||||
next is NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
|
||||
|
||||
fromDisplayRefreshRate is the previous display refresh rate.
|
||||
|
||||
toDisplayRefreshRate is the new display refresh rate.
|
||||
|
||||
Valid Usage (Implicit)
|
||||
The XR_FB_display_refresh_rate extension must be enabled prior to using XrEventDataDisplayRefreshRateChangedFB
|
||||
|
||||
type must be XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB
|
||||
|
||||
next must be NULL or a valid pointer to the next structure in a structure chain
|
||||
|
||||
New Functions
|
||||
|
||||
The xrEnumerateDisplayRefreshRatesFB function is defined as:
|
||||
|
||||
// Provided by XR_FB_display_refresh_rate
|
||||
XrResult xrEnumerateDisplayRefreshRatesFB(
|
||||
XrSession session,
|
||||
uint32_t displayRefreshRateCapacityInput,
|
||||
uint32_t* displayRefreshRateCountOutput,
|
||||
float* displayRefreshRates);
|
||||
Parameter Descriptions
|
||||
session is the session that enumerates the supported display refresh rates.
|
||||
|
||||
displayRefreshRateCapacityInput is the capacity of the displayRefreshRates, or 0 to retrieve the required capacity.
|
||||
|
||||
displayRefreshRateCountOutput is a pointer to the count of float displayRefreshRates written, or a pointer to the required capacity in the case that displayRefreshRateCapacityInput is insufficient.
|
||||
|
||||
displayRefreshRates is a pointer to an array of float display refresh rates, but can be NULL if displayRefreshRateCapacityInput is 0.
|
||||
|
||||
See Buffer Size Parameters chapter for a detailed description of retrieving the required displayRefreshRates size.
|
||||
|
||||
xrEnumerateDisplayRefreshRatesFB enumerates the display refresh rates supported by the current session. Display refresh rates must be in order from lowest to highest supported display refresh rates. Runtimes must always return identical buffer contents from this enumeration for the lifetime of the session.
|
||||
|
||||
Valid Usage (Implicit)
|
||||
The XR_FB_display_refresh_rate extension must be enabled prior to calling xrEnumerateDisplayRefreshRatesFB
|
||||
|
||||
session must be a valid XrSession handle
|
||||
|
||||
displayRefreshRateCountOutput must be a pointer to a uint32_t value
|
||||
|
||||
If displayRefreshRateCapacityInput is not 0, displayRefreshRates must be a pointer to an array of displayRefreshRateCapacityInput float values
|
||||
|
||||
Return Codes
|
||||
Success
|
||||
XR_SUCCESS
|
||||
|
||||
XR_SESSION_LOSS_PENDING
|
||||
|
||||
Failure
|
||||
XR_ERROR_FUNCTION_UNSUPPORTED
|
||||
|
||||
XR_ERROR_VALIDATION_FAILURE
|
||||
|
||||
XR_ERROR_RUNTIME_FAILURE
|
||||
|
||||
XR_ERROR_HANDLE_INVALID
|
||||
|
||||
XR_ERROR_INSTANCE_LOST
|
||||
|
||||
XR_ERROR_SESSION_LOST
|
||||
|
||||
XR_ERROR_SIZE_INSUFFICIENT
|
||||
|
||||
The xrGetDisplayRefreshRateFB function is defined as:
|
||||
|
||||
// Provided by XR_FB_display_refresh_rate
|
||||
XrResult xrGetDisplayRefreshRateFB(
|
||||
XrSession session,
|
||||
float* displayRefreshRate);
|
||||
Parameter Descriptions
|
||||
session is the XrSession to query.
|
||||
|
||||
displayRefreshRate is a pointer to a float into which the current display refresh rate will be placed.
|
||||
|
||||
xrGetDisplayRefreshRateFB retrieves the current display refresh rate.
|
||||
|
||||
Valid Usage (Implicit)
|
||||
The XR_FB_display_refresh_rate extension must be enabled prior to calling xrGetDisplayRefreshRateFB
|
||||
|
||||
session must be a valid XrSession handle
|
||||
|
||||
displayRefreshRate must be a pointer to a float value
|
||||
|
||||
Return Codes
|
||||
Success
|
||||
XR_SUCCESS
|
||||
|
||||
XR_SESSION_LOSS_PENDING
|
||||
|
||||
Failure
|
||||
XR_ERROR_FUNCTION_UNSUPPORTED
|
||||
|
||||
XR_ERROR_VALIDATION_FAILURE
|
||||
|
||||
XR_ERROR_RUNTIME_FAILURE
|
||||
|
||||
XR_ERROR_HANDLE_INVALID
|
||||
|
||||
XR_ERROR_INSTANCE_LOST
|
||||
|
||||
XR_ERROR_SESSION_LOST
|
||||
|
||||
The xrRequestDisplayRefreshRateFB function is defined as:
|
||||
|
||||
// Provided by XR_FB_display_refresh_rate
|
||||
XrResult xrRequestDisplayRefreshRateFB(
|
||||
XrSession session,
|
||||
float displayRefreshRate);
|
||||
Parameter Descriptions
|
||||
session is a valid XrSession handle.
|
||||
|
||||
displayRefreshRate is 0.0f or a supported display refresh rate. Supported display refresh rates are indicated by xrEnumerateDisplayRefreshRatesFB.
|
||||
|
||||
xrRequestDisplayRefreshRateFB provides a mechanism for an application to request the system to dynamically change the display refresh rate to the application preferred value. The runtime must return XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB if displayRefreshRate is not either 0.0f or one of the values enumerated by xrEnumerateDisplayRefreshRatesFB. A display refresh rate of 0.0f indicates the application has no preference.
|
||||
|
||||
Note that this is only a request and does not guarantee the system will switch to the requested display refresh rate.
|
||||
|
||||
Valid Usage (Implicit)
|
||||
The XR_FB_display_refresh_rate extension must be enabled prior to calling xrRequestDisplayRefreshRateFB
|
||||
|
||||
session must be a valid XrSession handle
|
||||
|
||||
Return Codes
|
||||
Success
|
||||
XR_SUCCESS
|
||||
|
||||
XR_SESSION_LOSS_PENDING
|
||||
|
||||
Failure
|
||||
XR_ERROR_FUNCTION_UNSUPPORTED
|
||||
|
||||
XR_ERROR_VALIDATION_FAILURE
|
||||
|
||||
XR_ERROR_RUNTIME_FAILURE
|
||||
|
||||
XR_ERROR_HANDLE_INVALID
|
||||
|
||||
XR_ERROR_INSTANCE_LOST
|
||||
|
||||
XR_ERROR_SESSION_LOST
|
||||
|
||||
XR_ERROR_FEATURE_UNSUPPORTED
|
||||
|
||||
XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB
|
||||
|
||||
Issues
|
||||
|
||||
Changing the display refresh rate from its system default does not come without trade-offs. Increasing the display refresh rate puts more load on the entire system and can lead to thermal degradation. Conversely, lowering the display refresh rate can provide better thermal sustainability but at the cost of more perceptual issues, like higher latency and flickering.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77f492ea9a608234294b51cf030292f6
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e3d6a1242bdfeb429ae342486ba096e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,263 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine;
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.DisplayRefreshRate
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "XR FB Display Refresh Rate",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android},
|
||||
Company = "HTC",
|
||||
Desc = "Support the display refresh rate.",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionString,
|
||||
Version = "1.0.0",
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class ViveDisplayRefreshRate : OpenXRFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.DisplayRefreshRate";
|
||||
void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <summary>
|
||||
/// OpenXR specification <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_FB_display_refresh_rate">12.54. XR_FB_display_refresh_rate</see>.
|
||||
/// </summary>
|
||||
public const string kOpenxrExtensionString = "XR_FB_display_refresh_rate";
|
||||
|
||||
/// <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.displayrefreshrate";
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
private XrInstance m_XrInstance = 0;
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateInstance">xrCreateInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The created instance.</param>
|
||||
/// <returns>True for valid <see cref="XrInstance">XrInstance</see></returns>
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
{
|
||||
WARNING("OnInstanceCreate() " + kOpenxrExtensionString + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_XrInstance = xrInstance;
|
||||
DEBUG("OnInstanceCreate() " + m_XrInstance);
|
||||
|
||||
return GetXrFunctionDelegates(m_XrInstance);
|
||||
}
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroyInstance">xrDestroyInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The instance to destroy.</param>
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
m_XrInstance = 0;
|
||||
DEBUG("OnInstanceDestroy() " + xrInstance);
|
||||
}
|
||||
|
||||
private XrSystemId m_XrSystemId = 0;
|
||||
/// <summary>
|
||||
/// Called when the <see cref="XrSystemId">XrSystemId</see> retrieved by <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystem">xrGetSystem</see> is changed.
|
||||
/// </summary>
|
||||
/// <param name="xrSystem">The system id.</param>
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
m_XrSystemId = xrSystem;
|
||||
DEBUG("OnSystemChange() " + m_XrSystemId);
|
||||
}
|
||||
|
||||
private XrSession m_XrSession = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateSession">xrCreateSession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The created session ID.</param>
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
m_XrSession = xrSession;
|
||||
DEBUG("OnSessionCreate() " + m_XrSession);
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroySession">xrDestroySession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The session ID to destroy.</param>
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
DEBUG("OnSessionDestroy() " + xrSession);
|
||||
|
||||
m_XrSession = 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OpenXR function delegates
|
||||
/// xrGetInstanceProcAddr
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr;
|
||||
|
||||
//xrRequestDisplayRefreshRateFB
|
||||
OpenXRHelper.xrRequestDisplayRefreshRateFBDelegate xrRequestDisplayRefreshRateFB;
|
||||
|
||||
//xrGetDisplayRefreshRateFB
|
||||
OpenXRHelper.xrGetDisplayRefreshRateFBDelegate xrGetDisplayRefreshRateFB;
|
||||
|
||||
//xrEnumerateDisplayRefreshRatesFB
|
||||
OpenXRHelper.xrEnumerateDisplayRefreshRatesFBDelegate xrEnumerateDisplayRefreshRatesFB;
|
||||
|
||||
|
||||
private bool GetXrFunctionDelegates(XrInstance xrInstance)
|
||||
{
|
||||
/// xrGetInstanceProcAddr
|
||||
if (xrGetInstanceProcAddr != null && xrGetInstanceProcAddr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetInstanceProcAddr.");
|
||||
XrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(
|
||||
xrGetInstanceProcAddr,
|
||||
typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate)) as OpenXRHelper.xrGetInstanceProcAddrDelegate;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetInstanceProcAddr");
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
DEBUG("Try Get function pointer of xrRequestDisplayRefreshRateFB.");
|
||||
|
||||
/// xrRequestDisplayRefreshRateFB
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrRequestDisplayRefreshRateFB", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrRequestDisplayRefreshRateFB.");
|
||||
xrRequestDisplayRefreshRateFB = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrRequestDisplayRefreshRateFBDelegate)) as OpenXRHelper.xrRequestDisplayRefreshRateFBDelegate;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("0. Get function pointer of xrRequestDisplayRefreshRateFB failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("1. Get function pointer of xrRequestDisplayRefreshRateFB failed.");
|
||||
}
|
||||
|
||||
/// xrGetDisplayRefreshRateFB
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrGetDisplayRefreshRateFB", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetDisplayRefreshRateFB.");
|
||||
xrGetDisplayRefreshRateFB = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrGetDisplayRefreshRateFBDelegate)) as OpenXRHelper.xrGetDisplayRefreshRateFBDelegate;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("0. Get function pointer of xrGetDisplayRefreshRateFB failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("1. Get function pointer of xrGetDisplayRefreshRateFB failed.");
|
||||
}
|
||||
|
||||
/// xrEnumerateDisplayRefreshRatesFB
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrEnumerateDisplayRefreshRatesFB", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrEnumerateDisplayRefreshRatesFB.");
|
||||
xrEnumerateDisplayRefreshRatesFB = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrEnumerateDisplayRefreshRatesFBDelegate)) as OpenXRHelper.xrEnumerateDisplayRefreshRatesFBDelegate;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("0. Get function pointer of xrEnumerateDisplayRefreshRatesFB failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("1. Get function pointer of xrEnumerateDisplayRefreshRatesFB failed.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refer to OpenXR <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrRequestDisplayRefreshRateFB">xrRequestDisplayRefreshRateFB</see>.
|
||||
/// </summary>
|
||||
/// <param name="displayRefreshRate"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult RequestDisplayRefreshRate(float displayRefreshRate)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled("XR_FB_display_refresh_rate"))
|
||||
{
|
||||
WARNING("RequestDisplayRefreshRate: XR_FB_display_refresh_rate is NOT enabled.");
|
||||
return XrResult.XR_ERROR_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
return xrRequestDisplayRefreshRateFB(m_XrSession, displayRefreshRate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refer to OpenXR <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetDisplayRefreshRateFB">xrGetDisplayRefreshRateFB</see>.
|
||||
/// </summary>
|
||||
/// <param name="displayRefreshRate"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult GetDisplayRefreshRate(out float displayRefreshRate)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled("XR_FB_display_refresh_rate"))
|
||||
{
|
||||
WARNING("GetDisplayRefreshRate: XR_FB_display_refresh_rate is NOT enabled.");
|
||||
displayRefreshRate = 90.0f;
|
||||
return XrResult.XR_ERROR_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
return xrGetDisplayRefreshRateFB(m_XrSession, out displayRefreshRate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refer to OpenXR <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrEnumerateDisplayRefreshRatesFB">xrEnumerateDisplayRefreshRatesFB</see>.
|
||||
/// </summary>
|
||||
/// <param name="displayRefreshRateCapacityInput"></param>
|
||||
/// <param name="displayRefreshRateCountOutput"></param>
|
||||
/// <param name="displayRefreshRates"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult EnumerateDisplayRefreshRates(UInt32 displayRefreshRateCapacityInput, out UInt32 displayRefreshRateCountOutput, out float displayRefreshRates)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled("XR_FB_display_refresh_rate"))
|
||||
{
|
||||
WARNING("EnumerateDisplayRefreshRates: XR_FB_display_refresh_rate is NOT enabled.");
|
||||
displayRefreshRateCountOutput = 0;
|
||||
displayRefreshRates = 90.0f;
|
||||
return XrResult.XR_ERROR_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
return xrEnumerateDisplayRefreshRatesFB(m_XrSession, displayRefreshRateCapacityInput, out displayRefreshRateCountOutput, out displayRefreshRates);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c6529da49ed6c34e9fc93a1ccfd9d4f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,79 @@
|
||||
// ===================== 2022 HTC Corporation. All Rights Reserved. ===================
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using VIVE.OpenXR.DisplayRefreshRate;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public class XR_FB_display_refresh_rate_defs
|
||||
{
|
||||
public virtual XrResult RequestDisplayRefreshRate(float displayRefreshRate)
|
||||
{
|
||||
return XrResult.XR_ERROR_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
public virtual XrResult GetDisplayRefreshRate(out float displayRefreshRate)
|
||||
{
|
||||
displayRefreshRate = 90.0f;
|
||||
return XrResult.XR_ERROR_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
public virtual XrResult EnumerateDisplayRefreshRates(UInt32 displayRefreshRateCapacityInput, out UInt32 displayRefreshRateCountOutput, out float displayRefreshRates)
|
||||
{
|
||||
displayRefreshRateCountOutput = 0;
|
||||
displayRefreshRates = 90.0f;
|
||||
return XrResult.XR_ERROR_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
public class XR_FB_display_refresh_rate
|
||||
{
|
||||
static XR_FB_display_refresh_rate_defs m_Instance = null;
|
||||
public static XR_FB_display_refresh_rate_defs Interop
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Instance == null)
|
||||
{
|
||||
m_Instance = new XR_FB_display_refresh_rate_impls();
|
||||
}
|
||||
return m_Instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refer to OpenXR <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrRequestDisplayRefreshRateFB">xrRequestDisplayRefreshRateFB</see>.
|
||||
/// </summary>
|
||||
/// <param name="displayRefreshRate"></param>
|
||||
/// <returns></returns>
|
||||
public static XrResult RequestDisplayRefreshRate(float displayRefreshRate)
|
||||
{
|
||||
return Interop.RequestDisplayRefreshRate(displayRefreshRate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refer to OpenXR <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetDisplayRefreshRateFB">xrGetDisplayRefreshRateFB</see>.
|
||||
/// </summary>
|
||||
/// <param name="displayRefreshRate"></param>
|
||||
/// <returns></returns>
|
||||
public static XrResult GetDisplayRefreshRate(out float displayRefreshRate)
|
||||
{
|
||||
return Interop.GetDisplayRefreshRate(out displayRefreshRate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refer to OpenXR <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrEnumerateDisplayRefreshRatesFB">xrEnumerateDisplayRefreshRatesFB</see>.
|
||||
/// </summary>
|
||||
/// <param name="displayRefreshRateCapacityInput"></param>
|
||||
/// <param name="displayRefreshRateCountOutput"></param>
|
||||
/// <param name="displayRefreshRates"></param>
|
||||
/// <returns></returns>
|
||||
public static XrResult EnumerateDisplayRefreshRates(UInt32 displayRefreshRateCapacityInput, out UInt32 displayRefreshRateCountOutput, out float displayRefreshRates)
|
||||
{
|
||||
return Interop.EnumerateDisplayRefreshRates(displayRefreshRateCapacityInput, out displayRefreshRateCountOutput, out displayRefreshRates);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8862d382ed6b93d499db2e5724af1939
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,68 @@
|
||||
// ===================== 2022 HTC Corporation. All Rights Reserved. ===================
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
using UnityEngine.XR.OpenXR;
|
||||
|
||||
using VIVE.OpenXR.DisplayRefreshRate;
|
||||
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public class XR_FB_display_refresh_rate_impls : XR_FB_display_refresh_rate_defs
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.XR_FB_display_refresh_rate_impls";
|
||||
void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
|
||||
private ViveDisplayRefreshRate feature = null;
|
||||
private void ASSERT_FEATURE() {
|
||||
if (feature == null) { feature = OpenXRSettings.Instance.GetFeature<ViveDisplayRefreshRate>(); }
|
||||
}
|
||||
|
||||
public override XrResult RequestDisplayRefreshRate(float displayRefreshRate)
|
||||
{
|
||||
DEBUG("RequestDisplayRefreshRate");
|
||||
XrResult result = XrResult.XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
ASSERT_FEATURE();
|
||||
if (feature)
|
||||
{
|
||||
result = (XrResult)feature.RequestDisplayRefreshRate(displayRefreshRate);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override XrResult GetDisplayRefreshRate(out float displayRefreshRate)
|
||||
{
|
||||
//DEBUG("GetDisplayRefreshRate");
|
||||
XrResult result = XrResult.XR_ERROR_VALIDATION_FAILURE;
|
||||
displayRefreshRate = 0.0f;
|
||||
|
||||
ASSERT_FEATURE();
|
||||
if (feature)
|
||||
{
|
||||
result = (XrResult)feature.GetDisplayRefreshRate(out displayRefreshRate);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override XrResult EnumerateDisplayRefreshRates(UInt32 displayRefreshRateCapacityInput, out UInt32 displayRefreshRateCountOutput, out float displayRefreshRates)
|
||||
{
|
||||
DEBUG("EnumerateDisplayRefreshRates");
|
||||
XrResult result = XrResult.XR_ERROR_VALIDATION_FAILURE;
|
||||
displayRefreshRateCountOutput = 0;
|
||||
displayRefreshRates = 90.0f;
|
||||
|
||||
ASSERT_FEATURE();
|
||||
if (feature)
|
||||
{
|
||||
result = (XrResult)feature.EnumerateDisplayRefreshRates(displayRefreshRateCapacityInput, out displayRefreshRateCountOutput, out displayRefreshRates);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4578bfda663cfda4a9ae76831b9ecc8f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 918d2a03e014f5348b0f5fc5c6f7630c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 734a59e6cccf84f4f9407d01c4d88727
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,87 @@
|
||||
# 12.68. XR_HTC_facial_tracking
|
||||
## Name String
|
||||
XR_HTC_facial_tracking
|
||||
## Revision
|
||||
1
|
||||
## Overview
|
||||
This extension allows an application to track and integrate users' eye and lip movements, empowering developers to read intention and model facial expressions.
|
||||
|
||||
## VIVE Plugin
|
||||
|
||||
Through feeding the blend shape values of eye expression to an avatar, its facial expression can be animated with the player<65><72>s eye movement. The following enumerations show the facial expression of eye blend shape.
|
||||
|
||||
public enum XrEyeExpressionHTC
|
||||
{
|
||||
XR_EYE_EXPRESSION_LEFT_BLINK_HTC = 0,
|
||||
XR_EYE_EXPRESSION_LEFT_WIDE_HTC = 1,
|
||||
XR_EYE_EXPRESSION_RIGHT_BLINK_HTC = 2,
|
||||
XR_EYE_EXPRESSION_RIGHT_WIDE_HTC = 3,
|
||||
XR_EYE_EXPRESSION_LEFT_SQUEEZE_HTC = 4,
|
||||
XR_EYE_EXPRESSION_RIGHT_SQUEEZE_HTC = 5,
|
||||
XR_EYE_EXPRESSION_LEFT_DOWN_HTC = 6,
|
||||
XR_EYE_EXPRESSION_RIGHT_DOWN_HTC = 7,
|
||||
XR_EYE_EXPRESSION_LEFT_OUT_HTC = 8,
|
||||
XR_EYE_EXPRESSION_RIGHT_IN_HTC = 9,
|
||||
XR_EYE_EXPRESSION_LEFT_IN_HTC = 10,
|
||||
XR_EYE_EXPRESSION_RIGHT_OUT_HTC = 11,
|
||||
XR_EYE_EXPRESSION_LEFT_UP_HTC = 12,
|
||||
XR_EYE_EXPRESSION_RIGHT_UP_HTC = 13,
|
||||
XR_EYE_EXPRESSION_MAX_ENUM_HTC = 14
|
||||
};
|
||||
|
||||
You can use the following API to retrieve the array of eye expression values if the return value is true.
|
||||
|
||||
using VIVE.OpenXR.FacialTracking;
|
||||
|
||||
bool ViveFacialTracking.GetFacialExpressions(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC, out float[] expressionWeightings);
|
||||
|
||||
Through feeding the blend shape values of lip expression to an avatar, its facial expression can be animated with the player<65><72>s lip movement. The following enumerations show the facial expression of lip blend shape values.
|
||||
|
||||
public enum XrLipExpressionHTC
|
||||
{
|
||||
XR_LIP_EXPRESSION_JAW_RIGHT_HTC = 0,
|
||||
XR_LIP_EXPRESSION_JAW_LEFT_HTC = 1,
|
||||
XR_LIP_EXPRESSION_JAW_FORWARD_HTC = 2,
|
||||
XR_LIP_EXPRESSION_JAW_OPEN_HTC = 3,
|
||||
XR_LIP_EXPRESSION_MOUTH_APE_SHAPE_HTC = 4,
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_RIGHT_HTC = 5,
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_LEFT_HTC = 6,
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_RIGHT_HTC = 7,
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_LEFT_HTC = 8,
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_OVERTURN_HTC = 9,
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_OVERTURN_HTC = 10,
|
||||
XR_LIP_EXPRESSION_MOUTH_POUT_HTC = 11,
|
||||
XR_LIP_EXPRESSION_MOUTH_SMILE_RIGHT_HTC = 12,
|
||||
XR_LIP_EXPRESSION_MOUTH_SMILE_LEFT_HTC = 13,
|
||||
XR_LIP_EXPRESSION_MOUTH_SAD_RIGHT_HTC = 14,
|
||||
XR_LIP_EXPRESSION_MOUTH_SAD_LEFT_HTC = 15,
|
||||
XR_LIP_EXPRESSION_CHEEK_PUFF_RIGHT_HTC = 16,
|
||||
XR_LIP_EXPRESSION_CHEEK_PUFF_LEFT_HTC = 17,
|
||||
XR_LIP_EXPRESSION_CHEEK_SUCK_HTC = 18,
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC = 19,
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_UPLEFT_HTC = 20,
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNRIGHT_HTC = 21,
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNLEFT_HTC = 22,
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_INSIDE_HTC = 23,
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_INSIDE_HTC = 24,
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_OVERLAY_HTC = 25,
|
||||
XR_LIP_EXPRESSION_TONGUE_LONGSTEP1_HTC = 26,
|
||||
XR_LIP_EXPRESSION_TONGUE_LEFT_HTC = 27,
|
||||
XR_LIP_EXPRESSION_TONGUE_RIGHT_HTC = 28,
|
||||
XR_LIP_EXPRESSION_TONGUE_UP_HTC = 29,
|
||||
XR_LIP_EXPRESSION_TONGUE_DOWN_HTC = 30,
|
||||
XR_LIP_EXPRESSION_TONGUE_ROLL_HTC = 31,
|
||||
XR_LIP_EXPRESSION_TONGUE_LONGSTEP2_HTC = 32,
|
||||
XR_LIP_EXPRESSION_TONGUE_UPRIGHT_MORPH_HTC = 33,
|
||||
XR_LIP_EXPRESSION_TONGUE_UPLEFT_MORPH_HTC = 34,
|
||||
XR_LIP_EXPRESSION_TONGUE_DOWNRIGHT_MORPH_HTC = 35,
|
||||
XR_LIP_EXPRESSION_TONGUE_DOWNLEFT_MORPH_HTC = 36,
|
||||
XR_LIP_EXPRESSION_MAX_ENUM_HTC = 37
|
||||
};
|
||||
|
||||
You can use the following API to retrieve the array of eye expression values if the return value is true.
|
||||
|
||||
using VIVE.OpenXR.FacialTracking;
|
||||
|
||||
bool ViveFacialTracking.GetFacialExpressions(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC, out float[] expressionWeightings);
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be0ee5c3ad3e1b64590d426f9d79b274
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3aca591eccf98834c902458afd7c5bc0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,595 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine;
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.FacialTracking
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Facial Tracking",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android, BuildTargetGroup.Standalone },
|
||||
Company = "HTC",
|
||||
Desc = "Support the facial tracking extension.",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionString,
|
||||
Version = "1.0.0",
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class ViveFacialTracking : OpenXRFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.FacialTracking.ViveFacialTracking";
|
||||
void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <summary>
|
||||
/// OpenXR specification <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_facial_tracking">12.68. XR_HTC_facial_tracking</see>.
|
||||
/// </summary>
|
||||
public const string kOpenxrExtensionString = "XR_HTC_facial_tracking";
|
||||
|
||||
/// <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.facial.tracking";
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
private bool m_XrInstanceCreated = false;
|
||||
private XrInstance m_XrInstance = 0;
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateInstance">xrCreateInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The created instance.</param>
|
||||
/// <returns>True for valid <see cref="XrInstance">XrInstance</see></returns>
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
{
|
||||
WARNING("OnInstanceCreate() " + kOpenxrExtensionString + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_XrInstanceCreated = true;
|
||||
m_XrInstance = xrInstance;
|
||||
DEBUG("OnInstanceCreate() " + m_XrInstance);
|
||||
|
||||
return GetXrFunctionDelegates(m_XrInstance);
|
||||
}
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroyInstance">xrDestroyInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The instance to destroy.</param>
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
m_XrInstanceCreated = false;
|
||||
m_XrInstance = 0;
|
||||
DEBUG("OnInstanceDestroy() " + xrInstance);
|
||||
}
|
||||
|
||||
private XrSystemId m_XrSystemId = 0;
|
||||
/// <summary>
|
||||
/// Called when the <see cref="XrSystemId">XrSystemId</see> retrieved by <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystem">xrGetSystem</see> is changed.
|
||||
/// </summary>
|
||||
/// <param name="xrSystem">The system id.</param>
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
m_XrSystemId = xrSystem;
|
||||
DEBUG("OnSystemChange() " + m_XrSystemId);
|
||||
}
|
||||
|
||||
private bool m_XrSessionCreated = false;
|
||||
private XrSession m_XrSession = 0;
|
||||
private bool hasEyeTracker = false, hasLipTracker = false;
|
||||
private XrFacialTrackerHTC m_EyeTracker = 0, m_LipTracker = 0;
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateSession">xrCreateSession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The created session ID.</param>
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
m_XrSession = xrSession;
|
||||
m_XrSessionCreated = true;
|
||||
DEBUG("OnSessionCreate() " + m_XrSession);
|
||||
|
||||
if (CreateFacialTracker(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC)) { DEBUG("OnSessionCreate() m_EyeTracker " + m_EyeTracker); }
|
||||
if (CreateFacialTracker(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC)) { DEBUG("OnSessionCreate() m_LipTracker " + m_LipTracker); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroySession">xrDestroySession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The session ID to destroy.</param>
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
DEBUG("OnSessionDestroy() " + xrSession);
|
||||
|
||||
// Facial Tracking is binding with xrSession so we destroy the trackers when xrSession is destroyed.
|
||||
DestroyFacialTracker(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC);
|
||||
DestroyFacialTracker(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC);
|
||||
|
||||
m_XrSession = 0;
|
||||
m_XrSessionCreated = false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OpenXR function delegates
|
||||
/// xrGetInstanceProcAddr
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr;
|
||||
|
||||
/// xrGetSystemProperties
|
||||
OpenXRHelper.xrGetSystemPropertiesDelegate xrGetSystemProperties;
|
||||
private XrResult GetSystemProperties(ref XrSystemProperties properties)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("GetSystemProperties() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("GetSystemProperties() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrGetSystemProperties(m_XrInstance, m_XrSystemId, ref properties);
|
||||
}
|
||||
|
||||
/// xrDestroySpace
|
||||
OpenXRHelper.xrDestroySpaceDelegate xrDestroySpace;
|
||||
private XrResult DestroySpace(XrSpace space)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("DestroySpace() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("DestroySpace() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrDestroySpace(space);
|
||||
}
|
||||
|
||||
ViveFacialTrackingHelper.xrCreateFacialTrackerHTCDelegate xrCreateFacialTrackerHTC;
|
||||
private XrResult CreateFacialTrackerHTC(XrFacialTrackerCreateInfoHTC createInfo, out XrFacialTrackerHTC facialTracker)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("CreateFacialTrackerHTC() XR_ERROR_SESSION_LOST.");
|
||||
facialTracker = 0;
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("CreateFacialTrackerHTC() XR_ERROR_INSTANCE_LOST.");
|
||||
facialTracker = 0;
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrCreateFacialTrackerHTC(m_XrSession, createInfo, out facialTracker);
|
||||
}
|
||||
|
||||
ViveFacialTrackingHelper.xrDestroyFacialTrackerHTCDelegate xrDestroyFacialTrackerHTC;
|
||||
private XrResult DestroyFacialTrackerHTC(XrFacialTrackerHTC facialTracker)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("DestroyFacialTrackerHTC() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("DestroyFacialTrackerHTC() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrDestroyFacialTrackerHTC(facialTracker);
|
||||
}
|
||||
|
||||
ViveFacialTrackingHelper.xrGetFacialExpressionsHTCDelegate xrGetFacialExpressionsHTC;
|
||||
private XrResult GetFacialExpressionsHTC(XrFacialTrackerHTC facialTracker, ref XrFacialExpressionsHTC facialExpressions)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("GetFacialExpressionsHTC() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("GetFacialExpressionsHTC() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrGetFacialExpressionsHTC(facialTracker, ref facialExpressions);
|
||||
}
|
||||
|
||||
private bool GetXrFunctionDelegates(XrInstance xrInstance)
|
||||
{
|
||||
/// xrGetInstanceProcAddr
|
||||
if (xrGetInstanceProcAddr != null && xrGetInstanceProcAddr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetInstanceProcAddr.");
|
||||
XrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(
|
||||
xrGetInstanceProcAddr,
|
||||
typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate)) as OpenXRHelper.xrGetInstanceProcAddrDelegate;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetInstanceProcAddr");
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
/// xrGetSystemProperties
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrGetSystemProperties", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetSystemProperties.");
|
||||
xrGetSystemProperties = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrGetSystemPropertiesDelegate)) as OpenXRHelper.xrGetSystemPropertiesDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetSystemProperties");
|
||||
return false;
|
||||
}
|
||||
/// xrDestroySpace
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrDestroySpace", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrDestroySpace.");
|
||||
xrDestroySpace = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrDestroySpaceDelegate)) as OpenXRHelper.xrDestroySpaceDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrDestroySpace");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// xrCreateFacialTrackerHTC
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrCreateFacialTrackerHTC", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrCreateFacialTrackerHTC.");
|
||||
xrCreateFacialTrackerHTC = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(ViveFacialTrackingHelper.xrCreateFacialTrackerHTCDelegate)) as ViveFacialTrackingHelper.xrCreateFacialTrackerHTCDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrCreateFacialTrackerHTC");
|
||||
return false;
|
||||
}
|
||||
/// xrDestroyFacialTrackerHTC
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrDestroyFacialTrackerHTC", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrDestroyFacialTrackerHTC.");
|
||||
xrDestroyFacialTrackerHTC = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(ViveFacialTrackingHelper.xrDestroyFacialTrackerHTCDelegate)) as ViveFacialTrackingHelper.xrDestroyFacialTrackerHTCDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrDestroyFacialTrackerHTC");
|
||||
return false;
|
||||
}
|
||||
/// xrGetFacialExpressionsHTC
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrGetFacialExpressionsHTC", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetFacialExpressionsHTC.");
|
||||
xrGetFacialExpressionsHTC = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(ViveFacialTrackingHelper.xrGetFacialExpressionsHTCDelegate)) as ViveFacialTrackingHelper.xrGetFacialExpressionsHTCDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetFacialExpressionsHTC");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
XrSystemFacialTrackingPropertiesHTC facialTrackingSystemProperties;
|
||||
XrSystemProperties systemProperties;
|
||||
private bool IsFacialTrackingSupported(XrFacialTrackingTypeHTC facialTrackingType)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("IsFacialTrackingSupported() session is not created.");
|
||||
return false;
|
||||
}
|
||||
|
||||
facialTrackingSystemProperties.type = XrStructureType.XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC;
|
||||
systemProperties.type = XrStructureType.XR_TYPE_SYSTEM_PROPERTIES;
|
||||
systemProperties.next = Marshal.AllocHGlobal(Marshal.SizeOf(facialTrackingSystemProperties));
|
||||
|
||||
long offset = 0;
|
||||
if (IntPtr.Size == 4)
|
||||
offset = systemProperties.next.ToInt32();
|
||||
else
|
||||
offset = systemProperties.next.ToInt64();
|
||||
|
||||
IntPtr sys_facial_tracking_prop_ptr = new IntPtr(offset);
|
||||
Marshal.StructureToPtr(facialTrackingSystemProperties, sys_facial_tracking_prop_ptr, false);
|
||||
|
||||
if (GetSystemProperties(ref systemProperties) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
offset = systemProperties.next.ToInt32();
|
||||
else
|
||||
offset = systemProperties.next.ToInt64();
|
||||
|
||||
sys_facial_tracking_prop_ptr = new IntPtr(offset);
|
||||
facialTrackingSystemProperties = (XrSystemFacialTrackingPropertiesHTC)Marshal.PtrToStructure(sys_facial_tracking_prop_ptr, typeof(XrSystemFacialTrackingPropertiesHTC));
|
||||
|
||||
DEBUG("IsFacialTrackingSupported() XrSystemFacialTrackingPropertiesHTC.supportEyeFacialTracking: "
|
||||
+ facialTrackingSystemProperties.supportEyeFacialTracking
|
||||
+ ", supportLipFacialTracking: "
|
||||
+ facialTrackingSystemProperties.supportLipFacialTracking);
|
||||
|
||||
return (facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC ?
|
||||
(facialTrackingSystemProperties.supportEyeFacialTracking > 0) : (facialTrackingSystemProperties.supportLipFacialTracking > 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("IsFacialTrackingSupported() GetSystemProperties failed.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An application can create an <see cref="XrFacialTrackingTypeHTC">XrFacialTrackerHTC</see> handle using CreateFacialTracker.
|
||||
/// </summary>
|
||||
/// <param name="facialTrackingType">The XrFacialTrackingTypeHTC describes which type of tracking the <see cref="XrFacialTrackerHTC">XrFacialTrackerHTC</see> is using.</param>
|
||||
/// <param name="facialTracker">The returned XrFacialTrackerHTC handle.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public XrResult CreateFacialTracker(XrFacialTrackerCreateInfoHTC createInfo, out XrFacialTrackerHTC facialTracker)
|
||||
{
|
||||
if (createInfo.facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC && hasEyeTracker)
|
||||
{
|
||||
facialTracker = m_EyeTracker;
|
||||
DEBUG("CreateFacialTracker() m_EyeTracker: " + facialTracker + " already created before.");
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
if (createInfo.facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC && hasLipTracker)
|
||||
{
|
||||
facialTracker = m_LipTracker;
|
||||
DEBUG("CreateFacialTracker() m_LipTracker: " + facialTracker + " already created before.");
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
if (!IsFacialTrackingSupported(createInfo.facialTrackingType))
|
||||
{
|
||||
ERROR("CreateFacialTracker() " + createInfo.facialTrackingType + " is NOT supported.");
|
||||
facialTracker = 0;
|
||||
return XrResult.XR_ERROR_VALIDATION_FAILURE;
|
||||
}
|
||||
|
||||
var result = CreateFacialTrackerHTC(createInfo, out facialTracker);
|
||||
DEBUG("CreateFacialTracker() " + createInfo.facialTrackingType + ", CreateFacialTrackerHTC = " + result + ", facialTracker: " + facialTracker);
|
||||
|
||||
if (result == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (createInfo.facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC)
|
||||
{
|
||||
hasEyeTracker = true;
|
||||
m_EyeTracker = facialTracker;
|
||||
DEBUG("CreateFacialTracker() m_EyeTracker " + m_EyeTracker);
|
||||
}
|
||||
if (createInfo.facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC)
|
||||
{
|
||||
hasLipTracker = true;
|
||||
m_LipTracker = facialTracker;
|
||||
DEBUG("CreateFacialTracker() m_LipTracker " + m_LipTracker);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// An application can create an <see cref="XrFacialTrackingTypeHTC">XrFacialTrackerHTC</see> handle using CreateFacialTracker.
|
||||
/// </summary>
|
||||
/// <param name="facialTrackingType">The XrFacialTrackingTypeHTC describes which type of tracking the <see cref="XrFacialTrackerHTC">XrFacialTrackerHTC</see> is using.</param>
|
||||
/// <returns>True for success.</returns>
|
||||
public bool CreateFacialTracker(XrFacialTrackingTypeHTC facialTrackingType)
|
||||
{
|
||||
XrFacialTrackerCreateInfoHTC createInfo = new XrFacialTrackerCreateInfoHTC(
|
||||
in_type: XrStructureType.XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC,
|
||||
in_next: IntPtr.Zero,
|
||||
in_facialTrackingType: facialTrackingType);
|
||||
|
||||
var result = CreateFacialTracker(createInfo, out XrFacialTrackerHTC value);
|
||||
DEBUG("CreateFacialTracker() " + createInfo.facialTrackingType + " tracker: " + value);
|
||||
|
||||
return result == XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the facial tracker and the underlying resources of the <see cref="XrFacialTrackingTypeHTC">facial tracking type</see> when finished with facial tracking experiences.
|
||||
/// </summary>
|
||||
/// <param name="facialTracker">Facial tracker in <see cref="XrFacialTrackerHTC">XrFacialTrackerHTC</see>.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public XrResult DestroyFacialTracker(XrFacialTrackerHTC facialTracker)
|
||||
{
|
||||
XrResult result = DestroyFacialTrackerHTC(facialTracker);
|
||||
DEBUG("DestroyFacialTracker() " + facialTracker + ", result: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Releases the facial tracker and the underlying resources of the <see cref="XrFacialTrackingTypeHTC">facial tracking type</see> when finished with facial tracking experiences.
|
||||
/// </summary>
|
||||
/// <param name="facialTrackingType">The <see cref="XrFacialTrackingTypeHTC">XrFacialTrackingTypeHTC</see> describes which type of tracking the <see cref="XrFacialTrackerHTC">XrFacialTrackerHTC</see> is using.</param>
|
||||
/// <returns>True for success.</returns>
|
||||
public bool DestroyFacialTracker(XrFacialTrackingTypeHTC facialTrackingType)
|
||||
{
|
||||
if (facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC && !hasEyeTracker)
|
||||
{
|
||||
DEBUG("DestroyFacialTracker() no " + facialTrackingType + "tracker.");
|
||||
return true;
|
||||
}
|
||||
if (facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC && !hasLipTracker)
|
||||
{
|
||||
DEBUG("DestroyFacialTracker() no " + facialTrackingType + "tracker.");
|
||||
return true;
|
||||
}
|
||||
|
||||
XrResult ret = XrResult.XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
if (facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC)
|
||||
{
|
||||
ret = DestroyFacialTracker(m_EyeTracker);
|
||||
hasEyeTracker = false;
|
||||
m_EyeTracker = 0;
|
||||
}
|
||||
if (facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC)
|
||||
{
|
||||
ret = DestroyFacialTracker(m_LipTracker);
|
||||
hasLipTracker = false;
|
||||
m_LipTracker = 0;
|
||||
}
|
||||
|
||||
return ret == XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
private int eyeUpdateFrame = -1, lipUpdateFrame = -1;
|
||||
private float[] defExpressionData = new float[(int)XrEyeExpressionHTC.XR_EYE_EXPRESSION_MAX_ENUM_HTC];
|
||||
private float[] s_EyeExpressionData = new float[(int)XrEyeExpressionHTC.XR_EYE_EXPRESSION_MAX_ENUM_HTC];
|
||||
private float[] s_LipExpressionData = new float[(int)XrLipExpressionHTC.XR_LIP_EXPRESSION_MAX_ENUM_HTC];
|
||||
XrFacialExpressionsHTC facialExpressionsDef = new XrFacialExpressionsHTC(XrStructureType.XR_TYPE_FACIAL_EXPRESSIONS_HTC, IntPtr.Zero, false, 0, 0, IntPtr.Zero);
|
||||
XrFacialExpressionsHTC m_FacialExpressionsEye = new XrFacialExpressionsHTC(XrStructureType.XR_TYPE_FACIAL_EXPRESSIONS_HTC, IntPtr.Zero, false, 0, 0, IntPtr.Zero);
|
||||
XrFacialExpressionsHTC m_FacialExpressionsLip = new XrFacialExpressionsHTC(XrStructureType.XR_TYPE_FACIAL_EXPRESSIONS_HTC, IntPtr.Zero, false, 0, 0, IntPtr.Zero);
|
||||
/// <summary>
|
||||
/// Retrieves an array of values of blend shapes for a facial expression on a given time.
|
||||
/// </summary>
|
||||
/// <param name="facialTrackingType">The <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XrFacialTrackingTypeHTC">XrFacialTrackingTypeHTC</see> describes which type of tracking the <see cref="XrFacialTrackerHTC">XrFacialTrackerHTC</see> is using.</param>
|
||||
/// <param name="expressionWeightings">A float array filled in by the runtime, specifying the weightings for each blend shape. The array size is <see cref="XrEyeExpressionHTC.XR_EYE_EXPRESSION_MAX_ENUM_HTC">XR_EYE_EXPRESSION_MAX_ENUM_HTC</see> for eye expression and <see cref="XrLipExpressionHTC.XR_LIP_EXPRESSION_MAX_ENUM_HTC">XR_LIP_EXPRESSION_MAX_ENUM_HTC</see> for lip expression.</param>
|
||||
/// <returns>True for success.</returns>
|
||||
public bool GetFacialExpressions(XrFacialTrackingTypeHTC facialTrackingType, out float[] expressionWeightings)
|
||||
{
|
||||
expressionWeightings = defExpressionData;
|
||||
|
||||
if (facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC)
|
||||
{
|
||||
if (GetFacialExpressions(m_EyeTracker, out XrFacialExpressionsHTC facialExpressions) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (facialExpressions.isActive)
|
||||
{
|
||||
Marshal.Copy(facialExpressions.expressionWeightings, s_EyeExpressionData, 0, (int)facialExpressions.expressionCount);
|
||||
expressionWeightings = s_EyeExpressionData;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (facialTrackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC)
|
||||
{
|
||||
if (GetFacialExpressions(m_LipTracker, out XrFacialExpressionsHTC facialExpressions) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (facialExpressions.isActive)
|
||||
{
|
||||
Marshal.Copy(facialExpressions.expressionWeightings, s_LipExpressionData, 0, (int)facialExpressions.expressionCount);
|
||||
expressionWeightings = s_LipExpressionData;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Retrieves the <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XrFacialExpressionsHTC">XrFacialExpressionsHTC</see> data of a <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XrFacialTrackerHTC">XrFacialTrackerHTC</see>.
|
||||
/// </summary>
|
||||
/// <param name="facialTracker">The <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XrFacialTrackerHTC">XrFacialTrackerHTC</see> handle represents the resources for an facial tracker of the specific facial tracking type.</param>
|
||||
/// <param name="facialExpressions">Structure returns data of a lip facial expression or an eye facial expression.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public XrResult GetFacialExpressions(XrFacialTrackerHTC facialTracker, out XrFacialExpressionsHTC facialExpressions)
|
||||
{
|
||||
facialExpressions = facialExpressionsDef;
|
||||
XrResult result = XrResult.XR_ERROR_VALIDATION_FAILURE;
|
||||
|
||||
if (facialTracker == m_EyeTracker)
|
||||
{
|
||||
if (eyeUpdateFrame == Time.frameCount)
|
||||
{
|
||||
facialExpressions = m_FacialExpressionsEye;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
eyeUpdateFrame = Time.frameCount;
|
||||
|
||||
// Initialize the XrFacialExpressionsHTC struct of Eye.
|
||||
if (m_FacialExpressionsEye.expressionCount == 0)
|
||||
{
|
||||
m_FacialExpressionsEye.type = XrStructureType.XR_TYPE_FACIAL_EXPRESSIONS_HTC;
|
||||
m_FacialExpressionsEye.next = IntPtr.Zero;
|
||||
m_FacialExpressionsEye.isActive = false;
|
||||
m_FacialExpressionsEye.sampleTime = 0;
|
||||
m_FacialExpressionsEye.expressionCount = (UInt32)XrEyeExpressionHTC.XR_EYE_EXPRESSION_MAX_ENUM_HTC;
|
||||
m_FacialExpressionsEye.expressionWeightings = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(float)) * (int)m_FacialExpressionsEye.expressionCount);
|
||||
}
|
||||
|
||||
result = GetFacialExpressionsHTC(facialTracker, ref m_FacialExpressionsEye);
|
||||
if (result == XrResult.XR_SUCCESS) { facialExpressions = m_FacialExpressionsEye; }
|
||||
}
|
||||
if (facialTracker == m_LipTracker)
|
||||
{
|
||||
if (lipUpdateFrame == Time.frameCount)
|
||||
{
|
||||
facialExpressions = m_FacialExpressionsLip;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
lipUpdateFrame = Time.frameCount;
|
||||
|
||||
// Initialize the XrFacialExpressionsHTC struct of Lip.
|
||||
if (m_FacialExpressionsLip.expressionCount == 0)
|
||||
{
|
||||
m_FacialExpressionsLip.type = XrStructureType.XR_TYPE_FACIAL_EXPRESSIONS_HTC;
|
||||
m_FacialExpressionsLip.next = IntPtr.Zero;
|
||||
m_FacialExpressionsLip.isActive = false;
|
||||
m_FacialExpressionsLip.sampleTime = 0;
|
||||
m_FacialExpressionsLip.expressionCount = (UInt32)XrLipExpressionHTC.XR_LIP_EXPRESSION_MAX_ENUM_HTC;
|
||||
m_FacialExpressionsLip.expressionWeightings = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(float)) * (int)m_FacialExpressionsLip.expressionCount);
|
||||
}
|
||||
|
||||
result = GetFacialExpressionsHTC(facialTracker, ref m_FacialExpressionsLip);
|
||||
if (result == XrResult.XR_SUCCESS) { facialExpressions = m_FacialExpressionsLip; }
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 178a55074d1e6624d8cfbdc23367a56f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,449 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace VIVE.OpenXR.FacialTracking
|
||||
{
|
||||
/// <summary>
|
||||
/// The XrFacialTrackerHTC handle represents the resources for an facial tracker of the specific facial tracking type.
|
||||
/// </summary>
|
||||
public struct XrFacialTrackerHTC : IEquatable<UInt64>
|
||||
{
|
||||
private readonly UInt64 value;
|
||||
|
||||
public XrFacialTrackerHTC(UInt64 u)
|
||||
{
|
||||
value = u;
|
||||
}
|
||||
|
||||
public static implicit operator UInt64(XrFacialTrackerHTC equatable)
|
||||
{
|
||||
return equatable.value;
|
||||
}
|
||||
public static implicit operator XrFacialTrackerHTC(UInt64 u)
|
||||
{
|
||||
return new XrFacialTrackerHTC(u);
|
||||
}
|
||||
|
||||
public bool Equals(XrFacialTrackerHTC other)
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
public bool Equals(UInt64 other)
|
||||
{
|
||||
return value == other;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is XrFacialTrackerHTC && Equals((XrFacialTrackerHTC)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
public static bool operator ==(XrFacialTrackerHTC a, XrFacialTrackerHTC b) { return a.Equals(b); }
|
||||
public static bool operator !=(XrFacialTrackerHTC a, XrFacialTrackerHTC b) { return !a.Equals(b); }
|
||||
public static bool operator >=(XrFacialTrackerHTC a, XrFacialTrackerHTC b) { return a.value >= b.value; }
|
||||
public static bool operator <=(XrFacialTrackerHTC a, XrFacialTrackerHTC b) { return a.value <= b.value; }
|
||||
public static bool operator >(XrFacialTrackerHTC a, XrFacialTrackerHTC b) { return a.value > b.value; }
|
||||
public static bool operator <(XrFacialTrackerHTC a, XrFacialTrackerHTC b) { return a.value < b.value; }
|
||||
public static XrFacialTrackerHTC operator +(XrFacialTrackerHTC a, XrFacialTrackerHTC b) { return a.value + b.value; }
|
||||
public static XrFacialTrackerHTC operator -(XrFacialTrackerHTC a, XrFacialTrackerHTC b) { return a.value - b.value; }
|
||||
public static XrFacialTrackerHTC operator *(XrFacialTrackerHTC a, XrFacialTrackerHTC b) { return a.value * b.value; }
|
||||
public static XrFacialTrackerHTC operator /(XrFacialTrackerHTC a, XrFacialTrackerHTC b)
|
||||
{
|
||||
if (b.value == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
return a.value / b.value;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// The XrFacialTrackingTypeHTC describes which type of tracking the <see cref="XrFacialTrackerHTC">XrFacialTrackerHTC</see> is using.
|
||||
/// </summary>
|
||||
public enum XrFacialTrackingTypeHTC
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies this handle will observe eye expressions, with values indexed by <see cref="XrEyeExpressionHTC">XrEyeExpressionHTC</see> whose count is <see cref="ViveFacialTrackingHelper.XR_FACIAL_EXPRESSION_EYE_COUNT_HTC">XR_FACIAL_EXPRESSION_EYE_COUNT_HTC</see>.
|
||||
/// </summary>
|
||||
XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC = 1,
|
||||
/// <summary>
|
||||
/// Specifies this handle will observe lip expressions, with values indexed by <see cref="XrLipExpressionHTC">XrLipExpressionHTC</see> whose count is <see cref="ViveFacialTrackingHelper.XR_FACIAL_EXPRESSION_LIP_COUNT_HTC">XR_FACIAL_EXPRESSION_LIP_COUNT_HTC</see>.
|
||||
/// </summary>
|
||||
XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC = 2,
|
||||
};
|
||||
/// <summary>
|
||||
/// Indicates the eye expressions. Refer to <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XrEyeExpressionHTC">XrEyeExpressionHTC</see> about the illustrations.
|
||||
/// </summary>
|
||||
public enum XrEyeExpressionHTC
|
||||
{
|
||||
/// <summary>
|
||||
/// This blend shape influences blinking of the right eye. When this value goes higher, left eye approaches close.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_LEFT_BLINK_HTC = 0,
|
||||
/// <summary>
|
||||
/// This blend shape keeps left eye wide and at that time XR_EYE_EXPRESSION_LEFT_BLINK_HTC value is 0.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_LEFT_WIDE_HTC = 1,
|
||||
/// <summary>
|
||||
/// This blend shape influences blinking of the right eye. When this value goes higher, right eye approaches close.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_RIGHT_BLINK_HTC = 2,
|
||||
/// <summary>
|
||||
/// This blend shape keeps right eye wide and at that time XR_EYE_EXPRESSION_RIGHT_BLINK_HTC value is 0.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_RIGHT_WIDE_HTC = 3,
|
||||
/// <summary>
|
||||
/// The blend shape closes eye tightly and at that time XR_EYE_EXPRESSION_LEFT_BLINK_HTC value is 1.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_LEFT_SQUEEZE_HTC = 4,
|
||||
/// <summary>
|
||||
/// The blend shape closes eye tightly and at that time XR_EYE_EXPRESSION_RIGHT_BLINK_HTC value is 1.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_RIGHT_SQUEEZE_HTC = 5,
|
||||
/// <summary>
|
||||
/// This blendShape influences the muscles around the left eye, moving these muscles further downward with a higher value.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_LEFT_DOWN_HTC = 6,
|
||||
/// <summary>
|
||||
/// This blendShape influences the muscles around the right eye, moving these muscles further downward with a higher value.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_RIGHT_DOWN_HTC = 7,
|
||||
/// <summary>
|
||||
/// This blendShape influences the muscles around the left eye, moving these muscles further leftward with a higher value.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_LEFT_OUT_HTC = 8,
|
||||
/// <summary>
|
||||
/// This blendShape influences the muscles around the right eye, moving these muscles further leftward with a higher value.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_RIGHT_IN_HTC = 9,
|
||||
/// <summary>
|
||||
/// This blendShape influences the muscles around the left eye, moving these muscles further rightward with a higher value.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_LEFT_IN_HTC = 10,
|
||||
/// <summary>
|
||||
/// This blendShape influences the muscles around the right eye, moving these muscles further rightward with a higher value.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_RIGHT_OUT_HTC = 11,
|
||||
/// <summary>
|
||||
/// This blendShape influences the muscles around the left eye, moving these muscles further upward with a higher value.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_LEFT_UP_HTC = 12,
|
||||
/// <summary>
|
||||
/// This blendShape influences the muscles around the right eye, moving these muscles further upward with a higher value.
|
||||
/// </summary>
|
||||
XR_EYE_EXPRESSION_RIGHT_UP_HTC = 13,
|
||||
XR_EYE_EXPRESSION_MAX_ENUM_HTC = 14
|
||||
};
|
||||
/// <summary>
|
||||
/// Indicates the lip expressions. Refer to <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XrLipExpressionHTC">XrLipExpressionHTC</see> about the illustrations.
|
||||
/// </summary>
|
||||
public enum XrLipExpressionHTC
|
||||
{
|
||||
/// <summary>
|
||||
/// This blend shape moves the jaw further rightward with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_JAW_RIGHT_HTC = 0,
|
||||
/// <summary>
|
||||
/// This blend shape moves the jaw further leftward with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_JAW_LEFT_HTC = 1,
|
||||
/// <summary>
|
||||
/// This blend shape moves the jaw forward with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_JAW_FORWARD_HTC = 2,
|
||||
/// <summary>
|
||||
/// This blend shape opens the mouth further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_JAW_OPEN_HTC = 3,
|
||||
/// <summary>
|
||||
/// This blend shape stretches the jaw further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_APE_SHAPE_HTC = 4,
|
||||
/// <summary>
|
||||
/// This blend shape moves your upper lip rightward.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_RIGHT_HTC = 5,
|
||||
/// <summary>
|
||||
/// This blend shape moves your upper lip leftward.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_LEFT_HTC = 6,
|
||||
/// <summary>
|
||||
/// This blend shape moves your lower lip rightward.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_RIGHT_HTC = 7,
|
||||
/// <summary>
|
||||
/// This blend shape moves your lower lip leftward.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_LEFT_HTC = 8,
|
||||
/// <summary>
|
||||
/// This blend shape pouts your upper lip. Can be used with <see cref="XrLipExpressionHTC.XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC">XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC</see> and <see cref="XrLipExpressionHTC.XR_LIP_EXPRESSION_MOUTH_UPPER_UPLEFT_HTC">XR_LIP_EXPRESSION_MOUTH_UPPER_UPLEFT_HTC</see> to complete upper O mouth shape.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_OVERTURN_HTC = 9,
|
||||
/// <summary>
|
||||
/// This blend shape pouts your lower lip. Can be used with <see cref="XrLipExpressionHTC.XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC">XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC</see> and <see cref="XrLipExpressionHTC.XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNRIGHT_HTC">XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNRIGHT_HTC</see> to complete upper O mouth shape.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_OVERTURN_HTC = 10,
|
||||
/// <summary>
|
||||
/// This blend shape allows the lips to pout more with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_POUT_HTC = 11,
|
||||
/// <summary>
|
||||
/// This blend shape raises the right side of the mouth further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_SMILE_RIGHT_HTC = 12,
|
||||
/// <summary>
|
||||
/// This blend shape raises the left side of the mouth further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_SMILE_LEFT_HTC = 13,
|
||||
/// <summary>
|
||||
/// This blend shape lowers the right side of the mouth further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_SAD_RIGHT_HTC = 14,
|
||||
/// <summary>
|
||||
/// This blend shape lowers the left side of the mouth further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_SAD_LEFT_HTC = 15,
|
||||
/// <summary>
|
||||
/// This blend shape puffs up the right side of the cheek further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_CHEEK_PUFF_RIGHT_HTC = 16,
|
||||
/// <summary>
|
||||
/// This blend shape puffs up the left side of the cheek further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_CHEEK_PUFF_LEFT_HTC = 17,
|
||||
/// <summary>
|
||||
/// This blend shape sucks in the cheeks on both sides further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_CHEEK_SUCK_HTC = 18,
|
||||
/// <summary>
|
||||
/// This blend shape raises the right upper lip further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC = 19,
|
||||
/// <summary>
|
||||
/// This blend shape raises the left upper lip further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_UPLEFT_HTC = 20,
|
||||
/// <summary>
|
||||
/// This blend shape lowers the right lower lip further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNRIGHT_HTC = 21,
|
||||
/// <summary>
|
||||
/// This blend shape lowers the left lower lip further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNLEFT_HTC = 22,
|
||||
/// <summary>
|
||||
/// This blend shape rolls in the upper lip further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_UPPER_INSIDE_HTC = 23,
|
||||
/// <summary>
|
||||
/// This blend shape rolls in the lower lip further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_INSIDE_HTC = 24,
|
||||
/// <summary>
|
||||
/// This blend shape stretches the lower lip further and lays it on the upper lip further with a higher value.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_MOUTH_LOWER_OVERLAY_HTC = 25,
|
||||
/// <summary>
|
||||
/// This blend shape sticks the tongue out slightly.
|
||||
///
|
||||
/// In step 1 of extending the tongue, the main action of the tongue is to lift up, and the elongated length only extends to a little bit beyond the teeth.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_LONGSTEP1_HTC = 26,
|
||||
/// <summary>
|
||||
/// This blend shape sticks the tongue out and left extremely.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_LEFT_HTC = 27,
|
||||
/// <summary>
|
||||
/// This blend shape sticks the tongue out and right extremely.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_RIGHT_HTC = 28,
|
||||
/// <summary>
|
||||
/// This blend shape sticks the tongue out and up extremely.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_UP_HTC = 29,
|
||||
/// <summary>
|
||||
/// This blend shape sticks the tongue out and down extremely.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_DOWN_HTC = 30,
|
||||
/// <summary>
|
||||
/// This blend shape sticks the tongue out with roll type.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_ROLL_HTC = 31,
|
||||
/// <summary>
|
||||
/// This blend shape sticks the tongue out extremely.
|
||||
///
|
||||
/// Continuing the step 1, it extends the tongue to the longest.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_LONGSTEP2_HTC = 32,
|
||||
/// <summary>
|
||||
/// This blend shape doesn’t make sense. When both the right and up blend shapes appear at the same time, the tongue will be deformed.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_UPRIGHT_MORPH_HTC = 33,
|
||||
/// <summary>
|
||||
/// This blend shape doesn’t make sense. When both the left and up blend shapes appear at the same time, the tongue will be deformed.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_UPLEFT_MORPH_HTC = 34,
|
||||
/// <summary>
|
||||
/// This blend shape doesn’t make sense. When both the right and down blend shapes appear at the same time, the tongue will be deformed.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_DOWNRIGHT_MORPH_HTC = 35,
|
||||
/// <summary>
|
||||
/// This blend shape doesn’t make sense. When both the left and down blend shapes appear at the same time, the tongue will be deformed.
|
||||
/// </summary>
|
||||
XR_LIP_EXPRESSION_TONGUE_DOWNLEFT_MORPH_HTC = 36,
|
||||
XR_LIP_EXPRESSION_MAX_ENUM_HTC = 37
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// An application can inspect whether the system is capable of two of the facial tracking by extending the <see cref="XrSystemProperties">XrSystemProperties</see> with <see cref="XrSystemFacialTrackingPropertiesHTC">XrSystemFacialTrackingPropertiesHTC</see> structure when calling <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystemProperties">xrGetSystemProperties</see>.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrSystemFacialTrackingPropertiesHTC
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="XrStructureType">XrStructureType</see> of this structure.
|
||||
/// </summary>
|
||||
public XrStructureType type;
|
||||
/// <summary>
|
||||
/// NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
|
||||
/// </summary>
|
||||
public IntPtr next;
|
||||
/// <summary>
|
||||
/// Indicates if the current system is capable of generating eye expressions.
|
||||
/// </summary>
|
||||
public XrBool32 supportEyeFacialTracking;
|
||||
/// <summary>
|
||||
/// Indicates if the current system is capable of generating lip expressions.
|
||||
/// </summary>
|
||||
public XrBool32 supportLipFacialTracking;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The XrFacialTrackerCreateInfoHTC structure describes the information to create an <see cref="XrFacialTrackerHTC">XrFacialTrackerHTC</see> handle.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrFacialTrackerCreateInfoHTC
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="XrStructureType">XrStructureType</see> of this structure.
|
||||
/// </summary>
|
||||
public XrStructureType type;
|
||||
/// <summary>
|
||||
/// NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
|
||||
/// </summary>
|
||||
public IntPtr next;
|
||||
/// <summary>
|
||||
/// An XrFacialTrackingTypeHTC which describes which type of facial tracking should be used for this handle.
|
||||
/// </summary>
|
||||
public XrFacialTrackingTypeHTC facialTrackingType;
|
||||
|
||||
/// <param name="in_type">The <see cref="XrStructureType">XrStructureType</see> of this structure.</param>
|
||||
/// <param name="in_next">NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.</param>
|
||||
/// <param name="in_facialTrackingType">An XrFacialTrackingTypeHTC which describes which type of facial tracking should be used for this handle.</param>
|
||||
public XrFacialTrackerCreateInfoHTC(XrStructureType in_type, IntPtr in_next, XrFacialTrackingTypeHTC in_facialTrackingType)
|
||||
{
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
facialTrackingType = in_facialTrackingType;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// XrFacialExpressionsHTC structure returns data of a lip facial expression or an eye facial expression.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrFacialExpressionsHTC
|
||||
{
|
||||
/// <summary>The XrStructureType of this structure.</summary>
|
||||
public XrStructureType type;
|
||||
/// <summary>NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.</summary>
|
||||
public IntPtr next;
|
||||
/// <summary>An XrBool32 indicating if the facial tracker is active.</summary>
|
||||
public XrBool32 isActive;
|
||||
/// <summary>When in time the expression is expressed.</summary>
|
||||
public XrTime sampleTime;
|
||||
/// <summary>A uint32_t describing the count of elements in expressionWeightings array.</summary>
|
||||
public UInt32 expressionCount;
|
||||
/// <summary>A float array filled in by the runtime, specifying the weightings for each blend shape.</summary>
|
||||
public IntPtr expressionWeightings;
|
||||
|
||||
/// <param name="in_type">The XrStructureType of this structure.</param>
|
||||
/// <param name="in_next">NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.</param>
|
||||
/// <param name="in_isActive">An XrBool32 indicating if the facial tracker is active.</param>
|
||||
/// <param name="in_sampleTime">When in time the expression is expressed.</param>
|
||||
/// <param name="in_expressionCount">>A uint32_t describing the count of elements in expressionWeightings array.</param>
|
||||
/// <param name="in_expressionWeightings">A float array filled in by the runtime, specifying the weightings for each blend shape.</param>
|
||||
public XrFacialExpressionsHTC(
|
||||
XrStructureType in_type,
|
||||
IntPtr in_next,
|
||||
XrBool32 in_isActive,
|
||||
XrTime in_sampleTime,
|
||||
UInt32 in_expressionCount,
|
||||
IntPtr in_expressionWeightings)
|
||||
{
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
isActive = in_isActive;
|
||||
sampleTime = in_sampleTime;
|
||||
expressionCount = in_expressionCount;
|
||||
expressionWeightings = in_expressionWeightings;
|
||||
}
|
||||
};
|
||||
|
||||
public static class ViveFacialTrackingHelper
|
||||
{
|
||||
/// <summary> The number of blend shapes in an expression of type <see cref="XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC">XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC</see>. </summary>
|
||||
public const UInt32 XR_FACIAL_EXPRESSION_EYE_COUNT_HTC = 14;
|
||||
/// <summary> The number of blend shapes in an expression of type <see cref="XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC">XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC.</see> </summary>
|
||||
public const UInt32 XR_FACIAL_EXPRESSION_LIP_COUNT_HTC = 37;
|
||||
|
||||
/// <summary>
|
||||
/// The delegate function of <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateFacialTrackerHTC">xrCreateFacialTrackerHTC</see>.
|
||||
/// </summary>
|
||||
/// <param name="session">An XrSession in which the facial expression will be active.</param>
|
||||
/// <param name="createInfo">The <see cref="XrFacialTrackerCreateInfoHTC">XrFacialTrackerCreateInfoHTC</see> used to specify the facial tracking type.</param>
|
||||
/// <param name="facialTracker">The returned <see cref="XrFacialTrackerHTC">XrFacialTrackerHTC</see> handle.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public delegate XrResult xrCreateFacialTrackerHTCDelegate(
|
||||
XrSession session,
|
||||
XrFacialTrackerCreateInfoHTC createInfo,
|
||||
out XrFacialTrackerHTC facialTracker);
|
||||
|
||||
/// <summary>
|
||||
/// The delegate function of <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroyFacialTrackerHTC">xrDestroyFacialTrackerHTC</see>.
|
||||
/// </summary>
|
||||
/// <param name="facialTracker">An XrFacialTrackerHTC previously created by xrCreateFacialTrackerHTC.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public delegate XrResult xrDestroyFacialTrackerHTCDelegate(
|
||||
XrFacialTrackerHTC facialTracker);
|
||||
|
||||
/// <summary>
|
||||
/// The delegate function of <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetFacialExpressionsHTC">xrGetFacialExpressionsHTC</see>.
|
||||
/// </summary>
|
||||
/// <param name="facialTracker">An <see cref="XrFacialTrackerHTC">XrFacialTrackerHTC</see> previously created by <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateFacialTrackerHTC">xrCreateFacialTrackerHTC</see>.</param>
|
||||
/// <param name="facialExpressions">A pointer to <see cref="XrFacialExpressionsHTC">XrFacialExpressionsHTC</see> receiving the returned facial expressions.</param>
|
||||
/// <returns></returns>
|
||||
public delegate XrResult xrGetFacialExpressionsHTCDelegate(
|
||||
XrFacialTrackerHTC facialTracker,
|
||||
ref XrFacialExpressionsHTC facialExpressions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ff2614ff91df1649bef349243f26eff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
com.htc.upm.vive.openxr/Runtime/Features/Foveation.meta
Normal file
8
com.htc.upm.vive.openxr/Runtime/Features/Foveation.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ea80802b9699ba4099f42a28dafe7f9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7668e041703aef84793af8e9ed989023
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,44 @@
|
||||
# 12.70. XR_HTC_vive_wrist_tracker_interaction
|
||||
## Name String
|
||||
XR_HTC_vive_wrist_tracker_interaction
|
||||
## Revision
|
||||
1
|
||||
## VIVE Wrist Tracker input
|
||||
### Interaction profile path:
|
||||
- /interaction_profiles/htc/vive_wrist_tracker
|
||||
|
||||
### Valid for user paths:
|
||||
- /user/wrist_htc/left
|
||||
- /user/wrist_htc/right
|
||||
|
||||
### Supported input source
|
||||
- On /user/wrist_htc/left only:
|
||||
- <20>K/input/menu/click
|
||||
- <20>K/input/x/click
|
||||
- On /user/wrist_htc/right only:
|
||||
- <20>K/input/system/click (may not be available for application use)
|
||||
- <20>K/input/a/click
|
||||
- <20>K/input/entity_htc/pose
|
||||
|
||||
The entity_htc pose allows the applications to recognize the origin of a tracked input device, especially for the wearable devices which are not held in the user<65><72>s hand. The entity_htc pose is defined as follows:
|
||||
|
||||
- The entity position: The center position of the tracked device.
|
||||
- The entity orientation: Oriented with +Y up, +X to the right, and -Z forward.
|
||||
|
||||
## VIVE Plugin
|
||||
|
||||
After adding the "VIVE Focus3 Wrist Tracker" to "Project Settings > XR Plugin-in Management > OpenXR > Android Tab > Interaction Profiles", you can use the following Input Action Pathes.
|
||||
|
||||
### Left Hand
|
||||
- <ViveWristTracker>{LeftHand}/primaryButton: Left tracker primary button pressed state.
|
||||
- <ViveWristTracker>{LeftHand}/menu: Left tracker menu button pressed state.
|
||||
- <ViveWristTracker>{LeftHand}/devicePose: Left tracker pose.
|
||||
- <ViveWristTracker>{LeftHand}/devicePose/isTracked: Left tracker tracking state.
|
||||
|
||||
### Right Hand
|
||||
- <ViveWristTracker>{RightHand}/primaryButton: Right tracker primary button pressed state.
|
||||
- <ViveWristTracker>{RightHand}/menu: Right tracker menu button pressed state.
|
||||
- <ViveWristTracker>{RightHand}/devicePose: Right tracker pose.
|
||||
- <ViveWristTracker>{RightHand}/devicePose/isTracked: Right tracker tracking state.
|
||||
|
||||
Refer to the <VIVE OpenXR sample path>/Plugin/Input/ActionMap/InputActions.inputActions about the "Input Action Path" usage and the sample <VIVE OpenXR sample path>/Plugin/Input/OpenXRInput.unity.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c68233f6b41d7145b07de86f5d16638
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 771c0636a727c9742971602d5da26011
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Foveation",
|
||||
Desc = "Support the HTC foveation extension.",
|
||||
Company = "HTC",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = "XR_HTC_foveation",
|
||||
Version = "1.0.0",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class ViveFoveation : OpenXRFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// Flag bits for XrFoveationDynamicFlagsHTC
|
||||
/// </summary>
|
||||
public const UInt64 XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_BIT_HTC = 0x00000001;
|
||||
public const UInt64 XR_FOVEATION_DYNAMIC_CLEAR_FOV_ENABLED_BIT_HTC = 0x00000002;
|
||||
public const UInt64 XR_FOVEATION_DYNAMIC_FOCAL_CENTER_OFFSET_ENABLED_BIT_HTC = 0x00000004;
|
||||
|
||||
/// <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.foveation";
|
||||
|
||||
protected override IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
{
|
||||
Debug.Log("EXT: registering our own xrGetInstanceProcAddr");
|
||||
if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Vulkan)
|
||||
{
|
||||
Debug.Log("Vulkan no hook foveation");
|
||||
return func;
|
||||
}
|
||||
return intercept_xrGetInstanceProcAddr(func);
|
||||
}
|
||||
|
||||
private const string ExtLib = "viveopenxr";
|
||||
[DllImport(ExtLib, EntryPoint = "intercept_xrGetInstanceProcAddr")]
|
||||
private static extern IntPtr intercept_xrGetInstanceProcAddr(IntPtr func);
|
||||
|
||||
[DllImport(ExtLib, EntryPoint = "applyFoveationHTC")]
|
||||
private static extern XrResult applyFoveationHTC(XrFoveationModeHTC mode, UInt32 configCount, XrFoveationConfigurationHTC[] configs, UInt64 flags);
|
||||
|
||||
/// <summary>
|
||||
/// function to apply HTC Foveation
|
||||
/// </summary>
|
||||
public static XrResult ApplyFoveationHTC(XrFoveationModeHTC mode, UInt32 configCount, XrFoveationConfigurationHTC[] configs, UInt64 flags = 0)
|
||||
{
|
||||
//Debug.Log("Unity HTCFoveat:configCount " + configCount);
|
||||
//if (configCount >=2) {
|
||||
//Debug.Log("Unity HTCFoveat:configs[0].clearFovDegree " + configs[0].clearFovDegree);
|
||||
//Debug.Log("Unity HTCFoveat:configs[0].level " + configs[0].level);
|
||||
//Debug.Log("Unity HTCFoveat:configs[1].clearFovDegree " + configs[1].clearFovDegree);
|
||||
//Debug.Log("Unity HTCFoveat:configs[1].level " + configs[1].level);
|
||||
//}
|
||||
return applyFoveationHTC(mode, configCount, configs, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17b6a897c202288439905d3efb0e006f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
com.htc.upm.vive.openxr/Runtime/Features/Hand.meta
Normal file
8
com.htc.upm.vive.openxr/Runtime/Features/Hand.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d77b72e71f09834b8a271fafab43127
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e96f290ae08cd3642932e5fd10d142e8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 771c4b3ec0a607546b6188ee58213b92
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
# 12.67 XR_HTC_hand_interaction
|
||||
## Name String
|
||||
XR_HTC_hand_interaction
|
||||
## Revision
|
||||
1
|
||||
## Hand Interaction Profile
|
||||
### Interaction profile path:
|
||||
- /interaction_profiles/htc/hand_interaction
|
||||
|
||||
### Valid for user paths:
|
||||
- /user/hand_htc/left
|
||||
- /user/hand_htc/right
|
||||
|
||||
### Supported input source
|
||||
- <20>K/input/select/value
|
||||
- <20>K/input/aim/pose
|
||||
|
||||
The application should use <20>K/input/aim/pose path to aim at objects in the world and use <20>K/input/select/value path to decide user selection from pinch shape strength which the range of value is 0.0f to 1.0f, with 1.0f meaning pinch fingers touched.
|
||||
|
||||
## VIVE Plugin
|
||||
|
||||
After adding the "VIVE Focus3 Hand Interaction" to "Project Settings > XR Plugin-in Management > OpenXR > Android Tab > Interaction Profiles", you can use the following Input Action Pathes.
|
||||
|
||||
### Left Hand
|
||||
- <ViveHandInteraction>{LeftHand}/selectValue: Presents the left hand pinch strength.
|
||||
- <ViveHandInteraction>{LeftHand}/pointerPose: Presents the left hand pinch pose.
|
||||
|
||||
### Right Hand
|
||||
- <ViveHandInteraction>{RightHand}/selectValue: Presents the right hand pinch strength.
|
||||
- <ViveHandInteraction>{RightHand}/pointerPose: Presents the right hand pinch pose.
|
||||
|
||||
Refer to the <VIVE OpenXR sample path>/Plugin/Input/ActionMap/InputActions.inputActions about the "Input Action Path" usage and the sample <VIVE OpenXR sample path>/Plugin/Input/OpenXRInput.unity.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1983ec0f3f6f1841b9824ef68235039
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8626a4ae9aacf7d41b32411a6e5a04f9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,342 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using UnityEngine.Scripting;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
using System.Text;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
|
||||
using PoseControl = UnityEngine.InputSystem.XR.PoseControl;
|
||||
#else
|
||||
using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.Hand
|
||||
{
|
||||
/// <summary>
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of hand interaction profiles in OpenXR. It enables <see cref="ViveHandInteraction.kOpenxrExtensionString">XR_HTC_hand_interaction</see> in the underyling runtime.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Hand Interaction",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android , BuildTargetGroup.Standalone},
|
||||
Company = "HTC",
|
||||
Desc = "Support for enabling the hand interaction profile. Will register the controller map for hand interaction if enabled.",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
Version = "1.0.0",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionString,
|
||||
Category = FeatureCategory.Interaction,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class ViveHandInteraction : OpenXRInteractionFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.Hand.ViveHandInteraction ";
|
||||
StringBuilder m_sb = null;
|
||||
StringBuilder sb {
|
||||
get {
|
||||
if (m_sb == null) { m_sb = new StringBuilder(); }
|
||||
return m_sb;
|
||||
}
|
||||
}
|
||||
void DEBUG(StringBuilder msg) { Debug.Log(msg); }
|
||||
void WARNING(StringBuilder msg) { Debug.LogWarning(msg); }
|
||||
|
||||
/// <summary>
|
||||
/// OpenXR specification <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_hand_interaction">12.69. XR_HTC_hand_interaction</see>.
|
||||
/// </summary>
|
||||
public const string kOpenxrExtensionString = "XR_HTC_hand_interaction";
|
||||
|
||||
/// <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.hand.interaction";
|
||||
|
||||
/// <summary>
|
||||
/// The interaction profile string used to reference the hand interaction input device.
|
||||
/// </summary>
|
||||
private const string profile = "/interaction_profiles/htc/hand_interaction";
|
||||
|
||||
private const string leftHand = "/user/hand_htc/left";
|
||||
private const string rightHand = "/user/hand_htc/right";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/select/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string selectValue = "/input/select/value";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/squeeze/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string gripValue = "/input/squeeze/value";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/aim/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
private const string pointerPose = "/input/aim/pose";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string devicePose = "/input/grip/pose";
|
||||
|
||||
|
||||
[Preserve, InputControlLayout(displayName = "Vive Hand Interaction (OpenXR)", commonUsages = new[] { "LeftHand", "RightHand" }, isGenericTypeOfDevice = true)]
|
||||
public class HandInteractionDevice : OpenXRDevice
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.Hand.ViveHandInteraction.HandInteractionDevice";
|
||||
void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <summary>
|
||||
/// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="ViveHandInteraction.selectValue"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "selectAxis, pinchStrength" }, usage = "Select")]
|
||||
public AxisControl selectValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="AxisControl"/> representing information from the <see cref="ViveHandInteraction.squeeze"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripAxis" }, usage = "Grip")]
|
||||
public AxisControl gripValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing information from the <see cref="ViveHandInteraction.devicePose"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing the <see cref="ViveHandInteraction.pointerPose"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "aimPose", usage = "Pointer")]
|
||||
public PoseControl pointerPose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 8, usage = "IsTracked")]
|
||||
public ButtonControl isTracked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [IntegerControl](xref:UnityEngine.InputSystem.Controls.IntegerControl) required for backwards compatibility with the XRSDK layouts. This represents the bit flag set to indicate what data is valid. This value is equivalent to mapping devicePose/trackingState.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 12, usage = "TrackingState")]
|
||||
public IntegerControl trackingState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the device position. For the VIVE Focus 3 device, this is both the device and the pointer position. This value is equivalent to mapping devicePose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 16, alias = "gripPosition")]
|
||||
public Vector3Control devicePosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the device orientation. For the VIVE Focus 3 device, this is both the device and the pointer rotation. This value is equivalent to mapping devicePose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 28, alias = "gripOrientation")]
|
||||
public QuaternionControl deviceRotation { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Internal call used to assign controls to the the correct element.
|
||||
/// </summary>
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
DEBUG("FinishSetup() interfaceName: " + description.interfaceName
|
||||
+ ", deviceClass: " + description.deviceClass
|
||||
+ ", product: " + description.product
|
||||
+ ", serial: " + description.serial
|
||||
+ ", version: " + description.version);
|
||||
|
||||
base.FinishSetup();
|
||||
|
||||
selectValue = GetChildControl<AxisControl>("selectValue");
|
||||
gripValue = GetChildControl<AxisControl>("gripValue");
|
||||
|
||||
devicePose = GetChildControl<PoseControl>("devicePose");
|
||||
pointerPose = GetChildControl<PoseControl>("pointerPose");
|
||||
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
devicePosition = GetChildControl<Vector3Control>("devicePosition");
|
||||
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable
|
||||
private bool m_XrInstanceCreated = false;
|
||||
#pragma warning restore
|
||||
private XrInstance m_XrInstance = 0;
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateInstance">xrCreateInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The created instance.</param>
|
||||
/// <returns>True for valid <see cref="XrInstance">XrInstance</see></returns>
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
// Requires the eye tracking extension
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
{
|
||||
sb.Clear().Append(LOG_TAG).Append("OnInstanceCreate() ").Append(kOpenxrExtensionString).Append(" is NOT enabled."); WARNING(sb);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_XrInstanceCreated = true;
|
||||
m_XrInstance = xrInstance;
|
||||
sb.Clear().Append(LOG_TAG).Append("OnInstanceCreate() " + m_XrInstance); DEBUG(sb);
|
||||
|
||||
return base.OnInstanceCreate(xrInstance);
|
||||
}
|
||||
|
||||
private const string kLayoutName = "ViveHandInteraction";
|
||||
private const string kDeviceLocalizedName = "Vive Hand Interaction OpenXR";
|
||||
/// <summary>
|
||||
/// Registers the <see cref="HandInteractionDevice"/> layout with the Input System.
|
||||
/// </summary>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
sb.Clear().Append(LOG_TAG).Append("RegisterDeviceLayout() Layout: ").Append(kLayoutName)
|
||||
.Append(", Product: ").Append(kDeviceLocalizedName);
|
||||
DEBUG(sb);
|
||||
InputSystem.RegisterLayout(typeof(HandInteractionDevice),
|
||||
kLayoutName,
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
||||
.WithProduct(kDeviceLocalizedName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the <see cref="HandInteractionDevice"/> layout from the Input System.
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
sb.Clear().Append(LOG_TAG).Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
InputSystem.RemoveLayout(kLayoutName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers action maps to Unity XR.
|
||||
/// </summary>
|
||||
protected override void RegisterActionMapsWithRuntime()
|
||||
{
|
||||
sb.Clear().Append(LOG_TAG).Append("RegisterActionMapsWithRuntime() Action map vivehandinteraction")
|
||||
.Append(", localizedName: ").Append(kDeviceLocalizedName)
|
||||
.Append(", desiredInteractionProfile").Append(profile);
|
||||
DEBUG(sb);
|
||||
|
||||
ActionMapConfig actionMap = new ActionMapConfig()
|
||||
{
|
||||
name = "vivehandinteraction",
|
||||
localizedName = kDeviceLocalizedName,
|
||||
desiredInteractionProfile = profile,
|
||||
manufacturer = "HTC",
|
||||
serialNumber = "",
|
||||
deviceInfos = new List<DeviceConfig>()
|
||||
{
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.HandTracking | InputDeviceCharacteristics.Left,
|
||||
userPath = leftHand // "/user/hand_htc/left"
|
||||
},
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.HandTracking | InputDeviceCharacteristics.Right,
|
||||
userPath = rightHand // "/user/hand_htc/right"
|
||||
}
|
||||
},
|
||||
actions = new List<ActionConfig>()
|
||||
{
|
||||
// Grip Axis
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "gripValue",
|
||||
localizedName = "Grip Axis",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Grip"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = gripValue,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select Axis
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "selectValue",
|
||||
localizedName = "Select Axis",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Select"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = selectValue,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Grip pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "devicePose",
|
||||
localizedName = "Device Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Device"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = devicePose,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Pointer Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "pointerPose",
|
||||
localizedName = "Pointer Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Pointer"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = pointerPose,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AddActionMap(actionMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec058e82c4fd831488e0fe81bb41d440
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c20ac17e6a9698a4ab9e7ac290153915
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3276899460ff6249b597e331d84b121
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
# 12.28 XR_EXT_hand_tracking
|
||||
## Name String
|
||||
XR_EXT_hand_tracking
|
||||
## Revision
|
||||
4
|
||||
## New Object Types
|
||||
- [XrHandTrackerEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandTrackerEXT)
|
||||
## New Enum Constants
|
||||
- [XR_HAND_JOINT_COUNT_EXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_HAND_JOINT_COUNT_EXT)
|
||||
[XrObjectType](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrObjectType) enumeration is extended with:
|
||||
- XR_OBJECT_TYPE_HAND_TRACKER_EXT
|
||||
[XrStructureType](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrStructureType) enumeration is extended with:
|
||||
- XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT
|
||||
- XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT
|
||||
- XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT
|
||||
- XR_TYPE_HAND_JOINT_LOCATIONS_EXT
|
||||
- XR_TYPE_HAND_JOINT_VELOCITIES_EXT
|
||||
## New Enums
|
||||
- [XrHandEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandEXT)
|
||||
- [XrHandJointEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandJointEXT)
|
||||
- [XrHandJointSetEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandJointSetEXT)
|
||||
## New Structures
|
||||
- [XrSystemHandTrackingPropertiesEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrSystemHandTrackingPropertiesEXT)
|
||||
- [XrHandTrackerCreateInfoEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandTrackerCreateInfoEXT)
|
||||
- [XrHandJointsLocateInfoEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandJointsLocateInfoEXT)
|
||||
- [XrHandJointLocationEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandJointLocationEXT)
|
||||
- [XrHandJointVelocityEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandJointVelocityEXT)
|
||||
- [XrHandJointLocationsEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandJointLocationsEXT)
|
||||
- [XrHandJointVelocitiesEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandJointVelocitiesEXT)
|
||||
## New Functions
|
||||
- [xrCreateHandTrackerEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#xrCreateHandTrackerEXT)
|
||||
- [xrDestroyHandTrackerEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#xrDestroyHandTrackerEXT)
|
||||
- [xrLocateHandJointsEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#xrLocateHandJointsEXT)
|
||||
|
||||
## VIVE Plugin
|
||||
|
||||
After enabling the "VIVE Focus3 Hand Tracking" from "Project Settings > XR Plugin-in Management > OpenXR > Android Tab", you can retrieve the [XrHandJointLocationEXT](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XrHandJointLocationEXT) by using the following code.
|
||||
|
||||
using VIVE.OpenXR.Hand;
|
||||
|
||||
XrHandJointLocationEXT[] HandjointLocations = new XrHandJointLocationEXT[(int)XrHandJointEXT.XR_HAND_JOINT_MAX_ENUM_EXT];
|
||||
var feature = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
if (feature && feature.GetJointLocations(isLeft, out HandjointLocations))
|
||||
{
|
||||
// now you have the hand joint data
|
||||
}
|
||||
|
||||
Refer to <VIVE OpenXR sample path>/Plugin/Input/Scripts/VIVE/RenderHand.cs about the sample code.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05f3bff8b2a4d0a4ea96ffedf619e30c
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9ee0f2aa88738b47ab943ec3a3b52a7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,820 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine;
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine.XR;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.Hand
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Hand Tracking",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android , BuildTargetGroup.Standalone },
|
||||
Company = "HTC",
|
||||
Desc = "Support the Hand Tracking extension.",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionString,
|
||||
Version = "4.0.0",
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class ViveHandTracking : OpenXRFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.Hand.ViveHandTracking";
|
||||
void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <summary>
|
||||
/// OpenXR specification <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_EXT_hand_tracking">12.29 XR_EXT_hand_tracking</see>.
|
||||
/// </summary>
|
||||
public const string kOpenxrExtensionString = "XR_EXT_hand_tracking";
|
||||
/// <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.hand.tracking";
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
private bool m_XrInstanceCreated = false;
|
||||
private XrInstance m_XrInstance = 0;
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateInstance">xrCreateInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The created instance.</param>
|
||||
/// <returns>True for valid <see cref="XrInstance">XrInstance</see></returns>
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
{
|
||||
WARNING("OnInstanceCreate() " + kOpenxrExtensionString + " is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_XrInstanceCreated = true;
|
||||
m_XrInstance = xrInstance;
|
||||
DEBUG("OnInstanceCreate() " + m_XrInstance);
|
||||
|
||||
return GetXrFunctionDelegates(m_XrInstance);
|
||||
}
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroyInstance">xrDestroyInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The instance to destroy.</param>
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
m_XrInstanceCreated = false;
|
||||
m_XrInstance = 0;
|
||||
DEBUG("OnInstanceDestroy() " + xrInstance);
|
||||
}
|
||||
|
||||
private XrSystemId m_XrSystemId = 0;
|
||||
/// <summary>
|
||||
/// Called when the <see cref="XrSystemId">XrSystemId</see> retrieved by <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystem">xrGetSystem</see> is changed.
|
||||
/// </summary>
|
||||
/// <param name="xrSystem">The system id.</param>
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
m_XrSystemId = xrSystem;
|
||||
DEBUG("OnSystemChange() " + m_XrSystemId);
|
||||
}
|
||||
|
||||
private bool m_XrSessionCreated = false;
|
||||
private XrSession m_XrSession = 0;
|
||||
private bool hasReferenceSpaceLocal = false, hasReferenceSpaceStage = false;
|
||||
private XrSpace m_ReferenceSpaceLocal = 0, m_ReferenceSpaceStage = 0;
|
||||
|
||||
private bool hasLeftHandTracker = false, hasRightHandTracker = false;
|
||||
private XrHandTrackerEXT leftHandTracker = 0, rightHandTracker = 0;
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateSession">xrCreateSession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The created session ID.</param>
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
m_XrSession = xrSession;
|
||||
m_XrSessionCreated = true;
|
||||
DEBUG("OnSessionCreate() " + m_XrSession);
|
||||
|
||||
// Enumerate supported reference space types and create the XrSpace.
|
||||
XrReferenceSpaceType[] spaces = new XrReferenceSpaceType[Enum.GetNames(typeof(XrReferenceSpaceType)).Count()];
|
||||
UInt32 spaceCountOutput;
|
||||
#pragma warning disable 0618
|
||||
if (EnumerateReferenceSpaces(
|
||||
spaceCapacityInput: 0,
|
||||
spaceCountOutput: out spaceCountOutput,
|
||||
spaces: out spaces[0]) == XrResult.XR_SUCCESS)
|
||||
#pragma warning restore 0618
|
||||
{
|
||||
DEBUG("OnSessionCreate() spaceCountOutput: " + spaceCountOutput);
|
||||
|
||||
Array.Resize(ref spaces, (int)spaceCountOutput);
|
||||
#pragma warning disable 0618
|
||||
if (EnumerateReferenceSpaces(
|
||||
spaceCapacityInput: spaceCountOutput,
|
||||
spaceCountOutput: out spaceCountOutput,
|
||||
spaces: out spaces[0]) == XrResult.XR_SUCCESS)
|
||||
#pragma warning restore 0618
|
||||
{
|
||||
XrReferenceSpaceCreateInfo createInfo;
|
||||
|
||||
/// Create m_ReferenceSpaceLocal
|
||||
if (IsReferenceSpaceTypeSupported(spaceCountOutput, spaces, XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_LOCAL))
|
||||
{
|
||||
createInfo.type = XrStructureType.XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
createInfo.next = IntPtr.Zero;
|
||||
createInfo.referenceSpaceType = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_LOCAL;//referenceSpaceType;
|
||||
createInfo.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1);
|
||||
createInfo.poseInReferenceSpace.position = new XrVector3f(0, 0, 0);
|
||||
|
||||
#pragma warning disable 0618
|
||||
if (CreateReferenceSpace(
|
||||
createInfo: ref createInfo,
|
||||
space: out m_ReferenceSpaceLocal) == XrResult.XR_SUCCESS)
|
||||
#pragma warning restore 0618
|
||||
{
|
||||
hasReferenceSpaceLocal = true;
|
||||
DEBUG("OnSessionCreate() CreateReferenceSpace LOCAL: " + m_ReferenceSpaceLocal);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("OnSessionCreate() CreateReferenceSpace LOCAL failed.");
|
||||
}
|
||||
}
|
||||
|
||||
/// Create m_ReferenceSpaceStage
|
||||
if (IsReferenceSpaceTypeSupported(spaceCountOutput, spaces, XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_STAGE))
|
||||
{
|
||||
createInfo.type = XrStructureType.XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
createInfo.next = IntPtr.Zero;
|
||||
createInfo.referenceSpaceType = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_STAGE;
|
||||
createInfo.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1);
|
||||
createInfo.poseInReferenceSpace.position = new XrVector3f(0, 0, 0);
|
||||
|
||||
#pragma warning disable 0618
|
||||
if (CreateReferenceSpace(
|
||||
createInfo: ref createInfo,
|
||||
space: out m_ReferenceSpaceStage) == XrResult.XR_SUCCESS)
|
||||
#pragma warning restore 0618
|
||||
{
|
||||
hasReferenceSpaceStage = true;
|
||||
DEBUG("OnSessionCreate() CreateReferenceSpace STAGE: " + m_ReferenceSpaceStage);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("OnSessionCreate() CreateReferenceSpace STAGE failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("OnSessionCreate() EnumerateReferenceSpaces(" + spaceCountOutput + ") failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("OnSessionCreate() EnumerateReferenceSpaces(0) failed.");
|
||||
}
|
||||
|
||||
{ // left hand tracker
|
||||
if (CreateHandTrackers(true, out XrHandTrackerEXT value))
|
||||
{
|
||||
hasLeftHandTracker = true;
|
||||
leftHandTracker = value;
|
||||
DEBUG("OnSessionCreate() leftHandTracker " + leftHandTracker);
|
||||
}
|
||||
}
|
||||
{ // right hand tracker
|
||||
if (CreateHandTrackers(false, out XrHandTrackerEXT value))
|
||||
{
|
||||
hasRightHandTracker = true;
|
||||
rightHandTracker = value;
|
||||
DEBUG("OnSessionCreate() rightHandTracker " + rightHandTracker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroySession">xrDestroySession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The session ID to destroy.</param>
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
DEBUG("OnSessionDestroy() " + xrSession);
|
||||
|
||||
// Reference Space is binding with xrSession so we destroy the xrSpace when xrSession is destroyed.
|
||||
if (hasReferenceSpaceLocal)
|
||||
{
|
||||
#pragma warning disable 0618
|
||||
if (DestroySpace(m_ReferenceSpaceLocal) == XrResult.XR_SUCCESS)
|
||||
#pragma warning restore 0618
|
||||
{
|
||||
DEBUG("OnSessionDestroy() DestroySpace LOCAL " + m_ReferenceSpaceLocal);
|
||||
m_ReferenceSpaceLocal = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("OnSessionDestroy() DestroySpace LOCAL " + m_ReferenceSpaceLocal + " failed.");
|
||||
}
|
||||
hasReferenceSpaceLocal = false;
|
||||
}
|
||||
if (hasReferenceSpaceStage)
|
||||
{
|
||||
#pragma warning disable 0618
|
||||
if (DestroySpace(m_ReferenceSpaceStage) == XrResult.XR_SUCCESS)
|
||||
#pragma warning restore 0618
|
||||
{
|
||||
DEBUG("OnSessionDestroy() DestroySpace STAGE " + m_ReferenceSpaceStage);
|
||||
m_ReferenceSpaceStage = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("OnSessionDestroy() DestroySpace STAGE " + m_ReferenceSpaceStage + " failed.");
|
||||
}
|
||||
hasReferenceSpaceStage = false;
|
||||
}
|
||||
|
||||
// Hand Tracking is binding with xrSession so we destroy the hand trackers when xrSession is destroyed.
|
||||
if (hasLeftHandTracker)
|
||||
{
|
||||
if (DestroyHandTrackerEXT(leftHandTracker) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
DEBUG("OnSessionDestroy() Left DestroyHandTrackerEXT " + leftHandTracker);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("OnSessionDestroy() Left DestroyHandTrackerEXT " + leftHandTracker + " failed.");
|
||||
}
|
||||
hasLeftHandTracker = false;
|
||||
}
|
||||
if (hasRightHandTracker)
|
||||
{
|
||||
if (DestroyHandTrackerEXT(rightHandTracker) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
DEBUG("OnSessionDestroy() Right DestroyHandTrackerEXT " + rightHandTracker);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("OnSessionDestroy() Right DestroyHandTrackerEXT " + rightHandTracker + " failed.");
|
||||
}
|
||||
hasRightHandTracker = false;
|
||||
}
|
||||
|
||||
m_XrSession = 0;
|
||||
m_XrSessionCreated = false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OpenXR function delegates
|
||||
/// xrGetInstanceProcAddr
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr;
|
||||
|
||||
/// xrGetSystemProperties
|
||||
OpenXRHelper.xrGetSystemPropertiesDelegate xrGetSystemProperties;
|
||||
/// <summary>
|
||||
/// An application can call GetSystemProperties to retrieve information about the system such as vendor ID, system name, and graphics and tracking properties.
|
||||
/// </summary>
|
||||
/// <param name="properties">Points to an instance of the XrSystemProperties structure, that will be filled with returned information.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
[Obsolete("This function will become private in next release")]
|
||||
public XrResult GetSystemProperties(ref XrSystemProperties properties)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("GetSystemProperties() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("GetSystemProperties() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrGetSystemProperties(m_XrInstance, m_XrSystemId, ref properties);
|
||||
}
|
||||
|
||||
/// xrEnumerateReferenceSpaces
|
||||
OpenXRHelper.xrEnumerateReferenceSpacesDelegate xrEnumerateReferenceSpaces;
|
||||
/// <summary>
|
||||
/// Enumerates the set of reference space types that this runtime supports for a given session. Runtimes must always return identical buffer contents from this enumeration for the lifetime of the session.
|
||||
/// </summary>
|
||||
/// <param name="spaceCapacityInput">The capacity of the spaces array, or 0 to indicate a request to retrieve the required capacity.</param>
|
||||
/// <param name="spaceCountOutput">A pointer to the count of spaces written, or a pointer to the required capacity in the case that spaceCapacityInput is insufficient.</param>
|
||||
/// <param name="spaces">A pointer to an application-allocated array that will be filled with the enumerant of each supported reference space. It can be NULL if spaceCapacityInput is 0.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
[Obsolete("This function will become private in next release")]
|
||||
public XrResult EnumerateReferenceSpaces(UInt32 spaceCapacityInput, out UInt32 spaceCountOutput, out XrReferenceSpaceType spaces)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("EnumerateReferenceSpaces() XR_ERROR_SESSION_LOST.");
|
||||
spaceCountOutput = 0;
|
||||
spaces = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT;
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("EnumerateReferenceSpaces() XR_ERROR_SESSION_LOST.");
|
||||
spaceCountOutput = 0;
|
||||
spaces = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT;
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrEnumerateReferenceSpaces(m_XrSession, spaceCapacityInput, out spaceCountOutput, out spaces);
|
||||
}
|
||||
|
||||
/// xrCreateReferenceSpace
|
||||
OpenXRHelper.xrCreateReferenceSpaceDelegate xrCreateReferenceSpace;
|
||||
/// <summary>
|
||||
/// Creates an <see cref="XrSpace">XrSpace</see> handle based on a chosen reference space. Application can provide an <see cref="XrPosef">XrPosef</see> to define the position and orientation of the new space’s origin within the natural reference frame of the reference space.
|
||||
/// </summary>
|
||||
/// <param name="createInfo">The XrReferenceSpaceCreateInfo used to specify the space.</param>
|
||||
/// <param name="space">The returned XrSpace handle.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
[Obsolete("This function will become private in next release")]
|
||||
public XrResult CreateReferenceSpace(ref XrReferenceSpaceCreateInfo createInfo, out XrSpace space)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("CreateReferenceSpace() XR_ERROR_SESSION_LOST.");
|
||||
space = 0;
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("CreateReferenceSpace() XR_ERROR_INSTANCE_LOST.");
|
||||
space = 0;
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrCreateReferenceSpace(m_XrSession, ref createInfo, out space);
|
||||
}
|
||||
|
||||
/// xrDestroySpace
|
||||
OpenXRHelper.xrDestroySpaceDelegate xrDestroySpace;
|
||||
/// <summary>
|
||||
/// <see cref="XrSpace">XrSpace</see> handles are destroyed using DestroySpace. The runtime may still use this space if there are active dependencies (e.g, compositions in progress).
|
||||
/// </summary>
|
||||
/// <param name="space">Must be a valid XrSpace handle.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
[Obsolete("This function will become private in next release")]
|
||||
public XrResult DestroySpace(XrSpace space)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("DestroySpace() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("DestroySpace() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrDestroySpace(space);
|
||||
}
|
||||
|
||||
/// xrCreateHandTrackerEXT
|
||||
ViveHandTrackingHelper.xrCreateHandTrackerEXTDelegate xrCreateHandTrackerEXT;
|
||||
/// <summary>
|
||||
/// An application can create an <see cref="XrHandTrackerEXT">XrHandTrackerEXT</see> handle using CreateHandTrackerEXT function.
|
||||
/// </summary>
|
||||
/// <param name="createInfo">The XrHandTrackerCreateInfoEXT used to specify the hand tracker.</param>
|
||||
/// <param name="handTracker">The returned XrHandTrackerEXT handle.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public XrResult CreateHandTrackerEXT(ref XrHandTrackerCreateInfoEXT createInfo, out XrHandTrackerEXT handTracker)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("CreateHandTrackerEXT() XR_ERROR_SESSION_LOST.");
|
||||
handTracker = 0;
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("CreateHandTrackerEXT() XR_ERROR_INSTANCE_LOST.");
|
||||
handTracker = 0;
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
if (createInfo.hand == XrHandEXT.XR_HAND_LEFT_EXT && hasLeftHandTracker)
|
||||
{
|
||||
DEBUG("CreateHandTrackerEXT() Left tracker " + leftHandTracker + " already created.");
|
||||
handTracker = leftHandTracker;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
if (createInfo.hand == XrHandEXT.XR_HAND_RIGHT_EXT && hasRightHandTracker)
|
||||
{
|
||||
DEBUG("CreateHandTrackerEXT() Right tracker " + rightHandTracker + " already created.");
|
||||
handTracker = rightHandTracker;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
return xrCreateHandTrackerEXT(m_XrSession, ref createInfo, out handTracker);
|
||||
}
|
||||
|
||||
/// xrDestroyHandTrackerEXT
|
||||
ViveHandTrackingHelper.xrDestroyHandTrackerEXTDelegate xrDestroyHandTrackerEXT;
|
||||
/// <summary>
|
||||
/// Releases the handTracker and the underlying resources when finished with hand tracking experiences.
|
||||
/// </summary>
|
||||
/// <param name="handTracker">An XrHandTrackerEXT previously created by <see cref="CreateHandTrackerEXT">CreateHandTrackerEXT</see>.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public XrResult DestroyHandTrackerEXT(XrHandTrackerEXT handTracker)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("DestroyHandTrackerEXT() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("DestroyHandTrackerEXT() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrDestroyHandTrackerEXT(handTracker);
|
||||
}
|
||||
|
||||
/// xrLocateHandJointsEXT
|
||||
ViveHandTrackingHelper.xrLocateHandJointsEXTDelegate xrLocateHandJointsEXT;
|
||||
/// <summary>
|
||||
/// The LocateHandJointsEXT function locates an array of hand joints to a base space at given time.
|
||||
/// </summary>
|
||||
/// <param name="handTracker">An <see cref="XrHandTrackerEXT">XrHandTrackerEXT</see> previously created by <see cref="ViveHandTracking.CreateHandTrackerEXT(ref XrHandTrackerCreateInfoEXT, out XrHandTrackerEXT)">CreateHandTrackerEXT</see>.</param>
|
||||
/// <param name="locateInfo">A pointer to <see cref="XrHandJointsLocateInfoEXT">XrHandJointsLocateInfoEXT</see> describing information to locate hand joints.</param>
|
||||
/// <param name="locations">A pointer to <see cref="XrHandJointLocationsEXT">XrHandJointLocationsEXT</see> receiving the returned hand joint locations.</param>
|
||||
/// <returns></returns>
|
||||
public XrResult LocateHandJointsEXT(XrHandTrackerEXT handTracker, XrHandJointsLocateInfoEXT locateInfo, ref XrHandJointLocationsEXT locations)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("LocateHandJointsEXT() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("LocateHandJointsEXT() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
return xrLocateHandJointsEXT(handTracker, locateInfo, ref locations);
|
||||
}
|
||||
|
||||
private bool GetXrFunctionDelegates(XrInstance xrInstance)
|
||||
{
|
||||
/// xrGetInstanceProcAddr
|
||||
if (xrGetInstanceProcAddr != null && xrGetInstanceProcAddr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetInstanceProcAddr.");
|
||||
XrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(
|
||||
xrGetInstanceProcAddr,
|
||||
typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate)) as OpenXRHelper.xrGetInstanceProcAddrDelegate;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetInstanceProcAddr");
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
/// xrGetSystemProperties
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrGetSystemProperties", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetSystemProperties.");
|
||||
xrGetSystemProperties = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrGetSystemPropertiesDelegate)) as OpenXRHelper.xrGetSystemPropertiesDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetSystemProperties");
|
||||
return false;
|
||||
}
|
||||
/// xrEnumerateReferenceSpaces
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrEnumerateReferenceSpaces", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrEnumerateReferenceSpaces.");
|
||||
xrEnumerateReferenceSpaces = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrEnumerateReferenceSpacesDelegate)) as OpenXRHelper.xrEnumerateReferenceSpacesDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrEnumerateReferenceSpaces");
|
||||
return false;
|
||||
}
|
||||
/// xrCreateReferenceSpace
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrCreateReferenceSpace", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrCreateReferenceSpace.");
|
||||
xrCreateReferenceSpace = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrCreateReferenceSpaceDelegate)) as OpenXRHelper.xrCreateReferenceSpaceDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrCreateReferenceSpace");
|
||||
return false;
|
||||
}
|
||||
/// xrDestroySpace
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrDestroySpace", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrDestroySpace.");
|
||||
xrDestroySpace = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(OpenXRHelper.xrDestroySpaceDelegate)) as OpenXRHelper.xrDestroySpaceDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrDestroySpace");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// xrCreateHandTrackerEXT
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrCreateHandTrackerEXT", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrCreateHandTrackerEXT.");
|
||||
xrCreateHandTrackerEXT = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(ViveHandTrackingHelper.xrCreateHandTrackerEXTDelegate)) as ViveHandTrackingHelper.xrCreateHandTrackerEXTDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrCreateHandTrackerEXT");
|
||||
return false;
|
||||
}
|
||||
/// xrDestroyHandTrackerEXT
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrDestroyHandTrackerEXT", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrDestroyHandTrackerEXT.");
|
||||
xrDestroyHandTrackerEXT = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(ViveHandTrackingHelper.xrDestroyHandTrackerEXTDelegate)) as ViveHandTrackingHelper.xrDestroyHandTrackerEXTDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrDestroyHandTrackerEXT");
|
||||
return false;
|
||||
}
|
||||
/// xrLocateHandJointsEXT
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrLocateHandJointsEXT", out funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrLocateHandJointsEXT.");
|
||||
xrLocateHandJointsEXT = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(ViveHandTrackingHelper.xrLocateHandJointsEXTDelegate)) as ViveHandTrackingHelper.xrLocateHandJointsEXTDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrLocateHandJointsEXT");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
static List<XRInputSubsystem> s_InputSubsystems = new List<XRInputSubsystem>();
|
||||
/// <summary>
|
||||
/// Retrieves the current tracking origin in Unity XR.
|
||||
/// </summary>
|
||||
/// <returns>The tracking origin in <see href="https://docs.unity3d.com/ScriptReference/XR.TrackingOriginModeFlags.html">TrackingOriginModeFlags</see></returns>
|
||||
public TrackingOriginModeFlags GetTrackingOriginMode()
|
||||
{
|
||||
XRInputSubsystem subsystem = null;
|
||||
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
if (s_InputSubsystems.Count > 0)
|
||||
{
|
||||
subsystem = s_InputSubsystems[0];
|
||||
}
|
||||
|
||||
if (subsystem != null)
|
||||
{
|
||||
return subsystem.GetTrackingOriginMode();
|
||||
}
|
||||
|
||||
return TrackingOriginModeFlags.Unknown;
|
||||
}
|
||||
private bool IsReferenceSpaceTypeSupported(UInt32 spaceCountOutput, XrReferenceSpaceType[] spaces, XrReferenceSpaceType space)
|
||||
{
|
||||
bool support = false;
|
||||
for (int i = 0; i < spaceCountOutput; i++)
|
||||
{
|
||||
DEBUG("IsReferenceSpaceTypeSupported() supported space[" + i + "]: " + spaces[i]);
|
||||
if (spaces[i] == space) { support = true; }
|
||||
}
|
||||
|
||||
return support;
|
||||
}
|
||||
|
||||
XrSystemHandTrackingPropertiesEXT handTrackingSystemProperties;
|
||||
XrSystemProperties systemProperties;
|
||||
private bool IsHandTrackingSupported()
|
||||
{
|
||||
bool ret = false;
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("IsHandTrackingSupported() session is not created.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
handTrackingSystemProperties.type = XrStructureType.XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT;
|
||||
systemProperties.type = XrStructureType.XR_TYPE_SYSTEM_PROPERTIES;
|
||||
systemProperties.next = Marshal.AllocHGlobal(Marshal.SizeOf(handTrackingSystemProperties));
|
||||
|
||||
long offset = 0;
|
||||
if (IntPtr.Size == 4)
|
||||
offset = systemProperties.next.ToInt32();
|
||||
else
|
||||
offset = systemProperties.next.ToInt64();
|
||||
|
||||
IntPtr sys_hand_tracking_prop_ptr = new IntPtr(offset);
|
||||
Marshal.StructureToPtr(handTrackingSystemProperties, sys_hand_tracking_prop_ptr, false);
|
||||
|
||||
#pragma warning disable 0618
|
||||
if (GetSystemProperties(ref systemProperties) == XrResult.XR_SUCCESS)
|
||||
#pragma warning restore 0618
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
offset = systemProperties.next.ToInt32();
|
||||
else
|
||||
offset = systemProperties.next.ToInt64();
|
||||
|
||||
sys_hand_tracking_prop_ptr = new IntPtr(offset);
|
||||
handTrackingSystemProperties = (XrSystemHandTrackingPropertiesEXT)Marshal.PtrToStructure(sys_hand_tracking_prop_ptr, typeof(XrSystemHandTrackingPropertiesEXT));
|
||||
|
||||
DEBUG("IsHandTrackingSupported() XrSystemHandTrackingPropertiesEXT.supportsHandTracking: " + handTrackingSystemProperties.supportsHandTracking);
|
||||
ret = handTrackingSystemProperties.supportsHandTracking > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("IsHandTrackingSupported() GetSystemProperties failed.");
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(systemProperties.next);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool CreateHandTrackers(bool isLeft, out XrHandTrackerEXT handTracker)
|
||||
{
|
||||
if (!IsHandTrackingSupported())
|
||||
{
|
||||
ERROR("CreateHandTrackers() " + (isLeft ? "Left" : "Right") + " hand tracking is NOT supported.");
|
||||
handTracker = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
XrHandTrackerCreateInfoEXT createInfo;
|
||||
createInfo.type = XrStructureType.XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT;
|
||||
createInfo.next = IntPtr.Zero;
|
||||
createInfo.hand = isLeft ? XrHandEXT.XR_HAND_LEFT_EXT : XrHandEXT.XR_HAND_RIGHT_EXT;
|
||||
createInfo.handJointSet = XrHandJointSetEXT.XR_HAND_JOINT_SET_DEFAULT_EXT;
|
||||
|
||||
var ret = CreateHandTrackerEXT(ref createInfo, out handTracker);
|
||||
DEBUG("CreateHandTrackers() " + (isLeft ? "Left" : "Right") + " CreateHandTrackerEXT = " + ret);
|
||||
|
||||
return ret == XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
private XrHandJointLocationEXT[] jointLocationsL = new XrHandJointLocationEXT[(int)XrHandJointEXT.XR_HAND_JOINT_MAX_ENUM_EXT];
|
||||
private XrHandJointLocationEXT[] jointLocationsR = new XrHandJointLocationEXT[(int)XrHandJointEXT.XR_HAND_JOINT_MAX_ENUM_EXT];
|
||||
private XrHandJointLocationsEXT locations = new XrHandJointLocationsEXT(XrStructureType.XR_TYPE_HAND_JOINT_LOCATIONS_EXT, IntPtr.Zero, false, 0, IntPtr.Zero);
|
||||
|
||||
public bool GetHandTrackingSpace(out XrSpace space)
|
||||
{
|
||||
space = 0;
|
||||
|
||||
TrackingOriginModeFlags origin = GetTrackingOriginMode();
|
||||
if (origin == TrackingOriginModeFlags.Unknown || origin == TrackingOriginModeFlags.Unbounded) { return false; }
|
||||
|
||||
space = (origin == TrackingOriginModeFlags.Device ? m_ReferenceSpaceLocal : m_ReferenceSpaceStage);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the <see cref="XrHandJointLocationEXT"> XrHandJointLocationEXT </see> data.
|
||||
/// </summary>
|
||||
/// <param name="isLeft">Left or right hand.</param>
|
||||
/// <param name="handJointLocation">Output parameter to retrieve <see cref="XrHandJointLocationEXT"> XrHandJointLocationEXT </see> data.</param>
|
||||
/// <returns>True for valid data.</returns>
|
||||
public bool GetJointLocations(bool isLeft, out XrHandJointLocationEXT[] handJointLocation)
|
||||
{
|
||||
bool ret = false;
|
||||
handJointLocation = isLeft ? jointLocationsL : jointLocationsR;
|
||||
|
||||
if (isLeft && !hasLeftHandTracker) { return ret; }
|
||||
if (!isLeft && !hasRightHandTracker) { return ret; }
|
||||
|
||||
TrackingOriginModeFlags origin = GetTrackingOriginMode();
|
||||
if (origin == TrackingOriginModeFlags.Unknown || origin == TrackingOriginModeFlags.Unbounded) { return ret; }
|
||||
XrSpace baseSpace = (origin == TrackingOriginModeFlags.Device ? m_ReferenceSpaceLocal : m_ReferenceSpaceStage);
|
||||
|
||||
/// Configures XrHandJointsLocateInfoEXT
|
||||
XrHandJointsLocateInfoEXT locateInfo = new XrHandJointsLocateInfoEXT(
|
||||
in_type: XrStructureType.XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT,
|
||||
in_next: IntPtr.Zero,
|
||||
in_baseSpace: baseSpace,
|
||||
in_time: 1);//
|
||||
|
||||
/// Configures XrHandJointLocationsEXT
|
||||
locations.type = XrStructureType.XR_TYPE_HAND_JOINT_LOCATIONS_EXT;
|
||||
locations.next = IntPtr.Zero;
|
||||
locations.isActive = false;
|
||||
locations.jointCount = (uint)(isLeft ? jointLocationsL.Length : jointLocationsR.Length);
|
||||
|
||||
XrHandJointLocationEXT joint_location_ext_type = default(XrHandJointLocationEXT);
|
||||
int jointLocationsLength = isLeft ? jointLocationsL.Length : jointLocationsR.Length;
|
||||
locations.jointLocations = Marshal.AllocHGlobal(Marshal.SizeOf(joint_location_ext_type) * jointLocationsLength);
|
||||
|
||||
long offset = 0;
|
||||
/*if (IntPtr.Size == 4)
|
||||
offset = locations.jointLocations.ToInt32();
|
||||
else
|
||||
offset = locations.jointLocations.ToInt64();
|
||||
|
||||
for (int i = 0; i < jointLocationsLength; i++)
|
||||
{
|
||||
IntPtr joint_location_ext_ptr = new IntPtr(offset);
|
||||
|
||||
if (isLeft)
|
||||
Marshal.StructureToPtr(jointLocationsL[i], joint_location_ext_ptr, false);
|
||||
else
|
||||
Marshal.StructureToPtr(jointLocationsR[i], joint_location_ext_ptr, false);
|
||||
|
||||
offset += Marshal.SizeOf(joint_location_ext_type);
|
||||
}*/
|
||||
|
||||
if (LocateHandJointsEXT(
|
||||
handTracker: (isLeft ? leftHandTracker : rightHandTracker),
|
||||
locateInfo: locateInfo,
|
||||
locations: ref locations) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (locations.isActive)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
offset = locations.jointLocations.ToInt32();
|
||||
else
|
||||
offset = locations.jointLocations.ToInt64();
|
||||
|
||||
for (int i = 0; i < locations.jointCount; i++)
|
||||
{
|
||||
IntPtr joint_location_ext_ptr = new IntPtr(offset);
|
||||
|
||||
if (isLeft)
|
||||
jointLocationsL[i] = (XrHandJointLocationEXT)Marshal.PtrToStructure(joint_location_ext_ptr, typeof(XrHandJointLocationEXT));
|
||||
else
|
||||
jointLocationsR[i] = (XrHandJointLocationEXT)Marshal.PtrToStructure(joint_location_ext_ptr, typeof(XrHandJointLocationEXT));
|
||||
|
||||
offset += Marshal.SizeOf(joint_location_ext_type);
|
||||
}
|
||||
|
||||
// ToDo: locationFlags?
|
||||
handJointLocation = isLeft ? jointLocationsL : jointLocationsR;
|
||||
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(locations.jointLocations);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 946578d91fd159a47b2ef0d5f4524fdb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,358 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System;
|
||||
|
||||
namespace VIVE.OpenXR.Hand
|
||||
{
|
||||
/// <summary>
|
||||
/// The XrHandTrackerEXT handle represents the resources for hand tracking of the specific hand.
|
||||
/// </summary>
|
||||
public struct XrHandTrackerEXT : IEquatable<ulong>
|
||||
{
|
||||
private readonly ulong value;
|
||||
|
||||
public XrHandTrackerEXT(ulong u)
|
||||
{
|
||||
value = u;
|
||||
}
|
||||
|
||||
public static implicit operator ulong(XrHandTrackerEXT xrInst)
|
||||
{
|
||||
return xrInst.value;
|
||||
}
|
||||
public static implicit operator XrHandTrackerEXT(ulong u)
|
||||
{
|
||||
return new XrHandTrackerEXT(u);
|
||||
}
|
||||
|
||||
public bool Equals(XrHandTrackerEXT other)
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
public bool Equals(ulong other)
|
||||
{
|
||||
return value == other;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is XrHandTrackerEXT && Equals((XrHandTrackerEXT)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
public static bool operator ==(XrHandTrackerEXT a, XrHandTrackerEXT b) { return a.Equals(b); }
|
||||
public static bool operator !=(XrHandTrackerEXT a, XrHandTrackerEXT b) { return !a.Equals(b); }
|
||||
public static bool operator >=(XrHandTrackerEXT a, XrHandTrackerEXT b) { return a.value >= b.value; }
|
||||
public static bool operator <=(XrHandTrackerEXT a, XrHandTrackerEXT b) { return a.value <= b.value; }
|
||||
public static bool operator >(XrHandTrackerEXT a, XrHandTrackerEXT b) { return a.value > b.value; }
|
||||
public static bool operator <(XrHandTrackerEXT a, XrHandTrackerEXT b) { return a.value < b.value; }
|
||||
public static XrHandTrackerEXT operator +(XrHandTrackerEXT a, XrHandTrackerEXT b) { return a.value + b.value; }
|
||||
public static XrHandTrackerEXT operator -(XrHandTrackerEXT a, XrHandTrackerEXT b) { return a.value - b.value; }
|
||||
public static XrHandTrackerEXT operator *(XrHandTrackerEXT a, XrHandTrackerEXT b) { return a.value * b.value; }
|
||||
public static XrHandTrackerEXT operator /(XrHandTrackerEXT a, XrHandTrackerEXT b)
|
||||
{
|
||||
if (b.value == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
return a.value / b.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The XrHandEXT describes which hand the <see cref="XrHandTrackerEXT">XrHandTrackerEXT</see> is tracking.
|
||||
/// </summary>
|
||||
public enum XrHandEXT
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the hand tracker will be tracking the user’s left hand.
|
||||
/// </summary>
|
||||
XR_HAND_LEFT_EXT = 1,
|
||||
/// <summary>
|
||||
/// Specifies the hand tracker will be tracking the user’s right hand.
|
||||
/// </summary>
|
||||
XR_HAND_RIGHT_EXT = 2,
|
||||
XR_HAND_MAX_ENUM_EXT = 3
|
||||
}
|
||||
/// <summary>
|
||||
/// Defines 26 joints for hand tracking: 4 joints for the thumb finger, 5 joints for the other four fingers, and the wrist and palm of the hands.
|
||||
/// </summary>
|
||||
public enum XrHandJointEXT
|
||||
{
|
||||
XR_HAND_JOINT_PALM_EXT = 0,
|
||||
XR_HAND_JOINT_WRIST_EXT = 1,
|
||||
XR_HAND_JOINT_THUMB_METACARPAL_EXT = 2,
|
||||
XR_HAND_JOINT_THUMB_PROXIMAL_EXT = 3,
|
||||
XR_HAND_JOINT_THUMB_DISTAL_EXT = 4,
|
||||
XR_HAND_JOINT_THUMB_TIP_EXT = 5,
|
||||
XR_HAND_JOINT_INDEX_METACARPAL_EXT = 6,
|
||||
XR_HAND_JOINT_INDEX_PROXIMAL_EXT = 7,
|
||||
XR_HAND_JOINT_INDEX_INTERMEDIATE_EXT = 8,
|
||||
XR_HAND_JOINT_INDEX_DISTAL_EXT = 9,
|
||||
XR_HAND_JOINT_INDEX_TIP_EXT = 10,
|
||||
XR_HAND_JOINT_MIDDLE_METACARPAL_EXT = 11,
|
||||
XR_HAND_JOINT_MIDDLE_PROXIMAL_EXT = 12,
|
||||
XR_HAND_JOINT_MIDDLE_INTERMEDIATE_EXT = 13,
|
||||
XR_HAND_JOINT_MIDDLE_DISTAL_EXT = 14,
|
||||
XR_HAND_JOINT_MIDDLE_TIP_EXT = 15,
|
||||
XR_HAND_JOINT_RING_METACARPAL_EXT = 16,
|
||||
XR_HAND_JOINT_RING_PROXIMAL_EXT = 17,
|
||||
XR_HAND_JOINT_RING_INTERMEDIATE_EXT = 18,
|
||||
XR_HAND_JOINT_RING_DISTAL_EXT = 19,
|
||||
XR_HAND_JOINT_RING_TIP_EXT = 20,
|
||||
XR_HAND_JOINT_LITTLE_METACARPAL_EXT = 21,
|
||||
XR_HAND_JOINT_LITTLE_PROXIMAL_EXT = 22,
|
||||
XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT = 23,
|
||||
XR_HAND_JOINT_LITTLE_DISTAL_EXT = 24,
|
||||
XR_HAND_JOINT_LITTLE_TIP_EXT = 25,
|
||||
XR_HAND_JOINT_MAX_ENUM_EXT = 26
|
||||
}
|
||||
/// <summary>
|
||||
/// The XrHandJointSetEXT enum describes the set of hand joints to track when creating an <see cref="XrHandTrackerEXT">XrHandTrackerEXT</see>.
|
||||
/// </summary>
|
||||
public enum XrHandJointSetEXT
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the created <see cref="XrHandTrackerEXT">XrHandTrackerEXT</see> tracks the set of hand joints described by <see cref="XrHandJointEXT">XrHandJointEXT</see> enum, i.e. the <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrLocateHandJointsEXT">xrLocateHandJointsEXT</see> function returns an array of joint locations with the count of <see cref="ViveHandTrackingHelper.XR_HAND_JOINT_COUNT_EXT">XR_HAND_JOINT_COUNT_EXT</see> and can be indexed using <see cref="XrHandJointEXT">XrHandJointEXT</see>.
|
||||
/// </summary>
|
||||
XR_HAND_JOINT_SET_DEFAULT_EXT = 0,
|
||||
XR_HAND_JOINT_SET_MAX_ENUM_EXT = 1
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An application can inspect whether the system is capable of hand tracking input by extending the <see cref="XrSystemProperties">XrSystemProperties</see> with XrSystemHandTrackingPropertiesEXT structure when calling <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystemProperties">xrGetSystemProperties</see>.
|
||||
/// </summary>
|
||||
public struct XrSystemHandTrackingPropertiesEXT
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="XrStructureType">XrStructureType</see> of this structure.
|
||||
/// </summary>
|
||||
public XrStructureType type;
|
||||
/// <summary>
|
||||
/// NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
|
||||
/// </summary>
|
||||
public IntPtr next;
|
||||
/// <summary>
|
||||
/// An <see cref="XrBool32">XrBool32</see>, indicating if current system is capable of hand tracking input.
|
||||
/// </summary>
|
||||
public XrBool32 supportsHandTracking;
|
||||
};
|
||||
/// <summary>
|
||||
/// The XrHandTrackerCreateInfoEXT structure describes the information to create an <see cref="XrHandTrackerEXT">XrHandTrackerEXT</see> handle.
|
||||
/// </summary>
|
||||
public struct XrHandTrackerCreateInfoEXT
|
||||
{
|
||||
/// <summary>
|
||||
/// The XrStructureType of this structure.
|
||||
/// </summary>
|
||||
public XrStructureType type;
|
||||
/// <summary>
|
||||
/// NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
|
||||
/// </summary>
|
||||
public IntPtr next;
|
||||
/// <summary>
|
||||
/// An <see cref="XrHandEXT">XrHandEXT</see> which describes which hand the tracker is tracking.
|
||||
/// </summary>
|
||||
public XrHandEXT hand;
|
||||
/// <summary>
|
||||
/// An <see cref="XrHandJointSetEXT">XrHandJointSetEXT</see> describe the set of hand joints to retrieve.
|
||||
/// </summary>
|
||||
public XrHandJointSetEXT handJointSet;
|
||||
/// <param name="in_type">The XrStructureType of this structure.</param>
|
||||
/// <param name="in_next">NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.</param>
|
||||
/// <param name="in_hand">An <see cref="XrHandEXT">XrHandEXT</see> which describes which hand the tracker is tracking.</param>
|
||||
/// <param name="in_handJointSet">An <see cref="XrHandJointSetEXT">XrHandJointSetEXT</see> describe the set of hand joints to retrieve.</param>
|
||||
public XrHandTrackerCreateInfoEXT(XrStructureType in_type, IntPtr in_next, XrHandEXT in_hand, XrHandJointSetEXT in_handJointSet)
|
||||
{
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
hand = in_hand;
|
||||
handJointSet = in_handJointSet;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The XrHandJointsLocateInfoEXT structure describes the information to locate hand joints.
|
||||
/// </summary>
|
||||
public struct XrHandJointsLocateInfoEXT
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="XrStructureType">XrStructureType</see> of this structure.
|
||||
/// </summary>
|
||||
public XrStructureType type;
|
||||
/// <summary>
|
||||
/// NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
|
||||
/// </summary>
|
||||
public IntPtr next;
|
||||
/// <summary>
|
||||
/// An <see cref="XrSpace">XrSpace</see> within which the returned hand joint locations will be represented.
|
||||
/// </summary>
|
||||
public XrSpace baseSpace;
|
||||
/// <summary>
|
||||
/// An <see cref="XrTime">XrTime</see> at which to locate the hand joints.
|
||||
/// </summary>
|
||||
public XrTime time;
|
||||
/// <param name="in_type">The <see cref="XrStructureType">XrStructureType</see> of this structure.</param>
|
||||
/// <param name="in_next">NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.</param>
|
||||
/// <param name="in_baseSpace">An <see cref="XrSpace">XrSpace</see> within which the returned hand joint locations will be represented.</param>
|
||||
/// <param name="in_time">An <see cref="XrTime">XrTime</see> at which to locate the hand joints.</param>
|
||||
public XrHandJointsLocateInfoEXT(XrStructureType in_type, IntPtr in_next, XrSpace in_baseSpace, XrTime in_time)
|
||||
{
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
baseSpace = in_baseSpace;
|
||||
time = in_time;
|
||||
}
|
||||
};
|
||||
/// <summary>
|
||||
/// XrHandJointLocationEXT structure describes the position, orientation, and radius of a hand joint.
|
||||
/// </summary>
|
||||
public struct XrHandJointLocationEXT
|
||||
{
|
||||
/// <summary>
|
||||
/// A bitfield, with bit masks defined in <see cref="XrSpaceLocationFlags">XrSpaceLocationFlags</see>, to indicate which members contain valid data. If none of the bits are set, no other fields in this structure should be considered to be valid or meaningful.
|
||||
/// </summary>
|
||||
public XrSpaceLocationFlags locationFlags;
|
||||
/// <summary>
|
||||
/// An <see cref="XrPosef">XrPosef</see> defining the position and orientation of the origin of a hand joint within the reference frame of the corresponding <see cref="XrHandJointsLocateInfoEXT.baseSpace">XrHandJointsLocateInfoEXT::baseSpace</see>.
|
||||
/// </summary>
|
||||
public XrPosef pose;
|
||||
/// <summary>
|
||||
/// A float value radius of the corresponding joint in units of meters.
|
||||
/// </summary>
|
||||
public float radius;
|
||||
}
|
||||
/// <summary>
|
||||
/// XrHandJointVelocityEXT structure describes the linear and angular velocity of a hand joint.
|
||||
/// </summary>
|
||||
public struct XrHandJointVelocityEXT
|
||||
{
|
||||
/// <summary>
|
||||
/// A bitfield, with bit masks defined in <see cref="XrSpaceVelocityFlags">XrSpaceVelocityFlags</see>, to indicate which members contain valid data. If none of the bits are set, no other fields in this structure should be considered to be valid or meaningful.
|
||||
/// </summary>
|
||||
public XrSpaceVelocityFlags velocityFlags;
|
||||
/// <summary>
|
||||
/// The relative linear velocity of the hand joint with respect to and expressed in the reference frame of the corresponding <see cref="XrHandJointsLocateInfoEXT.baseSpace">XrHandJointsLocateInfoEXT::baseSpace</see>, in units of meters per second.
|
||||
/// </summary>
|
||||
public XrVector3f linearVelocity;
|
||||
/// <summary>
|
||||
/// The relative angular velocity of the hand joint with respect to the corresponding <see cref="XrHandJointsLocateInfoEXT.baseSpace">XrHandJointsLocateInfoEXT::baseSpace</see>. The vector’s direction is expressed in the reference frame of the corresponding <see cref="XrHandJointsLocateInfoEXT.baseSpace">XrHandJointsLocateInfoEXT::baseSpace</see> and is parallel to the rotational axis of the hand joint. The vector’s magnitude is the relative angular speed of the hand joint in radians per second. The vector follows the right-hand rule for torque/rotation.
|
||||
/// </summary>
|
||||
public XrVector3f angularVelocity;
|
||||
}
|
||||
/// <summary>
|
||||
/// The application can chain an XrHandJointVelocitiesEXT structure to the next pointer of <see cref="XrHandJointLocationsEXT">XrHandJointLocationsEXT</see> when calling <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrLocateHandJointsEXT">xrLocateHandJointsEXT</see> to retrieve the hand joint velocities.
|
||||
/// </summary>
|
||||
public struct XrHandJointVelocitiesEXT
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="XrStructureType">XrStructureType</see> of this structure.
|
||||
/// </summary>
|
||||
public XrStructureType type;
|
||||
/// <summary>
|
||||
/// NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
|
||||
/// </summary>
|
||||
public IntPtr next;
|
||||
/// <summary>
|
||||
/// A uint32_t describing the number of elements in jointVelocities array.
|
||||
/// </summary>
|
||||
UInt32 jointCount;
|
||||
/// <summary>
|
||||
/// An array of <see cref="XrHandJointVelocityEXT">XrHandJointVelocityEXT</see> receiving the returned hand joint velocities.
|
||||
/// </summary>
|
||||
IntPtr jointVelocities; //XrHandJointVelocityEXT*
|
||||
}
|
||||
/// <summary>
|
||||
/// XrHandJointLocationsEXT structure returns the state of the hand joint locations.
|
||||
/// </summary>
|
||||
public struct XrHandJointLocationsEXT
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="XrStructureType">XrStructureType</see> of this structure.
|
||||
/// </summary>
|
||||
public XrStructureType type;
|
||||
/// <summary>
|
||||
/// NULL or a pointer to the next structure in a structure chain, such as <see cref="XrHandJointVelocitiesEXT">XrHandJointVelocitiesEXT</see>.
|
||||
/// </summary>
|
||||
public IntPtr next;
|
||||
/// <summary>
|
||||
/// An <see cref="XrBool32">XrBool32</see> indicating if the hand tracker is actively tracking.
|
||||
/// </summary>
|
||||
public XrBool32 isActive;
|
||||
/// <summary>
|
||||
/// A uint32_t describing the count of elements in jointLocations array.
|
||||
/// </summary>
|
||||
public UInt32 jointCount;
|
||||
/// <summary>
|
||||
/// An array of <see cref="XrHandJointLocationEXT">XrHandJointLocationEXT</see> receiving the returned hand joint locations.
|
||||
/// </summary>
|
||||
public IntPtr jointLocations; //XrHandJointLocationEXT*
|
||||
/// <param name="in_type">The <see cref="XrStructureType">XrStructureType</see> of this structure.</param>
|
||||
/// <param name="in_next">NULL or a pointer to the next structure in a structure chain, such as <see cref="XrHandJointVelocitiesEXT">XrHandJointVelocitiesEXT</see>.</param>
|
||||
/// <param name="in_isActive">An <see cref="XrBool32">XrBool32</see> indicating if the hand tracker is actively tracking.</param>
|
||||
/// <param name="in_jointCount">A uint32_t describing the count of elements in jointLocations array.</param>
|
||||
/// <param name="in_jointLocations">An array of <see cref="XrHandJointLocationEXT">XrHandJointLocationEXT</see> receiving the returned hand joint locations.</param>
|
||||
public XrHandJointLocationsEXT(XrStructureType in_type, IntPtr in_next, XrBool32 in_isActive, UInt32 in_jointCount, IntPtr in_jointLocations)
|
||||
{
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
isActive = in_isActive;
|
||||
jointCount = in_jointCount;
|
||||
jointLocations = in_jointLocations;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ViveHandTrackingHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the number of hand joint enumerants defined in <see cref="XrHandJointEXT">XrHandJointEXT</see>.
|
||||
/// </summary>
|
||||
public const int XR_HAND_JOINT_COUNT_EXT = 26;
|
||||
|
||||
/// <summary>
|
||||
/// The function delegate of <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateHandTrackerEXT">xrCreateHandTrackerEXT</see>.
|
||||
/// </summary>
|
||||
/// <param name="session">An <see cref="XrSession">XrSession</see> in which the hand tracker will be active.</param>
|
||||
/// <param name="createInfo">The <see cref="XrHandTrackerCreateInfoEXT">XrHandTrackerCreateInfoEXT</see> used to specify the hand tracker.</param>
|
||||
/// <param name="handTracker">The returned <see cref="XrHandTrackerEXT">XrHandTrackerEXT</see> handle.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public delegate XrResult xrCreateHandTrackerEXTDelegate(
|
||||
XrSession session,
|
||||
ref XrHandTrackerCreateInfoEXT createInfo,
|
||||
out XrHandTrackerEXT handTracker);
|
||||
/// <summary>
|
||||
/// The function delegate of <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroyHandTrackerEXT">xrDestroyHandTrackerEXT</see>.
|
||||
/// </summary>
|
||||
/// <param name="handTracker">An <see cref="XrHandTrackerEXT">XrHandTrackerEXT</see> previously created by <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateHandTrackerEXT">xrCreateHandTrackerEXT</see>.</param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public delegate XrResult xrDestroyHandTrackerEXTDelegate(
|
||||
XrHandTrackerEXT handTracker);
|
||||
/// <summary>
|
||||
/// The function delegate of <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrLocateHandJointsEXT">xrLocateHandJointsEXT</see>.
|
||||
/// </summary>
|
||||
/// <param name="handTracker">An <see cref="XrHandTrackerEXT">XrHandTrackerEXT</see> previously created by <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateHandTrackerEXT">xrCreateHandTrackerEXT</see>.</param>
|
||||
/// <param name="locateInfo">A pointer to <see cref="XrHandJointsLocateInfoEXT">XrHandJointsLocateInfoEXT</see> describing information to locate hand joints.</param>
|
||||
/// <param name="locations">A pointer to <see cref="XrHandJointLocationsEXT">XrHandJointLocationsEXT</see> receiving the returned hand joint locations.</param>
|
||||
/// <returns></returns>
|
||||
public delegate XrResult xrLocateHandJointsEXTDelegate(
|
||||
XrHandTrackerEXT handTracker,
|
||||
XrHandJointsLocateInfoEXT locateInfo,
|
||||
ref XrHandJointLocationsEXT locations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46df1d8f60e72ea44bf13cdca1f908b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d2be353ee1fd584cab39b6ee1a23369
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abf35aa708968a740b4565cdaa65ae7e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,345 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.SceneUnderstanding
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Scene Understanding",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.WSA},
|
||||
Company = "HTC",
|
||||
Desc = "Get function pointers related to openxr scene understanding",
|
||||
DocumentationLink = "https://developer.vive.com/resources/openxr/openxr-pcvr/tutorials/unity/interact-real-world-openxr-scene-understanding/",
|
||||
OpenxrExtensionStrings = "XR_MSFT_scene_understanding",
|
||||
Version = "0.0.1",
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class SceneUnderstanding_OpenXR_API : OpenXRFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "com.htc.openxr.sceneunderstanding.feature";
|
||||
|
||||
#region OpenXR callbacks
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnInstanceCreate({xrInstance})");
|
||||
m_XrInstance = xrInstance;
|
||||
|
||||
return GetXrFunctionDelegates(xrInstance);
|
||||
}
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnInstanceDestroy({xrInstance})");
|
||||
}
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnSessionCreate({xrSession})");
|
||||
m_XrSession = xrSession;
|
||||
systemProperties.type = XrStructureType.XR_TYPE_SYSTEM_PROPERTIES;
|
||||
int res = xrGetSystemProperties(ref systemProperties);
|
||||
if (res != (int)XrResult.XR_SUCCESS)
|
||||
{
|
||||
UnityEngine.Debug.Log("Failed to get systemproperties with error code : " + res);
|
||||
|
||||
}
|
||||
}
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnSystemChange({xrSystem})");
|
||||
m_systemid = xrSystem;
|
||||
}
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnSessionDestroy({xrSession})");
|
||||
}
|
||||
|
||||
bool CheckResult(XrResult result) => result == XrResult.XR_SUCCESS;
|
||||
public bool GetXrFunctionDelegates(ulong xrInstance)
|
||||
{
|
||||
Debug.Log("GetXrFunctionDelegates() begin");
|
||||
if (xrGetInstanceProcAddr == null || xrGetInstanceProcAddr == IntPtr.Zero)
|
||||
UnityEngine.Debug.LogError("xrGetInstanceProcAddr is null");
|
||||
// Get delegate of xrGetInstanceProcAddr.
|
||||
m_XrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer<xrGetInstanceProcDelegate>(xrGetInstanceProcAddr);
|
||||
// Get delegate of other OpenXR functions using xrGetInstanceProcAddr.
|
||||
bool successful = true;
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrGetSystemProperties", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrGetSystemProperties function failed"); return false; }
|
||||
m_xrGetSystemProperties = Marshal.GetDelegateForFunctionPointer(funcPtr, typeof(xrGetSystemPropertiesDelegate)) as xrGetSystemPropertiesDelegate;
|
||||
if (m_xrGetSystemProperties == null) { Debug.Log("m_xrGetSystemProperties == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrEnumerateReferenceSpaces", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrEnumerateReferenceSpaces function failed"); return false; }
|
||||
m_XrEnumerateReferenceSpaces = Marshal.GetDelegateForFunctionPointer<XrEnumerateReferenceSpacesDelegate>(funcPtr);
|
||||
if (m_XrEnumerateReferenceSpaces == null) { Debug.Log("m_XrEnumerateReferenceSpaces == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrCreateReferenceSpace", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrCreateReferenceSpace function failed"); return false; }
|
||||
m_XrCreateReferenceSpace = Marshal.GetDelegateForFunctionPointer<XrCreateReferenceSpaceDelegate>(funcPtr);
|
||||
if (m_XrCreateReferenceSpace == null) { Debug.Log("m_XrCreateReferenceSpace == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrDestroySpace", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrDestroySpace function failed"); return false; }
|
||||
m_XrDestroySpace = Marshal.GetDelegateForFunctionPointer<XrDestroySpaceDelegate>(funcPtr);
|
||||
if (m_XrDestroySpace == null) { Debug.Log("m_XrDestroySpace == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrEnumerateSceneComputeFeaturesMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrEnumerateSceneComputeFeaturesMSFT function failed"); return false; }
|
||||
m_XrEnumerateSceneComputeFeaturesMSFT = Marshal.GetDelegateForFunctionPointer<XrEnumerateSceneComputeFeaturesMSFTDelegate>(funcPtr);
|
||||
if (m_XrEnumerateSceneComputeFeaturesMSFT == null) { Debug.Log("m_XrEnumerateSceneComputeFeaturesMSFT == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrCreateSceneObserverMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrCreateSceneObserverMSFT function failed"); return false; }
|
||||
m_XrCreateSceneObserverMSFT = Marshal.GetDelegateForFunctionPointer<XrCreateSceneObserverMSFTDelegate>(funcPtr);
|
||||
if (m_XrCreateSceneObserverMSFT == null) { Debug.Log("m_XrCreateSceneObserverMSFT == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrDestroySceneObserverMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrDestroySceneObserverMSFT function failed"); return false; }
|
||||
m_XrDestroySceneObserverMSFT = Marshal.GetDelegateForFunctionPointer<XrDestroySceneObserverMSFTDelegate>(funcPtr);
|
||||
if (m_XrDestroySceneObserverMSFT == null) { Debug.Log("m_XrDestroySceneObserverMSFT == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrCreateSceneMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrCreateSceneMSFT function failed"); return false; }
|
||||
m_XrCreateSceneMSFT = Marshal.GetDelegateForFunctionPointer<XrCreateSceneMSFTDelegate>(funcPtr);
|
||||
if (m_XrCreateSceneMSFT == null) { Debug.Log("m_XrCreateSceneMSFT == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrDestroySceneMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrDestroySceneMSFT function failed"); return false; }
|
||||
m_XrDestroySceneMSFT = Marshal.GetDelegateForFunctionPointer<XrDestroySceneMSFTDelegate>(funcPtr);
|
||||
if (m_XrDestroySceneMSFT == null) { Debug.Log("m_XrDestroySceneMSFT == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrComputeNewSceneMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrComputeNewSceneMSFT function failed"); return false; }
|
||||
m_XrComputeNewSceneMSFT = Marshal.GetDelegateForFunctionPointer<XrComputeNewSceneMSFTDelegate>(funcPtr);
|
||||
if (m_XrComputeNewSceneMSFT == null) { Debug.Log("m_XrComputeNewSceneMSFT == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrGetSceneComputeStateMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrGetSceneComputeStateMSFT function failed"); return false; }
|
||||
m_XrGetSceneComputeStateMSFT = Marshal.GetDelegateForFunctionPointer<XrGetSceneComputeStateMSFTDelegate>(funcPtr);
|
||||
if (m_XrGetSceneComputeStateMSFT == null) { Debug.Log("m_XrGetSceneComputeStateMSFT == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrGetSceneComponentsMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrGetSceneComponentsMSFT function failed"); return false; }
|
||||
m_XrGetSceneComponentsMSFT = Marshal.GetDelegateForFunctionPointer<XrGetSceneComponentsMSFTDelegate>(funcPtr);
|
||||
if (m_XrGetSceneComponentsMSFT == null) { Debug.Log("m_XrGetSceneComponentsMSFT == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrLocateSceneComponentsMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrLocateSceneComponentsMSFT function failed"); return false; }
|
||||
m_XrLocateSceneComponentsMSFT = Marshal.GetDelegateForFunctionPointer<XrLocateSceneComponentsMSFTDelegate>(funcPtr);
|
||||
if (m_XrLocateSceneComponentsMSFT == null) { Debug.Log("m_XrLocateSceneComponentsMSFT == null"); }
|
||||
|
||||
successful &= CheckResult((XrResult)m_XrGetInstanceProcAddr(xrInstance, "xrGetSceneMeshBuffersMSFT", out funcPtr));
|
||||
if (funcPtr == IntPtr.Zero) { UnityEngine.Debug.Log("Get xrGetSceneMeshBuffersMSFT function failed"); return false; }
|
||||
m_XrGetSceneMeshBuffersMSFT = Marshal.GetDelegateForFunctionPointer<XrGetSceneMeshBuffersMSFTDelegate>(funcPtr);
|
||||
if (m_XrGetSceneMeshBuffersMSFT == null) { Debug.Log("m_XrGetSceneMeshBuffersMSFT == null"); }
|
||||
|
||||
Debug.Log("GetXrFunctionDelegates() end");
|
||||
return successful;
|
||||
}
|
||||
#endregion
|
||||
public ulong m_XrInstance;
|
||||
public ulong m_XrSession;
|
||||
public ulong m_systemid;
|
||||
public XrSystemProperties systemProperties;
|
||||
xrGetInstanceProcDelegate m_XrGetInstanceProcAddr;
|
||||
|
||||
public delegate int xrGetSystemPropertiesDelegate(ulong instance, ulong systemId, ref XrSystemProperties properties);
|
||||
public xrGetSystemPropertiesDelegate m_xrGetSystemProperties;
|
||||
public int xrGetSystemProperties(ref XrSystemProperties properties) =>
|
||||
m_xrGetSystemProperties(m_XrInstance, m_systemid, ref properties);
|
||||
|
||||
public delegate XrResult XrEnumerateReferenceSpacesDelegate(
|
||||
ulong session,
|
||||
uint spaceCapacityInput,
|
||||
out int spaceCountOutput,
|
||||
IntPtr spaces);
|
||||
public XrEnumerateReferenceSpacesDelegate m_XrEnumerateReferenceSpaces;
|
||||
public XrResult XrEnumerateReferenceSpaces(
|
||||
uint spaceCapacityInput,
|
||||
out int spaceCountOutput,
|
||||
IntPtr spaces
|
||||
) => m_XrEnumerateReferenceSpaces(
|
||||
m_XrSession,
|
||||
spaceCapacityInput,
|
||||
out spaceCountOutput,
|
||||
spaces
|
||||
);
|
||||
public delegate XrResult XrCreateReferenceSpaceDelegate(
|
||||
ulong session,
|
||||
ref XrReferenceSpaceCreateInfo createInfo,
|
||||
out ulong space);
|
||||
public XrCreateReferenceSpaceDelegate m_XrCreateReferenceSpace;
|
||||
public XrResult XrCreateReferenceSpace(
|
||||
ref XrReferenceSpaceCreateInfo createInfo,
|
||||
out ulong space
|
||||
) => m_XrCreateReferenceSpace(
|
||||
m_XrSession,
|
||||
ref createInfo,
|
||||
out space
|
||||
);
|
||||
public delegate XrResult XrDestroySpaceDelegate(
|
||||
ulong space);
|
||||
public XrDestroySpaceDelegate m_XrDestroySpace;
|
||||
public XrResult XrDestroySpace(
|
||||
ulong space
|
||||
) => m_XrDestroySpace(
|
||||
space
|
||||
);
|
||||
|
||||
public delegate XrResult XrEnumerateSceneComputeFeaturesMSFTDelegate(
|
||||
ulong instance,
|
||||
ulong systemId,
|
||||
uint featureCapacityInput,
|
||||
out uint featureCountOutput,
|
||||
IntPtr features
|
||||
);
|
||||
public XrEnumerateSceneComputeFeaturesMSFTDelegate m_XrEnumerateSceneComputeFeaturesMSFT;
|
||||
public XrResult XrEnumerateSceneComputeFeaturesMSFT(
|
||||
ulong systemId,
|
||||
uint featureCapacityInput,
|
||||
out uint featureCountOutput,
|
||||
IntPtr features
|
||||
) => m_XrEnumerateSceneComputeFeaturesMSFT(
|
||||
m_XrInstance,
|
||||
systemId,
|
||||
featureCapacityInput,
|
||||
out featureCountOutput,
|
||||
features
|
||||
);
|
||||
public delegate XrResult XrCreateSceneObserverMSFTDelegate(
|
||||
ulong session,
|
||||
ref XrSceneObserverCreateInfoMSFT createInfo,
|
||||
out ulong sceneObserver
|
||||
);
|
||||
public XrCreateSceneObserverMSFTDelegate m_XrCreateSceneObserverMSFT;
|
||||
public XrResult XrCreateSceneObserverMSFT(
|
||||
ref XrSceneObserverCreateInfoMSFT createInfo,
|
||||
out ulong sceneObserver
|
||||
) => m_XrCreateSceneObserverMSFT(
|
||||
m_XrSession,
|
||||
ref createInfo,
|
||||
out sceneObserver
|
||||
);
|
||||
|
||||
public delegate XrResult XrDestroySceneObserverMSFTDelegate(
|
||||
ulong sceneObserver
|
||||
);
|
||||
public XrDestroySceneObserverMSFTDelegate m_XrDestroySceneObserverMSFT;
|
||||
public XrResult XrDestroySceneObserverMSFT(
|
||||
ulong sceneObserver
|
||||
) => m_XrDestroySceneObserverMSFT(
|
||||
sceneObserver
|
||||
);
|
||||
|
||||
public delegate XrResult XrCreateSceneMSFTDelegate(
|
||||
ulong sceneObserver,
|
||||
ref XrSceneCreateInfoMSFT createInfo,
|
||||
out ulong scene
|
||||
);
|
||||
public XrCreateSceneMSFTDelegate m_XrCreateSceneMSFT;
|
||||
public XrResult XrCreateSceneMSFT(
|
||||
ulong sceneObserver,
|
||||
ref XrSceneCreateInfoMSFT createInfo,
|
||||
out ulong scene
|
||||
) => m_XrCreateSceneMSFT(
|
||||
sceneObserver,
|
||||
ref createInfo,
|
||||
out scene
|
||||
);
|
||||
|
||||
public delegate XrResult XrDestroySceneMSFTDelegate(
|
||||
ulong scene
|
||||
);
|
||||
public XrDestroySceneMSFTDelegate m_XrDestroySceneMSFT;
|
||||
public XrResult XrDestroySceneMSFT(
|
||||
ulong scene
|
||||
) => m_XrDestroySceneMSFT(
|
||||
scene
|
||||
);
|
||||
|
||||
public delegate XrResult XrComputeNewSceneMSFTDelegate(
|
||||
ulong sceneObserver,
|
||||
ref XrNewSceneComputeInfoMSFT computeInfo
|
||||
);
|
||||
public XrComputeNewSceneMSFTDelegate m_XrComputeNewSceneMSFT;
|
||||
public XrResult XrComputeNewSceneMSFT(
|
||||
ulong sceneObserver,
|
||||
ref XrNewSceneComputeInfoMSFT computeInfo
|
||||
) => m_XrComputeNewSceneMSFT(
|
||||
sceneObserver,
|
||||
ref computeInfo
|
||||
);
|
||||
|
||||
public delegate XrResult XrGetSceneComputeStateMSFTDelegate(
|
||||
ulong sceneObserver,
|
||||
out XrSceneComputeStateMSFT state
|
||||
);
|
||||
public XrGetSceneComputeStateMSFTDelegate m_XrGetSceneComputeStateMSFT;
|
||||
public XrResult XrGetSceneComputeStateMSFT(
|
||||
ulong sceneObserver,
|
||||
out XrSceneComputeStateMSFT state
|
||||
) => m_XrGetSceneComputeStateMSFT(
|
||||
sceneObserver,
|
||||
out state
|
||||
);
|
||||
|
||||
public delegate XrResult XrGetSceneComponentsMSFTDelegate(
|
||||
ulong scene,
|
||||
ref XrSceneComponentsGetInfoMSFT getInfo,
|
||||
ref XrSceneComponentsMSFT components
|
||||
);
|
||||
public XrGetSceneComponentsMSFTDelegate m_XrGetSceneComponentsMSFT;
|
||||
public XrResult XrGetSceneComponentsMSFT(
|
||||
ulong scene,
|
||||
ref XrSceneComponentsGetInfoMSFT getInfo,
|
||||
ref XrSceneComponentsMSFT components
|
||||
) => m_XrGetSceneComponentsMSFT(
|
||||
scene,
|
||||
ref getInfo,
|
||||
ref components
|
||||
);
|
||||
|
||||
public delegate XrResult XrLocateSceneComponentsMSFTDelegate(
|
||||
ulong scene,
|
||||
ref XrSceneComponentsLocateInfoMSFT locateInfo,
|
||||
ref XrSceneComponentLocationsMSFT locations
|
||||
);
|
||||
public XrLocateSceneComponentsMSFTDelegate m_XrLocateSceneComponentsMSFT;
|
||||
public XrResult XrLocateSceneComponentsMSFT(
|
||||
ulong scene,
|
||||
ref XrSceneComponentsLocateInfoMSFT locateInfo,
|
||||
ref XrSceneComponentLocationsMSFT locations
|
||||
) => m_XrLocateSceneComponentsMSFT(
|
||||
scene,
|
||||
ref locateInfo,
|
||||
ref locations
|
||||
);
|
||||
|
||||
public delegate XrResult XrGetSceneMeshBuffersMSFTDelegate(
|
||||
ulong scene,
|
||||
ref XrSceneMeshBuffersGetInfoMSFT getInfo,
|
||||
ref XrSceneMeshBuffersMSFT buffers
|
||||
);
|
||||
public XrGetSceneMeshBuffersMSFTDelegate m_XrGetSceneMeshBuffersMSFT;
|
||||
public XrResult XrGetSceneMeshBuffersMSFT(
|
||||
ulong scene,
|
||||
ref XrSceneMeshBuffersGetInfoMSFT getInfo,
|
||||
ref XrSceneMeshBuffersMSFT buffers
|
||||
) => m_XrGetSceneMeshBuffersMSFT(
|
||||
scene,
|
||||
ref getInfo,
|
||||
ref buffers
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f11d54adfd486544afef5e8b85f159d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,387 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR.SceneUnderstanding
|
||||
{
|
||||
public enum XrSceneComputeConsistencyMSFT
|
||||
{
|
||||
SnapshotComplete = 1,
|
||||
SnapshotIncompleteFast = 2,
|
||||
OcclusionOptimized = 3,
|
||||
}
|
||||
|
||||
public enum XrSceneBoundType
|
||||
{
|
||||
Sphere = 1,
|
||||
OrientedBox = 2,
|
||||
Frustum = 3,
|
||||
}
|
||||
|
||||
public enum XrSceneComputeFeatureMSFT
|
||||
{
|
||||
XR_SCENE_COMPUTE_FEATURE_PLANE_MSFT = 1,
|
||||
XR_SCENE_COMPUTE_FEATURE_PLANE_MESH_MSFT = 2,
|
||||
XR_SCENE_COMPUTE_FEATURE_VISUAL_MESH_MSFT = 3,
|
||||
XR_SCENE_COMPUTE_FEATURE_COLLIDER_MESH_MSFT = 4,
|
||||
XR_SCENE_COMPUTE_FEATURE_SERIALIZE_SCENE_MSFT = 1000098000,
|
||||
XR_SCENE_COMPUTE_FEATURE_OCCLUSION_HINT_MSFT = 1000099000,
|
||||
XR_SCENE_COMPUTE_FEATURE_MAX_ENUM_MSFT = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
public enum XrMeshComputeLodMSFT
|
||||
{
|
||||
Coarse = 1,
|
||||
Medium = 2,
|
||||
Fine = 3,
|
||||
Unlimited = 4,
|
||||
}
|
||||
|
||||
public enum XrSceneComponentTypeMSFT
|
||||
{
|
||||
XR_SCENE_COMPONENT_TYPE_INVALID_MSFT = -1,
|
||||
XR_SCENE_COMPONENT_TYPE_OBJECT_MSFT = 1,
|
||||
XR_SCENE_COMPONENT_TYPE_PLANE_MSFT = 2,
|
||||
XR_SCENE_COMPONENT_TYPE_VISUAL_MESH_MSFT = 3,
|
||||
XR_SCENE_COMPONENT_TYPE_COLLIDER_MESH_MSFT = 4,
|
||||
XR_SCENE_COMPONENT_TYPE_SERIALIZED_SCENE_FRAGMENT_MSFT = 1000098000,
|
||||
XR_SCENE_COMPONENT_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
public enum XrSceneObjectTypeMSFT
|
||||
{
|
||||
XR_SCENE_OBJECT_TYPE_UNCATEGORIZED_MSFT = -1,
|
||||
XR_SCENE_OBJECT_TYPE_BACKGROUND_MSFT = 1,
|
||||
XR_SCENE_OBJECT_TYPE_WALL_MSFT = 2,
|
||||
XR_SCENE_OBJECT_TYPE_FLOOR_MSFT = 3,
|
||||
XR_SCENE_OBJECT_TYPE_CEILING_MSFT = 4,
|
||||
XR_SCENE_OBJECT_TYPE_PLATFORM_MSFT = 5,
|
||||
XR_SCENE_OBJECT_TYPE_INFERRED_MSFT = 6,
|
||||
XR_SCENE_OBJECT_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
public enum XrScenePlaneAlignmentTypeMSFT
|
||||
{
|
||||
XR_SCENE_PLANE_ALIGNMENT_TYPE_NON_ORTHOGONAL_MSFT = 0,
|
||||
XR_SCENE_PLANE_ALIGNMENT_TYPE_HORIZONTAL_MSFT = 1,
|
||||
XR_SCENE_PLANE_ALIGNMENT_TYPE_VERTICAL_MSFT = 2,
|
||||
XR_SCENE_PLANE_ALIGNMENT_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
public enum XrSceneComputeStateMSFT
|
||||
{
|
||||
XR_SCENE_COMPUTE_STATE_NONE_MSFT = 0,
|
||||
XR_SCENE_COMPUTE_STATE_UPDATING_MSFT = 1,
|
||||
XR_SCENE_COMPUTE_STATE_COMPLETED_MSFT = 2,
|
||||
XR_SCENE_COMPUTE_STATE_COMPLETED_WITH_ERROR_MSFT = 3,
|
||||
XR_SCENE_COMPUTE_STATE_MAX_ENUM_MSFT = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
public struct XrUuidMSFT
|
||||
{
|
||||
public byte byte0;
|
||||
public byte byte1;
|
||||
public byte byte2;
|
||||
public byte byte3;
|
||||
public byte byte4;
|
||||
public byte byte5;
|
||||
public byte byte6;
|
||||
public byte byte7;
|
||||
public byte byte8;
|
||||
public byte byte9;
|
||||
public byte byte10;
|
||||
public byte byte11;
|
||||
public byte byte12;
|
||||
public byte byte13;
|
||||
public byte byte14;
|
||||
public byte byte15;
|
||||
public byte byte16;
|
||||
|
||||
}
|
||||
|
||||
public struct XrSceneObserverCreateInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
public struct XrSceneCreateInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
public struct XrSceneSphereBoundMSFT
|
||||
{
|
||||
public XrVector3f center;
|
||||
public float radius;
|
||||
}
|
||||
|
||||
public struct XrSceneOrientedBoxBoundMSFT
|
||||
{
|
||||
public XrPosef pose;
|
||||
public XrVector3f extents;
|
||||
}
|
||||
|
||||
public struct XrSceneFrustumBoundMSFT
|
||||
{
|
||||
public XrPosef pose;
|
||||
public XrFovf fov;
|
||||
public float farDistance;
|
||||
}
|
||||
|
||||
public struct XrSceneBoundsMSFT
|
||||
{
|
||||
public ulong space;
|
||||
public long time;
|
||||
public uint sphereCount;
|
||||
|
||||
// XrSceneSphereBoundMSFT
|
||||
public IntPtr spheres;
|
||||
public uint boxCount;
|
||||
|
||||
// XrSceneOrientedBoxBoundMSFT
|
||||
public IntPtr boxes;
|
||||
public uint frustumCount;
|
||||
|
||||
// XrSceneFrustumBoundMSFT
|
||||
public IntPtr frustums;
|
||||
}
|
||||
|
||||
public struct XrNewSceneComputeInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint requestedFeatureCount;
|
||||
|
||||
// XrSceneComputeFeatureMSFT array
|
||||
public IntPtr requestedFeatures;
|
||||
public uint disableInferredSceneObjects;
|
||||
public XrSceneBoundsMSFT bounds;
|
||||
}
|
||||
|
||||
// XrVisualMeshComputeLodInfoMSFT extends XrNewSceneComputeInfoMSFT
|
||||
public struct XrVisualMeshComputeLodInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrMeshComputeLodMSFT lod;
|
||||
}
|
||||
|
||||
public struct XrSceneComponentMSFT
|
||||
{
|
||||
public XrSceneComponentTypeMSFT componentType;
|
||||
public XrUuidMSFT componentId;
|
||||
public XrUuidMSFT parentObjectId;
|
||||
public long updateTime;
|
||||
}
|
||||
|
||||
public struct XrSceneComponentsMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint componentCapacityInput;
|
||||
public uint componentCountOutput;
|
||||
|
||||
// XrSceneComponentMSFT array
|
||||
public IntPtr components;
|
||||
}
|
||||
|
||||
public struct XrSceneComponentsGetInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrSceneComponentTypeMSFT componentType;
|
||||
}
|
||||
|
||||
public struct XrSceneComponentLocationMSFT
|
||||
{
|
||||
public ulong flags;
|
||||
public XrPosef pose;
|
||||
}
|
||||
|
||||
public struct XrSceneComponentLocationsMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint locationCount;
|
||||
|
||||
// XrSceneComponentLocationMSFT array
|
||||
public IntPtr locations;
|
||||
}
|
||||
|
||||
public struct XrSceneComponentsLocateInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
|
||||
// XrSpace
|
||||
public ulong baseSpace;
|
||||
|
||||
// XrTime
|
||||
public long time;
|
||||
public uint idCount;
|
||||
|
||||
// XrUuidMSFT array
|
||||
public IntPtr ids;
|
||||
}
|
||||
|
||||
public struct XrSceneObjectMSFT
|
||||
{
|
||||
public XrSceneObjectTypeMSFT objectType;
|
||||
}
|
||||
|
||||
// XrSceneObjectsMSFT extends XrSceneComponentsMSFT
|
||||
public struct XrSceneObjectsMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint sceneObjectCount;
|
||||
|
||||
// XrSceneObjectMSFT array
|
||||
public IntPtr sceneObjects;
|
||||
}
|
||||
|
||||
// XrSceneComponentParentFilterInfoMSFT extends XrSceneComponentsGetInfoMSFT
|
||||
public struct XrSceneComponentParentFilterInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrUuidMSFT parentObjectId;
|
||||
}
|
||||
|
||||
// XrSceneObjectTypesFilterInfoMSFT extends XrSceneComponentsGetInfoMSFT
|
||||
public struct XrSceneObjectTypesFilterInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint objectTypeCount;
|
||||
|
||||
// XrSceneObjectTypeMSFT array
|
||||
public IntPtr objectTypes;
|
||||
}
|
||||
|
||||
public struct XrScenePlaneMSFT
|
||||
{
|
||||
public XrScenePlaneAlignmentTypeMSFT alignment;
|
||||
public XrExtent2Df size;
|
||||
public ulong meshBufferId;
|
||||
|
||||
// XrBool32
|
||||
public uint supportsIndicesUint16;
|
||||
}
|
||||
|
||||
// XrScenePlanesMSFT extends XrSceneComponentsMSFT
|
||||
public struct XrScenePlanesMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint scenePlaneCount;
|
||||
|
||||
// XrScenePlaneMSFT array
|
||||
public IntPtr scenePlanes;
|
||||
}
|
||||
|
||||
// XrScenePlaneAlignmentFilterInfoMSFT extends XrSceneComponentsGetInfoMSFT
|
||||
public struct XrScenePlaneAlignmentFilterInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint alignmentCount;
|
||||
|
||||
// XrScenePlaneAlignmentTypeMSFT array
|
||||
public IntPtr alignments;
|
||||
}
|
||||
|
||||
public struct XrSceneMeshMSFT
|
||||
{
|
||||
public ulong meshBufferId;
|
||||
|
||||
// XrBool32
|
||||
public uint supportsIndicesUint16;
|
||||
}
|
||||
|
||||
// XrSceneMeshesMSFT extends XrSceneComponentsMSFT
|
||||
public struct XrSceneMeshesMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint sceneMeshCount;
|
||||
|
||||
// XrSceneMeshMSFT array
|
||||
public IntPtr sceneMeshes;
|
||||
}
|
||||
|
||||
public struct XrSceneMeshBuffersGetInfoMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public ulong meshBufferId;
|
||||
}
|
||||
|
||||
public struct XrSceneMeshBuffersMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
public struct XrSceneMeshVertexBufferMSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint vertexCapacityInput;
|
||||
public uint vertexCountOutput;
|
||||
|
||||
// XrVector3f array
|
||||
public IntPtr vertices;
|
||||
}
|
||||
|
||||
public struct XrSceneMeshIndicesUint32MSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint indexCapacityInput;
|
||||
public uint indexCountOutput;
|
||||
|
||||
// uint32_t array
|
||||
public IntPtr indices;
|
||||
}
|
||||
|
||||
public struct XrSceneMeshIndicesUint16MSFT
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint indexCapacityInput;
|
||||
public uint indexCountOutput;
|
||||
|
||||
// uint16_t array
|
||||
public IntPtr indices;
|
||||
}
|
||||
|
||||
public struct XrSystemPassThroughCameraInfoHTC
|
||||
{
|
||||
public float focalLengthX;
|
||||
public float focalLengthY;
|
||||
public float opticalCenterX;
|
||||
public float opticalCenterY;
|
||||
public uint imageWidth;
|
||||
public uint imageHeight;
|
||||
public uint imageChannelCount;
|
||||
}
|
||||
public struct XrSystemPassThroughPropertiesHTC
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint supportsPassThrough;
|
||||
XrSystemPassThroughCameraInfoHTC leftCameraInfo;
|
||||
XrSystemPassThroughCameraInfoHTC rightCameraInfo;
|
||||
public int deviceType;
|
||||
public long format;
|
||||
}
|
||||
|
||||
delegate int xrGetInstanceProcDelegate(ulong instance, string name, out IntPtr function);
|
||||
public static class ViveSceneUnderstandingHelper
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b8e83b965a9b0fd4cbef91ba1bd5010d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
com.htc.upm.vive.openxr/Runtime/Features/Tracker.meta
Normal file
8
com.htc.upm.vive.openxr/Runtime/Features/Tracker.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4289e9c086e05334eafd5cf129186882
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ceb6bae4c2ad8b429f23dcab89cf251
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,44 @@
|
||||
# 12.70. XR_HTC_vive_wrist_tracker_interaction
|
||||
## Name String
|
||||
XR_HTC_vive_wrist_tracker_interaction
|
||||
## Revision
|
||||
1
|
||||
## VIVE Wrist Tracker input
|
||||
### Interaction profile path:
|
||||
- /interaction_profiles/htc/vive_wrist_tracker
|
||||
|
||||
### Valid for user paths:
|
||||
- /user/wrist_htc/left
|
||||
- /user/wrist_htc/right
|
||||
|
||||
### Supported input source
|
||||
- On /user/wrist_htc/left only:
|
||||
- <20>K/input/menu/click
|
||||
- <20>K/input/x/click
|
||||
- On /user/wrist_htc/right only:
|
||||
- <20>K/input/system/click (may not be available for application use)
|
||||
- <20>K/input/a/click
|
||||
- <20>K/input/entity_htc/pose
|
||||
|
||||
The entity_htc pose allows the applications to recognize the origin of a tracked input device, especially for the wearable devices which are not held in the user<65><72>s hand. The entity_htc pose is defined as follows:
|
||||
|
||||
- The entity position: The center position of the tracked device.
|
||||
- The entity orientation: Oriented with +Y up, +X to the right, and -Z forward.
|
||||
|
||||
## VIVE Plugin
|
||||
|
||||
After adding the "VIVE Focus3 Wrist Tracker" to "Project Settings > XR Plugin-in Management > OpenXR > Android Tab > Interaction Profiles", you can use the following Input Action Pathes.
|
||||
|
||||
### Left Hand
|
||||
- <ViveWristTracker>{LeftHand}/primaryButton: Left tracker primary button pressed state.
|
||||
- <ViveWristTracker>{LeftHand}/menu: Left tracker menu button pressed state.
|
||||
- <ViveWristTracker>{LeftHand}/devicePose: Left tracker pose.
|
||||
- <ViveWristTracker>{LeftHand}/devicePose/isTracked: Left tracker tracking state.
|
||||
|
||||
### Right Hand
|
||||
- <ViveWristTracker>{RightHand}/primaryButton: Right tracker primary button pressed state.
|
||||
- <ViveWristTracker>{RightHand}/menu: Right tracker menu button pressed state.
|
||||
- <ViveWristTracker>{RightHand}/devicePose: Right tracker pose.
|
||||
- <ViveWristTracker>{RightHand}/devicePose/isTracked: Right tracker tracking state.
|
||||
|
||||
Refer to the <VIVE OpenXR sample path>/Plugin/Input/ActionMap/InputActions.inputActions about the "Input Action Path" usage and the sample <VIVE OpenXR sample path>/Plugin/Input/OpenXRInput.unity.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5730a6cbe3d89f408a7cd52289f7d3f
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83afdfd52871d724b87c568b98638daa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,324 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using UnityEngine.Scripting;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
#if USE_INPUT_SYSTEM_POSE_CONTROL // Scripting Define Symbol added by using OpenXR Plugin 1.6.0.
|
||||
using PoseControl = UnityEngine.InputSystem.XR.PoseControl;
|
||||
#else
|
||||
using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.Tracker
|
||||
{
|
||||
/// <summary>
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of wrist tracker interaction profiles in OpenXR. It enables XR_HTC_vive_wrist_tracker_interaction in the underyling runtime.
|
||||
/// This creates a new <see cref="InputDevice"/> with the <see cref="InputDeviceCharacteristics.TrackedDevice"/> characteristic.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Wrist Tracker",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android , BuildTargetGroup.Standalone},
|
||||
Company = "HTC",
|
||||
Desc = "Support for enabling the wrist tracker interaction profile. Will register the controller map for wrist tracker if enabled.",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
Version = "1.0.0",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionString,
|
||||
Category = FeatureCategory.Interaction,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class ViveWristTracker : OpenXRInteractionFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.Tracker.ViveWristTracker";
|
||||
void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <summary>
|
||||
/// OpenXR specification <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_vive_wrist_tracker_interaction">12.72. XR_HTC_vive_wrist_tracker_interaction</see>.
|
||||
/// </summary>
|
||||
public const string kOpenxrExtensionString = "XR_HTC_vive_wrist_tracker_interaction";
|
||||
|
||||
/// <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.tracker";
|
||||
|
||||
/// <summary>The interaction profile string used to reference the wrist tracker interaction input device.</summary>
|
||||
private const string profile = "/interaction_profiles/htc/vive_wrist_tracker";
|
||||
|
||||
private const string leftWrist = "/user/wrist_htc/left";
|
||||
private const string rightWrist = "/user/wrist_htc/right";
|
||||
|
||||
// Available Bindings
|
||||
// Left Hand Only
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/x/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="leftWrist"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonX = "/input/x/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/menu/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="leftWrist"/> user path.
|
||||
/// </summary>
|
||||
public const string menu = "/input/menu/click";
|
||||
|
||||
// Right Hand Only
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/a/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="rightWrist"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonA = "/input/a/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/system/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="rightWrist"/> user path.
|
||||
/// </summary>
|
||||
public const string system = "/input/system/click";
|
||||
|
||||
// Both Hands
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/entity_htc/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string entityPose = "/input/entity_htc/pose";
|
||||
|
||||
[Preserve, InputControlLayout(displayName = "Vive Wrist Tracker (OpenXR)", commonUsages = new[] { "LeftHand", "RightHand" }, isGenericTypeOfDevice = true)]
|
||||
public class WristTrackerDevice : OpenXRDevice
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.Tracker.ViveWristTracker.WristTrackerDevice";
|
||||
void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <summary>
|
||||
/// A <see href="https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/api/UnityEngine.InputSystem.Controls.ButtonControl.html">ButtonControl</see> that represents the <see cref="buttonA"/> <see cref="buttonX"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "A", "X", "buttonA", "buttonX" }, usage = "PrimaryButton")]
|
||||
public ButtonControl primaryButton { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="entityPose"/> OpenXR binding. The entity pose represents the location of the tracker.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "device", "entityPose" }, usage = "Device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see href="https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/api/UnityEngine.InputSystem.Controls.ButtonControl.html">ButtonControl</see> required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 24, usage = "IsTracked")]
|
||||
public ButtonControl isTracked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see href="https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/api/UnityEngine.InputSystem.Controls.IntegerControl.html">IntegerControl</see> required for backwards compatibility with the XRSDK layouts. This represents the bit flag set to indicate what data is valid. This value is equivalent to mapping devicePose/trackingState.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 28, usage = "TrackingState")]
|
||||
public IntegerControl trackingState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see href="https://docs.unity3d.com/Packages/com.unity.inputsystem@0.1/api/UnityEngine.Experimental.Input.Controls.Vector3Control.html">Vector3Control</see> required for backwards compatibility with the XRSDK layouts. This is the device position. For the VIVE XR device, this is both the device and the pointer position. This value is equivalent to mapping devicePose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 32, alias = "gripPosition")]
|
||||
public Vector3Control devicePosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see href="https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/api/UnityEngine.InputSystem.Controls.QuaternionControl.html">QuaternionControl</see> required for backwards compatibility with the XRSDK layouts. This is the device orientation. For the VIVE XR device, this is both the device and the pointer rotation. This value is equivalent to mapping devicePose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 44, alias = "gripOrientation")]
|
||||
public QuaternionControl deviceRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see href="https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/api/UnityEngine.InputSystem.Controls.ButtonControl.html">ButtonControl</see> that represents the <see cref="ViveWristTracker.menu"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "menuButton" }, usage = "MenuButton")]
|
||||
public ButtonControl menu { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Internal call used to assign controls to the the correct element.
|
||||
/// </summary>
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
/*for (int i = 0; i < InputSystem.devices.Count; i++)
|
||||
{
|
||||
var description = InputSystem.devices[i].description;
|
||||
DEBUG("FinishSetup() device[" + i + "], interfaceName: " + description.interfaceName
|
||||
+ ", deviceClass: " + description.deviceClass
|
||||
+ ", product: " + description.product);
|
||||
}*/
|
||||
|
||||
base.FinishSetup();
|
||||
|
||||
primaryButton = GetChildControl<ButtonControl>("primaryButton");
|
||||
menu = GetChildControl<ButtonControl>("menu");
|
||||
devicePose = GetChildControl<PoseControl>("devicePose");
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
devicePosition = GetChildControl<Vector3Control>("devicePosition");
|
||||
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable
|
||||
private bool m_XrInstanceCreated = false;
|
||||
#pragma warning restore
|
||||
private XrInstance m_XrInstance = 0;
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateInstance">xrCreateInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The created instance.</param>
|
||||
/// <returns>True for valid <see cref="XrInstance">XrInstance</see></returns>
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
// Requires the eye tracking extension
|
||||
/*if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
{
|
||||
WARNING("OnInstanceCreate() " + kOpenxrExtensionString + " is NOT enabled.");
|
||||
return false;
|
||||
}*/
|
||||
|
||||
m_XrInstanceCreated = true;
|
||||
m_XrInstance = xrInstance;
|
||||
DEBUG("OnInstanceCreate() " + m_XrInstance);
|
||||
|
||||
return base.OnInstanceCreate(xrInstance);
|
||||
}
|
||||
|
||||
private const string kLayoutName = "ViveWristTracker";
|
||||
private const string kDeviceLocalizedName = "Vive Wrist Tracker OpenXR";
|
||||
/// <summary>
|
||||
/// Registers the <see cref="WristTrackerDevice"/> layout with the Input System.
|
||||
/// </summary>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
InputSystem.RegisterLayout(typeof(WristTrackerDevice),
|
||||
kLayoutName,
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
||||
.WithProduct(kDeviceLocalizedName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the <see cref="WristTrackerDevice"/> layout from the Input System.
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
InputSystem.RemoveLayout(kLayoutName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers action maps to Unity XR.
|
||||
/// </summary>
|
||||
protected override void RegisterActionMapsWithRuntime()
|
||||
{
|
||||
ActionMapConfig actionMap = new ActionMapConfig()
|
||||
{
|
||||
name = "vivewristtracker",
|
||||
localizedName = kDeviceLocalizedName,
|
||||
desiredInteractionProfile = profile,
|
||||
manufacturer = "HTC",
|
||||
serialNumber = "",
|
||||
deviceInfos = new List<DeviceConfig>()
|
||||
{
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Left,
|
||||
userPath = leftWrist // "/user/wrist_htc/left"
|
||||
},
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Right,
|
||||
userPath = rightWrist // "/user/wrist_htc/right"
|
||||
}
|
||||
},
|
||||
actions = new List<ActionConfig>()
|
||||
{
|
||||
// X / A Press
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "primaryButton",
|
||||
localizedName = "Primary Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"PrimaryButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonX,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { leftWrist }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonA,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { rightWrist }
|
||||
},
|
||||
}
|
||||
},
|
||||
// Menu
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "menu",
|
||||
localizedName = "Menu",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"MenuButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = menu,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { leftWrist }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = system,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { rightWrist }
|
||||
},
|
||||
}
|
||||
},
|
||||
// Device Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "devicePose",
|
||||
localizedName = "Grip Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Device"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = entityPose,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AddActionMap(actionMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c438b3d1db2d7e4fb133eab8345e6bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user