version 2.5.1
This commit is contained in:
@@ -281,7 +281,8 @@ namespace VIVE.OpenXR.Editor
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
|
||||
var features = settings.GetFeatures<OpenXRFeature>();
|
||||
foreach (var feature in features)
|
||||
{
|
||||
if (!feature.enabled) { continue; }
|
||||
|
||||
@@ -310,6 +311,17 @@ namespace VIVE.OpenXR.Editor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (feature is VIVEFocus3Feature)
|
||||
{
|
||||
for (int i = 0; i < features.Length; i++)
|
||||
{
|
||||
if (features[i] is Enterprise.ViveEnterpriseCommand)
|
||||
{
|
||||
features[i].enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enableHandtracking)
|
||||
|
||||
@@ -51,6 +51,39 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
static GUIContent Label_QuadHeight = new GUIContent("Height", "Height of a Quad Layer");
|
||||
SerializedProperty Property_QuadHeight;
|
||||
|
||||
static string PropertyName_EquirectRadius = "m_EquirectRadius";
|
||||
static GUIContent Label_EquirectRadius = new GUIContent("Radius", "Radius of Equirect Layer");
|
||||
SerializedProperty Property_EquirectRadius;
|
||||
|
||||
static string PropertyName_EquirectScaleX = "m_EquirectScaleX";
|
||||
static GUIContent Label_EquirectScaleX = new GUIContent("scale.x", "Scale.X of Equirect Layer");
|
||||
SerializedProperty Property_EquirectScaleX;
|
||||
|
||||
static string PropertyName_EquirectScaleY = "m_EquirectScaleY";
|
||||
static GUIContent Label_EquirectScaleY = new GUIContent("scale.y", "Scale.Y of Equirect Layer");
|
||||
SerializedProperty Property_EquirectScaleY;
|
||||
|
||||
static string PropertyName_EquirectBiasX = "m_EquirectBiasX";
|
||||
static GUIContent Label_EquirectBiasX = new GUIContent("bias.x", "Bias.X of Equirect Layer");
|
||||
SerializedProperty Property_EquirectBiasX;
|
||||
|
||||
static string PropertyName_EquirectBiasY = "m_EquirectBiasY";
|
||||
static GUIContent Label_EquirectBiasY = new GUIContent("bias.y", "Bias.Y of Equirect Layer");
|
||||
SerializedProperty Property_EquirectBiasY;
|
||||
|
||||
static string PropertyName_EquirectCentralHorizontalAngle = "m_EquirectCentralHorizontalAngle";
|
||||
static GUIContent Label_EquirectCentralHorizontalAngle = new GUIContent("CentralHorizontalAngle", "Central Horizontal Angle of Equirect Layer");
|
||||
SerializedProperty Property_EquirectCentralHorizontalAngle;
|
||||
|
||||
static string PropertyName_EquirectUpperVerticalAngle = "m_EquirectUpperVerticalAngle";
|
||||
static GUIContent Label_EquirectUpperVerticalAngle = new GUIContent("UpperVerticalAngle", "Upper Vertical Angle of Equirect Layer");
|
||||
SerializedProperty Property_EquirectUpperVerticalAngle;
|
||||
|
||||
static string PropertyName_EquirectLowerVerticalAngle = "m_EquirectLowerVerticalAngle";
|
||||
static GUIContent Label_EquirectLowerVerticalAngle = new GUIContent("LowerVerticalAngle", "Lower Vertical Angle of Equirect Layer");
|
||||
SerializedProperty Property_EquirectLowerVerticalAngle;
|
||||
|
||||
|
||||
static string PropertyName_CylinderHeight = "m_CylinderHeight";
|
||||
static GUIContent Label_CylinderHeight = new GUIContent("Height", "Height of Cylinder Layer");
|
||||
SerializedProperty Property_CylinderHeight;
|
||||
@@ -138,6 +171,14 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
if (Property_LockMode == null) Property_LockMode = serializedObject.FindProperty(PropertyName_LockMode);
|
||||
if (Property_QuadWidth == null) Property_QuadWidth = serializedObject.FindProperty(PropertyName_QuadWidth);
|
||||
if (Property_QuadHeight == null) Property_QuadHeight = serializedObject.FindProperty(PropertyName_QuadHeight);
|
||||
if (Property_EquirectRadius == null) Property_EquirectRadius = serializedObject.FindProperty(PropertyName_EquirectRadius);
|
||||
if (Property_EquirectScaleX == null) Property_EquirectScaleX = serializedObject.FindProperty(PropertyName_EquirectScaleX);
|
||||
if (Property_EquirectScaleY == null) Property_EquirectScaleY = serializedObject.FindProperty(PropertyName_EquirectScaleY);
|
||||
if (Property_EquirectBiasX == null) Property_EquirectBiasX = serializedObject.FindProperty(PropertyName_EquirectBiasX);
|
||||
if (Property_EquirectBiasY == null) Property_EquirectBiasY = serializedObject.FindProperty(PropertyName_EquirectBiasY);
|
||||
if (Property_EquirectCentralHorizontalAngle == null) Property_EquirectCentralHorizontalAngle = serializedObject.FindProperty(PropertyName_EquirectCentralHorizontalAngle);
|
||||
if (Property_EquirectUpperVerticalAngle == null) Property_EquirectUpperVerticalAngle = serializedObject.FindProperty(PropertyName_EquirectUpperVerticalAngle);
|
||||
if (Property_EquirectLowerVerticalAngle == null) Property_EquirectLowerVerticalAngle = serializedObject.FindProperty(PropertyName_EquirectLowerVerticalAngle);
|
||||
if (Property_CylinderHeight == null) Property_CylinderHeight = serializedObject.FindProperty(PropertyName_CylinderHeight);
|
||||
if (Property_CylinderArcLength == null) Property_CylinderArcLength = serializedObject.FindProperty(PropertyName_CylinderArcLength);
|
||||
if (Property_CylinderRadius == null) Property_CylinderRadius = serializedObject.FindProperty(PropertyName_CylinderRadius);
|
||||
@@ -171,6 +212,138 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
EditorGUILayout.PropertyField(Property_LayerShape, new GUIContent(Label_LayerShape));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect || Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect2)
|
||||
{
|
||||
if (targetCompositionLayer.isPreviewingQuad)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingQuad = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.isPreviewingCylinder)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingCylinder = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
if (!FeatureHelpers.GetFeatureWithIdForBuildTarget(BuildTargetGroup.Android, ViveCompositionLayerEquirect.featureId).enabled)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The Composition Layer Equirect feature is not enabled in OpenXR Settings.\nEnable it to use Equirect layers.", MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
showLayerParams = EditorGUILayout.Foldout(showLayerParams, "Equirect Parameters");
|
||||
if (showLayerParams)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_EquirectRadius, new GUIContent(Label_EquirectRadius));
|
||||
|
||||
if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_EquirectScaleX, new GUIContent(Label_EquirectScaleX));
|
||||
EditorGUILayout.PropertyField(Property_EquirectScaleY, new GUIContent(Label_EquirectScaleY));
|
||||
EditorGUILayout.PropertyField(Property_EquirectBiasX, new GUIContent(Label_EquirectBiasX));
|
||||
EditorGUILayout.PropertyField(Property_EquirectBiasY, new GUIContent(Label_EquirectBiasY));
|
||||
}
|
||||
|
||||
else if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect2)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_EquirectCentralHorizontalAngle, new GUIContent(Label_EquirectCentralHorizontalAngle));
|
||||
EditorGUILayout.PropertyField(Property_EquirectUpperVerticalAngle, new GUIContent(Label_EquirectUpperVerticalAngle));
|
||||
EditorGUILayout.PropertyField(Property_EquirectLowerVerticalAngle, new GUIContent(Label_EquirectLowerVerticalAngle));
|
||||
}
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
bool EquirectParamsChanged = targetCompositionLayer.LayerDimensionsChanged();
|
||||
if (targetCompositionLayer.isPreviewingEquirect)
|
||||
{
|
||||
Transform generatedPreviewTransform = targetCompositionLayer.transform.Find(CompositionLayer.EquirectPreviewName);
|
||||
|
||||
if (generatedPreviewTransform != null)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview = generatedPreviewTransform.gameObject;
|
||||
|
||||
if (EquirectParamsChanged)
|
||||
{
|
||||
MeshFilter equirectMeshFilter = targetCompositionLayer.generatedPreview.GetComponent<MeshFilter>();
|
||||
|
||||
//Generate vertices
|
||||
equirectMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateEquirectMesh(targetCompositionLayer.hmd, targetCompositionLayer.EquirectRadius);
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture != targetCompositionLayer.texture)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Hide Equirect Preview"))
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUILayout.Button("Show Equirect Preview"))
|
||||
{
|
||||
Rect srcRectLeft = FullRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.LeftRight)
|
||||
srcRectLeft = LeftRightRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.TopDown)
|
||||
srcRectLeft = TopDownRect;
|
||||
|
||||
targetCompositionLayer.isPreviewingEquirect = true;
|
||||
//Vector3[] cylinderVertices = CompositionLayer.MeshGenerationHelper.GenerateCylinderVertex(targetCompositionLayer.CylinderAngleOfArc, targetCompositionLayer.CylinderRadius, targetCompositionLayer.CylinderHeight);
|
||||
//Add components to Game Object
|
||||
targetCompositionLayer.generatedPreview = new GameObject();
|
||||
targetCompositionLayer.generatedPreview.hideFlags = HideFlags.HideAndDontSave;
|
||||
targetCompositionLayer.generatedPreview.name = CompositionLayer.EquirectPreviewName;
|
||||
targetCompositionLayer.generatedPreview.transform.SetParent(targetCompositionLayer.gameObject.transform);
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
|
||||
MeshRenderer equirectMeshRenderer = targetCompositionLayer.generatedPreview.AddComponent<MeshRenderer>();
|
||||
MeshFilter equirectMeshFilter = targetCompositionLayer.generatedPreview.AddComponent<MeshFilter>();
|
||||
equirectMeshRenderer.sharedMaterial = new Material(Shader.Find("Unlit/Transparent"));
|
||||
|
||||
if (targetCompositionLayer.texture != null)
|
||||
{
|
||||
equirectMeshRenderer.sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
equirectMeshRenderer.sharedMaterial.mainTextureOffset = srcRectLeft.position;
|
||||
equirectMeshRenderer.sharedMaterial.mainTextureScale = srcRectLeft.size;
|
||||
}
|
||||
|
||||
//Generate Mesh
|
||||
equirectMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateEquirectMesh(targetCompositionLayer.hmd, targetCompositionLayer.EquirectRadius);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
}
|
||||
if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Cylinder)
|
||||
{
|
||||
if (!FeatureHelpers.GetFeatureWithIdForBuildTarget(BuildTargetGroup.Android, ViveCompositionLayerCylinder.featureId).enabled)
|
||||
@@ -187,6 +360,15 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
}
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.isPreviewingEquirect)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
Transform generatedQuadTransform = targetCompositionLayer.transform.Find(CompositionLayer.QuadUnderlayMeshName);
|
||||
if (generatedQuadTransform != null)
|
||||
{
|
||||
@@ -280,6 +462,7 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
|
||||
if (targetCompositionLayer.isPreviewingCylinder)
|
||||
{
|
||||
|
||||
Transform generatedPreviewTransform = targetCompositionLayer.transform.Find(CompositionLayer.CylinderPreviewName);
|
||||
|
||||
if (generatedPreviewTransform != null)
|
||||
@@ -372,6 +555,15 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
}
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.isPreviewingEquirect)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
showLayerParams = EditorGUILayout.Foldout(showLayerParams, "Quad Parameters");
|
||||
if (showLayerParams)
|
||||
@@ -507,7 +699,7 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
EditorGUI.indentLevel--;
|
||||
}*/
|
||||
|
||||
if (targetCompositionLayer.textureLeft == targetCompositionLayer.textureRight || targetCompositionLayer.textureRight == null)
|
||||
if((Property_LayerShape.intValue != (int)CompositionLayer.LayerShape.Equirect && Property_LayerShape.intValue != (int)CompositionLayer.LayerShape.Equirect2) && (targetCompositionLayer.textureLeft == targetCompositionLayer.textureRight || targetCompositionLayer.textureRight == null))
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_IsCustomRects, Label_IsCustomRects);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
@@ -93,9 +93,9 @@ public static class PackageManagerHelper
|
||||
case StatusCode.Failure:
|
||||
if (!s_wasRemoved)
|
||||
{
|
||||
if (m_removeRequest != null) { Debug.LogError("Something wrong when removing package from list. error:" + m_removeRequest.Error.errorCode + "(" + m_removeRequest.Error.message + ")"); }
|
||||
var request = m_removeRequest;
|
||||
m_removeRequest = null;
|
||||
Debug.LogError("Something wrong when removing package from list. error:" + m_removeRequest.Error.errorCode + "(" + m_removeRequest.Error.message + ")");
|
||||
}
|
||||
break;
|
||||
case StatusCode.Success:
|
||||
|
||||
@@ -149,10 +149,15 @@ namespace VIVE.OpenXR.Editor
|
||||
}
|
||||
}
|
||||
|
||||
static int checkPreferenceAssetsFrame = 0;
|
||||
static void OnUpdate()
|
||||
{
|
||||
if (!ViveOpenXRAndroidAssigned) { return; }
|
||||
|
||||
checkPreferenceAssetsFrame++;
|
||||
checkPreferenceAssetsFrame %= 1200; // 10s
|
||||
if (checkPreferenceAssetsFrame != 0) { return; }
|
||||
|
||||
CheckPreferenceAssets();
|
||||
|
||||
if (m_AssetAvatar)
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace VIVE.OpenXR
|
||||
"vive.openxr.feature.compositionlayer",
|
||||
"vive.openxr.feature.compositionlayer.cylinder",
|
||||
"vive.openxr.feature.compositionlayer.colorscalebias",
|
||||
CompositionLayer.ViveCompositionLayerEquirect.featureId,
|
||||
Tracker.ViveWristTracker.featureId,
|
||||
Hand.ViveHandInteraction.featureId,
|
||||
"vive.openxr.feature.foveation",
|
||||
|
||||
Binary file not shown.
@@ -7,8 +7,17 @@ namespace VIVE.OpenXR.Feature
|
||||
{
|
||||
public interface IViveFeatureWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// OnInstanceCreate might be called multiple times. Because many features might be using the same instance.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance"></param>
|
||||
/// <param name="xrGetInstanceProcAddr"></param>
|
||||
/// <returns></returns>
|
||||
public bool OnInstanceCreate(XrInstance xrInstance, IntPtr xrGetInstanceProcAddr);
|
||||
|
||||
/// <summary>
|
||||
/// OnInstanceDestroy might be called multiple times. Because many features might be using the same instance.
|
||||
/// </summary>
|
||||
public void OnInstanceDestroy();
|
||||
}
|
||||
|
||||
@@ -21,6 +30,11 @@ namespace VIVE.OpenXR.Feature
|
||||
// Set true in yourfeature's OnInstanceCreate
|
||||
public bool IsInited { get; protected set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// If the feature is inited not successfully, Set this true. Use to avoid multiple inits.
|
||||
/// </summary>
|
||||
public bool TryInited { get; protected set; } = false;
|
||||
|
||||
public OpenXRHelper.xrGetInstanceProcAddrDelegate xrGetInstanceProcAddr;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,24 +1,112 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public static class MemoryTools
|
||||
internal static class MemoryTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Make sure the input ptr is a OpenXR XrBaseStructure derived struct.
|
||||
/// </summary>
|
||||
/// <param name="ptr">the struct to get its next.</param>
|
||||
/// <returns>the next's value</returns>
|
||||
public static unsafe IntPtr GetNext(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return IntPtr.Zero;
|
||||
//Profiler.BeginSample("GetNext");
|
||||
XrBaseStructure* ptrToStruct = (XrBaseStructure*)ptr.ToPointer();
|
||||
//Profiler.EndSample();
|
||||
return ptrToStruct->next;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the input ptr is a OpenXR XrBaseStructure derived struct.
|
||||
/// </summary>
|
||||
/// <param name="ptr">the struct to get its type</param>
|
||||
/// <returns>the struct's type</returns>
|
||||
public static unsafe XrStructureType GetType(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
throw new Exception("The input pointer is null.");
|
||||
|
||||
//Profiler.BeginSample("GetType");
|
||||
XrBaseStructure* ptrToStruct = (XrBaseStructure*)ptr.ToPointer();
|
||||
//Profiler.EndSample();
|
||||
return ptrToStruct->type;
|
||||
}
|
||||
|
||||
public static unsafe XrBaseStructure ToBaseStructure(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
throw new Exception("The input pointer is null.");
|
||||
|
||||
//Profiler.BeginSample("ToBaseStructure");
|
||||
XrBaseStructure* ptrToStruct = (XrBaseStructure*)ptr.ToPointer();
|
||||
//Profiler.EndSample();
|
||||
return *ptrToStruct;
|
||||
}
|
||||
|
||||
public static unsafe T PtrToStructure<T>(IntPtr ptr) where T : unmanaged
|
||||
{
|
||||
//Profiler.BeginSample("PtrToStructure");
|
||||
// Not to use Marshal.PtrToStructure<T> because it is slow.
|
||||
T t = default; // Use new T() will cause GC alloc.
|
||||
Buffer.MemoryCopy((void*)ptr, &t, sizeof(T), sizeof(T));
|
||||
//Profiler.EndSample();
|
||||
return t;
|
||||
}
|
||||
|
||||
public static unsafe void PtrToStructure<T>(IntPtr ptr, ref T t) where T : unmanaged
|
||||
{
|
||||
//Profiler.BeginSample("PtrToStructure");
|
||||
fixed (T* destinationPtr = &t)
|
||||
{
|
||||
Buffer.MemoryCopy((void*)ptr, destinationPtr, sizeof(T), sizeof(T));
|
||||
}
|
||||
//Profiler.EndSample();
|
||||
}
|
||||
|
||||
public static unsafe void StructureToPtr<T>(T t, IntPtr ptr) where T : unmanaged
|
||||
{
|
||||
//Profiler.BeginSample("StructureToPtr");
|
||||
// Not to use Marshal.StructureToPtr<T> because it is slow.
|
||||
Buffer.MemoryCopy(&t, (void*)ptr, sizeof(T), sizeof(T));
|
||||
//Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the enum array to IntPtr. Should call <see cref="ReleaseRawMemory(IntPtr)"/> after use.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="array"></param>
|
||||
/// <returns></returns>
|
||||
public static IntPtr ToIntPtr<T>(T[] array) where T : Enum
|
||||
public static unsafe IntPtr ToIntPtr<T>(T[] array) where T : Enum
|
||||
{
|
||||
int size = Marshal.SizeOf(typeof(T)) * array.Length;
|
||||
int size = sizeof(int) * array.Length;
|
||||
IntPtr ptr = Marshal.AllocHGlobal(size);
|
||||
int[] intArray = new int[array.Length];
|
||||
|
||||
int* intPtr = (int*)ptr.ToPointer();
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
intArray[i] = (int)(object)array[i];
|
||||
Marshal.Copy(intArray, 0, ptr, array.Length);
|
||||
{
|
||||
// Convert enum to int. This has better performance than Convert.ToInt32.
|
||||
intPtr[i] = (int)(object)array[i];
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the struct to IntPtr. Should call <see cref="ReleaseRawMemory(IntPtr)"/> after use.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="structure"></param>
|
||||
/// <returns></returns>
|
||||
public static IntPtr ToIntPtr<T>(T structure) where T : struct
|
||||
{
|
||||
int size = Marshal.SizeOf(structure);
|
||||
IntPtr ptr = Marshal.AllocHGlobal(size);
|
||||
Marshal.StructureToPtr(structure, ptr, true);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -28,7 +116,7 @@ namespace VIVE.OpenXR
|
||||
/// <typeparam name="T">Data type could be primitive type or struct. Should call <see cref="ReleaseRawMemory(IntPtr)"/> after use.</typeparam>
|
||||
/// <param name="refArray">The data array</param>
|
||||
/// <returns>The memory handle. Should release by <see cref="ReleaseRawMemory(IntPtr)"/></returns>
|
||||
public static IntPtr MakeRawMemory<T>(T[] refArray)
|
||||
public static unsafe IntPtr MakeRawMemory<T>(T[] refArray) where T : unmanaged
|
||||
{
|
||||
int size = Marshal.SizeOf(typeof(T)) * refArray.Length;
|
||||
return Marshal.AllocHGlobal(size);
|
||||
@@ -41,16 +129,54 @@ namespace VIVE.OpenXR
|
||||
/// <param name="array">The output array.</param>
|
||||
/// <param name="raw">The data source in raw memory form.</param>
|
||||
/// <param name="count">Specify the copy count. Count should be less than array length.</param>
|
||||
public static void CopyFromRawMemory<T>(T[] array, IntPtr raw, int count = 0)
|
||||
public static unsafe void CopyFromRawMemory<T>(T[] array, IntPtr raw, int count = 0) where T : unmanaged
|
||||
{
|
||||
//Profiler.BeginSample("CopyFromRawMemory");
|
||||
int N = array.Length;
|
||||
if (count > 0 && count < array.Length)
|
||||
N = count;
|
||||
int step = Marshal.SizeOf(typeof(T));
|
||||
for (int i = 0; i < N; i++)
|
||||
int step = sizeof(T);
|
||||
int bufferSize = step * N;
|
||||
|
||||
// Pin array's address. Prevent GC move it.
|
||||
fixed (T* destPtr = array)
|
||||
{
|
||||
array[i] = Marshal.PtrToStructure<T>(IntPtr.Add(raw, i * step));
|
||||
T* sourcePtr = (T*)raw.ToPointer();
|
||||
Buffer.MemoryCopy(sourcePtr, destPtr, bufferSize, bufferSize);
|
||||
}
|
||||
//Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy all raw memory to the array. This has higher performance than <see cref="CopyFromRawMemory"/>.
|
||||
/// Use this method if you have frequent update requirements.
|
||||
/// You need prepare a byte buffer to store the raw memory. The byte buffer size should be tSize * array.Length.
|
||||
/// tSize is used for checking the byte buffer size. If tSize is 0, it will use Marshal.SizeOf(typeof(T)).
|
||||
/// You can save the size at your size to avoid the Marshal.Sizeof(typeof(T)) call repeatedly.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Convert the memory to this type array.</typeparam>
|
||||
/// <param name="array">The output array.</param>
|
||||
/// <param name="raw">The data source in raw memory form.</param>
|
||||
public static unsafe void CopyAllFromRawMemory<T>(T[] array, IntPtr raw) where T : unmanaged
|
||||
{
|
||||
#if DEBUG
|
||||
if (array == null)
|
||||
throw new ArgumentNullException(nameof(array), "Output array cannot be null.");
|
||||
if (raw == IntPtr.Zero)
|
||||
throw new ArgumentNullException(nameof(raw), "Raw memory pointer cannot be null.");
|
||||
#endif
|
||||
|
||||
//Profiler.BeginSample("CopyAllFromRawMemory");
|
||||
int elementSize = sizeof(T);
|
||||
int requiredBufferSize = elementSize * array.Length;
|
||||
|
||||
// Pin array's address. Prevent GC move it.
|
||||
fixed (T* destPtr = array)
|
||||
{
|
||||
T* sourcePtr = (T*)raw.ToPointer();
|
||||
Buffer.MemoryCopy(sourcePtr, destPtr, requiredBufferSize, requiredBufferSize);
|
||||
}
|
||||
//Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -59,13 +185,18 @@ namespace VIVE.OpenXR
|
||||
/// <typeparam name="T">Convert this type array to raw memory.</typeparam>
|
||||
/// <param name="raw">The output data in raw memory form</param>
|
||||
/// <param name="array">The data source</param>
|
||||
public static void CopyToRawMemory<T>(IntPtr raw, T[] array)
|
||||
public static unsafe void CopyToRawMemory<T>(IntPtr raw, T[] array) where T : unmanaged
|
||||
{
|
||||
int step = Marshal.SizeOf(typeof(T));
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
//Profiler.BeginSample("CopyToRawMemory");
|
||||
int step = sizeof(T);
|
||||
int bufferSize = step * array.Length;
|
||||
// Pin array's address. Prevent GC move it.
|
||||
fixed (T* destPtr = array)
|
||||
{
|
||||
Marshal.StructureToPtr<T>(array[i], IntPtr.Add(raw, i * step), false);
|
||||
void* ptr = raw.ToPointer();
|
||||
Buffer.MemoryCopy(destPtr, ptr, bufferSize, bufferSize);
|
||||
}
|
||||
//Profiler.EndSample();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -76,5 +207,22 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a pointer in the next chain. Make sure the input next pointer is a OpenXR XrBaseStructure derived struct.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="next"></param>
|
||||
/// <returns>true if exist</returns>
|
||||
public static bool HasPtrInNextChain(IntPtr target, IntPtr next)
|
||||
{
|
||||
while (next != IntPtr.Zero)
|
||||
{
|
||||
if (next == target)
|
||||
return true;
|
||||
next = GetNext(next);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
278
com.htc.upm.vive.openxr/Runtime/Common/ViveEnterpriseCommand.cs
Normal file
278
com.htc.upm.vive.openxr/Runtime/Common/ViveEnterpriseCommand.cs
Normal file
@@ -0,0 +1,278 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
namespace VIVE.OpenXR.Enterprise
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Enterprise Command",
|
||||
Desc = "Support Enterprise request with special command",
|
||||
Company = "HTC",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionString,
|
||||
Version = "0.1",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
FeatureId = featureId,
|
||||
Hidden = true
|
||||
)]
|
||||
#endif
|
||||
public class ViveEnterpriseCommand : OpenXRFeature
|
||||
{
|
||||
#region Log
|
||||
const string LOG_TAG = "VIVE.OpenXR.Enterprise.Command ";
|
||||
private static void DEBUG(String msg) { Debug.Log(LOG_TAG + msg); }
|
||||
private static void ERROR(String msg) { Debug.LogError(LOG_TAG + msg); }
|
||||
#endregion
|
||||
|
||||
/// <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.enterprise.command";
|
||||
|
||||
/// <summary>
|
||||
/// The extension string.
|
||||
/// </summary>
|
||||
public const string kOpenxrExtensionString = "XR_HTC_enterprise_command";
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
private static bool m_XrInstanceCreated = false;
|
||||
private static bool m_XrSessionCreated = false;
|
||||
private static XrInstance m_XrInstance = 0;
|
||||
private static XrSession m_XrSession = 0;
|
||||
private static XrSystemId m_XrSystemId = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateInstance">xrCreateInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The created instance.</param>
|
||||
/// <returns>True for valid <see cref="XrInstance">XrInstance</see></returns>
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
{
|
||||
ERROR($"OnInstanceCreate() {kOpenxrExtensionString} is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_XrInstanceCreated = true;
|
||||
m_XrInstance = xrInstance;
|
||||
DEBUG($"OnInstanceCreate() {m_XrInstance}");
|
||||
|
||||
return GetXrFunctionDelegates(m_XrInstance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroyInstance">xrDestroyInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The instance to destroy.</param>
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
if (m_XrInstance == xrInstance)
|
||||
{
|
||||
m_XrInstanceCreated = false;
|
||||
m_XrInstance = 0;
|
||||
}
|
||||
DEBUG($"OnInstanceDestroy() {xrInstance}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the <see cref="XrSystemId">XrSystemId</see> retrieved by <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystem">xrGetSystem</see> is changed.
|
||||
/// </summary>
|
||||
/// <param name="xrSystem">The system id.</param>
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
m_XrSystemId = xrSystem;
|
||||
DEBUG($"OnSystemChange() {m_XrSystemId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateSession">xrCreateSession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The created session ID.</param>
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
m_XrSession = xrSession;
|
||||
m_XrSessionCreated = true;
|
||||
DEBUG($"OnSessionCreate() {m_XrSession}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroySession">xrDestroySession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The session ID to destroy.</param>
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
DEBUG($"OnSessionDestroy() {xrSession}");
|
||||
|
||||
if (m_XrSession == xrSession)
|
||||
{
|
||||
m_XrSession = 0;
|
||||
m_XrSessionCreated = false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OpenXR function delegates
|
||||
/// xrEnterpriseCommandHTC
|
||||
private static ViveEnterpriseCommandHelper.xrEnterpriseCommandHTCDelegate xrEnterpriseCommandHTC;
|
||||
/// xrGetInstanceProcAddr
|
||||
private static OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr;
|
||||
|
||||
/// <summary>
|
||||
/// Enterprise command request for special functionality.
|
||||
/// </summary>
|
||||
/// <param name="request">The request of enterprise command</param>
|
||||
/// <param name="result">The result of enterprise command</param>
|
||||
/// <returns>Return XR_SUCCESS if request successfully. False otherwise.</returns>
|
||||
private static XrResult EnterpriseCommandHTC(XrEnterpriseCommandBufferHTC request, ref XrEnterpriseCommandBufferHTC result)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("EnterpriseCommandHTC() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("EnterpriseCommandHTC() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
DEBUG($"EnterpriseCommandHTC() code: {request.code}, data: {CharArrayToString(request.data)}");
|
||||
return xrEnterpriseCommandHTC(m_XrSession, request, ref result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the OpenXR function via XrInstance.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The XrInstance is provided by the Unity OpenXR Plugin.</param>
|
||||
/// <returns>Return true if request successfully. False otherwise.</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// xrEnterpriseCommandHTC
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrEnterpriseCommandHTC", out IntPtr funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrEnterpriseCommandHTC.");
|
||||
xrEnterpriseCommandHTC = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(ViveEnterpriseCommandHelper.xrEnterpriseCommandHTCDelegate)) as ViveEnterpriseCommandHelper.xrEnterpriseCommandHTCDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrEnterpriseCommandHTC");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public API
|
||||
private const int kCharLength = 256;
|
||||
private const char kEndChar = '\0';
|
||||
private static char[] charArray = new char[kCharLength];
|
||||
|
||||
/// <summary>
|
||||
/// Request special feature with command, it should take code and command string.
|
||||
/// </summary>
|
||||
/// <param name="requestCode">The type of request code is integer.</param>
|
||||
/// <param name="requestCommand">The maximum length of request command is 256.</param>
|
||||
/// <param name="resultCode">The output of result code.</param>
|
||||
/// <param name="resultCommand">The output of result command.</param>
|
||||
/// <returns>Return true if request successfully. False otherwise.</returns>
|
||||
public static bool CommandRequest(int requestCode, string requestCommand, out int resultCode, out string resultCommand)
|
||||
{
|
||||
resultCode = 0;
|
||||
resultCommand = string.Empty;
|
||||
XrEnterpriseCommandBufferHTC request = new XrEnterpriseCommandBufferHTC(requestCode, StringToCharArray(requestCommand));
|
||||
XrEnterpriseCommandBufferHTC result = new XrEnterpriseCommandBufferHTC(resultCode, StringToCharArray(resultCommand));
|
||||
if (EnterpriseCommandHTC(request, ref result) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
resultCode = result.code;
|
||||
resultCommand = CharArrayToString(result.data);
|
||||
DEBUG($"CommandRequest Result code: {resultCode}, data: {resultCommand}");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static char[] StringToCharArray(string str)
|
||||
{
|
||||
Array.Clear(charArray, 0, kCharLength);
|
||||
if (!string.IsNullOrEmpty(str))
|
||||
{
|
||||
int arrayLength = Math.Min(str.Length, kCharLength);
|
||||
for (int i = 0; i < arrayLength; i++)
|
||||
{
|
||||
charArray[i] = str[i];
|
||||
}
|
||||
charArray[kCharLength - 1] = kEndChar;
|
||||
}
|
||||
return charArray;
|
||||
}
|
||||
|
||||
private static string CharArrayToString(char[] charArray)
|
||||
{
|
||||
int actualLength = Array.FindIndex(charArray, c => c == kEndChar);
|
||||
if (actualLength == -1)
|
||||
{
|
||||
actualLength = charArray.Length;
|
||||
}
|
||||
|
||||
return new string(charArray, 0, actualLength);
|
||||
}
|
||||
}
|
||||
|
||||
#region Helper
|
||||
public struct XrEnterpriseCommandBufferHTC
|
||||
{
|
||||
public Int32 code;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
|
||||
public char[] data;
|
||||
|
||||
public XrEnterpriseCommandBufferHTC(int in_code, char[] in_data)
|
||||
{
|
||||
code = (Int32)in_code;
|
||||
data = new char[in_data.Length];
|
||||
Array.Copy(in_data, data, in_data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public class ViveEnterpriseCommandHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// The function delegate of xrEnterpriseCommandHTC.
|
||||
/// </summary>
|
||||
/// <param name="session">An <see cref="XrSession">XrSession</see> in which the enterprise command will be active.</param>
|
||||
/// <param name="request">The request of enterprise command</param>
|
||||
/// <param name="result">The result of enterprise command</param>
|
||||
/// <returns>Return XR_SUCCESS if request successfully. False otherwise.</returns>
|
||||
public delegate XrResult xrEnterpriseCommandHTCDelegate(
|
||||
XrSession session,
|
||||
XrEnterpriseCommandBufferHTC request,
|
||||
ref XrEnterpriseCommandBufferHTC result);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5b2125d5dc73694eaed34e97a0962e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -10,9 +10,14 @@ 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().
|
||||
///
|
||||
/// Note:
|
||||
/// In Standardalone's OpenXR MockRuntime, the CreateSwapchain and EnumerateSwapchainImages will work and return success,
|
||||
/// but the images's native pointer will be null.
|
||||
/// </summary>
|
||||
public class CommonWrapper : ViveFeatureWrapperBase<CommonWrapper>, IViveFeatureWrapper
|
||||
internal class CommonWrapper : ViveFeatureWrapperBase<CommonWrapper>, IViveFeatureWrapper
|
||||
{
|
||||
const string TAG = "CommonWrapper";
|
||||
OpenXRHelper.xrGetSystemPropertiesDelegate XrGetSystemProperties;
|
||||
OpenXRHelper.xrCreateSwapchainDelegate XrCreateSwapchain;
|
||||
OpenXRHelper.xrDestroySwapchainDelegate XrDestroySwapchain;
|
||||
@@ -32,11 +37,13 @@ namespace VIVE.OpenXR.Feature
|
||||
public bool OnInstanceCreate(XrInstance xrInstance, IntPtr xrGetInstanceProcAddrPtr)
|
||||
{
|
||||
if (IsInited) return true;
|
||||
if (TryInited) return false;
|
||||
TryInited = true;
|
||||
|
||||
if (xrInstance == 0)
|
||||
throw new Exception("CommonWrapper: xrInstance is null");
|
||||
|
||||
Debug.Log("CommonWrapper: OnInstanceCreate()");
|
||||
Log.D(TAG, "OnInstanceCreate()");
|
||||
SetGetInstanceProcAddrPtr(xrGetInstanceProcAddrPtr);
|
||||
|
||||
bool ret = true;
|
||||
@@ -64,9 +71,11 @@ namespace VIVE.OpenXR.Feature
|
||||
/// <returns></returns>
|
||||
public void OnInstanceDestroy()
|
||||
{
|
||||
// Do not destroy twice
|
||||
if (IsInited == false) return;
|
||||
IsInited = false;
|
||||
XrGetSystemProperties = null;
|
||||
Debug.Log("CommonWrapper: OnInstanceDestroy()");
|
||||
Log.D(TAG, "OnInstanceDestroy()");
|
||||
}
|
||||
|
||||
public XrResult GetInstanceProcAddr(XrInstance instance, string name, out IntPtr function)
|
||||
@@ -164,12 +173,12 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
if (formatCapacityInput == 0)
|
||||
{
|
||||
Debug.Log("CommonWrapper: EnumerateSwapchainFormats(ci=" + formatCapacityInput + ")");
|
||||
Log.D(TAG, "EnumerateSwapchainFormats(ci=" + formatCapacityInput + ")");
|
||||
return XrEnumerateSwapchainFormats(session, 0, ref formatCountOutput, IntPtr.Zero);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("CommonWrapper: EnumerateSwapchainFormats(ci=" + formatCapacityInput + ", formats=long[" + formats.Length + "])");
|
||||
Log.D(TAG, "EnumerateSwapchainFormats(ci=" + formatCapacityInput + ", formats=long[" + formats.Length + "])");
|
||||
IntPtr formatsPtr = MemoryTools.MakeRawMemory(formats);
|
||||
var ret = XrEnumerateSwapchainFormats(session, formatCapacityInput, ref formatCountOutput, formatsPtr);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace VIVE.OpenXR.Feature
|
||||
/// </summary>
|
||||
public class FutureWrapper : ViveFeatureWrapperBase<FutureWrapper>, IViveFeatureWrapper
|
||||
{
|
||||
const string TAG = "ViveFuture";
|
||||
|
||||
public enum XrFutureStateEXT
|
||||
{
|
||||
None = 0, // Not defined in extension. A default value.
|
||||
@@ -76,6 +78,8 @@ namespace VIVE.OpenXR.Feature
|
||||
public bool OnInstanceCreate(XrInstance xrInstance, IntPtr xrGetInstanceProcAddrPtr)
|
||||
{
|
||||
if (IsInited) return true;
|
||||
if (TryInited) return false;
|
||||
TryInited = true;
|
||||
|
||||
if (xrInstance == null)
|
||||
throw new Exception("FutureWrapper: xrInstance is null");
|
||||
@@ -85,12 +89,12 @@ namespace VIVE.OpenXR.Feature
|
||||
throw new Exception("FutureWrapper: xrGetInstanceProcAddr is null");
|
||||
SetGetInstanceProcAddrPtr(xrGetInstanceProcAddrPtr);
|
||||
|
||||
Debug.Log("FutureWrapper: OnInstanceCreate()");
|
||||
Log.D(TAG, "OnInstanceCreate()");
|
||||
|
||||
bool hasFuture = OpenXRRuntime.IsExtensionEnabled("XR_EXT_future");
|
||||
if (!hasFuture)
|
||||
{
|
||||
Debug.LogError("FutureWrapper: XR_EXT_future is not enabled. Check your feature's kOpenxrExtensionString.");
|
||||
Log.E(TAG, "FutureWrapper: XR_EXT_future is not enabled. Check your feature's kOpenxrExtensionString.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -102,7 +106,7 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
Debug.LogError("FutureWrapper: Failed to get function pointer.");
|
||||
Log.E(TAG,"FutureWrapper: Failed to get function pointer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -112,7 +116,7 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
public void OnInstanceDestroy()
|
||||
{
|
||||
Debug.Log("FutureWrapper: OnInstanceDestroy()");
|
||||
Log.D(TAG, "OnInstanceDestroy()");
|
||||
IsInited = false;
|
||||
XrPollFutureEXT = null;
|
||||
XrCancelFutureEXT = null;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR.Feature
|
||||
@@ -12,9 +13,13 @@ namespace VIVE.OpenXR.Feature
|
||||
/// </summary>
|
||||
public class SpaceWrapper : ViveFeatureWrapperBase<SpaceWrapper>, IViveFeatureWrapper
|
||||
{
|
||||
const string TAG = "ViveSpaceWrapper";
|
||||
|
||||
public delegate XrResult DelegateXrEnumerateReferenceSpaces(XrSession session, uint spaceCapacityInput, out uint spaceCountOutput, [Out] XrReferenceSpaceType[] spaces);
|
||||
delegate XrResult DelegateXrLocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, ref XrSpaceLocation location);
|
||||
delegate XrResult DelegateXrDestroySpace(XrSpace space);
|
||||
|
||||
DelegateXrEnumerateReferenceSpaces XrEnumerateReferenceSpaces;
|
||||
OpenXRHelper.xrCreateReferenceSpaceDelegate XrCreateReferenceSpace;
|
||||
DelegateXrLocateSpace XrLocateSpace;
|
||||
DelegateXrDestroySpace XrDestroySpace;
|
||||
@@ -29,17 +34,20 @@ namespace VIVE.OpenXR.Feature
|
||||
public bool OnInstanceCreate(XrInstance xrInstance, IntPtr GetAddr)
|
||||
{
|
||||
if (IsInited) return true;
|
||||
if (TryInited) return false;
|
||||
TryInited = true;
|
||||
|
||||
if (xrInstance == null)
|
||||
throw new Exception("ViveSpace: xrInstance is null");
|
||||
throw new Exception("ViveSpaceWrapper: xrInstance is null");
|
||||
|
||||
SetGetInstanceProcAddrPtr(GetAddr);
|
||||
|
||||
Debug.Log("ViveSpace: OnInstanceCreate()");
|
||||
Log.D(TAG, "OnInstanceCreate()");
|
||||
|
||||
bool ret = true;
|
||||
IntPtr funcPtr = IntPtr.Zero;
|
||||
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(xrGetInstanceProcAddr, xrInstance, "xrEnumerateReferenceSpaces", out XrEnumerateReferenceSpaces);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(xrGetInstanceProcAddr, xrInstance, "xrCreateReferenceSpace", out XrCreateReferenceSpace);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(xrGetInstanceProcAddr, xrInstance, "xrLocateSpace", out XrLocateSpace);
|
||||
ret &= OpenXRHelper.GetXrFunctionDelegate(xrGetInstanceProcAddr, xrInstance, "xrDestroySpace", out XrDestroySpace);
|
||||
@@ -49,12 +57,35 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
public void OnInstanceDestroy()
|
||||
{
|
||||
// Do not destroy twice
|
||||
if (IsInited == false) return;
|
||||
IsInited = false;
|
||||
XrEnumerateReferenceSpaces = null;
|
||||
XrCreateReferenceSpace = null;
|
||||
XrLocateSpace = null;
|
||||
XrDestroySpace = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="session"></param>
|
||||
/// <param name="spaceCapacityInput"></param>
|
||||
/// <param name="spaceCountOutput"></param>
|
||||
/// <param name="spaces"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult EnumerateReferenceSpaces(XrSession session, int spaceCapacityInput, ref int spaceCountOutput, ref XrReferenceSpaceType[] spaces)
|
||||
{
|
||||
spaceCountOutput = 0;
|
||||
if (!IsInited)
|
||||
return XrResult.XR_ERROR_HANDLE_INVALID;
|
||||
if (spaceCapacityInput != 0 && spaces != null && spaces.Length < spaceCapacityInput)
|
||||
return XrResult.XR_ERROR_SIZE_INSUFFICIENT;
|
||||
var ret = XrEnumerateReferenceSpaces(session, (uint)spaceCapacityInput, out uint spaceCountOutputXR, spaces);
|
||||
spaceCountOutput = (int)spaceCountOutputXR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a reference space without create info.
|
||||
/// Example:
|
||||
@@ -108,7 +139,7 @@ namespace VIVE.OpenXR.Feature
|
||||
{
|
||||
if (!IsInited)
|
||||
return XrResult.XR_ERROR_HANDLE_INVALID;
|
||||
Debug.Log($"DestroySpace({space})");
|
||||
Log.D(TAG, $"DestroySpace({space})");
|
||||
return XrDestroySpace(space);
|
||||
}
|
||||
}
|
||||
@@ -124,7 +155,7 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
public Space(XrSpace space)
|
||||
{
|
||||
Debug.Log($"Space({space})");
|
||||
Log.D($"Space({space})");
|
||||
this.space = space;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,25 @@ using UnityEngine;
|
||||
using AOT;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
internal class HookHandlerAttribute : Attribute
|
||||
{
|
||||
public string xrFuncName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Set this function to handle the hook process in <see cref="ViveInterceptors.XrGetInstanceProcAddrInterceptor" />
|
||||
/// </summary>
|
||||
/// <param name="xrFuncName">The hooked openxr function name</param>
|
||||
public HookHandlerAttribute(string xrFuncName)
|
||||
{
|
||||
this.xrFuncName = xrFuncName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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.
|
||||
@@ -22,6 +38,15 @@ namespace VIVE.OpenXR
|
||||
/// return ViveInterceptors.Instance.HookGetInstanceProcAddr(func);
|
||||
/// }
|
||||
/// </summary>
|
||||
|
||||
// For extending the ViveInterceptors class, create a new partial class and implement the required functions.
|
||||
// For example:
|
||||
// public partial class ViveInterceptors
|
||||
// {
|
||||
// [HookHandler("xrYourFunction")]
|
||||
// private static XrResult OnHookXrYourFunction(XrInstance instance, string name, out IntPtr function)
|
||||
// { ... }
|
||||
// }
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
public const string TAG = "VIVE.OpenXR.ViveInterceptors";
|
||||
@@ -32,8 +57,6 @@ namespace VIVE.OpenXR
|
||||
return m_sb;
|
||||
}
|
||||
}
|
||||
static void DEBUG(StringBuilder msg) { Debug.LogFormat("{0} {1}", TAG, msg); }
|
||||
static void ERROR(StringBuilder msg) { Debug.LogErrorFormat("{0} {1}", TAG, msg); }
|
||||
|
||||
public static ViveInterceptors instance = null;
|
||||
public static ViveInterceptors Instance
|
||||
@@ -48,15 +71,32 @@ namespace VIVE.OpenXR
|
||||
|
||||
public ViveInterceptors()
|
||||
{
|
||||
Debug.Log("ViveInterceptors");
|
||||
Log.D("ViveInterceptors");
|
||||
RegisterFunctions();
|
||||
}
|
||||
|
||||
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;
|
||||
delegate XrResult HookHandler(XrInstance instance, string name, out IntPtr function);
|
||||
static readonly Dictionary<string, HookHandler> interceptors = new Dictionary<string, HookHandler>();
|
||||
|
||||
[MonoPInvokeCallback(typeof(DelegateXrGetInstanceProcAddr))]
|
||||
private static void RegisterFunctions()
|
||||
{
|
||||
var methods = typeof(ViveInterceptors).GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||
foreach (var method in methods)
|
||||
{
|
||||
var attribute = method.GetCustomAttributes(typeof(HookHandlerAttribute), false).FirstOrDefault() as HookHandlerAttribute;
|
||||
if (attribute != null)
|
||||
{
|
||||
Log.I(TAG, $"Registering hook handler {attribute.xrFuncName}");
|
||||
interceptors.Add(attribute.xrFuncName, (HookHandler)method.CreateDelegate(typeof(HookHandler)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly OpenXRHelper.xrGetInstanceProcAddrDelegate hookXrGetInstanceProcAddrHandle = new OpenXRHelper.xrGetInstanceProcAddrDelegate(XrGetInstanceProcAddrInterceptor);
|
||||
private static readonly IntPtr hookGetInstanceProcAddrHandlePtr = Marshal.GetFunctionPointerForDelegate(hookXrGetInstanceProcAddrHandle);
|
||||
static OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddrOriginal = null;
|
||||
|
||||
[MonoPInvokeCallback(typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate))]
|
||||
private static XrResult XrGetInstanceProcAddrInterceptor(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
// Used to check if the original function is already hooked.
|
||||
@@ -66,64 +106,16 @@ namespace VIVE.OpenXR
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
// Custom interceptors
|
||||
if (name == "xrWaitFrame" && requiredFunctions.Contains(name))
|
||||
// Check if the function is intercepted by other features
|
||||
if (interceptors.ContainsKey(name))
|
||||
{
|
||||
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;
|
||||
}
|
||||
// If no request for this function, call the original function directly.
|
||||
if (!requiredFunctions.Contains(name))
|
||||
return XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
|
||||
if (name == "xrEndFrame" && requiredFunctions.Contains(name))
|
||||
{
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
var ret = interceptors[name](instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
XrEndFrameOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrEndFrame>(function);
|
||||
function = xrEndFrameInterceptorPtr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if PERFORMANCE_TEST
|
||||
if (name == "xrLocateSpace" && requiredFunctions.Contains(name))
|
||||
{
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
XrLocateSpaceOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrLocateSpace>(function);
|
||||
function = xrLocateSpaceInterceptorPtr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if (name == "xrPollEvent" && requiredFunctions.Contains(name))
|
||||
{
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
xrPollEventOrigin = Marshal.GetDelegateForFunctionPointer < xrPollEventDelegate > (function);
|
||||
function = xrPollEventPtr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (name == "xrBeginSession" && requiredFunctions.Contains(name))
|
||||
{
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
xrBeginSessionOrigin = Marshal.GetDelegateForFunctionPointer<xrBeginSessionDelegate>(function);
|
||||
function = xrBeginSessionPtr;
|
||||
}
|
||||
Log.I(TAG, name + " is intercepted");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -132,23 +124,23 @@ namespace VIVE.OpenXR
|
||||
|
||||
public IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
{
|
||||
Debug.Log($"{TAG}: HookGetInstanceProcAddr");
|
||||
Log.D(TAG, "HookGetInstanceProcAddr");
|
||||
if (XrGetInstanceProcAddrOriginal == null)
|
||||
{
|
||||
Debug.Log($"{TAG}: registering our own xrGetInstanceProcAddr");
|
||||
XrGetInstanceProcAddrOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrGetInstanceProcAddr>(func);
|
||||
Log.D(TAG, "registering our own xrGetInstanceProcAddr");
|
||||
XrGetInstanceProcAddrOriginal = Marshal.GetDelegateForFunctionPointer<OpenXRHelper.xrGetInstanceProcAddrDelegate>(func);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor) {
|
||||
// This is a trick to check if the original function is already hooked by this class. Sometimes, the static XrGetInstanceProcAddrOriginal didn't work as expected.
|
||||
Debug.Log($"{TAG}: Check if duplicate hooked by this script with instance=0 and \"ViveInterceptorHooked\" name. If following a loader error, ignore it.");
|
||||
Log.D(TAG, "Check if duplicate hooked by this script with instance=0 and \"ViveInterceptorHooked\" name. If following a loader error, ignore it.");
|
||||
// E OpenXR-Loader: Error [SPEC | xrGetInstanceProcAddr | VUID-xrGetInstanceProcAddr-instance-parameter] : XR_NULL_HANDLE for instance but query for ViveInterceptorHooked requires a valid instance
|
||||
|
||||
// Call XrGetInstanceProcAddrOriginal to check if the original function is already hooked by this class
|
||||
if (XrGetInstanceProcAddrOriginal(0, "ViveInterceptorHooked", out IntPtr function) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
// If it is called successfully, it means the original function is already hooked. So we should return the original function.
|
||||
Debug.Log($"{TAG}: Already hooked");
|
||||
Log.D(TAG, "Already hooked");
|
||||
return func;
|
||||
}
|
||||
}
|
||||
@@ -173,9 +165,34 @@ namespace VIVE.OpenXR
|
||||
/// <param name="name"></param>
|
||||
public void AddRequiredFunction(string name)
|
||||
{
|
||||
if (requiredFunctions.Contains(name)) return;
|
||||
Debug.Log($"{TAG}: AddRequiredFunction({name})");
|
||||
Log.D(TAG, $"AddRequiredFunction({name})");
|
||||
if (!interceptors.ContainsKey(name))
|
||||
{
|
||||
Log.E(TAG, $"AddRequiredFunction({name}) failed. No such function.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!requiredFunctions.Contains(name))
|
||||
requiredFunctions.Add(name);
|
||||
|
||||
// If your function support unregister, you can add the reference count here.
|
||||
if (name == "xrLocateViews")
|
||||
xrLocateViewsReferenceCount++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If no need to use this hooked function, call this will remove your requirement.
|
||||
/// If all requirements are removed, the original function will be called directly.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void RemoveRequiredFunction(string name)
|
||||
{
|
||||
// If your function support unregister, you can add the reference count here.
|
||||
if (requiredFunctions.Contains(name))
|
||||
{
|
||||
if (name == "xrLocateViews")
|
||||
xrLocateViewsReferenceCount = Mathf.Max(xrLocateViewsReferenceCount--, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,21 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrBeginSession")]
|
||||
private static XrResult OnHookXrBeginSession(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (xrBeginSessionOrigin == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
xrBeginSessionOrigin = Marshal.GetDelegateForFunctionPointer<xrBeginSessionDelegate>(function);
|
||||
}
|
||||
function = xrBeginSessionPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#region xrBeginSession
|
||||
public delegate XrResult xrBeginSessionDelegate(XrSession session, ref XrSessionBeginInfo beginInfo);
|
||||
private static xrBeginSessionDelegate xrBeginSessionOrigin = null;
|
||||
@@ -19,7 +34,7 @@ namespace VIVE.OpenXR
|
||||
[MonoPInvokeCallback(typeof(xrBeginSessionDelegate))]
|
||||
private static XrResult xrBeginSessionInterceptor(XrSession session, ref XrSessionBeginInfo beginInfo)
|
||||
{
|
||||
Profiler.BeginSample("ViveInterceptors:BeginSession");
|
||||
Profiler.BeginSample("VI:BeginSession");
|
||||
XrResult result = XrResult.XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
|
||||
if (xrBeginSessionOrigin != null)
|
||||
@@ -48,7 +63,8 @@ namespace VIVE.OpenXR
|
||||
IntPtr fs_begin_info_ptr = new IntPtr(offset);
|
||||
XrFrameSynchronizationSessionBeginInfoHTC fsBeginInfo = (XrFrameSynchronizationSessionBeginInfoHTC)Marshal.PtrToStructure(fs_begin_info_ptr, typeof(XrFrameSynchronizationSessionBeginInfoHTC));
|
||||
|
||||
sb.Clear().Append("xrBeginSessionInterceptor() beginInfo.next = (").Append(fsBeginInfo.type).Append(", ").Append(fsBeginInfo.mode).Append(")"); DEBUG(sb);
|
||||
sb.Clear().Append("xrBeginSessionInterceptor() beginInfo.next = (").Append(fsBeginInfo.type).Append(", ").Append(fsBeginInfo.mode).Append(")");
|
||||
Log.D(sb);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -56,7 +72,7 @@ namespace VIVE.OpenXR
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Clear().Append("xrBeginSessionInterceptor() Not assign xrBeginSession!"); ERROR(sb);
|
||||
Log.E("xrBeginSessionInterceptor() Not assign xrBeginSession!");
|
||||
}
|
||||
Profiler.EndSample();
|
||||
|
||||
@@ -79,7 +95,8 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
m_EnableFrameSynchronization = active;
|
||||
m_FrameSynchronizationMode = mode;
|
||||
sb.Clear().Append("ActivateFrameSynchronization() ").Append(active ? "enable " : "disable ").Append(mode); DEBUG(sb);
|
||||
sb.Clear().Append("ActivateFrameSynchronization() ").Append(active ? "enable " : "disable ").Append(mode);
|
||||
Log.D(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using AOT;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrLocateViews")]
|
||||
private static XrResult OnHookXrLocateViews(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (xrLocateViewsOriginal == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
xrLocateViewsOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrLocateViews>(function);
|
||||
}
|
||||
function = xrLocateViewsInterceptorPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
public struct XrViewLocateInfo
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrViewConfigurationType viewConfigurationType;
|
||||
public XrTime displayTime;
|
||||
public XrSpace space;
|
||||
}
|
||||
|
||||
public struct XrView
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrPosef pose;
|
||||
public XrFovf fov;
|
||||
}
|
||||
|
||||
public enum XrViewStateFlags {
|
||||
ORIENTATION_VALID_BIT = 0x00000001,
|
||||
POSITION_VALID_BIT = 0x00000002,
|
||||
ORIENTATION_TRACKED_BIT = 0x00000004,
|
||||
POSITION_TRACKED_BIT = 0x00000008,
|
||||
}
|
||||
|
||||
public struct XrViewState
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrViewStateFlags viewStateFlags;
|
||||
}
|
||||
|
||||
public delegate XrResult DelegateXrLocateViews(XrSession session, IntPtr /*XrViewLocateInfo*/ viewLocateInfo, IntPtr /*XrViewState*/ viewState, uint viewCapacityInput, ref uint viewCountOutput, IntPtr /*XrView*/ views);
|
||||
|
||||
private static readonly DelegateXrLocateViews xrLocateViewsInterceptorHandle = new DelegateXrLocateViews(XrLocateViewsInterceptor);
|
||||
private static readonly IntPtr xrLocateViewsInterceptorPtr = Marshal.GetFunctionPointerForDelegate(xrLocateViewsInterceptorHandle);
|
||||
static DelegateXrLocateViews xrLocateViewsOriginal = null;
|
||||
static int xrLocateViewsReferenceCount = 0;
|
||||
|
||||
[MonoPInvokeCallback(typeof(DelegateXrLocateViews))]
|
||||
private static XrResult XrLocateViewsInterceptor(XrSession session, IntPtr viewLocateInfo, IntPtr viewState, uint viewCapacityInput, ref uint viewCountOutput, IntPtr views)
|
||||
{
|
||||
// Call the original function if the reference count is less than or equal to 0
|
||||
if (xrLocateViewsReferenceCount <= 0)
|
||||
return xrLocateViewsOriginal(session, viewLocateInfo, viewState, viewCapacityInput, ref viewCountOutput, views);
|
||||
|
||||
Profiler.BeginSample("VI:LocateViewsA");
|
||||
XrResult result = XrResult.XR_SUCCESS;
|
||||
if (instance.BeforeOriginalLocateViews != null)
|
||||
instance.BeforeOriginalLocateViews(session, viewLocateInfo, viewState, viewCapacityInput, ref viewCountOutput, views);
|
||||
Profiler.EndSample();
|
||||
result = xrLocateViewsOriginal(session, viewLocateInfo, viewState, viewCapacityInput, ref viewCountOutput, views);
|
||||
Profiler.BeginSample("VI:LocateViewsB");
|
||||
instance.AfterOriginalLocateViews?.Invoke(session, viewLocateInfo, viewState, viewCapacityInput, ref viewCountOutput, views);
|
||||
Profiler.EndSample();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If you return false, the original function will not be called.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public delegate bool DelegateXrLocateViewsInterceptor(XrSession session, IntPtr viewLocateInfo, IntPtr viewState, uint viewCapacityInput, ref uint viewCountOutput, IntPtr views);
|
||||
|
||||
/// <summary>
|
||||
/// Use this to intercept the original function. This will be called before the original function.
|
||||
/// </summary>
|
||||
public DelegateXrLocateViewsInterceptor BeforeOriginalLocateViews;
|
||||
|
||||
/// <summary>
|
||||
/// Use this to intercept the original function. This will be called after the original function.
|
||||
/// </summary>
|
||||
public DelegateXrLocateViewsInterceptor AfterOriginalLocateViews;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5dfd24c69475c3740975bf5538de3869
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -12,6 +12,20 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrPollEvent")]
|
||||
private static XrResult OnHookXrPollEvent(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (xrPollEventOrigin == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
xrPollEventOrigin = Marshal.GetDelegateForFunctionPointer<xrPollEventDelegate>(function);
|
||||
}
|
||||
function = xrPollEventPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
#region xrPollEvent
|
||||
public delegate XrResult xrPollEventDelegate(XrInstance instance, ref XrEventDataBuffer eventData);
|
||||
private static xrPollEventDelegate xrPollEventOrigin = null;
|
||||
@@ -19,7 +33,7 @@ namespace VIVE.OpenXR
|
||||
[MonoPInvokeCallback(typeof(xrPollEventDelegate))]
|
||||
private static XrResult xrPollEventInterceptor(XrInstance instance, ref XrEventDataBuffer eventData)
|
||||
{
|
||||
Profiler.BeginSample("ViveInterceptors:WaitFrame");
|
||||
Profiler.BeginSample("VI:PollEvent");
|
||||
XrResult result = XrResult.XR_SUCCESS;
|
||||
|
||||
if (xrPollEventOrigin != null)
|
||||
@@ -28,7 +42,7 @@ namespace VIVE.OpenXR
|
||||
|
||||
if (result == XrResult.XR_SUCCESS)
|
||||
{
|
||||
sb.Clear().Append("xrPollEventInterceptor() xrPollEvent ").Append(eventData.type); DEBUG(sb);
|
||||
sb.Clear().Append("xrPollEventInterceptor() xrPollEvent ").Append(eventData.type); Log.D("PollEvent", sb);
|
||||
switch(eventData.type)
|
||||
{
|
||||
case XrStructureType.XR_TYPE_EVENT_DATA_PASSTHROUGH_CONFIGURATION_IMAGE_RATE_CHANGED_HTC:
|
||||
@@ -41,7 +55,7 @@ namespace VIVE.OpenXR
|
||||
.Append(", fromImageRatesrc.dstImageRate: ").Append(fromImageRate.dstImageRate)
|
||||
.Append(", toImageRate.srcImageRate: ").Append(toImageRate.srcImageRate)
|
||||
.Append(", toImageRate.dstImageRate: ").Append(toImageRate.dstImageRate);
|
||||
DEBUG(sb);
|
||||
Log.D("PollEvent", sb.ToString());
|
||||
VivePassthroughImageRateChanged.Send(fromImageRate.srcImageRate, fromImageRate.dstImageRate, toImageRate.srcImageRate, toImageRate.dstImageRate);
|
||||
}
|
||||
break;
|
||||
@@ -53,7 +67,7 @@ namespace VIVE.OpenXR
|
||||
sb.Clear().Append("xrPollEventInterceptor() XR_TYPE_EVENT_DATA_PASSTHROUGH_CONFIGURATION_IMAGE_QUALITY_CHANGED_HTC")
|
||||
.Append(", fromImageQuality: ").Append(fromImageQuality.scale)
|
||||
.Append(", toImageQuality: ").Append(toImageQuality.scale);
|
||||
DEBUG(sb);
|
||||
Log.D("PollEvent", sb);
|
||||
VivePassthroughImageQualityChanged.Send(fromImageQuality.scale, toImageQuality.scale);
|
||||
}
|
||||
break;
|
||||
@@ -65,7 +79,7 @@ namespace VIVE.OpenXR
|
||||
sb.Clear().Append("xrPollEventInterceptor() XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB")
|
||||
.Append(", fromDisplayRefreshRate: ").Append(fromDisplayRefreshRate)
|
||||
.Append(", toDisplayRefreshRate: ").Append(toDisplayRefreshRate);
|
||||
DEBUG(sb);
|
||||
Log.D("PollEvent", sb);
|
||||
ViveDisplayRefreshRateChanged.Send(fromDisplayRefreshRate, toDisplayRefreshRate);
|
||||
}
|
||||
break;
|
||||
@@ -87,7 +101,7 @@ namespace VIVE.OpenXR
|
||||
.Append(", session: ").Append(eventDataSession.session)
|
||||
.Append(", state: ").Append(eventDataSession.state)
|
||||
.Append(", isUserPresent: ").Append(isUserPresent);
|
||||
DEBUG(sb);
|
||||
Log.D("PollEvent", sb);
|
||||
}
|
||||
break;
|
||||
case XrStructureType.XR_TYPE_EVENT_DATA_USER_PRESENCE_CHANGED_EXT:
|
||||
@@ -97,7 +111,7 @@ namespace VIVE.OpenXR
|
||||
sb.Clear().Append("xrPollEventInterceptor() XR_TYPE_EVENT_DATA_USER_PRESENCE_CHANGED_EXT")
|
||||
.Append(", session: ").Append(eventDataUserPresence.session)
|
||||
.Append(", isUserPresent: ").Append(isUserPresent);
|
||||
DEBUG(sb);
|
||||
Log.D("PollEvent", sb);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -105,7 +119,7 @@ namespace VIVE.OpenXR
|
||||
}
|
||||
}
|
||||
|
||||
//sb.Clear().Append("xrPollEventInterceptor() xrPollEvent result: ").Append(result).Append(", isUserPresent: ").Append(isUserPresent); DEBUG(sb);
|
||||
//sb.Clear().Append("xrPollEventInterceptor() xrPollEvent result: ").Append(result).Append(", isUserPresent: ").Append(isUserPresent); Log.d("PollEvent", sb);
|
||||
}
|
||||
Profiler.EndSample();
|
||||
|
||||
|
||||
@@ -8,6 +8,20 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrEndFrame")]
|
||||
private static XrResult OnHookXrEndFrame(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (XrEndFrameOriginal == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
XrEndFrameOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrEndFrame>(function);
|
||||
}
|
||||
function = xrEndFrameInterceptorPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
public struct XrCompositionLayerBaseHeader
|
||||
{
|
||||
public XrStructureType type; // This base structure itself has no associated XrStructureType value.
|
||||
@@ -37,15 +51,16 @@ namespace VIVE.OpenXR
|
||||
// instance must not null
|
||||
//if (instance == null)
|
||||
// return XrEndFrameOriginal(session, ref frameEndInfo);
|
||||
Profiler.BeginSample("VI:EndFrame");
|
||||
Profiler.BeginSample("VI:EndFrameB");
|
||||
XrResult result = XrResult.XR_SUCCESS;
|
||||
if (instance.BeforeOriginalEndFrame != null &&
|
||||
!instance.BeforeOriginalEndFrame(session, ref frameEndInfo, ref result))
|
||||
{
|
||||
bool ret = true;
|
||||
if (instance.BeforeOriginalEndFrame != null)
|
||||
ret = instance.BeforeOriginalEndFrame(session, ref frameEndInfo, ref result);
|
||||
Profiler.EndSample();
|
||||
if (!ret)
|
||||
return result;
|
||||
}
|
||||
result = XrEndFrameOriginal(session, ref frameEndInfo);
|
||||
Profiler.BeginSample("VI:EndFrameA");
|
||||
instance.AfterOriginalEndFrame?.Invoke(session, ref frameEndInfo, ref result);
|
||||
Profiler.EndSample();
|
||||
return result;
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using AOT;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrGetVisibilityMaskKHR")]
|
||||
private static XrResult OnHookXrGetVisibilityMaskKHR(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (xrGetVisibilityMaskKHROriginal == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
xrGetVisibilityMaskKHROriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrGetVisibilityMaskKHR>(function);
|
||||
}
|
||||
function = xrGetVisibilityMaskKHRInterceptorPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
public enum XrVisibilityMaskTypeKHR
|
||||
{
|
||||
HIDDEN_TRIANGLE_MESH_KHR = 1,
|
||||
VISIBLE_TRIANGLE_MESH_KHR = 2,
|
||||
LINE_LOOP_KHR = 3,
|
||||
}
|
||||
|
||||
public struct XrVisibilityMaskKHR
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint vertexCapacityInput;
|
||||
public uint vertexCountOutput;
|
||||
public IntPtr vertices; // XrVector2f array
|
||||
public uint indexCapacityInput;
|
||||
public uint indexCountOutput;
|
||||
public IntPtr indices; // uint array
|
||||
}
|
||||
|
||||
// XrCompositionLayerSpaceWarpInfoFlagsFB bits
|
||||
public delegate XrResult DelegateXrGetVisibilityMaskKHR(XrSession session, XrViewConfigurationType viewConfigurationType, uint viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, ref XrVisibilityMaskKHR visibilityMask);
|
||||
|
||||
private static readonly DelegateXrGetVisibilityMaskKHR xrGetVisibilityMaskKHRInterceptorHandle = new DelegateXrGetVisibilityMaskKHR(XrGetVisibilityMaskKHRInterceptor);
|
||||
private static readonly IntPtr xrGetVisibilityMaskKHRInterceptorPtr = Marshal.GetFunctionPointerForDelegate(xrGetVisibilityMaskKHRInterceptorHandle);
|
||||
static DelegateXrGetVisibilityMaskKHR xrGetVisibilityMaskKHROriginal = null;
|
||||
|
||||
[MonoPInvokeCallback(typeof(DelegateXrGetVisibilityMaskKHR))]
|
||||
private static XrResult XrGetVisibilityMaskKHRInterceptor(XrSession session, XrViewConfigurationType viewConfigurationType, uint viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, ref XrVisibilityMaskKHR visibilityMask)
|
||||
{
|
||||
// instance must not null
|
||||
//if (instance == null)
|
||||
// return XrGetVisibilityMaskKHROriginal(session, ref frameEndInfo);
|
||||
Profiler.BeginSample("VI:GetVMB");
|
||||
XrResult result = XrResult.XR_SUCCESS;
|
||||
bool ret = true;
|
||||
if (instance.BeforeOriginalGetVisibilityMaskKHR != null)
|
||||
ret = instance.BeforeOriginalGetVisibilityMaskKHR(session, viewConfigurationType, viewIndex, visibilityMaskType, ref visibilityMask, ref result);
|
||||
Profiler.EndSample();
|
||||
if (!ret)
|
||||
return result;
|
||||
result = xrGetVisibilityMaskKHROriginal(session, viewConfigurationType, viewIndex, visibilityMaskType, ref visibilityMask);
|
||||
Profiler.BeginSample("VI:GetVMA");
|
||||
instance.AfterOriginalGetVisibilityMaskKHR?.Invoke(session, viewConfigurationType, viewIndex, visibilityMaskType, ref visibilityMask, ref result);
|
||||
Profiler.EndSample();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If you return false, the original function will not be called.
|
||||
/// </summary>
|
||||
/// <param name="session"></param>
|
||||
/// <param name="frameEndInfo"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public delegate bool DelegateXrGetVisibilityMaskKHRInterceptor(XrSession session, XrViewConfigurationType viewConfigurationType, uint viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, ref XrVisibilityMaskKHR visibilityMask, ref XrResult result);
|
||||
|
||||
/// <summary>
|
||||
/// Use this to intercept the original function. This will be called before the original function.
|
||||
/// </summary>
|
||||
public DelegateXrGetVisibilityMaskKHRInterceptor BeforeOriginalGetVisibilityMaskKHR;
|
||||
|
||||
/// <summary>
|
||||
/// Use this to intercept the original function. This will be called after the original function.
|
||||
/// </summary>
|
||||
public DelegateXrGetVisibilityMaskKHRInterceptor AfterOriginalGetVisibilityMaskKHR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4c00b0b7df78d34d89cd728c9de0672
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -9,7 +9,20 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
#region XRWaitFrame
|
||||
[HookHandler("xrWaitFrame")]
|
||||
private static XrResult OnHookXrWaitFrame(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (XrWaitFrameOriginal == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
XrWaitFrameOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrWaitFrame>(function);
|
||||
}
|
||||
function = xrWaitFrameInterceptorPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
public struct XrFrameWaitInfo
|
||||
{
|
||||
public XrStructureType type;
|
||||
@@ -103,6 +116,5 @@ namespace VIVE.OpenXR
|
||||
/// Use this to intercept the original function. This will be called after the original function.
|
||||
/// </summary>
|
||||
public DelegateXrWaitFrameInterceptor AfterOriginalWaitFrame;
|
||||
#endregion XRWaitFrame
|
||||
}
|
||||
}
|
||||
|
||||
247
com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs
Normal file
247
com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs
Normal file
@@ -0,0 +1,247 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
using System.Text;
|
||||
// Non android will need UnityEngine
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public static class Log
|
||||
{
|
||||
public const string TAG = "VIVE.OpenXR";
|
||||
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
[DllImport("liblog.so")]
|
||||
private static extern int __android_log_print(int prio, string tag, string fmt, string msg);
|
||||
#endif
|
||||
|
||||
// Use ("%s", message) instead of just (message) is because of the following reason:
|
||||
// In case message contains special characters like %, \n, \r, etc. It will be treated as format string.
|
||||
// This is a little waste of performance, but it's safer.
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void D(string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, TAG, "%s", message); // Android Debug
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void I(string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, TAG, "%s", message); // Android Info
|
||||
#else
|
||||
Debug.Log(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void W(string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, TAG, "%s", message); // Android Warning
|
||||
#else
|
||||
Debug.LogWarning(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void E(string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, TAG, "%s", message); // Android Error
|
||||
#else
|
||||
Debug.LogError(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void D(string tag, string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, tag, "%s", message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void I(string tag, string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, tag, "%s", message);
|
||||
#else
|
||||
Debug.LogFormat("{0}: {1}", tag, message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void W(string tag, string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, tag, "%s", message); // Android Warning
|
||||
#else
|
||||
Debug.LogWarningFormat("{0}: {1}", tag, message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void E(string tag, string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, tag, "%s", message); // Android Error
|
||||
#else
|
||||
Debug.LogErrorFormat("{0}: {1}", tag, message);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void D(StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, TAG, "%s", message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void I(StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, TAG, "%s", message.ToString());
|
||||
#else
|
||||
Debug.Log(message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void W(StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, TAG, "%s", message.ToString()); // Android Warning
|
||||
#else
|
||||
Debug.LogWarning(message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void E(StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, TAG, "%s", message.ToString()); // Android Error
|
||||
#else
|
||||
Debug.LogError(message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void D(string tag, StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, tag, "%s", message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void I(string tag, StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, tag, "%s", message.ToString());
|
||||
#else
|
||||
Debug.LogFormat("{0}: {1}", tag, message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void W(string tag, StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, tag, "%s", message.ToString()); // Android Warning
|
||||
#else
|
||||
Debug.LogWarningFormat("{0}: {1}", tag, message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void E(string tag, StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, tag, "%s", message.ToString()); // Android Error
|
||||
#else
|
||||
Debug.LogErrorFormat("{0}: {1}", tag, message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void DFmt(string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, TAG, "%s", string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void IFmt(string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, TAG, "%s", string.Format(fmt, args));
|
||||
#else
|
||||
Debug.LogFormat(fmt, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void WFmt(string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, TAG, "%s", string.Format(fmt, args)); // Android Warning
|
||||
#else
|
||||
Debug.LogWarningFormat(fmt, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void EFmt(string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, TAG, "%s", string.Format(fmt, args)); // Android Error
|
||||
#else
|
||||
Debug.LogErrorFormat(fmt, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void DFmt(string tag, string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, tag, "%s", string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void IFmt(string tag, string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, tag, "%s", string.Format(fmt, args));
|
||||
#else
|
||||
Debug.LogFormat("{0}: {1}", tag, string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void WFmt(string tag, string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, tag, "%s", string.Format(fmt, args)); // Android Warning
|
||||
#else
|
||||
Debug.LogWarningFormat("{0}: {1}", tag, fmt, string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void EFmt(string tag, string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, tag, "%s", string.Format(fmt, args)); // Android Error
|
||||
#else
|
||||
Debug.LogErrorFormat("{0}: {1}", tag, fmt, string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
11
com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs.meta
Normal file
11
com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9750d8d4e8eb4994088534cb111510d3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -58,7 +58,8 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
isFree = true
|
||||
};
|
||||
pool.Insert(index, newItem);
|
||||
Debug.Log("RT.MessagePool.Obtain() pool count=" + pool.Count);
|
||||
//Log.d("RT.MessagePool.Obtain<" + typeof(T) + ">() pool count=" + pool.Count); // Not to expose developer's type.
|
||||
Log.D("RT.MessagePool.Obtain() pool count=" + pool.Count);
|
||||
return newItem;
|
||||
}
|
||||
|
||||
@@ -101,7 +102,8 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
/// The queueSize should be the double count of message you want to pass to render thread in one frame.
|
||||
/// </summary>
|
||||
/// <param name="queueSize"></param>
|
||||
public PreAllocatedQueue(int queueSize = 2) : base() {
|
||||
public PreAllocatedQueue(int queueSize = 2) : base()
|
||||
{
|
||||
for (int i = 0; i < queueSize; i++)
|
||||
{
|
||||
list.Add(null);
|
||||
@@ -221,7 +223,8 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
|
||||
~RenderThreadTask()
|
||||
{
|
||||
try { CommandList.RemoveAt(id); } finally { }
|
||||
// Remove could be in a random order, and will cause orderId change. DO not remove any of them.
|
||||
//try { CommandList.Remove(this); } finally { }
|
||||
}
|
||||
|
||||
void IssuePluginEvent(IntPtr callback, int eventID)
|
||||
@@ -287,22 +290,28 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
private static void SampleReceiver1(PreAllocatedQueue dataQueue)
|
||||
{
|
||||
var msg = dataQueue.Dequeue() as SampleMessage;
|
||||
// no need to check msg if it is null because your design should avoid it.
|
||||
if (msg != null)
|
||||
{
|
||||
// Keep data before release. Use local variable to keep data and release msg early. Should not keep the msg instance itself.
|
||||
var data = msg.dataPassedToRenderThread;
|
||||
// Make sure release the msg if finished. Other wise the memory will keep increasing when Obtain.
|
||||
MessagePool.Release(msg);
|
||||
|
||||
Debug.Log("Task1, the data passed to render thread: " + data);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SampleReceiver2(PreAllocatedQueue dataQueue)
|
||||
{
|
||||
var msg = dataQueue.Dequeue() as SampleMessage;
|
||||
if (msg != null)
|
||||
{
|
||||
// Keep data before release. Use local variable to keep data and release msg early. Should not keep the msg instance itself.
|
||||
var data = msg.dataPassedToRenderThread;
|
||||
// Make sure release the msg if finished. Other wise the memory will keep increasing when Obtain.
|
||||
MessagePool.Release(msg);
|
||||
Debug.Log("Task2, the data passed to render thread: " + data);
|
||||
}
|
||||
}
|
||||
|
||||
// Send a message to the render thread every frame.
|
||||
private void Update()
|
||||
|
||||
@@ -8,6 +8,7 @@ using UnityEngine.XR.OpenXR;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using VIVE.OpenXR.CompositionLayer;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
@@ -16,15 +17,18 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
#if UNITY_EDITOR
|
||||
[SerializeField]
|
||||
public bool isPreviewingCylinder = false;
|
||||
public bool isPreviewingEquirect = false;
|
||||
[SerializeField]
|
||||
public bool isPreviewingQuad = false;
|
||||
[SerializeField]
|
||||
public GameObject generatedPreview = null;
|
||||
|
||||
public const string CylinderPreviewName = "CylinderPreview";
|
||||
public const string EquirectPreviewName = "EquirectPreview";
|
||||
public const string QuadPreviewName = "QuadPreview";
|
||||
#endif
|
||||
public const string CylinderUnderlayMeshName = "Underlay Alpha Mesh (Cylinder)";
|
||||
public const string EquirectUnderlayMeshName = "Underlay Alpha Mesh (Equirect)";
|
||||
public const string QuadUnderlayMeshName = "Underlay Alpha Mesh (Quad)";
|
||||
public const string FallbackMeshName = "FallbackMeshGO";
|
||||
|
||||
@@ -56,6 +60,15 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
public float QuadHeight { get { return m_QuadHeight; } set { m_QuadHeight = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
[Min(0.001f)]
|
||||
private float m_CylinderRadius = 1f;
|
||||
public float cylinderRadius { get { return m_CylinderRadius; } }
|
||||
#if UNITY_EDITOR
|
||||
public float CylinderRadius { get { return m_CylinderRadius; } set { m_CylinderRadius = value; } }
|
||||
#endif
|
||||
|
||||
|
||||
[SerializeField]
|
||||
[Min(0.001f)]
|
||||
private float m_CylinderHeight = 1f;
|
||||
@@ -74,10 +87,66 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
|
||||
[SerializeField]
|
||||
[Min(0.001f)]
|
||||
private float m_CylinderRadius = 1f;
|
||||
public float cylinderRadius { get { return m_CylinderRadius; } }
|
||||
private float m_EquirectRadius = 1f;
|
||||
public float equirectRadius { get { return m_EquirectRadius; } }
|
||||
#if UNITY_EDITOR
|
||||
public float CylinderRadius { get { return m_CylinderRadius; } set { m_CylinderRadius = value; } }
|
||||
public float EquirectRadius { get { return m_EquirectRadius; } set { m_EquirectRadius = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.0f, 1.0f)]
|
||||
private float m_EquirectScaleX = 1.0f;
|
||||
public float equirectScaleX { get { return m_EquirectScaleX; } }
|
||||
#if UNITY_EDITOR
|
||||
public float EquirectScaleX { get { return m_EquirectScaleX; } set { m_EquirectScaleX = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.0f, 1.0f)]
|
||||
private float m_EquirectScaleY = 1.0f;
|
||||
public float equirectScaleY { get { return m_EquirectScaleY; } }
|
||||
#if UNITY_EDITOR
|
||||
public float EquirectScaleY { get { return m_EquirectScaleY; } set { m_EquirectScaleY = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.0f, 1.0f)]
|
||||
private float m_EquirectBiasX = 0.0f;
|
||||
public float equirectBiasX { get { return m_EquirectBiasX; } }
|
||||
#if UNITY_EDITOR
|
||||
public float EquirectBiasX { get { return m_EquirectBiasX; } set { m_EquirectBiasX = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.0f, 1.0f)]
|
||||
private float m_EquirectBiasY = 0.0f;
|
||||
public float equirectBiasY { get { return m_EquirectBiasY; } }
|
||||
#if UNITY_EDITOR
|
||||
public float EquirectBiasY { get { return m_EquirectBiasY; } set { m_EquirectBiasY = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
[Range(0f, 360f)]
|
||||
private float m_EquirectCentralHorizontalAngle = 360f;
|
||||
public float equirectCentralHorizontalAngle { get { return m_EquirectCentralHorizontalAngle; } }
|
||||
#if UNITY_EDITOR
|
||||
public float EquirectCentralHorizontalAngle { get { return m_EquirectCentralHorizontalAngle; } set { m_EquirectCentralHorizontalAngle = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
[Range(-90f, 90f)]
|
||||
private float m_EquirectUpperVerticalAngle = 90f;
|
||||
public float equirectUpperVerticalAngle { get { return m_EquirectUpperVerticalAngle; } }
|
||||
#if UNITY_EDITOR
|
||||
public float EquirectUpperVerticalAngle { get { return m_EquirectUpperVerticalAngle; } set { m_EquirectUpperVerticalAngle = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
[Range(-90f, 90f)]
|
||||
private float m_EquirectLowerVerticalAngle = -90f;
|
||||
public float equirectLowerVerticalAngle { get { return m_EquirectLowerVerticalAngle; } }
|
||||
#if UNITY_EDITOR
|
||||
public float EquirectLowerVerticalAngle { get { return m_EquirectLowerVerticalAngle; } set { m_EquirectLowerVerticalAngle = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
@@ -171,6 +240,7 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
private LayerShape previousLayerShape = LayerShape.Quad;
|
||||
private float previousQuadWidth = 1f;
|
||||
private float previousQuadHeight = 1f;
|
||||
private float previousEquirectRadius = 1f;
|
||||
private float previousCylinderHeight = 1f;
|
||||
private float previousCylinderArcLength = 1f;
|
||||
private float previousCylinderRadius = 1f;
|
||||
@@ -192,7 +262,7 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
private bool placeholderGenerated = false;
|
||||
private static bool isSynchronized = false;
|
||||
private static RenderThreadSynchronizer synchronizer;
|
||||
private Camera hmd;
|
||||
public Camera hmd;
|
||||
|
||||
private ViveCompositionLayer compositionLayerFeature = null;
|
||||
|
||||
@@ -362,6 +432,7 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
previousLayerShape = layerShape;
|
||||
previousQuadWidth = m_QuadWidth;
|
||||
previousQuadHeight = m_QuadHeight;
|
||||
previousEquirectRadius = m_EquirectRadius;
|
||||
previousCylinderHeight = m_CylinderHeight;
|
||||
previousCylinderArcLength = m_CylinderArcLength;
|
||||
previousCylinderRadius = m_CylinderRadius;
|
||||
@@ -690,6 +761,20 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
compositionLayerCylinderFeature.Submit_CompositionLayerCylinder(AssignCompositionLayerParamsCylinder(eyeid, botheye), (OpenXR.CompositionLayer.LayerType)layerType, compositionDepth, (eyeid == 0) ? layerID : layerIDRight);
|
||||
}
|
||||
break;
|
||||
case LayerShape.Equirect:// TODO added code to submit
|
||||
ViveCompositionLayerEquirect compositionLayerEquicrectFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayerEquirect>();
|
||||
if (compositionLayerEquicrectFeature != null && compositionLayerEquicrectFeature.EquirectExtensionEnabled)
|
||||
{
|
||||
compositionLayerEquicrectFeature.Submit_CompositionLayerEquirect(AssignCompositionLayerParamsEquirect(eyeid), (OpenXR.CompositionLayer.LayerType)layerType, compositionDepth, (eyeid == 0) ? layerID : layerIDRight);
|
||||
}
|
||||
break;
|
||||
case LayerShape.Equirect2:// TODO added code to submit
|
||||
compositionLayerEquicrectFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayerEquirect>();
|
||||
if (compositionLayerEquicrectFeature != null && compositionLayerEquicrectFeature.Equirect2ExtensionEnabled)
|
||||
{
|
||||
compositionLayerEquicrectFeature.Submit_CompositionLayerEquirect2(AssignCompositionLayerParamsEquirect2(eyeid), (OpenXR.CompositionLayer.LayerType)layerType, compositionDepth, (eyeid == 0) ? layerID : layerIDRight);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,7 +923,7 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
else
|
||||
{
|
||||
XRInputSubsystem subsystem = null;
|
||||
SubsystemManager.GetInstances(inputSubsystems);
|
||||
SubsystemManager.GetSubsystems(inputSubsystems);
|
||||
if (inputSubsystems.Count > 0)
|
||||
{
|
||||
subsystem = inputSubsystems[0];
|
||||
@@ -873,6 +958,97 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
return CompositionLayerParamsQuad;
|
||||
}
|
||||
|
||||
XrCompositionLayerEquirectKHR CompositionLayerParamsEquirect = new XrCompositionLayerEquirectKHR();
|
||||
private XrCompositionLayerEquirectKHR AssignCompositionLayerParamsEquirect(int eyeid)
|
||||
{
|
||||
compositionLayerFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayer>();
|
||||
|
||||
CompositionLayerParamsEquirect.type = XrStructureType.XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR;
|
||||
CompositionLayerParamsEquirect.layerFlags = ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT | ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||
|
||||
if (!enabledColorScaleBiasInShader)
|
||||
{
|
||||
CompositionLayerParamsEquirect.layerFlags |= ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
|
||||
}
|
||||
|
||||
CompositionLayerParamsEquirect.subImage.imageRect = layerTextures[eyeid].textureLayout;
|
||||
CompositionLayerParamsEquirect.subImage.imageArrayIndex = 0;
|
||||
GetCompositionLayerPose(ref CompositionLayerParamsEquirect.pose); //Update isHeadLock
|
||||
|
||||
// HeadLock
|
||||
CompositionLayerParamsEquirect.space = compositionLayerFeature.HeadLockSpace;
|
||||
|
||||
switch (layerVisibility)
|
||||
{
|
||||
default:
|
||||
case Visibility.Both:
|
||||
CompositionLayerParamsEquirect.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_BOTH;
|
||||
break;
|
||||
case Visibility.Left:
|
||||
CompositionLayerParamsEquirect.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_LEFT;
|
||||
break;
|
||||
case Visibility.Right:
|
||||
CompositionLayerParamsEquirect.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_RIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
CompositionLayerParamsEquirect.subImage.imageRect = layerTextures[eyeid].textureLayout;
|
||||
CompositionLayerParamsEquirect.subImage.imageArrayIndex = 0;
|
||||
GetCompositionLayerPose(ref CompositionLayerParamsEquirect.pose);
|
||||
CompositionLayerParamsEquirect.radius = m_EquirectRadius;
|
||||
CompositionLayerParamsEquirect.scale.x = m_EquirectScaleX;
|
||||
CompositionLayerParamsEquirect.scale.y = m_EquirectScaleY;
|
||||
CompositionLayerParamsEquirect.bias.x = m_EquirectBiasX;
|
||||
CompositionLayerParamsEquirect.bias.y = m_EquirectBiasY;
|
||||
|
||||
return CompositionLayerParamsEquirect;
|
||||
}
|
||||
|
||||
XrCompositionLayerEquirect2KHR CompositionLayerParamsEquirect2 = new XrCompositionLayerEquirect2KHR();
|
||||
private XrCompositionLayerEquirect2KHR AssignCompositionLayerParamsEquirect2(int eyeid)
|
||||
{
|
||||
compositionLayerFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayer>();
|
||||
|
||||
CompositionLayerParamsEquirect2.type = XrStructureType.XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR;
|
||||
CompositionLayerParamsEquirect2.layerFlags = ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT | ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||
|
||||
if (!enabledColorScaleBiasInShader)
|
||||
{
|
||||
CompositionLayerParamsEquirect2.layerFlags |= ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
|
||||
}
|
||||
|
||||
CompositionLayerParamsEquirect2.subImage.imageRect = layerTextures[eyeid].textureLayout;
|
||||
CompositionLayerParamsEquirect2.subImage.imageArrayIndex = 0;
|
||||
GetCompositionLayerPose(ref CompositionLayerParamsEquirect2.pose); //Update isHeadLock
|
||||
|
||||
// HeadLock
|
||||
CompositionLayerParamsEquirect2.space = compositionLayerFeature.HeadLockSpace;
|
||||
|
||||
switch (layerVisibility)
|
||||
{
|
||||
default:
|
||||
case Visibility.Both:
|
||||
CompositionLayerParamsEquirect2.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_BOTH;
|
||||
break;
|
||||
case Visibility.Left:
|
||||
CompositionLayerParamsEquirect2.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_LEFT;
|
||||
break;
|
||||
case Visibility.Right:
|
||||
CompositionLayerParamsEquirect2.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_RIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
CompositionLayerParamsEquirect2.subImage.imageRect = layerTextures[eyeid].textureLayout;
|
||||
CompositionLayerParamsEquirect2.subImage.imageArrayIndex = 0;
|
||||
GetCompositionLayerPose(ref CompositionLayerParamsEquirect2.pose);
|
||||
CompositionLayerParamsEquirect2.radius = m_EquirectRadius;
|
||||
CompositionLayerParamsEquirect2.centralHorizontalAngle = Mathf.Deg2Rad * m_EquirectCentralHorizontalAngle;
|
||||
CompositionLayerParamsEquirect2.upperVerticalAngle = Mathf.Deg2Rad * m_EquirectUpperVerticalAngle;
|
||||
CompositionLayerParamsEquirect2.lowerVerticalAngle = Mathf.Deg2Rad * m_EquirectLowerVerticalAngle;
|
||||
|
||||
return CompositionLayerParamsEquirect2;
|
||||
}
|
||||
|
||||
XrCompositionLayerCylinderKHR CompositionLayerParamsCylinder = new XrCompositionLayerCylinderKHR();
|
||||
private XrCompositionLayerCylinderKHR AssignCompositionLayerParamsCylinder(int eyeid, bool botheye)
|
||||
{
|
||||
@@ -893,7 +1069,7 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
else
|
||||
{
|
||||
XRInputSubsystem subsystem = null;
|
||||
SubsystemManager.GetInstances(inputSubsystems);
|
||||
SubsystemManager.GetSubsystems(inputSubsystems);
|
||||
if (inputSubsystems.Count > 0)
|
||||
{
|
||||
subsystem = inputSubsystems[0];
|
||||
@@ -1122,7 +1298,15 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
bool isChanged = false;
|
||||
|
||||
if (layerShape == LayerShape.Cylinder)
|
||||
if (layerShape == LayerShape.Equirect)
|
||||
{
|
||||
if (previousEquirectRadius != m_EquirectRadius)
|
||||
{
|
||||
previousEquirectRadius = m_EquirectRadius;
|
||||
isChanged = true;
|
||||
}
|
||||
}
|
||||
else if (layerShape == LayerShape.Cylinder)
|
||||
{
|
||||
if (previousAngleOfArc != m_CylinderAngleOfArc ||
|
||||
previousCylinderArcLength != m_CylinderArcLength ||
|
||||
@@ -1583,6 +1767,9 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
case LayerShape.Cylinder:
|
||||
generatedMesh = MeshGenerationHelper.GenerateCylinderMesh(m_CylinderAngleOfArc, MeshGenerationHelper.GenerateCylinderVertex(m_CylinderAngleOfArc, m_CylinderRadius, m_CylinderHeight));
|
||||
break;
|
||||
case LayerShape.Equirect:
|
||||
generatedMesh = MeshGenerationHelper.GenerateEquirectMesh(hmd, m_EquirectRadius);
|
||||
break;
|
||||
}
|
||||
|
||||
generatedFallbackMesh = new GameObject();
|
||||
@@ -1622,6 +1809,9 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
case LayerShape.Cylinder:
|
||||
generatedMesh = MeshGenerationHelper.GenerateCylinderMesh(m_CylinderAngleOfArc, MeshGenerationHelper.GenerateCylinderVertex(m_CylinderAngleOfArc, m_CylinderRadius, m_CylinderHeight));
|
||||
break;
|
||||
case LayerShape.Equirect:
|
||||
generatedMesh = MeshGenerationHelper.GenerateEquirectMesh(hmd, m_EquirectRadius);
|
||||
break;
|
||||
}
|
||||
|
||||
generatedFallbackMesh.transform.localScale = GetNormalizedLocalScale(transform, Vector3.one);
|
||||
@@ -1657,6 +1847,26 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
|
||||
switch (layerShape)
|
||||
{
|
||||
case LayerShape.Equirect:
|
||||
generatedUnderlayMesh = new GameObject();
|
||||
generatedUnderlayMesh.name = EquirectUnderlayMeshName;
|
||||
generatedUnderlayMesh.transform.SetParent(transform);
|
||||
generatedUnderlayMesh.transform.localPosition = Vector3.zero;
|
||||
generatedUnderlayMesh.transform.localRotation = Quaternion.identity;
|
||||
|
||||
generatedUnderlayMesh.transform.localScale = GetNormalizedLocalScale(transform, Vector3.one);
|
||||
|
||||
generatedUnderlayMeshRenderer = generatedUnderlayMesh.AddComponent<MeshRenderer>();
|
||||
generatedUnderlayMeshFilter = generatedUnderlayMesh.AddComponent<MeshFilter>();
|
||||
if (solidEffect)
|
||||
generatedUnderlayMeshRenderer.sharedMaterial = new Material(Shader.Find("VIVE/OpenXR/CompositionLayer/UnderlayAlphaZeroSolid"));
|
||||
else
|
||||
generatedUnderlayMeshRenderer.sharedMaterial = new Material(Shader.Find("VIVE/OpenXR/CompositionLayer/UnderlayAlphaZero"));
|
||||
generatedUnderlayMeshRenderer.material.mainTexture = texture;
|
||||
|
||||
//Generate Mesh
|
||||
generatedUnderlayMeshFilter.mesh = MeshGenerationHelper.GenerateEquirectMesh(hmd, m_EquirectRadius);
|
||||
break;
|
||||
case LayerShape.Cylinder:
|
||||
//Generate vertices
|
||||
Vector3[] cylinderVertices = MeshGenerationHelper.GenerateCylinderVertex(m_CylinderAngleOfArc, m_CylinderRadius, m_CylinderHeight);
|
||||
@@ -1718,6 +1928,10 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
|
||||
switch (layerShape)
|
||||
{
|
||||
case LayerShape.Equirect:
|
||||
Destroy(generatedUnderlayMeshFilter.mesh);
|
||||
generatedUnderlayMeshFilter.mesh = MeshGenerationHelper.GenerateEquirectMesh(hmd, m_EquirectRadius);
|
||||
break;
|
||||
case LayerShape.Cylinder:
|
||||
//Generate vertices
|
||||
Vector3[] cylinderVertices = MeshGenerationHelper.GenerateCylinderVertex(m_CylinderAngleOfArc, m_CylinderRadius, m_CylinderHeight);
|
||||
@@ -1774,6 +1988,8 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
Quad = 0,
|
||||
Cylinder = 1,
|
||||
Equirect = 2,
|
||||
Equirect2 = 3,
|
||||
}
|
||||
|
||||
public enum Visibility
|
||||
@@ -2040,6 +2256,92 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
return vertices;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector3 InverseTransformVert(in Vector3 vert, in Vector3 position, in Vector3 scale, float worldScale)
|
||||
{
|
||||
return new Vector3(
|
||||
(worldScale * vert.x - position.x) / scale.x,
|
||||
(worldScale * vert.y - position.y) / scale.y,
|
||||
(worldScale * vert.z - position.z) / scale.z);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector2 GetSphereUV(float theta, float phi, float expandScale)
|
||||
{
|
||||
float thetaU = expandScale * (theta / (2 * Mathf.PI) - 0.5f) + 0.5f;
|
||||
float phiV = expandScale * phi / Mathf.PI + 0.5f;
|
||||
|
||||
return new Vector2(thetaU, phiV);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector3 GetSphereVert(float theta, float phi)
|
||||
{
|
||||
return new Vector3(-Mathf.Sin(theta) * Mathf.Cos(phi), Mathf.Sin(phi), -Mathf.Cos(theta) * Mathf.Cos(phi));
|
||||
}
|
||||
|
||||
public static void BuildSphere(List<Vector3> verts, List<Vector2> uv, List<int> triangles, Vector3 position,
|
||||
Quaternion rotation, Vector3 scale, Rect rect, float worldScale = 800, int latitudes = 128,
|
||||
int longitudes = 128, float expandCoefficient = 1.0f)
|
||||
{
|
||||
position = Quaternion.Inverse(rotation) * position;
|
||||
|
||||
latitudes = Mathf.CeilToInt(latitudes * rect.height);
|
||||
longitudes = Mathf.CeilToInt(longitudes * rect.width);
|
||||
|
||||
float minTheta = Mathf.PI * 2.0f * rect.x;
|
||||
float minPhi = Mathf.PI * (0.5f - rect.y - rect.height);
|
||||
|
||||
float thetaScale = Mathf.PI * 2.0f * rect.width / longitudes;
|
||||
float phiScale = Mathf.PI * rect.height / latitudes;
|
||||
|
||||
float expandScale = 1.0f / expandCoefficient;
|
||||
|
||||
for (int j = 0; j < latitudes + 1; j += 1)
|
||||
{
|
||||
for (int k = 0; k < longitudes + 1; k++)
|
||||
{
|
||||
float theta = minTheta + k * thetaScale;
|
||||
float phi = minPhi + j * phiScale;
|
||||
|
||||
Vector2 suv = GetSphereUV(theta, phi, expandScale);
|
||||
uv.Add(new Vector2((suv.x - rect.x) / rect.width, (suv.y - rect.y) / rect.height));
|
||||
Vector3 vert = GetSphereVert(theta, phi);
|
||||
verts.Add(InverseTransformVert(in vert, in position, in scale, worldScale));
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < latitudes; j++)
|
||||
{
|
||||
for (int k = 0; k < longitudes; k++)
|
||||
{
|
||||
triangles.Add(j * (longitudes + 1) + k);
|
||||
triangles.Add((j + 1) * (longitudes + 1) + k);
|
||||
triangles.Add((j + 1) * (longitudes + 1) + k + 1);
|
||||
triangles.Add((j + 1) * (longitudes + 1) + k + 1);
|
||||
triangles.Add(j * (longitudes + 1) + k + 1);
|
||||
triangles.Add(j * (longitudes + 1) + k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Mesh GenerateEquirectMesh(Camera hmd, float equirectRadius)
|
||||
{
|
||||
Mesh eqicrectMesh = new Mesh();
|
||||
List<int> _Tris = new List<int>();
|
||||
List<Vector2> _UV = new List<Vector2>();
|
||||
List<Vector3> _Verts = new List<Vector3>();
|
||||
Rect _Rect = new Rect(0, 0, 1, 1);
|
||||
|
||||
BuildSphere(_Verts, _UV, _Tris, Camera.main.transform.position, Camera.main.transform.rotation, equirectRadius* Vector3.one, _Rect);
|
||||
|
||||
eqicrectMesh.SetVertices(_Verts);
|
||||
eqicrectMesh.SetTriangles(_Tris, 0);
|
||||
eqicrectMesh.SetUVs(0, _UV);
|
||||
eqicrectMesh.UploadMeshData(false);
|
||||
return eqicrectMesh;
|
||||
}
|
||||
|
||||
public static Mesh GenerateCylinderMesh(float cylinderAngleOfArc, Vector3[] vertices)
|
||||
{
|
||||
Mesh cylinderMesh = new Mesh();
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace VIVE.OpenXR.Editor.Interaction
|
||||
boxStyleWarning);
|
||||
GUILayout.EndHorizontal();
|
||||
EditorGUILayout.PropertyField(m_ViveXRTracker);
|
||||
|
||||
/*
|
||||
#if UNITY_ANDROID
|
||||
// ViveHandInteractionExt
|
||||
GUILayout.Space(20);
|
||||
@@ -88,6 +88,7 @@ namespace VIVE.OpenXR.Editor.Interaction
|
||||
GUILayout.EndHorizontal();
|
||||
EditorGUILayout.PropertyField(m_KHRHandInteraction);
|
||||
#endif
|
||||
*/
|
||||
#endregion
|
||||
|
||||
ViveInteractions myScript = target as ViveInteractions;
|
||||
@@ -96,7 +97,7 @@ namespace VIVE.OpenXR.Editor.Interaction
|
||||
bool viveHandInteraction = myScript.UseViveHandInteraction();
|
||||
bool viveWristTracker = myScript.UseViveWristTracker();
|
||||
bool viveXrTracker = myScript.UseViveXrTracker();
|
||||
bool khrHandInteraction = myScript.UseKhrHandInteraction();
|
||||
//bool khrHandInteraction = myScript.UseKhrHandInteraction();
|
||||
|
||||
OpenXRSettings settings = null;
|
||||
#if UNITY_ANDROID
|
||||
@@ -116,7 +117,7 @@ namespace VIVE.OpenXR.Editor.Interaction
|
||||
feature.enabled = viveXrTracker;
|
||||
addPathEnumeration = viveXrTracker;
|
||||
}
|
||||
if (feature is Hand.ViveHandInteractionExt) { feature.enabled = khrHandInteraction; }
|
||||
//if (feature is Hand.ViveHandInteractionExt) { feature.enabled = khrHandInteraction; }
|
||||
}
|
||||
|
||||
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
|
||||
|
||||
@@ -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:
|
||||
@@ -215,6 +215,35 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
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;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# 12.1. XR_HTC_frame_synchronization
|
||||
## Overview
|
||||
Traditional, runtime will use the latest frame which will cost jitter. With Frame Synchronization, the render frame will not be discarded for smooth gameplay experience.
|
||||
However, if the GPU cannot consistently finish rendering on time (rendering more than one vsync at a time), jitter will still occur. Therefore, reducing GPU load is key to smooth gameplay.
|
||||
The application frame loop relies on xrWaitFrame throttling to synchronize application frame submissions with the display. This extension allows the application to set the frame synchronization mode to adjust the interval between the application frame submission time and the corresponding display time according to the demand of the application. The runtime will return the appropriate XrFrameState::predictedDisplayTime returned by xrWaitFrame to throttle the frame loop approaching to the frame rendering time of the application with the consistent good user experience throughout the session.
|
||||
## Name String
|
||||
XR_HTC_frame_synchronization
|
||||
## Revision
|
||||
|
||||
@@ -11,6 +11,7 @@ using UnityEngine.InputSystem;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
@@ -30,7 +31,7 @@ namespace VIVE.OpenXR.Hand
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of hand interaction profiles in OpenXR. It enables <see cref="ViveHandInteractionExt.kOpenxrExtensionString">XR_EXT_hand_interaction</see> in the underyling runtime.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Hand Interaction Ext",
|
||||
[OpenXRFeature(UiName = "VIVE XR Hand Interaction Ext (Deprecated)",
|
||||
Hidden = true,
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
Company = "HTC",
|
||||
@@ -41,6 +42,7 @@ namespace VIVE.OpenXR.Hand
|
||||
Category = FeatureCategory.Interaction,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
[Obsolete("This class is deprecated. Please use Unity Hand Interaction Profile instead.")]
|
||||
public class ViveHandInteractionExt : OpenXRInteractionFeature
|
||||
{
|
||||
#region Log
|
||||
|
||||
@@ -0,0 +1,458 @@
|
||||
using System.Collections.Generic;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using VIVE.OpenXR.Interaction;
|
||||
|
||||
#if UNITY_XR_HANDS
|
||||
using UnityEngine.XR.Hands;
|
||||
using UnityEngine.XR.Hands.ProviderImplementation;
|
||||
namespace VIVE.OpenXR.Hand
|
||||
{
|
||||
public class ViveHandProvider : XRHandSubsystemProvider
|
||||
{
|
||||
#region Hand Interaction
|
||||
private const string kFeatureAimPos = "PointerPosition";
|
||||
private const string kFeatureAimRot = "PointerRotation";
|
||||
private const string kFeatureAimValue = "PointerActivateValue";
|
||||
private const string kFeatureGripPos = "DevicePosition";
|
||||
private const string kFeatureGripRot = "DeviceRotation";
|
||||
private const string kFeatureGripValue = "GraspValue";
|
||||
private const string kFeaturePinchPos = "PinchPosition";
|
||||
private const string kFeaturePinchRot = "PinchRotation";
|
||||
private const string kFeaturePinchValue = "PinchValue";
|
||||
private const string kFeaturePokePos = "PokePosition";
|
||||
private const string kFeaturePokeRot = "PokeRotation";
|
||||
|
||||
private class HandDevice
|
||||
{
|
||||
public Pose aimPose => m_AimPose;
|
||||
public Pose gripPose => m_GripPose;
|
||||
public Pose pinchPose => m_PinchPose;
|
||||
public Pose pokePose => m_PokePose;
|
||||
public float aimActivateValue => m_AimActivateValue;
|
||||
public float graspValue => m_GraspValue;
|
||||
public float pinchValue => m_PinchValue;
|
||||
|
||||
private Pose m_AimPose = Pose.identity;
|
||||
private Pose m_GripPose = Pose.identity;
|
||||
private Pose m_PinchPose = Pose.identity;
|
||||
private Pose m_PokePose = Pose.identity;
|
||||
private float m_AimActivateValue = 0;
|
||||
private float m_GraspValue = 0;
|
||||
private float m_PinchValue = 0;
|
||||
|
||||
private InputDevice device = default(InputDevice);
|
||||
private Dictionary<string, InputFeatureUsage<Vector3>> posUsageMapping = new Dictionary<string, InputFeatureUsage<Vector3>>();
|
||||
private Dictionary<string, InputFeatureUsage<Quaternion>> rotUsageMapping = new Dictionary<string, InputFeatureUsage<Quaternion>>();
|
||||
private Dictionary<string, InputFeatureUsage<float>> valueUsageMapping = new Dictionary<string, InputFeatureUsage<float>>();
|
||||
|
||||
public HandDevice(InputDevice device)
|
||||
{
|
||||
this.device = device;
|
||||
|
||||
List<InputFeatureUsage> inputFeatures = new List<InputFeatureUsage>();
|
||||
device.TryGetFeatureUsages(inputFeatures);
|
||||
for (int i = 0; i < inputFeatures.Count; i++)
|
||||
{
|
||||
InputFeatureUsage feature = inputFeatures[i];
|
||||
switch (feature.name)
|
||||
{
|
||||
case kFeatureAimPos:
|
||||
case kFeatureGripPos:
|
||||
case kFeaturePinchPos:
|
||||
case kFeaturePokePos:
|
||||
posUsageMapping.Add(feature.name, feature.As<Vector3>());
|
||||
break;
|
||||
case kFeatureAimRot:
|
||||
case kFeatureGripRot:
|
||||
case kFeaturePinchRot:
|
||||
case kFeaturePokeRot:
|
||||
rotUsageMapping.Add(feature.name, feature.As<Quaternion>());
|
||||
break;
|
||||
case kFeatureAimValue:
|
||||
case kFeatureGripValue:
|
||||
case kFeaturePinchValue:
|
||||
valueUsageMapping.Add(feature.name, feature.As<float>());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateInputValue()
|
||||
{
|
||||
UpdatePosition();
|
||||
UpdateRotation();
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private void UpdatePosition()
|
||||
{
|
||||
var enumerator = posUsageMapping.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var feature = enumerator.Current;
|
||||
string featureName = feature.Key;
|
||||
InputFeatureUsage<Vector3> featureUsage = feature.Value;
|
||||
if (device.TryGetFeatureValue(featureUsage, out Vector3 position))
|
||||
{
|
||||
switch (featureName)
|
||||
{
|
||||
case kFeatureAimPos:
|
||||
m_AimPose.position = position;
|
||||
break;
|
||||
case kFeatureGripPos:
|
||||
m_GripPose.position = position;
|
||||
break;
|
||||
case kFeaturePinchPos:
|
||||
m_PinchPose.position = position;
|
||||
break;
|
||||
case kFeaturePokePos:
|
||||
m_PokePose.position = position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateRotation()
|
||||
{
|
||||
var enumerator = rotUsageMapping.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var feature = enumerator.Current;
|
||||
string featureName = feature.Key;
|
||||
InputFeatureUsage<Quaternion> featureUsage = feature.Value;
|
||||
if (device.TryGetFeatureValue(featureUsage, out Quaternion rotation))
|
||||
{
|
||||
switch (featureName)
|
||||
{
|
||||
case kFeatureAimRot:
|
||||
m_AimPose.rotation = rotation;
|
||||
break;
|
||||
case kFeatureGripRot:
|
||||
m_GripPose.rotation = rotation;
|
||||
break;
|
||||
case kFeaturePinchRot:
|
||||
m_PinchPose.rotation = rotation;
|
||||
break;
|
||||
case kFeaturePokeRot:
|
||||
m_PokePose.rotation = rotation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateValue()
|
||||
{
|
||||
var enumerator = valueUsageMapping.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var feature = enumerator.Current;
|
||||
string featureName = feature.Key;
|
||||
InputFeatureUsage<float> featureUsage = feature.Value;
|
||||
if (device.TryGetFeatureValue(featureUsage, out float value))
|
||||
{
|
||||
switch (featureName)
|
||||
{
|
||||
case kFeatureAimValue:
|
||||
m_AimActivateValue = value;
|
||||
break;
|
||||
case kFeatureGripValue:
|
||||
m_GraspValue = value;
|
||||
break;
|
||||
case kFeaturePinchValue:
|
||||
m_PinchValue = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static HandDevice leftHandDevice = null;
|
||||
private static HandDevice rightHandDevice = null;
|
||||
private const string kInteractionDeviceName = "Vive Hand Interaction Ext OpenXR";
|
||||
#endregion
|
||||
|
||||
private ViveHandTracking viveHand;
|
||||
|
||||
public override void Destroy() { }
|
||||
|
||||
public override void GetHandLayout(NativeArray<bool> handJointsInLayout)
|
||||
{
|
||||
handJointsInLayout[XRHandJointID.Palm.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.Wrist.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.ThumbMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.ThumbProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.ThumbDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.ThumbTip.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.IndexMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.IndexProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.IndexIntermediate.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.IndexDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.IndexTip.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.MiddleMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.MiddleProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.MiddleIntermediate.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.MiddleDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.MiddleTip.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.RingMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.RingProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.RingIntermediate.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.RingDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.RingTip.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.LittleMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.LittleProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.LittleIntermediate.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.LittleDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.LittleTip.ToIndex()] = true;
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
Initialize();
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
InitHandInteractionDevices();
|
||||
InputDevices.deviceConnected += DeviceConnected;
|
||||
InputDevices.deviceDisconnected += DeviceDisconnected;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
InputDevices.deviceConnected -= DeviceConnected;
|
||||
InputDevices.deviceDisconnected -= DeviceDisconnected;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override XRHandSubsystem.UpdateSuccessFlags TryUpdateHands(XRHandSubsystem.UpdateType updateType, ref Pose leftHandRootPose, NativeArray<XRHandJoint> leftHandJoints, ref Pose rightHandRootPose, NativeArray<XRHandJoint> rightHandJoints)
|
||||
{
|
||||
XRHandSubsystem.UpdateSuccessFlags flags = XRHandSubsystem.UpdateSuccessFlags.None;
|
||||
if (UpdateHand(true, ref leftHandRootPose, ref leftHandJoints))
|
||||
{
|
||||
flags |= XRHandSubsystem.UpdateSuccessFlags.LeftHandRootPose | XRHandSubsystem.UpdateSuccessFlags.LeftHandJoints;
|
||||
}
|
||||
if (UpdateHand(false, ref rightHandRootPose, ref rightHandJoints))
|
||||
{
|
||||
flags |= XRHandSubsystem.UpdateSuccessFlags.RightHandRootPose | XRHandSubsystem.UpdateSuccessFlags.RightHandJoints;
|
||||
}
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
if (updateType == XRHandSubsystem.UpdateType.Dynamic && canSurfaceCommonPoseData)
|
||||
{
|
||||
UpdateHandInteraction();
|
||||
}
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
public override bool canSurfaceCommonPoseData => HandInteractionSupport();
|
||||
|
||||
public override bool TryGetAimPose(Handedness handedness, out Pose aimPose)
|
||||
{
|
||||
aimPose = Pose.identity;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
aimPose = handDevice.aimPose;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetAimActivateValue(Handedness handedness, out float aimActivateValue)
|
||||
{
|
||||
aimActivateValue = 0;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
aimActivateValue = handDevice.aimActivateValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetGripPose(Handedness handedness, out Pose gripPose)
|
||||
{
|
||||
gripPose = Pose.identity;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
gripPose = handDevice.gripPose;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetGraspValue(Handedness handedness, out float graspValue)
|
||||
{
|
||||
graspValue = 0;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
graspValue = handDevice.graspValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetPinchPose(Handedness handedness, out Pose pinchPose)
|
||||
{
|
||||
pinchPose = Pose.identity;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
pinchPose = handDevice.pinchPose;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetPinchValue(Handedness handedness, out float pinchValue)
|
||||
{
|
||||
pinchValue = 0;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
pinchValue = handDevice.pinchValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetPokePose(Handedness handedness, out Pose pokePose)
|
||||
{
|
||||
pokePose = Pose.identity;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
pokePose = handDevice.pokePose;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DeviceConnected(InputDevice inputDevice)
|
||||
{
|
||||
if (inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Left) &&
|
||||
inputDevice.name == kInteractionDeviceName)
|
||||
{
|
||||
leftHandDevice = new HandDevice(inputDevice);
|
||||
}
|
||||
if (inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Right) &&
|
||||
inputDevice.name == kInteractionDeviceName)
|
||||
{
|
||||
rightHandDevice = new HandDevice(inputDevice);
|
||||
}
|
||||
}
|
||||
|
||||
private void DeviceDisconnected(InputDevice inputDevice)
|
||||
{
|
||||
if (inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Left) &&
|
||||
inputDevice.name == kInteractionDeviceName)
|
||||
{
|
||||
leftHandDevice = default;
|
||||
}
|
||||
if (inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Right) &&
|
||||
inputDevice.name == kInteractionDeviceName)
|
||||
{
|
||||
rightHandDevice = default;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitHandInteractionDevices()
|
||||
{
|
||||
List<InputDevice> inputDevices = new List<InputDevice>();
|
||||
InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.HeldInHand |
|
||||
InputDeviceCharacteristics.HandTracking |
|
||||
InputDeviceCharacteristics.TrackedDevice, inputDevices);
|
||||
for (int i = 0; i < inputDevices.Count; i++)
|
||||
{
|
||||
InputDevice inputDevice = inputDevices[i];
|
||||
DeviceConnected(inputDevice);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHandInteraction()
|
||||
{
|
||||
if (leftHandDevice != null)
|
||||
{
|
||||
leftHandDevice.UpdateInputValue();
|
||||
}
|
||||
if (rightHandDevice != null)
|
||||
{
|
||||
rightHandDevice.UpdateInputValue();
|
||||
}
|
||||
}
|
||||
|
||||
private HandDevice GetHandDevice(Handedness handedness) => handedness == Handedness.Left ? leftHandDevice : rightHandDevice;
|
||||
|
||||
private bool HandInteractionSupport()
|
||||
{
|
||||
ViveInteractions viveInteractions = OpenXRSettings.Instance.GetFeature<ViveInteractions>();
|
||||
if (viveInteractions.enabled)
|
||||
{
|
||||
return viveInteractions.UseKhrHandInteraction();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
viveHand = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
}
|
||||
|
||||
private bool UpdateHand(bool isLeft, ref Pose handRootPose, ref NativeArray<XRHandJoint> handJoints)
|
||||
{
|
||||
if (!viveHand) { return false; }
|
||||
bool isValid = viveHand.GetJointLocations(isLeft, out XrHandJointLocationEXT[] viveJoints);
|
||||
|
||||
Handedness handedness = isLeft ? Handedness.Left : Handedness.Right;
|
||||
XRHandJointTrackingState trackingState = XRHandJointTrackingState.None;
|
||||
for (int jointIndex = XRHandJointID.BeginMarker.ToIndex(); jointIndex < XRHandJointID.EndMarker.ToIndex(); ++jointIndex)
|
||||
{
|
||||
XRHandJointID jointID = XRHandJointIDUtility.FromIndex(jointIndex);
|
||||
int viveIndex = XRHandJointIDToIndex(jointID);
|
||||
|
||||
Pose pose = Pose.identity;
|
||||
if (isValid)
|
||||
{
|
||||
pose.position = viveJoints[viveIndex].pose.position.ToUnityVector();
|
||||
pose.rotation = viveJoints[viveIndex].pose.orientation.ToUnityQuaternion();
|
||||
trackingState = XRHandJointTrackingState.Pose;
|
||||
}
|
||||
handJoints[jointIndex] = XRHandProviderUtility.CreateJoint(handedness, trackingState, jointID, pose);
|
||||
}
|
||||
handJoints[XRHandJointID.Wrist.ToIndex()].TryGetPose(out handRootPose);
|
||||
return isValid;
|
||||
}
|
||||
|
||||
private int XRHandJointIDToIndex(XRHandJointID id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case XRHandJointID.Palm:
|
||||
return 0;
|
||||
case XRHandJointID.Wrist:
|
||||
return 1;
|
||||
default:
|
||||
return (int)id - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68f6a3e78d49e1143a9aa0a111a04a0a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,102 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using VIVE.OpenXR.Interaction;
|
||||
|
||||
#if UNITY_XR_HANDS
|
||||
using UnityEngine.XR.Hands;
|
||||
using UnityEngine.XR.Hands.ProviderImplementation;
|
||||
namespace VIVE.OpenXR.Hand
|
||||
{
|
||||
public class ViveHandSubsystem : XRHandSubsystem
|
||||
{
|
||||
public const string featureId = "vive.openxr.feature.xrhandsubsystem";
|
||||
private static XRHandSubsystem subsystem = null;
|
||||
private XRHandProviderUtility.SubsystemUpdater subsystemUpdater = null;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void RegisterDescriptor()
|
||||
{
|
||||
if (!ViveHandTrackingSupport()) { return; }
|
||||
bool handInteractionSupport = HandInteractionSupport();
|
||||
|
||||
var handsSubsystemCinfo = new XRHandSubsystemDescriptor.Cinfo
|
||||
{
|
||||
id = featureId,
|
||||
providerType = typeof(ViveHandProvider),
|
||||
subsystemTypeOverride = typeof(ViveHandSubsystem),
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
supportsAimPose = handInteractionSupport,
|
||||
supportsAimActivateValue = handInteractionSupport,
|
||||
supportsGraspValue = handInteractionSupport,
|
||||
supportsGripPose = handInteractionSupport,
|
||||
supportsPinchPose = handInteractionSupport,
|
||||
supportsPinchValue = handInteractionSupport,
|
||||
supportsPokePose = handInteractionSupport,
|
||||
#endif
|
||||
};
|
||||
XRHandSubsystemDescriptor.Register(handsSubsystemCinfo);
|
||||
}
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void StartSubsystem()
|
||||
{
|
||||
List<XRHandSubsystemDescriptor> descriptors = new List<XRHandSubsystemDescriptor>();
|
||||
if (subsystem == null || !subsystem.running)
|
||||
{
|
||||
descriptors.Clear();
|
||||
SubsystemManager.GetSubsystemDescriptors(descriptors);
|
||||
for (int i = 0; i < descriptors.Count; i++)
|
||||
{
|
||||
XRHandSubsystemDescriptor descriptor = descriptors[i];
|
||||
if (descriptor.id == featureId)
|
||||
{
|
||||
subsystem = descriptor.Create();
|
||||
subsystem.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
if (subsystemUpdater == null)
|
||||
{
|
||||
subsystemUpdater = new XRHandProviderUtility.SubsystemUpdater(subsystem);
|
||||
}
|
||||
subsystemUpdater.Start();
|
||||
|
||||
}
|
||||
|
||||
protected override void OnStop()
|
||||
{
|
||||
base.OnStop();
|
||||
subsystemUpdater.Stop();
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
subsystemUpdater.Destroy();
|
||||
subsystemUpdater = null;
|
||||
}
|
||||
|
||||
private static bool ViveHandTrackingSupport()
|
||||
{
|
||||
ViveHandTracking viveHand = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
return viveHand.enabled;
|
||||
}
|
||||
|
||||
private static bool HandInteractionSupport()
|
||||
{
|
||||
ViveInteractions viveInteractions = OpenXRSettings.Instance.GetFeature<ViveInteractions>();
|
||||
if (viveInteractions.enabled)
|
||||
{
|
||||
return viveInteractions.UseKhrHandInteraction();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ce39c25a1e4a794c807d9f723d37804
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -9,7 +9,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using AOT;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
|
||||
@@ -63,48 +62,74 @@ namespace VIVE.OpenXR.Hand
|
||||
private bool m_XrInstanceCreated = false;
|
||||
private XrInstance m_XrInstance = 0;
|
||||
private static IntPtr xrGetInstanceProcAddr_prev;
|
||||
private static IntPtr WaitFrame_prev;
|
||||
private static XrFrameWaitInfo m_frameWaitInfo;
|
||||
private static XrFrameState m_frameState;
|
||||
private static XrTime m_predictedDisplayTime;
|
||||
private static XrDuration m_predictedDisplayDuration;
|
||||
|
||||
private static int sizeOfXrHandJointLocationEXT = Marshal.SizeOf(typeof(XrHandJointLocationEXT));
|
||||
private static IntPtr handJointLocationsNativeBuffer = IntPtr.Zero;
|
||||
private static byte[] handJointLocationsByteBuffer = null;
|
||||
private static int handJointLocationsNativeBufferLength = 0; // Not byte size, it is the number of XrHandJointLocationEXT.
|
||||
|
||||
protected override IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
{
|
||||
UnityEngine.Debug.Log("EXT: registering our own xrGetInstanceProcAddr");
|
||||
xrGetInstanceProcAddr_prev = func;
|
||||
return Marshal.GetFunctionPointerForDelegate(m_intercept_xrWaitFrame_xrGetInstanceProcAddr);
|
||||
ViveInterceptors.Instance.AddRequiredFunction("xrWaitFrame");
|
||||
if (ViveInterceptors.Instance.BeforeOriginalWaitFrame == null)
|
||||
{
|
||||
ViveInterceptors.Instance.BeforeOriginalWaitFrame = new ViveInterceptors.DelegateXrWaitFrameInterceptor(BeforeWaitFrame);
|
||||
}
|
||||
[MonoPInvokeCallback(typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate))]
|
||||
private static XrResult intercept_xrWaitFrame_xrGetInstanceProcAddr(XrInstance instance, string name, out IntPtr function)
|
||||
else
|
||||
{
|
||||
if (xrGetInstanceProcAddr_prev == null || xrGetInstanceProcAddr_prev == IntPtr.Zero)
|
||||
{
|
||||
UnityEngine.Debug.LogError("xrGetInstanceProcAddr_prev is null");
|
||||
function = IntPtr.Zero;
|
||||
return XrResult.XR_ERROR_VALIDATION_FAILURE;
|
||||
ViveInterceptors.Instance.BeforeOriginalWaitFrame += BeforeWaitFrame;
|
||||
}
|
||||
|
||||
// Get delegate of old xrGetInstanceProcAddr.
|
||||
var xrGetProc = Marshal.GetDelegateForFunctionPointer<OpenXRHelper.xrGetInstanceProcAddrDelegate>(xrGetInstanceProcAddr_prev);
|
||||
XrResult result = xrGetProc(instance, name, out function);
|
||||
if (name == "xrWaitFrame")
|
||||
if (ViveInterceptors.Instance.AfterOriginalWaitFrame == null)
|
||||
{
|
||||
WaitFrame_prev = function;
|
||||
m_intercept_xrWaitFrame = intercepted_xrWaitFrame;
|
||||
function = Marshal.GetFunctionPointerForDelegate(m_intercept_xrWaitFrame); ;
|
||||
UnityEngine.Debug.Log("Getting xrWaitFrame func");
|
||||
ViveInterceptors.Instance.AfterOriginalWaitFrame = new ViveInterceptors.DelegateXrWaitFrameInterceptor(AfterWaitFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViveInterceptors.Instance.AfterOriginalWaitFrame += AfterWaitFrame;
|
||||
}
|
||||
return ViveInterceptors.Instance.HookGetInstanceProcAddr(func);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
[MonoPInvokeCallback(typeof(OpenXRHelper.xrWaitFrameDelegate))]
|
||||
private static int intercepted_xrWaitFrame(ulong session, ref XrFrameWaitInfo frameWaitInfo, ref XrFrameState frameState)
|
||||
private bool BeforeWaitFrame(XrSession session, ref ViveInterceptors.XrFrameWaitInfo frameWaitInfo, ref ViveInterceptors.XrFrameState frameState, ref XrResult result)
|
||||
{
|
||||
// Get delegate of prev xrWaitFrame.
|
||||
var xrWaitFrame = Marshal.GetDelegateForFunctionPointer<OpenXRHelper.xrWaitFrameDelegate>(WaitFrame_prev);
|
||||
int res = xrWaitFrame(session, ref frameWaitInfo, ref frameState);
|
||||
m_frameWaitInfo = frameWaitInfo;
|
||||
m_frameState = frameState;
|
||||
return res;
|
||||
ViveInterceptors.XrFrameState nextFrameState = new ViveInterceptors.XrFrameState
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_PASSTHROUGH_HAND_TRACKER_FRAME_STATE_HTC,
|
||||
next = frameState.next,
|
||||
predictedDisplayPeriod = 0,
|
||||
predictedDisplayTime = 0,
|
||||
shouldRender = false
|
||||
};
|
||||
frameState.next = MemoryTools.ToIntPtr(nextFrameState);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool AfterWaitFrame(XrSession session, ref ViveInterceptors.XrFrameWaitInfo frameWaitInfo, ref ViveInterceptors.XrFrameState frameState, ref XrResult result)
|
||||
{
|
||||
m_predictedDisplayTime = frameState.predictedDisplayTime;
|
||||
m_predictedDisplayDuration = frameState.predictedDisplayPeriod;
|
||||
|
||||
IntPtr next = frameState.next;
|
||||
HashSet<IntPtr> visited = new HashSet<IntPtr>();
|
||||
int iterationCount = 0;
|
||||
int maxIterations = 10;
|
||||
while (next != IntPtr.Zero && !visited.Contains(next))
|
||||
{
|
||||
if (iterationCount++ > maxIterations) { break; }
|
||||
visited.Add(next);
|
||||
ViveInterceptors.XrFrameState nextFrameState = Marshal.PtrToStructure<ViveInterceptors.XrFrameState>(next);
|
||||
if (nextFrameState.type == XrStructureType.XR_TYPE_PASSTHROUGH_HAND_TRACKER_FRAME_STATE_HTC &&
|
||||
nextFrameState.predictedDisplayTime != 0)
|
||||
{
|
||||
m_predictedDisplayTime = nextFrameState.predictedDisplayTime;
|
||||
break;
|
||||
}
|
||||
next = nextFrameState.next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -140,6 +165,14 @@ namespace VIVE.OpenXR.Hand
|
||||
InputSystem.onAfterUpdate -= UpdateCallback;
|
||||
}
|
||||
sb.Clear().Append(LOG_TAG).Append("OnInstanceDestroy() ").Append(xrInstance); DEBUG(sb);
|
||||
// release buffer
|
||||
if (handJointLocationsNativeBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(handJointLocationsNativeBuffer);
|
||||
handJointLocationsNativeBuffer = IntPtr.Zero;
|
||||
handJointLocationsByteBuffer = null;
|
||||
handJointLocationsNativeBufferLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private XrSystemId m_XrSystemId = 0;
|
||||
@@ -343,9 +376,6 @@ namespace VIVE.OpenXR.Hand
|
||||
#endregion
|
||||
|
||||
#region OpenXR function delegates
|
||||
private static readonly OpenXRHelper.xrGetInstanceProcAddrDelegate m_intercept_xrWaitFrame_xrGetInstanceProcAddr
|
||||
= new OpenXRHelper.xrGetInstanceProcAddrDelegate(intercept_xrWaitFrame_xrGetInstanceProcAddr);
|
||||
private static OpenXRHelper.xrWaitFrameDelegate m_intercept_xrWaitFrame;
|
||||
/// xrGetInstanceProcAddr
|
||||
OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr;
|
||||
|
||||
@@ -681,7 +711,7 @@ namespace VIVE.OpenXR.Hand
|
||||
{
|
||||
XRInputSubsystem subsystem = null;
|
||||
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
SubsystemManager.GetSubsystems(s_InputSubsystems);
|
||||
if (s_InputSubsystems.Count > 0)
|
||||
{
|
||||
subsystem = s_InputSubsystems[0];
|
||||
@@ -795,7 +825,7 @@ namespace VIVE.OpenXR.Hand
|
||||
return true;
|
||||
}
|
||||
|
||||
private int lastUpdateFrameL = -1, lastUpdateFrameR = -1;
|
||||
private int lastUpdateFrameL = -1, lastUpdateFrameR = -1, updateFrame = -1;
|
||||
private void UpdateCallback()
|
||||
{
|
||||
// Only allow updating poses once at BeforeRender & Dynamic per frame.
|
||||
@@ -805,6 +835,10 @@ namespace VIVE.OpenXR.Hand
|
||||
lastUpdateFrameL = -1;
|
||||
lastUpdateFrameR = -1;
|
||||
}
|
||||
if (InputState.currentUpdateType == InputUpdateType.BeforeRender)
|
||||
{
|
||||
updateFrame = Time.frameCount;
|
||||
}
|
||||
}
|
||||
private bool AllowUpdate(bool isLeft)
|
||||
{
|
||||
@@ -832,90 +866,69 @@ namespace VIVE.OpenXR.Hand
|
||||
public bool GetJointLocations(bool isLeft, out XrHandJointLocationEXT[] handJointLocation, out XrTime timestamp)
|
||||
{
|
||||
handJointLocation = isLeft ? jointLocationsL : jointLocationsR;
|
||||
timestamp = m_frameState.predictedDisplayTime;
|
||||
long displayTime = m_predictedDisplayTime;
|
||||
if (Time.frameCount > updateFrame)
|
||||
{
|
||||
displayTime += m_predictedDisplayDuration;
|
||||
}
|
||||
timestamp = displayTime;
|
||||
if (!AllowUpdate(isLeft)) { return true; }
|
||||
|
||||
bool ret = false;
|
||||
if (isLeft && !hasLeftHandTracker) { return ret; }
|
||||
if (!isLeft && !hasRightHandTracker) { return ret; }
|
||||
|
||||
OpenXRHelper.Trace.Begin("GetJointLocations");
|
||||
|
||||
TrackingOriginModeFlags origin = GetTrackingOriginMode();
|
||||
if (origin == TrackingOriginModeFlags.Unknown || origin == TrackingOriginModeFlags.Unbounded) { return ret; }
|
||||
XrSpace baseSpace = (origin == TrackingOriginModeFlags.Device ? m_ReferenceSpaceLocal : m_ReferenceSpaceStage);
|
||||
|
||||
/// Configures XrHandJointsLocateInfoEXT
|
||||
XrHandJointsLocateInfoEXT locateInfo = new XrHandJointsLocateInfoEXT(
|
||||
in_type: XrStructureType.XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT,
|
||||
in_next: IntPtr.Zero,
|
||||
in_baseSpace: baseSpace,
|
||||
in_time: m_frameState.predictedDisplayTime);
|
||||
in_baseSpace: GetCurrentAppSpace(),
|
||||
in_time: displayTime);
|
||||
|
||||
/// Configures XrHandJointLocationsEXT
|
||||
locations.type = XrStructureType.XR_TYPE_HAND_JOINT_LOCATIONS_EXT;
|
||||
locations.next = IntPtr.Zero;
|
||||
locations.isActive = false;
|
||||
locations.jointCount = (uint)(isLeft ? jointLocationsL.Length : jointLocationsR.Length);
|
||||
locations.jointCount = (uint)(handJointLocation.Length);
|
||||
|
||||
XrHandJointLocationEXT joint_location_ext_type = default(XrHandJointLocationEXT);
|
||||
int jointLocationsLength = isLeft ? jointLocationsL.Length : jointLocationsR.Length;
|
||||
locations.jointLocations = Marshal.AllocHGlobal(Marshal.SizeOf(joint_location_ext_type) * jointLocationsLength);
|
||||
int jointLocationsLength = handJointLocation.Length;
|
||||
|
||||
long offset = 0;
|
||||
/*if (IntPtr.Size == 4)
|
||||
offset = locations.jointLocations.ToInt32();
|
||||
else
|
||||
offset = locations.jointLocations.ToInt64();
|
||||
|
||||
for (int i = 0; i < jointLocationsLength; i++)
|
||||
if (handJointLocationsNativeBuffer == null || handJointLocationsNativeBuffer == IntPtr.Zero)
|
||||
{
|
||||
IntPtr joint_location_ext_ptr = new IntPtr(offset);
|
||||
int N = sizeOfXrHandJointLocationEXT * jointLocationsLength;
|
||||
handJointLocationsNativeBuffer = Marshal.AllocHGlobal(N);
|
||||
handJointLocationsByteBuffer = new byte[N];
|
||||
handJointLocationsNativeBufferLength = jointLocationsLength;
|
||||
DEBUG($"GetJointLocations() handJointLocationsNativeBuffer[{N}] is allocated.");
|
||||
}
|
||||
else if (handJointLocationsNativeBufferLength < jointLocationsLength)
|
||||
{
|
||||
Marshal.FreeHGlobal(handJointLocationsNativeBuffer);
|
||||
int N = sizeOfXrHandJointLocationEXT * jointLocationsLength;
|
||||
handJointLocationsNativeBuffer = Marshal.AllocHGlobal(N);
|
||||
handJointLocationsByteBuffer = new byte[N];
|
||||
handJointLocationsNativeBufferLength = jointLocationsLength;
|
||||
DEBUG($"GetJointLocations() handJointLocationsNativeBuffer[{N}] is allocated.");
|
||||
}
|
||||
|
||||
if (isLeft)
|
||||
Marshal.StructureToPtr(jointLocationsL[i], joint_location_ext_ptr, false);
|
||||
else
|
||||
Marshal.StructureToPtr(jointLocationsR[i], joint_location_ext_ptr, false);
|
||||
locations.jointLocations = handJointLocationsNativeBuffer;
|
||||
|
||||
offset += Marshal.SizeOf(joint_location_ext_type);
|
||||
}*/
|
||||
|
||||
if (LocateHandJointsEXT(
|
||||
var retX = LocateHandJointsEXT(
|
||||
handTracker: (isLeft ? leftHandTracker : rightHandTracker),
|
||||
locateInfo: locateInfo,
|
||||
locations: ref locations) == XrResult.XR_SUCCESS)
|
||||
locations: ref locations);
|
||||
|
||||
if (retX == XrResult.XR_SUCCESS)
|
||||
{
|
||||
timestamp = locateInfo.time;
|
||||
|
||||
if (locations.isActive)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
offset = locations.jointLocations.ToInt32();
|
||||
else
|
||||
offset = locations.jointLocations.ToInt64();
|
||||
|
||||
for (int i = 0; i < locations.jointCount; i++)
|
||||
{
|
||||
IntPtr joint_location_ext_ptr = new IntPtr(offset);
|
||||
|
||||
if (isLeft)
|
||||
jointLocationsL[i] = (XrHandJointLocationEXT)Marshal.PtrToStructure(joint_location_ext_ptr, typeof(XrHandJointLocationEXT));
|
||||
else
|
||||
jointLocationsR[i] = (XrHandJointLocationEXT)Marshal.PtrToStructure(joint_location_ext_ptr, typeof(XrHandJointLocationEXT));
|
||||
|
||||
offset += Marshal.SizeOf(joint_location_ext_type);
|
||||
}
|
||||
|
||||
// ToDo: locationFlags?
|
||||
handJointLocation = isLeft ? jointLocationsL : jointLocationsR;
|
||||
|
||||
MemoryTools.CopyAllFromRawMemory(handJointLocation, handJointLocationsNativeBuffer);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(locations.jointLocations);
|
||||
|
||||
OpenXRHelper.Trace.End();
|
||||
return ret;
|
||||
}
|
||||
/// <summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -172,10 +172,10 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// 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)
|
||||
public XrPassthroughColorHTC(float in_alpha)
|
||||
{
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
type = XrStructureType.XR_TYPE_PASSTHROUGH_COLOR_HTC;
|
||||
next = IntPtr.Zero;
|
||||
alpha = in_alpha;
|
||||
}
|
||||
};
|
||||
@@ -201,7 +201,7 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// <summary>
|
||||
/// An array of XrVector3f. The size of the array must be equal to vertexCount.
|
||||
/// </summary>
|
||||
public XrVector3f[] vertices;
|
||||
public IntPtr vertices; // XrVector3f
|
||||
/// <summary>
|
||||
/// The count of indices array in the mesh.
|
||||
/// </summary>
|
||||
@@ -209,7 +209,7 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// <summary>
|
||||
/// An array of triangle indices. The size of the array must be equal to indexCount.
|
||||
/// </summary>
|
||||
public UInt32[] indices;
|
||||
public IntPtr indices; // UInt32[]
|
||||
/// <summary>
|
||||
/// The XrSpace that defines the projected passthrough's base space for transformations.
|
||||
/// </summary>
|
||||
@@ -226,21 +226,6 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// 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;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -273,11 +258,12 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// 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,
|
||||
|
||||
public XrCompositionLayerPassthroughHTC(XrCompositionLayerFlags in_layerFlags,
|
||||
XrSpace in_space, XrPassthroughHTC in_passthrough, XrPassthroughColorHTC in_color)
|
||||
{
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
type = XrStructureType.XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC;
|
||||
next = IntPtr.Zero;
|
||||
layerFlags = in_layerFlags;
|
||||
space = in_space;
|
||||
passthrough = in_passthrough;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace UnityEngine.XR.OpenXR.Features.Interactions
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(
|
||||
UiName = "HTC Vive Tracker Profile",
|
||||
UiName = "HTC VIVE Tracker Profile",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.WSA },
|
||||
Company = "MASSIVE",
|
||||
Desc = "Allows for mapping input to the HTC Vive Tracker interaction profile.",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using VIVE.OpenXR.Hand;
|
||||
|
||||
namespace VIVE.OpenXR.Models
|
||||
@@ -69,16 +70,43 @@ namespace VIVE.OpenXR.Models
|
||||
skinMeshRenderer = GetComponentInChildren<SkinnedMeshRenderer>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
Application.onBeforeRender += BeforeRenderUpdate;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Application.onBeforeRender -= BeforeRenderUpdate;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (skinMeshRenderer == null) { return; }
|
||||
UpdateHand();
|
||||
}
|
||||
|
||||
private void BeforeRenderUpdate()
|
||||
{
|
||||
if (!skinMeshRenderer.enabled) { return; }
|
||||
UpdateHand();
|
||||
}
|
||||
|
||||
private void UpdateHand()
|
||||
{
|
||||
Profiler.BeginSample("HandModelActions");
|
||||
if (skinMeshRenderer == null) { Profiler.EndSample(); return; }
|
||||
|
||||
Profiler.BeginSample("GetJointLocations");
|
||||
if (!XR_EXT_hand_tracking.Interop.GetJointLocations(m_IsLeft, out XrHandJointLocationEXT[] handJointLocation))
|
||||
{
|
||||
skinMeshRenderer.enabled = false;
|
||||
Profiler.EndSample();
|
||||
Profiler.EndSample();
|
||||
return;
|
||||
}
|
||||
Profiler.EndSample();
|
||||
|
||||
Profiler.BeginSample("UpdateJointPose");
|
||||
skinMeshRenderer.enabled = !ForceHidden;
|
||||
|
||||
UpdateJointPosition(handJointLocation[(int)XrHandJointEXT.XR_HAND_JOINT_WRIST_EXT], ref m_Wrist);
|
||||
@@ -114,6 +142,8 @@ namespace VIVE.OpenXR.Models
|
||||
UpdateJointRotation(handJointLocation[(int)XrHandJointEXT.XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT], ref m_Little_Intermediate);
|
||||
UpdateJointRotation(handJointLocation[(int)XrHandJointEXT.XR_HAND_JOINT_LITTLE_DISTAL_EXT], ref m_Little_Distal);
|
||||
UpdateJointRotation(handJointLocation[(int)XrHandJointEXT.XR_HAND_JOINT_LITTLE_TIP_EXT], ref m_Little_Tip);
|
||||
Profiler.EndSample();
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
private void UpdateJointPosition(XrHandJointLocationEXT pose, ref GameObject joint)
|
||||
|
||||
@@ -127,6 +127,9 @@ namespace VIVE.OpenXR
|
||||
XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC = 1000317001,
|
||||
XR_TYPE_PASSTHROUGH_COLOR_HTC = 1000317002,
|
||||
XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC = 1000317003,
|
||||
XR_TYPE_PASSTHROUGH_HAND_TRACKER_FRAME_STATE_HTC = 1000317100,
|
||||
XR_TYPE_PASSTHROUGH_VIVE_CONTROLLER_FRAME_STATE_HTC = 1000317101,
|
||||
XR_TYPE_PASSTHROUGH_VIVE_TRACKER_FRAME_STATE_HTC = 1000317102,
|
||||
XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC = 1000317004,
|
||||
XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX = 1000033000,
|
||||
XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX = 1000033003,
|
||||
@@ -544,6 +547,24 @@ namespace VIVE.OpenXR
|
||||
}
|
||||
}
|
||||
|
||||
public struct XrBaseStructure
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
public struct XrBaseOutStructure
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
public struct XrBaseInStructure
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
#region 2.18. Coordinate System
|
||||
/// <summary>
|
||||
/// A two-dimensional vector is defined by the XrVector2f structure.
|
||||
@@ -3243,7 +3264,7 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
Debug.Log("Get function pointer of " + name);
|
||||
Log.D("Get function pointer of " + name);
|
||||
func = Marshal.GetDelegateForFunctionPointer<Type>(funcPtr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
//using VIVE.OpenXR.Utils;
|
||||
using VIVE.OpenXR.Hand;
|
||||
@@ -59,20 +60,7 @@ namespace VIVE.OpenXR
|
||||
|
||||
if (m_JointLocations.isActive == 1)
|
||||
{
|
||||
long offset = 0;
|
||||
XrHandJointLocationEXT joint_location_ext_type = default(XrHandJointLocationEXT);
|
||||
|
||||
if (IntPtr.Size == 4)
|
||||
offset = m_JointLocations.jointLocations.ToInt32();
|
||||
else
|
||||
offset = m_JointLocations.jointLocations.ToInt64();
|
||||
|
||||
for (int i = 0; i < m_JointLocations.jointCount; i++)
|
||||
{
|
||||
IntPtr joint_location_ext_ptr = new IntPtr(offset);
|
||||
s_JointLocation[isLeft][i] = (XrHandJointLocationEXT)Marshal.PtrToStructure(joint_location_ext_ptr, typeof(XrHandJointLocationEXT));
|
||||
offset += Marshal.SizeOf(joint_location_ext_type);
|
||||
}
|
||||
MemoryTools.CopyFromRawMemory(handJointLocation, m_JointLocations.jointLocations, (int)m_JointLocations.jointCount);
|
||||
|
||||
handJointLocation = s_JointLocation[isLeft];
|
||||
return true;
|
||||
|
||||
@@ -86,13 +86,8 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
if (ASSERT_FEATURE())
|
||||
{
|
||||
if (feature.GetJointLocations(isLeft, out XrHandJointLocationEXT[] array, out timestamp))
|
||||
if (feature.GetJointLocations(isLeft, out handJointLocation, out timestamp))
|
||||
{
|
||||
if (l_HandJointLocation == null) { l_HandJointLocation = new List<XrHandJointLocationEXT>(); }
|
||||
l_HandJointLocation.Clear();
|
||||
for (int i = 0; i < array.Length; i++) { l_HandJointLocation.Add(array[i]); }
|
||||
|
||||
handJointLocation = l_HandJointLocation.ToArray();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,27 +43,6 @@ namespace VIVE.OpenXR
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void GetOriginEndFrameLayerList(out List<IntPtr> layers)
|
||||
{
|
||||
ASSERT_FEATURE();
|
||||
layers = new List<IntPtr>();
|
||||
#if UNITY_STANDALONE
|
||||
if (feature)
|
||||
feature.GetOriginEndFrameLayerList(out layers);
|
||||
|
||||
else
|
||||
layers = new List<IntPtr>();
|
||||
#endif
|
||||
}
|
||||
public override void SubmitLayers(List<IntPtr> layers)
|
||||
{
|
||||
ASSERT_FEATURE();
|
||||
#if UNITY_STANDALONE
|
||||
if (feature)
|
||||
feature.SubmitLayers(layers);
|
||||
#endif
|
||||
}
|
||||
|
||||
public override XrSpace GetTrackingSpace()
|
||||
{
|
||||
ASSERT_FEATURE();
|
||||
@@ -77,10 +56,8 @@ namespace VIVE.OpenXR
|
||||
public override XrFrameState GetFrameState()
|
||||
{
|
||||
ASSERT_FEATURE();
|
||||
#if UNITY_STANDALONE
|
||||
if (feature)
|
||||
return feature.GetFrameState();
|
||||
#endif
|
||||
return new XrFrameState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
@@ -107,6 +106,12 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
|
||||
public static class VIVEInput
|
||||
{
|
||||
private const string kFloatType = "float";
|
||||
private const string kVector2Type = "Vector2";
|
||||
private const string kVector3Type = "Vector3";
|
||||
private const string kQuaternionType = "Quaternion";
|
||||
private const string kPoseType = "Pose";
|
||||
|
||||
private struct InputActionMapping
|
||||
{
|
||||
public DeviceCategory device;
|
||||
@@ -115,15 +120,18 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
public HandEvent handEvent;
|
||||
public InputAction inputAction { get; private set; }
|
||||
|
||||
public InputActionMapping(string bindingPath, DeviceCategory device,
|
||||
PoseState poseState = PoseState.None, ButtonEvent buttonEvent = ButtonEvent.None, HandEvent handEvent = HandEvent.None)
|
||||
public InputActionMapping(string in_BindingPath, DeviceCategory in_Device,
|
||||
PoseState in_PoseState = PoseState.None,
|
||||
ButtonEvent in_ButtonEvent = ButtonEvent.None,
|
||||
HandEvent in_HandEvent = HandEvent.None,
|
||||
string in_Type = "")
|
||||
{
|
||||
inputAction = new InputAction(binding: bindingPath);
|
||||
inputAction = new InputAction(binding: in_BindingPath, expectedControlType: in_Type);
|
||||
inputAction.Enable();
|
||||
this.device = device;
|
||||
this.poseState = poseState;
|
||||
this.buttonEvent = buttonEvent;
|
||||
this.handEvent = handEvent;
|
||||
this.device = in_Device;
|
||||
this.poseState = in_PoseState;
|
||||
this.buttonEvent = in_ButtonEvent;
|
||||
this.handEvent = in_HandEvent;
|
||||
}
|
||||
|
||||
public static InputActionMapping Identify => new InputActionMapping("", DeviceCategory.None);
|
||||
@@ -150,11 +158,11 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
public Vector3 position { get; private set; }
|
||||
public Quaternion rotation { get; private set; }
|
||||
|
||||
public JointData(bool isValid, Vector3 position, Quaternion rotation)
|
||||
public JointData(bool in_IsValid, Vector3 in_Position, Quaternion in_Rotation)
|
||||
{
|
||||
this.isValid = isValid;
|
||||
this.position = position;
|
||||
this.rotation = rotation;
|
||||
this.isValid = in_IsValid;
|
||||
this.position = in_Position;
|
||||
this.rotation = in_Rotation;
|
||||
}
|
||||
|
||||
public static JointData Identify => new JointData(false, Vector3.zero, Quaternion.identity);
|
||||
@@ -164,18 +172,44 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
public bool isTracked { get; private set; }
|
||||
public int updateTime { get; private set; }
|
||||
public JointData[] joints { get; private set; }
|
||||
private JointData[] jointBuffer;
|
||||
|
||||
public HandData(JointData[] joints)
|
||||
public HandData(JointData[] in_Joints)
|
||||
{
|
||||
this.joints = joints;
|
||||
isTracked = !this.joints.Any(x => x.isValid == false);
|
||||
jointBuffer = new JointData[(int)HandJointType.Count];
|
||||
for (int i = 0; i < in_Joints.Length; i++)
|
||||
{
|
||||
jointBuffer[i] = in_Joints[i];
|
||||
}
|
||||
this.joints = jointBuffer;
|
||||
isTracked = true;
|
||||
for (int i = 0; i < this.joints.Length; i++)
|
||||
{
|
||||
if (!this.joints[i].isValid)
|
||||
{
|
||||
isTracked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateTime = Time.frameCount;
|
||||
}
|
||||
|
||||
public void Update(JointData[] joints)
|
||||
public void Update(JointData[] in_Joints)
|
||||
{
|
||||
this.joints = joints;
|
||||
isTracked = !this.joints.Any(x => x.isValid == false);
|
||||
for (int i = 0; i < in_Joints.Length; i++)
|
||||
{
|
||||
jointBuffer[i] = in_Joints[i];
|
||||
}
|
||||
this.joints = jointBuffer;
|
||||
isTracked = true;
|
||||
for (int i = 0; i < this.joints.Length; i++)
|
||||
{
|
||||
if (!this.joints[i].isValid)
|
||||
{
|
||||
isTracked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateTime = Time.frameCount;
|
||||
}
|
||||
|
||||
@@ -193,12 +227,16 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
}
|
||||
|
||||
private static bool isInitInputActions = false;
|
||||
private static List<InputActionMapping> inputActions = new List<InputActionMapping>();
|
||||
private static HandData leftHand = HandData.Identify;
|
||||
private static HandData rightHand = HandData.Identify;
|
||||
private static bool m_IsInitInputActions = false;
|
||||
private static bool m_IsSupportViveHand = false;
|
||||
private static bool m_IsSupportXrHand = false;
|
||||
private static List<InputActionMapping> s_InputActions = new List<InputActionMapping>();
|
||||
private static HandData m_LeftHand = HandData.Identify;
|
||||
private static HandData m_RightHand = HandData.Identify;
|
||||
private static JointData[] m_JointBuffer = new JointData[(int)HandJointType.Count];
|
||||
#if UNITY_XR_HANDS
|
||||
private static XRHandSubsystem handSubsystem = null;
|
||||
private static XRHandSubsystem m_HandSubsystem = null;
|
||||
private static List<XRHandSubsystem> m_HandSubsystems = new List<XRHandSubsystem>();
|
||||
#endif
|
||||
|
||||
#region Public Interface
|
||||
@@ -221,18 +259,16 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
else
|
||||
{
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == device && x.poseState == poseState);
|
||||
if (inputActionMapping == null) { return false; }
|
||||
|
||||
try
|
||||
if (GetInputActionMapping(device, poseState, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<float>() > 0;
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,18 +291,16 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
else
|
||||
{
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == device && x.poseState == poseState);
|
||||
if (inputActionMapping == null) { return false; }
|
||||
|
||||
try
|
||||
if (GetInputActionMapping(device, poseState, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kVector3Type)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<Vector3>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,18 +323,16 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
else
|
||||
{
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == device && x.poseState == poseState);
|
||||
if (inputActionMapping == null) { return false; }
|
||||
|
||||
try
|
||||
if (GetInputActionMapping(device, poseState, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kQuaternionType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<Quaternion>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,12 +347,15 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = false;
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.WasPressedThisFrame();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -335,12 +370,15 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = false;
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.WasReleasedThisFrame();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -355,21 +393,16 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = false;
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
try
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<float>() == 1;
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -383,21 +416,16 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = 0f;
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
try
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<float>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -411,18 +439,14 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = Vector2.zero;
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
try
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kVector2Type)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<Vector2>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -438,18 +462,14 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = 0;
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetHand(handedness) && x.handEvent == handEvent);
|
||||
if (inputActionMapping != null)
|
||||
if (GetInputActionMapping(GetHand(handedness), handEvent, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
try
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<float>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -465,19 +485,19 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = Pose.identity;
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetHand(handedness) && x.handEvent == handEvent);
|
||||
if (inputActionMapping != null)
|
||||
if (GetInputActionMapping(GetHand(handedness), handEvent, out InputActionMapping inputActionMapping))
|
||||
{
|
||||
try
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kPoseType)
|
||||
{
|
||||
# if USE_INPUT_SYSTEM_POSE_CONTROL
|
||||
UnityEngine.InputSystem.XR.PoseState pose = inputActionMapping.inputAction.ReadValue<UnityEngine.InputSystem.XR.PoseState>();
|
||||
#else
|
||||
UnityEngine.XR.OpenXR.Input.Pose pose = inputActionMapping.inputAction.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>();
|
||||
#endif
|
||||
eventResult = new Pose(pose.position, pose.rotation);
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -495,13 +515,13 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
jointPose = Pose.identity;
|
||||
if (handedness == Handedness.Left)
|
||||
{
|
||||
jointPose = new Pose(leftHand.joints[(int)joint].position, leftHand.joints[(int)joint].rotation);
|
||||
return leftHand.joints[(int)joint].isValid;
|
||||
jointPose = new Pose(m_LeftHand.joints[(int)joint].position, m_LeftHand.joints[(int)joint].rotation);
|
||||
return m_LeftHand.joints[(int)joint].isValid;
|
||||
}
|
||||
else
|
||||
{
|
||||
jointPose = new Pose(rightHand.joints[(int)joint].position, rightHand.joints[(int)joint].rotation);
|
||||
return rightHand.joints[(int)joint].isValid;
|
||||
jointPose = new Pose(m_RightHand.joints[(int)joint].position, m_RightHand.joints[(int)joint].rotation);
|
||||
return m_RightHand.joints[(int)joint].isValid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,24 +533,27 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
public static bool IsHandTracked(Handedness handedness)
|
||||
{
|
||||
CheckHandUpdated();
|
||||
return handedness == Handedness.Left ? leftHand.isTracked : rightHand.isTracked;
|
||||
return handedness == Handedness.Left ? m_LeftHand.isTracked : m_RightHand.isTracked;
|
||||
}
|
||||
|
||||
public static bool IsHandValidate()
|
||||
{
|
||||
if (!m_IsInitInputActions)
|
||||
{
|
||||
ViveHandTracking viveHand = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
if (viveHand)
|
||||
{
|
||||
return true;
|
||||
m_IsSupportViveHand = true;
|
||||
}
|
||||
#if UNITY_XR_HANDS
|
||||
HandTracking xrHand = OpenXRSettings.Instance.GetFeature<HandTracking>();
|
||||
if (xrHand)
|
||||
{
|
||||
return true;
|
||||
m_IsSupportXrHand = true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return m_IsSupportViveHand || m_IsSupportXrHand;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -538,187 +561,228 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
private static bool CheckInitialize()
|
||||
{
|
||||
if (!isInitInputActions)
|
||||
if (!m_IsInitInputActions)
|
||||
{
|
||||
Initialized();
|
||||
isInitInputActions = true;
|
||||
IsHandValidate();
|
||||
m_IsInitInputActions = true;
|
||||
}
|
||||
return isInitInputActions;
|
||||
return m_IsInitInputActions;
|
||||
}
|
||||
|
||||
private static void Initialized()
|
||||
{
|
||||
#region Head
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/isTracked", DeviceCategory.HMD, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyePosition", DeviceCategory.HMD, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeRotation", DeviceCategory.HMD, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeVelocity", DeviceCategory.HMD, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAngularVelocity", DeviceCategory.HMD, poseState: PoseState.AngularVelocity));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAcceleration", DeviceCategory.HMD, poseState: PoseState.Acceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAngularAcceleration", DeviceCategory.HMD, poseState: PoseState.AngularAcceleration));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/isTracked", DeviceCategory.HMD, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyePosition", DeviceCategory.HMD, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeRotation", DeviceCategory.HMD, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeVelocity", DeviceCategory.HMD, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAngularVelocity", DeviceCategory.HMD, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAcceleration", DeviceCategory.HMD, in_PoseState: PoseState.Acceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAngularAcceleration", DeviceCategory.HMD, in_PoseState: PoseState.AngularAcceleration, in_Type: kVector3Type));
|
||||
#endregion
|
||||
#region Eye
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/isTracked", DeviceCategory.CenterEye, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/position", DeviceCategory.CenterEye, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/rotation", DeviceCategory.CenterEye, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/velocity", DeviceCategory.CenterEye, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/angularVelocity", DeviceCategory.CenterEye, poseState: PoseState.AngularVelocity));
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/isTracked", DeviceCategory.CenterEye, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/position", DeviceCategory.CenterEye, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/rotation", DeviceCategory.CenterEye, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/velocity", DeviceCategory.CenterEye, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/angularVelocity", DeviceCategory.CenterEye, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
#endregion
|
||||
#region Controller
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/isTracked", DeviceCategory.LeftController, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/pointerPosition", DeviceCategory.LeftController, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/pointerRotation", DeviceCategory.LeftController, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceVelocity", DeviceCategory.LeftController, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAngularVelocity", DeviceCategory.LeftController, poseState: PoseState.AngularVelocity));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAcceleration", DeviceCategory.LeftController, poseState: PoseState.Acceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAngularAcceleration", DeviceCategory.LeftController, poseState: PoseState.AngularAcceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{grip}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.GripValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{gripButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.GripPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{trigger}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.TriggerValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/triggerTouched", DeviceCategory.LeftController, buttonEvent: ButtonEvent.TriggerTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{triggerButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.TriggerPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxis}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Primary2DAxisValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxisTouch}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Primary2DAxisTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxisClick}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Primary2DAxisPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxis}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Secondary2DAxisValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxisTouch}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Secondary2DAxisTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxisClick}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Secondary2DAxisPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primaryButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.PrimaryButton));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondaryButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.SecondaryButton));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/parkingTouched", DeviceCategory.LeftController, buttonEvent: ButtonEvent.ParkingTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/menu", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Menu));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/isTracked", DeviceCategory.LeftController, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/pointerPosition", DeviceCategory.LeftController, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/pointerRotation", DeviceCategory.LeftController, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceVelocity", DeviceCategory.LeftController, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAngularVelocity", DeviceCategory.LeftController, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAcceleration", DeviceCategory.LeftController, in_PoseState: PoseState.Acceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAngularAcceleration", DeviceCategory.LeftController, in_PoseState: PoseState.AngularAcceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{grip}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.GripValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{gripButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.GripPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{trigger}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.TriggerValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/triggerTouched", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.TriggerTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{triggerButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.TriggerPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxis}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Primary2DAxisValue, in_Type: kVector2Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxisTouch}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Primary2DAxisTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxisClick}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Primary2DAxisPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxis}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Secondary2DAxisValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxisTouch}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Secondary2DAxisTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxisClick}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Secondary2DAxisPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primaryButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.PrimaryButton, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondaryButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.SecondaryButton, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/parkingTouched", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.ParkingTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/menu", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Menu, in_Type: kFloatType));
|
||||
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/isTracked", DeviceCategory.RightController, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/pointerPosition", DeviceCategory.RightController, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/pointerRotation", DeviceCategory.RightController, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceVelocity", DeviceCategory.RightController, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAngularVelocity", DeviceCategory.RightController, poseState: PoseState.AngularVelocity));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAcceleration", DeviceCategory.RightController, poseState: PoseState.Acceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAngularAcceleration", DeviceCategory.RightController, poseState: PoseState.AngularAcceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{grip}", DeviceCategory.RightController, buttonEvent: ButtonEvent.GripValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{gripButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.GripPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{trigger}", DeviceCategory.RightController, buttonEvent: ButtonEvent.TriggerValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/triggerTouched", DeviceCategory.RightController, buttonEvent: ButtonEvent.TriggerTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{triggerButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.TriggerPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxis}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Primary2DAxisValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxisTouch}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Primary2DAxisTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxisClick}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Primary2DAxisPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxis}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Secondary2DAxisValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxisTouch}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Secondary2DAxisTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxisClick}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Secondary2DAxisPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primaryButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.PrimaryButton));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondaryButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.SecondaryButton));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/parkingTouched", DeviceCategory.RightController, buttonEvent: ButtonEvent.ParkingTouch));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/isTracked", DeviceCategory.RightController, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/pointerPosition", DeviceCategory.RightController, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/pointerRotation", DeviceCategory.RightController, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceVelocity", DeviceCategory.RightController, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAngularVelocity", DeviceCategory.RightController, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAcceleration", DeviceCategory.RightController, in_PoseState: PoseState.Acceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAngularAcceleration", DeviceCategory.RightController, in_PoseState: PoseState.AngularAcceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{grip}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.GripValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{gripButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.GripPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{trigger}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.TriggerValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/triggerTouched", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.TriggerTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{triggerButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.TriggerPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxis}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Primary2DAxisValue, in_Type: kVector2Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxisTouch}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Primary2DAxisTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxisClick}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Primary2DAxisPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxis}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Secondary2DAxisValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxisTouch}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Secondary2DAxisTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxisClick}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Secondary2DAxisPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primaryButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.PrimaryButton, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondaryButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.SecondaryButton, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/parkingTouched", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.ParkingTouch, in_Type: kFloatType));
|
||||
#endregion
|
||||
#region Hand
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/selectValue", DeviceCategory.LeftHand, handEvent: HandEvent.PinchValue));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/pointerPose", DeviceCategory.LeftHand, handEvent: HandEvent.PinchPose));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/gripValue", DeviceCategory.LeftHand, handEvent: HandEvent.GraspValue));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/devicePose", DeviceCategory.LeftHand, handEvent: HandEvent.GraspPose));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/selectValue", DeviceCategory.LeftHand, in_HandEvent: HandEvent.PinchValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/pointerPose", DeviceCategory.LeftHand, in_HandEvent: HandEvent.PinchPose, in_Type: kPoseType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/gripValue", DeviceCategory.LeftHand, in_HandEvent: HandEvent.GraspValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/devicePose", DeviceCategory.LeftHand, in_HandEvent: HandEvent.GraspPose, in_Type: kPoseType));
|
||||
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/selectValue", DeviceCategory.RightHand, handEvent: HandEvent.PinchValue));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/pointerPose", DeviceCategory.RightHand, handEvent: HandEvent.PinchPose));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/gripValue", DeviceCategory.RightHand, handEvent: HandEvent.GraspValue));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/devicePose", DeviceCategory.RightHand, handEvent: HandEvent.GraspPose));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/selectValue", DeviceCategory.RightHand, in_HandEvent: HandEvent.PinchValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/pointerPose", DeviceCategory.RightHand, in_HandEvent: HandEvent.PinchPose, in_Type: kPoseType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/gripValue", DeviceCategory.RightHand, in_HandEvent: HandEvent.GraspValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/devicePose", DeviceCategory.RightHand, in_HandEvent: HandEvent.GraspPose, in_Type: kPoseType));
|
||||
#endregion
|
||||
#region Tracker
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/isTracked", DeviceCategory.Tracker0, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePosition", DeviceCategory.Tracker0, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/deviceRotation", DeviceCategory.Tracker0, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/velocity", DeviceCategory.Tracker0, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/angularVelocity", DeviceCategory.Tracker0, poseState: PoseState.AngularVelocity));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/isTracked", DeviceCategory.Tracker0, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePosition", DeviceCategory.Tracker0, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/deviceRotation", DeviceCategory.Tracker0, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/velocity", DeviceCategory.Tracker0, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/angularVelocity", DeviceCategory.Tracker0, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/isTracked", DeviceCategory.Tracker1, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePosition", DeviceCategory.Tracker1, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/deviceRotation", DeviceCategory.Tracker1, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/velocity", DeviceCategory.Tracker1, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/angularVelocity", DeviceCategory.Tracker1, poseState: PoseState.AngularVelocity));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/isTracked", DeviceCategory.Tracker1, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePosition", DeviceCategory.Tracker1, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/deviceRotation", DeviceCategory.Tracker1, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/velocity", DeviceCategory.Tracker1, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/angularVelocity", DeviceCategory.Tracker1, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/isTracked", DeviceCategory.Tracker2, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePosition", DeviceCategory.Tracker2, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/deviceRotation", DeviceCategory.Tracker2, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/velocity", DeviceCategory.Tracker2, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/angularVelocity", DeviceCategory.Tracker2, poseState: PoseState.AngularVelocity));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/isTracked", DeviceCategory.Tracker2, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePosition", DeviceCategory.Tracker2, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/deviceRotation", DeviceCategory.Tracker2, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/velocity", DeviceCategory.Tracker2, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/angularVelocity", DeviceCategory.Tracker2, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/isTracked", DeviceCategory.Tracker3, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePosition", DeviceCategory.Tracker3, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/deviceRotation", DeviceCategory.Tracker3, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/velocity", DeviceCategory.Tracker3, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/angularVelocity", DeviceCategory.Tracker3, poseState: PoseState.AngularVelocity));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/isTracked", DeviceCategory.Tracker3, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePosition", DeviceCategory.Tracker3, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/deviceRotation", DeviceCategory.Tracker3, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/velocity", DeviceCategory.Tracker3, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/angularVelocity", DeviceCategory.Tracker3, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/isTracked", DeviceCategory.Tracker4, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePosition", DeviceCategory.Tracker4, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/deviceRotation", DeviceCategory.Tracker4, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/velocity", DeviceCategory.Tracker4, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/angularVelocity", DeviceCategory.Tracker4, poseState: PoseState.AngularVelocity));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/isTracked", DeviceCategory.Tracker4, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePosition", DeviceCategory.Tracker4, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/deviceRotation", DeviceCategory.Tracker4, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/velocity", DeviceCategory.Tracker4, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/angularVelocity", DeviceCategory.Tracker4, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
#endregion
|
||||
}
|
||||
|
||||
private static bool GetInputActionMapping(DeviceCategory device, PoseState poseState, out InputActionMapping inputActionMapping)
|
||||
{
|
||||
inputActionMapping = default;
|
||||
for (int i = 0; i < s_InputActions.Count; i++)
|
||||
{
|
||||
var action = s_InputActions[i];
|
||||
if (action.device == device && action.poseState == poseState)
|
||||
{
|
||||
inputActionMapping = action;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool GetInputActionMapping(DeviceCategory device, ButtonEvent buttonEvent, out InputActionMapping inputActionMapping)
|
||||
{
|
||||
inputActionMapping = default;
|
||||
for (int i = 0; i < s_InputActions.Count; i++)
|
||||
{
|
||||
var action = s_InputActions[i];
|
||||
if (action.device == device && action.buttonEvent == buttonEvent)
|
||||
{
|
||||
inputActionMapping = action;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool GetInputActionMapping(DeviceCategory device, HandEvent handEvent, out InputActionMapping inputActionMapping)
|
||||
{
|
||||
inputActionMapping = default;
|
||||
for (int i = 0; i < s_InputActions.Count; i++)
|
||||
{
|
||||
var action = s_InputActions[i];
|
||||
if (action.device == device && action.handEvent == handEvent)
|
||||
{
|
||||
inputActionMapping = action;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void CheckHandUpdated()
|
||||
{
|
||||
if (Time.frameCount > leftHand.updateTime ||
|
||||
Time.frameCount > rightHand.updateTime)
|
||||
int frameCount = Time.frameCount;
|
||||
if (frameCount > m_LeftHand.updateTime ||
|
||||
frameCount > m_RightHand.updateTime)
|
||||
{
|
||||
ViveHandTracking viveHand = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
if (viveHand)
|
||||
{
|
||||
UpdateViveHand(true, viveHand);
|
||||
UpdateViveHand(false, viveHand);
|
||||
}
|
||||
|
||||
#if UNITY_XR_HANDS
|
||||
HandTracking xrHand = OpenXRSettings.Instance.GetFeature<HandTracking>();
|
||||
if (xrHand)
|
||||
if (m_IsSupportViveHand || m_IsSupportXrHand)
|
||||
{
|
||||
if (handSubsystem == null || !handSubsystem.running)
|
||||
if (m_HandSubsystem == null || !m_HandSubsystem.running)
|
||||
{
|
||||
if (handSubsystem != null && !handSubsystem.running)
|
||||
if (m_HandSubsystem != null)
|
||||
{
|
||||
handSubsystem.updatedHands -= OnUpdatedHands;
|
||||
handSubsystem = null;
|
||||
m_HandSubsystem.updatedHands -= OnUpdatedHands;
|
||||
m_HandSubsystem = null;
|
||||
}
|
||||
|
||||
var handSubsystems = new List<XRHandSubsystem>();
|
||||
SubsystemManager.GetSubsystems(handSubsystems);
|
||||
for (var i = 0; i < handSubsystems.Count; ++i)
|
||||
m_HandSubsystems.Clear();
|
||||
SubsystemManager.GetSubsystems(m_HandSubsystems);
|
||||
for (var i = 0; i < m_HandSubsystems.Count; ++i)
|
||||
{
|
||||
var xrHnad = handSubsystems[i];
|
||||
if (xrHnad.running)
|
||||
var xrHand = m_HandSubsystems[i];
|
||||
if (xrHand.running)
|
||||
{
|
||||
handSubsystem = xrHnad;
|
||||
m_HandSubsystem = xrHand;
|
||||
m_HandSubsystem.updatedHands += OnUpdatedHands;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (handSubsystem != null && handSubsystem.running)
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (m_IsSupportViveHand)
|
||||
{
|
||||
handSubsystem.updatedHands += OnUpdatedHands;
|
||||
}
|
||||
}
|
||||
UpdateViveHand(true);
|
||||
UpdateViveHand(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateViveHand(bool isLeft, ViveHandTracking viveHand)
|
||||
private static void UpdateViveHand(bool isLeft)
|
||||
{
|
||||
bool isUpdated = viveHand.GetJointLocations(isLeft, out XrHandJointLocationEXT[] viveJoints);
|
||||
JointData[] joints = new JointData[viveJoints.Length];
|
||||
for (int i = 0; i < joints.Length; i++)
|
||||
bool isUpdated = XR_EXT_hand_tracking.Interop.GetJointLocations(isLeft, out XrHandJointLocationEXT[] viveJoints);
|
||||
for (int i = 0; i < m_JointBuffer.Length; i++)
|
||||
{
|
||||
bool isValid = isUpdated &&
|
||||
viveJoints[i].locationFlags.HasFlag(XrSpaceLocationFlags.XR_SPACE_LOCATION_POSITION_TRACKED_BIT) &&
|
||||
viveJoints[i].locationFlags.HasFlag(XrSpaceLocationFlags.XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT);
|
||||
Vector3 position = viveJoints[i].pose.position.ToUnityVector();
|
||||
Quaternion rotation = viveJoints[i].pose.orientation.ToUnityQuaternion();
|
||||
joints[i] = new JointData(isValid, position, rotation);
|
||||
m_JointBuffer[i] = new JointData(isValid, position, rotation);
|
||||
}
|
||||
if (isLeft)
|
||||
{
|
||||
leftHand.Update(joints);
|
||||
m_LeftHand.Update(m_JointBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
rightHand.Update(joints);
|
||||
m_RightHand.Update(m_JointBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -732,24 +796,30 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateXRHand(bool isLeft, XRHandSubsystem xrHnad, bool isUpdated)
|
||||
private static void UpdateXRHand(bool isLeft, XRHandSubsystem xrHand, bool isUpdated)
|
||||
{
|
||||
JointData[] joints = new JointData[(int)HandJointType.Count];
|
||||
for (int i = 0; i < joints.Length; i++)
|
||||
for (int i = 0; i < m_JointBuffer.Length; i++)
|
||||
{
|
||||
XRHandJointID jointId = JointTypeToXRId(i);
|
||||
XRHandJoint joint = (isLeft ? xrHnad.leftHand : xrHnad.rightHand).GetJoint(jointId);
|
||||
bool isValid = isUpdated && joint.trackingState.HasFlag(XRHandJointTrackingState.Pose);
|
||||
joint.TryGetPose(out Pose pose);
|
||||
joints[i] = new JointData(isValid, pose.position, pose.rotation);
|
||||
}
|
||||
if (isLeft)
|
||||
XRHandJoint joint = (isLeft ? xrHand.leftHand : xrHand.rightHand).GetJoint(jointId);
|
||||
|
||||
if (isUpdated && joint.trackingState.HasFlag(XRHandJointTrackingState.Pose))
|
||||
{
|
||||
leftHand.Update(joints);
|
||||
joint.TryGetPose(out Pose pose);
|
||||
m_JointBuffer[i] = new JointData(true, pose.position, pose.rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
rightHand.Update(joints);
|
||||
m_JointBuffer[i] = new JointData(false, Vector3.zero, Quaternion.identity);
|
||||
}
|
||||
}
|
||||
if (isLeft)
|
||||
{
|
||||
m_LeftHand.Update(m_JointBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RightHand.Update(m_JointBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using System.Threading.Tasks;
|
||||
using VIVE.OpenXR;
|
||||
using System.Linq;
|
||||
|
||||
namespace VIVE.OpenXR.Passthrough
|
||||
{
|
||||
@@ -27,13 +26,7 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return false;
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
private static Dictionary<XrPassthroughHTC, XrCompositionLayerPassthroughHTC> passthrough2Layer = new Dictionary<XrPassthroughHTC, XrCompositionLayerPassthroughHTC>();
|
||||
private static Dictionary<XrPassthroughHTC, IntPtr> passthrough2LayerPtr = new Dictionary<XrPassthroughHTC, IntPtr>();
|
||||
private static Dictionary<XrPassthroughHTC, bool> passthrough2IsUnderLay= new Dictionary<XrPassthroughHTC, bool>();
|
||||
private static Dictionary<XrPassthroughHTC, XrPassthroughMeshTransformInfoHTC> passthrough2meshTransform = new Dictionary<XrPassthroughHTC, XrPassthroughMeshTransformInfoHTC>();
|
||||
private static Dictionary<XrPassthroughHTC, IntPtr> passthrough2meshTransformInfoPtr = new Dictionary<XrPassthroughHTC, IntPtr>();
|
||||
#endif
|
||||
private static Dictionary<XrPassthroughHTC, PassthroughLayer> layersDict = new Dictionary<XrPassthroughHTC, PassthroughLayer>();
|
||||
|
||||
#region Public APIs
|
||||
/// <summary>
|
||||
@@ -58,42 +51,32 @@ namespace VIVE.OpenXR.Passthrough
|
||||
}
|
||||
XrPassthroughCreateInfoHTC createInfo = new XrPassthroughCreateInfoHTC(
|
||||
XrStructureType.XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC,
|
||||
#if UNITY_ANDROID
|
||||
IntPtr.Zero,
|
||||
#else
|
||||
new IntPtr(6), //Enter IntPtr(0) for backward compatibility (using createPassthrough to enable the passthrough feature), or enter IntPtr(6) to enable the passthrough feature based on the layer submitted to endframe.
|
||||
#endif
|
||||
XrPassthroughFormHTC.XR_PASSTHROUGH_FORM_PLANAR_HTC
|
||||
);
|
||||
|
||||
#if UNITY_ANDROID
|
||||
res = passthroughFeature.CreatePassthroughHTC(createInfo, out passthrough, layerType, compositionDepth, onDestroyPassthroughSessionHandler);
|
||||
DEBUG("CreatePlanarPassthrough() CreatePassthroughHTC result: " + res + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
#if UNITY_STANDALONE
|
||||
res = XR_HTC_passthrough.xrCreatePassthroughHTC(createInfo, out passthrough);
|
||||
if(res == XrResult.XR_SUCCESS)
|
||||
{
|
||||
XrPassthroughColorHTC passthroughColor = new XrPassthroughColorHTC(
|
||||
in_type: XrStructureType.XR_TYPE_PASSTHROUGH_COLOR_HTC,
|
||||
in_next: IntPtr.Zero,
|
||||
in_alpha: alpha);
|
||||
XrCompositionLayerPassthroughHTC compositionLayerPassthrough = new XrCompositionLayerPassthroughHTC(
|
||||
in_type: XrStructureType.XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC,
|
||||
in_next: IntPtr.Zero,
|
||||
in_layerFlags: (UInt64)XrCompositionLayerFlagBits.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT,
|
||||
in_space: 0,
|
||||
in_passthrough: passthrough,
|
||||
in_color: passthroughColor);
|
||||
passthrough2Layer.Add(passthrough, compositionLayerPassthrough);
|
||||
IntPtr layerPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrCompositionLayerPassthroughHTC)));
|
||||
passthrough2LayerPtr.Add(passthrough, layerPtr);
|
||||
if (layerType == CompositionLayer.LayerType.Underlay)
|
||||
passthrough2IsUnderLay.Add(passthrough, true);
|
||||
if (layerType == CompositionLayer.LayerType.Overlay)
|
||||
passthrough2IsUnderLay.Add(passthrough, false);
|
||||
PassthroughLayer layer = new PassthroughLayer(passthrough, layerType);
|
||||
var xrLayer = PassthroughLayer.MakeEmptyLayer();
|
||||
xrLayer.passthrough = passthrough;
|
||||
xrLayer.layerFlags = (UInt64)XrCompositionLayerFlagBits.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
|
||||
xrLayer.color.alpha = alpha;
|
||||
layer.SetLayer(xrLayer);
|
||||
|
||||
layersDict.Add(passthrough, layer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (res == XrResult.XR_SUCCESS)
|
||||
{
|
||||
SetPassthroughAlpha(passthrough, alpha);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -138,54 +121,34 @@ namespace VIVE.OpenXR.Passthrough
|
||||
|
||||
XrPassthroughCreateInfoHTC createInfo = new XrPassthroughCreateInfoHTC(
|
||||
XrStructureType.XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC,
|
||||
#if UNITY_ANDROID
|
||||
IntPtr.Zero,
|
||||
#else
|
||||
new IntPtr(6), //Enter IntPtr(0) for backward compatibility (using createPassthrough to enable the passthrough feature), or enter IntPtr(6) to enable the passthrough feature based on the layer submitted to endframe.
|
||||
#endif
|
||||
XrPassthroughFormHTC.XR_PASSTHROUGH_FORM_PROJECTED_HTC
|
||||
);
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
res = XR_HTC_passthrough.xrCreatePassthroughHTC(createInfo, out passthrough);
|
||||
if (res == XrResult.XR_SUCCESS)
|
||||
{
|
||||
XrPassthroughMeshTransformInfoHTC PassthroughMeshTransformInfo = new XrPassthroughMeshTransformInfoHTC(
|
||||
in_type: XrStructureType.XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC,
|
||||
in_next: IntPtr.Zero,
|
||||
in_vertexCount: 0,
|
||||
in_vertices: new XrVector3f[0],
|
||||
in_indexCount: 0,
|
||||
in_indices: new UInt32[0],
|
||||
in_baseSpace: XR_HTC_passthrough.Interop.GetTrackingSpace(),
|
||||
in_time: XR_HTC_passthrough.Interop.GetFrameState().predictedDisplayTime,
|
||||
in_pose: new XrPosef(),
|
||||
in_scale: new XrVector3f()
|
||||
);
|
||||
IntPtr meshTransformInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrPassthroughMeshTransformInfoHTC)));
|
||||
Marshal.StructureToPtr(PassthroughMeshTransformInfo, meshTransformInfoPtr, false);
|
||||
XrPassthroughColorHTC passthroughColor = new XrPassthroughColorHTC(
|
||||
in_type: XrStructureType.XR_TYPE_PASSTHROUGH_COLOR_HTC,
|
||||
in_next: IntPtr.Zero,
|
||||
in_alpha: alpha);
|
||||
XrCompositionLayerPassthroughHTC compositionLayerPassthrough = new XrCompositionLayerPassthroughHTC(
|
||||
in_type: XrStructureType.XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC,
|
||||
in_next: meshTransformInfoPtr,
|
||||
in_layerFlags: (UInt64)XrCompositionLayerFlagBits.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT,
|
||||
in_space: 0,
|
||||
in_passthrough: passthrough,
|
||||
in_color: passthroughColor);
|
||||
passthrough2meshTransform.Add(passthrough, PassthroughMeshTransformInfo);
|
||||
passthrough2meshTransformInfoPtr.Add(passthrough, meshTransformInfoPtr);
|
||||
passthrough2Layer.Add(passthrough, compositionLayerPassthrough);
|
||||
IntPtr layerPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrCompositionLayerPassthroughHTC)));
|
||||
passthrough2LayerPtr.Add(passthrough, layerPtr);
|
||||
if (layerType == CompositionLayer.LayerType.Underlay)
|
||||
passthrough2IsUnderLay.Add(passthrough, true);
|
||||
if (layerType == CompositionLayer.LayerType.Overlay)
|
||||
passthrough2IsUnderLay.Add(passthrough, false);
|
||||
var layer = new PassthroughLayer(passthrough, layerType);
|
||||
var xrLayer = PassthroughLayer.MakeEmptyLayer();
|
||||
xrLayer.passthrough = passthrough;
|
||||
xrLayer.layerFlags = (UInt64)XrCompositionLayerFlagBits.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
|
||||
xrLayer.space = 0;
|
||||
xrLayer.color.alpha = alpha;
|
||||
layer.SetLayer(xrLayer);
|
||||
var xrMesh = PassthroughLayer.MakeMeshTransform();
|
||||
|
||||
xrMesh.time = XR_HTC_passthrough.Interop.GetFrameState().predictedDisplayTime;
|
||||
xrMesh.baseSpace = XR_HTC_passthrough.Interop.GetTrackingSpace();
|
||||
xrMesh.scale = new XrVector3f(meshScale.x, meshScale.y, meshScale.z);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
|
||||
layersDict.Add(passthrough, layer);
|
||||
}
|
||||
#endif
|
||||
#if UNITY_ANDROID
|
||||
res = passthroughFeature.CreatePassthroughHTC(createInfo, out passthrough, layerType, compositionDepth, onDestroyPassthroughSessionHandler);
|
||||
DEBUG("CreateProjectedPassthrough() CreatePassthroughHTC result: " + res + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
|
||||
if (res == XrResult.XR_SUCCESS)
|
||||
{
|
||||
SetPassthroughAlpha(passthrough, alpha);
|
||||
@@ -219,54 +182,30 @@ namespace VIVE.OpenXR.Passthrough
|
||||
|
||||
XrPassthroughCreateInfoHTC createInfo = new XrPassthroughCreateInfoHTC(
|
||||
XrStructureType.XR_TYPE_PASSTHROUGH_CREATE_INFO_HTC,
|
||||
#if UNITY_ANDROID
|
||||
IntPtr.Zero,
|
||||
#else
|
||||
new IntPtr(6), //Enter IntPtr(0) for backward compatibility (using createPassthrough to enable the passthrough feature), or enter IntPtr(6) to enable the passthrough feature based on the layer submitted to endframe.
|
||||
#endif
|
||||
XrPassthroughFormHTC.XR_PASSTHROUGH_FORM_PROJECTED_HTC
|
||||
);
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
res = XR_HTC_passthrough.xrCreatePassthroughHTC(createInfo, out passthrough);
|
||||
if (res == XrResult.XR_SUCCESS)
|
||||
{
|
||||
XrPassthroughMeshTransformInfoHTC PassthroughMeshTransformInfo = new XrPassthroughMeshTransformInfoHTC(
|
||||
in_type: XrStructureType.XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC,
|
||||
in_next: IntPtr.Zero,
|
||||
in_vertexCount: 0,
|
||||
in_vertices: new XrVector3f[0],
|
||||
in_indexCount: 0,
|
||||
in_indices: new UInt32[0],
|
||||
in_baseSpace: XR_HTC_passthrough.Interop.GetTrackingSpace(),
|
||||
in_time: XR_HTC_passthrough.Interop.GetFrameState().predictedDisplayTime,
|
||||
in_pose: new XrPosef(),
|
||||
in_scale: new XrVector3f()
|
||||
);
|
||||
IntPtr meshTransformInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrPassthroughMeshTransformInfoHTC)));
|
||||
Marshal.StructureToPtr(PassthroughMeshTransformInfo, meshTransformInfoPtr, false);
|
||||
XrPassthroughColorHTC passthroughColor = new XrPassthroughColorHTC(
|
||||
in_type: XrStructureType.XR_TYPE_PASSTHROUGH_COLOR_HTC,
|
||||
in_next: IntPtr.Zero,
|
||||
in_alpha: alpha);
|
||||
XrCompositionLayerPassthroughHTC compositionLayerPassthrough = new XrCompositionLayerPassthroughHTC(
|
||||
in_type: XrStructureType.XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC,
|
||||
in_next: meshTransformInfoPtr,
|
||||
in_layerFlags: (UInt64)XrCompositionLayerFlagBits.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT,
|
||||
in_space: 0,
|
||||
in_passthrough: passthrough,
|
||||
in_color: passthroughColor);
|
||||
passthrough2meshTransform.Add(passthrough, PassthroughMeshTransformInfo);
|
||||
passthrough2meshTransformInfoPtr.Add(passthrough, meshTransformInfoPtr);
|
||||
passthrough2Layer.Add(passthrough, compositionLayerPassthrough);
|
||||
IntPtr layerPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrCompositionLayerPassthroughHTC)));
|
||||
passthrough2LayerPtr.Add(passthrough, layerPtr);
|
||||
if (layerType == CompositionLayer.LayerType.Underlay)
|
||||
passthrough2IsUnderLay.Add(passthrough, true);
|
||||
if (layerType == CompositionLayer.LayerType.Overlay)
|
||||
passthrough2IsUnderLay.Add(passthrough, false);
|
||||
var layer = new PassthroughLayer(passthrough, layerType);
|
||||
var xrLayer = PassthroughLayer.MakeEmptyLayer();
|
||||
xrLayer.passthrough = passthrough;
|
||||
xrLayer.layerFlags = (UInt64)XrCompositionLayerFlagBits.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
|
||||
xrLayer.color.alpha = alpha;
|
||||
layer.SetLayer(xrLayer);
|
||||
|
||||
var xrMesh = PassthroughLayer.MakeMeshTransform();
|
||||
layer.SetMeshTransform(xrMesh, true);
|
||||
|
||||
layersDict.Add(passthrough, layer);
|
||||
}
|
||||
#endif
|
||||
#if UNITY_ANDROID
|
||||
res = passthroughFeature.CreatePassthroughHTC(createInfo, out passthrough, layerType, onDestroyPassthroughSessionHandler);
|
||||
DEBUG("CreateProjectedPassthrough() CreatePassthroughHTC result: " + res + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
|
||||
if (res == XrResult.XR_SUCCESS)
|
||||
{
|
||||
SetPassthroughAlpha(passthrough, alpha);
|
||||
@@ -275,35 +214,10 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return res;
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
private static async void SubmitLayer()
|
||||
private static void SubmitLayer()
|
||||
{
|
||||
await Task.Run(() => {
|
||||
int layerListCount = 0;
|
||||
while(layerListCount == 0)
|
||||
{
|
||||
System.Threading.Thread.Sleep(1);
|
||||
XR_HTC_passthrough.Interop.GetOriginEndFrameLayerList(out List<IntPtr> layerList);//GetOriginEndFrameLayers
|
||||
layerListCount = layerList.Count;
|
||||
foreach (var passthrough in passthrough2IsUnderLay.Keys)
|
||||
{
|
||||
//Get and submit layer list
|
||||
if (layerListCount != 0)
|
||||
{
|
||||
Marshal.StructureToPtr(passthrough2Layer[passthrough], passthrough2LayerPtr[passthrough], false);
|
||||
if (passthrough2IsUnderLay[passthrough])
|
||||
layerList.Insert(0, passthrough2LayerPtr[passthrough]);
|
||||
else
|
||||
layerList.Insert(1, passthrough2LayerPtr[passthrough]);
|
||||
passthroughFeature.SubmitLayers(layersDict.Values.ToList());
|
||||
}
|
||||
}
|
||||
if(layerListCount != 0)
|
||||
XR_HTC_passthrough.Interop.SubmitLayers(layerList);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// To Destroying a passthrough.
|
||||
@@ -326,23 +240,17 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return res;
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
XrPassthroughHTC pt = passthrough2Layer[passthrough].passthrough;
|
||||
XR_HTC_passthrough.xrDestroyPassthroughHTC(pt);
|
||||
passthrough2IsUnderLay.Remove(passthrough);
|
||||
if (layersDict.ContainsKey(passthrough))
|
||||
{
|
||||
XR_HTC_passthrough.xrDestroyPassthroughHTC(passthrough);
|
||||
var layer = layersDict[passthrough];
|
||||
layer.Dispose();
|
||||
layersDict.Remove(passthrough);
|
||||
}
|
||||
|
||||
SubmitLayer();
|
||||
passthrough2Layer.Remove(pt);
|
||||
if(passthrough2LayerPtr.ContainsKey(passthrough)) Marshal.FreeHGlobal(passthrough2LayerPtr[passthrough]);
|
||||
passthrough2LayerPtr.Remove(passthrough);
|
||||
if(passthrough2meshTransformInfoPtr.ContainsKey(passthrough)) Marshal.FreeHGlobal(passthrough2meshTransformInfoPtr[passthrough]);
|
||||
passthrough2meshTransformInfoPtr.Remove(passthrough);
|
||||
passthrough2meshTransform.Remove(passthrough);
|
||||
|
||||
res = XrResult.XR_SUCCESS;
|
||||
#elif UNITY_ANDROID
|
||||
res = passthroughFeature.DestroyPassthroughHTC(passthrough);
|
||||
DEBUG("DestroyPassthrough() DestroyPassthroughHTC result: " + res + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -368,36 +276,18 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if UNITY_ANDROID
|
||||
if (autoClamp)
|
||||
if (layersDict.ContainsKey(passthrough))
|
||||
{
|
||||
ret = passthroughFeature.SetAlpha(passthrough, Mathf.Clamp01(alpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (alpha < 0f || alpha > 1f)
|
||||
{
|
||||
ERROR("SetPassthroughAlpha: Alpha out of range");
|
||||
return ret;
|
||||
}
|
||||
var layer = layersDict[passthrough];
|
||||
var xrLayer = layer.GetLayer();
|
||||
xrLayer.color.alpha = alpha;
|
||||
layer.SetLayer(xrLayer);
|
||||
|
||||
ret = passthroughFeature.SetAlpha(passthrough, alpha);
|
||||
}
|
||||
DEBUG("SetPassthroughAlpha() SetAlpha result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
if (passthrough2Layer.ContainsKey(passthrough))
|
||||
{
|
||||
XrCompositionLayerPassthroughHTC layer = passthrough2Layer[passthrough];
|
||||
layer.color.alpha = alpha;
|
||||
passthrough2Layer[passthrough] = layer;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -425,47 +315,20 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
XrVector3f[] vertexBufferXrVector = new XrVector3f[vertexBuffer.Length];
|
||||
|
||||
for (int i = 0; i < vertexBuffer.Length; i++)
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
vertexBufferXrVector[i] = OpenXRHelper.ToOpenXRVector(vertexBuffer[i], convertFromUnityToOpenXR);
|
||||
}
|
||||
|
||||
uint[] indexBufferUint = new uint[indexBuffer.Length];
|
||||
|
||||
for (int i = 0; i < indexBuffer.Length; i++)
|
||||
{
|
||||
indexBufferUint[i] = (uint)indexBuffer[i];
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough))
|
||||
{
|
||||
XrPassthroughMeshTransformInfoHTC MeshTransformInfo = passthrough2meshTransform[passthrough];
|
||||
MeshTransformInfo.vertexCount = (uint)vertexBuffer.Length;
|
||||
MeshTransformInfo.vertices = vertexBufferXrVector;
|
||||
MeshTransformInfo.indexCount = (uint)indexBuffer.Length;
|
||||
MeshTransformInfo.indices = indexBufferUint;
|
||||
passthrough2meshTransform[passthrough] = MeshTransformInfo;
|
||||
Marshal.StructureToPtr(MeshTransformInfo, passthrough2meshTransformInfoPtr[passthrough], false);
|
||||
XrCompositionLayerPassthroughHTC layer = passthrough2Layer[passthrough];
|
||||
layer.next = passthrough2meshTransformInfoPtr[passthrough];
|
||||
passthrough2Layer[passthrough] = layer;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
//Note: Ignore Clock-Wise definition of index buffer for now as passthrough extension does not have back-face culling
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMesh(passthrough, (uint)vertexBuffer.Length, vertexBufferXrVector, (uint)indexBuffer.Length, indexBufferUint); ;
|
||||
DEBUG("SetProjectedPassthroughMesh() SetMesh result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
layer.SetMeshData(ref xrMesh, vertexBuffer, indexBuffer, convertFromUnityToOpenXR);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the mesh transform of a projected passthrough layer.
|
||||
/// </summary>
|
||||
@@ -508,31 +371,24 @@ namespace VIVE.OpenXR.Passthrough
|
||||
|
||||
XrVector3f meshXrScale = OpenXRHelper.ToOpenXRVector(meshScale, false);
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough))
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
XrPassthroughMeshTransformInfoHTC MeshTransformInfo = passthrough2meshTransform[passthrough];
|
||||
MeshTransformInfo.pose = meshXrPose;
|
||||
MeshTransformInfo.scale = meshXrScale;
|
||||
passthrough2meshTransform[passthrough] = MeshTransformInfo;
|
||||
Marshal.StructureToPtr(MeshTransformInfo, passthrough2meshTransformInfoPtr[passthrough], false);
|
||||
XrCompositionLayerPassthroughHTC layer = passthrough2Layer[passthrough];
|
||||
layer.next = passthrough2meshTransformInfoPtr[passthrough];
|
||||
passthrough2Layer[passthrough] = layer;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransform(passthrough, passthroughFeature.GetXrSpaceFromSpaceType(spaceType), meshXrPose, meshXrScale);
|
||||
DEBUG("SetProjectedPassthroughMeshTransform() SetMeshTransform result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
xrMesh.pose = meshXrPose;
|
||||
xrMesh.scale = meshXrScale;
|
||||
xrMesh.time = XR_HTC_passthrough.Interop.GetFrameState().predictedDisplayTime;
|
||||
xrMesh.baseSpace = passthroughFeature.GetXrSpaceFromSpaceType(spaceType);
|
||||
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies layer type and composition depth of a passthrough layer.
|
||||
/// </summary>
|
||||
@@ -550,24 +406,20 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
if (passthrough2IsUnderLay.ContainsKey(passthrough))
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
passthrough2IsUnderLay[passthrough] = layerType == CompositionLayer.LayerType.Underlay ? true : false;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetLayerType(passthrough, layerType, compositionDepth);
|
||||
DEBUG("SetPassthroughLayerType() SetLayerType result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
layer.LayerType = layerType;
|
||||
layer.Depth = (int)compositionDepth;
|
||||
|
||||
SubmitLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the space of a projected passthrough layer.
|
||||
/// </summary>
|
||||
@@ -584,30 +436,20 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough))
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
XrPassthroughMeshTransformInfoHTC MeshTransformInfo = passthrough2meshTransform[passthrough];
|
||||
MeshTransformInfo.baseSpace = passthroughFeature.GetXrSpaceFromSpaceType(spaceType);
|
||||
passthrough2meshTransform[passthrough] = MeshTransformInfo;
|
||||
Marshal.StructureToPtr(MeshTransformInfo, passthrough2meshTransformInfoPtr[passthrough], false);
|
||||
XrCompositionLayerPassthroughHTC layer = passthrough2Layer[passthrough];
|
||||
layer.next = passthrough2meshTransformInfoPtr[passthrough];
|
||||
passthrough2Layer[passthrough] = layer;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransformSpace(passthrough, passthroughFeature.GetXrSpaceFromSpaceType(spaceType));
|
||||
DEBUG("SetProjectedPassthroughSpaceType() SetMeshTransformSpace result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
xrMesh.baseSpace = passthroughFeature.GetXrSpaceFromSpaceType(spaceType);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the mesh position of a projected passthrough layer.
|
||||
/// </summary>
|
||||
@@ -639,32 +481,20 @@ namespace VIVE.OpenXR.Passthrough
|
||||
trackingSpaceMeshPosition = trackingSpaceLayerPoseTRS.GetColumn(3); //4th Column of TRS Matrix is the position
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough))
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
XrPassthroughMeshTransformInfoHTC MeshTransformInfo = passthrough2meshTransform[passthrough];
|
||||
XrPosef meshXrPose = MeshTransformInfo.pose;
|
||||
meshXrPose.position = OpenXRHelper.ToOpenXRVector(trackingSpaceMeshPosition, convertFromUnityToOpenXR); ;
|
||||
MeshTransformInfo.pose = meshXrPose;
|
||||
passthrough2meshTransform[passthrough] = MeshTransformInfo;
|
||||
Marshal.StructureToPtr(MeshTransformInfo, passthrough2meshTransformInfoPtr[passthrough], false);
|
||||
XrCompositionLayerPassthroughHTC layer = passthrough2Layer[passthrough];
|
||||
layer.next = passthrough2meshTransformInfoPtr[passthrough];
|
||||
passthrough2Layer[passthrough] = layer;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransformPosition(passthrough, OpenXRHelper.ToOpenXRVector(trackingSpaceMeshPosition, convertFromUnityToOpenXR));
|
||||
DEBUG("SetProjectedPassthroughMeshPosition() SetMeshTransformPosition result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
xrMesh.pose.position = OpenXRHelper.ToOpenXRVector(trackingSpaceMeshPosition, convertFromUnityToOpenXR);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the mesh orientation of a projected passthrough layer.
|
||||
/// </summary>
|
||||
@@ -696,32 +526,20 @@ namespace VIVE.OpenXR.Passthrough
|
||||
trackingSpaceMeshRotation = Quaternion.LookRotation(trackingSpaceLayerPoseTRS.GetColumn(2), trackingSpaceLayerPoseTRS.GetColumn(1));
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough))
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
XrPassthroughMeshTransformInfoHTC MeshTransformInfo = passthrough2meshTransform[passthrough];
|
||||
XrPosef meshXrPose = MeshTransformInfo.pose;
|
||||
meshXrPose.orientation = OpenXRHelper.ToOpenXRQuaternion(trackingSpaceMeshRotation, convertFromUnityToOpenXR);
|
||||
MeshTransformInfo.pose = meshXrPose;
|
||||
passthrough2meshTransform[passthrough] = MeshTransformInfo;
|
||||
Marshal.StructureToPtr(MeshTransformInfo, passthrough2meshTransformInfoPtr[passthrough], false);
|
||||
XrCompositionLayerPassthroughHTC layer = passthrough2Layer[passthrough];
|
||||
layer.next = passthrough2meshTransformInfoPtr[passthrough];
|
||||
passthrough2Layer[passthrough] = layer;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransformOrientation(passthrough, OpenXRHelper.ToOpenXRQuaternion(trackingSpaceMeshRotation, convertFromUnityToOpenXR));
|
||||
DEBUG("SetProjectedPassthroughMeshOrientation() SetMeshTransformOrientation result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
xrMesh.pose.orientation = OpenXRHelper.ToOpenXRQuaternion(trackingSpaceMeshRotation, convertFromUnityToOpenXR);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the mesh scale of a passthrough layer.
|
||||
/// </summary>
|
||||
@@ -738,30 +556,20 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough))
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
XrPassthroughMeshTransformInfoHTC MeshTransformInfo = passthrough2meshTransform[passthrough];
|
||||
MeshTransformInfo.scale = OpenXRHelper.ToOpenXRVector(meshScale, false);
|
||||
passthrough2meshTransform[passthrough] = MeshTransformInfo;
|
||||
Marshal.StructureToPtr(MeshTransformInfo, passthrough2meshTransformInfoPtr[passthrough], false);
|
||||
XrCompositionLayerPassthroughHTC layer = passthrough2Layer[passthrough];
|
||||
layer.next = passthrough2meshTransformInfoPtr[passthrough];
|
||||
passthrough2Layer[passthrough] = layer;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransformScale(passthrough, OpenXRHelper.ToOpenXRVector(meshScale, false));
|
||||
DEBUG("SetProjectedPassthroughScale() SetMeshTransformScale result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
xrMesh.scale = OpenXRHelper.ToOpenXRVector(meshScale, false);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To get the list of IDs of active passthrough layers.
|
||||
/// </summary>
|
||||
|
||||
@@ -699,6 +699,7 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4806409459047702211}
|
||||
- component: {fileID: 5568897672767345397}
|
||||
- component: {fileID: 1039589470112983849}
|
||||
- component: {fileID: 1039589470112983840}
|
||||
- component: {fileID: 1039589470112983852}
|
||||
@@ -725,6 +726,19 @@ Transform:
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &5568897672767345397
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4806409459047702212}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 52790aba0e3d55f4fb27aded6c698d8b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Handedness: 1
|
||||
--- !u!114 &1039589470112983849
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -858,6 +858,7 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7152668487518777764}
|
||||
- component: {fileID: 7057365311429264906}
|
||||
- component: {fileID: 3431167848623168894}
|
||||
- component: {fileID: 3431167848623168881}
|
||||
- component: {fileID: 3431167848623168882}
|
||||
@@ -884,6 +885,19 @@ Transform:
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &7057365311429264906
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7152668487518777765}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 52790aba0e3d55f4fb27aded6c698d8b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Handedness: 0
|
||||
--- !u!114 &3431167848623168894
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
@@ -129,6 +130,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
private HandGrabInteractable candidate = null;
|
||||
private Pose wristPose = Pose.identity;
|
||||
private Quaternion[] fingerJointRotation = new Quaternion[jointsPathMapping.Count];
|
||||
private bool isNewInputSystem = false;
|
||||
|
||||
#region MonoBehaviours
|
||||
|
||||
@@ -156,6 +158,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
sb.Append("However, you still can record grab pose if you use direct preview mode.");
|
||||
WARNING(sb);
|
||||
}
|
||||
isNewInputSystem = Keyboard.current != null;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
@@ -199,7 +202,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
|
||||
if (IsEnterPressed())
|
||||
{
|
||||
FindNearInteractable();
|
||||
SavePoseWithCandidate();
|
||||
@@ -326,6 +329,19 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
return updated;
|
||||
}
|
||||
|
||||
private bool IsEnterPressed()
|
||||
{
|
||||
if (isNewInputSystem)
|
||||
{
|
||||
return (Keyboard.current.enterKey?.wasPressedThisFrame ?? false) ||
|
||||
(Keyboard.current.numpadEnterKey?.wasPressedThisFrame ?? false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the nearest interactable object to the hand.
|
||||
/// </summary>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
@@ -183,8 +182,9 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
if (!isGrabbable || isGrabbed) { return 0; }
|
||||
Vector3 closestPoint = GetClosestPoint(grabberPos);
|
||||
float distacne = Vector3.Distance(grabberPos, closestPoint);
|
||||
return distacne > grabDistance ? 0 : 1 - (distacne / grabDistance);
|
||||
float distanceSqr = (grabberPos - closestPoint).sqrMagnitude;
|
||||
float grabDistSqr = grabDistance * grabDistance;
|
||||
return distanceSqr > grabDistSqr ? 0 : 1 - (distanceSqr / grabDistSqr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -263,35 +263,41 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
private Vector3 GetClosestPoint(Vector3 sourcePos)
|
||||
{
|
||||
Vector3 closestPoint = Vector3.zero;
|
||||
float shortDistance = float.MaxValue;
|
||||
float shortDistanceSqr = float.MaxValue;
|
||||
for (int i = 0; i < allColliders.Count; i++)
|
||||
{
|
||||
Collider collider = allColliders[i];
|
||||
Vector3 closePoint = collider.ClosestPointOnBounds(sourcePos);
|
||||
float distance = Vector3.Distance(sourcePos, closePoint);
|
||||
float distanceSqr = (sourcePos - closePoint).sqrMagnitude;
|
||||
if (distanceSqr < 0.001f)
|
||||
{
|
||||
return closePoint;
|
||||
}
|
||||
|
||||
if (collider.bounds.Contains(closePoint))
|
||||
{
|
||||
Vector3 direction = closePoint - sourcePos;
|
||||
direction.Normalize();
|
||||
int hitCount = Physics.RaycastNonAlloc(sourcePos, direction, hitResults, distance);
|
||||
int hitCount = Physics.RaycastNonAlloc(sourcePos, direction, hitResults, Mathf.Sqrt(distanceSqr));
|
||||
|
||||
for (int j = 0; j < hitCount; j++)
|
||||
{
|
||||
RaycastHit hit = hitResults[j];
|
||||
if (hit.collider == collider)
|
||||
{
|
||||
float hitDistance = Vector3.Distance(sourcePos, hit.point);
|
||||
if (distance > hitDistance)
|
||||
float hitDistanceSqr = (sourcePos - hit.point).sqrMagnitude;
|
||||
if (distanceSqr > hitDistanceSqr)
|
||||
{
|
||||
distance = hitDistance;
|
||||
distanceSqr = hitDistanceSqr;
|
||||
closePoint = hit.point;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shortDistance > distance)
|
||||
if (shortDistanceSqr > distanceSqr)
|
||||
{
|
||||
shortDistance = distance;
|
||||
shortDistanceSqr = distanceSqr;
|
||||
closestPoint = closePoint;
|
||||
}
|
||||
}
|
||||
@@ -361,9 +367,12 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// <param name="index">The index of the indicator to show.</param>
|
||||
private void ShowIndicatorByIndex(int index)
|
||||
{
|
||||
foreach (var grabPose in m_GrabPoses)
|
||||
for (int i = 0; i < m_GrabPoses.Count; i++)
|
||||
{
|
||||
grabPose.indicator.SetActive(false);
|
||||
if (index != i)
|
||||
{
|
||||
m_GrabPoses[i].indicator.SetActive(false);
|
||||
}
|
||||
}
|
||||
if (index >= 0 && index < m_GrabPoses.Count &&
|
||||
m_GrabPoses[index].indicator.enableIndicator)
|
||||
@@ -379,9 +388,9 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// <param name="isLeft">Whether the hand side is left.</param>
|
||||
private void ShowAllIndicator(bool isLeft)
|
||||
{
|
||||
foreach (var grabPose in m_GrabPoses)
|
||||
for (int i = 0; i < m_GrabPoses.Count; i++)
|
||||
{
|
||||
grabPose.indicator.SetActive(false);
|
||||
m_GrabPoses[i].indicator.SetActive(false);
|
||||
}
|
||||
foreach (var grabPose in m_GrabPoses)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
@@ -79,6 +78,13 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
private Pose wristPose = Pose.identity;
|
||||
private Vector3[] fingerTipPosition = new Vector3[(int)FingerId.Count];
|
||||
|
||||
private const int kMaxCacheSize = 100;
|
||||
private int lastBufferCount = 0;
|
||||
private Collider[] colliderBuffer = new Collider[50];
|
||||
private HandGrabInteractable[] grabbableBuffer = new HandGrabInteractable[50];
|
||||
private LinkedList<Collider> lruList = new LinkedList<Collider>();
|
||||
private Dictionary<Collider, LinkedListNode<Collider>> unusedColliders = new Dictionary<Collider, LinkedListNode<Collider>>();
|
||||
|
||||
#region MonoBehaviour
|
||||
private void Awake()
|
||||
{
|
||||
@@ -159,7 +165,6 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// </summary>
|
||||
private void FindCandidate()
|
||||
{
|
||||
currentCandidate = null;
|
||||
float distanceScore = float.MinValue;
|
||||
if (GetClosestGrabbable(m_GrabDistance, out HandGrabInteractable grabbable, out float score) && score > distanceScore)
|
||||
{
|
||||
@@ -189,28 +194,47 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
grabbable = null;
|
||||
maxScore = 0f;
|
||||
|
||||
Collider[] nearColliders = Physics.OverlapSphere(wristPose.position, 0.5f);
|
||||
List<HandGrabInteractable> nearHandGrabInteractables = new List<HandGrabInteractable>();
|
||||
for (int i = 0; i < nearColliders.Length; i++)
|
||||
for (int i = 0; i < lastBufferCount; i++)
|
||||
{
|
||||
HandGrabInteractable interactable = nearColliders[i].GetComponentInParent<HandGrabInteractable>();
|
||||
if (interactable && !nearHandGrabInteractables.Contains(interactable))
|
||||
{
|
||||
nearHandGrabInteractables.Add(interactable);
|
||||
continue;
|
||||
}
|
||||
interactable = nearColliders[i].GetComponentInChildren<HandGrabInteractable>();
|
||||
if (interactable && !nearHandGrabInteractables.Contains(interactable))
|
||||
{
|
||||
nearHandGrabInteractables.Add(interactable);
|
||||
continue;
|
||||
}
|
||||
HandGrabInteractable interactable = grabbableBuffer[i];
|
||||
interactable.ShowIndicator(false, this);
|
||||
}
|
||||
|
||||
for (int i = 0; i < nearHandGrabInteractables.Count; i++)
|
||||
int colliderCount = Physics.OverlapSphereNonAlloc(wristPose.position, grabDistance * 5, colliderBuffer);
|
||||
int interactableCount = 0;
|
||||
for (int i = 0; i < colliderCount; i++)
|
||||
{
|
||||
HandGrabInteractable interactable = nearHandGrabInteractables[i];
|
||||
interactable.ShowIndicator(false, this);
|
||||
Collider collider = colliderBuffer[i];
|
||||
if (unusedColliders.TryGetValue(collider, out _)) { continue; }
|
||||
|
||||
HandGrabInteractable interactable = collider.GetComponentInParent<HandGrabInteractable>()
|
||||
?? collider.GetComponentInChildren<HandGrabInteractable>();
|
||||
if (interactable != null)
|
||||
{
|
||||
bool isUnique = true;
|
||||
for (int j = 0; j < interactableCount; j++)
|
||||
{
|
||||
if (grabbableBuffer[j] == interactable)
|
||||
{
|
||||
isUnique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isUnique)
|
||||
{
|
||||
grabbableBuffer[interactableCount++] = interactable;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddUnusedColliders(collider);
|
||||
}
|
||||
}
|
||||
lastBufferCount = interactableCount;
|
||||
|
||||
for (int i = 0; i < interactableCount; i++)
|
||||
{
|
||||
HandGrabInteractable interactable = grabbableBuffer[i];
|
||||
for (int j = 0; j < fingerTipPosition.Length; j++)
|
||||
{
|
||||
float distanceScore = interactable.CalculateDistanceScore(fingerTipPosition[j], grabDistance);
|
||||
@@ -279,5 +303,18 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
m_Grabbable.UpdatePositionAndRotation(wristPose);
|
||||
}
|
||||
|
||||
private void AddUnusedColliders(Collider collider)
|
||||
{
|
||||
if (lruList.Count >= kMaxCacheSize)
|
||||
{
|
||||
var oldest = lruList.First;
|
||||
unusedColliders.Remove(oldest.Value);
|
||||
lruList.RemoveFirst();
|
||||
}
|
||||
|
||||
var node = lruList.AddLast(collider);
|
||||
unusedColliders[collider] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
@@ -85,7 +84,11 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
private Quaternion lastRotation;
|
||||
private bool isInit = false;
|
||||
private bool isTracked = true;
|
||||
private List<Vector3> collisionDirections = new List<Vector3>();
|
||||
private const int k_MaxCollisionCount = 100;
|
||||
private readonly ContactPoint[] contactPointsBuffer = new ContactPoint[k_MaxCollisionCount];
|
||||
private readonly Vector3[] collisionsDirection = new Vector3[k_MaxCollisionCount];
|
||||
private readonly object collisionLock = new object();
|
||||
private int currentCollisionCount = 0;
|
||||
private bool isGrabbing = false;
|
||||
|
||||
#region MonoBehaviour
|
||||
@@ -163,7 +166,11 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
|
||||
if (isGrabbing)
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rootJointRigidbody.linearVelocity = Vector3.zero;
|
||||
#else
|
||||
rootJointRigidbody.velocity = Vector3.zero;
|
||||
#endif
|
||||
rootJointRigidbody.angularVelocity = Vector3.zero;
|
||||
rootJoint.localPosition = lastRootPos;
|
||||
rootJoint.localRotation = lastRotation;
|
||||
@@ -232,12 +239,16 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
Vector3 vel = (lastRootPos - rootJoint.position) / Time.deltaTime;
|
||||
if (IsValidVelocity(vel))
|
||||
{
|
||||
if (collisionDirections.Count > 0)
|
||||
lock (collisionLock)
|
||||
{
|
||||
if (currentCollisionCount > 0)
|
||||
{
|
||||
float minAngle = float.MaxValue;
|
||||
Vector3 closestDirection = Vector3.zero;
|
||||
foreach (Vector3 direction in collisionDirections.ToList())
|
||||
|
||||
for (int i = 0; i < currentCollisionCount; i++)
|
||||
{
|
||||
Vector3 direction = collisionsDirection[i];
|
||||
float angle = Mathf.Abs(Vector3.Angle(direction, vel));
|
||||
if (angle < minAngle)
|
||||
{
|
||||
@@ -245,8 +256,6 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
closestDirection = direction;
|
||||
}
|
||||
}
|
||||
collisionDirections.Clear();
|
||||
|
||||
Vector3 adjustedDirection = closestDirection;
|
||||
if (Vector3.Dot(vel, closestDirection) > 0)
|
||||
{
|
||||
@@ -257,8 +266,14 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
vel.Normalize();
|
||||
}
|
||||
currentCollisionCount = 0;
|
||||
}
|
||||
}
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rootJointRigidbody.linearVelocity = vel;
|
||||
#else
|
||||
rootJointRigidbody.velocity = vel;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +314,11 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
lastRootPos = Vector3.zero;
|
||||
lastRotation = Quaternion.identity;
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rootJointRigidbody.linearVelocity = Vector3.zero;
|
||||
#else
|
||||
rootJointRigidbody.velocity = Vector3.zero;
|
||||
#endif
|
||||
rootJointRigidbody.angularVelocity = Vector3.zero;
|
||||
}
|
||||
foreach (JointCollider jointCollider in jointsCollider)
|
||||
@@ -355,11 +374,15 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
case JointCollider.CollisionState.Stay:
|
||||
if (collision.contactCount > 0 && (collision.rigidbody == null || collision.rigidbody.isKinematic))
|
||||
{
|
||||
ContactPoint[] contactPoints = new ContactPoint[collision.contactCount];
|
||||
collision.GetContacts(contactPoints);
|
||||
foreach (ContactPoint contactPoint in contactPoints)
|
||||
lock (collisionLock)
|
||||
{
|
||||
collisionDirections.Add(contactPoint.normal * -1f);
|
||||
currentCollisionCount = Mathf.Min(contactPointsBuffer.Length, collision.contactCount);
|
||||
collision.GetContacts(contactPointsBuffer);
|
||||
|
||||
for (int i = 0; i < currentCollisionCount; i++)
|
||||
{
|
||||
collisionsDirection[i] = contactPointsBuffer[i].normal * -1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -635,6 +635,8 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
},
|
||||
};
|
||||
// palm, wrist, thumb, index, middle, ring, pinky
|
||||
private static readonly int[] fingerGroup = { 1, 1, 4, 5, 5, 5, 5 };
|
||||
|
||||
public bool valid = false;
|
||||
public bool isTracked = false;
|
||||
@@ -771,14 +773,16 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
group = 0;
|
||||
index = jointId;
|
||||
|
||||
// palm, wrist, thumb, index, middle, ring, pinky
|
||||
int[] fingerGroup = { 1, 1, 4, 5, 5, 5, 5 };
|
||||
while (index > fingerGroup[group])
|
||||
for (int i = 0; i < fingerGroup.Length; i++)
|
||||
{
|
||||
index -= fingerGroup[group];
|
||||
group += 1;
|
||||
if (index <= fingerGroup[i])
|
||||
{
|
||||
group = i;
|
||||
index -= 1; // Adjust to 0-based index
|
||||
return;
|
||||
}
|
||||
index -= fingerGroup[i];
|
||||
}
|
||||
index -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -848,32 +852,29 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// <param name="isLeft">True if the hand is left; otherwise, false.</param>
|
||||
private static void GetFingerData(FingerId id, ref FingerData finger, bool isLeft)
|
||||
{
|
||||
JointType[] jointTypes = { };
|
||||
switch (id)
|
||||
{
|
||||
case FingerId.Thumb: jointTypes = s_ThumbJoints; break;
|
||||
case FingerId.Index: jointTypes = s_IndexJoints; break;
|
||||
case FingerId.Middle: jointTypes = s_MiddleJoints; break;
|
||||
case FingerId.Ring: jointTypes = s_RingJoints; break;
|
||||
case FingerId.Pinky: jointTypes = s_PinkyJoints; break;
|
||||
default: return;
|
||||
}
|
||||
JointType[] jointTypes = GetJointTypes(id);
|
||||
if (jointTypes == null) return;
|
||||
|
||||
float deltaTime = Time.deltaTime;
|
||||
Vector3 parentVel = Vector3.zero;
|
||||
|
||||
for (int i = 0; i < jointTypes.Length; i++)
|
||||
{
|
||||
Vector3 parentVel = i == 0 ? Vector3.zero : finger.joints[i - 1].velocity;
|
||||
JointData lastJoint = finger.joints[i];
|
||||
GetJointData(jointTypes[i], ref finger.joints[i], isLeft);
|
||||
ref JointData joint = ref finger.joints[i];
|
||||
Vector3 lastPosition = joint.position;
|
||||
|
||||
DataWrapper.GetJointPose(jointTypes[i], ref joint.position, ref joint.rotation, isLeft);
|
||||
joint.velocity = (joint.position - lastPosition) / deltaTime;
|
||||
|
||||
//As the velocity of child node should not be lower than the parent node.
|
||||
//Add the current parent node's velocity multiplied by time to the last position of child node, obtaining the new simulated position.
|
||||
if (parentVel.magnitude > finger.joints[i].velocity.magnitude)
|
||||
if (parentVel.magnitude > joint.velocity.magnitude)
|
||||
{
|
||||
lastJoint.position += parentVel * Time.deltaTime;
|
||||
finger.joints[i] = lastJoint;
|
||||
joint.position += parentVel * deltaTime;
|
||||
}
|
||||
parentVel = joint.velocity;
|
||||
}
|
||||
|
||||
// Since the thumb does not have joint3, it is replaced by joint2.
|
||||
if (id == FingerId.Thumb)
|
||||
{
|
||||
finger.joints[(int)JointId.Tip] = finger.joint3;
|
||||
@@ -885,6 +886,19 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
}
|
||||
|
||||
private static JointType[] GetJointTypes(FingerId id)
|
||||
{
|
||||
return id switch
|
||||
{
|
||||
FingerId.Thumb => s_ThumbJoints,
|
||||
FingerId.Index => s_IndexJoints,
|
||||
FingerId.Middle => s_MiddleJoints,
|
||||
FingerId.Ring => s_RingJoints,
|
||||
FingerId.Pinky => s_PinkyJoints,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the data for the left or right hand.
|
||||
/// </summary>
|
||||
@@ -1067,16 +1081,16 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
Vector3 thumbTip = thumbData.tip.position;
|
||||
Vector3 thumbJoint2 = thumbData.joint2.position;
|
||||
Vector3 thumbJoint1 = thumbData.joint1.position;
|
||||
Vector3[] fingerPos = { fingerData.tip.position,
|
||||
fingerData.joint3.position,
|
||||
fingerData.joint2.position};
|
||||
|
||||
float distance = float.PositiveInfinity;
|
||||
for (int i = 0; i < fingerPos.Length; i++)
|
||||
{
|
||||
distance = Mathf.Min(distance, CalculateShortestDistance(fingerPos[i], thumbTip, thumbJoint2));
|
||||
distance = Mathf.Min(distance, CalculateShortestDistance(fingerPos[i], thumbJoint2, thumbJoint1));
|
||||
}
|
||||
distance = Mathf.Min(distance, CalculateShortestDistance(fingerData.tip.position, thumbTip, thumbJoint2));
|
||||
distance = Mathf.Min(distance, CalculateShortestDistance(fingerData.tip.position, thumbJoint2, thumbJoint1));
|
||||
|
||||
distance = Mathf.Min(distance, CalculateShortestDistance(fingerData.joint3.position, thumbTip, thumbJoint2));
|
||||
distance = Mathf.Min(distance, CalculateShortestDistance(fingerData.joint3.position, thumbJoint2, thumbJoint1));
|
||||
|
||||
distance = Mathf.Min(distance, CalculateShortestDistance(fingerData.joint2.position, thumbTip, thumbJoint2));
|
||||
distance = Mathf.Min(distance, CalculateShortestDistance(fingerData.joint2.position, thumbJoint2, thumbJoint1));
|
||||
return distance;
|
||||
}
|
||||
|
||||
@@ -1732,9 +1746,16 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// <param name="enable">True to enable the indicator, false to deactivate it.</param>
|
||||
public void SetActive(bool enable)
|
||||
{
|
||||
if (target != null)
|
||||
if (target)
|
||||
{
|
||||
target.SetActive(enable);
|
||||
if (enable)
|
||||
{
|
||||
target.transform.localScale = Vector3.one;
|
||||
}
|
||||
else
|
||||
{
|
||||
target.transform.localScale = Vector3.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
if (keepUpdate)
|
||||
{
|
||||
keepUpdate = false;
|
||||
StopCoroutine(UpdatePose());
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHandMeshRenderer(HandMeshManager handMeshRenderer)
|
||||
@@ -44,21 +40,15 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
yield return new WaitUntil(() => m_Initialized);
|
||||
base.OnEnable();
|
||||
if (!keepUpdate)
|
||||
{
|
||||
keepUpdate = true;
|
||||
StartCoroutine(UpdatePose());
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator UpdatePose()
|
||||
private void Update()
|
||||
{
|
||||
while (keepUpdate)
|
||||
{
|
||||
yield return new WaitForFixedUpdate();
|
||||
|
||||
if (!keepUpdate) { return; }
|
||||
HandPose handPose = HandPoseProvider.GetHandPose(m_HandMesh.isLeft ? HandPoseType.HAND_LEFT : HandPoseType.HAND_RIGHT);
|
||||
m_IsTracked = handPose.IsTracked();
|
||||
if (!m_IsTracked) { return; }
|
||||
|
||||
for (int i = 0; i < poseCount; i++)
|
||||
{
|
||||
@@ -81,4 +71,3 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
if (keepUpdate)
|
||||
{
|
||||
keepUpdate = false;
|
||||
StopCoroutine(UpdatePose());
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetType(HandPoseType poseType)
|
||||
@@ -43,25 +39,18 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
yield return new WaitUntil(() => m_Initialized);
|
||||
base.OnEnable();
|
||||
if (!keepUpdate)
|
||||
{
|
||||
keepUpdate = true;
|
||||
StartCoroutine(UpdatePose());
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator UpdatePose()
|
||||
private void Update()
|
||||
{
|
||||
Vector3 position = Vector3.zero;
|
||||
Quaternion rotation = Quaternion.identity;
|
||||
while (keepUpdate)
|
||||
{
|
||||
yield return new WaitForEndOfFrame();
|
||||
|
||||
if (!keepUpdate) { return; }
|
||||
HandData handData = CachedHand.Get(isLeft);
|
||||
m_IsTracked = handData.isTracked;
|
||||
if (!m_IsTracked) { continue; }
|
||||
if (!m_IsTracked) { return; }
|
||||
|
||||
Vector3 position = Vector3.zero;
|
||||
Quaternion rotation = Quaternion.identity;
|
||||
for (int i = 0; i < poseCount; i++)
|
||||
{
|
||||
if (handData.GetJointPosition((JointType)i, ref position) && handData.GetJointRotation((JointType)i, ref rotation))
|
||||
@@ -82,4 +71,3 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
@@ -9,13 +10,15 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
[SerializeField]
|
||||
private float forceMultiplier = 1.0f;
|
||||
|
||||
private readonly int MIN_POSE_SAMPLES = 2;
|
||||
private readonly int MAX_POSE_SAMPLES = 10;
|
||||
private const int MIN_POSE_SAMPLES = 2;
|
||||
private const int MAX_POSE_SAMPLES = 10;
|
||||
private readonly float MIN_VELOCITY = 0.5f;
|
||||
|
||||
private Rigidbody interactableRigidbody;
|
||||
private List<Pose> movementPoses = new List<Pose>();
|
||||
private List<float> timestamps = new List<float>();
|
||||
private Pose[] movementPoses = new Pose[MAX_POSE_SAMPLES];
|
||||
private float[] timestamps = new float[MAX_POSE_SAMPLES];
|
||||
private int currentPoseIndex = 0;
|
||||
private int poseCount = 0;
|
||||
private bool isBegin = false;
|
||||
private bool isEnd = false;
|
||||
private object lockVel = new object();
|
||||
@@ -36,7 +39,11 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
|
||||
if (isEnd)
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
interactableRigidbody.linearVelocity = Vector3.zero;
|
||||
#else
|
||||
interactableRigidbody.velocity = Vector3.zero;
|
||||
#endif
|
||||
interactableRigidbody.angularVelocity = Vector3.zero;
|
||||
|
||||
Vector3 velocity = CalculateVelocity();
|
||||
@@ -46,8 +53,10 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
interactableRigidbody = null;
|
||||
|
||||
movementPoses.Clear();
|
||||
timestamps.Clear();
|
||||
Array.Clear(movementPoses, 0, MAX_POSE_SAMPLES);
|
||||
Array.Clear(timestamps, 0, MAX_POSE_SAMPLES);
|
||||
currentPoseIndex = 0;
|
||||
poseCount = 0;
|
||||
isEnd = false;
|
||||
}
|
||||
}
|
||||
@@ -55,28 +64,29 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
private void RecordMovement()
|
||||
{
|
||||
float time = Time.time;
|
||||
if (movementPoses.Count == 0 ||
|
||||
timestamps[movementPoses.Count - 1] != time)
|
||||
{
|
||||
movementPoses.Add(new Pose(interactableRigidbody.position, interactableRigidbody.rotation));
|
||||
timestamps.Add(time);
|
||||
}
|
||||
|
||||
if (movementPoses.Count > MAX_POSE_SAMPLES)
|
||||
int lastIndex = (currentPoseIndex + poseCount - 1) % MAX_POSE_SAMPLES;
|
||||
if (poseCount == 0 || timestamps[lastIndex] != time)
|
||||
{
|
||||
movementPoses.RemoveAt(0);
|
||||
timestamps.RemoveAt(0);
|
||||
movementPoses[currentPoseIndex] = new Pose(interactableRigidbody.position, interactableRigidbody.rotation);
|
||||
timestamps[currentPoseIndex] = time;
|
||||
|
||||
if (poseCount < MAX_POSE_SAMPLES)
|
||||
{
|
||||
poseCount++;
|
||||
}
|
||||
currentPoseIndex = (currentPoseIndex + 1) % MAX_POSE_SAMPLES;
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 CalculateVelocity()
|
||||
{
|
||||
if (movementPoses.Count >= MIN_POSE_SAMPLES)
|
||||
if (poseCount >= MIN_POSE_SAMPLES)
|
||||
{
|
||||
List<Vector3> velocities = new List<Vector3>();
|
||||
for (int i = 0; i < movementPoses.Count - 1; i++)
|
||||
for (int i = 0; i < poseCount - 1; i++)
|
||||
{
|
||||
for (int j = i + 1; j < movementPoses.Count; j++)
|
||||
for (int j = i + 1; j < poseCount; j++)
|
||||
{
|
||||
velocities.Add(GetVelocity(i, j));
|
||||
}
|
||||
@@ -89,9 +99,9 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
|
||||
private Vector3 GetVelocity(int idx1, int idx2)
|
||||
{
|
||||
if (idx1 < 0 || idx1 >= movementPoses.Count
|
||||
|| idx2 < 0 || idx2 >= movementPoses.Count
|
||||
|| movementPoses.Count < MIN_POSE_SAMPLES)
|
||||
if (idx1 < 0 || idx1 >= poseCount
|
||||
|| idx2 < 0 || idx2 >= poseCount
|
||||
|| poseCount < MIN_POSE_SAMPLES)
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"WindowsStandalone64"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
@@ -24,6 +24,11 @@
|
||||
"expression": "1.3.0",
|
||||
"define": "UNITY_XR_HANDS"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.xr.hands",
|
||||
"expression": "1.5.0",
|
||||
"define": "UNITY_XR_HANDS_1_5_0"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.xr.interaction.toolkit",
|
||||
"expression": "0.9.4-preview",
|
||||
|
||||
@@ -56,8 +56,8 @@ namespace VIVE.OpenXR
|
||||
return m_sb;
|
||||
}
|
||||
}
|
||||
void DEBUG(StringBuilder msg) { Debug.LogFormat("{0} {1}", LOG_TAG, msg); }
|
||||
void ERROR(StringBuilder msg) { Debug.LogErrorFormat("{0} {1}", LOG_TAG, msg); }
|
||||
void DEBUG(StringBuilder msg) { Debug.Log(LOG_TAG + msg); }
|
||||
void ERROR(StringBuilder msg) { Debug.LogError(LOG_TAG + msg); }
|
||||
#endregion
|
||||
|
||||
private static VIVEFocus3Profile m_Instance = null;
|
||||
@@ -88,11 +88,13 @@ namespace VIVE.OpenXR
|
||||
return m_sb;
|
||||
}
|
||||
}
|
||||
void DEBUG(StringBuilder msg) { Debug.LogFormat("{0} {1}", LOG_TAG, msg); }
|
||||
void ERROR(StringBuilder msg) { Debug.LogErrorFormat("{0} {1}", LOG_TAG, msg); }
|
||||
void DEBUG(StringBuilder msg) { Debug.Log(LOG_TAG + msg); }
|
||||
void ERROR(StringBuilder msg) { Debug.LogError(LOG_TAG + msg); }
|
||||
#endregion
|
||||
|
||||
#region Action Path
|
||||
|
||||
#region Button
|
||||
/// <summary>
|
||||
/// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents the <see cref="VIVEFocus3Profile.thumbstick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
@@ -145,7 +147,7 @@ namespace VIVE.OpenXR
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="triggerClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "indexButton", "triggerButton" }, usage = "TriggerButton")]
|
||||
public ButtonControl triggerPressed { get; private set; }
|
||||
public ButtonControl triggerPressed { get; private set; } // InputControl(offset = 20)
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="triggerTouch"/> OpenXR binding.
|
||||
@@ -157,7 +159,7 @@ namespace VIVE.OpenXR
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="thumbstickClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "JoystickOrPadPressed", "thumbstickClick", "joystickClicked", "primary2DAxisClick" }, usage = "Primary2DAxisClick")]
|
||||
public ButtonControl thumbstickClicked { get; private set; }
|
||||
public ButtonControl thumbstickClicked { get; private set; } // InputControl(offset = 22)
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="thumbstickTouch"/> OpenXR binding.
|
||||
@@ -169,31 +171,31 @@ namespace VIVE.OpenXR
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="thumbrest"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "ParkingTouched", "parkingTouched" })]
|
||||
public ButtonControl thumbrestTouched { get; private set; }
|
||||
public ButtonControl thumbrestTouched { get; private set; } // InputControl(offset = 24)
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="gripPose"/> OpenXR binding. The grip pose represents the location of the user's palm or holding a motion controller.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="VIVEFocus3Profile.aim"/> OpenXR binding. The pointer pose represents the tip of the controller pointing forward.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "aimPose", "pointerPose" }, usage = "Pointer")]
|
||||
public PoseControl pointer { get; private set; }
|
||||
#if UNITY_ANDROID
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing the <see cref="VIVEFocus3Profile.pokePose"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "indexTip", usage = "Poke")]
|
||||
public PoseControl pokePose { get; private set; }
|
||||
|
||||
#if UNITY_ANDROID
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing the <see cref="VIVEFocus3Profile.pinchPose"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, usage = "Pinch")]
|
||||
public PoseControl pinchPose { get; private set; }
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing the <see cref="VIVEFocus3Profile.pokePose"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "indexTip", usage = "Poke")]
|
||||
public PoseControl pokePose { get; private set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
@@ -227,28 +229,29 @@ namespace VIVE.OpenXR
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 104, noisy = true, alias = "pointerOrientation")]
|
||||
public QuaternionControl pointerRotation { get; private set; }
|
||||
#if UNITY_ANDROID
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the poke position. This value is equivalent to mapping pokePose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 152, noisy = true)]
|
||||
public Vector3Control pokePosition { get; private set; }
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the poke orientation. This value is equivalent to mapping pokePose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 164, noisy = true)]
|
||||
public QuaternionControl pokeRotation { get; private set; }
|
||||
|
||||
#if UNITY_ANDROID
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the pinch position. This value is equivalent to mapping pinchPose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 212, noisy = true)]
|
||||
[Preserve, InputControl(offset = 152, noisy = true)]
|
||||
public Vector3Control pinchPosition { get; private set; }
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the pinch orientation. This value is equivalent to mapping pinchPose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 224, noisy = true)]
|
||||
[Preserve, InputControl(offset = 164, noisy = true)]
|
||||
public QuaternionControl pinchRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the poke position. This value is equivalent to mapping pokePose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 212, noisy = true)]
|
||||
public Vector3Control pokePosition { get; private set; }
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the poke orientation. This value is equivalent to mapping pokePose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 224, noisy = true)]
|
||||
public QuaternionControl pokeRotation { get; private set; }
|
||||
#endif
|
||||
/// <summary>
|
||||
/// A <see cref="HapticControl"/> that represents the <see cref="VIVEFocus3Profile.haptic"/> binding.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
using System.Text;
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
@@ -43,12 +43,6 @@ namespace VIVE.OpenXR
|
||||
private float m_CameraHeight = 1.5f;
|
||||
public float CameraHeight { get { return m_CameraHeight; } set { m_CameraHeight = value; } }
|
||||
|
||||
[System.Obsolete("This variable is deprecated. Please use CameraHeight instead.")]
|
||||
[SerializeField]
|
||||
private float m_CameraYOffset = 1;
|
||||
[System.Obsolete("This variable is deprecated. Please use CameraHeight instead.")]
|
||||
public float CameraYOffset { get { return m_CameraYOffset; } set { m_CameraYOffset = value; } }
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
[SerializeField]
|
||||
private InputActionAsset m_ActionAsset;
|
||||
@@ -56,10 +50,14 @@ namespace VIVE.OpenXR
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
static List<XRInputSubsystem> s_InputSubsystems = new List<XRInputSubsystem>();
|
||||
private static readonly List<XRInputSubsystem> s_InputSubsystems = new List<XRInputSubsystem>();
|
||||
private static readonly object lockObj = new object();
|
||||
private float m_LastRecenteredTime = 0.0f;
|
||||
|
||||
#region MonoBehaviour
|
||||
private void OnEnable()
|
||||
{
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
UpdateInputSubsystems();
|
||||
for (int i = 0; i < s_InputSubsystems.Count; i++)
|
||||
{
|
||||
s_InputSubsystems[i].trackingOriginUpdated += TrackingOriginUpdated;
|
||||
@@ -74,29 +72,12 @@ namespace VIVE.OpenXR
|
||||
}
|
||||
private void OnDisable()
|
||||
{
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
UpdateInputSubsystems();
|
||||
for (int i = 0; i < s_InputSubsystems.Count; i++)
|
||||
{
|
||||
s_InputSubsystems[i].trackingOriginUpdated -= TrackingOriginUpdated;
|
||||
}
|
||||
}
|
||||
|
||||
float m_LastRecenteredTime = 0.0f;
|
||||
private void TrackingOriginUpdated(XRInputSubsystem obj)
|
||||
{
|
||||
m_LastRecenteredTime = Time.time;
|
||||
sb.Clear().Append("TrackingOriginUpdated() m_LastRecenteredTime: ").Append(m_LastRecenteredTime); DEBUG(sb);
|
||||
}
|
||||
|
||||
XRInputSubsystem m_InputSystem = null;
|
||||
void UpdateInputSystem()
|
||||
{
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
if (s_InputSubsystems.Count > 0)
|
||||
{
|
||||
m_InputSystem = s_InputSubsystems[0];
|
||||
}
|
||||
}
|
||||
private void Awake()
|
||||
{
|
||||
if (m_Instance == null)
|
||||
@@ -107,38 +88,18 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
Destroy(this);
|
||||
}
|
||||
|
||||
UpdateInputSystem();
|
||||
if (m_InputSystem != null)
|
||||
{
|
||||
sb.Clear().Append("Awake() TrySetTrackingOriginMode ").Append(m_TrackingOrigin); DEBUG(sb);
|
||||
m_InputSystem.TrySetTrackingOriginMode(m_TrackingOrigin);
|
||||
|
||||
TrackingOriginModeFlags mode = m_InputSystem.GetTrackingOriginMode();
|
||||
sb.Clear().Append("Awake() Tracking mode is set to ").Append(mode); DEBUG(sb);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Clear().Append("Awake() no XRInputSubsystem."); DEBUG(sb);
|
||||
}
|
||||
m_TrackingOriginEx = m_TrackingOrigin;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
UpdateInputSystem();
|
||||
if (m_InputSystem != null)
|
||||
TrackingOriginModeFlags mode = GetTrackingOriginMode();
|
||||
if ((mode != m_TrackingOrigin || m_TrackingOriginEx != m_TrackingOrigin) &&
|
||||
m_TrackingOrigin != TrackingOriginModeFlags.Unknown &&
|
||||
SetTrackingOriginMode(m_TrackingOrigin))
|
||||
{
|
||||
TrackingOriginModeFlags mode = m_InputSystem.GetTrackingOriginMode();
|
||||
if ((mode != m_TrackingOrigin || m_TrackingOriginEx != m_TrackingOrigin) && m_TrackingOrigin != TrackingOriginModeFlags.Unknown)
|
||||
{
|
||||
m_InputSystem.TrySetTrackingOriginMode(m_TrackingOrigin);
|
||||
|
||||
mode = m_InputSystem.GetTrackingOriginMode();
|
||||
mode = GetTrackingOriginMode();
|
||||
sb.Clear().Append("Update() Tracking mode is set to " + mode);
|
||||
m_TrackingOriginEx = m_TrackingOrigin;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_CameraOffset != null && m_TrackingOrigin == TrackingOriginModeFlags.Device)
|
||||
{
|
||||
@@ -149,5 +110,66 @@ namespace VIVE.OpenXR
|
||||
m_CameraOffset.transform.localPosition = cameraPosOffset;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private bool SetTrackingOriginMode(TrackingOriginModeFlags value)
|
||||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
UpdateInputSubsystems();
|
||||
|
||||
for (int i = 0; i < s_InputSubsystems.Count; i++)
|
||||
{
|
||||
var subsys = s_InputSubsystems[i];
|
||||
if (!subsys.running)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (subsys.TrySetTrackingOriginMode(value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Debug.LogWarning($"Failed to set TrackingOriginModeFlags({value}) to XRInputSubsystem: {subsys.subsystemDescriptor?.id ?? "Unknown"}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private TrackingOriginModeFlags GetTrackingOriginMode()
|
||||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
UpdateInputSubsystems();
|
||||
|
||||
for(int i=0; i< s_InputSubsystems.Count; i++)
|
||||
{
|
||||
var subsys = s_InputSubsystems[i];
|
||||
if (!subsys.running)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return subsys.GetTrackingOriginMode();
|
||||
}
|
||||
return TrackingOriginModeFlags.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateInputSubsystems()
|
||||
{
|
||||
s_InputSubsystems.Clear();
|
||||
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
SubsystemManager.GetSubsystems(s_InputSubsystems);
|
||||
#else
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void TrackingOriginUpdated(XRInputSubsystem obj)
|
||||
{
|
||||
m_LastRecenteredTime = Time.time;
|
||||
sb.Clear().Append("TrackingOriginUpdated() m_LastRecenteredTime: ").Append(m_LastRecenteredTime); DEBUG(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace VIVE.OpenXR.Samples.Anchor
|
||||
void GetXRInputSubsystem()
|
||||
{
|
||||
List<XRInputSubsystem> xrSubsystemList = new List<XRInputSubsystem>();
|
||||
SubsystemManager.GetInstances(xrSubsystemList);
|
||||
SubsystemManager.GetSubsystems(xrSubsystemList);
|
||||
foreach (var xrSubsystem in xrSubsystemList)
|
||||
{
|
||||
if (xrSubsystem.running)
|
||||
@@ -675,6 +675,12 @@ namespace VIVE.OpenXR.Samples.Anchor
|
||||
if (task.IsCompleted)
|
||||
{
|
||||
Task<(XrResult, string, byte[])> t = task as Task<(XrResult, string, byte[])>;
|
||||
if (t == null)
|
||||
{
|
||||
tasks.Remove(task);
|
||||
break;
|
||||
}
|
||||
|
||||
if (t.Result.Item1 == XrResult.XR_SUCCESS)
|
||||
{
|
||||
// write to file
|
||||
|
||||
@@ -349,9 +349,9 @@
|
||||
},
|
||||
{
|
||||
"name": "IsTracked",
|
||||
"type": "Value",
|
||||
"type": "Button",
|
||||
"id": "384094ab-6290-4de1-9b73-6dd7fae94298",
|
||||
"expectedControlType": "Analog",
|
||||
"expectedControlType": "Button",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": true
|
||||
@@ -1230,9 +1230,9 @@
|
||||
},
|
||||
{
|
||||
"name": "IsTracked",
|
||||
"type": "Value",
|
||||
"type": "Button",
|
||||
"id": "d1478f77-9424-45e1-bbe0-949fcfaec599",
|
||||
"expectedControlType": "Analog",
|
||||
"expectedControlType": "Button",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": true
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa549247e9994a84697e73e6d1288e2b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.XR;
|
||||
using VIVE.OpenXR;
|
||||
|
||||
[RequireComponent(typeof(Text))]
|
||||
public class DebugIsTrackedOffset : MonoBehaviour
|
||||
{
|
||||
public InputActionReference isTracked1 = null;
|
||||
public InputActionReference isTracked2 = null;
|
||||
public InputActionReference isTracked3 = null;
|
||||
public InputActionReference isTracked4 = null;
|
||||
|
||||
private Text m_Text = null;
|
||||
private void Start()
|
||||
{
|
||||
m_Text = GetComponent<Text>();
|
||||
}
|
||||
void Update()
|
||||
{
|
||||
if (m_Text == null) { return; }
|
||||
|
||||
m_Text.text = "";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked1, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += isTracked1.action.name + ": " + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\n";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked2, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += isTracked2.action.name + ": " + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\n";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked3, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += isTracked3.action.name + ": " + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\n";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked4, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += isTracked4.action.name + ": " + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c5ffdf8ced75cf41a74cb761a3987dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.XR;
|
||||
using VIVE.OpenXR;
|
||||
|
||||
[RequireComponent(typeof(Text))]
|
||||
public class DebugPoseData : MonoBehaviour
|
||||
{
|
||||
public string PoseName = "";
|
||||
public InputActionReference isTracked = null;
|
||||
public InputActionReference trackingState = null;
|
||||
public InputActionReference position = null;
|
||||
public InputActionReference rotation = null;
|
||||
public InputActionReference pose = null;
|
||||
|
||||
private Text m_Text = null;
|
||||
private void Start()
|
||||
{
|
||||
m_Text = GetComponent<Text>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (m_Text == null) { return; }
|
||||
|
||||
m_Text.text = PoseName + " ----";
|
||||
|
||||
if (isTracked != null)
|
||||
{
|
||||
m_Text.text += "\nisTracked: ";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trackingState != null)
|
||||
{
|
||||
m_Text.text += "\ntrackingState: ";
|
||||
{
|
||||
if (OpenXRHelper.GetInteger(trackingState, out InputTrackingState value, out string msg))
|
||||
{
|
||||
m_Text.text += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (position != null)
|
||||
{
|
||||
m_Text.text += "\nposition: ";
|
||||
{
|
||||
if (OpenXRHelper.GetVector3(position, out Vector3 value, out string msg))
|
||||
{
|
||||
m_Text.text += "(" + value.x.ToString("N3") + ", " + value.y.ToString("N3") + ", " + value.z.ToString("N3") + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rotation != null)
|
||||
{
|
||||
m_Text.text += "\nrotation: ";
|
||||
{
|
||||
if (OpenXRHelper.GetQuaternion(rotation, out Quaternion value, out string msg))
|
||||
{
|
||||
m_Text.text += "(" + value.x.ToString("N3") + ", " + value.y.ToString("N3") + ", " + value.z.ToString("N3") + ", " + value.w.ToString("N3") + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pose != null)
|
||||
{
|
||||
m_Text.text += "\npose.isTracked: ";
|
||||
{
|
||||
if (OpenXRHelper.GetPoseIsTracked(pose, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\npose.trackingState: ";
|
||||
{
|
||||
if (OpenXRHelper.GetPoseTrackingState(pose, out InputTrackingState value, out string msg))
|
||||
{
|
||||
m_Text.text += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\npose.position: ";
|
||||
{
|
||||
if (OpenXRHelper.GetPosePosition(pose, out Vector3 value, out string msg))
|
||||
{
|
||||
m_Text.text += "(" + value.x.ToString("N3") + ", " + value.y.ToString("N3") + ", " + value.z.ToString("N3") + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\npose.rotation: ";
|
||||
{
|
||||
if (OpenXRHelper.GetPoseRotation(pose, out Quaternion value, out string msg))
|
||||
{
|
||||
m_Text.text += "(" + value.x.ToString("N3") + ", " + value.y.ToString("N3") + ", " + value.z.ToString("N3") + ", " + value.w.ToString("N3") + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04725f4c022874d40a6e786b002b782a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -111,7 +111,14 @@ namespace VIVE.OpenXR.Samples
|
||||
rotationTracked = ((uint)trackingState & (uint)InputTrackingState.Rotation) != 0;
|
||||
|
||||
bool tracked = isActive /*&& positionTracked */&& rotationTracked; // Show the object with 3DoF.
|
||||
// Temporary workaround for PC platform: The isTracked value for HandInteractionEXT always returns false.
|
||||
// For now, forcing it to true using a macro. This will be properly fixed in the next patch.
|
||||
#if UNITY_STANDALONE
|
||||
if (IsActive.action.ToString() == "Hand/isTrackedR" || IsActive.action.ToString() == "Hand/isTrackedL")
|
||||
m_ObjectToHide.SetActive(true);
|
||||
#else
|
||||
m_ObjectToHide.SetActive(tracked);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,439 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 9
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 0
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 12
|
||||
m_GIWorkflowMode: 1
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 2
|
||||
m_BakeResolution: 40
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 1
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherFiltering: 1
|
||||
m_FinalGatherRayCount: 256
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 2
|
||||
m_BakeBackend: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 256
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 1
|
||||
m_PVRDenoiserTypeDirect: 1
|
||||
m_PVRDenoiserTypeIndirect: 1
|
||||
m_PVRDenoiserTypeAO: 1
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 0}
|
||||
m_LightingSettings: {fileID: 0}
|
||||
--- !u!196 &4
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 2
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
accuratePlacement: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &165655209
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 165655211}
|
||||
- component: {fileID: 165655210}
|
||||
m_Layer: 0
|
||||
m_Name: Directional Light
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!108 &165655210
|
||||
Light:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 165655209}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 10
|
||||
m_Type: 1
|
||||
m_Shape: 0
|
||||
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
|
||||
m_Intensity: 1
|
||||
m_Range: 10
|
||||
m_SpotAngle: 30
|
||||
m_InnerSpotAngle: 21.80208
|
||||
m_CookieSize: 10
|
||||
m_Shadows:
|
||||
m_Type: 2
|
||||
m_Resolution: -1
|
||||
m_CustomResolution: -1
|
||||
m_Strength: 1
|
||||
m_Bias: 0.05
|
||||
m_NormalBias: 0.4
|
||||
m_NearPlane: 0.2
|
||||
m_CullingMatrixOverride:
|
||||
e00: 1
|
||||
e01: 0
|
||||
e02: 0
|
||||
e03: 0
|
||||
e10: 0
|
||||
e11: 1
|
||||
e12: 0
|
||||
e13: 0
|
||||
e20: 0
|
||||
e21: 0
|
||||
e22: 1
|
||||
e23: 0
|
||||
e30: 0
|
||||
e31: 0
|
||||
e32: 0
|
||||
e33: 1
|
||||
m_UseCullingMatrixOverride: 0
|
||||
m_Cookie: {fileID: 0}
|
||||
m_DrawHalo: 0
|
||||
m_Flare: {fileID: 0}
|
||||
m_RenderMode: 0
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingLayerMask: 1
|
||||
m_Lightmapping: 4
|
||||
m_LightShadowCasterMode: 0
|
||||
m_AreaSize: {x: 1, y: 1}
|
||||
m_BounceIntensity: 1
|
||||
m_ColorTemperature: 6570
|
||||
m_UseColorTemperature: 0
|
||||
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_UseBoundingSphereOverride: 0
|
||||
m_UseViewFrustumForShadowCasterCull: 1
|
||||
m_ShadowRadius: 0
|
||||
m_ShadowAngle: 0
|
||||
--- !u!4 &165655211
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 165655209}
|
||||
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
|
||||
m_LocalPosition: {x: 0, y: 3, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
|
||||
--- !u!1001 &577647561
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 7207139244497761804, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: VRSRig_withController
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 2
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244497761807, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244786812522, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_ClearFlags
|
||||
value: 2
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244786812522, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_BackGroundColor.b
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244786812522, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_BackGroundColor.g
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7207139244786812522, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
propertyPath: m_BackGroundColor.r
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
--- !u!1 &577647562 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 7207139244497761804, guid: aa6466f3484ac344fb3c59a5b6398f84, type: 3}
|
||||
m_PrefabInstance: {fileID: 577647561}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &1436813407
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 4106666293350236145, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: VRSInputManager
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -0.20003967
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0.3311797
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 1.3696996
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4106666293350236147, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 247f35baba2bd814c96bea592859803d, type: 3}
|
||||
--- !u!1 &1888556275
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1888556277}
|
||||
- component: {fileID: 1888556276}
|
||||
m_Layer: 0
|
||||
m_Name: Underlay
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1888556276
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1888556275}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 221c4e845ba39fa4396461ac8c3b9e8e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
isPreviewingCylinder: 0
|
||||
isPreviewingEquirect: 1
|
||||
isPreviewingQuad: 0
|
||||
generatedPreview: {fileID: 0}
|
||||
layerType: 2
|
||||
compositionDepth: 0
|
||||
layerShape: 3
|
||||
layerVisibility: 0
|
||||
m_QuadWidth: 1
|
||||
m_QuadHeight: 1
|
||||
m_CylinderRadius: 1
|
||||
m_CylinderHeight: 1
|
||||
m_CylinderArcLength: 1
|
||||
m_EquirectRadius: 10
|
||||
m_EquirectScaleX: 1
|
||||
m_EquirectScaleY: 1
|
||||
m_EquirectBiasX: 0
|
||||
m_EquirectBiasY: 0
|
||||
m_EquirectCentralHorizontalAngle: 360
|
||||
m_EquirectUpperVerticalAngle: 90
|
||||
m_EquirectLowerVerticalAngle: -90
|
||||
m_CylinderAngleOfArc: 180
|
||||
lockMode: 0
|
||||
isDynamicLayer: 0
|
||||
isExternalSurface: 0
|
||||
isCustomRects: 0
|
||||
customRects: 2
|
||||
externalSurfaceWidth: 1280
|
||||
externalSurfaceHeight: 720
|
||||
applyColorScaleBias: 0
|
||||
solidEffect: 0
|
||||
colorScale: {r: 1, g: 1, b: 1, a: 1}
|
||||
colorBias: {r: 0, g: 0, b: 0, a: 0}
|
||||
isProtectedSurface: 0
|
||||
texture: {fileID: 2800000, guid: 536e6f3c92ead484baf6cebabecc58a7, type: 3}
|
||||
textureRight: {fileID: 0}
|
||||
renderPriority: 0
|
||||
trackingOrigin: {fileID: 577647562}
|
||||
generatedUnderlayMesh: {fileID: 0}
|
||||
generatedFallbackMesh: {fileID: 0}
|
||||
hmd: {fileID: 0}
|
||||
--- !u!4 &1888556277
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1888556275}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 3
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c44817993abad6145928810ed11e7e49
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,135 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 536e6f3c92ead484baf6cebabecc58a7
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 4096
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -22,6 +22,7 @@ Material:
|
||||
RenderType: Transparent
|
||||
disabledShaderPasses:
|
||||
- GRABPASS
|
||||
- ALWAYS
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
|
||||
@@ -54,6 +54,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "068b86ec-3f14-4d24-9b42-7057d00ab904",
|
||||
"path": "<HandInteraction>{LeftHand}/isTracked",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "isTrackedL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "b605cbf6-38fb-422a-b12d-48e386a67e9a",
|
||||
@@ -65,6 +76,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "fa2d2138-eb75-4cce-8088-3445f1560e97",
|
||||
"path": "<HandInteraction>{RightHand}/isTracked",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "isTrackedR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "9535518b-92b1-45ff-9525-624d0c52de13",
|
||||
@@ -76,6 +98,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "4331ebf5-824f-405f-8a29-a4c4049c23d9",
|
||||
"path": "<HandInteraction>{RightHand}/trackingState",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "trackingStateR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "1ccbb62c-6370-4507-847e-8fda100510e8",
|
||||
@@ -86,6 +119,17 @@
|
||||
"action": "trackingStateL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "f4e2d931-5b80-4e10-8e95-37c99a3d9536",
|
||||
"path": "<HandInteraction>{LeftHand}/trackingState",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "trackingStateL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -160,6 +204,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "0afb0794-9c98-41f7-9f58-8a1e64bc8bdc",
|
||||
"path": "<HandInteraction>{LeftHand}/devicePose",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "d41d33db-8b6c-4f21-9459-fd203551d990",
|
||||
@@ -171,6 +226,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "d46b4d0f-f908-4cd0-aece-22eb2318f8e7",
|
||||
"path": "<HandInteraction>{RightHand}/devicePose",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "48b33d4f-e9f9-4890-b836-d7303386c8b0",
|
||||
@@ -182,6 +248,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "005e532f-bb88-4636-8604-3c3dbf891803",
|
||||
"path": "<HandInteraction>{LeftHand}/graspValue",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ValueL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "e43dc5cd-3e96-4453-b6b2-818250c91436",
|
||||
@@ -193,6 +270,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "ddd425a1-b196-4a6c-bbba-69f3fa9b44b8",
|
||||
"path": "<HandInteraction>{RightHand}/graspValue",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ValueR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "3e8a289a-aa43-44fd-bbdf-ed15035ad5ef",
|
||||
@@ -204,6 +292,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "9c47003b-b29e-49a8-8ee5-7700bdf3ef66",
|
||||
"path": "<HandInteraction>{RightHand}/graspReady",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ReadyR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "79e10ffe-7276-4a95-b380-9d244bc2b213",
|
||||
@@ -214,6 +313,17 @@
|
||||
"action": "ReadyL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "5f1f8ba8-8258-4293-8a1c-b7680ae212c0",
|
||||
"path": "<HandInteraction>{LeftHand}/graspReady",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ReadyL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -230,6 +340,24 @@
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "PositionL",
|
||||
"type": "PassThrough",
|
||||
"id": "3c743437-254f-480d-ab2a-fbb7fa3a1c75",
|
||||
"expectedControlType": "Vector3",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "RotationL",
|
||||
"type": "PassThrough",
|
||||
"id": "a61c5a21-e370-4bd7-91cc-4939db98a735",
|
||||
"expectedControlType": "Quaternion",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "ValueL",
|
||||
"type": "Value",
|
||||
@@ -257,6 +385,24 @@
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "PositionR",
|
||||
"type": "PassThrough",
|
||||
"id": "eb88b286-d41a-4441-8680-eae89ddd9427",
|
||||
"expectedControlType": "Vector3",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "RotationR",
|
||||
"type": "PassThrough",
|
||||
"id": "4b410388-aabc-4cef-944e-68d5f68bcc44",
|
||||
"expectedControlType": "Quaternion",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "ValueR",
|
||||
"type": "Value",
|
||||
@@ -288,6 +434,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "45cf0dab-fbfc-478f-aa3b-f74eafb029e9",
|
||||
"path": "<HandInteraction>{LeftHand}/pointer",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "cbaae569-a034-4ce6-8cdd-eef5586aaa7e",
|
||||
@@ -299,6 +456,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "bb49f848-f6b0-4a1a-b60c-1f08a8bdffcc",
|
||||
"path": "<HandInteraction>{RightHand}/pointer",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "514be0ed-99f4-4f3a-a53b-672c0caeb1d5",
|
||||
@@ -310,6 +478,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "8e248108-0a74-421f-b2b6-0172ccf49da8",
|
||||
"path": "<HandInteraction>{LeftHand}/pointerActivateValue",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ValueL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "b3c9d90b-0ad0-42c6-9cda-1ac1d74719a5",
|
||||
@@ -321,6 +500,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "afb0658c-57a3-4f84-99ce-f2b5731b081a",
|
||||
"path": "<HandInteraction>{RightHand}/pointerActivateValue",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ValueR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "03ca7d96-43df-406f-8b41-c3b8168cbcbc",
|
||||
@@ -332,6 +522,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "ff1d9683-a045-4394-95f3-8b8637109b91",
|
||||
"path": "<HandInteraction>{RightHand}/pointerActivateReady",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ReadyR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "0f20788a-3543-4fd0-8e4e-9ad56108877e",
|
||||
@@ -342,6 +543,299 @@
|
||||
"action": "ReadyL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "4df69cb3-1d60-4aab-9af4-528400022e93",
|
||||
"path": "<HandInteraction>{LeftHand}/pointerActivateReady",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ReadyL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "4af711ee-8f25-4a6b-900b-cce9a68655de",
|
||||
"path": "<ViveHandInteractionExt>{LeftHand}/pointerPosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "056d875e-56e5-4783-b73c-7d2a83407530",
|
||||
"path": "<HandInteraction>{LeftHand}/pointerPosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "d47309f6-c5d1-4892-bf76-e51faa8b6137",
|
||||
"path": "<ViveHandInteractionExt>{LeftHand}/pointerRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "f4fade07-9a27-4a3a-9145-87fc4e6fc282",
|
||||
"path": "<HandInteraction>{LeftHand}/pointerRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "61444e1e-91f4-45a7-8104-93317a4fcfa8",
|
||||
"path": "<ViveHandInteractionExt>{RightHand}/pointerPosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "d66724bb-6f33-46eb-8205-3912e3cdb72d",
|
||||
"path": "<HandInteraction>{RightHand}/pointerPosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "3f05dfd2-7dcb-46ee-a8c8-20c921c62793",
|
||||
"path": "<ViveHandInteractionExt>{RightHand}/pointerRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "c3aa63db-3ff8-4206-b62a-d1caf6ffafd5",
|
||||
"path": "<HandInteraction>{RightHand}/pointerRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "HandPoke",
|
||||
"id": "a4cfc781-c114-4451-96d5-857c3a9385fa",
|
||||
"actions": [
|
||||
{
|
||||
"name": "PoseL",
|
||||
"type": "PassThrough",
|
||||
"id": "e9feeab8-c68c-47d7-8560-8f3b2c44d2bf",
|
||||
"expectedControlType": "Pose",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "PositionL",
|
||||
"type": "PassThrough",
|
||||
"id": "eed73641-933c-4836-9ed7-f0f28ddbf9ec",
|
||||
"expectedControlType": "Vector3",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "RotationL",
|
||||
"type": "PassThrough",
|
||||
"id": "5ad8d488-2973-487b-a19f-c8eb588c67d3",
|
||||
"expectedControlType": "Quaternion",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "PoseR",
|
||||
"type": "PassThrough",
|
||||
"id": "1bac4e9e-ce3d-4218-bbca-255ef780cf6c",
|
||||
"expectedControlType": "Pose",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "PositionR",
|
||||
"type": "PassThrough",
|
||||
"id": "cdd9430c-70f2-4854-b3ae-81b884e87168",
|
||||
"expectedControlType": "Vector3",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "RotationR",
|
||||
"type": "PassThrough",
|
||||
"id": "81746764-95ef-48ce-b2e1-e05330f97e05",
|
||||
"expectedControlType": "Quaternion",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
}
|
||||
],
|
||||
"bindings": [
|
||||
{
|
||||
"name": "",
|
||||
"id": "efd73d26-df7d-4b90-93c2-202a5f70c05c",
|
||||
"path": "<ViveHandInteractionExt>{LeftHand}/pokePose",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "8e9539c4-4aca-471f-b843-bd282a33616b",
|
||||
"path": "<HandInteraction>{LeftHand}/pokePose",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "124f3c45-0d83-4302-9f2a-cb945f7c268e",
|
||||
"path": "<ViveHandInteractionExt>{RightHand}/pokePose",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "d6bd90fd-f8ab-4cc7-ab90-c604788b32e8",
|
||||
"path": "<HandInteraction>{RightHand}/pokePose",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "29fcebb4-1111-4c52-becf-a20a4919c8bd",
|
||||
"path": "<ViveHandInteractionExt>{RightHand}/pokePosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "3f1a484f-a430-4f62-9587-47944d3ceb8a",
|
||||
"path": "<HandInteraction>{RightHand}/pokePosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "72bb3809-4dba-4b8c-a35a-6c2078873256",
|
||||
"path": "<ViveHandInteractionExt>{LeftHand}/pokeRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "c64e7c60-8e41-47d7-80b3-8f8dd7c17071",
|
||||
"path": "<HandInteraction>{LeftHand}/pokeRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "cae2d11b-bd7f-4fc4-b247-c21af26cf2d5",
|
||||
"path": "<ViveHandInteractionExt>{RightHand}/pokeRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "59f0ff0b-c894-4fb7-b775-7a8dbc56c718",
|
||||
"path": "<HandInteraction>{RightHand}/pokeRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "79dfac35-3c6f-45b2-8045-eeba5534cb14",
|
||||
"path": "<ViveHandInteractionExt>{LeftHand}/pokePosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "6b420474-04e5-46bb-b76f-a4aef922dac4",
|
||||
"path": "<HandInteraction>{LeftHand}/pokePosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -358,6 +852,24 @@
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "PositionL",
|
||||
"type": "PassThrough",
|
||||
"id": "d0f34fc0-7d91-44ad-8fcb-2be82414f6ba",
|
||||
"expectedControlType": "Vector3",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "RotationL",
|
||||
"type": "PassThrough",
|
||||
"id": "69f4a637-3eaf-490d-9de8-d9a08bff9fff",
|
||||
"expectedControlType": "Quaternion",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "ValueL",
|
||||
"type": "Value",
|
||||
@@ -385,6 +897,24 @@
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "PositionR",
|
||||
"type": "PassThrough",
|
||||
"id": "d46fd2f7-9611-4d4f-bc93-12999b1f862e",
|
||||
"expectedControlType": "Vector3",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "RotationR",
|
||||
"type": "PassThrough",
|
||||
"id": "5ea8b91a-29fb-4e5a-bb65-f61664a39b2a",
|
||||
"expectedControlType": "Quaternion",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "ValueR",
|
||||
"type": "Value",
|
||||
@@ -416,6 +946,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "e73a46a3-8913-44c6-a015-713f387ff238",
|
||||
"path": "<HandInteraction>{LeftHand}/pinchPose",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "92e779f7-ba6f-417d-9f4c-9d5f81790686",
|
||||
@@ -427,6 +968,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "8c9406c8-c451-43cc-8a39-b8ec5d841c2b",
|
||||
"path": "<HandInteraction>{RightHand}/pinchPose",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "f5f748fd-da48-423b-864a-340e9934041f",
|
||||
@@ -438,6 +990,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "dbc9eb68-a3a8-4309-b690-2215efd2af77",
|
||||
"path": "<HandInteraction>{LeftHand}/pinchValue",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ValueL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "838dbd9a-6c54-4959-9a92-0168b20d3632",
|
||||
@@ -449,6 +1012,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "79ebe950-0644-4adb-a13d-fd1d5e109e57",
|
||||
"path": "<HandInteraction>{RightHand}/pinchValue",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ValueR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "30bc3116-8581-42b7-9a73-8f4ce570083e",
|
||||
@@ -460,6 +1034,17 @@
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "e50e1257-1b2b-46ab-99b2-231ccee5eeb6",
|
||||
"path": "<HandInteraction>{RightHand}/pinchReady",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "ReadyR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "9591b4cc-cf0b-4096-91ae-848358b0f366",
|
||||
@@ -470,52 +1055,103 @@
|
||||
"action": "ReadyL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "HandPoke",
|
||||
"id": "a4cfc781-c114-4451-96d5-857c3a9385fa",
|
||||
"actions": [
|
||||
{
|
||||
"name": "PoseL",
|
||||
"type": "PassThrough",
|
||||
"id": "e9feeab8-c68c-47d7-8560-8f3b2c44d2bf",
|
||||
"expectedControlType": "Pose",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "PoseR",
|
||||
"type": "PassThrough",
|
||||
"id": "1bac4e9e-ce3d-4218-bbca-255ef780cf6c",
|
||||
"expectedControlType": "Pose",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
}
|
||||
],
|
||||
"bindings": [
|
||||
{
|
||||
"name": "",
|
||||
"id": "efd73d26-df7d-4b90-93c2-202a5f70c05c",
|
||||
"path": "<ViveHandInteractionExt>{LeftHand}/pokePose",
|
||||
"id": "136c49a3-8f2b-476b-9adf-98e7ed1e6e9a",
|
||||
"path": "<HandInteraction>{LeftHand}/pinchReady",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseL",
|
||||
"action": "ReadyL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "124f3c45-0d83-4302-9f2a-cb945f7c268e",
|
||||
"path": "<ViveHandInteractionExt>{RightHand}/pokePose",
|
||||
"id": "9221267c-62a0-47cb-aeba-aca47714c033",
|
||||
"path": "<ViveHandInteractionExt>{LeftHand}/pinchRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PoseR",
|
||||
"action": "RotationL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "b4dcfb93-89e5-45cf-bde0-6c2adea454b3",
|
||||
"path": "<HandInteraction>{LeftHand}/pinchRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "b841def8-addf-4eae-808f-5160a5ff3ed5",
|
||||
"path": "<ViveHandInteractionExt>{LeftHand}/pinchPosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "3253d57e-11aa-4449-8960-16e8911854d5",
|
||||
"path": "<HandInteraction>{LeftHand}/pinchPosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionL",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "88a63c73-43a1-469c-99b0-ef08bd0b95e7",
|
||||
"path": "<ViveHandInteractionExt>{RightHand}/pinchPosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "bf69fb00-cf5a-40da-a774-437f1ea76d44",
|
||||
"path": "<HandInteraction>{RightHand}/pinchPosition",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "PositionR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "7f0a8dc7-c33a-4811-ad95-367df499cfb8",
|
||||
"path": "<ViveHandInteractionExt>{RightHand}/pinchRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "ef207392-905c-4a08-9e1f-7bdf0b66069a",
|
||||
"path": "<HandInteraction>{RightHand}/pinchRotation",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": "",
|
||||
"action": "RotationR",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
}
|
||||
|
||||
@@ -1768,6 +1768,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -1808,6 +1809,18 @@ MonoBehaviour:
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 5c275b7c-6878-407c-acb9-66806a61261b
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
@@ -1826,7 +1839,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &672225543
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -2227,6 +2239,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -2245,6 +2258,14 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: 226fcfb5-99d1-4280-be7d-6cab3c65b50e
|
||||
m_Path: <HandInteraction>{RightHand}/pinchPosition
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_RotationInput:
|
||||
@@ -2265,6 +2286,26 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: bcafb8fd-f86e-42bf-90ac-af906ad3c602
|
||||
m_Path: <HandInteraction>{RightHand}/pinchRotation
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: de44ecc7-66b7-4528-a659-367b18da0fbc
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
@@ -2285,7 +2326,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1001 &743277234
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -2939,6 +2979,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -2957,6 +2998,14 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: 4364030c-a105-4d8e-a293-2110f00c6bd2
|
||||
m_Path: <HandInteraction>{LeftHand}/pinchPosition
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_RotationInput:
|
||||
@@ -2977,6 +3026,26 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: a3e41bb8-f7e1-4d78-982f-efb634541fad
|
||||
m_Path: <HandInteraction>{LeftHand}/pinchRotation
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: c406c9d0-8b04-4a9b-8176-c2f2ecb97e6d
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
@@ -2997,7 +3066,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &1007103283
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -3361,6 +3429,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -3401,6 +3470,18 @@ MonoBehaviour:
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 03a60622-a192-4d59-b71c-846ad1399680
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
@@ -3419,7 +3500,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1001 &1226082257
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -3736,6 +3816,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -3754,6 +3835,14 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: 34a62fdc-c1b6-4cf1-a7de-b7024d3ca2cf
|
||||
m_Path: <HandInteraction>{LeftHand}/pointerPosition
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_RotationInput:
|
||||
@@ -3774,6 +3863,26 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: 6e74078d-e467-4dc6-8023-a29a8e78d576
|
||||
m_Path: <HandInteraction>{LeftHand}/pointerRotation
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 6a3020fa-bbda-4b50-adfe-31d7c651a205
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
@@ -3794,7 +3903,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &1414890483
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -4053,6 +4161,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -4071,6 +4180,14 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: 449e07f6-b6de-4297-8c24-68fa0c54203b
|
||||
m_Path: <HandInteraction>{RightHand}/devicePosition
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_RotationInput:
|
||||
@@ -4091,6 +4208,26 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: 2d2d7513-e9e2-44fe-a2f3-8519275ddf39
|
||||
m_Path: <HandInteraction>{RightHand}/deviceRotation
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: f109a673-1db0-4c0a-90b3-7d2f485e71e1
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
@@ -4111,7 +4248,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1001 &1495351303
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -4760,6 +4896,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -4778,6 +4915,14 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: a98522ae-3d15-4f68-8b52-3e0b07bac073
|
||||
m_Path: <HandInteraction>{RightHand}/pokePosition
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_RotationInput:
|
||||
@@ -4798,6 +4943,26 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: a5a97017-b5d5-497d-b9e8-a4c31f49c490
|
||||
m_Path: <HandInteraction>{RightHand}/pokeRotation
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 1105b297-66c4-46e5-a497-8c5fada26fca
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
@@ -4818,7 +4983,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &1708107229
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -5771,6 +5935,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -5811,6 +5976,18 @@ MonoBehaviour:
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: dbd06a1e-0881-4702-b7ef-a4bb81c023fd
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
@@ -5829,7 +6006,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &1947228662
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -5893,6 +6069,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -5911,6 +6088,14 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: b51f75c3-0d11-4a26-b603-185a4f559861
|
||||
m_Path: <HandInteraction>{LeftHand}/pokePosition
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_RotationInput:
|
||||
@@ -5931,6 +6116,26 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: 59e61b20-ab73-411d-8b56-ac6f0e182f9d
|
||||
m_Path: <HandInteraction>{LeftHand}/pokeRotation
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 52fe8957-1665-4732-a1a1-f95cc70a1c78
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
@@ -5951,7 +6156,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &1962967395
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -6093,6 +6297,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -6111,6 +6316,14 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: 2b53a195-ce43-4708-a385-e61a8c6ec293
|
||||
m_Path: <HandInteraction>{LeftHand}/devicePosition
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_RotationInput:
|
||||
@@ -6131,6 +6344,26 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: 5717e88d-f9be-4c5d-a42b-a82e179bc64d
|
||||
m_Path: <HandInteraction>{LeftHand}/deviceRotation
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: ec3ea843-1c14-4b82-a1ca-3e61d0da8985
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
@@ -6151,7 +6384,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &2064717940
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -6215,6 +6447,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -6255,6 +6488,18 @@ MonoBehaviour:
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: eb274547-769d-45f6-890b-abda078e5899
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
@@ -6273,7 +6518,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &2073298331
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -6504,6 +6748,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -6522,6 +6767,14 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: b9726b6c-9ecb-4694-982a-9099c7c1df5e
|
||||
m_Path: <HandInteraction>{RightHand}/pointerPosition
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Position Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_RotationInput:
|
||||
@@ -6542,6 +6795,26 @@ MonoBehaviour:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
- m_Name:
|
||||
m_Id: fdb8ffda-f0d5-4c9b-b785-6afb920dafa8
|
||||
m_Path: <HandInteraction>{RightHand}/pointerRotation
|
||||
m_Interactions:
|
||||
m_Processors:
|
||||
m_Groups:
|
||||
m_Action: Rotation Input
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 0b86eacc-f773-400d-98a7-92e950a58b04
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
@@ -6562,7 +6835,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!4 &543450651583740275 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 5562507940235781211, guid: a6579de606ad5b54893722f363b5371d, type: 3}
|
||||
@@ -7983,6 +8255,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -8023,6 +8296,18 @@ MonoBehaviour:
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 8d1a2e5f-8b6f-4fa9-a4d9-b17c00a26569
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name: Position
|
||||
m_Type: 0
|
||||
@@ -8057,7 +8342,6 @@ MonoBehaviour:
|
||||
m_Action: Rotation
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &6088718223833369450
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -8172,6 +8456,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -8212,6 +8497,18 @@ MonoBehaviour:
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 7b3328e4-c5ac-4bf5-86d8-e72901205f35
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name: Position
|
||||
m_Type: 0
|
||||
@@ -8246,7 +8543,6 @@ MonoBehaviour:
|
||||
m_Action: Rotation
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &6088718223950534255
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -8736,6 +9032,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
@@ -8776,6 +9073,18 @@ MonoBehaviour:
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name: Tracking State Input
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: ae1fc38a-9c71-495c-aab6-ed33ddf01498
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name: Position
|
||||
m_Type: 0
|
||||
@@ -8810,7 +9119,6 @@ MonoBehaviour:
|
||||
m_Action: Rotation
|
||||
m_Flags: 0
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1001 &7278110509245602027
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@ namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
|
||||
|
||||
if (m_ActionReference != null
|
||||
&& m_ActionReference.action != null
|
||||
&& m_ActionReference.action.controls.Count > 0
|
||||
//&& m_ActionReference.action.controls.Count > 0 // The Count of InputActionProperty will become 0 after switching interaction profiles.
|
||||
&& m_ActionReference.action.enabled == true)
|
||||
{
|
||||
m_TargetGameobject.SetActive(true);
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
|
||||
if (m_TimeRemainingTillChange <= 0.0f)
|
||||
{
|
||||
List<XRInputSubsystem> inputSubsystems = new List<XRInputSubsystem>();
|
||||
SubsystemManager.GetInstances(inputSubsystems);
|
||||
SubsystemManager.GetSubsystems(inputSubsystems);
|
||||
XRInputSubsystem subsystem = inputSubsystems?[0];
|
||||
if (subsystem != null)
|
||||
{
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace UnityEngine.XR.OpenXR.Samples.ControllerSample
|
||||
|
||||
XRInputSubsystem subsystem = null;
|
||||
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
SubsystemManager.GetSubsystems(s_InputSubsystems);
|
||||
if(s_InputSubsystems.Count > 0)
|
||||
{
|
||||
subsystem = s_InputSubsystems[0];
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace VIVE.OpenXR.Samples.OpenXRInput
|
||||
{
|
||||
public class RemoveRenderMask : MonoBehaviour
|
||||
{
|
||||
private void OnEnable()
|
||||
{
|
||||
StartCoroutine(RemoveOcclusionMask());
|
||||
}
|
||||
IEnumerator RemoveOcclusionMask()
|
||||
{
|
||||
// Find DisplaySubsystem
|
||||
XRDisplaySubsystem display = null;
|
||||
List<XRDisplaySubsystem> displaySubsystems = new List<XRDisplaySubsystem>();
|
||||
do
|
||||
{
|
||||
SubsystemManager.GetSubsystems(displaySubsystems);
|
||||
foreach (var d in displaySubsystems)
|
||||
{
|
||||
if (d.running)
|
||||
{
|
||||
display = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (display == null);
|
||||
Debug.Log("RemoveOcclusionMask XRSettings.occlusionMaskScale = 0");
|
||||
XRSettings.occlusionMaskScale = 0;
|
||||
XRSettings.useOcclusionMesh = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f60faf6b28b7954b9ddf397eda40dc7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -29,7 +29,7 @@ public class PlaneDetectionTestHandle : MonoBehaviour
|
||||
void GetXRInputSubsystem()
|
||||
{
|
||||
List<XRInputSubsystem> xrSubsystemList = new List<XRInputSubsystem>();
|
||||
SubsystemManager.GetInstances(xrSubsystemList);
|
||||
SubsystemManager.GetSubsystems(xrSubsystemList);
|
||||
foreach (var xrSubsystem in xrSubsystemList)
|
||||
{
|
||||
if (xrSubsystem.running)
|
||||
|
||||
@@ -96,7 +96,11 @@ public class Controller : MonoBehaviour
|
||||
{
|
||||
GameObject ball = Instantiate(sphere, spawnPoint);
|
||||
Rigidbody rb = ball.GetComponent<Rigidbody>();
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rb.linearVelocity = ball.transform.parent.forward * shootVelocity;
|
||||
#else
|
||||
rb.velocity = ball.transform.parent.forward * shootVelocity;
|
||||
#endif
|
||||
rb.isKinematic = false;
|
||||
ball.transform.parent = null;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,11 @@ namespace UnityEngine.XR.OpenXR.Samples.MeshingFeature
|
||||
{
|
||||
if (transform.position.y < -10)
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rb.linearVelocity = Vector3.zero;
|
||||
#else
|
||||
rb.velocity = Vector3.zero;
|
||||
#endif
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
rb.MovePosition(starting);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace UnityEngine.XR.OpenXR.Samples.MeshingFeature
|
||||
}
|
||||
|
||||
var meshSubsystems = new List<XRMeshSubsystem>();
|
||||
SubsystemManager.GetInstances(meshSubsystems);
|
||||
SubsystemManager.GetSubsystems(meshSubsystems);
|
||||
if (meshSubsystems.Count == 1)
|
||||
{
|
||||
s_MeshSubsystem = meshSubsystems[0];
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.textmeshpro",
|
||||
"expression": "3.2.0-pre.10",
|
||||
"define": "UNITY_TEXT_MESH_PRO_3_2_0_PRE_10_OR_NEWER"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.xr.openxr",
|
||||
"expression": "1.6.0",
|
||||
@@ -32,11 +37,6 @@
|
||||
"name": "com.unity.xr.openxr",
|
||||
"expression": "1.9.1",
|
||||
"define": "UNITY_XR_OPENXR_1_9_1"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.textmeshpro",
|
||||
"expression": "3.2.0-pre.10",
|
||||
"define": "UNITY_TEXT_MESH_PRO_3_2_0_PRE_10_OR_NEWER"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
|
||||
@@ -23034,7 +23034,7 @@ GameObject:
|
||||
- component: {fileID: 785420544}
|
||||
- component: {fileID: 785420543}
|
||||
- component: {fileID: 785420542}
|
||||
- component: {fileID: 785420541}
|
||||
- component: {fileID: 785420545}
|
||||
m_Layer: 5
|
||||
m_Name: QuitBtn
|
||||
m_TagString: Untagged
|
||||
@@ -23063,18 +23063,6 @@ RectTransform:
|
||||
m_AnchoredPosition: {x: 0, y: -96}
|
||||
m_SizeDelta: {x: 86.2, y: 30}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &785420541
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 785420539}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b661f25ed5b57874290a0bafb5ad8234, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!114 &785420542
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -23119,8 +23107,8 @@ MonoBehaviour:
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 785420541}
|
||||
m_TargetAssemblyTypeName: Wave.Essence.Extra.QuitApplication, Wave.Essence
|
||||
- m_Target: {fileID: 785420545}
|
||||
m_TargetAssemblyTypeName: VIVE.OpenXR.Toolkits.Common.LeaveScene, VIVE.OpenXR.Toolkits
|
||||
m_MethodName: ExitGame
|
||||
m_Mode: 1
|
||||
m_Arguments:
|
||||
@@ -23169,6 +23157,18 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 785420539}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &785420545
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 785420539}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 46285a19de0bb1b4f849a4b0bcfc5c0f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &792366970
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -68792,6 +68792,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 1
|
||||
m_Action:
|
||||
@@ -68816,6 +68817,18 @@ MonoBehaviour:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 3113219943245244623, guid: 7731a6c81e069424eb7df31b19b84b41, type: 3}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 49637aaa-d811-48fe-9f86-4076b1bbf006
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
@@ -68834,7 +68847,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!4 &2336634745151424894
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -68947,6 +68959,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 1
|
||||
m_Action:
|
||||
@@ -68971,6 +68984,18 @@ MonoBehaviour:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: -5246335118593862002, guid: 7731a6c81e069424eb7df31b19b84b41, type: 3}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 49846443-d944-470e-969c-29e6fe616f69
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
@@ -68989,7 +69014,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &2336634745461817778
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -69698,6 +69722,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_IgnoreTrackingState: 0
|
||||
m_PositionInput:
|
||||
m_UseReference: 1
|
||||
m_Action:
|
||||
@@ -69722,6 +69747,18 @@ MonoBehaviour:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: -3341103204585363708, guid: 7731a6c81e069424eb7df31b19b84b41, type: 3}
|
||||
m_TrackingStateInput:
|
||||
m_UseReference: 0
|
||||
m_Action:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
m_ExpectedControlType:
|
||||
m_Id: 346b5aa3-6f99-4b26-847e-776c912c914e
|
||||
m_Processors:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_Reference: {fileID: 0}
|
||||
m_PositionAction:
|
||||
m_Name:
|
||||
m_Type: 0
|
||||
@@ -69740,7 +69777,6 @@ MonoBehaviour:
|
||||
m_Interactions:
|
||||
m_SingletonActionBindings: []
|
||||
m_Flags: 0
|
||||
m_HasMigratedActions: 1
|
||||
--- !u!1 &2336634746049650654
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "com.htc.upm.vive.openxr",
|
||||
"displayName": "VIVE OpenXR Plugin",
|
||||
"version": "2.5.0",
|
||||
"version": "2.5.1",
|
||||
"unity": "2021.3",
|
||||
"description": "The \"VIVE OpenXR Plugin\" package enables your application to run on VIVE devices. \nThis package is a bridge between VIVE devides and Unity OpenXR.\nThis package complements Unity's \"OpenXR Plugin\" package, and enables you to use extra features, as listed in the following.\n\n- Controller Input\n- Hand Tracking\n- Wrist Tracking\n- Eye Gaze\n- CompositionLayer\n- Facial Tracking\n\n\nYou can view the documentation for additional information.",
|
||||
"keywords": [
|
||||
@@ -15,9 +15,10 @@
|
||||
"url": "https://www.htc.com"
|
||||
},
|
||||
"dependencies": {
|
||||
"com.unity.inputsystem": "1.4.3",
|
||||
"com.unity.xr.management": "4.2.1",
|
||||
"com.unity.xr.openxr": "1.3.1"
|
||||
"com.unity.inputsystem": "1.7.0",
|
||||
"com.unity.xr.openxr": "1.12.1",
|
||||
"com.unity.xr.interaction.toolkit": "2.5.4"
|
||||
},
|
||||
"samples": [
|
||||
{
|
||||
@@ -33,6 +34,6 @@
|
||||
],
|
||||
"type": "library",
|
||||
"hideInEditor": false,
|
||||
"documentationUrl": "https://developer.vive.com/resources/openxr/openxr-mobile/tutorials/unity/getting-started-openxr-mobile/",
|
||||
"changelogUrl": "https://developer.vive.com/resources/openxr/openxr-mobile/download/latest/"
|
||||
"documentationUrl": "https://developer.vive.com/resources/openxr/unity/tutorials/setup-and-installation/getting-started-with-openxr/",
|
||||
"changelogUrl": "https://developer.vive.com/resources/openxr/unity/download/latest/"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user