// Copyright HTC Corporation All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
namespace VIVE.OpenXR.Passthrough
{
///
/// The forms of passthrough layer.
///
public enum PassthroughLayerForm
{
/// Fullscreen Passthrough Form
Planar = 0,
/// Projected Passthrough Form
Projected = 1
}
///
/// The types of passthrough space.
///
public enum ProjectedPassthroughSpaceType
{
///
/// XR_REFERENCE_SPACE_TYPE_VIEW at (0,0,0) with orientation (0,0,0,1)
///
Headlock = 0,
///
/// 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)
///
///
Worldlock = 1
}
// -------------------- 12.88. XR_HTC_passthrough --------------------
#region New Object Types
///
/// An application can create an XrPassthroughHTC handle by calling xrCreatePassthroughHTC. The returned passthrough handle can be subsequently used in API calls.
///
public struct XrPassthroughHTC : IEquatable
{
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;
}
}
#endregion
#region New Enums
///
/// The XrPassthroughFormHTC enumeration identifies the form of the passthrough, presenting the passthrough fill the full screen or project onto a specified mesh.
///
public enum XrPassthroughFormHTC
{
///
/// Presents the passthrough with full of the entire screen..
///
XR_PASSTHROUGH_FORM_PLANAR_HTC = 0,
///
/// Presents the passthrough projecting onto a custom mesh.
///
XR_PASSTHROUGH_FORM_PROJECTED_HTC = 1,
};
#endregion
#region New Structures
///
/// The XrPassthroughCreateInfoHTC structure describes the information to create an XrPassthroughCreateInfoHTC handle.
///
[StructLayout(LayoutKind.Sequential)]
public struct XrPassthroughCreateInfoHTC
{
///
/// The XrStructureType of this structure.
///
public XrStructureType type;
///
/// NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
///
public IntPtr next;
///
/// The form specifies the form of passthrough.
///
public XrPassthroughFormHTC form;
/// The XrStructureType of this structure.
/// NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
/// An XrFacialTrackingTypeHTC which describes which type of facial tracking should be used for this handle.
public XrPassthroughCreateInfoHTC(XrStructureType in_type, IntPtr in_next, XrPassthroughFormHTC in_form)
{
type = in_type;
next = in_next;
form = in_form;
}
};
///
/// 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.
///
[StructLayout(LayoutKind.Sequential)]
public struct XrPassthroughColorHTC
{
///
/// The XrStructureType of this structure.
///
public XrStructureType type;
///
/// Next is NULL or a pointer to the next structure in a structure chain, such as XrPassthroughMeshTransformInfoHTC.
///
public IntPtr next;
///
/// The alpha value of the passthrough in the range [0, 1].
///
public float alpha;
public XrPassthroughColorHTC(XrStructureType in_type, IntPtr in_next, float in_alpha)
{
type = in_type;
next = in_next;
alpha = in_alpha;
}
};
///
/// The XrPassthroughMeshTransformInfoHTC structure describes the mesh and transformation.
///
[StructLayout(LayoutKind.Sequential)]
public struct XrPassthroughMeshTransformInfoHTC
{
///
/// The XrStructureType of this structure.
///
public XrStructureType type;
///
/// Next is NULL or a pointer to the next structure in a structure chain.
///
public IntPtr next;
///
/// The count of vertices array in the mesh.
///
public UInt32 vertexCount;
///
/// An array of XrVector3f. The size of the array must be equal to vertexCount.
///
public XrVector3f[] vertices;
///
/// The count of indices array in the mesh.
///
public UInt32 indexCount;
///
/// An array of triangle indices. The size of the array must be equal to indexCount.
///
public UInt32[] indices;
///
/// The XrSpace that defines the projected passthrough's base space for transformations.
///
public XrSpace baseSpace;
///
/// The XrTime that defines the time at which the transform is applied.
///
public XrTime time;
///
/// The XrPosef that defines the pose of the mesh
///
public XrPosef pose;
///
/// The XrVector3f that defines the scale of the mesh
///
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;
}
};
///
/// 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.
///
[StructLayout(LayoutKind.Sequential)]
public struct XrCompositionLayerPassthroughHTC
{
///
/// The XrStructureType of this structure.
///
public XrStructureType type;
///
/// Next is NULL or a pointer to the next structure in a structure chain, such as XrPassthroughMeshTransformInfoHTC.
///
public IntPtr next;
///
/// A bitmask of XrCompositionLayerFlagBits describing flags to apply to the layer.
///
public XrCompositionLayerFlags layerFlags;
///
/// The XrSpace that specifies the layerˇ¦s space - must be XR_NULL_HANDLE.
///
public XrSpace space;
///
/// The XrPassthroughHTC previously created by xrCreatePassthroughHTC.
///
public XrPassthroughHTC passthrough;
///
/// The XrPassthroughColorHTC describing the color information with the alpha value of the passthrough layer.
///
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;
}
};
[StructLayout(LayoutKind.Sequential)]
public struct XrPassthroughConfigurationBaseHeaderHTC
{
public XrStructureType type;
public IntPtr next;
};
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct XrPassthroughConfigurationImageRateHTC
{
public XrStructureType type;
public IntPtr next;
public float srcImageRate;
public float dstImageRate;
};
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct XrPassthroughConfigurationImageQualityHTC
{
public XrStructureType type;
public IntPtr next;
public float scale;
};
[StructLayout(LayoutKind.Sequential)]
public struct XrEventDataPassthroughConfigurationImageRateChangedHTC
{
public XrStructureType type;
public IntPtr next;
public XrPassthroughConfigurationImageRateHTC fromImageRate;
public XrPassthroughConfigurationImageRateHTC toImageRate;
public XrEventDataPassthroughConfigurationImageRateChangedHTC(XrStructureType in_type, IntPtr in_next, XrPassthroughConfigurationImageRateHTC in_fromImageRate, XrPassthroughConfigurationImageRateHTC in_toImageRate)
{
type = in_type;
next = in_next;
fromImageRate = in_fromImageRate;
toImageRate = in_toImageRate;
}
public static XrEventDataPassthroughConfigurationImageRateChangedHTC identity
{
get
{
return new XrEventDataPassthroughConfigurationImageRateChangedHTC(
XrStructureType.XR_TYPE_EVENT_DATA_PASSTHROUGH_CONFIGURATION_IMAGE_RATE_CHANGED_HTC,
IntPtr.Zero,
new XrPassthroughConfigurationImageRateHTC { type = XrStructureType.XR_TYPE_PASSTHROUGH_CONFIGURATION_IMAGE_RATE_HTC, next = IntPtr.Zero },
new XrPassthroughConfigurationImageRateHTC { type = XrStructureType.XR_TYPE_PASSTHROUGH_CONFIGURATION_IMAGE_RATE_HTC, next = IntPtr.Zero }); // user is default present
}
}
public static bool Get(XrEventDataBuffer eventDataBuffer, out XrEventDataPassthroughConfigurationImageRateChangedHTC eventDataPassthroughConfigurationImageRate)
{
eventDataPassthroughConfigurationImageRate = identity;
if (eventDataBuffer.type == XrStructureType.XR_TYPE_EVENT_DATA_PASSTHROUGH_CONFIGURATION_IMAGE_RATE_CHANGED_HTC)
{
eventDataPassthroughConfigurationImageRate.next = eventDataBuffer.next;
eventDataPassthroughConfigurationImageRate.fromImageRate.type = (XrStructureType)BitConverter.ToUInt32(eventDataBuffer.varying, 0);
eventDataPassthroughConfigurationImageRate.fromImageRate.next = (IntPtr)BitConverter.ToInt64(eventDataBuffer.varying, 8);
eventDataPassthroughConfigurationImageRate.fromImageRate.srcImageRate = BitConverter.ToSingle(eventDataBuffer.varying, 16);
eventDataPassthroughConfigurationImageRate.fromImageRate.dstImageRate = BitConverter.ToSingle(eventDataBuffer.varying, 20);
eventDataPassthroughConfigurationImageRate.toImageRate.type = (XrStructureType)BitConverter.ToUInt32(eventDataBuffer.varying, 24);
eventDataPassthroughConfigurationImageRate.toImageRate.next = (IntPtr)BitConverter.ToInt64(eventDataBuffer.varying, 32);
eventDataPassthroughConfigurationImageRate.toImageRate.srcImageRate = BitConverter.ToSingle(eventDataBuffer.varying, 40);
eventDataPassthroughConfigurationImageRate.toImageRate.dstImageRate = BitConverter.ToSingle(eventDataBuffer.varying, 44);
return true;
}
return false;
}
};
[StructLayout(LayoutKind.Sequential)]
public struct XrEventDataPassthroughConfigurationImageQualityChangedHTC
{
public XrStructureType type;
public IntPtr next;
public XrPassthroughConfigurationImageQualityHTC fromImageQuality;
public XrPassthroughConfigurationImageQualityHTC toImageQuality;
public XrEventDataPassthroughConfigurationImageQualityChangedHTC(XrStructureType in_type, IntPtr in_next, XrPassthroughConfigurationImageQualityHTC in_fromImageQuality, XrPassthroughConfigurationImageQualityHTC in_toImageQuality)
{
type = in_type;
next = in_next;
fromImageQuality = in_fromImageQuality;
toImageQuality = in_toImageQuality;
}
public static XrEventDataPassthroughConfigurationImageQualityChangedHTC identity
{
get
{
return new XrEventDataPassthroughConfigurationImageQualityChangedHTC(
XrStructureType.XR_TYPE_EVENT_DATA_PASSTHROUGH_CONFIGURATION_IMAGE_QUALITY_CHANGED_HTC,
IntPtr.Zero,
new XrPassthroughConfigurationImageQualityHTC { type = XrStructureType.XR_TYPE_PASSTHROUGH_CONFIGURATION_IMAGE_QUALITY_HTC, next = IntPtr.Zero },
new XrPassthroughConfigurationImageQualityHTC { type = XrStructureType.XR_TYPE_PASSTHROUGH_CONFIGURATION_IMAGE_QUALITY_HTC, next = IntPtr.Zero }); // user is default present
}
}
public static bool Get(XrEventDataBuffer eventDataBuffer, out XrEventDataPassthroughConfigurationImageQualityChangedHTC ventDataPassthroughConfigurationImageQuality)
{
ventDataPassthroughConfigurationImageQuality = identity;
if (eventDataBuffer.type == XrStructureType.XR_TYPE_EVENT_DATA_PASSTHROUGH_CONFIGURATION_IMAGE_QUALITY_CHANGED_HTC)
{
ventDataPassthroughConfigurationImageQuality.next = eventDataBuffer.next;
ventDataPassthroughConfigurationImageQuality.fromImageQuality.type = (XrStructureType)BitConverter.ToUInt32(eventDataBuffer.varying, 0);
ventDataPassthroughConfigurationImageQuality.fromImageQuality.next = (IntPtr)BitConverter.ToInt64(eventDataBuffer.varying, 8);
ventDataPassthroughConfigurationImageQuality.fromImageQuality.scale = BitConverter.ToSingle(eventDataBuffer.varying, 16);
ventDataPassthroughConfigurationImageQuality.toImageQuality.type = (XrStructureType)BitConverter.ToUInt32(eventDataBuffer.varying, 24);
ventDataPassthroughConfigurationImageQuality.toImageQuality.next = (IntPtr)BitConverter.ToInt64(eventDataBuffer.varying, 32);
ventDataPassthroughConfigurationImageQuality.toImageQuality.scale = BitConverter.ToSingle(eventDataBuffer.varying, 40);
return true;
}
return false;
}
};
[StructLayout(LayoutKind.Sequential)]
public struct XrSystemPassthroughConfigurationPropertiesHTC
{
public XrStructureType type;
public IntPtr next;
public XrBool32 supportsImageRate;
public XrBool32 supportsImageQuality;
};
#endregion
#region New Functions
public static class VivePassthroughHelper
{
///
/// The delegate function of xrCreatePassthroughHTC.
///
/// An XrSession in which the passthrough will be active.
/// createInfo is a pointer to an XrPassthroughCreateInfoHTC structure containing information about how to create the passthrough.
/// passthrough is a pointer to a handle in which the created XrPassthroughHTC is returned.
/// XR_SUCCESS for success.
public delegate XrResult xrCreatePassthroughHTCDelegate(
XrSession session,
XrPassthroughCreateInfoHTC createInfo,
out XrPassthroughHTC passthrough);
///
/// The delegate function of xrDestroyFacialTrackerHTC.
///
/// passthrough is the XrPassthroughHTC to be destroyed..
/// XR_SUCCESS for success.
public delegate XrResult xrDestroyPassthroughHTCDelegate(
XrPassthroughHTC passthrough);
public delegate XrResult xrEnumeratePassthroughImageRatesHTCDelegate(
XrSession session,
[In] UInt32 imageRateCapacityInput,
ref UInt32 imageRateCountOutput,
[In, Out] XrPassthroughConfigurationImageRateHTC[] imageRates);
public delegate XrResult xrGetPassthroughConfigurationHTCDelegate(
XrSession session,
IntPtr/*ref XrPassthroughConfigurationBaseHeaderHTC*/ config);
public delegate XrResult xrSetPassthroughConfigurationHTCDelegate(
XrSession session,
IntPtr/*ref XrPassthroughConfigurationBaseHeaderHTC*/ config);
}
public static class VivePassthroughImageQualityChanged
{
public delegate void OnImageQualityChanged(float fromQuality, float toQuality);
public static void Listen(OnImageQualityChanged callback)
{
if (!allEventListeners.Contains(callback))
allEventListeners.Add(callback);
}
public static void Remove(OnImageQualityChanged callback)
{
if (allEventListeners.Contains(callback))
allEventListeners.Remove(callback);
}
public static void Send(float fromQuality, float toQuality)
{
int N = 0;
if (allEventListeners != null)
{
N = allEventListeners.Count;
for (int i = N - 1; i >= 0; i--)
{
OnImageQualityChanged single = allEventListeners[i];
try
{
single(fromQuality, toQuality);
}
catch (Exception e)
{
Debug.Log("Event : " + e.ToString());
allEventListeners.Remove(single);
Debug.Log("Event : A listener is removed due to exception.");
}
}
}
}
private static List allEventListeners = new List();
}
public static class VivePassthroughImageRateChanged
{
public delegate void OnImageRateChanged(float fromSrcImageRate, float fromDestImageRate, float toSrcImageRate, float toDestImageRate);
public static void Listen(OnImageRateChanged callback)
{
if (!allEventListeners.Contains(callback))
allEventListeners.Add(callback);
}
public static void Remove(OnImageRateChanged callback)
{
if (allEventListeners.Contains(callback))
allEventListeners.Remove(callback);
}
public static void Send(float fromSrcImageRate, float fromDestImageRate, float toSrcImageRate, float toDestImageRate)
{
int N = 0;
if (allEventListeners != null)
{
N = allEventListeners.Count;
for (int i = N - 1; i >= 0; i--)
{
OnImageRateChanged single = allEventListeners[i];
try
{
single(fromSrcImageRate, fromDestImageRate, toSrcImageRate, toDestImageRate);
}
catch (Exception e)
{
Debug.Log("Event : " + e.ToString());
allEventListeners.Remove(single);
Debug.Log("Event : A listener is removed due to exception.");
}
}
}
}
private static List allEventListeners = new List();
}
#endregion
}