diff --git a/com.htc.upm.vive.openxr/Editor/AndroidManifestProcess.cs b/com.htc.upm.vive.openxr/Editor/AndroidManifestProcess.cs index ad8402b..f03e9e6 100644 --- a/com.htc.upm.vive.openxr/Editor/AndroidManifestProcess.cs +++ b/com.htc.upm.vive.openxr/Editor/AndroidManifestProcess.cs @@ -281,7 +281,8 @@ namespace VIVE.OpenXR.Editor } } - foreach (var feature in settings.GetFeatures()) + var features = settings.GetFeatures(); + 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) diff --git a/com.htc.upm.vive.openxr/Editor/CompositionLayer/Scripts/CompositionLayerEditor.cs b/com.htc.upm.vive.openxr/Editor/CompositionLayer/Scripts/CompositionLayerEditor.cs index 08c8526..0c70847 100644 --- a/com.htc.upm.vive.openxr/Editor/CompositionLayer/Scripts/CompositionLayerEditor.cs +++ b/com.htc.upm.vive.openxr/Editor/CompositionLayer/Scripts/CompositionLayerEditor.cs @@ -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(); + + //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().sharedMaterial.mainTexture != targetCompositionLayer.texture) + { + targetCompositionLayer.generatedPreview.GetComponent().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(); + MeshFilter equirectMeshFilter = targetCompositionLayer.generatedPreview.AddComponent(); + 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(); diff --git a/com.htc.upm.vive.openxr/Editor/PackageManagerHelper.cs b/com.htc.upm.vive.openxr/Editor/PackageManagerHelper.cs index d31971f..aee19b5 100644 --- a/com.htc.upm.vive.openxr/Editor/PackageManagerHelper.cs +++ b/com.htc.upm.vive.openxr/Editor/PackageManagerHelper.cs @@ -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: diff --git a/com.htc.upm.vive.openxr/Editor/Preferences/ViveOpenXRPreference.cs b/com.htc.upm.vive.openxr/Editor/Preferences/ViveOpenXRPreference.cs index 4a164ff..1d076ca 100644 --- a/com.htc.upm.vive.openxr/Editor/Preferences/ViveOpenXRPreference.cs +++ b/com.htc.upm.vive.openxr/Editor/Preferences/ViveOpenXRPreference.cs @@ -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) diff --git a/com.htc.upm.vive.openxr/Editor/ViveOpenXRFeatureSet.cs b/com.htc.upm.vive.openxr/Editor/ViveOpenXRFeatureSet.cs index 2a78fb2..cf6618c 100644 --- a/com.htc.upm.vive.openxr/Editor/ViveOpenXRFeatureSet.cs +++ b/com.htc.upm.vive.openxr/Editor/ViveOpenXRFeatureSet.cs @@ -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", diff --git a/com.htc.upm.vive.openxr/Runtime/Android/arm64/libviveopenxr.so b/com.htc.upm.vive.openxr/Runtime/Android/arm64/libviveopenxr.so index 9256aa2..9d88081 100644 --- a/com.htc.upm.vive.openxr/Runtime/Android/arm64/libviveopenxr.so +++ b/com.htc.upm.vive.openxr/Runtime/Android/arm64/libviveopenxr.so @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:03112f1238f564e25967d7421da91a81e842bd69dec6f5d5b3aadc73a1c2468b -size 513424 +oid sha256:6b1d3fde3d76688289de5e62fdcaba9be8040b7b7365b6e23f502f80e6d67fa6 +size 516080 diff --git a/com.htc.upm.vive.openxr/Runtime/Common/IViveFeatureWrapper.cs b/com.htc.upm.vive.openxr/Runtime/Common/IViveFeatureWrapper.cs index 3b3e93d..f9dce23 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/IViveFeatureWrapper.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/IViveFeatureWrapper.cs @@ -7,8 +7,17 @@ namespace VIVE.OpenXR.Feature { public interface IViveFeatureWrapper { + /// + /// OnInstanceCreate might be called multiple times. Because many features might be using the same instance. + /// + /// + /// + /// public bool OnInstanceCreate(XrInstance xrInstance, IntPtr xrGetInstanceProcAddr); + /// + /// OnInstanceDestroy might be called multiple times. Because many features might be using the same instance. + /// public void OnInstanceDestroy(); } @@ -21,6 +30,11 @@ namespace VIVE.OpenXR.Feature // Set true in yourfeature's OnInstanceCreate public bool IsInited { get; protected set; } = false; + /// + /// If the feature is inited not successfully, Set this true. Use to avoid multiple inits. + /// + public bool TryInited { get; protected set; } = false; + public OpenXRHelper.xrGetInstanceProcAddrDelegate xrGetInstanceProcAddr; /// diff --git a/com.htc.upm.vive.openxr/Runtime/Common/MemoryTools.cs b/com.htc.upm.vive.openxr/Runtime/Common/MemoryTools.cs index 64ebe5e..ca57f90 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/MemoryTools.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/MemoryTools.cs @@ -1,26 +1,114 @@ using System; using System.Runtime.InteropServices; +using UnityEngine.Profiling; namespace VIVE.OpenXR { - public static class MemoryTools - { + internal static class MemoryTools + { + /// + /// Make sure the input ptr is a OpenXR XrBaseStructure derived struct. + /// + /// the struct to get its next. + /// the next's value + 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; + } + + /// + /// Make sure the input ptr is a OpenXR XrBaseStructure derived struct. + /// + /// the struct to get its type + /// the struct's type + 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(IntPtr ptr) where T : unmanaged + { + //Profiler.BeginSample("PtrToStructure"); + // Not to use Marshal.PtrToStructure 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(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, IntPtr ptr) where T : unmanaged + { + //Profiler.BeginSample("StructureToPtr"); + // Not to use Marshal.StructureToPtr because it is slow. + Buffer.MemoryCopy(&t, (void*)ptr, sizeof(T), sizeof(T)); + //Profiler.EndSample(); + } + /// /// Convert the enum array to IntPtr. Should call after use. /// - /// /// /// - public static IntPtr ToIntPtr(T[] array) where T : Enum - { - int size = Marshal.SizeOf(typeof(T)) * array.Length; - IntPtr ptr = Marshal.AllocHGlobal(size); - int[] intArray = new int[array.Length]; - for (int i = 0; i < array.Length; i++) - intArray[i] = (int)(object)array[i]; - Marshal.Copy(intArray, 0, ptr, array.Length); - return ptr; - } + public static unsafe IntPtr ToIntPtr(T[] array) where T : Enum + { + int size = sizeof(int) * array.Length; + IntPtr ptr = Marshal.AllocHGlobal(size); + + int* intPtr = (int*)ptr.ToPointer(); + for (int i = 0; i < array.Length; i++) + { + // Convert enum to int. This has better performance than Convert.ToInt32. + intPtr[i] = (int)(object)array[i]; + } + + return ptr; + } + + /// + /// Convert the struct to IntPtr. Should call after use. + /// + /// + /// + /// + public static IntPtr ToIntPtr(T structure) where T : struct + { + int size = Marshal.SizeOf(structure); + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(structure, ptr, true); + return ptr; + } /// /// Make the same size raw buffer from input array. @@ -28,30 +116,68 @@ namespace VIVE.OpenXR /// Data type could be primitive type or struct. Should call after use. /// The data array /// The memory handle. Should release by - public static IntPtr MakeRawMemory(T[] refArray) - { - int size = Marshal.SizeOf(typeof(T)) * refArray.Length; - return Marshal.AllocHGlobal(size); - } + public static unsafe IntPtr MakeRawMemory(T[] refArray) where T : unmanaged + { + int size = Marshal.SizeOf(typeof(T)) * refArray.Length; + return Marshal.AllocHGlobal(size); + } - /// - /// Copy the raw memory to the array. You should make sure the array has the same size as the raw memory. - /// - /// Convert the memory to this type array. - /// The output array. - /// The data source in raw memory form. - /// Specify the copy count. Count should be less than array length. - public static void CopyFromRawMemory(T[] array, IntPtr raw, int count = 0) - { - 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++) - { - array[i] = Marshal.PtrToStructure(IntPtr.Add(raw, i * step)); - } - } + /// + /// Copy the raw memory to the array. You should make sure the array has the same size as the raw memory. + /// + /// Convert the memory to this type array. + /// The output array. + /// The data source in raw memory form. + /// Specify the copy count. Count should be less than array length. + public static unsafe void CopyFromRawMemory(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 = sizeof(T); + int bufferSize = step * N; + + // Pin array's address. Prevent GC move it. + fixed (T* destPtr = array) + { + T* sourcePtr = (T*)raw.ToPointer(); + Buffer.MemoryCopy(sourcePtr, destPtr, bufferSize, bufferSize); + } + //Profiler.EndSample(); + } + + /// + /// Copy all raw memory to the array. This has higher performance than . + /// 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. + /// + /// Convert the memory to this type array. + /// The output array. + /// The data source in raw memory form. + public static unsafe void CopyAllFromRawMemory(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(); + } /// /// Make the same size raw buffer from input array. Make sure the raw has enough size. @@ -59,22 +185,44 @@ namespace VIVE.OpenXR /// Convert this type array to raw memory. /// The output data in raw memory form /// The data source - public static void CopyToRawMemory(IntPtr raw, T[] array) - { - int step = Marshal.SizeOf(typeof(T)); - for (int i = 0; i < array.Length; i++) - { - Marshal.StructureToPtr(array[i], IntPtr.Add(raw, i * step), false); - } - } + public static unsafe void CopyToRawMemory(IntPtr raw, T[] array) where T : unmanaged + { + //Profiler.BeginSample("CopyToRawMemory"); + int step = sizeof(T); + int bufferSize = step * array.Length; + // Pin array's address. Prevent GC move it. + fixed (T* destPtr = array) + { + void* ptr = raw.ToPointer(); + Buffer.MemoryCopy(destPtr, ptr, bufferSize, bufferSize); + } + //Profiler.EndSample(); + } /// /// Release the raw memory handle which is created by /// /// public static void ReleaseRawMemory(IntPtr ptr) - { - Marshal.FreeHGlobal(ptr); - } - } -} \ No newline at end of file + { + Marshal.FreeHGlobal(ptr); + } + + /// + /// Find a pointer in the next chain. Make sure the input next pointer is a OpenXR XrBaseStructure derived struct. + /// + /// + /// + /// true if exist + public static bool HasPtrInNextChain(IntPtr target, IntPtr next) + { + while (next != IntPtr.Zero) + { + if (next == target) + return true; + next = GetNext(next); + } + return false; + } + } +} diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveEnterpriseCommand.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveEnterpriseCommand.cs new file mode 100644 index 0000000..d429d13 --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveEnterpriseCommand.cs @@ -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 + + /// + /// The feature id string. This is used to give the feature a well known id for reference. + /// + public const string featureId = "vive.openxr.feature.enterprise.command"; + + /// + /// The extension string. + /// + 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; + + /// + /// Called when xrCreateInstance is done. + /// + /// The created instance. + /// True for valid XrInstance + 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); + } + + /// + /// Called when xrDestroyInstance is done. + /// + /// The instance to destroy. + protected override void OnInstanceDestroy(ulong xrInstance) + { + if (m_XrInstance == xrInstance) + { + m_XrInstanceCreated = false; + m_XrInstance = 0; + } + DEBUG($"OnInstanceDestroy() {xrInstance}"); + } + + /// + /// Called when the XrSystemId retrieved by xrGetSystem is changed. + /// + /// The system id. + protected override void OnSystemChange(ulong xrSystem) + { + m_XrSystemId = xrSystem; + DEBUG($"OnSystemChange() {m_XrSystemId}"); + } + + /// + /// Called when xrCreateSession is done. + /// + /// The created session ID. + protected override void OnSessionCreate(ulong xrSession) + { + m_XrSession = xrSession; + m_XrSessionCreated = true; + DEBUG($"OnSessionCreate() {m_XrSession}"); + } + + /// + /// Called when xrDestroySession is done. + /// + /// The session ID to destroy. + 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; + + /// + /// Enterprise command request for special functionality. + /// + /// The request of enterprise command + /// The result of enterprise command + /// Return XR_SUCCESS if request successfully. False otherwise. + 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); + } + + /// + /// Get the OpenXR function via XrInstance. + /// + /// The XrInstance is provided by the Unity OpenXR Plugin. + /// Return true if request successfully. False otherwise. + 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]; + + /// + /// Request special feature with command, it should take code and command string. + /// + /// The type of request code is integer. + /// The maximum length of request command is 256. + /// The output of result code. + /// The output of result command. + /// Return true if request successfully. False otherwise. + 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 + { + /// + /// The function delegate of xrEnterpriseCommandHTC. + /// + /// An XrSession in which the enterprise command will be active. + /// The request of enterprise command + /// The result of enterprise command + /// Return XR_SUCCESS if request successfully. False otherwise. + public delegate XrResult xrEnterpriseCommandHTCDelegate( + XrSession session, + XrEnterpriseCommandBufferHTC request, + ref XrEnterpriseCommandBufferHTC result); + } + #endregion +} diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveEnterpriseCommand.cs.meta b/com.htc.upm.vive.openxr/Runtime/Common/ViveEnterpriseCommand.cs.meta new file mode 100644 index 0000000..3783ee6 --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveEnterpriseCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d5b2125d5dc73694eaed34e97a0962e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureCommonWrapper.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureCommonWrapper.cs index d1b61ed..4c07431 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureCommonWrapper.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureCommonWrapper.cs @@ -10,9 +10,14 @@ namespace VIVE.OpenXR.Feature /// /// 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. /// - public class CommonWrapper : ViveFeatureWrapperBase, IViveFeatureWrapper + internal class CommonWrapper : ViveFeatureWrapperBase, 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 /// 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) @@ -201,7 +210,7 @@ namespace VIVE.OpenXR.Feature return XrResult.XR_ERROR_HANDLE_INVALID; } - Profiler.BeginSample("ASW: xrAcqScImg"); + Profiler.BeginSample("ASW:xrAcqScImg"); var res = XrAcquireSwapchainImage(swapchain, ref acquireInfo, out index); Profiler.EndSample(); return res; @@ -217,7 +226,7 @@ namespace VIVE.OpenXR.Feature return XrResult.XR_ERROR_HANDLE_INVALID; } - Profiler.BeginSample("ASW: xrWaitScImg"); + Profiler.BeginSample("ASW:xrWaitScImg"); var res = XrWaitSwapchainImage(swapchain, ref waitInfo); Profiler.EndSample(); return res; @@ -234,7 +243,7 @@ namespace VIVE.OpenXR.Feature } // Add Profiler - Profiler.BeginSample("ASW: xrRelScImg"); + Profiler.BeginSample("ASW:xrRelScImg"); var res = XrReleaseSwapchainImage(swapchain, ref releaseInfo); Profiler.EndSample(); return res; diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureFutureWrapper.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureFutureWrapper.cs index c433453..976cc0d 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureFutureWrapper.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureFutureWrapper.cs @@ -17,6 +17,8 @@ namespace VIVE.OpenXR.Feature /// public class FutureWrapper : ViveFeatureWrapperBase, 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; diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureSpaceWrapper.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureSpaceWrapper.cs index 845325e..cbe32b5 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureSpaceWrapper.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveFeatureSpaceWrapper.cs @@ -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 /// public class SpaceWrapper : ViveFeatureWrapperBase, 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; } + /// + /// + /// + /// + /// + /// + /// + /// + 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; + } + /// /// 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; } diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptors.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptors.cs index cab9508..62d5a80 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptors.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptors.cs @@ -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; } + + /// + /// Set this function to handle the hook process in + /// + /// The hooked openxr function name + public HookHandlerAttribute(string xrFuncName) + { + this.xrFuncName = xrFuncName; + } + } + /// /// 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,7 +38,16 @@ namespace VIVE.OpenXR /// return ViveInterceptors.Instance.HookGetInstanceProcAddr(func); /// } /// - partial class ViveInterceptors + + // 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"; static StringBuilder m_sb = null; @@ -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 interceptors = new Dictionary(); - [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(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(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(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(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(func); + Log.D(TAG, "registering our own xrGetInstanceProcAddr"); + XrGetInstanceProcAddrOriginal = Marshal.GetDelegateForFunctionPointer(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 /// public void AddRequiredFunction(string name) { - if (requiredFunctions.Contains(name)) return; - Debug.Log($"{TAG}: AddRequiredFunction({name})"); - requiredFunctions.Add(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++; + } + + /// + /// 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. + /// + /// + 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); + } } } } diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsBeginSession.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsBeginSession.cs index a19cf48..58699ae 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsBeginSession.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsBeginSession.cs @@ -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(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); } } -} \ No newline at end of file +} diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsLocateView.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsLocateView.cs new file mode 100644 index 0000000..7925947 --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsLocateView.cs @@ -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(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; + } + + /// + /// If you return false, the original function will not be called. + /// + /// + public delegate bool DelegateXrLocateViewsInterceptor(XrSession session, IntPtr viewLocateInfo, IntPtr viewState, uint viewCapacityInput, ref uint viewCountOutput, IntPtr views); + + /// + /// Use this to intercept the original function. This will be called before the original function. + /// + public DelegateXrLocateViewsInterceptor BeforeOriginalLocateViews; + + /// + /// Use this to intercept the original function. This will be called after the original function. + /// + public DelegateXrLocateViewsInterceptor AfterOriginalLocateViews; + } +} diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsLocateView.cs.meta b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsLocateView.cs.meta new file mode 100644 index 0000000..1fbdf19 --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsLocateView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5dfd24c69475c3740975bf5538de3869 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsPollEvent.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsPollEvent.cs index 0489911..dee4c48 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsPollEvent.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsPollEvent.cs @@ -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(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(); diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsSubmit.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsSubmit.cs index b72353d..090b519 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsSubmit.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsSubmit.cs @@ -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(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)) - { - Profiler.EndSample(); + 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; @@ -86,4 +101,4 @@ namespace VIVE.OpenXR } #endif } -} \ No newline at end of file +} diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsVisibilityMask.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsVisibilityMask.cs new file mode 100644 index 0000000..3a5a7a4 --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsVisibilityMask.cs @@ -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(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; + } + + /// + /// If you return false, the original function will not be called. + /// + /// + /// + /// + /// + public delegate bool DelegateXrGetVisibilityMaskKHRInterceptor(XrSession session, XrViewConfigurationType viewConfigurationType, uint viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, ref XrVisibilityMaskKHR visibilityMask, ref XrResult result); + + /// + /// Use this to intercept the original function. This will be called before the original function. + /// + public DelegateXrGetVisibilityMaskKHRInterceptor BeforeOriginalGetVisibilityMaskKHR; + + /// + /// Use this to intercept the original function. This will be called after the original function. + /// + public DelegateXrGetVisibilityMaskKHRInterceptor AfterOriginalGetVisibilityMaskKHR; + } +} diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsVisibilityMask.cs.meta b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsVisibilityMask.cs.meta new file mode 100644 index 0000000..a8ea42f --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsVisibilityMask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4c00b0b7df78d34d89cd728c9de0672 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsWaitFrame.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsWaitFrame.cs index 2d49ea2..45f89e0 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsWaitFrame.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveInterceptorsWaitFrame.cs @@ -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(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. /// public DelegateXrWaitFrameInterceptor AfterOriginalWaitFrame; - #endregion XRWaitFrame } } diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs new file mode 100644 index 0000000..2f9393c --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs @@ -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. + + /// + /// Not show in Standalone + /// + 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 + } + + /// + /// Not show in Standalone + /// + 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 + } + + /// + /// Not show in Standalone + /// + 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 + } + + /// + /// Not show in Standalone + /// + 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 + } + + /// + /// Not show in Standalone + /// + 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 + } + + /// + /// Not show in Standalone + /// + 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 + } + } +} \ No newline at end of file diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs.meta b/com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs.meta new file mode 100644 index 0000000..eaa3ba7 --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveLog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9750d8d4e8eb4994088534cb111510d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Runtime/Common/ViveRenderThreadTask.cs b/com.htc.upm.vive.openxr/Runtime/Common/ViveRenderThreadTask.cs index 4c85f8c..1ecd520 100644 --- a/com.htc.upm.vive.openxr/Runtime/Common/ViveRenderThreadTask.cs +++ b/com.htc.upm.vive.openxr/Runtime/Common/ViveRenderThreadTask.cs @@ -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,12 +102,13 @@ namespace VIVE.OpenXR.Common.RenderThread /// The queueSize should be the double count of message you want to pass to render thread in one frame. /// /// - public PreAllocatedQueue(int queueSize = 2) : base() { - for (int i = 0; i < queueSize; i++) + public PreAllocatedQueue(int queueSize = 2) : base() + { + for (int i = 0; i < queueSize; i++) { - list.Add(null); - } - } + list.Add(null); + } + } private int Next(int value) { @@ -154,7 +156,7 @@ namespace VIVE.OpenXR.Common.RenderThread /// After use the Message, call Release() to the message. /// /// - public Message Dequeue() + public Message Dequeue() { // No lock protection here. If list is not change size, it is safe. // However if list changed size, it is safe in most case. @@ -163,12 +165,12 @@ namespace VIVE.OpenXR.Common.RenderThread } } - /// - /// RenderThreadTask class is used to execute specified tasks on the rendering thread. - /// You don't need to develop a native function to run your task on the rendering thread. - /// And you don't need to design how to pass data to render thread. - /// This class can be run in Unity Editor since Unity 2021. Test your code in Unity Editor can save your time. - /// + /// + /// RenderThreadTask class is used to execute specified tasks on the rendering thread. + /// You don't need to develop a native function to run your task on the rendering thread. + /// And you don't need to design how to pass data to render thread. + /// This class can be run in Unity Editor since Unity 2021. Test your code in Unity Editor can save your time. + /// /// You should only create RenderThreadTask as static readonly. Do not create RenderThreadTask in dynamic. /// /// You should not run Unity.Engine code in RenderThread. It will cause the Unity.Engine to hang. @@ -177,8 +179,8 @@ namespace VIVE.OpenXR.Common.RenderThread /// /// The 'lock' expression is not used here. Because I believe the lock is not necessary in this case. /// And the lock will cause the performance issue. All the design here help you not to use 'lock'. - /// - public class RenderThreadTask + /// + public class RenderThreadTask { private static IntPtr GetFunctionPointerForDelegate(Delegate del) { @@ -208,20 +210,21 @@ namespace VIVE.OpenXR.Common.RenderThread /// The callback in render thread. /// If issue this event once in a frame, set queueSize as 2. /// - public RenderThreadTask(Receiver render, int queueSize = 2) - { - queue = new PreAllocatedQueue(queueSize); - receiver = render; - if (receiver == null) - throw new ArgumentNullException("receiver should not be null"); - - CommandList.Add(this); - id = CommandList.IndexOf(this); - } - - ~RenderThreadTask() + public RenderThreadTask(Receiver render, int queueSize = 2) { - try { CommandList.RemoveAt(id); } finally { } + queue = new PreAllocatedQueue(queueSize); + receiver = render; + if (receiver == null) + throw new ArgumentNullException("receiver should not be null"); + + CommandList.Add(this); + id = CommandList.IndexOf(this); + } + + ~RenderThreadTask() + { + // 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) @@ -282,30 +285,36 @@ namespace VIVE.OpenXR.Common.RenderThread // Use static readonly to create RenderThreadTask. Keep internal to avoid miss use by other developers. internal static readonly RenderThreadTask sampleRenderThreadTask1 = new RenderThreadTask(SampleReceiver1); // Different task use different RenderThreadTask and different recevier. - internal static readonly RenderThreadTask sampleRenderThreadTask2 = new RenderThreadTask(SampleReceiver2); + internal static readonly RenderThreadTask sampleRenderThreadTask2 = new RenderThreadTask(SampleReceiver2); - private static void SampleReceiver1(PreAllocatedQueue dataQueue) + 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. - // 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); + 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; - var data = msg.dataPassedToRenderThread; - MessagePool.Release(msg); - Debug.Log("Task2, 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() + // Send a message to the render thread every frame. + private void Update() { // Make sure only one kind of message object is used in the queue. var msg = sampleRenderThreadTask1.Queue.Obtain(); @@ -318,12 +327,12 @@ namespace VIVE.OpenXR.Common.RenderThread public void OnClicked() { // Reuse the same message type is ok. - var msg = sampleRenderThreadTask2.Queue.Obtain(); - msg.dataPassedToRenderThread = 234; - sampleRenderThreadTask2.Queue.Enqueue(msg); - sampleRenderThreadTask2.IssueEvent(); - } - } + var msg = sampleRenderThreadTask2.Queue.Obtain(); + msg.dataPassedToRenderThread = 234; + sampleRenderThreadTask2.Queue.Enqueue(msg); + sampleRenderThreadTask2.IssueEvent(); + } + } #endif #endregion } diff --git a/com.htc.upm.vive.openxr/Runtime/CompositionLayer/Scripts/CompositionLayer.cs b/com.htc.upm.vive.openxr/Runtime/CompositionLayer/Scripts/CompositionLayer.cs index ce8dda3..9d419a2 100644 --- a/com.htc.upm.vive.openxr/Runtime/CompositionLayer/Scripts/CompositionLayer.cs +++ b/com.htc.upm.vive.openxr/Runtime/CompositionLayer/Scripts/CompositionLayer.cs @@ -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(); + 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(); + 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(); + + 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(); + + 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(); + generatedUnderlayMeshFilter = generatedUnderlayMesh.AddComponent(); + 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 verts, List uv, List 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 _Tris = new List(); + List _UV = new List(); + List _Verts = new List(); + 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(); diff --git a/com.htc.upm.vive.openxr/Runtime/Editor/Interactions/ViveInteractionsEditor.cs b/com.htc.upm.vive.openxr/Runtime/Editor/Interactions/ViveInteractionsEditor.cs index 9235803..0aeff95 100644 --- a/com.htc.upm.vive.openxr/Runtime/Editor/Interactions/ViveInteractionsEditor.cs +++ b/com.htc.upm.vive.openxr/Runtime/Editor/Interactions/ViveInteractionsEditor.cs @@ -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()) diff --git a/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerEquirect.cs b/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerEquirect.cs new file mode 100644 index 0000000..b6767dd --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerEquirect.cs @@ -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); } + + /// + /// The feature id string. This is used to give the feature a well known id for reference. + /// + 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; + /// + /// The extension "XR_KHR_composition_layer_equirect" is enabled or not. + /// + public bool EquirectExtensionEnabled + { + get { return m_EquirectExtensionEnabled; } + } + + private bool m_Equirect2ExtensionEnabled = true; + /// + /// The extension "XR_KHR_composition_layer_equirect2" is enabled or not. + /// + 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); + /// + /// submit compostion layer of type equirect. + /// + 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); + /// + /// submit compostion layer of type equirect2. + /// + 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 + } +} diff --git a/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerEquirect.cs.meta b/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerEquirect.cs.meta new file mode 100644 index 0000000..7bb96f2 --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerEquirect.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec826264ff4d75d4081f2ca472a3e083 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerHelper.cs b/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerHelper.cs index d6efd44..4c8996c 100644 --- a/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerHelper.cs +++ b/com.htc.upm.vive.openxr/Runtime/Features/CompositionLayer/Scripts/ViveCompositionLayerHelper.cs @@ -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; diff --git a/com.htc.upm.vive.openxr/Runtime/Features/FrameSynchronization/Documentation/OpenXRExtensions.md b/com.htc.upm.vive.openxr/Runtime/Features/FrameSynchronization/Documentation/OpenXRExtensions.md index fb84b6a..ddfb5da 100644 --- a/com.htc.upm.vive.openxr/Runtime/Features/FrameSynchronization/Documentation/OpenXRExtensions.md +++ b/com.htc.upm.vive.openxr/Runtime/Features/FrameSynchronization/Documentation/OpenXRExtensions.md @@ -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 diff --git a/com.htc.upm.vive.openxr/Runtime/Features/Hand/Interaction/Scripts/ViveHandInteractionExt.cs b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Interaction/Scripts/ViveHandInteractionExt.cs index 30d18a5..b5bef3b 100644 --- a/com.htc.upm.vive.openxr/Runtime/Features/Hand/Interaction/Scripts/ViveHandInteractionExt.cs +++ b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Interaction/Scripts/ViveHandInteractionExt.cs @@ -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 enables the use of hand interaction profiles in OpenXR. It enables XR_EXT_hand_interaction in the underyling runtime. /// #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 diff --git a/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandProvider.cs b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandProvider.cs new file mode 100644 index 0000000..dfd294b --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandProvider.cs @@ -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> posUsageMapping = new Dictionary>(); + private Dictionary> rotUsageMapping = new Dictionary>(); + private Dictionary> valueUsageMapping = new Dictionary>(); + + public HandDevice(InputDevice device) + { + this.device = device; + + List inputFeatures = new List(); + 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()); + break; + case kFeatureAimRot: + case kFeatureGripRot: + case kFeaturePinchRot: + case kFeaturePokeRot: + rotUsageMapping.Add(feature.name, feature.As()); + break; + case kFeatureAimValue: + case kFeatureGripValue: + case kFeaturePinchValue: + valueUsageMapping.Add(feature.name, feature.As()); + 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 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 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 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 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 leftHandJoints, ref Pose rightHandRootPose, NativeArray 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 inputDevices = new List(); + 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(); + if (viveInteractions.enabled) + { + return viveInteractions.UseKhrHandInteraction(); + } + return false; + } +#endif + + private void Initialize() + { + viveHand = OpenXRSettings.Instance.GetFeature(); + } + + private bool UpdateHand(bool isLeft, ref Pose handRootPose, ref NativeArray 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 + diff --git a/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandProvider.cs.meta b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandProvider.cs.meta new file mode 100644 index 0000000..34df112 --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 68f6a3e78d49e1143a9aa0a111a04a0a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandSubsystem.cs b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandSubsystem.cs new file mode 100644 index 0000000..eb43f3f --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandSubsystem.cs @@ -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 descriptors = new List(); + 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(); + return viveHand.enabled; + } + + private static bool HandInteractionSupport() + { + ViveInteractions viveInteractions = OpenXRSettings.Instance.GetFeature(); + if (viveInteractions.enabled) + { + return viveInteractions.UseKhrHandInteraction(); + } + return false; + } + } +} +#endif \ No newline at end of file diff --git a/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandSubsystem.cs.meta b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandSubsystem.cs.meta new file mode 100644 index 0000000..05f0f6c --- /dev/null +++ b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandSubsystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ce39c25a1e4a794c807d9f723d37804 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandTracking.cs b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandTracking.cs index b2ea076..c17540d 100644 --- a/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandTracking.cs +++ b/com.htc.upm.vive.openxr/Runtime/Features/Hand/Tracking/Scripts/ViveHandTracking.cs @@ -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); - } - [MonoPInvokeCallback(typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate))] - private static XrResult intercept_xrWaitFrame_xrGetInstanceProcAddr(XrInstance instance, string name, out IntPtr function) - { - if (xrGetInstanceProcAddr_prev == null || xrGetInstanceProcAddr_prev == IntPtr.Zero) + ViveInterceptors.Instance.AddRequiredFunction("xrWaitFrame"); + if (ViveInterceptors.Instance.BeforeOriginalWaitFrame == null) { - UnityEngine.Debug.LogError("xrGetInstanceProcAddr_prev is null"); - function = IntPtr.Zero; - return XrResult.XR_ERROR_VALIDATION_FAILURE; + ViveInterceptors.Instance.BeforeOriginalWaitFrame = new ViveInterceptors.DelegateXrWaitFrameInterceptor(BeforeWaitFrame); + } + else + { + ViveInterceptors.Instance.BeforeOriginalWaitFrame += BeforeWaitFrame; } - // Get delegate of old xrGetInstanceProcAddr. - var xrGetProc = Marshal.GetDelegateForFunctionPointer(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); } - - return result; - + else + { + ViveInterceptors.Instance.AfterOriginalWaitFrame += AfterWaitFrame; + } + return ViveInterceptors.Instance.HookGetInstanceProcAddr(func); } - [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(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 visited = new HashSet(); + 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(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; } /// @@ -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; } /// diff --git a/com.htc.upm.vive.openxr/Runtime/Features/Passthrough/Scripts/VivePassthrough.cs b/com.htc.upm.vive.openxr/Runtime/Features/Passthrough/Scripts/VivePassthrough.cs index 1de5a92..516df0a 100644 --- a/com.htc.upm.vive.openxr/Runtime/Features/Passthrough/Scripts/VivePassthrough.cs +++ b/com.htc.upm.vive.openxr/Runtime/Features/Passthrough/Scripts/VivePassthrough.cs @@ -10,7 +10,9 @@ using UnityEngine.XR.OpenXR; using UnityEngine.XR.OpenXR.Features; using UnityEngine; using UnityEngine.XR; -using AOT; +using VIVE.OpenXR.CompositionLayer; +using UnityEngine.Profiling; +using VIVE.OpenXR.Feature; #if UNITY_EDITOR using UnityEditor.XR.OpenXR.Features; @@ -18,6 +20,254 @@ using UnityEditor.XR.OpenXR.Features; namespace VIVE.OpenXR.Passthrough { + public class PassthroughLayer : IDisposable + { + private XrPassthroughHTC xrHandle = 0; + private XrCompositionLayerPassthroughHTC layer; + private IntPtr layerPtr = IntPtr.Zero; + private XrPassthroughMeshTransformInfoHTC meshTransform; + private bool needMesh = false; + private IntPtr meshPtr = IntPtr.Zero; + private CompositionLayer.LayerType layerType = CompositionLayer.LayerType.Underlay; + private bool disposedValue = false; + private IntPtr verticesPtr = IntPtr.Zero; + private IntPtr indicesPtr = IntPtr.Zero; + private int depth = 0; + + public bool NeedMesh { get => needMesh; set => needMesh = value; } + public CompositionLayer.LayerType LayerType { get => layerType; set => layerType = value; } + public int Depth { get => depth; set => depth = value; } + + public PassthroughLayer(XrPassthroughHTC xrHandle, CompositionLayer.LayerType layerType) + { + this.xrHandle = xrHandle; + this.layerType = layerType; + + layer = new XrCompositionLayerPassthroughHTC(); + layerPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrCompositionLayerPassthroughHTC))); + + meshTransform = new XrPassthroughMeshTransformInfoHTC(); + meshPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrPassthroughMeshTransformInfoHTC))); + } + + public PassthroughLayer() + { + layer = new XrCompositionLayerPassthroughHTC(); + layerPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrCompositionLayerPassthroughHTC))); + + meshTransform = new XrPassthroughMeshTransformInfoHTC(); + meshPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrPassthroughMeshTransformInfoHTC))); + } + + public void SetLayer(XrCompositionLayerPassthroughHTC layer) + { + this.layer = layer; + } + + public static XrCompositionLayerPassthroughHTC MakeEmptyLayer() + { + XrPassthroughColorHTC passthroughColor = new XrPassthroughColorHTC(in_alpha: 0); + XrCompositionLayerPassthroughHTC compositionLayerPassthrough = new XrCompositionLayerPassthroughHTC( + in_layerFlags: (UInt64)XrCompositionLayerFlagBits.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT, + in_space: 0, + in_passthrough: 0, + in_color: passthroughColor); + + return compositionLayerPassthrough; + } + + public XrCompositionLayerPassthroughHTC GetLayer() + { + return layer; + } + + /// + /// Never null unless disposed. + /// + /// + public IntPtr GetLayerPtr() + { + return layerPtr; + } + + /// + /// Before SetMeshTransform, you should call SetLayer first. + /// + /// + /// + public void SetMeshTransform(XrPassthroughMeshTransformInfoHTC meshTransform, bool needMesh = true) + { + this.meshTransform = meshTransform; + NeedMesh = needMesh; + } + + public static XrPassthroughMeshTransformInfoHTC MakeMeshTransform() + { + return new XrPassthroughMeshTransformInfoHTC() + { + type = XrStructureType.XR_TYPE_PASSTHROUGH_MESH_TRANSFORM_INFO_HTC, + next = IntPtr.Zero, + vertexCount = 0, + vertices = IntPtr.Zero, + indexCount = 0, + indices = IntPtr.Zero, + baseSpace = 0, + time = 0, + pose = XrPosef.Identity, + scale = XrVector3f.One, + }; + } + + public bool SetMeshData(ref XrPassthroughMeshTransformInfoHTC mesh, Vector3[] vertices, int[] indices, bool convertFromUnityToOpenXR = true) + { + if (vertices.Length < 3 || indices.Length % 3 != 0) //Must have at least 3 vertices and complete triangles + { + Debug.LogError("PassthroughLayer: Mesh data invalid."); + return false; + } + + // check our vertex buffer and index buffer + if (verticesPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(verticesPtr); + verticesPtr = IntPtr.Zero; + } + + if (indicesPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(indicesPtr); + indicesPtr = IntPtr.Zero; + } + + verticesPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(XrVector3f)) * vertices.Length); + indicesPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint)) * indices.Length); + + XrVector3f[] xrVertices = new XrVector3f[vertices.Length]; + for (int i = 0; i < vertices.Length; i++) + { + xrVertices[i] = OpenXRHelper.ToOpenXRVector(vertices[i], convertFromUnityToOpenXR); + } + + uint[] indicesUint = new uint[indices.Length]; + // Unity is contrary to OpenXR in the order of the vertices in the triangle. + for (int i = 0; i < indices.Length; i += 3) + { + indicesUint[i] = (uint)indices[i]; + indicesUint[i + 1] = (uint)indices[i + 2]; + indicesUint[i + 2] = (uint)indices[i + 1]; + } + + MemoryTools.CopyToRawMemory(verticesPtr, xrVertices); + MemoryTools.CopyToRawMemory(indicesPtr, indicesUint); + + mesh.vertexCount = (uint)vertices.Length; + mesh.vertices = verticesPtr; + + mesh.indexCount = (uint)indices.Length; + mesh.indices = indicesPtr; + + return true; + } + + /// + /// Copy to native buffer + /// + public void ToNativeBuffer() + { + if (layerPtr == IntPtr.Zero) + return; + + if (NeedMesh) + { + layer.next = meshPtr; + MemoryTools.StructureToPtr(meshTransform, meshPtr); + MemoryTools.StructureToPtr(layer, layerPtr); + } + else + { + if (layer.next != IntPtr.Zero) + layer.next = IntPtr.Zero; + MemoryTools.StructureToPtr(layer, layerPtr); + } + } + + public XrPassthroughMeshTransformInfoHTC GetMesh() + { + return meshTransform; + } + + public IntPtr GetMeshTransformPtr() + { + return meshPtr; + } + + public bool IsOverlay() + { + return layerType == CompositionLayer.LayerType.Overlay; + } + + public bool IsUnderlay() + { + return layerType == CompositionLayer.LayerType.Underlay; + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + xrHandle = 0; + } + + if (layerPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(layerPtr); + layerPtr = IntPtr.Zero; + } + + if (meshPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(meshPtr); + meshPtr = IntPtr.Zero; + } + + if (verticesPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(verticesPtr); + verticesPtr = IntPtr.Zero; + } + + if (indicesPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(indicesPtr); + indicesPtr = IntPtr.Zero; + } + + disposedValue = true; + } + } + + ~PassthroughLayer() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: false); + } + + void IDisposable.Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + internal void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } + #if UNITY_EDITOR [OpenXRFeature(UiName = "VIVE XR Passthrough", Desc = "Enable this feature to use the VIVE OpenXR Passthrough feature.", @@ -32,18 +282,15 @@ namespace VIVE.OpenXR.Passthrough public class VivePassthrough : OpenXRFeature { #region LOG - const string LOG_TAG = "VIVE.OpenXR.Passthrough.VivePassthrough"; - StringBuilder m_sb = null; - StringBuilder sb { + const string TAG = "VivePassthrough"; + StringBuilder sb = new StringBuilder(); + + StringBuilder CSB { get { - if (m_sb == null) { m_sb = new StringBuilder(); } - return m_sb; + return sb.Clear(); } } - static void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); } - static void DEBUG(StringBuilder msg) { Debug.LogFormat("{0} {1}", LOG_TAG, msg); } - static void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); } - static void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); } + #endregion /// @@ -56,117 +303,144 @@ namespace VIVE.OpenXR.Passthrough /// public const string kOpenxrExtensionStrings = "XR_HTC_passthrough XR_HTC_passthrough_configuration"; -#if UNITY_STANDALONE - private static IntPtr xrGetInstanceProcAddr_prev; - private static IntPtr XrEndFrame_prev; - private static IntPtr XrWaitFrame_prev; - private static List layerListOrigin = new List(); - private static List layerListModified = new List(); - private static IntPtr layersModified = Marshal.AllocHGlobal((int)(Marshal.SizeOf(typeof(IntPtr)) * 30)); //Preallocate a layer buffer with sufficient size and reuse it for each frame. + private static IntPtr[] layersOrigin = null; + private static IntPtr[] layersModified = null; + private static int sizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr)); + private static IntPtr layersModifiedPtr = Marshal.AllocHGlobal(sizeOfIntPtr * 30); //Preallocate a layer buffer with sufficient size and reuse it for each frame. + protected override IntPtr HookGetInstanceProcAddr(IntPtr func) { - UnityEngine.Debug.Log("EXT: registering our own xrGetInstanceProcAddr"); - xrGetInstanceProcAddr_prev = func; - return Marshal.GetFunctionPointerForDelegate(Intercept_xrGetInstanceProcAddr); - } - [MonoPInvokeCallback(typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate))] - private static XrResult InterceptXrEndFrame_xrGetInstanceProcAddr(XrInstance instance, string name, out IntPtr function) - { - if (xrGetInstanceProcAddr_prev == null || xrGetInstanceProcAddr_prev == IntPtr.Zero) - { - UnityEngine.Debug.LogError("xrGetInstanceProcAddr_prev is null"); - function = IntPtr.Zero; - return XrResult.XR_ERROR_VALIDATION_FAILURE; - } + var interceptors = ViveInterceptors.Instance; + interceptors.AddRequiredFunction("xrWaitFrame"); + interceptors.AddRequiredFunction("xrEndFrame"); - // Get delegate of old xrGetInstanceProcAddr. - var xrGetProc = Marshal.GetDelegateForFunctionPointer(xrGetInstanceProcAddr_prev); - XrResult result = xrGetProc(instance, name, out function); - if (name == "xrEndFrame") - { - XrEndFrame_prev = function; - m_intercept_xrEndFrame = intercepted_xrEndFrame; - function = Marshal.GetFunctionPointerForDelegate(m_intercept_xrEndFrame); ; - UnityEngine.Debug.Log("Getting xrEndFrame func"); - } - if (name == "xrWaitFrame") - { - XrWaitFrame_prev = function; - m_intercept_xrWaitFrame = intercepted_xrWaitFrame; - function = Marshal.GetFunctionPointerForDelegate(m_intercept_xrWaitFrame); ; - UnityEngine.Debug.Log("Getting xrWaitFrame func"); - } - return result; + return interceptors.HookGetInstanceProcAddr(func); } - [MonoPInvokeCallback(typeof(OpenXRHelper.xrEndFrameDelegate))] - private static XrResult intercepted_xrEndFrame(XrSession session, ref XrFrameEndInfo frameEndInfo) + struct XrCompositionLayerProjection { - XrResult res; - // Get delegate of prev xrEndFrame. - var xrEndFrame = Marshal.GetDelegateForFunctionPointer(XrEndFrame_prev); + public XrStructureType type; + public IntPtr next; + public XrCompositionLayerFlags layerFlags; + public XrSpace space; + public uint viewCount; + public IntPtr views; + } + + + private void ForceProjectionLayerTransparent(IntPtr[] layersPtr) + { + // Find the projection layer in freameEndInfo + int projIndex = -1; + IntPtr projLayerPtr = IntPtr.Zero; + for (int i = 0; i < layersPtr.Length; i++) + { + projLayerPtr = layersPtr[i]; + if (MemoryTools.GetType(projLayerPtr) == XrStructureType.XR_TYPE_COMPOSITION_LAYER_PROJECTION) + { + projIndex = i; + break; + } + } + + // No projection layer found. + if (projIndex == -1) + Debug.Log("No projection layer"); + + // Force projection layer accept transparent + XrCompositionLayerProjection xrProjLayer = default; + MemoryTools.PtrToStructure(projLayerPtr, ref xrProjLayer); + xrProjLayer.layerFlags |= ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT; + MemoryTools.StructureToPtr(xrProjLayer, projLayerPtr); + } + + private bool OnBeforeEndFrame(XrSession session, ref ViveInterceptors.XrFrameEndInfo frameEndInfo, ref XrResult result) + { + // It is possible that the layerCount is 0, so we need to check it. + if (frameEndInfo.layerCount == 0 || ptLayers == null || ptLayers.Count == 0) + return true; - layerListOrigin.Clear(); uint layerCount = frameEndInfo.layerCount; - IntPtr layers = frameEndInfo.layers; - for (int i = 0; i < layerCount; i++) - { - IntPtr ptr = Marshal.ReadIntPtr(layers, i * Marshal.SizeOf(typeof(IntPtr))); - XrCompositionLayerBaseHeader header = (XrCompositionLayerBaseHeader)Marshal.PtrToStructure(ptr, typeof(XrCompositionLayerBaseHeader)); - layerListOrigin.Add(ptr); - } - List layerListNew; - if (layerListModified.Count != 0) - { - layerListNew = new List(layerListModified); - } - else - { - layerListNew = new List(layerListOrigin); - } - for (int i = 0; i < layerListNew.Count; i++) - { - Marshal.WriteIntPtr(layersModified, i * Marshal.SizeOf(typeof(IntPtr)), layerListNew[i]); - } - frameEndInfo.layers = layersModified; - frameEndInfo.layerCount = (uint)layerListNew.Count; - res = xrEndFrame(session, ref frameEndInfo); - return res; - } - private static XrFrameWaitInfo m_frameWaitInfo; - private static XrFrameState m_frameState; - [MonoPInvokeCallback(typeof(OpenXRHelper.xrWaitFrameDelegate))] - private static int intercepted_xrWaitFrame(ulong session, ref XrFrameWaitInfo frameWaitInfo, ref XrFrameState frameState) - { - var xrWaitFrame = Marshal.GetDelegateForFunctionPointer(XrWaitFrame_prev); - int res = xrWaitFrame(session, ref frameWaitInfo, ref frameState); - m_frameWaitInfo = frameWaitInfo; - m_frameState = frameState; - return res; - } - public void GetOriginEndFrameLayerList(out List layers) - { - layers = new List(layerListOrigin); + Profiler.BeginSample("Pt"); + + // Make all layers to array + if (layersOrigin == null || layersOrigin.Length != layerCount) + layersOrigin = new IntPtr[layerCount]; + MemoryTools.CopyAllFromRawMemory(layersOrigin, frameEndInfo.layers); + + // Insert our layers into layersOrigin + // Total passthough layers count + var finalCount = ptLayers.Count + layerCount; + if (layersModified == null || layersModified.Length != finalCount) + layersModified = new IntPtr[finalCount]; + + int j = 0; + bool hasUnderlay = false; + // Insert underlay + for (int i = 0; i < ptLayers.Count; i++) + { + if (ptLayers[i].IsUnderlay()) + { + ptLayers[i].ToNativeBuffer(); + var ptr = ptLayers[i].GetLayerPtr(); + if (ptr != IntPtr.Zero) + layersModified[j++] = ptr; + hasUnderlay = true; + } + } + if (hasUnderlay) + ForceProjectionLayerTransparent(layersOrigin); + + // put original layers into layersModified + for (int i = 0; i < layersOrigin.Length; i++) + { + layersModified[j++] = layersOrigin[i]; + } + + // Append overlay + for (int i = 0; i < ptLayers.Count; i++) + { + if (ptLayers[i].IsOverlay()) + { + ptLayers[i].ToNativeBuffer(); + var ptr = ptLayers[i].GetLayerPtr(); + if (ptr != IntPtr.Zero) + layersModified[j++] = ptr; + } + } + + MemoryTools.CopyToRawMemory(layersModifiedPtr, layersModified); + + // Change original layers + frameEndInfo.layers = layersModifiedPtr; + frameEndInfo.layerCount = (uint)layersModified.Length; + + Profiler.EndSample(); + + return true; } - public void SubmitLayers(List layers) + List ptLayers = null; + + /// + /// Call this function in game thread + /// + /// passthrough layers + public void SubmitLayers(List layers) { - layerListModified = new List(layers); - //UnityEngine.Debug.Log("####Update submit end " + layerListModified.Count); + ptLayers = layers; } + public XrFrameState GetFrameState() { - return m_frameState; + var frameState = ViveInterceptors.Instance.GetCurrentFrameState(); + return new XrFrameState() { + predictedDisplayTime = frameState.predictedDisplayTime, + predictedDisplayPeriod = frameState.predictedDisplayPeriod, + shouldRender = frameState.shouldRender + }; } -#endif -#if UNITY_ANDROID - protected override IntPtr HookGetInstanceProcAddr(IntPtr func) - { - ViveInterceptors.Instance.AddRequiredFunction("xrPollEvent"); - return ViveInterceptors.Instance.HookGetInstanceProcAddr(func); - } -#endif #region OpenXR Life Cycle private bool m_XrInstanceCreated = false; @@ -180,35 +454,50 @@ namespace VIVE.OpenXR.Passthrough private XrInstance m_XrInstance = 0; protected override bool OnInstanceCreate(ulong xrInstance) { + Log.D(TAG, "OnInstanceCreate() " + m_XrInstance); foreach (string kOpenxrExtensionString in kOpenxrExtensionStrings.Split(' ')) { if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString)) { - WARNING("OnInstanceCreate() " + kOpenxrExtensionString + " is NOT enabled."); + Log.W(TAG, "OnInstanceCreate() " + kOpenxrExtensionString + " is NOT enabled."); } else { - DEBUG("OnInstanceCreate() " + kOpenxrExtensionString + " is enabled."); + Log.I(TAG, "OnInstanceCreate() " + kOpenxrExtensionString + " is enabled."); } } + SpaceWrapper.Instance.OnInstanceCreate(xrInstance, xrGetInstanceProcAddr); + CommonWrapper.Instance.OnInstanceCreate(xrInstance, xrGetInstanceProcAddr); + bool ret = GetXrFunctionDelegates(xrInstance); + if (!ret) + return ret; + m_XrInstanceCreated = true; m_XrInstance = xrInstance; - DEBUG("OnInstanceCreate() " + m_XrInstance); + ViveInterceptors.Instance.BeforeOriginalEndFrame += OnBeforeEndFrame; - return GetXrFunctionDelegates(m_XrInstance); + return ret; } protected override void OnInstanceDestroy(ulong xrInstance) { + if (m_XrInstanceCreated) + { + ViveInterceptors.Instance.BeforeOriginalEndFrame -= OnBeforeEndFrame; + + CommonWrapper.Instance.OnInstanceDestroy(); + SpaceWrapper.Instance.OnInstanceDestroy(); + } + m_XrInstanceCreated = false; - DEBUG("OnInstanceDestroy() " + m_XrInstance); + Log.D(TAG, "OnInstanceDestroy() " + m_XrInstance); } private XrSystemId m_XrSystemId = 0; protected override void OnSystemChange(ulong xrSystem) { m_XrSystemId = xrSystem; - DEBUG("OnSystemChange() " + m_XrSystemId); + Log.D(TAG, "OnSystemChange() " + m_XrSystemId); } private bool m_XrSessionCreated = false; @@ -224,7 +513,7 @@ namespace VIVE.OpenXR.Passthrough { m_XrSession = xrSession; m_XrSessionCreated = true; - DEBUG("OnSessionCreate() " + m_XrSession); + Log.I(TAG, "OnSessionCreate() " + m_XrSession); CheckConfigurationSupport(); } @@ -253,23 +542,25 @@ namespace VIVE.OpenXR.Passthrough protected override void OnSessionBegin(ulong xrSession) { m_XrSessionEnding = false; - DEBUG("OnSessionBegin() " + m_XrSession); + Log.D(TAG, "OnSessionBegin() " + m_XrSession); // Enumerate supported reference space types and create the XrSpace. - XrReferenceSpaceType[] spaces = new XrReferenceSpaceType[Enum.GetNames(typeof(XrReferenceSpaceType)).Count()]; - UInt32 spaceCountOutput; - if (EnumerateReferenceSpaces( + XrReferenceSpaceType[] spaces = null;// new XrReferenceSpaceType[Enum.GetNames(typeof(XrReferenceSpaceType)).Count()]; + int spaceCountOutput = 0; + if (SpaceWrapper.Instance.EnumerateReferenceSpaces( + xrSession, spaceCapacityInput: 0, - spaceCountOutput: out spaceCountOutput, - spaces: out spaces[0]) == XrResult.XR_SUCCESS) + spaceCountOutput: ref spaceCountOutput, + spaces: ref spaces) == XrResult.XR_SUCCESS) { - //DEBUG("spaceCountOutput: " + spaceCountOutput); + //Log.I(TAG, "spaceCountOutput: " + spaceCountOutput); Array.Resize(ref spaces, (int)spaceCountOutput); - if (EnumerateReferenceSpaces( + if (SpaceWrapper.Instance.EnumerateReferenceSpaces( + xrSession, spaceCapacityInput: spaceCountOutput, - spaceCountOutput: out spaceCountOutput, - spaces: out spaces[0]) == XrResult.XR_SUCCESS) + spaceCountOutput: ref spaceCountOutput, + spaces: ref spaces) == XrResult.XR_SUCCESS) { if (spaces.Contains(XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_LOCAL)) { @@ -280,20 +571,21 @@ namespace VIVE.OpenXR.Passthrough referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1); referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.position = new XrVector3f(0, 0, 0); - if (CreateReferenceSpace( - createInfo: ref referenceSpaceCreateInfoWorldLock, - space: out m_WorldLockSpaceOriginOnHead) == XrResult.XR_SUCCESS) + if (SpaceWrapper.Instance.CreateReferenceSpace( + xrSession, + createInfo: referenceSpaceCreateInfoWorldLock, + space: out m_WorldLockSpaceOriginOnHead) == XrResult.XR_SUCCESS) { - //DEBUG("CreateReferenceSpace: " + m_WorldLockSpaceOriginOnHead); + //Log.I(TAG, "CreateReferenceSpace: " + m_WorldLockSpaceOriginOnHead); } else { - ERROR("CreateReferenceSpace for world lock layers on head failed."); + Log.E(TAG, "CreateReferenceSpace for world lock layers on head failed."); } } else { - ERROR("CreateReferenceSpace no space type for world lock on head layers."); + Log.E(TAG, "CreateReferenceSpace no space type for world lock on head layers."); } if (spaces.Contains(XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_STAGE)) @@ -305,20 +597,21 @@ namespace VIVE.OpenXR.Passthrough referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1); referenceSpaceCreateInfoWorldLock.poseInReferenceSpace.position = new XrVector3f(0, 0, 0); - if (CreateReferenceSpace( - createInfo: ref referenceSpaceCreateInfoWorldLock, - space: out m_WorldLockSpaceOriginOnFloor) == XrResult.XR_SUCCESS) + if (SpaceWrapper.Instance.CreateReferenceSpace( + xrSession, + createInfo: referenceSpaceCreateInfoWorldLock, + space: out m_WorldLockSpaceOriginOnFloor) == XrResult.XR_SUCCESS) { - //DEBUG("CreateReferenceSpace: " + m_WorldLockSpaceOriginOnFloor); + //Log.I(TAG, "CreateReferenceSpace: " + m_WorldLockSpaceOriginOnFloor); } else { - ERROR("CreateReferenceSpace for world lock layers on floor failed."); + Log.E(TAG, "CreateReferenceSpace for world lock layers on floor failed."); } } else { - ERROR("CreateReferenceSpace no space type for world lock on floor layers."); + Log.E(TAG, "CreateReferenceSpace no space type for world lock on floor layers."); } if (spaces.Contains(XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_VIEW)) @@ -330,36 +623,37 @@ namespace VIVE.OpenXR.Passthrough referenceSpaceCreateInfoHeadLock.poseInReferenceSpace.orientation = new XrQuaternionf(0, 0, 0, 1); referenceSpaceCreateInfoHeadLock.poseInReferenceSpace.position = new XrVector3f(0, 0, 0); - if (CreateReferenceSpace( - createInfo: ref referenceSpaceCreateInfoHeadLock, - space: out m_HeadLockSpace) == XrResult.XR_SUCCESS) + if (SpaceWrapper.Instance.CreateReferenceSpace( + xrSession, + createInfo: referenceSpaceCreateInfoHeadLock, + space: out m_HeadLockSpace) == XrResult.XR_SUCCESS) { - //DEBUG("CreateReferenceSpace: " + m_HeadLockSpace); + //Log.I(TAG, "CreateReferenceSpace: " + m_HeadLockSpace); } else { - ERROR("CreateReferenceSpace for head lock layers failed."); + Log.E(TAG, "CreateReferenceSpace for head lock layers failed."); } } else { - ERROR("CreateReferenceSpace no space type for head lock layers."); + Log.E(TAG, "CreateReferenceSpace no space type for head lock layers."); } } else { - ERROR("EnumerateReferenceSpaces(" + spaceCountOutput + ") failed."); + Log.E(TAG, "EnumerateReferenceSpaces(" + spaceCountOutput + ") failed."); } } else { - ERROR("EnumerateReferenceSpaces(0) failed."); + Log.E(TAG, "EnumerateReferenceSpaces(0) failed."); } } protected override void OnSessionEnd(ulong xrSession) { m_XrSessionEnding = true; - DEBUG("OnSessionEnd() " + m_XrSession); + Log.D(TAG, "OnSessionEnd() " + m_XrSession); } /// @@ -371,7 +665,7 @@ namespace VIVE.OpenXR.Passthrough { if (!m_XrSessionCreated || m_XrSession != xrSession) { return; } - sb.Clear().Append("OnSessionDestroy() " + xrSession); DEBUG(sb); + Log.D(TAG, CSB.Append("OnSessionDestroy() " + xrSession)); m_XrSessionCreated = false; m_XrSession = 0; @@ -382,24 +676,24 @@ namespace VIVE.OpenXR.Passthrough DestroyPassthroughHTC(currentpassthrough); if (OnPassthroughSessionDestroyHandlerDictionary.ContainsKey(currentpassthrough) && OnPassthroughSessionDestroyHandlerDictionary[currentpassthrough] != null) { - sb.Clear().Append("OnSessionDestroy() Call back ").Append(passthroughs[i]); DEBUG(sb); + Log.D(TAG, CSB.Append("OnSessionDestroy() Call back ").Append(passthroughs[i])); OnPassthroughSessionDestroyHandlerDictionary[passthroughs[i]].Invoke(passthroughs[i]); } } if (m_HeadLockSpace != 0) { - DestroySpace(m_HeadLockSpace); + SpaceWrapper.Instance.DestroySpace(m_HeadLockSpace); m_HeadLockSpace = 0; } if (m_WorldLockSpaceOriginOnFloor != 0) { - DestroySpace(m_WorldLockSpaceOriginOnFloor); + SpaceWrapper.Instance.DestroySpace(m_WorldLockSpaceOriginOnFloor); m_WorldLockSpaceOriginOnFloor = 0; } if (m_WorldLockSpaceOriginOnHead != 0) { - DestroySpace(m_WorldLockSpaceOriginOnHead); + SpaceWrapper.Instance.DestroySpace(m_WorldLockSpaceOriginOnHead); m_WorldLockSpaceOriginOnHead = 0; } } @@ -415,7 +709,7 @@ namespace VIVE.OpenXR.Passthrough private XrSessionState m_XrSessionOldState = XrSessionState.XR_SESSION_STATE_UNKNOWN; protected override void OnSessionStateChange(int oldState, int newState) { - DEBUG("OnSessionStateChange() oldState: " + oldState + " newState:" + newState); + Log.D(TAG, "OnSessionStateChange() oldState: " + oldState + " newState:" + newState); if (Enum.IsDefined(typeof(XrSessionState), oldState)) { @@ -423,7 +717,7 @@ namespace VIVE.OpenXR.Passthrough } else { - DEBUG("OnSessionStateChange() oldState undefined"); + Log.I(TAG, "OnSessionStateChange() oldState undefined"); } if (Enum.IsDefined(typeof(XrSessionState), newState)) @@ -432,7 +726,7 @@ namespace VIVE.OpenXR.Passthrough } else { - DEBUG("OnSessionStateChange() newState undefined"); + Log.I(TAG, "OnSessionStateChange() newState undefined"); } } @@ -441,77 +735,8 @@ namespace VIVE.OpenXR.Passthrough #region OpenXR function delegates /// xrGetInstanceProcAddr OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr; - - /// xrGetSystemProperties - OpenXRHelper.xrGetSystemPropertiesDelegate xrGetSystemProperties; - /// - /// Helper function to get this feature' properties. - /// See xrGetSystemProperties - /// - public XrResult GetSystemProperties(ref XrSystemProperties properties) - { - if (m_XrInstanceCreated) - { - return xrGetSystemProperties(m_XrInstance, m_XrSystemId, ref properties); - } - - return XrResult.XR_ERROR_INSTANCE_LOST; - } - -#if UNITY_STANDALONE - OpenXRHelper.xrGetInstanceProcAddrDelegate Intercept_xrGetInstanceProcAddr = - new OpenXRHelper.xrGetInstanceProcAddrDelegate(InterceptXrEndFrame_xrGetInstanceProcAddr); - - private static OpenXRHelper.xrEndFrameDelegate m_intercept_xrEndFrame; - private static OpenXRHelper.xrWaitFrameDelegate m_intercept_xrWaitFrame; - VivePassthroughHelper.xrCreatePassthroughHTCDelegate xrCreatePassthroughHTC; VivePassthroughHelper.xrDestroyPassthroughHTCDelegate xrDestroyPassthroughHTC; -#endif - - /// xrEnumerateReferenceSpaces - OpenXRHelper.xrEnumerateReferenceSpacesDelegate xrEnumerateReferenceSpaces; - private XrResult EnumerateReferenceSpaces(UInt32 spaceCapacityInput, out UInt32 spaceCountOutput, out XrReferenceSpaceType spaces) - { - if (!m_XrSessionCreated) - { - spaceCountOutput = 0; - spaces = XrReferenceSpaceType.XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT; - return XrResult.XR_ERROR_SESSION_NOT_RUNNING; - } - - return xrEnumerateReferenceSpaces(m_XrSession, spaceCapacityInput, out spaceCountOutput, out spaces); - } - - /// xrCreateReferenceSpace - OpenXRHelper.xrCreateReferenceSpaceDelegate xrCreateReferenceSpace; - /// - /// Creates a reference space - /// See xrCreateReferenceSpace - /// - private XrResult CreateReferenceSpace(ref XrReferenceSpaceCreateInfo createInfo, out XrSpace space) - { - if (!m_XrSessionCreated) - { - space = 0; - return XrResult.XR_ERROR_SESSION_NOT_RUNNING; - } - - return xrCreateReferenceSpace(m_XrSession, ref createInfo, out space); - } - - /// xrDestroySpace - OpenXRHelper.xrDestroySpaceDelegate xrDestroySpace; - private XrResult DestroySpace(XrSpace space) - { - if (space != 0) - { - return xrDestroySpace(space); - } - return XrResult.XR_ERROR_REFERENCE_SPACE_UNSUPPORTED; - } - - VivePassthroughHelper.xrEnumeratePassthroughImageRatesHTCDelegate xrEnumeratePassthroughImageRatesHTC; VivePassthroughHelper.xrGetPassthroughConfigurationHTCDelegate xrGetPassthroughConfigurationHTC; VivePassthroughHelper.xrSetPassthroughConfigurationHTCDelegate xrSetPassthroughConfigurationHTC; @@ -521,361 +746,32 @@ namespace VIVE.OpenXR.Passthrough /// xrGetInstanceProcAddr if (xrGetInstanceProcAddr != null && xrGetInstanceProcAddr != IntPtr.Zero) { - DEBUG("Get function pointer of xrGetInstanceProcAddr."); + Log.I(TAG, "Get function pointer of xrGetInstanceProcAddr."); XrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer( xrGetInstanceProcAddr, typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate)) as OpenXRHelper.xrGetInstanceProcAddrDelegate; } else { - ERROR("xrGetInstanceProcAddr"); + Log.E(TAG, "xrGetInstanceProcAddr"); return false; } - IntPtr funcPtr = IntPtr.Zero; - /// xrGetSystemProperties - if (XrGetInstanceProcAddr(xrInstance, "xrGetSystemProperties", out funcPtr) == XrResult.XR_SUCCESS) - { - if (funcPtr != IntPtr.Zero) - { - DEBUG("Get function pointer of xrGetSystemProperties."); - xrGetSystemProperties = Marshal.GetDelegateForFunctionPointer( - funcPtr, - typeof(OpenXRHelper.xrGetSystemPropertiesDelegate)) as OpenXRHelper.xrGetSystemPropertiesDelegate; - } - } - else - { - ERROR("xrGetSystemProperties"); - return false; - } - /// xrEnumerateReferenceSpaces - if (XrGetInstanceProcAddr(xrInstance, "xrEnumerateReferenceSpaces", out funcPtr) == XrResult.XR_SUCCESS) - { - if (funcPtr != IntPtr.Zero) - { - DEBUG("Get function pointer of xrEnumerateReferenceSpaces."); - xrEnumerateReferenceSpaces = Marshal.GetDelegateForFunctionPointer( - funcPtr, - typeof(OpenXRHelper.xrEnumerateReferenceSpacesDelegate)) as OpenXRHelper.xrEnumerateReferenceSpacesDelegate; - } - } - else - { - ERROR("xrEnumerateReferenceSpaces"); - return false; - } - /// xrCreateReferenceSpace - if (XrGetInstanceProcAddr(xrInstance, "xrCreateReferenceSpace", out funcPtr) == XrResult.XR_SUCCESS) - { - if (funcPtr != IntPtr.Zero) - { - DEBUG("Get function pointer of xrCreateReferenceSpace."); - xrCreateReferenceSpace = Marshal.GetDelegateForFunctionPointer( - funcPtr, - typeof(OpenXRHelper.xrCreateReferenceSpaceDelegate)) as OpenXRHelper.xrCreateReferenceSpaceDelegate; - } - } - else - { - ERROR("xrCreateReferenceSpace"); - return false; - } - /// xrDestroySpace - if (XrGetInstanceProcAddr(xrInstance, "xrDestroySpace", out funcPtr) == XrResult.XR_SUCCESS) - { - if (funcPtr != IntPtr.Zero) - { - DEBUG("Get function pointer of xrDestroySpace."); - xrDestroySpace = Marshal.GetDelegateForFunctionPointer( - funcPtr, - typeof(OpenXRHelper.xrDestroySpaceDelegate)) as OpenXRHelper.xrDestroySpaceDelegate; - } - } - else - { - ERROR("xrDestroySpace"); - return false; - } -#if UNITY_ANDROID - /// xrEnumeratePassthroughImageRatesHTC - if (XrGetInstanceProcAddr(xrInstance, "xrEnumeratePassthroughImageRatesHTC", out funcPtr) == XrResult.XR_SUCCESS) - { - if (funcPtr != IntPtr.Zero) - { - DEBUG("Get function pointer of xrEnumeratePassthroughImageRatesHTC."); - xrEnumeratePassthroughImageRatesHTC = Marshal.GetDelegateForFunctionPointer( - funcPtr, - typeof(VivePassthroughHelper.xrEnumeratePassthroughImageRatesHTCDelegate)) as VivePassthroughHelper.xrEnumeratePassthroughImageRatesHTCDelegate; - } - } - else - { - ERROR("xrEnumeratePassthroughImageRatesHTC"); - //return false; - } + bool ret = true; + IntPtr funcPtr = IntPtr.Zero; - /// xrGetPassthroughConfigurationHTC - if (XrGetInstanceProcAddr(xrInstance, "xrGetPassthroughConfigurationHTC", out funcPtr) == XrResult.XR_SUCCESS) - { - if (funcPtr != IntPtr.Zero) - { - DEBUG("Get function pointer of xrGetPassthroughConfigurationHTC."); - xrGetPassthroughConfigurationHTC = Marshal.GetDelegateForFunctionPointer( - funcPtr, - typeof(VivePassthroughHelper.xrGetPassthroughConfigurationHTCDelegate)) as VivePassthroughHelper.xrGetPassthroughConfigurationHTCDelegate; - } - } - else - { - ERROR("xrGetPassthroughConfigurationHTC"); - //return false; - } - - /// xrSetPassthroughConfigurationHTC - if (XrGetInstanceProcAddr(xrInstance, "xrSetPassthroughConfigurationHTC", out funcPtr) == XrResult.XR_SUCCESS) - { - if (funcPtr != IntPtr.Zero) - { - DEBUG("Get function pointer of xrSetPassthroughConfigurationHTC."); - xrSetPassthroughConfigurationHTC = Marshal.GetDelegateForFunctionPointer( - funcPtr, - typeof(VivePassthroughHelper.xrSetPassthroughConfigurationHTCDelegate)) as VivePassthroughHelper.xrSetPassthroughConfigurationHTCDelegate; - } - } - else - { - ERROR("xrSetPassthroughConfigurationHTC"); - //return false; - } -#endif -#if UNITY_STANDALONE - /// xrCreatePassthroughHTC - if (XrGetInstanceProcAddr(xrInstance, "xrCreatePassthroughHTC", out funcPtr) == XrResult.XR_SUCCESS) - { - if (funcPtr != IntPtr.Zero) - { - DEBUG("Get function pointer of xrCreatePassthroughHTC."); - xrCreatePassthroughHTC = Marshal.GetDelegateForFunctionPointer( - funcPtr, - typeof(VivePassthroughHelper.xrCreatePassthroughHTCDelegate)) as VivePassthroughHelper.xrCreatePassthroughHTCDelegate; - } - } - else - { - ERROR("xrCreatePassthroughHTC"); - return false; - } - /// xrCreatePassthroughHTC - if (XrGetInstanceProcAddr(xrInstance, "xrDestroyPassthroughHTC", out funcPtr) == XrResult.XR_SUCCESS) - { - if (funcPtr != IntPtr.Zero) - { - DEBUG("Get function pointer of xrDestroyPassthroughHTC."); - xrDestroyPassthroughHTC = Marshal.GetDelegateForFunctionPointer( - funcPtr, - typeof(VivePassthroughHelper.xrDestroyPassthroughHTCDelegate)) as VivePassthroughHelper.xrDestroyPassthroughHTCDelegate; - } - } - else - { - ERROR("xrDestroyPassthroughHTC"); - return false; - } -#endif + ret &= OpenXRHelper.GetXrFunctionDelegate(XrGetInstanceProcAddr, xrInstance, "xrCreatePassthroughHTC", out xrCreatePassthroughHTC); + ret &= OpenXRHelper.GetXrFunctionDelegate(XrGetInstanceProcAddr, xrInstance, "xrDestroyPassthroughHTC", out xrDestroyPassthroughHTC); #if UNITY_ANDROID - if (GetFuncAddrs(xrInstance, xrGetInstanceProcAddr) == XrResult.XR_SUCCESS) - { - DEBUG("Get function pointers in native."); - } - else - { - ERROR("GetFuncAddrs"); - return false; - } + ret &= OpenXRHelper.GetXrFunctionDelegate(XrGetInstanceProcAddr, xrInstance, "xrEnumeratePassthroughImageRatesHTC", out xrEnumeratePassthroughImageRatesHTC); + ret &= OpenXRHelper.GetXrFunctionDelegate(XrGetInstanceProcAddr, xrInstance, "xrGetPassthroughConfigurationHTC", out xrGetPassthroughConfigurationHTC); + ret &= OpenXRHelper.GetXrFunctionDelegate(XrGetInstanceProcAddr, xrInstance, "xrSetPassthroughConfigurationHTC", out xrSetPassthroughConfigurationHTC); #endif - return true; + return ret; } #endregion -#if UNITY_ANDROID -#region Android Hook - Public - private const string ExtLib = "viveopenxr"; - [DllImport(ExtLib, EntryPoint = "htcpassthrough_CreatePassthrough")] - private static extern int ViveCreatePassthrough(XrSession session, CompositionLayer.LayerType layerType, PassthroughLayerForm layerForm, uint compositionDepth = 0); - [DllImport(ExtLib, EntryPoint = "htcpassthrough_DestroyPassthrough")] - private static extern bool ViveDestroyPassthrough(int passthroughID); - - [DllImport(ExtLib, EntryPoint = "htcpassthrough_SetAlpha")] - private static extern bool ViveSetAlpha(int passthroughID, float alpha); - /// - /// Set Passthough Alpha. - /// - public bool SetAlpha(XrPassthroughHTC passthrough, float alpha) - { - if (!m_XrInstanceCreated) - { - ERROR("SetAlpha: " + kOpenxrExtensionStrings + " is NOT enabled."); - return false; - } - if (passthrough == 0) { ERROR("SetAlpha() Invalid passthrough."); return false; } - - int passthroughID = (int)(passthrough & 0x00007FFF); - sb.Clear().Append("SetAlpha() passthrough: ").Append(passthroughID).Append(", alpha: ").Append(alpha); DEBUG(sb); - return ViveSetAlpha(passthroughID, alpha); - } - - [DllImport(ExtLib, EntryPoint = "htcpassthrough_SetLayerType")] - private static extern bool ViveSetLayerType(int passthroughID, CompositionLayer.LayerType layerType, uint compositionDepth = 0); - /// - /// Set Passthough Layer Type. - /// - public bool SetLayerType(XrPassthroughHTC passthrough, CompositionLayer.LayerType layerType, uint compositionDepth = 0) - { - if (!m_XrInstanceCreated) - { - ERROR("SetLayerType: " + kOpenxrExtensionStrings + " is NOT enabled."); - return false; - } - if (passthrough == 0) { ERROR("SetLayerType() Invalid passthrough."); return false; } - - int passthroughID = (int)(passthrough & 0x00007FFF); - sb.Clear().Append("SetAlpha() passthrough: ").Append(passthroughID).Append(", layerType: ").Append(layerType).Append(", compositionDepth: ").Append(compositionDepth); DEBUG(sb); - return ViveSetLayerType(passthroughID, layerType, compositionDepth); - } - - [DllImport(ExtLib, EntryPoint = "htcpassthrough_SetMesh")] - private static extern bool ViveSetMesh(int passthroughID, uint vertexCount, [In, Out] XrVector3f[] vertexBuffer, uint indexCount, [In, Out] uint[] indexBuffer); - /// - /// Set Passthough Mesh. - /// - public bool SetMesh(XrPassthroughHTC passthrough, uint vertexCount, [In, Out] XrVector3f[] vertexBuffer, uint indexCount, [In, Out] uint[] indexBuffer) - { - if (!m_XrInstanceCreated) - { - ERROR("SetMesh: " + kOpenxrExtensionStrings + " is NOT enabled."); - return false; - } - if (passthrough == 0) { ERROR("SetMesh() Invalid passthrough."); return false; } - - int passthroughID = (int)(passthrough & 0x00007FFF); - sb.Clear().Append("SetMesh() passthrough: ").Append(passthroughID).Append(", vertexCount: ").Append(vertexCount).Append(", indexCount: ").Append(indexCount); DEBUG(sb); - return ViveSetMesh(passthroughID, vertexCount, vertexBuffer, indexCount, indexBuffer); - } - - [DllImport(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransform")] - private static extern bool ViveSetMeshTransform(int passthroughID, XrSpace meshSpace, XrPosef meshPose, XrVector3f meshScale); - /// - /// Set Passthough Mesh Transform. - /// - public bool SetMeshTransform(XrPassthroughHTC passthrough, XrSpace meshSpace, XrPosef meshPose, XrVector3f meshScale) - { - if (!m_XrInstanceCreated) - { - ERROR("SetMeshTransform: " + kOpenxrExtensionStrings + " is NOT enabled."); - return false; - } - if (passthrough == 0) { ERROR("SetMeshTransform() Invalid passthrough."); return false; } - - int passthroughID = (int)(passthrough & 0x00007FFF); - sb.Clear().Append("SetMeshTransform() passthrough: ").Append(passthroughID).Append(", meshSpace: ").Append(meshSpace); DEBUG(sb); - return ViveSetMeshTransform(passthroughID, meshSpace, meshPose, meshScale); - } - - [DllImport(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransformSpace")] - private static extern bool ViveSetMeshTransformSpace(int passthroughID, XrSpace meshSpace); - /// - /// Set Passthough Mesh Transform Space. - /// - public bool SetMeshTransformSpace(XrPassthroughHTC passthrough, XrSpace meshSpace) - { - if (!m_XrInstanceCreated) - { - ERROR("SetMeshTransformSpace: " + kOpenxrExtensionStrings + " is NOT enabled."); - return false; - } - if (passthrough == 0) { ERROR("SetMeshTransformSpace() Invalid passthrough."); return false; } - - int passthroughID = (int)(passthrough & 0x00007FFF); - sb.Clear().Append("SetMeshTransformSpace() passthrough: ").Append(passthroughID).Append(", meshSpace: ").Append(meshSpace); DEBUG(sb); - return ViveSetMeshTransformSpace(passthroughID, meshSpace); - } - - [DllImport(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransformPosition")] - private static extern bool ViveSetMeshTransformPosition(int passthroughID, XrVector3f meshPosition); - /// - /// Set Passthough Mesh Transform Position. - /// - public bool SetMeshTransformPosition(XrPassthroughHTC passthrough, XrVector3f meshPosition) - { - if (!m_XrInstanceCreated) - { - ERROR("SetMeshTransformPosition: " + kOpenxrExtensionStrings + " is NOT enabled."); - return false; - } - if (passthrough == 0) { ERROR("SetMeshTransformPosition() Invalid passthrough."); return false; } - - int passthroughID = (int)(passthrough & 0x00007FFF); - sb.Clear().Append("SetMeshTransformPosition() passthrough: ").Append(passthroughID); DEBUG(sb); - return ViveSetMeshTransformPosition(passthroughID, meshPosition); - } - - [DllImport(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransformOrientation")] - private static extern bool ViveSetMeshTransformOrientation(int passthroughID, XrQuaternionf meshOrientation); - /// - /// Set Passthough Mesh Transform orientation. - /// - public bool SetMeshTransformOrientation(XrPassthroughHTC passthrough, XrQuaternionf meshOrientation) - { - if (!m_XrInstanceCreated) - { - ERROR("SetMeshTransformOrientation: " + kOpenxrExtensionStrings + " is NOT enabled."); - return false; - } - if (passthrough == 0) { ERROR("SetMeshTransformOrientation() Invalid passthrough."); return false; } - - int passthroughID = (int)(passthrough & 0x00007FFF); - sb.Clear().Append("SetMeshTransformOrientation() passthrough: ").Append(passthroughID); DEBUG(sb); - return ViveSetMeshTransformOrientation(passthroughID, meshOrientation); - } - - [DllImport(ExtLib, EntryPoint = "htcpassthrough_SetMeshTransformScale")] - private static extern bool ViveSetMeshTransformScale(int passthroughID, XrVector3f meshScale); - /// - /// Set Passthough Mesh Transform scale. - /// - public bool SetMeshTransformScale(XrPassthroughHTC passthrough, XrVector3f meshScale) - { - if (!m_XrInstanceCreated) - { - ERROR("SetMeshTransformScale: " + kOpenxrExtensionStrings + " is NOT enabled."); - return false; - } - if (passthrough == 0) { ERROR("SetMeshTransformScale() Invalid passthrough."); return false; } - - int passthroughID = (int)(passthrough & 0x00007FFF); - sb.Clear().Append("SetMeshTransformScale() passthrough: ").Append(passthroughID); DEBUG(sb); - return ViveSetMeshTransformScale(passthroughID, meshScale); - } -#endregion - -#region Android Hook - Private - [DllImport(ExtLib, EntryPoint = "htcpassthrough_GetFuncAddrs")] - private static extern XrResult ViveGetFuncAddrs(XrInstance xrInstance, IntPtr xrGetInstanceProcAddrFuncPtr); - private XrResult GetFuncAddrs(XrInstance xrInstance, IntPtr xrGetInstanceProcAddrFuncPtr) - { - if (!m_XrInstanceCreated) - { - ERROR("ViveGetFuncAddrs: " + kOpenxrExtensionStrings + " is NOT enabled."); - return XrResult.XR_ERROR_FEATURE_UNSUPPORTED; - } - - return ViveGetFuncAddrs(xrInstance, xrGetInstanceProcAddrFuncPtr); - } -#endregion -#endif - private List passthroughList = new List(); public List PassthroughList { get { @@ -891,46 +787,27 @@ namespace VIVE.OpenXR.Passthrough if (!m_XrSessionCreated) { - ERROR("CreatePassthroughHTC() XR_ERROR_SESSION_LOST."); + Log.E(TAG, "CreatePassthroughHTC() XR_ERROR_SESSION_LOST."); return XrResult.XR_ERROR_SESSION_LOST; } if (!m_XrInstanceCreated) { - ERROR("CreatePassthroughHTC() XR_ERROR_INSTANCE_LOST."); + Log.E(TAG, "CreatePassthroughHTC() XR_ERROR_INSTANCE_LOST."); return XrResult.XR_ERROR_INSTANCE_LOST; } - sb.Clear().Append("CreatePassthroughHTC() layerType: ").Append(layerType).Append(", compositionDepth: ").Append(compositionDepth); DEBUG(sb); + Log.I(TAG, CSB.Append("CreatePassthroughHTC() layerType: ").Append(layerType).Append(", compositionDepth: ").Append(compositionDepth)); XrResult result = XrResult.XR_ERROR_RUNTIME_FAILURE; -#if UNITY_STANDALONE result = xrCreatePassthroughHTC(m_XrSession, createInfo, out passthrough); - DEBUG("CreatePassthroughHTC() xrCreatePassthroughHTC result: " + result); + Log.I(TAG, "CreatePassthroughHTC() xrCreatePassthroughHTC result: " + result); if (result == XrResult.XR_SUCCESS) { passthroughList.Add(passthrough); if (onDestroy != null) { OnPassthroughSessionDestroyHandlerDictionary.Add(passthrough, onDestroy); } } -#endif -#if UNITY_ANDROID - int passthroughID = 0; - - if (createInfo.form == XrPassthroughFormHTC.XR_PASSTHROUGH_FORM_PLANAR_HTC) - passthroughID = ViveCreatePassthrough(m_XrSession, layerType, PassthroughLayerForm.Planar, compositionDepth); - else // createInfo.form == XrPassthroughFormHTC.XR_PASSTHROUGH_FORM_PROJECTED_HTC - passthroughID = ViveCreatePassthrough(m_XrSession, layerType, PassthroughLayerForm.Projected, compositionDepth); - - sb.Clear().Append("CreatePassthroughHTC() CreatePassthrough passthroughID: ").Append(passthroughID); DEBUG(sb); - if (passthroughID != 0) - { - passthrough = (UInt64)(passthroughID & 0x7FFFFFFF); - passthroughList.Add(passthrough); - if (onDestroy != null) { OnPassthroughSessionDestroyHandlerDictionary.Add(passthrough, onDestroy); } - result = XrResult.XR_SUCCESS; - } -#endif return result; } public XrResult CreatePassthroughHTC(XrPassthroughCreateInfoHTC createInfo, out XrPassthroughHTC passthrough, CompositionLayer.LayerType layerType, OnPassthroughSessionDestroyDelegate onDestroy = null) @@ -946,37 +823,24 @@ namespace VIVE.OpenXR.Passthrough { if (!passthroughList.Contains(passthrough)) { - ERROR("DestroyPassthroughHTC() Invalid passthrough: " + passthrough); + Log.E(TAG, "DestroyPassthroughHTC() Invalid passthrough: " + passthrough); return XrResult.XR_ERROR_VALIDATION_FAILURE; } - sb.Clear().Append("DestroyPassthroughHTC() passthrough: ").Append(passthrough); DEBUG(sb); + Log.I(TAG, CSB.Append("DestroyPassthroughHTC() passthrough: ").Append(passthrough)); XrResult result = XrResult.XR_ERROR_RUNTIME_FAILURE; int passthroughID = (int)(passthrough & 0x00007FFF); -#if UNITY_STANDALONE result = xrDestroyPassthroughHTC(passthrough); - sb.Clear().Append("DestroyPassthroughHTC() ").Append(passthrough).Append(", result: ").Append(result); DEBUG(sb); + Log.I(TAG, CSB.Append("DestroyPassthroughHTC() ").Append(passthrough).Append(", result: ").Append(result)); if (result == XrResult.XR_SUCCESS) { passthroughList.Remove(passthrough); if (OnPassthroughSessionDestroyHandlerDictionary.ContainsKey(passthrough)) OnPassthroughSessionDestroyHandlerDictionary.Remove(passthrough); } -#endif -#if UNITY_ANDROID - bool ret = ViveDestroyPassthrough(passthroughID); - sb.Clear().Append("DestroyPassthroughHTC() ").Append(passthroughID).Append(", ret: ").Append(ret); DEBUG(sb); - if (ret) - { - passthroughList.Remove(passthrough); - if (OnPassthroughSessionDestroyHandlerDictionary.ContainsKey(passthrough)) - OnPassthroughSessionDestroyHandlerDictionary.Remove(passthrough); - result = XrResult.XR_SUCCESS; - } -#endif return result; } @@ -987,7 +851,7 @@ namespace VIVE.OpenXR.Passthrough public XrSpace GetTrackingSpace() { XrSpace space = GetCurrentAppSpace(); - sb.Clear().Append("GetTrackingSpace() ").Append(space); DEBUG(sb); + Log.I(TAG, CSB.Append("GetTrackingSpace() ").Append(space)); return space; } @@ -1006,7 +870,7 @@ namespace VIVE.OpenXR.Passthrough case ProjectedPassthroughSpaceType.Worldlock: default: XRInputSubsystem subsystem = null; - SubsystemManager.GetInstances(inputSubsystems); + SubsystemManager.GetSubsystems(inputSubsystems); if (inputSubsystems.Count > 0) { subsystem = inputSubsystems[0]; @@ -1041,7 +905,7 @@ namespace VIVE.OpenXR.Passthrough { if (!m_XrSessionCreated) { - ERROR("EnumeratePassthroughImageRatesHTC() XR_ERROR_SESSION_LOST."); + Log.E(TAG, "EnumeratePassthroughImageRatesHTC() XR_ERROR_SESSION_LOST."); return XrResult.XR_ERROR_SESSION_LOST; } return xrEnumeratePassthroughImageRatesHTC(m_XrSession, imageRateCapacityInput, ref imageRateCountOutput, imageRates); @@ -1051,7 +915,7 @@ namespace VIVE.OpenXR.Passthrough { if (!m_XrSessionCreated) { - ERROR("GetPassthroughConfigurationHTC() XR_ERROR_SESSION_LOST."); + Log.E(TAG, "GetPassthroughConfigurationHTC() XR_ERROR_SESSION_LOST."); return XrResult.XR_ERROR_SESSION_LOST; } return xrGetPassthroughConfigurationHTC(m_XrSession, config); @@ -1061,7 +925,7 @@ namespace VIVE.OpenXR.Passthrough { if (!m_XrSessionCreated) { - ERROR("SetPassthroughConfigurationHTC() XR_ERROR_SESSION_LOST."); + Log.E(TAG, "SetPassthroughConfigurationHTC() XR_ERROR_SESSION_LOST."); return XrResult.XR_ERROR_SESSION_LOST; } return xrSetPassthroughConfigurationHTC(m_XrSession, config); @@ -1077,7 +941,7 @@ namespace VIVE.OpenXR.Passthrough m_SupportsImageQuality = false; if (!m_XrSessionCreated) { - ERROR("CheckUserPresenceSupport() session is not created."); + Log.E(TAG, "CheckUserPresenceSupport() session is not created."); return; } @@ -1095,7 +959,7 @@ namespace VIVE.OpenXR.Passthrough IntPtr passthroughConfigurationPtr = new IntPtr(offset); Marshal.StructureToPtr(passthroughConfigurationProperties, passthroughConfigurationPtr, false); - if (GetSystemProperties(ref systemProperties) == XrResult.XR_SUCCESS) + if (CommonWrapper.Instance.GetSystemProperties(m_XrInstance, m_XrSystemId, ref systemProperties) == XrResult.XR_SUCCESS) { if (IntPtr.Size == 4) offset = systemProperties.next.ToInt32(); @@ -1105,14 +969,14 @@ namespace VIVE.OpenXR.Passthrough passthroughConfigurationPtr = new IntPtr(offset); passthroughConfigurationProperties = (XrSystemPassthroughConfigurationPropertiesHTC)Marshal.PtrToStructure(passthroughConfigurationPtr, typeof(XrSystemPassthroughConfigurationPropertiesHTC)); - sb.Clear().Append("CheckConfigurationSupport() supportsImageQuality: ").Append((UInt32)passthroughConfigurationProperties.supportsImageQuality); DEBUG(sb); - sb.Clear().Append("CheckConfigurationSupport() supportsImageRate: ").Append((UInt32)passthroughConfigurationProperties.supportsImageRate); DEBUG(sb); + Log.I(TAG, CSB.Append("CheckConfigurationSupport() supportsImageQuality: ").Append((UInt32)passthroughConfigurationProperties.supportsImageQuality)); + Log.I(TAG, CSB.Append("CheckConfigurationSupport() supportsImageRate: ").Append((UInt32)passthroughConfigurationProperties.supportsImageRate)); m_SupportsImageQuality = passthroughConfigurationProperties.supportsImageQuality; m_SupportsImageRate = passthroughConfigurationProperties.supportsImageRate; } else { - ERROR("CheckSupport() GetSystemProperties failed."); + Log.E(TAG, "CheckSupport() GetSystemProperties failed."); } Marshal.FreeHGlobal(systemProperties.next); diff --git a/com.htc.upm.vive.openxr/Runtime/Features/Passthrough/Scripts/VivePassthroughHelper.cs b/com.htc.upm.vive.openxr/Runtime/Features/Passthrough/Scripts/VivePassthroughHelper.cs index 9cd4051..ace11b3 100644 --- a/com.htc.upm.vive.openxr/Runtime/Features/Passthrough/Scripts/VivePassthroughHelper.cs +++ b/com.htc.upm.vive.openxr/Runtime/Features/Passthrough/Scripts/VivePassthroughHelper.cs @@ -172,10 +172,10 @@ namespace VIVE.OpenXR.Passthrough /// The alpha value of the passthrough in the range [0, 1]. /// public float alpha; - public XrPassthroughColorHTC(XrStructureType in_type, IntPtr in_next, float in_alpha) + 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 /// /// An array of XrVector3f. The size of the array must be equal to vertexCount. /// - public XrVector3f[] vertices; + public IntPtr vertices; // XrVector3f /// /// The count of indices array in the mesh. /// @@ -209,7 +209,7 @@ namespace VIVE.OpenXR.Passthrough /// /// An array of triangle indices. The size of the array must be equal to indexCount. /// - public UInt32[] indices; + public IntPtr indices; // UInt32[] /// /// The XrSpace that defines the projected passthrough's base space for transformations. /// @@ -226,21 +226,6 @@ namespace VIVE.OpenXR.Passthrough /// The XrVector3f that defines the scale of the mesh /// public XrVector3f scale; - public XrPassthroughMeshTransformInfoHTC(XrStructureType in_type, IntPtr in_next, UInt32 in_vertexCount, - XrVector3f[] in_vertices, UInt32 in_indexCount, UInt32[] in_indices, XrSpace in_baseSpace, XrTime in_time, - XrPosef in_pose, XrVector3f in_scale) - { - type = in_type; - next = in_next; - vertexCount = in_vertexCount; - vertices = in_vertices; - indexCount = in_indexCount; - indices = in_indices; - baseSpace = in_baseSpace; - time = in_time; - pose = in_pose; - scale = in_scale; - } }; /// @@ -273,11 +258,12 @@ namespace VIVE.OpenXR.Passthrough /// The XrPassthroughColorHTC describing the color information with the alpha value of the passthrough layer. /// public XrPassthroughColorHTC color; - public XrCompositionLayerPassthroughHTC(XrStructureType in_type, IntPtr in_next, XrCompositionLayerFlags in_layerFlags, + + 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; diff --git a/com.htc.upm.vive.openxr/Runtime/Features/Tracker/ViveTracker/HTCViveTrackerProfile.cs b/com.htc.upm.vive.openxr/Runtime/Features/Tracker/ViveTracker/HTCViveTrackerProfile.cs index 241eeb2..b8d6a39 100644 --- a/com.htc.upm.vive.openxr/Runtime/Features/Tracker/ViveTracker/HTCViveTrackerProfile.cs +++ b/com.htc.upm.vive.openxr/Runtime/Features/Tracker/ViveTracker/HTCViveTrackerProfile.cs @@ -26,7 +26,7 @@ namespace UnityEngine.XR.OpenXR.Features.Interactions /// #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.", diff --git a/com.htc.upm.vive.openxr/Runtime/Models/Hand/HandModelActions.cs b/com.htc.upm.vive.openxr/Runtime/Models/Hand/HandModelActions.cs index 09be440..abb2943 100644 --- a/com.htc.upm.vive.openxr/Runtime/Models/Hand/HandModelActions.cs +++ b/com.htc.upm.vive.openxr/Runtime/Models/Hand/HandModelActions.cs @@ -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(); } + 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) diff --git a/com.htc.upm.vive.openxr/Runtime/OpenXRUtils.cs b/com.htc.upm.vive.openxr/Runtime/OpenXRUtils.cs index 466ab51..5a03222 100644 --- a/com.htc.upm.vive.openxr/Runtime/OpenXRUtils.cs +++ b/com.htc.upm.vive.openxr/Runtime/OpenXRUtils.cs @@ -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 /// /// 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(funcPtr); return true; } diff --git a/com.htc.upm.vive.openxr/Runtime/Profiles/XR_EXT_hand_tracking.cs b/com.htc.upm.vive.openxr/Runtime/Profiles/XR_EXT_hand_tracking.cs index a3d5cef..7946898 100644 --- a/com.htc.upm.vive.openxr/Runtime/Profiles/XR_EXT_hand_tracking.cs +++ b/com.htc.upm.vive.openxr/Runtime/Profiles/XR_EXT_hand_tracking.cs @@ -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; diff --git a/com.htc.upm.vive.openxr/Runtime/Profiles/XR_EXT_hand_tracking_impls.cs b/com.htc.upm.vive.openxr/Runtime/Profiles/XR_EXT_hand_tracking_impls.cs index 7121cee..7163847 100644 --- a/com.htc.upm.vive.openxr/Runtime/Profiles/XR_EXT_hand_tracking_impls.cs +++ b/com.htc.upm.vive.openxr/Runtime/Profiles/XR_EXT_hand_tracking_impls.cs @@ -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(); } - l_HandJointLocation.Clear(); - for (int i = 0; i < array.Length; i++) { l_HandJointLocation.Add(array[i]); } - - handJointLocation = l_HandJointLocation.ToArray(); return true; } } diff --git a/com.htc.upm.vive.openxr/Runtime/Profiles/XR_HTC_passthrough_impls.cs b/com.htc.upm.vive.openxr/Runtime/Profiles/XR_HTC_passthrough_impls.cs index 81c8e86..3c7b2aa 100644 --- a/com.htc.upm.vive.openxr/Runtime/Profiles/XR_HTC_passthrough_impls.cs +++ b/com.htc.upm.vive.openxr/Runtime/Profiles/XR_HTC_passthrough_impls.cs @@ -43,27 +43,6 @@ namespace VIVE.OpenXR return result; } - public override void GetOriginEndFrameLayerList(out List layers) - { - ASSERT_FEATURE(); - layers = new List(); -#if UNITY_STANDALONE - if (feature) - feature.GetOriginEndFrameLayerList(out layers); - - else - layers = new List(); -#endif - } - public override void SubmitLayers(List 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(); } } diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/Common/VIVEInput.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/Common/VIVEInput.cs index d1985ca..8b32112 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/Common/VIVEInput.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/Common/VIVEInput.cs @@ -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 inputActions = new List(); - 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 s_InputActions = new List(); + 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 m_HandSubsystems = new List(); #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)) { - eventResult = inputActionMapping.inputAction.ReadValue() > 0; - return true; - } - catch (InvalidOperationException) - { - return false; + var inputAction = inputActionMapping.inputAction; + if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType) + { + eventResult = inputActionMapping.inputAction.ReadValue() > 0; + return true; + } } + 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)) { - eventResult = inputActionMapping.inputAction.ReadValue(); - return true; - } - catch (InvalidOperationException) - { - return false; + var inputAction = inputActionMapping.inputAction; + if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kVector3Type) + { + eventResult = inputActionMapping.inputAction.ReadValue(); + return true; + } } + 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)) { - eventResult = inputActionMapping.inputAction.ReadValue(); - return true; - } - catch (InvalidOperationException) - { - return false; + var inputAction = inputActionMapping.inputAction; + if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kQuaternionType) + { + eventResult = inputActionMapping.inputAction.ReadValue(); + return true; + } } + return false; } } @@ -315,11 +347,14 @@ 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)) { - eventResult = inputActionMapping.inputAction.WasPressedThisFrame(); - return true; + var inputAction = inputActionMapping.inputAction; + if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType) + { + eventResult = inputActionMapping.inputAction.WasPressedThisFrame(); + return true; + } } return false; } @@ -335,11 +370,14 @@ 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)) { - eventResult = inputActionMapping.inputAction.WasReleasedThisFrame(); - return true; + 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() == 1; return true; } - catch (InvalidOperationException) - { - return false; - } } return false; - } /// @@ -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(); return true; } - catch (InvalidOperationException) - { - return false; - } } return false; - } /// @@ -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(); 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(); 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(); +#else UnityEngine.XR.OpenXR.Input.Pose pose = inputActionMapping.inputAction.ReadValue(); +#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() { - ViveHandTracking viveHand = OpenXRSettings.Instance.GetFeature(); - if (viveHand) + if (!m_IsInitInputActions) { - return true; - } + ViveHandTracking viveHand = OpenXRSettings.Instance.GetFeature(); + if (viveHand) + { + m_IsSupportViveHand = true; + } #if UNITY_XR_HANDS - HandTracking xrHand = OpenXRSettings.Instance.GetFeature(); - if (xrHand) - { - return true; - } + HandTracking xrHand = OpenXRSettings.Instance.GetFeature(); + if (xrHand) + { + m_IsSupportXrHand = true; + } #endif - return false; + } + return m_IsSupportViveHand || m_IsSupportXrHand; } #endregion @@ -538,192 +561,233 @@ 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("/isTracked", DeviceCategory.HMD, poseState: PoseState.IsTracked)); - inputActions.Add(new InputActionMapping("/centerEyePosition", DeviceCategory.HMD, poseState: PoseState.Position)); - inputActions.Add(new InputActionMapping("/centerEyeRotation", DeviceCategory.HMD, poseState: PoseState.Rotation)); - inputActions.Add(new InputActionMapping("/centerEyeVelocity", DeviceCategory.HMD, poseState: PoseState.Velocity)); - inputActions.Add(new InputActionMapping("/centerEyeAngularVelocity", DeviceCategory.HMD, poseState: PoseState.AngularVelocity)); - inputActions.Add(new InputActionMapping("/centerEyeAcceleration", DeviceCategory.HMD, poseState: PoseState.Acceleration)); - inputActions.Add(new InputActionMapping("/centerEyeAngularAcceleration", DeviceCategory.HMD, poseState: PoseState.AngularAcceleration)); + s_InputActions.Add(new InputActionMapping("/isTracked", DeviceCategory.HMD, in_PoseState: PoseState.IsTracked, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("/centerEyePosition", DeviceCategory.HMD, in_PoseState: PoseState.Position, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("/centerEyeRotation", DeviceCategory.HMD, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType)); + s_InputActions.Add(new InputActionMapping("/centerEyeVelocity", DeviceCategory.HMD, in_PoseState: PoseState.Velocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("/centerEyeAngularVelocity", DeviceCategory.HMD, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("/centerEyeAcceleration", DeviceCategory.HMD, in_PoseState: PoseState.Acceleration, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("/centerEyeAngularAcceleration", DeviceCategory.HMD, in_PoseState: PoseState.AngularAcceleration, in_Type: kVector3Type)); #endregion #region Eye - inputActions.Add(new InputActionMapping("/pose/isTracked", DeviceCategory.CenterEye, poseState: PoseState.IsTracked)); - inputActions.Add(new InputActionMapping("/pose/position", DeviceCategory.CenterEye, poseState: PoseState.Position)); - inputActions.Add(new InputActionMapping("/pose/rotation", DeviceCategory.CenterEye, poseState: PoseState.Rotation)); - inputActions.Add(new InputActionMapping("/pose/velocity", DeviceCategory.CenterEye, poseState: PoseState.Velocity)); - inputActions.Add(new InputActionMapping("/pose/angularVelocity", DeviceCategory.CenterEye, poseState: PoseState.AngularVelocity)); + s_InputActions.Add(new InputActionMapping("/pose/isTracked", DeviceCategory.CenterEye, in_PoseState: PoseState.IsTracked, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("/pose/position", DeviceCategory.CenterEye, in_PoseState: PoseState.Position, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("/pose/rotation", DeviceCategory.CenterEye, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType)); + s_InputActions.Add(new InputActionMapping("/pose/velocity", DeviceCategory.CenterEye, in_PoseState: PoseState.Velocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("/pose/angularVelocity", DeviceCategory.CenterEye, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type)); #endregion #region Controller - inputActions.Add(new InputActionMapping("{LeftHand}/isTracked", DeviceCategory.LeftController, poseState: PoseState.IsTracked)); - inputActions.Add(new InputActionMapping("{LeftHand}/pointerPosition", DeviceCategory.LeftController, poseState: PoseState.Position)); - inputActions.Add(new InputActionMapping("{LeftHand}/pointerRotation", DeviceCategory.LeftController, poseState: PoseState.Rotation)); - inputActions.Add(new InputActionMapping("{LeftHand}/deviceVelocity", DeviceCategory.LeftController, poseState: PoseState.Velocity)); - inputActions.Add(new InputActionMapping("{LeftHand}/deviceAngularVelocity", DeviceCategory.LeftController, poseState: PoseState.AngularVelocity)); - inputActions.Add(new InputActionMapping("{LeftHand}/deviceAcceleration", DeviceCategory.LeftController, poseState: PoseState.Acceleration)); - inputActions.Add(new InputActionMapping("{LeftHand}/deviceAngularAcceleration", DeviceCategory.LeftController, poseState: PoseState.AngularAcceleration)); - inputActions.Add(new InputActionMapping("{LeftHand}/{grip}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.GripValue)); - inputActions.Add(new InputActionMapping("{LeftHand}/{gripButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.GripPress)); - inputActions.Add(new InputActionMapping("{LeftHand}/{trigger}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.TriggerValue)); - inputActions.Add(new InputActionMapping("{LeftHand}/triggerTouched", DeviceCategory.LeftController, buttonEvent: ButtonEvent.TriggerTouch)); - inputActions.Add(new InputActionMapping("{LeftHand}/{triggerButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.TriggerPress)); - inputActions.Add(new InputActionMapping("{LeftHand}/{primary2DAxis}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Primary2DAxisValue)); - inputActions.Add(new InputActionMapping("{LeftHand}/{primary2DAxisTouch}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Primary2DAxisTouch)); - inputActions.Add(new InputActionMapping("{LeftHand}/{primary2DAxisClick}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Primary2DAxisPress)); - inputActions.Add(new InputActionMapping("{LeftHand}/{secondary2DAxis}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Secondary2DAxisValue)); - inputActions.Add(new InputActionMapping("{LeftHand}/{secondary2DAxisTouch}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Secondary2DAxisTouch)); - inputActions.Add(new InputActionMapping("{LeftHand}/{secondary2DAxisClick}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Secondary2DAxisPress)); - inputActions.Add(new InputActionMapping("{LeftHand}/{primaryButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.PrimaryButton)); - inputActions.Add(new InputActionMapping("{LeftHand}/{secondaryButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.SecondaryButton)); - inputActions.Add(new InputActionMapping("{LeftHand}/parkingTouched", DeviceCategory.LeftController, buttonEvent: ButtonEvent.ParkingTouch)); - inputActions.Add(new InputActionMapping("{LeftHand}/menu", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Menu)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/isTracked", DeviceCategory.LeftController, in_PoseState: PoseState.IsTracked, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/pointerPosition", DeviceCategory.LeftController, in_PoseState: PoseState.Position, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/pointerRotation", DeviceCategory.LeftController, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/deviceVelocity", DeviceCategory.LeftController, in_PoseState: PoseState.Velocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/deviceAngularVelocity", DeviceCategory.LeftController, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/deviceAcceleration", DeviceCategory.LeftController, in_PoseState: PoseState.Acceleration, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/deviceAngularAcceleration", DeviceCategory.LeftController, in_PoseState: PoseState.AngularAcceleration, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{grip}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.GripValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{gripButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.GripPress, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{trigger}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.TriggerValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/triggerTouched", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.TriggerTouch, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{triggerButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.TriggerPress, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{primary2DAxis}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Primary2DAxisValue, in_Type: kVector2Type)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{primary2DAxisTouch}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Primary2DAxisTouch, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{primary2DAxisClick}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Primary2DAxisPress, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{secondary2DAxis}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Secondary2DAxisValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{secondary2DAxisTouch}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Secondary2DAxisTouch, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{secondary2DAxisClick}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Secondary2DAxisPress, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{primaryButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.PrimaryButton, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/{secondaryButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.SecondaryButton, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/parkingTouched", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.ParkingTouch, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/menu", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Menu, in_Type: kFloatType)); - inputActions.Add(new InputActionMapping("{RightHand}/isTracked", DeviceCategory.RightController, poseState: PoseState.IsTracked)); - inputActions.Add(new InputActionMapping("{RightHand}/pointerPosition", DeviceCategory.RightController, poseState: PoseState.Position)); - inputActions.Add(new InputActionMapping("{RightHand}/pointerRotation", DeviceCategory.RightController, poseState: PoseState.Rotation)); - inputActions.Add(new InputActionMapping("{RightHand}/deviceVelocity", DeviceCategory.RightController, poseState: PoseState.Velocity)); - inputActions.Add(new InputActionMapping("{RightHand}/deviceAngularVelocity", DeviceCategory.RightController, poseState: PoseState.AngularVelocity)); - inputActions.Add(new InputActionMapping("{RightHand}/deviceAcceleration", DeviceCategory.RightController, poseState: PoseState.Acceleration)); - inputActions.Add(new InputActionMapping("{RightHand}/deviceAngularAcceleration", DeviceCategory.RightController, poseState: PoseState.AngularAcceleration)); - inputActions.Add(new InputActionMapping("{RightHand}/{grip}", DeviceCategory.RightController, buttonEvent: ButtonEvent.GripValue)); - inputActions.Add(new InputActionMapping("{RightHand}/{gripButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.GripPress)); - inputActions.Add(new InputActionMapping("{RightHand}/{trigger}", DeviceCategory.RightController, buttonEvent: ButtonEvent.TriggerValue)); - inputActions.Add(new InputActionMapping("{RightHand}/triggerTouched", DeviceCategory.RightController, buttonEvent: ButtonEvent.TriggerTouch)); - inputActions.Add(new InputActionMapping("{RightHand}/{triggerButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.TriggerPress)); - inputActions.Add(new InputActionMapping("{RightHand}/{primary2DAxis}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Primary2DAxisValue)); - inputActions.Add(new InputActionMapping("{RightHand}/{primary2DAxisTouch}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Primary2DAxisTouch)); - inputActions.Add(new InputActionMapping("{RightHand}/{primary2DAxisClick}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Primary2DAxisPress)); - inputActions.Add(new InputActionMapping("{RightHand}/{secondary2DAxis}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Secondary2DAxisValue)); - inputActions.Add(new InputActionMapping("{RightHand}/{secondary2DAxisTouch}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Secondary2DAxisTouch)); - inputActions.Add(new InputActionMapping("{RightHand}/{secondary2DAxisClick}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Secondary2DAxisPress)); - inputActions.Add(new InputActionMapping("{RightHand}/{primaryButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.PrimaryButton)); - inputActions.Add(new InputActionMapping("{RightHand}/{secondaryButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.SecondaryButton)); - inputActions.Add(new InputActionMapping("{RightHand}/parkingTouched", DeviceCategory.RightController, buttonEvent: ButtonEvent.ParkingTouch)); + s_InputActions.Add(new InputActionMapping("{RightHand}/isTracked", DeviceCategory.RightController, in_PoseState: PoseState.IsTracked, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/pointerPosition", DeviceCategory.RightController, in_PoseState: PoseState.Position, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{RightHand}/pointerRotation", DeviceCategory.RightController, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/deviceVelocity", DeviceCategory.RightController, in_PoseState: PoseState.Velocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{RightHand}/deviceAngularVelocity", DeviceCategory.RightController, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{RightHand}/deviceAcceleration", DeviceCategory.RightController, in_PoseState: PoseState.Acceleration, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{RightHand}/deviceAngularAcceleration", DeviceCategory.RightController, in_PoseState: PoseState.AngularAcceleration, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{grip}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.GripValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{gripButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.GripPress, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{trigger}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.TriggerValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/triggerTouched", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.TriggerTouch, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{triggerButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.TriggerPress, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{primary2DAxis}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Primary2DAxisValue, in_Type: kVector2Type)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{primary2DAxisTouch}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Primary2DAxisTouch, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{primary2DAxisClick}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Primary2DAxisPress, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{secondary2DAxis}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Secondary2DAxisValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{secondary2DAxisTouch}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Secondary2DAxisTouch, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{secondary2DAxisClick}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Secondary2DAxisPress, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{primaryButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.PrimaryButton, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/{secondaryButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.SecondaryButton, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/parkingTouched", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.ParkingTouch, in_Type: kFloatType)); #endregion #region Hand - inputActions.Add(new InputActionMapping("{LeftHand}/selectValue", DeviceCategory.LeftHand, handEvent: HandEvent.PinchValue)); - inputActions.Add(new InputActionMapping("{LeftHand}/pointerPose", DeviceCategory.LeftHand, handEvent: HandEvent.PinchPose)); - inputActions.Add(new InputActionMapping("{LeftHand}/gripValue", DeviceCategory.LeftHand, handEvent: HandEvent.GraspValue)); - inputActions.Add(new InputActionMapping("{LeftHand}/devicePose", DeviceCategory.LeftHand, handEvent: HandEvent.GraspPose)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/selectValue", DeviceCategory.LeftHand, in_HandEvent: HandEvent.PinchValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/pointerPose", DeviceCategory.LeftHand, in_HandEvent: HandEvent.PinchPose, in_Type: kPoseType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/gripValue", DeviceCategory.LeftHand, in_HandEvent: HandEvent.GraspValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{LeftHand}/devicePose", DeviceCategory.LeftHand, in_HandEvent: HandEvent.GraspPose, in_Type: kPoseType)); - inputActions.Add(new InputActionMapping("{RightHand}/selectValue", DeviceCategory.RightHand, handEvent: HandEvent.PinchValue)); - inputActions.Add(new InputActionMapping("{RightHand}/pointerPose", DeviceCategory.RightHand, handEvent: HandEvent.PinchPose)); - inputActions.Add(new InputActionMapping("{RightHand}/gripValue", DeviceCategory.RightHand, handEvent: HandEvent.GraspValue)); - inputActions.Add(new InputActionMapping("{RightHand}/devicePose", DeviceCategory.RightHand, handEvent: HandEvent.GraspPose)); + s_InputActions.Add(new InputActionMapping("{RightHand}/selectValue", DeviceCategory.RightHand, in_HandEvent: HandEvent.PinchValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/pointerPose", DeviceCategory.RightHand, in_HandEvent: HandEvent.PinchPose, in_Type: kPoseType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/gripValue", DeviceCategory.RightHand, in_HandEvent: HandEvent.GraspValue, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{RightHand}/devicePose", DeviceCategory.RightHand, in_HandEvent: HandEvent.GraspPose, in_Type: kPoseType)); #endregion #region Tracker - inputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/devicePose/isTracked", DeviceCategory.Tracker0, poseState: PoseState.IsTracked)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/devicePosition", DeviceCategory.Tracker0, poseState: PoseState.Position)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/deviceRotation", DeviceCategory.Tracker0, poseState: PoseState.Rotation)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/devicePose/velocity", DeviceCategory.Tracker0, poseState: PoseState.Velocity)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/devicePose/angularVelocity", DeviceCategory.Tracker0, poseState: PoseState.AngularVelocity)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/devicePose/isTracked", DeviceCategory.Tracker0, in_PoseState: PoseState.IsTracked, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/devicePosition", DeviceCategory.Tracker0, in_PoseState: PoseState.Position, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/deviceRotation", DeviceCategory.Tracker0, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/devicePose/velocity", DeviceCategory.Tracker0, in_PoseState: PoseState.Velocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 0}/devicePose/angularVelocity", DeviceCategory.Tracker0, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/devicePose/isTracked", DeviceCategory.Tracker1, poseState: PoseState.IsTracked)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/devicePosition", DeviceCategory.Tracker1, poseState: PoseState.Position)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/deviceRotation", DeviceCategory.Tracker1, poseState: PoseState.Rotation)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/devicePose/velocity", DeviceCategory.Tracker1, poseState: PoseState.Velocity)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/devicePose/angularVelocity", DeviceCategory.Tracker1, poseState: PoseState.AngularVelocity)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/devicePose/isTracked", DeviceCategory.Tracker1, in_PoseState: PoseState.IsTracked, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/devicePosition", DeviceCategory.Tracker1, in_PoseState: PoseState.Position, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/deviceRotation", DeviceCategory.Tracker1, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/devicePose/velocity", DeviceCategory.Tracker1, in_PoseState: PoseState.Velocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 1}/devicePose/angularVelocity", DeviceCategory.Tracker1, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/devicePose/isTracked", DeviceCategory.Tracker2, poseState: PoseState.IsTracked)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/devicePosition", DeviceCategory.Tracker2, poseState: PoseState.Position)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/deviceRotation", DeviceCategory.Tracker2, poseState: PoseState.Rotation)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/devicePose/velocity", DeviceCategory.Tracker2, poseState: PoseState.Velocity)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/devicePose/angularVelocity", DeviceCategory.Tracker2, poseState: PoseState.AngularVelocity)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/devicePose/isTracked", DeviceCategory.Tracker2, in_PoseState: PoseState.IsTracked, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/devicePosition", DeviceCategory.Tracker2, in_PoseState: PoseState.Position, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/deviceRotation", DeviceCategory.Tracker2, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/devicePose/velocity", DeviceCategory.Tracker2, in_PoseState: PoseState.Velocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 2}/devicePose/angularVelocity", DeviceCategory.Tracker2, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/devicePose/isTracked", DeviceCategory.Tracker3, poseState: PoseState.IsTracked)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/devicePosition", DeviceCategory.Tracker3, poseState: PoseState.Position)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/deviceRotation", DeviceCategory.Tracker3, poseState: PoseState.Rotation)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/devicePose/velocity", DeviceCategory.Tracker3, poseState: PoseState.Velocity)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/devicePose/angularVelocity", DeviceCategory.Tracker3, poseState: PoseState.AngularVelocity)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/devicePose/isTracked", DeviceCategory.Tracker3, in_PoseState: PoseState.IsTracked, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/devicePosition", DeviceCategory.Tracker3, in_PoseState: PoseState.Position, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/deviceRotation", DeviceCategory.Tracker3, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/devicePose/velocity", DeviceCategory.Tracker3, in_PoseState: PoseState.Velocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 3}/devicePose/angularVelocity", DeviceCategory.Tracker3, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 4}/devicePose/isTracked", DeviceCategory.Tracker4, poseState: PoseState.IsTracked)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 4}/devicePosition", DeviceCategory.Tracker4, poseState: PoseState.Position)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 4}/deviceRotation", DeviceCategory.Tracker4, poseState: PoseState.Rotation)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 4}/devicePose/velocity", DeviceCategory.Tracker4, poseState: PoseState.Velocity)); - inputActions.Add(new InputActionMapping("{Ultimate Tracker 4}/devicePose/angularVelocity", DeviceCategory.Tracker4, poseState: PoseState.AngularVelocity)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 4}/devicePose/isTracked", DeviceCategory.Tracker4, in_PoseState: PoseState.IsTracked, in_Type: kFloatType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 4}/devicePosition", DeviceCategory.Tracker4, in_PoseState: PoseState.Position, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 4}/deviceRotation", DeviceCategory.Tracker4, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType)); + s_InputActions.Add(new InputActionMapping("{Ultimate Tracker 4}/devicePose/velocity", DeviceCategory.Tracker4, in_PoseState: PoseState.Velocity, in_Type: kVector3Type)); + s_InputActions.Add(new InputActionMapping("{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(); - if (viveHand) - { - UpdateViveHand(true, viveHand); - UpdateViveHand(false, viveHand); - } - #if UNITY_XR_HANDS - HandTracking xrHand = OpenXRSettings.Instance.GetFeature(); - 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(); - 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) - { - handSubsystem.updatedHands += OnUpdatedHands; - } } } +#else + if (m_IsSupportViveHand) + { + 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); } } #if UNITY_XR_HANDS - private static void OnUpdatedHands(XRHandSubsystem xrHnad, XRHandSubsystem.UpdateSuccessFlags flags, XRHandSubsystem.UpdateType type) + private static void OnUpdatedHands(XRHandSubsystem xrHnad, XRHandSubsystem.UpdateSuccessFlags flags, XRHandSubsystem.UpdateType type) { if (xrHnad != null && xrHnad.running) { @@ -732,42 +796,48 @@ 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) - { - leftHand.Update(joints); - } - else - { - rightHand.Update(joints); - } - } + XRHandJoint joint = (isLeft ? xrHand.leftHand : xrHand.rightHand).GetJoint(jointId); - private static XRHandJointID JointTypeToXRId(int id) - { - switch (id) - { - case 0: - return XRHandJointID.Palm; - case 1: - return XRHandJointID.Wrist; - default: - return (XRHandJointID)(id + 1); - } - } + if (isUpdated && joint.trackingState.HasFlag(XRHandJointTrackingState.Pose)) + { + joint.TryGetPose(out Pose pose); + m_JointBuffer[i] = new JointData(true, pose.position, pose.rotation); + } + else + { + m_JointBuffer[i] = new JointData(false, Vector3.zero, Quaternion.identity); + } + } + if (isLeft) + { + m_LeftHand.Update(m_JointBuffer); + } + else + { + m_RightHand.Update(m_JointBuffer); + } + } + + private static XRHandJointID JointTypeToXRId(int id) + { + switch (id) + { + case 0: + return XRHandJointID.Palm; + case 1: + return XRHandJointID.Wrist; + default: + return (XRHandJointID)(id + 1); + } + } #endif - private static DeviceCategory GetController(Handedness handedness) + private static DeviceCategory GetController(Handedness handedness) { DeviceCategory device = DeviceCategory.None; switch (handedness) diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/Passthrough/PassthroughAPI.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/Passthrough/PassthroughAPI.cs index b4aa10f..1f5c367 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/Passthrough/PassthroughAPI.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/Passthrough/PassthroughAPI.cs @@ -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 passthrough2Layer = new Dictionary(); - private static Dictionary passthrough2LayerPtr = new Dictionary(); - private static Dictionary passthrough2IsUnderLay= new Dictionary(); - private static Dictionary passthrough2meshTransform = new Dictionary(); - private static Dictionary passthrough2meshTransformInfoPtr = new Dictionary(); -#endif + private static Dictionary layersDict = new Dictionary(); #region Public APIs /// @@ -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,43 +214,18 @@ namespace VIVE.OpenXR.Passthrough return res; } -#if UNITY_STANDALONE - private static async void SubmitLayer() - { - await Task.Run(() => { - int layerListCount = 0; - while(layerListCount == 0) - { - System.Threading.Thread.Sleep(1); - XR_HTC_passthrough.Interop.GetOriginEndFrameLayerList(out List 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]); - } - } - if(layerListCount != 0) - XR_HTC_passthrough.Interop.SubmitLayers(layerList); - } - }); - - } -#endif + private static void SubmitLayer() + { + passthroughFeature.SubmitLayers(layersDict.Values.ToList()); + } - /// - /// To Destroying a passthrough. - /// You should call this function when the delegate is invoked. - /// - /// The created - /// XR_SUCCESS for success. - public static XrResult DestroyPassthrough(XrPassthroughHTC passthrough) + /// + /// To Destroying a passthrough. + /// You should call this function when the delegate is invoked. + /// + /// The created + /// XR_SUCCESS for success. + public static XrResult DestroyPassthrough(XrPassthroughHTC passthrough) { XrResult res = XrResult.XR_ERROR_RUNTIME_FAILURE; @@ -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; - } - - 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; + var layer = layersDict[passthrough]; + var xrLayer = layer.GetLayer(); + xrLayer.color.alpha = alpha; + layer.SetLayer(xrLayer); + SubmitLayer(); ret = true; } else ret = false; -#endif return ret; } @@ -425,45 +315,18 @@ namespace VIVE.OpenXR.Passthrough return ret; } - XrVector3f[] vertexBufferXrVector = new XrVector3f[vertexBuffer.Length]; + if (layersDict[passthrough] == null) + { + ERROR("Passthrough layer not found."); + return ret; + } - for (int i = 0; i < vertexBuffer.Length; i++) - { - 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 - return ret; + var layer = layersDict[passthrough]; + var xrMesh = layer.GetMesh(); + layer.SetMeshData(ref xrMesh, vertexBuffer, indexBuffer, convertFromUnityToOpenXR); + layer.SetMeshTransform(xrMesh); + SubmitLayer(); + return true; } /// @@ -508,29 +371,22 @@ namespace VIVE.OpenXR.Passthrough XrVector3f meshXrScale = OpenXRHelper.ToOpenXRVector(meshScale, false); -#if UNITY_STANDALONE - if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough)) - { - 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 (layersDict[passthrough] == null) + { + ERROR("Passthrough layer not found."); + return ret; + } -#if UNITY_ANDROID - ret = passthroughFeature.SetMeshTransform(passthrough, passthroughFeature.GetXrSpaceFromSpaceType(spaceType), meshXrPose, meshXrScale); - DEBUG("SetProjectedPassthroughMeshTransform() SetMeshTransform result: " + ret + ", passthrough: " + passthrough); -#endif - 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; } /// @@ -550,22 +406,18 @@ namespace VIVE.OpenXR.Passthrough return ret; } -#if UNITY_STANDALONE - if (passthrough2IsUnderLay.ContainsKey(passthrough)) - { - passthrough2IsUnderLay[passthrough] = layerType == CompositionLayer.LayerType.Underlay ? true : false; - SubmitLayer(); - ret = true; - } - else - ret = false; -#endif + if (layersDict[passthrough] == null) + { + ERROR("Passthrough layer not found."); + return ret; + } -#if UNITY_ANDROID - ret = passthroughFeature.SetLayerType(passthrough, layerType, compositionDepth); - DEBUG("SetPassthroughLayerType() SetLayerType result: " + ret + ", passthrough: " + passthrough); -#endif - return ret; + var layer = layersDict[passthrough]; + layer.LayerType = layerType; + layer.Depth = (int)compositionDepth; + + SubmitLayer(); + return true; } /// @@ -584,28 +436,18 @@ namespace VIVE.OpenXR.Passthrough return ret; } -#if UNITY_STANDALONE - if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough)) - { - 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 (layersDict[passthrough] == null) + { + ERROR("Passthrough layer not found."); + return ret; + } -#if UNITY_ANDROID - ret = passthroughFeature.SetMeshTransformSpace(passthrough, passthroughFeature.GetXrSpaceFromSpaceType(spaceType)); - DEBUG("SetProjectedPassthroughSpaceType() SetMeshTransformSpace result: " + ret + ", passthrough: " + passthrough); -#endif - return ret; + var layer = layersDict[passthrough]; + var xrMesh = layer.GetMesh(); + xrMesh.baseSpace = passthroughFeature.GetXrSpaceFromSpaceType(spaceType); + layer.SetMeshTransform(xrMesh); + SubmitLayer(); + return true; } /// @@ -639,30 +481,18 @@ namespace VIVE.OpenXR.Passthrough trackingSpaceMeshPosition = trackingSpaceLayerPoseTRS.GetColumn(3); //4th Column of TRS Matrix is the position } -#if UNITY_STANDALONE - if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough)) - { - 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 (layersDict[passthrough] == null) + { + ERROR("Passthrough layer not found."); + return ret; + } -#if UNITY_ANDROID - ret = passthroughFeature.SetMeshTransformPosition(passthrough, OpenXRHelper.ToOpenXRVector(trackingSpaceMeshPosition, convertFromUnityToOpenXR)); - DEBUG("SetProjectedPassthroughMeshPosition() SetMeshTransformPosition result: " + ret + ", passthrough: " + passthrough); -#endif - return ret; + var layer = layersDict[passthrough]; + var xrMesh = layer.GetMesh(); + xrMesh.pose.position = OpenXRHelper.ToOpenXRVector(trackingSpaceMeshPosition, convertFromUnityToOpenXR); + layer.SetMeshTransform(xrMesh); + SubmitLayer(); + return true; } /// @@ -696,30 +526,18 @@ namespace VIVE.OpenXR.Passthrough trackingSpaceMeshRotation = Quaternion.LookRotation(trackingSpaceLayerPoseTRS.GetColumn(2), trackingSpaceLayerPoseTRS.GetColumn(1)); } -#if UNITY_STANDALONE - if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough)) - { - 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 (layersDict[passthrough] == null) + { + ERROR("Passthrough layer not found."); + return ret; + } -#if UNITY_ANDROID - ret = passthroughFeature.SetMeshTransformOrientation(passthrough, OpenXRHelper.ToOpenXRQuaternion(trackingSpaceMeshRotation, convertFromUnityToOpenXR)); - DEBUG("SetProjectedPassthroughMeshOrientation() SetMeshTransformOrientation result: " + ret + ", passthrough: " + passthrough); -#endif - return ret; + var layer = layersDict[passthrough]; + var xrMesh = layer.GetMesh(); + xrMesh.pose.orientation = OpenXRHelper.ToOpenXRQuaternion(trackingSpaceMeshRotation, convertFromUnityToOpenXR); + layer.SetMeshTransform(xrMesh); + SubmitLayer(); + return true; } /// @@ -738,28 +556,18 @@ namespace VIVE.OpenXR.Passthrough return ret; } -#if UNITY_STANDALONE - if (passthrough2meshTransformInfoPtr.ContainsKey(passthrough)) - { - 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 (layersDict[passthrough] == null) + { + ERROR("Passthrough layer not found."); + return ret; + } -#if UNITY_ANDROID - ret = passthroughFeature.SetMeshTransformScale(passthrough, OpenXRHelper.ToOpenXRVector(meshScale, false)); - DEBUG("SetProjectedPassthroughScale() SetMeshTransformScale result: " + ret + ", passthrough: " + passthrough); -#endif - return ret; + var layer = layersDict[passthrough]; + var xrMesh = layer.GetMesh(); + xrMesh.scale = OpenXRHelper.ToOpenXRVector(meshScale, false); + layer.SetMeshTransform(xrMesh); + SubmitLayer(); + return true; } /// diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Resources/Prefabs/VIVEXRHandGrabberLeft.prefab b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Resources/Prefabs/VIVEXRHandGrabberLeft.prefab index bfa7016..e0ad0ef 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Resources/Prefabs/VIVEXRHandGrabberLeft.prefab +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Resources/Prefabs/VIVEXRHandGrabberLeft.prefab @@ -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 diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Resources/Prefabs/VIVEXRHandGrabberRight.prefab b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Resources/Prefabs/VIVEXRHandGrabberRight.prefab index 15649f5..5b422f8 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Resources/Prefabs/VIVEXRHandGrabberRight.prefab +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Resources/Prefabs/VIVEXRHandGrabberRight.prefab @@ -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 diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/CustomGrabPose.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/CustomGrabPose.cs index 96bd583..d53933c 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/CustomGrabPose.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/CustomGrabPose.cs @@ -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); + } + } + /// /// Finds the nearest interactable object to the hand. /// diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/HandGrabInteractable.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/HandGrabInteractable.cs index 1be89fd..e3a0160 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/HandGrabInteractable.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/HandGrabInteractable.cs @@ -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; @@ -87,8 +86,8 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction [SerializeField] private IOneHandContraintMovement m_OneHandContraintMovement; - public IOneHandContraintMovement oneHandContraintMovement { get { return m_OneHandContraintMovement; } set { m_OneHandContraintMovement = value; } } - public bool isContraint => m_OneHandContraintMovement != null; + public IOneHandContraintMovement oneHandContraintMovement { get { return m_OneHandContraintMovement; } set { m_OneHandContraintMovement = value; } } + public bool isContraint => m_OneHandContraintMovement != null; #pragma warning disable [SerializeField] @@ -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); } /// @@ -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 /// The index of the indicator to show. 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 /// Whether the hand side is left. 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) { diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/HandGrabInteractor.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/HandGrabInteractor.cs index 3d305cc..0542292 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/HandGrabInteractor.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/Grab/HandGrabInteractor.cs @@ -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 lruList = new LinkedList(); + private Dictionary> unusedColliders = new Dictionary>(); + #region MonoBehaviour private void Awake() { @@ -159,7 +165,6 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction /// 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 nearHandGrabInteractables = new List(); - for (int i = 0; i < nearColliders.Length; i++) + for (int i = 0; i < lastBufferCount; i++) { - HandGrabInteractable interactable = nearColliders[i].GetComponentInParent(); - if (interactable && !nearHandGrabInteractables.Contains(interactable)) - { - nearHandGrabInteractables.Add(interactable); - continue; - } - interactable = nearColliders[i].GetComponentInChildren(); - 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() + ?? collider.GetComponentInChildren(); + 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; + } } } diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandColliderController.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandColliderController.cs index 194b668..84ed55e 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandColliderController.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandColliderController.cs @@ -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 collisionDirections = new List(); + 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; @@ -175,7 +182,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction } } - #endregion +#endregion private IEnumerator WaitForInit() { @@ -232,33 +239,41 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction Vector3 vel = (lastRootPos - rootJoint.position) / Time.deltaTime; if (IsValidVelocity(vel)) { - if (collisionDirections.Count > 0) + lock (collisionLock) { - float minAngle = float.MaxValue; - Vector3 closestDirection = Vector3.zero; - foreach (Vector3 direction in collisionDirections.ToList()) + if (currentCollisionCount > 0) { - float angle = Mathf.Abs(Vector3.Angle(direction, vel)); - if (angle < minAngle) - { - minAngle = angle; - closestDirection = direction; - } - } - collisionDirections.Clear(); + float minAngle = float.MaxValue; + Vector3 closestDirection = Vector3.zero; - Vector3 adjustedDirection = closestDirection; - if (Vector3.Dot(vel, closestDirection) > 0) - { - adjustedDirection *= -1f; - } - vel = Vector3.ProjectOnPlane(vel, adjustedDirection); - if (vel.magnitude > 1) - { - vel.Normalize(); + for (int i = 0; i < currentCollisionCount; i++) + { + Vector3 direction = collisionsDirection[i]; + float angle = Mathf.Abs(Vector3.Angle(direction, vel)); + if (angle < minAngle) + { + minAngle = angle; + closestDirection = direction; + } + } + Vector3 adjustedDirection = closestDirection; + if (Vector3.Dot(vel, closestDirection) > 0) + { + adjustedDirection *= -1f; + } + vel = Vector3.ProjectOnPlane(vel, adjustedDirection); + if (vel.magnitude > 1) + { + vel.Normalize(); + } + currentCollisionCount = 0; } } +#if UNITY_6000_0_OR_NEWER + rootJointRigidbody.linearVelocity = vel; +#else rootJointRigidbody.velocity = vel; +#endif } } @@ -287,7 +302,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction && !float.IsInfinity(vector.x) && !float.IsInfinity(vector.y) && !float.IsInfinity(vector.z); } - #region Event CallBack +#region Event CallBack /// /// When tracking state changing, reset the pose and enable/disable collider. @@ -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,17 +374,21 @@ 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; } } - #endregion +#endregion } } diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandInteractionUtils.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandInteractionUtils.cs index 763effa..c0f5eaa 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandInteractionUtils.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandInteractionUtils.cs @@ -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 /// True if the hand is left; otherwise, false. 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 + }; + } + /// /// Update the data for the left or right hand. /// @@ -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 /// True to enable the indicator, false to deactivate it. 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; + } } } diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandPose/MeshHandPose.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandPose/MeshHandPose.cs index a7d95bd..1cf3029 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandPose/MeshHandPose.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandPose/MeshHandPose.cs @@ -7,7 +7,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction { [SerializeField] private HandMeshManager m_HandMesh; - + private bool keepUpdate = false; protected override void OnEnable() @@ -18,11 +18,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction protected override void OnDisable() { base.OnDisable(); - if (keepUpdate) - { - keepUpdate = false; - StopCoroutine(UpdatePose()); - } + keepUpdate = false; } public void SetHandMeshRenderer(HandMeshManager handMeshRenderer) @@ -44,39 +40,32 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction { yield return new WaitUntil(() => m_Initialized); base.OnEnable(); - if (!keepUpdate) - { - keepUpdate = true; - StartCoroutine(UpdatePose()); - } + keepUpdate = true; } - private IEnumerator UpdatePose() + private void Update() { - while (keepUpdate) + 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++) { - yield return new WaitForFixedUpdate(); - - HandPose handPose = HandPoseProvider.GetHandPose(m_HandMesh.isLeft ? HandPoseType.HAND_LEFT : HandPoseType.HAND_RIGHT); - m_IsTracked = handPose.IsTracked(); - - for (int i = 0; i < poseCount; i++) + if (m_HandMesh.GetJointPositionAndRotation((JointType)i, out Vector3 position, out Quaternion rotation) && + m_HandMesh.GetJointPositionAndRotation((JointType)i, out Vector3 localPosition, out Quaternion localRotation, local: true)) { - if (m_HandMesh.GetJointPositionAndRotation((JointType)i, out Vector3 position, out Quaternion rotation) && - m_HandMesh.GetJointPositionAndRotation((JointType)i, out Vector3 localPosition, out Quaternion localRotation, local: true)) - { - m_Position[i] = position; - m_Rotation[i] = rotation; - m_LocalPosition[i] = localPosition; - m_LocalRotation[i] = localRotation; - } - else - { - m_Position[i] = Vector3.zero; - m_Rotation[i] = Quaternion.identity; - m_LocalPosition[i] = Vector3.zero; - m_LocalRotation[i] = Quaternion.identity; - } + m_Position[i] = position; + m_Rotation[i] = rotation; + m_LocalPosition[i] = localPosition; + m_LocalRotation[i] = localRotation; + } + else + { + m_Position[i] = Vector3.zero; + m_Rotation[i] = Quaternion.identity; + m_LocalPosition[i] = Vector3.zero; + m_LocalRotation[i] = Quaternion.identity; } } } diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandPose/RealHandPose.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandPose/RealHandPose.cs index 9832ebe..c5463f3 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandPose/RealHandPose.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/HandPose/RealHandPose.cs @@ -18,11 +18,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction protected override void OnDisable() { base.OnDisable(); - if (keepUpdate) - { - keepUpdate = false; - StopCoroutine(UpdatePose()); - } + keepUpdate = false; } public override void SetType(HandPoseType poseType) @@ -43,41 +39,33 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction { yield return new WaitUntil(() => m_Initialized); base.OnEnable(); - if (!keepUpdate) - { - keepUpdate = true; - StartCoroutine(UpdatePose()); - } + keepUpdate = true; } - private IEnumerator UpdatePose() + private void Update() { + if (!keepUpdate) { return; } + HandData handData = CachedHand.Get(isLeft); + m_IsTracked = handData.isTracked; + if (!m_IsTracked) { return; } + Vector3 position = Vector3.zero; Quaternion rotation = Quaternion.identity; - while (keepUpdate) + for (int i = 0; i < poseCount; i++) { - yield return new WaitForEndOfFrame(); - - HandData handData = CachedHand.Get(isLeft); - m_IsTracked = handData.isTracked; - if (!m_IsTracked) { continue; } - - for (int i = 0; i < poseCount; i++) + if (handData.GetJointPosition((JointType)i, ref position) && handData.GetJointRotation((JointType)i, ref rotation)) { - if (handData.GetJointPosition((JointType)i, ref position) && handData.GetJointRotation((JointType)i, ref rotation)) - { - m_Position[i] = transform.position + transform.rotation * position; - m_Rotation[i] = transform.rotation * rotation; - m_LocalPosition[i] = position; - m_LocalRotation[i] = rotation; - } - else - { - m_Position[i] = Vector3.zero; - m_Rotation[i] = Quaternion.identity; - m_LocalPosition[i] = Vector3.zero; - m_LocalRotation[i] = Quaternion.identity; - } + m_Position[i] = transform.position + transform.rotation * position; + m_Rotation[i] = transform.rotation * rotation; + m_LocalPosition[i] = position; + m_LocalRotation[i] = rotation; + } + else + { + m_Position[i] = Vector3.zero; + m_Rotation[i] = Quaternion.identity; + m_LocalPosition[i] = Vector3.zero; + m_LocalRotation[i] = Quaternion.identity; } } } diff --git a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/PhysicsInteractable.cs b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/PhysicsInteractable.cs index 9b13b9c..843cd88 100644 --- a/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/PhysicsInteractable.cs +++ b/com.htc.upm.vive.openxr/Runtime/Toolkits/RealisticHandInteraction(experimental)/Scripts/PhysicsInteractable.cs @@ -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 movementPoses = new List(); - private List timestamps = new List(); + 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 velocities = new List(); - 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; } diff --git a/com.htc.upm.vive.openxr/Runtime/VIVE.OpenXR.asmdef b/com.htc.upm.vive.openxr/Runtime/VIVE.OpenXR.asmdef index 9fa3941..af57bc8 100644 --- a/com.htc.upm.vive.openxr/Runtime/VIVE.OpenXR.asmdef +++ b/com.htc.upm.vive.openxr/Runtime/VIVE.OpenXR.asmdef @@ -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", @@ -41,4 +46,4 @@ } ], "noEngineReferences": false -} \ No newline at end of file +} diff --git a/com.htc.upm.vive.openxr/Runtime/VIVEFocus3Profile.cs b/com.htc.upm.vive.openxr/Runtime/VIVEFocus3Profile.cs index 36802e4..20f0ee7 100644 --- a/com.htc.upm.vive.openxr/Runtime/VIVEFocus3Profile.cs +++ b/com.htc.upm.vive.openxr/Runtime/VIVEFocus3Profile.cs @@ -48,7 +48,7 @@ namespace VIVE.OpenXR public class VIVEFocus3Profile : OpenXRInteractionFeature { #region Log - const string LOG_TAG = "VIVE.OpenXR.VIVEFocus3Profile"; + const string LOG_TAG = "VIVE.OpenXR.VIVEFocus3Profile "; StringBuilder m_sb = null; StringBuilder sb { get { @@ -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 /// /// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents the OpenXR binding. /// @@ -145,7 +147,7 @@ namespace VIVE.OpenXR /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the OpenXR binding. /// [Preserve, InputControl(aliases = new[] { "indexButton", "triggerButton" }, usage = "TriggerButton")] - public ButtonControl triggerPressed { get; private set; } + public ButtonControl triggerPressed { get; private set; } // InputControl(offset = 20) /// /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the OpenXR binding. @@ -157,7 +159,7 @@ namespace VIVE.OpenXR /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the OpenXR binding. /// [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) /// /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the OpenXR binding. @@ -169,31 +171,31 @@ namespace VIVE.OpenXR /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the OpenXR binding. /// [Preserve, InputControl(aliases = new[] { "ParkingTouched", "parkingTouched" })] - public ButtonControl thumbrestTouched { get; private set; } + public ButtonControl thumbrestTouched { get; private set; } // InputControl(offset = 24) + #endregion /// /// A that represents the OpenXR binding. The grip pose represents the location of the user's palm or holding a motion controller. /// [Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")] public PoseControl devicePose { get; private set; } - /// /// A that represents the OpenXR binding. The pointer pose represents the tip of the controller pointing forward. /// [Preserve, InputControl(offset = 0, aliases = new[] { "aimPose", "pointerPose" }, usage = "Pointer")] public PoseControl pointer { get; private set; } -#if UNITY_ANDROID - /// - /// A representing the OpenXR binding. - /// - [Preserve, InputControl(offset = 0, alias = "indexTip", usage = "Poke")] - public PoseControl pokePose { get; private set; } +#if UNITY_ANDROID /// /// A representing the OpenXR binding. /// [Preserve, InputControl(offset = 0, usage = "Pinch")] public PoseControl pinchPose { get; private set; } + /// + /// A representing the OpenXR binding. + /// + [Preserve, InputControl(offset = 0, alias = "indexTip", usage = "Poke")] + public PoseControl pokePose { get; private set; } #endif /// @@ -227,28 +229,29 @@ namespace VIVE.OpenXR /// [Preserve, InputControl(offset = 104, noisy = true, alias = "pointerOrientation")] public QuaternionControl pointerRotation { get; private set; } -#if UNITY_ANDROID - /// - /// 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. - /// - [Preserve, InputControl(offset = 152, noisy = true)] - public Vector3Control pokePosition { get; private set; } - /// - /// 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. - /// - [Preserve, InputControl(offset = 164, noisy = true)] - public QuaternionControl pokeRotation { get; private set; } +#if UNITY_ANDROID /// /// 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. /// - [Preserve, InputControl(offset = 212, noisy = true)] + [Preserve, InputControl(offset = 152, noisy = true)] public Vector3Control pinchPosition { get; private set; } /// /// 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. /// - [Preserve, InputControl(offset = 224, noisy = true)] + [Preserve, InputControl(offset = 164, noisy = true)] public QuaternionControl pinchRotation { get; private set; } + + /// + /// 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. + /// + [Preserve, InputControl(offset = 212, noisy = true)] + public Vector3Control pokePosition { get; private set; } + /// + /// 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. + /// + [Preserve, InputControl(offset = 224, noisy = true)] + public QuaternionControl pokeRotation { get; private set; } #endif /// /// A that represents the binding. diff --git a/com.htc.upm.vive.openxr/Runtime/VIVERig.cs b/com.htc.upm.vive.openxr/Runtime/VIVERig.cs index 26f4401..732536b 100644 --- a/com.htc.upm.vive.openxr/Runtime/VIVERig.cs +++ b/com.htc.upm.vive.openxr/Runtime/VIVERig.cs @@ -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 s_InputSubsystems = new List(); + private static readonly List s_InputSubsystems = new List(); + 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,37 +88,17 @@ 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(); - sb.Clear().Append("Update() Tracking mode is set to " + mode); - m_TrackingOriginEx = m_TrackingOrigin; - } + 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); + } } } diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Anchor/Scripts/AnchorTestHandle.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Anchor/Scripts/AnchorTestHandle.cs index 9eeea90..4977d0c 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Anchor/Scripts/AnchorTestHandle.cs +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Anchor/Scripts/AnchorTestHandle.cs @@ -124,7 +124,7 @@ namespace VIVE.OpenXR.Samples.Anchor void GetXRInputSubsystem() { List xrSubsystemList = new List(); - 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 diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/ActionMap/InputActions.inputactions b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/ActionMap/InputActions.inputactions index 9c3c2ff..888649f 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/ActionMap/InputActions.inputactions +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/ActionMap/InputActions.inputactions @@ -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 diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug.meta b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug.meta new file mode 100644 index 0000000..1bacff8 --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fa549247e9994a84697e73e6d1288e2b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugIsTrackedOffset.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugIsTrackedOffset.cs new file mode 100644 index 0000000..e228231 --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugIsTrackedOffset.cs @@ -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(); + } + 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; + } + } + } +} diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugIsTrackedOffset.cs.meta b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugIsTrackedOffset.cs.meta new file mode 100644 index 0000000..b733ef6 --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugIsTrackedOffset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c5ffdf8ced75cf41a74cb761a3987dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugPoseData.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugPoseData.cs new file mode 100644 index 0000000..6e71407 --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugPoseData.cs @@ -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(); + } + + 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; + } + } + } + } +} diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugPoseData.cs.meta b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugPoseData.cs.meta new file mode 100644 index 0000000..64d5bf0 --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/Debug/DebugPoseData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 04725f4c022874d40a6e786b002b782a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/HideObjectWhenUntracked.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/HideObjectWhenUntracked.cs index c769031..88738d0 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/HideObjectWhenUntracked.cs +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Commons/Script/HideObjectWhenUntracked.cs @@ -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 } } } diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Scenes/CompositionLayerTest_Equirect.unity b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Scenes/CompositionLayerTest_Equirect.unity new file mode 100644 index 0000000..a5df9fe --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Scenes/CompositionLayerTest_Equirect.unity @@ -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} diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Scenes/CompositionLayerTest_Equirect.unity.meta b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Scenes/CompositionLayerTest_Equirect.unity.meta new file mode 100644 index 0000000..0a4e279 --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Scenes/CompositionLayerTest_Equirect.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c44817993abad6145928810ed11e7e49 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Textures/pixel360.jpg b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Textures/pixel360.jpg new file mode 100644 index 0000000..6610dc1 --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Textures/pixel360.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6dc0e85f9cdaa725ab8f36b7650cafb7fc690e80504a7113c644f94e5b6a14f +size 7683524 diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Textures/pixel360.jpg.meta b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Textures/pixel360.jpg.meta new file mode 100644 index 0000000..f659f1c --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/CompositionLayer2/Textures/pixel360.jpg.meta @@ -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: diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/FacialTracking/ViveSR/Models/version2/Avatar_Shieh/Avatar_Shieh_V2.fbx b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/FacialTracking/ViveSR/Models/version2/Avatar_Shieh/Avatar_Shieh_V2.fbx index e1a9fab..18bfe2e 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/FacialTracking/ViveSR/Models/version2/Avatar_Shieh/Avatar_Shieh_V2.fbx +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/FacialTracking/ViveSR/Models/version2/Avatar_Shieh/Avatar_Shieh_V2.fbx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2df92bbb1ab2081169abde24bd1724afcc507c8eedf1aa9535faf80d349bf72 -size 15079679 +oid sha256:a408ee55e903ecccaba43951c19bb53ec5a2b6924b26fc0a8ffac445861362cf +size 15088903 diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/FacialTracking/ViveSR/Models/version2/Avatar_Shieh/Materials/eyelash_mat.mat b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/FacialTracking/ViveSR/Models/version2/Avatar_Shieh/Materials/eyelash_mat.mat index 97ebea5..c6663f4 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/FacialTracking/ViveSR/Models/version2/Avatar_Shieh/Materials/eyelash_mat.mat +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/FacialTracking/ViveSR/Models/version2/Avatar_Shieh/Materials/eyelash_mat.mat @@ -22,6 +22,7 @@ Material: RenderType: Transparent disabledShaderPasses: - GRABPASS + - ALWAYS m_SavedProperties: serializedVersion: 3 m_TexEnvs: diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/HandInteractionExt/HandInteractionExt.inputactions b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/HandInteractionExt/HandInteractionExt.inputactions index 7aa5e1a..4628edb 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/HandInteractionExt/HandInteractionExt.inputactions +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/HandInteractionExt/HandInteractionExt.inputactions @@ -54,6 +54,17 @@ "isComposite": false, "isPartOfComposite": false }, + { + "name": "", + "id": "068b86ec-3f14-4d24-9b42-7057d00ab904", + "path": "{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": "{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": "{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": "{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": "{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": "{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": "{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": "{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": "{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": "{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": "{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": "{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": "{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": "{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": "{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": "{LeftHand}/pointerActivateReady", + "interactions": "", + "processors": "", + "groups": "", + "action": "ReadyL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "4af711ee-8f25-4a6b-900b-cce9a68655de", + "path": "{LeftHand}/pointerPosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "056d875e-56e5-4783-b73c-7d2a83407530", + "path": "{LeftHand}/pointerPosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "d47309f6-c5d1-4892-bf76-e51faa8b6137", + "path": "{LeftHand}/pointerRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "f4fade07-9a27-4a3a-9145-87fc4e6fc282", + "path": "{LeftHand}/pointerRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "61444e1e-91f4-45a7-8104-93317a4fcfa8", + "path": "{RightHand}/pointerPosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "d66724bb-6f33-46eb-8205-3912e3cdb72d", + "path": "{RightHand}/pointerPosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "3f05dfd2-7dcb-46ee-a8c8-20c921c62793", + "path": "{RightHand}/pointerRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "c3aa63db-3ff8-4206-b62a-d1caf6ffafd5", + "path": "{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": "{LeftHand}/pokePose", + "interactions": "", + "processors": "", + "groups": "", + "action": "PoseL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "8e9539c4-4aca-471f-b843-bd282a33616b", + "path": "{LeftHand}/pokePose", + "interactions": "", + "processors": "", + "groups": "", + "action": "PoseL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "124f3c45-0d83-4302-9f2a-cb945f7c268e", + "path": "{RightHand}/pokePose", + "interactions": "", + "processors": "", + "groups": "", + "action": "PoseR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "d6bd90fd-f8ab-4cc7-ab90-c604788b32e8", + "path": "{RightHand}/pokePose", + "interactions": "", + "processors": "", + "groups": "", + "action": "PoseR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "29fcebb4-1111-4c52-becf-a20a4919c8bd", + "path": "{RightHand}/pokePosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "3f1a484f-a430-4f62-9587-47944d3ceb8a", + "path": "{RightHand}/pokePosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "72bb3809-4dba-4b8c-a35a-6c2078873256", + "path": "{LeftHand}/pokeRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "c64e7c60-8e41-47d7-80b3-8f8dd7c17071", + "path": "{LeftHand}/pokeRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "cae2d11b-bd7f-4fc4-b247-c21af26cf2d5", + "path": "{RightHand}/pokeRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "59f0ff0b-c894-4fb7-b775-7a8dbc56c718", + "path": "{RightHand}/pokeRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "79dfac35-3c6f-45b2-8045-eeba5534cb14", + "path": "{LeftHand}/pokePosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "6b420474-04e5-46bb-b76f-a4aef922dac4", + "path": "{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": "{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": "{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": "{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": "{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": "{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": "{LeftHand}/pokePose", + "id": "136c49a3-8f2b-476b-9adf-98e7ed1e6e9a", + "path": "{LeftHand}/pinchReady", "interactions": "", "processors": "", "groups": "", - "action": "PoseL", + "action": "ReadyL", "isComposite": false, "isPartOfComposite": false }, { "name": "", - "id": "124f3c45-0d83-4302-9f2a-cb945f7c268e", - "path": "{RightHand}/pokePose", + "id": "9221267c-62a0-47cb-aeba-aca47714c033", + "path": "{LeftHand}/pinchRotation", "interactions": "", "processors": "", "groups": "", - "action": "PoseR", + "action": "RotationL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "b4dcfb93-89e5-45cf-bde0-6c2adea454b3", + "path": "{LeftHand}/pinchRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "b841def8-addf-4eae-808f-5160a5ff3ed5", + "path": "{LeftHand}/pinchPosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "3253d57e-11aa-4449-8960-16e8911854d5", + "path": "{LeftHand}/pinchPosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionL", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "88a63c73-43a1-469c-99b0-ef08bd0b95e7", + "path": "{RightHand}/pinchPosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "bf69fb00-cf5a-40da-a774-437f1ea76d44", + "path": "{RightHand}/pinchPosition", + "interactions": "", + "processors": "", + "groups": "", + "action": "PositionR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "7f0a8dc7-c33a-4811-ad95-367df499cfb8", + "path": "{RightHand}/pinchRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationR", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "ef207392-905c-4a08-9e1f-7bdf0b66069a", + "path": "{RightHand}/pinchRotation", + "interactions": "", + "processors": "", + "groups": "", + "action": "RotationR", "isComposite": false, "isPartOfComposite": false } diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/HandInteractionExt/HandInteractionExt.unity b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/HandInteractionExt/HandInteractionExt.unity index 382ac2d..c784306 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/HandInteractionExt/HandInteractionExt.unity +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/HandInteractionExt/HandInteractionExt.unity @@ -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: {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: {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: {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: {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: {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: {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: {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: {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: {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: {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: {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: {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: {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: {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: {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: {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 diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/OpenXRInput.unity b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/OpenXRInput.unity index 7bc69bf..cee5052 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/OpenXRInput.unity +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/OpenXRInput.unity @@ -844,6 +844,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 0 m_Action: @@ -884,6 +885,18 @@ MonoBehaviour: m_Flags: 0 m_Flags: 0 m_Reference: {fileID: 0} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: Position m_Type: 0 @@ -918,7 +931,6 @@ MonoBehaviour: m_Action: Rotation m_Flags: 0 m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &44028069 GameObject: m_ObjectHideFlags: 0 @@ -1322,6 +1334,84 @@ MonoBehaviour: m_OnValueChanged: m_PersistentCalls: m_Calls: [] +--- !u!1 &95751956 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 95751957} + - component: {fileID: 95751959} + - component: {fileID: 95751958} + m_Layer: 0 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &95751957 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 95751956} + 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: + - {fileID: 1807340437} + - {fileID: 1301415412} + m_Father: {fileID: 1335781104} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &95751958 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 95751956} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &95751959 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 95751956} + m_CullTransparentMesh: 1 --- !u!1 &99841488 GameObject: m_ObjectHideFlags: 0 @@ -2481,7 +2571,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &169007645 RectTransform: m_ObjectHideFlags: 0 @@ -2843,6 +2933,105 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 202480261} m_CullTransparentMesh: 0 +--- !u!1 &204292438 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 204292439} + - component: {fileID: 204292442} + - component: {fileID: 204292441} + - component: {fileID: 204292443} + m_Layer: 0 + m_Name: ControllerDeviceLText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &204292439 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 204292438} + 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: 2115463875} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 200} + m_SizeDelta: {x: 780, y: 210} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &204292441 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 204292438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.860898, g: 0.8773585, b: 0.1779548, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 3 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Pose +--- !u!222 &204292442 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 204292438} + m_CullTransparentMesh: 1 +--- !u!114 &204292443 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 204292438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 04725f4c022874d40a6e786b002b782a, type: 3} + m_Name: + m_EditorClassIdentifier: + PoseName: Controller Device Left + isTracked: {fileID: 3005817691354473129, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + trackingState: {fileID: 5178774767481721072, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + position: {fileID: 9019252231132517785, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + rotation: {fileID: -22420666449113973, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + pose: {fileID: -1624222239408711063, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} --- !u!1 &205297455 GameObject: m_ObjectHideFlags: 0 @@ -3348,8 +3537,8 @@ RectTransform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 247509055} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0.015, y: 0.015, z: 0.015} + m_LocalPosition: {x: 0, y: 0, z: 10} + m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 343022093} @@ -3417,7 +3606,7 @@ Canvas: m_SortingBucketNormalizedSize: 0 m_AdditionalShaderChannelsFlag: 0 m_SortingLayerID: 0 - m_SortingOrder: 0 + m_SortingOrder: 3000 m_TargetDisplay: 0 --- !u!1 &251179011 GameObject: @@ -4122,6 +4311,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 1 m_Action: @@ -4146,6 +4336,18 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: 3242339893588026215, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: m_Type: 0 @@ -4164,7 +4366,6 @@ MonoBehaviour: m_Interactions: m_SingletonActionBindings: [] m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1001 &308409639 PrefabInstance: m_ObjectHideFlags: 0 @@ -4700,6 +4901,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 1 m_Action: @@ -4724,6 +4926,18 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: -2199575455336610917, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: m_Type: 0 @@ -4742,7 +4956,6 @@ MonoBehaviour: m_Interactions: m_SingletonActionBindings: [] m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &354515905 GameObject: m_ObjectHideFlags: 0 @@ -4798,6 +5011,105 @@ MonoBehaviour: enabledColor: {r: 0, g: 1, b: 0, a: 1} disabledColor: {r: 1, g: 0, b: 0, a: 1} image: {fileID: 614512880} +--- !u!1 &360924782 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 360924783} + - component: {fileID: 360924786} + - component: {fileID: 360924785} + - component: {fileID: 360924784} + m_Layer: 0 + m_Name: ControllerPointerLText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &360924783 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 360924782} + 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: 2115463875} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -10} + m_SizeDelta: {x: 780, y: 210} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &360924784 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 360924782} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 04725f4c022874d40a6e786b002b782a, type: 3} + m_Name: + m_EditorClassIdentifier: + PoseName: Controller Pointer Left + isTracked: {fileID: 0} + trackingState: {fileID: 0} + position: {fileID: 1805487408676636314, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + rotation: {fileID: -3341103204585363708, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + pose: {fileID: -6495569650943898615, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} +--- !u!114 &360924785 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 360924782} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.860898, g: 0.8773585, b: 0.1779548, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 3 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Pose +--- !u!222 &360924786 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 360924782} + m_CullTransparentMesh: 1 --- !u!1 &366208948 GameObject: m_ObjectHideFlags: 0 @@ -5738,6 +6050,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 0 m_Action: @@ -5778,6 +6091,18 @@ MonoBehaviour: m_Flags: 0 m_Flags: 0 m_Reference: {fileID: 0} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: m_Type: 0 @@ -5796,7 +6121,6 @@ MonoBehaviour: m_Interactions: m_SingletonActionBindings: [] m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &474357745 GameObject: m_ObjectHideFlags: 0 @@ -6928,6 +7252,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 0 m_Action: @@ -6968,6 +7293,18 @@ MonoBehaviour: m_Flags: 0 m_Flags: 0 m_Reference: {fileID: 0} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: Position m_Type: 0 @@ -7002,7 +7339,6 @@ MonoBehaviour: m_Action: Rotation m_Flags: 0 m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &579305141 GameObject: m_ObjectHideFlags: 0 @@ -10137,13 +10473,15 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 855247512} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -3.41, y: -0.24, z: 2} + m_LocalPosition: {x: 0, y: 0, z: 2} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - {fileID: 867397450} - {fileID: 169007645} - {fileID: 1654580157} + - {fileID: 1232393573} + - {fileID: 1335781104} m_Father: {fileID: 1588199579} m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -10499,7 +10837,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 3, y: 0.368} + m_AnchoredPosition: {x: -0.5, y: 0.05} m_SizeDelta: {x: 400, y: 140} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &867397451 @@ -11254,6 +11592,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 1 m_Action: @@ -11278,6 +11617,18 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: -4462678269106331646, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: m_Type: 0 @@ -11296,7 +11647,6 @@ MonoBehaviour: m_Interactions: m_SingletonActionBindings: [] m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &983759432 GameObject: m_ObjectHideFlags: 0 @@ -12155,6 +12505,7 @@ GameObject: - component: {fileID: 1060976102} - component: {fileID: 1060976104} - component: {fileID: 1060976105} + - component: {fileID: 1060976106} m_Layer: 0 m_Name: PlayerRig m_TagString: Untagged @@ -12268,6 +12619,18 @@ MonoBehaviour: Enabled: 1 m_HandRaycast: Enabled: 1 +--- !u!114 &1060976106 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1060976100} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7f60faf6b28b7954b9ddf397eda40dc7, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &1062713251 GameObject: m_ObjectHideFlags: 0 @@ -14700,6 +15063,107 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1228911008} m_CullTransparentMesh: 1 +--- !u!1 &1232393572 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1232393573} + - component: {fileID: 1232393576} + - component: {fileID: 1232393575} + - component: {fileID: 1232393574} + m_Layer: 0 + m_Name: ControllerPoseL + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1232393573 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1232393572} + m_LocalRotation: {x: 0, y: -0.13052624, z: 0, w: 0.9914449} + m_LocalPosition: {x: 0, y: 0, z: 1.3105831} + m_LocalScale: {x: 0.003, y: 0.003, z: 0.003} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2115463875} + m_Father: {fileID: 855247513} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: -15, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -1.7, y: 0} + m_SizeDelta: {x: 800, y: 620} + m_Pivot: {x: 1, y: 1} +--- !u!114 &1232393574 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1232393572} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1232393575 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1232393572} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 1 +--- !u!223 &1232393576 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1232393572} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 2 + m_Camera: {fileID: 963194227} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 --- !u!1 &1235362498 GameObject: m_ObjectHideFlags: 0 @@ -15328,6 +15792,105 @@ MonoBehaviour: enabledColor: {r: 0, g: 1, b: 0, a: 1} disabledColor: {r: 1, g: 0, b: 0, a: 1} image: {fileID: 2026257814} +--- !u!1 &1301415411 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1301415412} + - component: {fileID: 1301415415} + - component: {fileID: 1301415414} + - component: {fileID: 1301415413} + m_Layer: 0 + m_Name: ControllerPointerRText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1301415412 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1301415411} + 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: 95751957} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -10} + m_SizeDelta: {x: 780, y: 210} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1301415413 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1301415411} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 04725f4c022874d40a6e786b002b782a, type: 3} + m_Name: + m_EditorClassIdentifier: + PoseName: Controller Pointer Right + isTracked: {fileID: 0} + trackingState: {fileID: 0} + position: {fileID: -5730229631511484051, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + rotation: {fileID: -5246335118593862002, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + pose: {fileID: -8433335059429281244, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} +--- !u!114 &1301415414 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1301415411} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.860898, g: 0.8773585, b: 0.1779548, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 3 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Pose +--- !u!222 &1301415415 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1301415411} + m_CullTransparentMesh: 1 --- !u!1 &1301507905 GameObject: m_ObjectHideFlags: 0 @@ -15581,6 +16144,107 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1330451524} m_CullTransparentMesh: 1 +--- !u!1 &1335781103 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1335781104} + - component: {fileID: 1335781107} + - component: {fileID: 1335781106} + - component: {fileID: 1335781105} + m_Layer: 0 + m_Name: ControllerPoseR + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1335781104 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1335781103} + m_LocalRotation: {x: 0, y: 0.13052616, z: 0, w: 0.9914449} + m_LocalPosition: {x: 0, y: 0, z: 0.79} + m_LocalScale: {x: 0.003, y: 0.003, z: 0.003} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 95751957} + m_Father: {fileID: 855247513} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 15, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 3.1, y: 0} + m_SizeDelta: {x: 800, y: 620} + m_Pivot: {x: 1, y: 1} +--- !u!114 &1335781105 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1335781103} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1335781106 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1335781103} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 1 +--- !u!223 &1335781107 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1335781103} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 2 + m_Camera: {fileID: 963194227} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 --- !u!1 &1337837810 GameObject: m_ObjectHideFlags: 0 @@ -18178,6 +18842,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 0 m_Action: @@ -18218,6 +18883,18 @@ MonoBehaviour: m_Flags: 0 m_Flags: 0 m_Reference: {fileID: 0} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: Position m_Type: 0 @@ -18252,7 +18929,6 @@ MonoBehaviour: m_Action: Rotation m_Flags: 0 m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &1573123701 GameObject: m_ObjectHideFlags: 0 @@ -18357,8 +19033,8 @@ RectTransform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1574464185} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0.015, y: 0.015, z: 0.015} + m_LocalPosition: {x: 0, y: 0, z: 10} + m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1162657276} @@ -18388,7 +19064,7 @@ Canvas: m_SortingBucketNormalizedSize: 0 m_AdditionalShaderChannelsFlag: 0 m_SortingLayerID: 0 - m_SortingOrder: 0 + m_SortingOrder: 3000 m_TargetDisplay: 0 --- !u!114 &1574464188 MonoBehaviour: @@ -19269,6 +19945,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 0 m_Action: @@ -19309,6 +19986,18 @@ MonoBehaviour: m_Flags: 0 m_Flags: 0 m_Reference: {fileID: 0} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: Position m_Type: 0 @@ -19343,7 +20032,6 @@ MonoBehaviour: m_Action: Rotation m_Flags: 0 m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &1632315497 GameObject: m_ObjectHideFlags: 0 @@ -19658,6 +20346,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 0 m_Action: @@ -19698,6 +20387,18 @@ MonoBehaviour: m_Flags: 0 m_Flags: 0 m_Reference: {fileID: 0} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: m_Type: 0 @@ -19716,7 +20417,6 @@ MonoBehaviour: m_Interactions: m_SingletonActionBindings: [] m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &1640201746 GameObject: m_ObjectHideFlags: 0 @@ -19987,7 +20687,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 3, y: -1.299} + m_AnchoredPosition: {x: -0.5, y: -1} m_SizeDelta: {x: 800, y: 550} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1654580158 @@ -21005,6 +21705,105 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1807220543} m_CullTransparentMesh: 1 +--- !u!1 &1807340436 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1807340437} + - component: {fileID: 1807340440} + - component: {fileID: 1807340439} + - component: {fileID: 1807340438} + m_Layer: 0 + m_Name: ControllerDeviceRText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1807340437 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1807340436} + 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: 95751957} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 200} + m_SizeDelta: {x: 780, y: 210} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1807340438 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1807340436} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 04725f4c022874d40a6e786b002b782a, type: 3} + m_Name: + m_EditorClassIdentifier: + PoseName: Controller Device Right + isTracked: {fileID: -1219534774619098812, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + trackingState: {fileID: 7186331274470829537, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + position: {fileID: 7443918988805782556, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + rotation: {fileID: 7542131730279260107, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + pose: {fileID: 5353795866969974560, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} +--- !u!114 &1807340439 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1807340436} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.860898, g: 0.8773585, b: 0.1779548, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 3 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Pose +--- !u!222 &1807340440 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1807340436} + m_CullTransparentMesh: 1 --- !u!1 &1808727839 GameObject: m_ObjectHideFlags: 0 @@ -21645,6 +22444,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 0 m_Action: @@ -21685,6 +22485,18 @@ MonoBehaviour: m_Flags: 0 m_Flags: 0 m_Reference: {fileID: 0} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: Position m_Type: 0 @@ -21719,7 +22531,6 @@ MonoBehaviour: m_Action: Rotation m_Flags: 0 m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &1863449114 GameObject: m_ObjectHideFlags: 0 @@ -23742,6 +24553,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 1 m_Action: @@ -23766,6 +24578,18 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: 728203289168863980, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: m_Type: 0 @@ -23784,7 +24608,6 @@ MonoBehaviour: m_Interactions: m_SingletonActionBindings: [] m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &2002148294 GameObject: m_ObjectHideFlags: 0 @@ -23835,6 +24658,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 1 m_Action: @@ -23859,6 +24683,18 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: 8869308336890601743, guid: 699f4d2073ed2e34ea7f7944795b868c, type: 3} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: m_Type: 0 @@ -23877,7 +24713,6 @@ MonoBehaviour: m_Interactions: m_SingletonActionBindings: [] m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &2007418226 GameObject: m_ObjectHideFlags: 0 @@ -24286,6 +25121,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_TrackingType: 0 m_UpdateType: 0 + m_IgnoreTrackingState: 0 m_PositionInput: m_UseReference: 0 m_Action: @@ -24326,6 +25162,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: 9d0b38fe-1f35-4a69-89e3-cd656a0016cd + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_PositionAction: m_Name: Position m_Type: 0 @@ -24360,7 +25208,6 @@ MonoBehaviour: m_Action: Rotation m_Flags: 0 m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &2026257812 GameObject: m_ObjectHideFlags: 0 @@ -25222,6 +26069,84 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2113810499} m_CullTransparentMesh: 0 +--- !u!1 &2115463874 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2115463875} + - component: {fileID: 2115463877} + - component: {fileID: 2115463876} + m_Layer: 0 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2115463875 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2115463874} + 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: + - {fileID: 204292439} + - {fileID: 360924783} + m_Father: {fileID: 1232393573} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2115463876 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2115463874} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &2115463877 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2115463874} + m_CullTransparentMesh: 1 --- !u!1 &2130989217 GameObject: m_ObjectHideFlags: 0 diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/ActionToVisibilityISX.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/ActionToVisibilityISX.cs index fa7a305..ea3c87b 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/ActionToVisibilityISX.cs +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/ActionToVisibilityISX.cs @@ -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); diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/AutomaticTrackingModeChanger.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/AutomaticTrackingModeChanger.cs index e8053fe..4c08673 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/AutomaticTrackingModeChanger.cs +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/AutomaticTrackingModeChanger.cs @@ -24,7 +24,7 @@ namespace UnityEngine.XR.OpenXR.Samples.ControllerSample if (m_TimeRemainingTillChange <= 0.0f) { List inputSubsystems = new List(); - SubsystemManager.GetInstances(inputSubsystems); + SubsystemManager.GetSubsystems(inputSubsystems); XRInputSubsystem subsystem = inputSubsystems?[0]; if (subsystem != null) { diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/TrackingModeOrigin.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/TrackingModeOrigin.cs index 85bc1a9..3c7c0a4 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/TrackingModeOrigin.cs +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/TrackingModeOrigin.cs @@ -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]; diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/VIVE/RemoveRenderMask.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/VIVE/RemoveRenderMask.cs new file mode 100644 index 0000000..b5c7179 --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/VIVE/RemoveRenderMask.cs @@ -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 displaySubsystems = new List(); + 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; + } + } +} \ No newline at end of file diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/VIVE/RemoveRenderMask.cs.meta b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/VIVE/RemoveRenderMask.cs.meta new file mode 100644 index 0000000..23f1f3d --- /dev/null +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/Input/Scripts/VIVE/RemoveRenderMask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f60faf6b28b7954b9ddf397eda40dc7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/PlaneDetection/Scripts/PlaneDetectionTestHandle.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/PlaneDetection/Scripts/PlaneDetectionTestHandle.cs index 06cf017..4365f86 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/PlaneDetection/Scripts/PlaneDetectionTestHandle.cs +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/PlaneDetection/Scripts/PlaneDetectionTestHandle.cs @@ -29,7 +29,7 @@ public class PlaneDetectionTestHandle : MonoBehaviour void GetXRInputSubsystem() { List xrSubsystemList = new List(); - SubsystemManager.GetInstances(xrSubsystemList); + SubsystemManager.GetSubsystems(xrSubsystemList); foreach (var xrSubsystem in xrSubsystemList) { if (xrSubsystem.running) diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Controller.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Controller.cs index 5893548..17767ab 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Controller.cs +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Controller.cs @@ -96,7 +96,11 @@ public class Controller : MonoBehaviour { GameObject ball = Instantiate(sphere, spawnPoint); Rigidbody rb = ball.GetComponent(); +#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; } diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Meshing Subsystem Feature/FallingSphere.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Meshing Subsystem Feature/FallingSphere.cs index 42ae0bf..0e27ddf 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Meshing Subsystem Feature/FallingSphere.cs +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Meshing Subsystem Feature/FallingSphere.cs @@ -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); } diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Meshing Subsystem Feature/MeshingBehaviour.cs b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Meshing Subsystem Feature/MeshingBehaviour.cs index 3c6e10c..77302aa 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Meshing Subsystem Feature/MeshingBehaviour.cs +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/SceneUnderstanding/Meshing Subsystem Feature/MeshingBehaviour.cs @@ -85,7 +85,7 @@ namespace UnityEngine.XR.OpenXR.Samples.MeshingFeature } var meshSubsystems = new List(); - SubsystemManager.GetInstances(meshSubsystems); + SubsystemManager.GetSubsystems(meshSubsystems); if (meshSubsystems.Count == 1) { s_MeshSubsystem = meshSubsystems[0]; diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/VIVE.OpenXR.Samples.asmdef b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/VIVE.OpenXR.Samples.asmdef index 870fb96..6d41703 100644 --- a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/VIVE.OpenXR.Samples.asmdef +++ b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/VIVE.OpenXR.Samples.asmdef @@ -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,12 +37,7 @@ "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 -} +} \ No newline at end of file diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/ViveTracker/ViveTrackerSample.unity b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/VIVETracker/VIVETracker.unity similarity index 100% rename from com.htc.upm.vive.openxr/Samples~/Samples/Samples/ViveTracker/ViveTrackerSample.unity rename to com.htc.upm.vive.openxr/Samples~/Samples/Samples/VIVETracker/VIVETracker.unity diff --git a/com.htc.upm.vive.openxr/Samples~/Samples/Samples/ViveTracker/ViveTrackerSample.unity.meta b/com.htc.upm.vive.openxr/Samples~/Samples/Samples/VIVETracker/VIVETracker.unity.meta similarity index 100% rename from com.htc.upm.vive.openxr/Samples~/Samples/Samples/ViveTracker/ViveTrackerSample.unity.meta rename to com.htc.upm.vive.openxr/Samples~/Samples/Samples/VIVETracker/VIVETracker.unity.meta diff --git a/com.htc.upm.vive.openxr/Samples~/Toolkits/Toolkits/BodyTracking(experimental)/Demo/BodyTracking.unity b/com.htc.upm.vive.openxr/Samples~/Toolkits/Toolkits/BodyTracking(experimental)/Demo/BodyTracking.unity index e09b301..f754b57 100644 --- a/com.htc.upm.vive.openxr/Samples~/Toolkits/Toolkits/BodyTracking(experimental)/Demo/BodyTracking.unity +++ b/com.htc.upm.vive.openxr/Samples~/Toolkits/Toolkits/BodyTracking(experimental)/Demo/BodyTracking.unity @@ -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 diff --git a/com.htc.upm.vive.openxr/package.json b/com.htc.upm.vive.openxr/package.json index 429d579..1970d95 100644 --- a/com.htc.upm.vive.openxr/package.json +++ b/com.htc.upm.vive.openxr/package.json @@ -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/" }