上传YomovSDK
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,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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b06faf09f93c35b4b83640fd9908b630
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5621f5c5156e7648a0c3a1fa86497a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abd96d069ecb9b243a69661e0bffdfab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec826264ff4d75d4081f2ca472a3e083
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f26de592e4135874baf6e64cc94183be
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 layer’s 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7dfb147f98026e44786fda53bb2aeb18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e78888b9743d564482402fe284c9126
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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