version 2.3.0
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR.Feature
|
||||
{
|
||||
/// <summary>
|
||||
/// To use this wrapper, you need to call CommonWrapper.Instance.OnInstanceCreate() in your feature's OnInstanceCreate(),
|
||||
/// and call CommonWrapper.Instance.OnInstanceDestroy() in your feature's OnInstanceDestroy().
|
||||
/// </summary>
|
||||
public class CommonWrapper
|
||||
{
|
||||
static CommonWrapper instance = null;
|
||||
public static CommonWrapper Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new CommonWrapper();
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
bool isInited = false;
|
||||
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr;
|
||||
OpenXRHelper.xrGetSystemPropertiesDelegate XrGetSystemProperties;
|
||||
|
||||
/// <summary>
|
||||
/// In feature's OnInstanceCreate(), call CommonWrapper.Instance.OnInstanceCreate() for init common APIs.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">Passed in feature's OnInstanceCreate.</param>
|
||||
/// <param name="xrGetInstanceProcAddr">Pass OpenXRFeature.xrGetInstanceProcAddr in.</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception">If input data not valid.</exception>
|
||||
public bool OnInstanceCreate(XrInstance xrInstance, IntPtr xrGetInstanceProcAddr)
|
||||
{
|
||||
if (isInited) return true;
|
||||
|
||||
if (xrInstance == 0)
|
||||
throw new Exception("CommonWrapper: xrInstance is null");
|
||||
|
||||
Debug.Log("CommonWrapper: OnInstanceCreate()");
|
||||
/// OpenXRFeature.xrGetInstanceProcAddr
|
||||
if (xrGetInstanceProcAddr == null || xrGetInstanceProcAddr == IntPtr.Zero)
|
||||
throw new Exception("CommonWrapper: xrGetInstanceProcAddr is null");
|
||||
|
||||
Debug.Log("CommonWrapper: Get function pointer of xrGetInstanceProcAddr.");
|
||||
XrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(
|
||||
xrGetInstanceProcAddr,
|
||||
typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate)) as OpenXRHelper.xrGetInstanceProcAddrDelegate;
|
||||
|
||||
bool ret = true;
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(XrGetInstanceProcAddr, xrInstance, "xrGetSystemProperties", out XrGetSystemProperties);
|
||||
|
||||
if (!ret)
|
||||
throw new Exception("CommonWrapper: Get function pointers failed.");
|
||||
|
||||
isInited = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In feature's OnInstanceDestroy(), call CommonWrapper.Instance.OnInstanceDestroy() for disable common APIs.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void OnInstanceDestroy()
|
||||
{
|
||||
isInited = false;
|
||||
XrGetInstanceProcAddr = null;
|
||||
XrGetSystemProperties = null;
|
||||
Debug.Log("CommonWrapper: OnInstanceDestroy()");
|
||||
}
|
||||
|
||||
public XrResult GetInstanceProcAddr(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (isInited == false || XrGetInstanceProcAddr == null)
|
||||
{
|
||||
function = IntPtr.Zero;
|
||||
return XrResult.XR_ERROR_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
return XrGetInstanceProcAddr(instance, name, out function);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to get system properties. Need input your features' xrInstance and xrSystemId. Fill the system properites in next for you feature.
|
||||
/// See <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystemProperties">xrGetSystemProperties</see>
|
||||
/// </summary>
|
||||
/// <param name="instance"></param>
|
||||
/// <param name="systemId"></param>
|
||||
/// <param name="properties"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult GetSystemProperties(XrInstance instance, XrSystemId systemId, ref XrSystemProperties properties)
|
||||
{
|
||||
if (isInited == false || XrGetSystemProperties == null)
|
||||
{
|
||||
return XrResult.XR_ERROR_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
return XrGetSystemProperties(instance, systemId, ref properties);
|
||||
}
|
||||
|
||||
|
||||
public XrResult GetProperties<T>(XrInstance instance, XrSystemId systemId, ref T featureProperty)
|
||||
{
|
||||
XrSystemProperties systemProperties = new XrSystemProperties();
|
||||
systemProperties.type = XrStructureType.XR_TYPE_SYSTEM_PROPERTIES;
|
||||
systemProperties.next = Marshal.AllocHGlobal(Marshal.SizeOf(featureProperty));
|
||||
|
||||
long offset = 0;
|
||||
if (IntPtr.Size == 4)
|
||||
offset = systemProperties.next.ToInt32();
|
||||
else
|
||||
offset = systemProperties.next.ToInt64();
|
||||
|
||||
IntPtr pdPropertiesPtr = new IntPtr(offset);
|
||||
Marshal.StructureToPtr(featureProperty, pdPropertiesPtr, false);
|
||||
|
||||
var ret = GetSystemProperties(instance, systemId, ref systemProperties);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
offset = systemProperties.next.ToInt32();
|
||||
else
|
||||
offset = systemProperties.next.ToInt64();
|
||||
|
||||
pdPropertiesPtr = new IntPtr(offset);
|
||||
featureProperty = Marshal.PtrToStructure<T>(pdPropertiesPtr);
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(systemProperties.next);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b940cd65f52cd5c44bd79869c5d521b2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,226 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
// Remove FAKE_DATA if editor or windows is supported.
|
||||
#if UNITY_EDITOR
|
||||
#define FAKE_DATA
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR.Feature
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// To use this wrapper, you need to call CommonWrapper.Instance.OnInstanceCreate() in your feature's OnInstanceCreate(),
|
||||
/// and call CommonWrapper.Instance.OnInstanceDestroy() in your feature's OnInstanceDestroy().
|
||||
/// </summary>
|
||||
public class SpaceWrapper
|
||||
{
|
||||
static SpaceWrapper instance = null;
|
||||
public static SpaceWrapper Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new SpaceWrapper();
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
bool isInited = false;
|
||||
|
||||
delegate XrResult DelegateXrLocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, ref XrSpaceLocation location);
|
||||
delegate XrResult DelegateXrDestroySpace(XrSpace space);
|
||||
|
||||
OpenXRHelper.xrCreateReferenceSpaceDelegate XrCreateReferenceSpace;
|
||||
DelegateXrLocateSpace XrLocateSpace;
|
||||
DelegateXrDestroySpace XrDestroySpace;
|
||||
|
||||
/// <summary>
|
||||
/// Features should call ViveSpaceWrapper.Instance.OnInstanceCreate() in their OnInstanceCreate().
|
||||
/// </summary>
|
||||
/// <param name="xrInstance"></param>
|
||||
/// <param name="GetAddr"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public bool OnInstanceCreate(XrInstance xrInstance, OpenXRHelper.xrGetInstanceProcAddrDelegate GetAddr)
|
||||
{
|
||||
if (isInited) return true;
|
||||
|
||||
if (xrInstance == null)
|
||||
throw new Exception("ViveSpace: xrInstance is null");
|
||||
|
||||
if (GetAddr == null)
|
||||
throw new Exception("ViveSpace: xrGetInstanceProcAddr is null");
|
||||
|
||||
Debug.Log("ViveSpace: OnInstanceCreate()");
|
||||
|
||||
bool ret = true;
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, xrInstance, "xrCreateReferenceSpace", out XrCreateReferenceSpace);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, xrInstance, "xrLocateSpace", out XrLocateSpace);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(GetAddr, xrInstance, "xrDestroySpace", out XrDestroySpace);
|
||||
isInited = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void OnInstanceDestroy()
|
||||
{
|
||||
isInited = false;
|
||||
XrCreateReferenceSpace = null;
|
||||
XrLocateSpace = null;
|
||||
XrDestroySpace = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a reference space without create info.
|
||||
/// Example:
|
||||
/// CreateReferenceSpace(session, XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_LOCAL, XrPosef.identity, out space);
|
||||
/// CreateReferenceSpace(session, XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_STAGE, XrPosef.identity, out space);
|
||||
/// </summary>
|
||||
/// <param name="session"></param>
|
||||
/// <param name="referenceSpaceType"></param>
|
||||
/// <param name="pose"></param>
|
||||
/// <param name="space"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult CreateReferenceSpace(XrSession session, XrReferenceSpaceType referenceSpaceType, XrPosef pose, out XrSpace space)
|
||||
{
|
||||
if (!isInited)
|
||||
throw new Exception("ViveSpace: not initialized");
|
||||
|
||||
var createInfo = new XrReferenceSpaceCreateInfo();
|
||||
createInfo.type = XrStructureType.XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
createInfo.next = IntPtr.Zero;
|
||||
createInfo.referenceSpaceType = referenceSpaceType;
|
||||
createInfo.poseInReferenceSpace = pose;
|
||||
return XrCreateReferenceSpace(session, ref createInfo, out space);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a reference space.
|
||||
/// </summary>
|
||||
/// <param name="session"></param>
|
||||
/// <param name="createInfo"></param>
|
||||
/// <param name="space"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult CreateReferenceSpace(XrSession session, XrReferenceSpaceCreateInfo createInfo, out XrSpace space)
|
||||
{
|
||||
if (!isInited)
|
||||
throw new Exception("ViveSpace: not initialized");
|
||||
|
||||
return XrCreateReferenceSpace(session, ref createInfo, out space);
|
||||
}
|
||||
|
||||
public XrResult LocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, ref XrSpaceLocation location)
|
||||
{
|
||||
if (!isInited)
|
||||
throw new Exception("ViveSpace: not initialized");
|
||||
Debug.Log($"LocateSpace(s={space}, bs={baseSpace}, t={time}");
|
||||
return XrLocateSpace(space, baseSpace, time, ref location);
|
||||
}
|
||||
|
||||
public XrResult DestroySpace(XrSpace space)
|
||||
{
|
||||
if (!isInited)
|
||||
throw new Exception("ViveSpace: not initialized");
|
||||
Debug.Log($"DestroySpace({space})");
|
||||
return XrDestroySpace(space);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The XrSpace's Unity wrapper. Input and output are in Unity coordinate system.
|
||||
/// After use it, you should call Dispose() to release the XrSpace.
|
||||
/// </summary>
|
||||
public class Space : IDisposable
|
||||
{
|
||||
protected XrSpace space;
|
||||
private bool disposed = false;
|
||||
|
||||
public Space(XrSpace space)
|
||||
{
|
||||
Debug.Log($"Space({space})");
|
||||
this.space = space;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the raw XrSpace. Only use it when class Space instance is alive.
|
||||
/// You should not try to store this XrSpace, because it may be destroyed.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public XrSpace GetXrSpace()
|
||||
{
|
||||
return space;
|
||||
}
|
||||
|
||||
public bool GetRelatedPose(XrSpace baseSpace, XrTime time, out UnityEngine.Pose pose)
|
||||
{
|
||||
#if FAKE_DATA
|
||||
if (Application.isEditor)
|
||||
{
|
||||
// make a random Pose
|
||||
//var pos = new Vector3(UnityEngine.Random.Range(-1f, 1f), UnityEngine.Random.Range(-1f, 1f), UnityEngine.Random.Range(-1f, 1f));
|
||||
//var rot = new Quaternion(UnityEngine.Random.Range(-1f, 1f), UnityEngine.Random.Range(-1f, 1f), UnityEngine.Random.Range(-1f, 1f), UnityEngine.Random.Range(-1f, 1f));
|
||||
var pos = Vector3.up;
|
||||
var rot = Quaternion.identity;
|
||||
rot.Normalize();
|
||||
pose = new Pose(pos, rot);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
// If the xrBaseSpace is changed, the pose will be updated.
|
||||
pose = default;
|
||||
XrSpaceLocation location = new XrSpaceLocation();
|
||||
location.type = XrStructureType.XR_TYPE_SPACE_LOCATION;
|
||||
location.next = IntPtr.Zero;
|
||||
var ret = SpaceWrapper.Instance.LocateSpace(space, baseSpace, time, ref location);
|
||||
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
{
|
||||
Debug.Log("Space: LocateSpace ret=" + ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Log("Space: baseSpace=" + baseSpace + ", space=" + space + ", time=" + time + ", ret=" + ret);
|
||||
Debug.Log("Space: location.locationFlags=" + location.locationFlags);
|
||||
Debug.Log("Space: location.pose.position=" + location.pose.position.x + "," + location.pose.position.y + "," + location.pose.position.z);
|
||||
Debug.Log("Space: location.pose.orientation=" + location.pose.orientation.x + "," + location.pose.orientation.y + "," + location.pose.orientation.z + "," + location.pose.orientation.w);
|
||||
if ((location.locationFlags & XrSpaceLocationFlags.XR_SPACE_LOCATION_POSITION_VALID_BIT) > 0 &&
|
||||
(location.locationFlags & XrSpaceLocationFlags.XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) > 0)
|
||||
{
|
||||
pose = new Pose(location.pose.position.ToUnityVector(), location.pose.orientation.ToUnityQuaternion());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Managered resource
|
||||
}
|
||||
// Non managered resource
|
||||
Debug.Log($"Space: DestroySpace({space})");
|
||||
SpaceWrapper.Instance.DestroySpace(space);
|
||||
space = 0;
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
~Space()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8fbeadd31afbe14996c061ac261041d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
83
com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptors.cs
Normal file
83
com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptors.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using AOT;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is made for all features that need to intercept OpenXR API calls.
|
||||
/// Some APIs will be called by Unity internally, and we need to intercept them in c# to get some information.
|
||||
/// Append more interceptable functions for this class by adding a new partial class.
|
||||
/// The partial class can help the delegate name be nice to read and search.
|
||||
/// Please create per function in one partial class.
|
||||
///
|
||||
/// For all features want to use this class, please call <see cref="HookGetInstanceProcAddr" /> in your feature class.
|
||||
/// For example:
|
||||
/// protected override IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
/// {
|
||||
/// return HtcInterceptors.Instance.HookGetInstanceProcAddr(func);
|
||||
/// }
|
||||
/// </summary>
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
public const string TAG = "Interceptors";
|
||||
|
||||
public static ViveInterceptors instance = null;
|
||||
public static ViveInterceptors Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new ViveInterceptors();
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public ViveInterceptors()
|
||||
{
|
||||
Debug.Log("HtcInterceptors");
|
||||
}
|
||||
|
||||
bool isInited = false;
|
||||
|
||||
public delegate XrResult DelegateXrGetInstanceProcAddr(XrInstance instance, string name, out IntPtr function);
|
||||
private static readonly DelegateXrGetInstanceProcAddr hookXrGetInstanceProcAddrHandle = new DelegateXrGetInstanceProcAddr(XrGetInstanceProcAddrInterceptor);
|
||||
private static readonly IntPtr hookGetInstanceProcAddrHandlePtr = Marshal.GetFunctionPointerForDelegate(hookXrGetInstanceProcAddrHandle);
|
||||
static DelegateXrGetInstanceProcAddr XrGetInstanceProcAddrOriginal = null;
|
||||
|
||||
[MonoPInvokeCallback(typeof(DelegateXrGetInstanceProcAddr))]
|
||||
private static XrResult XrGetInstanceProcAddrInterceptor(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
// Custom interceptors
|
||||
if (name == "xrWaitFrame")
|
||||
{
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
XrWaitFrameOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrWaitFrame>(function);
|
||||
function = xrWaitFrameInterceptorPtr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
}
|
||||
|
||||
public IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
{
|
||||
Debug.Log($"{TAG}: registering our own xrGetInstanceProcAddr");
|
||||
if (XrGetInstanceProcAddrOriginal == null)
|
||||
{
|
||||
XrGetInstanceProcAddrOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrGetInstanceProcAddr>(func);
|
||||
isInited = true;
|
||||
return hookGetInstanceProcAddrHandlePtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return func;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 118a2474c266d174d834b364821865b5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using AOT;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
#region XRWaitFrame
|
||||
public struct XrFrameWaitInfo
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
public struct XrFrameState
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrTime predictedDisplayTime;
|
||||
public XrDuration predictedDisplayPeriod;
|
||||
public XrBool32 shouldRender;
|
||||
}
|
||||
|
||||
public delegate XrResult DelegateXrWaitFrame(XrSession session, ref XrFrameWaitInfo frameWaitInfo, ref XrFrameState frameState);
|
||||
private static readonly DelegateXrWaitFrame xrWaitFrameInterceptorHandle = new DelegateXrWaitFrame(XrWaitFrameInterceptor);
|
||||
private static readonly IntPtr xrWaitFrameInterceptorPtr = Marshal.GetFunctionPointerForDelegate(xrWaitFrameInterceptorHandle);
|
||||
static DelegateXrWaitFrame XrWaitFrameOriginal = null;
|
||||
|
||||
[MonoPInvokeCallback(typeof(DelegateXrWaitFrame))]
|
||||
private static XrResult XrWaitFrameInterceptor(XrSession session, ref XrFrameWaitInfo frameWaitInfo, ref XrFrameState frameState)
|
||||
{
|
||||
var ret = XrWaitFrameOriginal(session, ref frameWaitInfo, ref frameState);
|
||||
currentFrameState = frameState;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static XrFrameState currentFrameState = new XrFrameState() { predictedDisplayTime = 0 };
|
||||
|
||||
public XrFrameState GetCurrentFrameState()
|
||||
{
|
||||
if (!isInited) throw new Exception("ViveInterceptors is not inited");
|
||||
|
||||
return currentFrameState;
|
||||
}
|
||||
|
||||
public XrTime GetPredictTime()
|
||||
{
|
||||
if (!isInited) throw new Exception("ViveInterceptors is not inited");
|
||||
|
||||
Debug.Log($"{TAG}: XrWaitFrameInterceptor(predictedDisplayTime={currentFrameState.predictedDisplayTime}");
|
||||
if (currentFrameState.predictedDisplayTime == 0)
|
||||
return new XrTime((long)(1000000L * (Time.unscaledTimeAsDouble + 0.011f)));
|
||||
else
|
||||
return currentFrameState.predictedDisplayTime;
|
||||
}
|
||||
#endregion XRWaitFrame
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9bfc07f267ee39b47a4bcbb8c1c786cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user