version 2.0.0
This commit is contained in:
@@ -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:
|
||||
Reference in New Issue
Block a user