上传YomovSDK

This commit is contained in:
Sora丶kong
2026-03-03 03:15:46 +08:00
parent 9096da7e6c
commit eb97f31065
6477 changed files with 1932208 additions and 3 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1850b50609fc1db458be9f8f11c62852
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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*

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: cbab5ef182d5d34438925945775e2443
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f29d9246fa53ed5469160eb0ec165fb8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,570 @@
// Copyright HTC Corporation All Rights Reserved.
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;
/// <summary>
/// The XR instance is created or not.
/// </summary>
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;
/// <summary>
/// The XR session is created or not.
/// </summary>
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;
/// <summary>
/// The XR session is ending or not.
/// </summary>
public bool XrSessionEnding
{
get { return m_XrSessionEnding; }
}
private XrSpace m_WorldLockSpaceOriginOnHead = 0, m_WorldLockSpaceOriginOnFloor = 0, m_HeadLockSpace = 0;
/// <summary>
/// The XrSpace of world lock space origin on head.
/// </summary>
public XrSpace WorldLockSpaceOriginOnHead
{
get { return m_WorldLockSpaceOriginOnHead; }
}
/// <summary>
/// The XrSpace of world lock space origin on floor.
/// </summary>
public XrSpace WorldLockSpaceOriginOnFloor
{
get { return m_WorldLockSpaceOriginOnFloor; }
}
/// <summary>
/// The XrSpace of head lock space.
/// </summary>
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;
}
}
/// <summary>
/// The current XR Session state.
/// </summary>
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;
/// <summary>
/// Helper function to get this feature' properties.
/// See <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystemProperties">xrGetSystemProperties</see>
/// </summary>
public XrResult 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;
/// <summary>
/// Enumerate available reference spaces
/// See <see href="https://registry.khronos.org/OpenXR/specs/1.0/man/html/xrEnumerateReferenceSpaces.html">xrEnumerateReferenceSpaces</see>
/// </summary>
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;
/// <summary>
/// Creates a reference space
/// See <see href="https://registry.khronos.org/OpenXR/specs/1.0/man/html/xrCreateReferenceSpace.html">xrCreateReferenceSpace</see>
/// </summary>
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;
/// <summary>
/// Destroys an XrSpace
/// See <see href="https://registry.khronos.org/OpenXR/specs/1.0/man/html/xrDestroySpace.html">xrDestroySpace</see>
/// </summary>
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_GetExternalSurfaceObj")]
public static extern IntPtr VIVEOpenXR_Compositionlayer_GetExternalSurfaceObj();
public IntPtr Compositionlayer_GetExternalSurfaceObj()
{
return VIVEOpenXR_Compositionlayer_GetExternalSurfaceObj();
}
[DllImportAttribute(ExtLib, EntryPoint = "compositionlayer_GetExternalSurfaceObj2")]
public static extern IntPtr VIVEOpenXR_Compositionlayer_GetExternalSurfaceObj2(int layerID);
public IntPtr Compositionlayer_GetExternalSurfaceObj2(int layerID)
{
return VIVEOpenXR_Compositionlayer_GetExternalSurfaceObj2(layerID);
}
[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, bool isExternal);
/// <summary>
/// Init composion layer.
/// </summary>
public int CompositionLayer_Init(uint textureWidth, uint textureHeight, GraphicsAPI graphicsAPI, bool isDynamic, bool isProtected, out uint imageCount, bool isExternal = false)
{
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, isExternal);
}
[DllImportAttribute(ExtLib, EntryPoint = "compositionlayer_GetTexture")]
public static extern IntPtr VIVEOpenXR_CompositionLayer_GetTexture(int layerID, out uint imageIndex);
/// <summary>
/// Get composition layer texture.
/// </summary>
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);
/// <summary>
/// release composition layer texture.
/// </summary>
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);
/// <summary>
/// destroy composition layer.
/// </summary>
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);
/// <summary>
/// submit compostion layer of type quad.
/// </summary>
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);
/// <summary>
/// get function address of composition layer.
/// </summary>
public XrResult CompositionLayer_GetFuncAddrs(XrInstance xrInstance, IntPtr xrGetInstanceProcAddrFuncPtr)
{
return VIVEOpenXR_CompositionLayer_GetFuncAddrs(xrInstance, xrGetInstanceProcAddrFuncPtr);
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b06faf09f93c35b4b83640fd9908b630
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
// Copyright HTC Corporation All Rights Reserved.
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;
/// <summary>
/// The extension of "XR_KHR_composition_layer_color_scale_bias" is enabled or not.
/// </summary>
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);
/// <summary>
/// Submit Compostion Layer Color Bias Settings to specific layer ID.
/// </summary>
public void Submit_CompositionLayerColorBias(XrCompositionLayerColorScaleBiasKHR colorBias, int layerID)
{
if (!ColorScaleBiasExtensionEnabled)
{
ERROR("Submit_CompositionLayerColorBias: " + kOpenXRColorScaleBiasExtensionString + " is not enabled.");
return;
}
VIVEOpenXR_Submit_CompositionLayerColorBias(colorBias, layerID);
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a5621f5c5156e7648a0c3a1fa86497a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,88 @@
// Copyright HTC Corporation All Rights Reserved.
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;
/// <summary>
/// The extension "XR_KHR_composition_layer_cylinder" is enabled or not.
/// </summary>
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);
/// <summary>
/// submit compostion layer of type cylinder.
/// </summary>
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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: abd96d069ecb9b243a69661e0bffdfab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
// Copyright HTC Corporation All Rights Reserved.
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 (Equirect)",
Desc = "Enable this feature to enable the Composition Layer Equirect Extension",
Company = "HTC",
DocumentationLink = "..\\Documentation",
OpenxrExtensionStrings = kOpenXRCylinderExtensionString,
Version = "1.0.0",
BuildTargetGroups = new[] { BuildTargetGroup.Android },
FeatureId = featureId
)]
#endif
public class ViveCompositionLayerEquirect : OpenXRFeature
{
const string LOG_TAG = "VIVE.OpenXR.ViveCompositionLayer.Equirect";
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.equirect";
private const string kOpenXRCylinderExtensionString = "XR_KHR_composition_layer_equirect XR_KHR_composition_layer_equirect2";
private bool m_EquirectExtensionEnabled = true;
/// <summary>
/// The extension "XR_KHR_composition_layer_equirect" is enabled or not.
/// </summary>
public bool EquirectExtensionEnabled
{
get { return m_EquirectExtensionEnabled; }
}
private bool m_Equirect2ExtensionEnabled = true;
/// <summary>
/// The extension "XR_KHR_composition_layer_equirect2" is enabled or not.
/// </summary>
public bool Equirect2ExtensionEnabled
{
get { return m_Equirect2ExtensionEnabled; }
}
#region OpenXR Life Cycle
protected override bool OnInstanceCreate(ulong xrInstance)
{
if (!OpenXRRuntime.IsExtensionEnabled("XR_KHR_composition_layer_equirect"))
{
WARNING("OnInstanceCreate() " + "XR_KHR_composition_layer_equirect" + " is NOT enabled.");
m_EquirectExtensionEnabled = false;
return false;
}
if (!OpenXRRuntime.IsExtensionEnabled("XR_KHR_composition_layer_equirect2"))
{
WARNING("OnInstanceCreate() " + "XR_KHR_composition_layer_equirect2" + " is NOT enabled.");
m_Equirect2ExtensionEnabled = false;
return false;
}
return true;
}
#endregion
#region Wrapper Functions
private const string ExtLib = "viveopenxr";
[DllImportAttribute(ExtLib, EntryPoint = "submit_CompositionLayerEquirect")]
public static extern void VIVEOpenXR_Submit_CompositionLayerEquirect(XrCompositionLayerEquirectKHR equirect, LayerType layerType, uint compositionDepth, int layerID);
/// <summary>
/// submit compostion layer of type equirect.
/// </summary>
public void Submit_CompositionLayerEquirect(XrCompositionLayerEquirectKHR equirect, LayerType layerType, uint compositionDepth, int layerID)
{
if (!EquirectExtensionEnabled)
{
ERROR("Submit_CompositionLayerEquirect: " + "XR_KHR_composition_layer_equirect" + " is NOT enabled.");
}
VIVEOpenXR_Submit_CompositionLayerEquirect(equirect, layerType, compositionDepth, layerID);
}
[DllImportAttribute(ExtLib, EntryPoint = "submit_CompositionLayerEquirect2")]
public static extern void VIVEOpenXR_Submit_CompositionLayerEquirect2(XrCompositionLayerEquirect2KHR equirect2, LayerType layerType, uint compositionDepth, int layerID);
/// <summary>
/// submit compostion layer of type equirect2.
/// </summary>
public void Submit_CompositionLayerEquirect2(XrCompositionLayerEquirect2KHR equirect2, LayerType layerType, uint compositionDepth, int layerID)
{
if (!Equirect2ExtensionEnabled)
{
ERROR("Submit_CompositionLayerEquirect2: " + "XR_KHR_composition_layer_equirect2" + " is NOT enabled.");
}
VIVEOpenXR_Submit_CompositionLayerEquirect2(equirect2, layerType, compositionDepth, layerID);
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ec826264ff4d75d4081f2ca472a3e083
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,203 @@
// Copyright HTC Corporation All Rights Reserved.
using UnityEditor;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
using UnityEngine;
using System;
using System.Runtime.InteropServices;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
#endif
namespace VIVE.OpenXR.CompositionLayer
{
#if UNITY_EDITOR
[OpenXRFeature(UiName = "VIVE XR Composition Layer (Extra Settings) (Beta)",
Desc = "Enable this feature to use the Composition Layer Extra Settings.",
Company = "HTC",
DocumentationLink = "..\\Documentation",
OpenxrExtensionStrings = kOpenxrExtensionStrings,
Version = "1.0.0",
BuildTargetGroups = new[] { BuildTargetGroup.Android },
FeatureId = featureId
)]
#endif
public class ViveCompositionLayerExtraSettings : OpenXRFeature
{
const string LOG_TAG = "VIVE.OpenXR.ViveCompositionLayer.ExtraSettings";
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>
/// Settings Editor Enable Sharpening or Not.
/// </summary>
public bool SettingsEditorEnableSharpening = false;
/// <summary>
/// Support Sharpening or Not.
/// </summary>
public bool supportSharpening = false;
/// <summary>
/// Settings Editor Sharpening Mode
/// </summary>
public XrSharpeningModeHTC SettingsEditorSharpeningMode = XrSharpeningModeHTC.FAST;
/// <summary>
/// Settings Editor Sharpening Levell
/// </summary>
[Range(0.0f, 1.0f)]
public float SettingsEditorSharpeningLevel = 1.0f;
/// <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.extrasettings";
/// <summary>
/// OpenXR specification.
/// </summary>
public const string kOpenxrExtensionStrings = "XR_HTC_composition_layer_extra_settings";
#region OpenXR Life Cycle
private bool m_XrInstanceCreated = false;
/// <summary>
/// The XR instance is created or not.
/// </summary>
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 true;
}
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;
/// <summary>
/// The XR session is created or not.
/// </summary>
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;
/// <summary>
/// The XR session is ending or not.
/// </summary>
public bool XrSessionEnding
{
get { return m_XrSessionEnding; }
}
protected override void OnSessionBegin(ulong xrSession)
{
m_XrSessionEnding = false;
DEBUG("OnSessionBegin() " + m_XrSession);
//enable Sharpening
if (OpenXRRuntime.IsExtensionEnabled("XR_HTC_composition_layer_extra_settings"))
{
ViveCompositionLayer_UpdateSystemProperties(m_XrInstance, m_XrSystemId);
supportSharpening = ViveCompositionLayer_IsSupportSharpening();
if (supportSharpening && SettingsEditorEnableSharpening)
{
EnableSharpening(SettingsEditorSharpeningMode, SettingsEditorSharpeningLevel);
}
}
}
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);
}
#endregion
#region Wrapper Functions
private const string ExtLib = "viveopenxr";
[DllImportAttribute(ExtLib, EntryPoint = "viveCompositionLayer_UpdateSystemProperties")]
private static extern int VIVEOpenXR_ViveCompositionLayer_UpdateSystemProperties(XrInstance instance, XrSystemId system_id);
private int ViveCompositionLayer_UpdateSystemProperties(XrInstance instance, XrSystemId system_id)
{
return VIVEOpenXR_ViveCompositionLayer_UpdateSystemProperties(instance, system_id);
}
[DllImportAttribute(ExtLib, EntryPoint = "viveCompositionLayer_IsSupportSharpening")]
private static extern bool VIVEOpenXR_ViveCompositionLayer_IsSupportSharpening();
private bool ViveCompositionLayer_IsSupportSharpening()
{
return VIVEOpenXR_ViveCompositionLayer_IsSupportSharpening();
}
[DllImportAttribute(ExtLib, EntryPoint = "viveCompositionLayer_enableSharpening")]
private static extern int VIVEOpenXR_ViveCompositionLayer_enableSharpening(XrSharpeningModeHTC sharpeningMode, float sharpeningLevel);
/// <summary>
/// Enable the sharpening setting applying to the projection layer.
/// </summary>
/// <param name="sharpeningMode">The sharpening mode in <see cref="XrSharpeningModeHTC"/>.</param>
/// <param name="sharpeningLevel">The sharpening level in float [0, 1].</param>
/// <returns>True for success.</returns>
public bool EnableSharpening(XrSharpeningModeHTC sharpeningMode, float sharpeningLevel)
{
return (VIVEOpenXR_ViveCompositionLayer_enableSharpening(sharpeningMode, sharpeningLevel) == 0);
}
[DllImportAttribute(ExtLib, EntryPoint = "viveCompositionLayer_disableSharpening")]
private static extern int VIVEOpenXR_ViveCompositionLayer_DisableSharpening();
/// <summary>
/// Disable the sharpening setting on the projection layer.
/// </summary>
/// <returns>True for success</returns>
public bool DisableSharpening()
{
return (VIVEOpenXR_ViveCompositionLayer_DisableSharpening() == 0);
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f26de592e4135874baf6e64cc94183be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,583 @@
// Copyright HTC Corporation All Rights Reserved.
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 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 XrCompositionLayerEquirectKHR
{
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 XrVector2f scale;
public XrVector2f bias;
}
[StructLayout(LayoutKind.Sequential)]
public struct XrCompositionLayerEquirect2KHR
{
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 centralHorizontalAngle;
public float upperVerticalAngle;
public float lowerVerticalAngle;
}
[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;
}
[StructLayout(LayoutKind.Sequential)]
public struct XrCompositionLayerSharpeningSettingHTC
{
public XrStructureType type;
public IntPtr next;
public XrSharpeningModeHTC mode;
public float sharpeningLevel;
}
[StructLayout(LayoutKind.Sequential)]
public struct XrCompositionLayerSuperSamplingSettingHTC
{
public XrStructureType type;
public IntPtr next;
public XrSuperSamplingModeHTC mode;
}
public enum XrSharpeningModeHTC
{
FAST = 0,
NORMAL = 1,
QUALITY = 2,
AUTOMATIC = 3,
}
public enum XrSuperSamplingModeHTC
{
FAST = 0,
NORMAL = 1,
QUALITY = 2,
AUTOMATIC = 3,
}
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
}
/// <summary>
/// An application can create an <see cref="XrPassthroughHTC">XrPassthroughHTC</see> handle by calling <see cref="ViveCompositionLayerHelper.xrCreatePassthroughHTC">xrCreatePassthroughHTC</see>. The returned passthrough handle can be subsequently used in API calls.
/// </summary>
public struct XrPassthroughHTC : IEquatable<UInt64>
{
private readonly UInt64 value;
public XrPassthroughHTC(UInt64 u)
{
value = u;
}
public static implicit operator UInt64(XrPassthroughHTC equatable)
{
return equatable.value;
}
public static implicit operator XrPassthroughHTC(UInt64 u)
{
return new XrPassthroughHTC(u);
}
public bool Equals(XrPassthroughHTC other)
{
return value == other.value;
}
public bool Equals(UInt64 other)
{
return value == other;
}
public override bool Equals(object obj)
{
return obj is XrPassthroughHTC && Equals((XrPassthroughHTC)obj);
}
public override int GetHashCode()
{
return value.GetHashCode();
}
public override string ToString()
{
return value.ToString();
}
public static bool operator ==(XrPassthroughHTC a, XrPassthroughHTC b) { return a.Equals(b); }
public static bool operator !=(XrPassthroughHTC a, XrPassthroughHTC b) { return !a.Equals(b); }
public static bool operator >=(XrPassthroughHTC a, XrPassthroughHTC b) { return a.value >= b.value; }
public static bool operator <=(XrPassthroughHTC a, XrPassthroughHTC b) { return a.value <= b.value; }
public static bool operator >(XrPassthroughHTC a, XrPassthroughHTC b) { return a.value > b.value; }
public static bool operator <(XrPassthroughHTC a, XrPassthroughHTC b) { return a.value < b.value; }
public static XrPassthroughHTC operator +(XrPassthroughHTC a, XrPassthroughHTC b) { return a.value + b.value; }
public static XrPassthroughHTC operator -(XrPassthroughHTC a, XrPassthroughHTC b) { return a.value - b.value; }
public static XrPassthroughHTC operator *(XrPassthroughHTC a, XrPassthroughHTC b) { return a.value * b.value; }
public static XrPassthroughHTC operator /(XrPassthroughHTC a, XrPassthroughHTC b)
{
if (b.value == 0)
{
throw new DivideByZeroException();
}
return a.value / b.value;
}
}
/// <summary>
/// The XrPassthroughFormHTC enumeration identifies the form of the passthrough, presenting the passthrough fill the full screen or project onto a specified mesh.
/// </summary>
public enum XrPassthroughFormHTC
{
/// <summary>
/// Presents the passthrough with full of the entire screen..
/// </summary>
XR_PASSTHROUGH_FORM_PLANAR_HTC = 0,
/// <summary>
/// Presents the passthrough projecting onto a custom mesh.
/// </summary>
XR_PASSTHROUGH_FORM_PROJECTED_HTC = 1,
};
/// <summary>
/// The XrPassthroughCreateInfoHTC structure describes the information to create an <see cref="XrPassthroughCreateInfoHTC">XrPassthroughCreateInfoHTC</see> handle.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct XrPassthroughCreateInfoHTC
{
/// <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>
/// The form specifies the form of passthrough.
/// </summary>
public XrPassthroughFormHTC form;
/// <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 XrPassthroughCreateInfoHTC(XrStructureType in_type, IntPtr in_next, XrPassthroughFormHTC in_form)
{
type = in_type;
next = in_next;
form = in_form;
}
};
/// <summary>
/// The application can specify the XrPassthroughColorHTC to adjust the alpha value of the passthrough. The range is between 0.0f and 1.0f, 1.0f means opaque.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct XrPassthroughColorHTC
{
/// <summary>
/// The XrStructureType of this structure.
/// </summary>
public XrStructureType type;
/// <summary>
/// Next is NULL or a pointer to the next structure in a structure chain, such as XrPassthroughMeshTransformInfoHTC.
/// </summary>
public IntPtr next;
/// <summary>
/// The alpha value of the passthrough in the range [0, 1].
/// </summary>
public float alpha;
public XrPassthroughColorHTC(XrStructureType in_type, IntPtr in_next, float in_alpha)
{
type = in_type;
next = in_next;
alpha = in_alpha;
}
};
/// <summary>
/// A pointer to XrCompositionLayerPassthroughHTC may be submitted in xrEndFrame as a pointer to the base structure XrCompositionLayerBaseHeader, in the desired layer order, to request the runtime to composite a passthrough layer into the final frame output.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct XrCompositionLayerPassthroughHTC
{
/// <summary>
/// The XrStructureType of this structure.
/// </summary>
public XrStructureType type;
/// <summary>
/// Next is NULL or a pointer to the next structure in a structure chain, such as XrPassthroughMeshTransformInfoHTC.
/// </summary>
public IntPtr next;
/// <summary>
/// A bitmask of XrCompositionLayerFlagBits describing flags to apply to the layer.
/// </summary>
public XrCompositionLayerFlags layerFlags;
/// <summary>
/// The XrSpace that specifies the layers space - must be XR_NULL_HANDLE.
/// </summary>
public XrSpace space;
/// <summary>
/// The XrPassthroughHTC previously created by xrCreatePassthroughHTC.
/// </summary>
public XrPassthroughHTC passthrough;
/// <summary>
/// The XrPassthroughColorHTC describing the color information with the alpha value of the passthrough layer.
/// </summary>
public XrPassthroughColorHTC color;
public XrCompositionLayerPassthroughHTC(XrStructureType in_type, IntPtr in_next, XrCompositionLayerFlags in_layerFlags,
XrSpace in_space, XrPassthroughHTC in_passthrough, XrPassthroughColorHTC in_color)
{
type = in_type;
next = in_next;
layerFlags = in_layerFlags;
space = in_space;
passthrough = in_passthrough;
color = in_color;
}
};
/// <summary>
/// The XrPassthroughMeshTransformInfoHTC structure describes the mesh and transformation.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct XrPassthroughMeshTransformInfoHTC
{
/// <summary>
/// The XrStructureType of this structure.
/// </summary>
public XrStructureType type;
/// <summary>
/// Next is NULL or a pointer to the next structure in a structure chain.
/// </summary>
public IntPtr next;
/// <summary>
/// The count of vertices array in the mesh.
/// </summary>
public UInt32 vertexCount;
/// <summary>
/// An array of XrVector3f. The size of the array must be equal to vertexCount.
/// </summary>
public XrVector3f[] vertices;
/// <summary>
/// The count of indices array in the mesh.
/// </summary>
public UInt32 indexCount;
/// <summary>
/// An array of triangle indices. The size of the array must be equal to indexCount.
/// </summary>
public UInt32[] indices;
/// <summary>
/// The XrSpace that defines the projected passthrough's base space for transformations.
/// </summary>
public XrSpace baseSpace;
/// <summary>
/// The XrTime that defines the time at which the transform is applied.
/// </summary>
public XrTime time;
/// <summary>
/// The XrPosef that defines the pose of the mesh
/// </summary>
public XrPosef pose;
/// <summary>
/// The XrVector3f that defines the scale of the mesh
/// </summary>
public XrVector3f scale;
public XrPassthroughMeshTransformInfoHTC(XrStructureType in_type, IntPtr in_next, UInt32 in_vertexCount,
XrVector3f[] in_vertices, UInt32 in_indexCount, UInt32[] in_indices, XrSpace in_baseSpace, XrTime in_time,
XrPosef in_pose, XrVector3f in_scale)
{
type = in_type;
next = in_next;
vertexCount = in_vertexCount;
vertices = in_vertices;
indexCount = in_indexCount;
indices = in_indices;
baseSpace = in_baseSpace;
time = in_time;
pose = in_pose;
scale = in_scale;
}
};
public static class ViveCompositionLayerHelper
{
/// <summary>
/// The delegate function of <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreatePassthroughHTC">xrCreatePassthroughHTC</see>.
/// </summary>
/// <param name="session">An <see cref="XrSession">XrSession</see> in which the passthrough will be active.</param>
/// <param name="createInfo">createInfo is a pointer to an <see cref="XrPassthroughCreateInfoHTC">XrPassthroughCreateInfoHTC</see> structure containing information about how to create the passthrough.</param>
/// <param name="passthrough">passthrough is a pointer to a handle in which the created <see cref="XrPassthroughHTC">XrPassthroughHTC</see> is returned.</param>
/// <returns>XR_SUCCESS for success.</returns>
public delegate XrResult xrCreatePassthroughHTCDelegate(
XrSession session,
XrPassthroughCreateInfoHTC createInfo,
out XrPassthroughHTC passthrough);
/// <summary>
/// The delegate function of <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroyPassthroughHTC">xrDestroyFacialTrackerHTC</see>.
/// </summary>
/// <param name="passthrough">passthrough is the <see cref="XrPassthroughHTC">XrPassthroughHTC</see> to be destroyed..</param>
/// <returns>XR_SUCCESS for success.</returns>
public delegate XrResult xrDestroyPassthroughHTCDelegate(
XrPassthroughHTC passthrough);
// 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7dfb147f98026e44786fda53bb2aeb18
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,943 @@
// Copyright HTC Corporation All Rights Reserved.
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) (Deprecated)",
Desc = "Enable this feature to use the HTC Passthrough feature.",
Company = "HTC",
DocumentationLink = "..\\Documentation",
OpenxrExtensionStrings = kOpenxrExtensionStrings,
Version = "1.0.0",
BuildTargetGroups = new[] { BuildTargetGroup.Android ,BuildTargetGroup.Standalone},
FeatureId = featureId
)]
#endif
[Obsolete("This class is deprecated. Please use VivePassthrough instead.")]
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>();
/// <summary>
/// The List of passthrough ID.
/// </summary>
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";
/// <summary>
/// The extension string.
/// </summary>
public const string kOpenxrExtensionStrings = "XR_HTC_passthrough";
private bool m_HTCPassthroughExtensionEnabled = true;
/// <summary>
/// The HTC Passthrough extension is enabled or not.
/// </summary>
public bool HTCPassthroughExtensionEnabled
{
get { return m_HTCPassthroughExtensionEnabled; }
}
#region OpenXR Life Cycle
private bool m_XrInstanceCreated = false;
/// <summary>
/// The XR instance is created or not.
/// </summary>
public bool XrInstanceCreated
{
get { return m_XrInstanceCreated; }
}
#if UNITY_STANDALONE
private static IntPtr xrGetInstanceProcAddr_prev;
private static IntPtr XrEndFrame_prev;
private static IntPtr XrWaitFrame_prev;
private static List<IntPtr> layerListOrigin = new List<IntPtr>();
private static List<IntPtr> layerListModified = new List<IntPtr>();
private static IntPtr layersModified = Marshal.AllocHGlobal((int)(Marshal.SizeOf(typeof(IntPtr)) * 30)); //Preallocate a layer buffer with sufficient size and reuse it for each frame.
protected override IntPtr HookGetInstanceProcAddr(IntPtr func)
{
UnityEngine.Debug.Log("EXT: registering our own xrGetInstanceProcAddr");
xrGetInstanceProcAddr_prev = func;
return Marshal.GetFunctionPointerForDelegate(Intercept_xrGetInstanceProcAddr);
}
[MonoPInvokeCallback(typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate))]
private static XrResult InterceptXrEndFrame_xrGetInstanceProcAddr(XrInstance instance, string name, out IntPtr function)
{
if (xrGetInstanceProcAddr_prev == null || xrGetInstanceProcAddr_prev == IntPtr.Zero)
{
UnityEngine.Debug.LogError("xrGetInstanceProcAddr_prev is null");
function = IntPtr.Zero;
return XrResult.XR_ERROR_VALIDATION_FAILURE;
}
// Get delegate of old xrGetInstanceProcAddr.
var xrGetProc = Marshal.GetDelegateForFunctionPointer<OpenXRHelper.xrGetInstanceProcAddrDelegate>(xrGetInstanceProcAddr_prev);
XrResult result = xrGetProc(instance, name, out function);
if (name == "xrEndFrame")
{
XrEndFrame_prev = function;
m_intercept_xrEndFrame = intercepted_xrEndFrame;
function = Marshal.GetFunctionPointerForDelegate(m_intercept_xrEndFrame); ;
UnityEngine.Debug.Log("Getting xrEndFrame func");
}
if (name == "xrWaitFrame")
{
XrWaitFrame_prev = function;
m_intercept_xrWaitFrame = intercepted_xrWaitFrame;
function = Marshal.GetFunctionPointerForDelegate(m_intercept_xrWaitFrame); ;
UnityEngine.Debug.Log("Getting xrWaitFrame func");
}
return result;
}
[MonoPInvokeCallback(typeof(OpenXRHelper.xrEndFrameDelegate))]
private static XrResult intercepted_xrEndFrame(XrSession session, ref XrFrameEndInfo frameEndInfo)
{
XrResult res;
// Get delegate of prev xrEndFrame.
var xrEndFrame = Marshal.GetDelegateForFunctionPointer<OpenXRHelper.xrEndFrameDelegate>(XrEndFrame_prev);
layerListOrigin.Clear();
uint layerCount = frameEndInfo.layerCount;
IntPtr layers = frameEndInfo.layers;
for (int i = 0; i < layerCount; i++)
{
IntPtr ptr = Marshal.ReadIntPtr(layers, i * Marshal.SizeOf(typeof(IntPtr)));
XrCompositionLayerBaseHeader header = (XrCompositionLayerBaseHeader)Marshal.PtrToStructure(ptr, typeof(XrCompositionLayerBaseHeader));
layerListOrigin.Add(ptr);
}
List<IntPtr> layerListNew;
if (layerListModified.Count != 0)
{
layerListNew = new List<IntPtr>(layerListModified);
}
else
{
layerListNew = new List<IntPtr>(layerListOrigin);
}
for (int i = 0; i < layerListNew.Count; i++)
{
Marshal.WriteIntPtr(layersModified, i * Marshal.SizeOf(typeof(IntPtr)), layerListNew[i]);
}
frameEndInfo.layers = layersModified;
frameEndInfo.layerCount = (uint)layerListNew.Count;
res = xrEndFrame(session, ref frameEndInfo);
return res;
}
private static XrFrameWaitInfo m_frameWaitInfo;
private static XrFrameState m_frameState;
[MonoPInvokeCallback(typeof(OpenXRHelper.xrWaitFrameDelegate))]
private static int intercepted_xrWaitFrame(ulong session, ref XrFrameWaitInfo frameWaitInfo, ref XrFrameState frameState)
{
var xrWaitFrame = Marshal.GetDelegateForFunctionPointer<OpenXRHelper.xrWaitFrameDelegate>(XrWaitFrame_prev);
int res = xrWaitFrame(session, ref frameWaitInfo, ref frameState);
m_frameWaitInfo = frameWaitInfo;
m_frameState = frameState;
return res;
}
public void GetOriginEndFrameLayerList(out List<IntPtr> layers)
{
layers = new List<IntPtr>(layerListOrigin);
}
public void SubmitLayers(List<IntPtr> layers)
{
layerListModified = new List<IntPtr>(layers);
//UnityEngine.Debug.Log("####Update submit end " + layerListModified.Count);
}
public XrFrameState GetFrameState()
{
return m_frameState;
}
#endif
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;
/// <summary>
/// The XR session is created or not.
/// </summary>
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;
/// <summary>
/// The XR session is ending or not.
/// </summary>
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);
}
/// <summary>
/// The delegate of Passthrough Session Destroy.
/// </summary>
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);
#if UNITY_ANDROID
//Notify that all passthrough layers should be destroyed
List<int> currentPassthroughIDs = PassthroughIDList;
foreach (int passthroughID in currentPassthroughIDs)
{
OnPassthroughSessionDestroyDelegate OnPassthroughSessionDestroyHandler = OnPassthroughSessionDestroyHandlerDictionary[passthroughID];
OnPassthroughSessionDestroyHandler?.Invoke(passthroughID);
}
#endif
#if UNITY_STANDALONE
//Notify that all passthrough layers should be destroyed
List<XrPassthroughHTC> currentPassthroughs = PassthroughList;
foreach (XrPassthroughHTC passthrough in currentPassthroughs)
{
DestroyPassthroughHTC(passthrough);
}
#endif
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;
}
}
/// <summary>
/// The current XR session state.
/// </summary>
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;
#if UNITY_STANDALONE
OpenXRHelper.xrGetInstanceProcAddrDelegate Intercept_xrGetInstanceProcAddr =
new OpenXRHelper.xrGetInstanceProcAddrDelegate(InterceptXrEndFrame_xrGetInstanceProcAddr);
#endif
private static OpenXRHelper.xrEndFrameDelegate m_intercept_xrEndFrame;
private static OpenXRHelper.xrWaitFrameDelegate m_intercept_xrWaitFrame;
/// xrGetSystemProperties
OpenXRHelper.xrGetSystemPropertiesDelegate xrGetSystemProperties;
/// <summary>
/// Helper function to get this feature' properties.
/// See <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystemProperties">xrGetSystemProperties</see>
/// </summary>
public XrResult 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;
/// <summary>
/// Creates a reference space
/// See <see href="https://registry.khronos.org/OpenXR/specs/1.0/man/html/xrCreateReferenceSpace.html">xrCreateReferenceSpace</see>
/// </summary>
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;
}
#if UNITY_STANDALONE
private List<XrPassthroughHTC> passthroughList = new List<XrPassthroughHTC>();
public List<XrPassthroughHTC> PassthroughList { get { return new List<XrPassthroughHTC>(passthroughList); } }
ViveCompositionLayerHelper.xrCreatePassthroughHTCDelegate xrCreatePassthroughHTC;
public XrResult CreatePassthroughHTC(XrPassthroughCreateInfoHTC createInfo, out XrPassthroughHTC passthrough)
{
if (!m_XrSessionCreated)
{
ERROR("CreatePassthroughHTC() XR_ERROR_SESSION_LOST.");
passthrough = 0;
return XrResult.XR_ERROR_SESSION_LOST;
}
if (!m_XrInstanceCreated)
{
ERROR("CreatePassthroughHTC() XR_ERROR_INSTANCE_LOST.");
passthrough = 0;
return XrResult.XR_ERROR_INSTANCE_LOST;
}
XrResult res = xrCreatePassthroughHTC(m_XrSession, createInfo, out passthrough);
if (res == XrResult.XR_SUCCESS)
{
passthroughList.Add(passthrough);
passthroughIDList.Add(((int)(ulong)passthrough));
}
else
ERROR("CreatePassthroughHTC() "+res);
return res;
}
ViveCompositionLayerHelper.xrDestroyPassthroughHTCDelegate xrDestroyPassthroughHTC;
public XrResult DestroyPassthroughHTC(XrPassthroughHTC passthrough)
{
DEBUG("Entry");
XrResult res = xrDestroyPassthroughHTC(passthrough);
if (res == XrResult.XR_SUCCESS)
{
passthroughList.Remove(passthrough);
passthroughIDList.Remove(((int)(ulong)passthrough));
}
return res;
}
/// <summary>
/// According to XRInputSubsystem's tracking origin mode, return the corresponding XrSpace.
/// </summary>
/// <returns></returns>
public XrSpace GetTrackingSpace()
{
var s = GetCurrentAppSpace();
Debug.Log("VivePassthrough GetTrackingSpace() s=" + s);
return s;
}
#endif
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 UNITY_STANDALONE
/// xrCreatePassthroughHTC
if (XrGetInstanceProcAddr(xrInstance, "xrCreatePassthroughHTC", out funcPtr) == XrResult.XR_SUCCESS)
{
if (funcPtr != IntPtr.Zero)
{
DEBUG("Get function pointer of xrCreatePassthroughHTC.");
xrCreatePassthroughHTC = Marshal.GetDelegateForFunctionPointer(
funcPtr,
typeof(ViveCompositionLayerHelper.xrCreatePassthroughHTCDelegate)) as ViveCompositionLayerHelper.xrCreatePassthroughHTCDelegate;
}
}
else
{
ERROR("xrCreatePassthroughHTC");
return false;
}
/// xrCreatePassthroughHTC
if (XrGetInstanceProcAddr(xrInstance, "xrDestroyPassthroughHTC", out funcPtr) == XrResult.XR_SUCCESS)
{
if (funcPtr != IntPtr.Zero)
{
DEBUG("Get function pointer of xrDestroyPassthroughHTC.");
xrDestroyPassthroughHTC = Marshal.GetDelegateForFunctionPointer(
funcPtr,
typeof(ViveCompositionLayerHelper.xrDestroyPassthroughHTCDelegate)) as ViveCompositionLayerHelper.xrDestroyPassthroughHTCDelegate;
}
}
else
{
ERROR("xrDestroyPassthroughHTC");
return false;
}
#endif
#if UNITY_ANDROID
if (HTCPassthrough_GetFuncAddrs(xrInstance, xrGetInstanceProcAddr) == XrResult.XR_SUCCESS)
{
DEBUG("Get function pointers in native.");
}
else
{
ERROR("HTCPassthrough_GetFuncAddrs");
return false;
}
#endif
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);
/// <summary>
/// Create Passthrough.
/// </summary>
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);
/// <summary>
/// Set Passthough Alpha.
/// </summary>
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);
/// <summary>
/// Set Passthough Layer Type.
/// </summary>
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);
/// <summary>
/// Set Passthough Mesh.
/// </summary>
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);
/// <summary>
/// Set Passthough Mesh Transform.
/// </summary>
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);
/// <summary>
/// Set Passthough Mesh Transform Space.
/// </summary>
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);
/// <summary>
/// Set Passthough Mesh Transform Position.
/// </summary>
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);
/// <summary>
/// Set Passthough Mesh Transform orientation.
/// </summary>
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);
/// <summary>
/// Set Passthough Mesh Transform scale.
/// </summary>
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);
/// <summary>
/// Destroy Passthough.
/// </summary>
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
/// <summary>
/// Helper function to get XrSpace from space type.
/// </summary>
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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0e78888b9743d564482402fe284c9126
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
// Copyright HTC Corporation All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace VIVE.OpenXR.CompositionLayer.Passthrough
{
[Obsolete("This enumeration is deprecated. Please use XrStructureType instead.")]
//[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,
}
[Obsolete("This enumeration is deprecated. Please use VIVE.OpenXR.Passthrough.PassthroughLayerForm instead.")]
public enum PassthroughLayerForm
{
///<summary> Fullscreen Passthrough Form</summary>
Planar = 0,
///<summary> Projected Passthrough Form</summary>
Projected = 1
}
[Obsolete("This enumeration is deprecated. Please use VIVE.OpenXR.Passthrough.ProjectedPassthroughSpaceType instead.")]
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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 58a0974face1c1b448dab924ce82c5ee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: