Compare commits
1 Commits
master
...
versions/2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bfa2ad4c7 |
150
.gitattributes
vendored
@@ -1,24 +1,132 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
#https://gist.githubusercontent.com/nemotoo/b8a1c3a0f1225bb9231979f389fd4f3f/raw/dc3e8cab80fc62d1c60db70c761b1ffa636aa796/.gitattributes
|
||||
#grafted from https://hextantstudios.com/unity-gitattributes/
|
||||
# Macro for Unity YAML-based asset files.
|
||||
[attr]unityyaml -text merge=unityyamlmerge diff
|
||||
# Macro for all binary files that should use Git LFS.
|
||||
[attr]lfs -text filter=lfs diff=lfs merge=lfs
|
||||
# Default to auto-normalized line endings.
|
||||
* text=auto
|
||||
## Unity ##
|
||||
*.txt text
|
||||
*.cs diff=csharp text
|
||||
*.cginc text
|
||||
*.shader text
|
||||
*.mat merge=unityyamlmerge eol=lf
|
||||
*.anim merge=unityyamlmerge eol=lf
|
||||
*.unity merge=unityyamlmerge eol=lf
|
||||
*.prefab merge=unityyamlmerge eol=lf
|
||||
*.physicsMaterial2D merge=unityyamlmerge eol=lf
|
||||
*.physicsMaterial merge=unityyamlmerge eol=lf
|
||||
*.physicMaterial merge=unityyamlmerge eol=lf
|
||||
*.asset merge=unityyamlmerge eol=lf
|
||||
*.meta merge=unityyamlmerge eol=lf
|
||||
*.controller merge=unityyamlmerge eol=lf
|
||||
*.flare merge=unityyamlmerge eol=lf
|
||||
# Code
|
||||
*.cs text diff=csharp
|
||||
# Unity Text Assets
|
||||
*.meta unityyaml
|
||||
*.unity unityyaml
|
||||
*.asset unityyaml
|
||||
*.prefab unityyaml
|
||||
*.mat unityyaml
|
||||
#asink: anim files can get large
|
||||
*.anim unityyaml lfs
|
||||
*.controller unityyaml
|
||||
*.overrideController unityyaml
|
||||
*.physicMaterial unityyaml
|
||||
*.physicsMaterial2D unityyaml
|
||||
*.playable unityyaml
|
||||
*.mask unityyaml
|
||||
*.brush unityyaml
|
||||
*.flare unityyaml
|
||||
*.fontsettings unityyaml
|
||||
*.guiskin unityyaml
|
||||
*.giparams unityyaml
|
||||
*.renderTexture unityyaml
|
||||
*.spriteatlas unityyaml
|
||||
*.terrainlayer unityyaml
|
||||
*.mixer unityyaml
|
||||
*.shadervariants unityyaml
|
||||
*.preset unityyaml
|
||||
*.asmdef -text diff
|
||||
# Unity Binary Assets
|
||||
*.cubemap lfs
|
||||
*.unitypackage lfs
|
||||
# Note: Unity terrain assets must have "-Terrain" suffix.
|
||||
*-[Tt]errain.asset -unityyaml lfs
|
||||
# Note: Unity navmesh assets must have "-NavMesh" suffix.
|
||||
*-[Nn]av[Mm]esh.asset -unityyaml lfs
|
||||
## git-lfs ##
|
||||
#Image
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||
*.psd filter=lfs diff=lfs merge=lfs -text
|
||||
*.ai filter=lfs diff=lfs merge=lfs -text
|
||||
#Audio
|
||||
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||
#Video
|
||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
*.mov filter=lfs diff=lfs merge=lfs -text
|
||||
#3D Object
|
||||
*.FBX -text
|
||||
*.fbx -text
|
||||
*.blend -text
|
||||
*.obj -text
|
||||
*.FBX filter=lfs diff=lfs merge=lfs -text
|
||||
*.fbx filter=lfs diff=lfs merge=lfs -text
|
||||
*.blend filter=lfs diff=lfs merge=lfs -text
|
||||
*.obj filter=lfs diff=lfs merge=lfs -text
|
||||
#ETC
|
||||
*.a filter=lfs diff=lfs merge=lfs -text
|
||||
*.exr filter=lfs diff=lfs merge=lfs -text
|
||||
*.tga filter=lfs diff=lfs merge=lfs -text
|
||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.dll filter=lfs diff=lfs merge=lfs -text
|
||||
*.unitypackage filter=lfs diff=lfs merge=lfs -text
|
||||
*.aif filter=lfs diff=lfs merge=lfs -text
|
||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||
*.rns filter=lfs diff=lfs merge=lfs -text
|
||||
*.reason filter=lfs diff=lfs merge=lfs -text
|
||||
*.lxo filter=lfs diff=lfs merge=lfs -text
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
*.aar filter=lfs diff=lfs merge=lfs -text
|
||||
*.lighting filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
#/LocalPackages (tests_withnewpackage)
|
||||
#$ find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u
|
||||
|
||||
#$ find ./* -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u
|
||||
#LICENSE
|
||||
#LICENSE_WaveSDKNativeBinary
|
||||
#aar
|
||||
#anim
|
||||
#apk
|
||||
#asmdef
|
||||
#asset
|
||||
#bat
|
||||
#controller
|
||||
#cs
|
||||
#default
|
||||
#dll
|
||||
#docx
|
||||
#dummy
|
||||
#exe
|
||||
#exr
|
||||
#fbx
|
||||
#gitignored
|
||||
#ini
|
||||
#inputactions
|
||||
#json
|
||||
#lighting
|
||||
#mat
|
||||
#md
|
||||
#meta
|
||||
#mtl
|
||||
#obj
|
||||
#physicMaterial
|
||||
#png
|
||||
#prefab
|
||||
#preset
|
||||
#renderTexture
|
||||
#setting
|
||||
#shader
|
||||
#so
|
||||
#tm1
|
||||
#tmp
|
||||
#txt
|
||||
#unity
|
||||
#unitypackage
|
||||
#wav
|
||||
#xml
|
||||
|
||||
|
||||
*.hdr filter=lfs diff=lfs merge=lfs -text
|
||||
*.lighting filter=lfs diff=lfs merge=lfs -text
|
||||
*.so filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -281,8 +281,7 @@ namespace VIVE.OpenXR.Editor
|
||||
}
|
||||
}
|
||||
|
||||
var features = settings.GetFeatures<OpenXRFeature>();
|
||||
foreach (var feature in features)
|
||||
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
|
||||
{
|
||||
if (!feature.enabled) { continue; }
|
||||
|
||||
@@ -311,17 +310,6 @@ namespace VIVE.OpenXR.Editor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (feature is VIVEFocus3Feature)
|
||||
{
|
||||
for (int i = 0; i < features.Length; i++)
|
||||
{
|
||||
if (features[i] is Enterprise.ViveEnterpriseCommand)
|
||||
{
|
||||
features[i].enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enableHandtracking)
|
||||
|
||||
@@ -51,39 +51,6 @@ 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;
|
||||
@@ -171,14 +138,6 @@ 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);
|
||||
@@ -212,138 +171,6 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
EditorGUILayout.PropertyField(Property_LayerShape, new GUIContent(Label_LayerShape));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect || Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect2)
|
||||
{
|
||||
if (targetCompositionLayer.isPreviewingQuad)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingQuad = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.isPreviewingCylinder)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingCylinder = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
if (!FeatureHelpers.GetFeatureWithIdForBuildTarget(BuildTargetGroup.Android, ViveCompositionLayerEquirect.featureId).enabled)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The Composition Layer Equirect feature is not enabled in OpenXR Settings.\nEnable it to use Equirect layers.", MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
showLayerParams = EditorGUILayout.Foldout(showLayerParams, "Equirect Parameters");
|
||||
if (showLayerParams)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_EquirectRadius, new GUIContent(Label_EquirectRadius));
|
||||
|
||||
if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_EquirectScaleX, new GUIContent(Label_EquirectScaleX));
|
||||
EditorGUILayout.PropertyField(Property_EquirectScaleY, new GUIContent(Label_EquirectScaleY));
|
||||
EditorGUILayout.PropertyField(Property_EquirectBiasX, new GUIContent(Label_EquirectBiasX));
|
||||
EditorGUILayout.PropertyField(Property_EquirectBiasY, new GUIContent(Label_EquirectBiasY));
|
||||
}
|
||||
|
||||
else if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect2)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_EquirectCentralHorizontalAngle, new GUIContent(Label_EquirectCentralHorizontalAngle));
|
||||
EditorGUILayout.PropertyField(Property_EquirectUpperVerticalAngle, new GUIContent(Label_EquirectUpperVerticalAngle));
|
||||
EditorGUILayout.PropertyField(Property_EquirectLowerVerticalAngle, new GUIContent(Label_EquirectLowerVerticalAngle));
|
||||
}
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
bool EquirectParamsChanged = targetCompositionLayer.LayerDimensionsChanged();
|
||||
if (targetCompositionLayer.isPreviewingEquirect)
|
||||
{
|
||||
Transform generatedPreviewTransform = targetCompositionLayer.transform.Find(CompositionLayer.EquirectPreviewName);
|
||||
|
||||
if (generatedPreviewTransform != null)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview = generatedPreviewTransform.gameObject;
|
||||
|
||||
if (EquirectParamsChanged)
|
||||
{
|
||||
MeshFilter equirectMeshFilter = targetCompositionLayer.generatedPreview.GetComponent<MeshFilter>();
|
||||
|
||||
//Generate vertices
|
||||
equirectMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateEquirectMesh(targetCompositionLayer.hmd, targetCompositionLayer.EquirectRadius);
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture != targetCompositionLayer.texture)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Hide Equirect Preview"))
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUILayout.Button("Show Equirect Preview"))
|
||||
{
|
||||
Rect srcRectLeft = FullRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.LeftRight)
|
||||
srcRectLeft = LeftRightRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.TopDown)
|
||||
srcRectLeft = TopDownRect;
|
||||
|
||||
targetCompositionLayer.isPreviewingEquirect = true;
|
||||
//Vector3[] cylinderVertices = CompositionLayer.MeshGenerationHelper.GenerateCylinderVertex(targetCompositionLayer.CylinderAngleOfArc, targetCompositionLayer.CylinderRadius, targetCompositionLayer.CylinderHeight);
|
||||
//Add components to Game Object
|
||||
targetCompositionLayer.generatedPreview = new GameObject();
|
||||
targetCompositionLayer.generatedPreview.hideFlags = HideFlags.HideAndDontSave;
|
||||
targetCompositionLayer.generatedPreview.name = CompositionLayer.EquirectPreviewName;
|
||||
targetCompositionLayer.generatedPreview.transform.SetParent(targetCompositionLayer.gameObject.transform);
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
|
||||
MeshRenderer equirectMeshRenderer = targetCompositionLayer.generatedPreview.AddComponent<MeshRenderer>();
|
||||
MeshFilter equirectMeshFilter = targetCompositionLayer.generatedPreview.AddComponent<MeshFilter>();
|
||||
equirectMeshRenderer.sharedMaterial = new Material(Shader.Find("Unlit/Transparent"));
|
||||
|
||||
if (targetCompositionLayer.texture != null)
|
||||
{
|
||||
equirectMeshRenderer.sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
equirectMeshRenderer.sharedMaterial.mainTextureOffset = srcRectLeft.position;
|
||||
equirectMeshRenderer.sharedMaterial.mainTextureScale = srcRectLeft.size;
|
||||
}
|
||||
|
||||
//Generate Mesh
|
||||
equirectMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateEquirectMesh(targetCompositionLayer.hmd, targetCompositionLayer.EquirectRadius);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
}
|
||||
if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Cylinder)
|
||||
{
|
||||
if (!FeatureHelpers.GetFeatureWithIdForBuildTarget(BuildTargetGroup.Android, ViveCompositionLayerCylinder.featureId).enabled)
|
||||
@@ -360,15 +187,6 @@ 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)
|
||||
{
|
||||
@@ -462,7 +280,6 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
|
||||
if (targetCompositionLayer.isPreviewingCylinder)
|
||||
{
|
||||
|
||||
Transform generatedPreviewTransform = targetCompositionLayer.transform.Find(CompositionLayer.CylinderPreviewName);
|
||||
|
||||
if (generatedPreviewTransform != null)
|
||||
@@ -555,15 +372,6 @@ 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)
|
||||
@@ -699,7 +507,7 @@ namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
EditorGUI.indentLevel--;
|
||||
}*/
|
||||
|
||||
if((Property_LayerShape.intValue != (int)CompositionLayer.LayerShape.Equirect && Property_LayerShape.intValue != (int)CompositionLayer.LayerShape.Equirect2) && (targetCompositionLayer.textureLeft == targetCompositionLayer.textureRight || targetCompositionLayer.textureRight == null))
|
||||
if (targetCompositionLayer.textureLeft == targetCompositionLayer.textureRight || targetCompositionLayer.textureRight == null)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_IsCustomRects, Label_IsCustomRects);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
@@ -93,9 +93,9 @@ public static class PackageManagerHelper
|
||||
case StatusCode.Failure:
|
||||
if (!s_wasRemoved)
|
||||
{
|
||||
if (m_removeRequest != null) { Debug.LogError("Something wrong when removing package from list. error:" + m_removeRequest.Error.errorCode + "(" + m_removeRequest.Error.message + ")"); }
|
||||
var request = m_removeRequest;
|
||||
m_removeRequest = null;
|
||||
Debug.LogError("Something wrong when removing package from list. error:" + m_removeRequest.Error.errorCode + "(" + m_removeRequest.Error.message + ")");
|
||||
}
|
||||
break;
|
||||
case StatusCode.Success:
|
||||
|
||||
@@ -149,15 +149,10 @@ namespace VIVE.OpenXR.Editor
|
||||
}
|
||||
}
|
||||
|
||||
static int checkPreferenceAssetsFrame = 0;
|
||||
static void OnUpdate()
|
||||
{
|
||||
if (!ViveOpenXRAndroidAssigned) { return; }
|
||||
|
||||
checkPreferenceAssetsFrame++;
|
||||
checkPreferenceAssetsFrame %= 1200; // 10s
|
||||
if (checkPreferenceAssetsFrame != 0) { return; }
|
||||
|
||||
CheckPreferenceAssets();
|
||||
|
||||
if (m_AssetAvatar)
|
||||
|
||||
@@ -14,7 +14,6 @@ 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",
|
||||
|
||||
@@ -7,17 +7,8 @@ namespace VIVE.OpenXR.Feature
|
||||
{
|
||||
public interface IViveFeatureWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// OnInstanceCreate might be called multiple times. Because many features might be using the same instance.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance"></param>
|
||||
/// <param name="xrGetInstanceProcAddr"></param>
|
||||
/// <returns></returns>
|
||||
public bool OnInstanceCreate(XrInstance xrInstance, IntPtr xrGetInstanceProcAddr);
|
||||
|
||||
/// <summary>
|
||||
/// OnInstanceDestroy might be called multiple times. Because many features might be using the same instance.
|
||||
/// </summary>
|
||||
public void OnInstanceDestroy();
|
||||
}
|
||||
|
||||
@@ -30,11 +21,6 @@ namespace VIVE.OpenXR.Feature
|
||||
// Set true in yourfeature's OnInstanceCreate
|
||||
public bool IsInited { get; protected set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// If the feature is inited not successfully, Set this true. Use to avoid multiple inits.
|
||||
/// </summary>
|
||||
public bool TryInited { get; protected set; } = false;
|
||||
|
||||
public OpenXRHelper.xrGetInstanceProcAddrDelegate xrGetInstanceProcAddr;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,114 +1,26 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
internal static class MemoryTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Make sure the input ptr is a OpenXR XrBaseStructure derived struct.
|
||||
/// </summary>
|
||||
/// <param name="ptr">the struct to get its next.</param>
|
||||
/// <returns>the next's value</returns>
|
||||
public static unsafe IntPtr GetNext(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return IntPtr.Zero;
|
||||
//Profiler.BeginSample("GetNext");
|
||||
XrBaseStructure* ptrToStruct = (XrBaseStructure*)ptr.ToPointer();
|
||||
//Profiler.EndSample();
|
||||
return ptrToStruct->next;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the input ptr is a OpenXR XrBaseStructure derived struct.
|
||||
/// </summary>
|
||||
/// <param name="ptr">the struct to get its type</param>
|
||||
/// <returns>the struct's type</returns>
|
||||
public static unsafe XrStructureType GetType(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
throw new Exception("The input pointer is null.");
|
||||
|
||||
//Profiler.BeginSample("GetType");
|
||||
XrBaseStructure* ptrToStruct = (XrBaseStructure*)ptr.ToPointer();
|
||||
//Profiler.EndSample();
|
||||
return ptrToStruct->type;
|
||||
}
|
||||
|
||||
public static unsafe XrBaseStructure ToBaseStructure(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
throw new Exception("The input pointer is null.");
|
||||
|
||||
//Profiler.BeginSample("ToBaseStructure");
|
||||
XrBaseStructure* ptrToStruct = (XrBaseStructure*)ptr.ToPointer();
|
||||
//Profiler.EndSample();
|
||||
return *ptrToStruct;
|
||||
}
|
||||
|
||||
public static unsafe T PtrToStructure<T>(IntPtr ptr) where T : unmanaged
|
||||
{
|
||||
//Profiler.BeginSample("PtrToStructure");
|
||||
// Not to use Marshal.PtrToStructure<T> because it is slow.
|
||||
T t = default; // Use new T() will cause GC alloc.
|
||||
Buffer.MemoryCopy((void*)ptr, &t, sizeof(T), sizeof(T));
|
||||
//Profiler.EndSample();
|
||||
return t;
|
||||
}
|
||||
|
||||
public static unsafe void PtrToStructure<T>(IntPtr ptr, ref T t) where T : unmanaged
|
||||
{
|
||||
//Profiler.BeginSample("PtrToStructure");
|
||||
fixed (T* destinationPtr = &t)
|
||||
{
|
||||
Buffer.MemoryCopy((void*)ptr, destinationPtr, sizeof(T), sizeof(T));
|
||||
}
|
||||
//Profiler.EndSample();
|
||||
}
|
||||
|
||||
public static unsafe void StructureToPtr<T>(T t, IntPtr ptr) where T : unmanaged
|
||||
{
|
||||
//Profiler.BeginSample("StructureToPtr");
|
||||
// Not to use Marshal.StructureToPtr<T> because it is slow.
|
||||
Buffer.MemoryCopy(&t, (void*)ptr, sizeof(T), sizeof(T));
|
||||
//Profiler.EndSample();
|
||||
}
|
||||
|
||||
public static class MemoryTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert the enum array to IntPtr. Should call <see cref="ReleaseRawMemory(IntPtr)"/> after use.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="array"></param>
|
||||
/// <returns></returns>
|
||||
public static unsafe IntPtr ToIntPtr<T>(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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the struct to IntPtr. Should call <see cref="ReleaseRawMemory(IntPtr)"/> after use.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="structure"></param>
|
||||
/// <returns></returns>
|
||||
public static IntPtr ToIntPtr<T>(T structure) where T : struct
|
||||
{
|
||||
int size = Marshal.SizeOf(structure);
|
||||
IntPtr ptr = Marshal.AllocHGlobal(size);
|
||||
Marshal.StructureToPtr(structure, ptr, true);
|
||||
return ptr;
|
||||
}
|
||||
public static IntPtr ToIntPtr<T>(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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make the same size raw buffer from input array.
|
||||
@@ -116,68 +28,30 @@ namespace VIVE.OpenXR
|
||||
/// <typeparam name="T">Data type could be primitive type or struct. Should call <see cref="ReleaseRawMemory(IntPtr)"/> after use.</typeparam>
|
||||
/// <param name="refArray">The data array</param>
|
||||
/// <returns>The memory handle. Should release by <see cref="ReleaseRawMemory(IntPtr)"/></returns>
|
||||
public static unsafe IntPtr MakeRawMemory<T>(T[] refArray) where T : unmanaged
|
||||
{
|
||||
int size = Marshal.SizeOf(typeof(T)) * refArray.Length;
|
||||
return Marshal.AllocHGlobal(size);
|
||||
}
|
||||
public static IntPtr MakeRawMemory<T>(T[] refArray)
|
||||
{
|
||||
int size = Marshal.SizeOf(typeof(T)) * refArray.Length;
|
||||
return Marshal.AllocHGlobal(size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the raw memory to the array. You should make sure the array has the same size as the raw memory.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Convert the memory to this type array.</typeparam>
|
||||
/// <param name="array">The output array.</param>
|
||||
/// <param name="raw">The data source in raw memory form.</param>
|
||||
/// <param name="count">Specify the copy count. Count should be less than array length.</param>
|
||||
public static unsafe void CopyFromRawMemory<T>(T[] array, IntPtr raw, int count = 0) where T : unmanaged
|
||||
{
|
||||
//Profiler.BeginSample("CopyFromRawMemory");
|
||||
int N = array.Length;
|
||||
if (count > 0 && count < array.Length)
|
||||
N = count;
|
||||
int step = 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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy all raw memory to the array. This has higher performance than <see cref="CopyFromRawMemory"/>.
|
||||
/// Use this method if you have frequent update requirements.
|
||||
/// You need prepare a byte buffer to store the raw memory. The byte buffer size should be tSize * array.Length.
|
||||
/// tSize is used for checking the byte buffer size. If tSize is 0, it will use Marshal.SizeOf(typeof(T)).
|
||||
/// You can save the size at your size to avoid the Marshal.Sizeof(typeof(T)) call repeatedly.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Convert the memory to this type array.</typeparam>
|
||||
/// <param name="array">The output array.</param>
|
||||
/// <param name="raw">The data source in raw memory form.</param>
|
||||
public static unsafe void CopyAllFromRawMemory<T>(T[] array, IntPtr raw) where T : unmanaged
|
||||
{
|
||||
#if DEBUG
|
||||
if (array == null)
|
||||
throw new ArgumentNullException(nameof(array), "Output array cannot be null.");
|
||||
if (raw == IntPtr.Zero)
|
||||
throw new ArgumentNullException(nameof(raw), "Raw memory pointer cannot be null.");
|
||||
#endif
|
||||
|
||||
//Profiler.BeginSample("CopyAllFromRawMemory");
|
||||
int elementSize = sizeof(T);
|
||||
int requiredBufferSize = elementSize * array.Length;
|
||||
|
||||
// Pin array's address. Prevent GC move it.
|
||||
fixed (T* destPtr = array)
|
||||
{
|
||||
T* sourcePtr = (T*)raw.ToPointer();
|
||||
Buffer.MemoryCopy(sourcePtr, destPtr, requiredBufferSize, requiredBufferSize);
|
||||
}
|
||||
//Profiler.EndSample();
|
||||
}
|
||||
/// <summary>
|
||||
/// Copy the raw memory to the array. You should make sure the array has the same size as the raw memory.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Convert the memory to this type array.</typeparam>
|
||||
/// <param name="array">The output array.</param>
|
||||
/// <param name="raw">The data source in raw memory form.</param>
|
||||
/// <param name="count">Specify the copy count. Count should be less than array length.</param>
|
||||
public static void CopyFromRawMemory<T>(T[] array, IntPtr raw, int count = 0)
|
||||
{
|
||||
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<T>(IntPtr.Add(raw, i * step));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make the same size raw buffer from input array. Make sure the raw has enough size.
|
||||
@@ -185,44 +59,22 @@ namespace VIVE.OpenXR
|
||||
/// <typeparam name="T">Convert this type array to raw memory.</typeparam>
|
||||
/// <param name="raw">The output data in raw memory form</param>
|
||||
/// <param name="array">The data source</param>
|
||||
public static unsafe void CopyToRawMemory<T>(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();
|
||||
}
|
||||
public static void CopyToRawMemory<T>(IntPtr raw, T[] array)
|
||||
{
|
||||
int step = Marshal.SizeOf(typeof(T));
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
Marshal.StructureToPtr<T>(array[i], IntPtr.Add(raw, i * step), false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release the raw memory handle which is created by <see cref="MakeRawMemory{T}(T[])"/>
|
||||
/// </summary>
|
||||
/// <param name="ptr"></param>
|
||||
public static void ReleaseRawMemory(IntPtr ptr)
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a pointer in the next chain. Make sure the input next pointer is a OpenXR XrBaseStructure derived struct.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="next"></param>
|
||||
/// <returns>true if exist</returns>
|
||||
public static bool HasPtrInNextChain(IntPtr target, IntPtr next)
|
||||
{
|
||||
while (next != IntPtr.Zero)
|
||||
{
|
||||
if (next == target)
|
||||
return true;
|
||||
next = GetNext(next);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
namespace VIVE.OpenXR.Enterprise
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Enterprise Command",
|
||||
Desc = "Support Enterprise request with special command",
|
||||
Company = "HTC",
|
||||
OpenxrExtensionStrings = kOpenxrExtensionString,
|
||||
Version = "0.1",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
FeatureId = featureId,
|
||||
Hidden = true
|
||||
)]
|
||||
#endif
|
||||
public class ViveEnterpriseCommand : OpenXRFeature
|
||||
{
|
||||
#region Log
|
||||
const string LOG_TAG = "VIVE.OpenXR.Enterprise.Command ";
|
||||
private static void DEBUG(String msg) { Debug.Log(LOG_TAG + msg); }
|
||||
private static void ERROR(String msg) { Debug.LogError(LOG_TAG + msg); }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "vive.openxr.feature.enterprise.command";
|
||||
|
||||
/// <summary>
|
||||
/// The extension string.
|
||||
/// </summary>
|
||||
public const string kOpenxrExtensionString = "XR_HTC_enterprise_command";
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
private static bool m_XrInstanceCreated = false;
|
||||
private static bool m_XrSessionCreated = false;
|
||||
private static XrInstance m_XrInstance = 0;
|
||||
private static XrSession m_XrSession = 0;
|
||||
private static XrSystemId m_XrSystemId = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateInstance">xrCreateInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The created instance.</param>
|
||||
/// <returns>True for valid <see cref="XrInstance">XrInstance</see></returns>
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled(kOpenxrExtensionString))
|
||||
{
|
||||
ERROR($"OnInstanceCreate() {kOpenxrExtensionString} is NOT enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_XrInstanceCreated = true;
|
||||
m_XrInstance = xrInstance;
|
||||
DEBUG($"OnInstanceCreate() {m_XrInstance}");
|
||||
|
||||
return GetXrFunctionDelegates(m_XrInstance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroyInstance">xrDestroyInstance</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The instance to destroy.</param>
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
if (m_XrInstance == xrInstance)
|
||||
{
|
||||
m_XrInstanceCreated = false;
|
||||
m_XrInstance = 0;
|
||||
}
|
||||
DEBUG($"OnInstanceDestroy() {xrInstance}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the <see cref="XrSystemId">XrSystemId</see> retrieved by <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrGetSystem">xrGetSystem</see> is changed.
|
||||
/// </summary>
|
||||
/// <param name="xrSystem">The system id.</param>
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
m_XrSystemId = xrSystem;
|
||||
DEBUG($"OnSystemChange() {m_XrSystemId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrCreateSession">xrCreateSession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The created session ID.</param>
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
m_XrSession = xrSession;
|
||||
m_XrSessionCreated = true;
|
||||
DEBUG($"OnSessionCreate() {m_XrSession}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see href="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#xrDestroySession">xrDestroySession</see> is done.
|
||||
/// </summary>
|
||||
/// <param name="xrSession">The session ID to destroy.</param>
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
DEBUG($"OnSessionDestroy() {xrSession}");
|
||||
|
||||
if (m_XrSession == xrSession)
|
||||
{
|
||||
m_XrSession = 0;
|
||||
m_XrSessionCreated = false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OpenXR function delegates
|
||||
/// xrEnterpriseCommandHTC
|
||||
private static ViveEnterpriseCommandHelper.xrEnterpriseCommandHTCDelegate xrEnterpriseCommandHTC;
|
||||
/// xrGetInstanceProcAddr
|
||||
private static OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddr;
|
||||
|
||||
/// <summary>
|
||||
/// Enterprise command request for special functionality.
|
||||
/// </summary>
|
||||
/// <param name="request">The request of enterprise command</param>
|
||||
/// <param name="result">The result of enterprise command</param>
|
||||
/// <returns>Return XR_SUCCESS if request successfully. False otherwise.</returns>
|
||||
private static XrResult EnterpriseCommandHTC(XrEnterpriseCommandBufferHTC request, ref XrEnterpriseCommandBufferHTC result)
|
||||
{
|
||||
if (!m_XrSessionCreated)
|
||||
{
|
||||
ERROR("EnterpriseCommandHTC() XR_ERROR_SESSION_LOST.");
|
||||
return XrResult.XR_ERROR_SESSION_LOST;
|
||||
}
|
||||
if (!m_XrInstanceCreated)
|
||||
{
|
||||
ERROR("EnterpriseCommandHTC() XR_ERROR_INSTANCE_LOST.");
|
||||
return XrResult.XR_ERROR_INSTANCE_LOST;
|
||||
}
|
||||
|
||||
DEBUG($"EnterpriseCommandHTC() code: {request.code}, data: {CharArrayToString(request.data)}");
|
||||
return xrEnterpriseCommandHTC(m_XrSession, request, ref result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the OpenXR function via XrInstance.
|
||||
/// </summary>
|
||||
/// <param name="xrInstance">The XrInstance is provided by the Unity OpenXR Plugin.</param>
|
||||
/// <returns>Return true if request successfully. False otherwise.</returns>
|
||||
private bool GetXrFunctionDelegates(XrInstance xrInstance)
|
||||
{
|
||||
/// xrGetInstanceProcAddr
|
||||
if (xrGetInstanceProcAddr != null && xrGetInstanceProcAddr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrGetInstanceProcAddr.");
|
||||
XrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(
|
||||
xrGetInstanceProcAddr,
|
||||
typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate)) as OpenXRHelper.xrGetInstanceProcAddrDelegate;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrGetInstanceProcAddr");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// xrEnterpriseCommandHTC
|
||||
if (XrGetInstanceProcAddr(xrInstance, "xrEnterpriseCommandHTC", out IntPtr funcPtr) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
DEBUG("Get function pointer of xrEnterpriseCommandHTC.");
|
||||
xrEnterpriseCommandHTC = Marshal.GetDelegateForFunctionPointer(
|
||||
funcPtr,
|
||||
typeof(ViveEnterpriseCommandHelper.xrEnterpriseCommandHTCDelegate)) as ViveEnterpriseCommandHelper.xrEnterpriseCommandHTCDelegate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("xrEnterpriseCommandHTC");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public API
|
||||
private const int kCharLength = 256;
|
||||
private const char kEndChar = '\0';
|
||||
private static char[] charArray = new char[kCharLength];
|
||||
|
||||
/// <summary>
|
||||
/// Request special feature with command, it should take code and command string.
|
||||
/// </summary>
|
||||
/// <param name="requestCode">The type of request code is integer.</param>
|
||||
/// <param name="requestCommand">The maximum length of request command is 256.</param>
|
||||
/// <param name="resultCode">The output of result code.</param>
|
||||
/// <param name="resultCommand">The output of result command.</param>
|
||||
/// <returns>Return true if request successfully. False otherwise.</returns>
|
||||
public static bool CommandRequest(int requestCode, string requestCommand, out int resultCode, out string resultCommand)
|
||||
{
|
||||
resultCode = 0;
|
||||
resultCommand = string.Empty;
|
||||
XrEnterpriseCommandBufferHTC request = new XrEnterpriseCommandBufferHTC(requestCode, StringToCharArray(requestCommand));
|
||||
XrEnterpriseCommandBufferHTC result = new XrEnterpriseCommandBufferHTC(resultCode, StringToCharArray(resultCommand));
|
||||
if (EnterpriseCommandHTC(request, ref result) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
resultCode = result.code;
|
||||
resultCommand = CharArrayToString(result.data);
|
||||
DEBUG($"CommandRequest Result code: {resultCode}, data: {resultCommand}");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static char[] StringToCharArray(string str)
|
||||
{
|
||||
Array.Clear(charArray, 0, kCharLength);
|
||||
if (!string.IsNullOrEmpty(str))
|
||||
{
|
||||
int arrayLength = Math.Min(str.Length, kCharLength);
|
||||
for (int i = 0; i < arrayLength; i++)
|
||||
{
|
||||
charArray[i] = str[i];
|
||||
}
|
||||
charArray[kCharLength - 1] = kEndChar;
|
||||
}
|
||||
return charArray;
|
||||
}
|
||||
|
||||
private static string CharArrayToString(char[] charArray)
|
||||
{
|
||||
int actualLength = Array.FindIndex(charArray, c => c == kEndChar);
|
||||
if (actualLength == -1)
|
||||
{
|
||||
actualLength = charArray.Length;
|
||||
}
|
||||
|
||||
return new string(charArray, 0, actualLength);
|
||||
}
|
||||
}
|
||||
|
||||
#region Helper
|
||||
public struct XrEnterpriseCommandBufferHTC
|
||||
{
|
||||
public Int32 code;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
|
||||
public char[] data;
|
||||
|
||||
public XrEnterpriseCommandBufferHTC(int in_code, char[] in_data)
|
||||
{
|
||||
code = (Int32)in_code;
|
||||
data = new char[in_data.Length];
|
||||
Array.Copy(in_data, data, in_data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public class ViveEnterpriseCommandHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// The function delegate of xrEnterpriseCommandHTC.
|
||||
/// </summary>
|
||||
/// <param name="session">An <see cref="XrSession">XrSession</see> in which the enterprise command will be active.</param>
|
||||
/// <param name="request">The request of enterprise command</param>
|
||||
/// <param name="result">The result of enterprise command</param>
|
||||
/// <returns>Return XR_SUCCESS if request successfully. False otherwise.</returns>
|
||||
public delegate XrResult xrEnterpriseCommandHTCDelegate(
|
||||
XrSession session,
|
||||
XrEnterpriseCommandBufferHTC request,
|
||||
ref XrEnterpriseCommandBufferHTC result);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5b2125d5dc73694eaed34e97a0962e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -10,14 +10,9 @@ namespace VIVE.OpenXR.Feature
|
||||
/// <summary>
|
||||
/// To use this wrapper, you need to call CommonWrapper.Instance.OnInstanceCreate() in your feature's OnInstanceCreate(),
|
||||
/// and call CommonWrapper.Instance.OnInstanceDestroy() in your feature's OnInstanceDestroy().
|
||||
///
|
||||
/// Note:
|
||||
/// In Standardalone's OpenXR MockRuntime, the CreateSwapchain and EnumerateSwapchainImages will work and return success,
|
||||
/// but the images's native pointer will be null.
|
||||
/// </summary>
|
||||
internal class CommonWrapper : ViveFeatureWrapperBase<CommonWrapper>, IViveFeatureWrapper
|
||||
public class CommonWrapper : ViveFeatureWrapperBase<CommonWrapper>, IViveFeatureWrapper
|
||||
{
|
||||
const string TAG = "CommonWrapper";
|
||||
OpenXRHelper.xrGetSystemPropertiesDelegate XrGetSystemProperties;
|
||||
OpenXRHelper.xrCreateSwapchainDelegate XrCreateSwapchain;
|
||||
OpenXRHelper.xrDestroySwapchainDelegate XrDestroySwapchain;
|
||||
@@ -37,13 +32,11 @@ 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");
|
||||
|
||||
Log.D(TAG, "OnInstanceCreate()");
|
||||
Debug.Log("CommonWrapper: OnInstanceCreate()");
|
||||
SetGetInstanceProcAddrPtr(xrGetInstanceProcAddrPtr);
|
||||
|
||||
bool ret = true;
|
||||
@@ -71,11 +64,9 @@ namespace VIVE.OpenXR.Feature
|
||||
/// <returns></returns>
|
||||
public void OnInstanceDestroy()
|
||||
{
|
||||
// Do not destroy twice
|
||||
if (IsInited == false) return;
|
||||
IsInited = false;
|
||||
XrGetSystemProperties = null;
|
||||
Log.D(TAG, "OnInstanceDestroy()");
|
||||
Debug.Log("CommonWrapper: OnInstanceDestroy()");
|
||||
}
|
||||
|
||||
public XrResult GetInstanceProcAddr(XrInstance instance, string name, out IntPtr function)
|
||||
@@ -173,12 +164,12 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
if (formatCapacityInput == 0)
|
||||
{
|
||||
Log.D(TAG, "EnumerateSwapchainFormats(ci=" + formatCapacityInput + ")");
|
||||
Debug.Log("CommonWrapper: EnumerateSwapchainFormats(ci=" + formatCapacityInput + ")");
|
||||
return XrEnumerateSwapchainFormats(session, 0, ref formatCountOutput, IntPtr.Zero);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.D(TAG, "EnumerateSwapchainFormats(ci=" + formatCapacityInput + ", formats=long[" + formats.Length + "])");
|
||||
Debug.Log("CommonWrapper: 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)
|
||||
@@ -210,7 +201,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;
|
||||
@@ -226,7 +217,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;
|
||||
@@ -243,7 +234,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;
|
||||
|
||||
@@ -17,8 +17,6 @@ namespace VIVE.OpenXR.Feature
|
||||
/// </summary>
|
||||
public class FutureWrapper : ViveFeatureWrapperBase<FutureWrapper>, IViveFeatureWrapper
|
||||
{
|
||||
const string TAG = "ViveFuture";
|
||||
|
||||
public enum XrFutureStateEXT
|
||||
{
|
||||
None = 0, // Not defined in extension. A default value.
|
||||
@@ -78,8 +76,6 @@ 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");
|
||||
@@ -89,12 +85,12 @@ namespace VIVE.OpenXR.Feature
|
||||
throw new Exception("FutureWrapper: xrGetInstanceProcAddr is null");
|
||||
SetGetInstanceProcAddrPtr(xrGetInstanceProcAddrPtr);
|
||||
|
||||
Log.D(TAG, "OnInstanceCreate()");
|
||||
Debug.Log("FutureWrapper: OnInstanceCreate()");
|
||||
|
||||
bool hasFuture = OpenXRRuntime.IsExtensionEnabled("XR_EXT_future");
|
||||
if (!hasFuture)
|
||||
{
|
||||
Log.E(TAG, "FutureWrapper: XR_EXT_future is not enabled. Check your feature's kOpenxrExtensionString.");
|
||||
Debug.LogError("FutureWrapper: XR_EXT_future is not enabled. Check your feature's kOpenxrExtensionString.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -106,7 +102,7 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
Log.E(TAG,"FutureWrapper: Failed to get function pointer.");
|
||||
Debug.LogError("FutureWrapper: Failed to get function pointer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,7 +112,7 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
public void OnInstanceDestroy()
|
||||
{
|
||||
Log.D(TAG, "OnInstanceDestroy()");
|
||||
Debug.Log("FutureWrapper: OnInstanceDestroy()");
|
||||
IsInited = false;
|
||||
XrPollFutureEXT = null;
|
||||
XrCancelFutureEXT = null;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR.Feature
|
||||
@@ -13,13 +12,9 @@ namespace VIVE.OpenXR.Feature
|
||||
/// </summary>
|
||||
public class SpaceWrapper : ViveFeatureWrapperBase<SpaceWrapper>, IViveFeatureWrapper
|
||||
{
|
||||
const string TAG = "ViveSpaceWrapper";
|
||||
|
||||
public delegate XrResult DelegateXrEnumerateReferenceSpaces(XrSession session, uint spaceCapacityInput, out uint spaceCountOutput, [Out] XrReferenceSpaceType[] spaces);
|
||||
delegate XrResult DelegateXrLocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, ref XrSpaceLocation location);
|
||||
delegate XrResult DelegateXrDestroySpace(XrSpace space);
|
||||
|
||||
DelegateXrEnumerateReferenceSpaces XrEnumerateReferenceSpaces;
|
||||
OpenXRHelper.xrCreateReferenceSpaceDelegate XrCreateReferenceSpace;
|
||||
DelegateXrLocateSpace XrLocateSpace;
|
||||
DelegateXrDestroySpace XrDestroySpace;
|
||||
@@ -34,20 +29,17 @@ 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("ViveSpaceWrapper: xrInstance is null");
|
||||
throw new Exception("ViveSpace: xrInstance is null");
|
||||
|
||||
SetGetInstanceProcAddrPtr(GetAddr);
|
||||
|
||||
Log.D(TAG, "OnInstanceCreate()");
|
||||
Debug.Log("ViveSpace: 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);
|
||||
@@ -57,35 +49,12 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
public void OnInstanceDestroy()
|
||||
{
|
||||
// Do not destroy twice
|
||||
if (IsInited == false) return;
|
||||
IsInited = false;
|
||||
XrEnumerateReferenceSpaces = null;
|
||||
XrCreateReferenceSpace = null;
|
||||
XrLocateSpace = null;
|
||||
XrDestroySpace = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="session"></param>
|
||||
/// <param name="spaceCapacityInput"></param>
|
||||
/// <param name="spaceCountOutput"></param>
|
||||
/// <param name="spaces"></param>
|
||||
/// <returns></returns>
|
||||
public XrResult EnumerateReferenceSpaces(XrSession session, int spaceCapacityInput, ref int spaceCountOutput, ref XrReferenceSpaceType[] spaces)
|
||||
{
|
||||
spaceCountOutput = 0;
|
||||
if (!IsInited)
|
||||
return XrResult.XR_ERROR_HANDLE_INVALID;
|
||||
if (spaceCapacityInput != 0 && spaces != null && spaces.Length < spaceCapacityInput)
|
||||
return XrResult.XR_ERROR_SIZE_INSUFFICIENT;
|
||||
var ret = XrEnumerateReferenceSpaces(session, (uint)spaceCapacityInput, out uint spaceCountOutputXR, spaces);
|
||||
spaceCountOutput = (int)spaceCountOutputXR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a reference space without create info.
|
||||
/// Example:
|
||||
@@ -139,7 +108,7 @@ namespace VIVE.OpenXR.Feature
|
||||
{
|
||||
if (!IsInited)
|
||||
return XrResult.XR_ERROR_HANDLE_INVALID;
|
||||
Log.D(TAG, $"DestroySpace({space})");
|
||||
Debug.Log($"DestroySpace({space})");
|
||||
return XrDestroySpace(space);
|
||||
}
|
||||
}
|
||||
@@ -155,7 +124,7 @@ namespace VIVE.OpenXR.Feature
|
||||
|
||||
public Space(XrSpace space)
|
||||
{
|
||||
Log.D($"Space({space})");
|
||||
Debug.Log($"Space({space})");
|
||||
this.space = space;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,25 +5,9 @@ using UnityEngine;
|
||||
using AOT;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
internal class HookHandlerAttribute : Attribute
|
||||
{
|
||||
public string xrFuncName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Set this function to handle the hook process in <see cref="ViveInterceptors.XrGetInstanceProcAddrInterceptor" />
|
||||
/// </summary>
|
||||
/// <param name="xrFuncName">The hooked openxr function name</param>
|
||||
public HookHandlerAttribute(string xrFuncName)
|
||||
{
|
||||
this.xrFuncName = xrFuncName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class is made for all features that need to intercept OpenXR API calls.
|
||||
/// Some APIs will be called by Unity internally, and we need to intercept them in c# to get some information.
|
||||
@@ -38,16 +22,7 @@ namespace VIVE.OpenXR
|
||||
/// return ViveInterceptors.Instance.HookGetInstanceProcAddr(func);
|
||||
/// }
|
||||
/// </summary>
|
||||
|
||||
// For extending the ViveInterceptors class, create a new partial class and implement the required functions.
|
||||
// For example:
|
||||
// public partial class ViveInterceptors
|
||||
// {
|
||||
// [HookHandler("xrYourFunction")]
|
||||
// private static XrResult OnHookXrYourFunction(XrInstance instance, string name, out IntPtr function)
|
||||
// { ... }
|
||||
// }
|
||||
partial class ViveInterceptors
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
public const string TAG = "VIVE.OpenXR.ViveInterceptors";
|
||||
static StringBuilder m_sb = null;
|
||||
@@ -57,6 +32,8 @@ 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
|
||||
@@ -71,32 +48,15 @@ namespace VIVE.OpenXR
|
||||
|
||||
public ViveInterceptors()
|
||||
{
|
||||
Log.D("ViveInterceptors");
|
||||
RegisterFunctions();
|
||||
Debug.Log("ViveInterceptors");
|
||||
}
|
||||
|
||||
delegate XrResult HookHandler(XrInstance instance, string name, out IntPtr function);
|
||||
static readonly Dictionary<string, HookHandler> interceptors = new Dictionary<string, HookHandler>();
|
||||
|
||||
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);
|
||||
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 OpenXRHelper.xrGetInstanceProcAddrDelegate XrGetInstanceProcAddrOriginal = null;
|
||||
static DelegateXrGetInstanceProcAddr XrGetInstanceProcAddrOriginal = null;
|
||||
|
||||
[MonoPInvokeCallback(typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate))]
|
||||
[MonoPInvokeCallback(typeof(DelegateXrGetInstanceProcAddr))]
|
||||
private static XrResult XrGetInstanceProcAddrInterceptor(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
// Used to check if the original function is already hooked.
|
||||
@@ -106,16 +66,64 @@ namespace VIVE.OpenXR
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
// Check if the function is intercepted by other features
|
||||
if (interceptors.ContainsKey(name))
|
||||
// Custom interceptors
|
||||
if (name == "xrWaitFrame" && requiredFunctions.Contains(name))
|
||||
{
|
||||
// If no request for this function, call the original function directly.
|
||||
if (!requiredFunctions.Contains(name))
|
||||
return XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
|
||||
var ret = interceptors[name](instance, name, out function);
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
Log.I(TAG, name + " is intercepted");
|
||||
{
|
||||
XrWaitFrameOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrWaitFrame>(function);
|
||||
function = xrWaitFrameInterceptorPtr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (name == "xrEndFrame" && requiredFunctions.Contains(name))
|
||||
{
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
XrEndFrameOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrEndFrame>(function);
|
||||
function = xrEndFrameInterceptorPtr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if PERFORMANCE_TEST
|
||||
if (name == "xrLocateSpace" && requiredFunctions.Contains(name))
|
||||
{
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
XrLocateSpaceOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrLocateSpace>(function);
|
||||
function = xrLocateSpaceInterceptorPtr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if (name == "xrPollEvent" && requiredFunctions.Contains(name))
|
||||
{
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
xrPollEventOrigin = Marshal.GetDelegateForFunctionPointer < xrPollEventDelegate > (function);
|
||||
function = xrPollEventPtr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (name == "xrBeginSession" && requiredFunctions.Contains(name))
|
||||
{
|
||||
Debug.Log($"{TAG}: XrGetInstanceProcAddrInterceptor() {name} is intercepted.");
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret == XrResult.XR_SUCCESS)
|
||||
{
|
||||
xrBeginSessionOrigin = Marshal.GetDelegateForFunctionPointer<xrBeginSessionDelegate>(function);
|
||||
function = xrBeginSessionPtr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -124,23 +132,23 @@ namespace VIVE.OpenXR
|
||||
|
||||
public IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
{
|
||||
Log.D(TAG, "HookGetInstanceProcAddr");
|
||||
Debug.Log($"{TAG}: HookGetInstanceProcAddr");
|
||||
if (XrGetInstanceProcAddrOriginal == null)
|
||||
{
|
||||
Log.D(TAG, "registering our own xrGetInstanceProcAddr");
|
||||
XrGetInstanceProcAddrOriginal = Marshal.GetDelegateForFunctionPointer<OpenXRHelper.xrGetInstanceProcAddrDelegate>(func);
|
||||
Debug.Log($"{TAG}: registering our own xrGetInstanceProcAddr");
|
||||
XrGetInstanceProcAddrOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrGetInstanceProcAddr>(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.
|
||||
Log.D(TAG, "Check if duplicate hooked by this script with instance=0 and \"ViveInterceptorHooked\" name. If following a loader error, ignore it.");
|
||||
Debug.Log($"{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.
|
||||
Log.D(TAG, "Already hooked");
|
||||
Debug.Log($"{TAG}: Already hooked");
|
||||
return func;
|
||||
}
|
||||
}
|
||||
@@ -165,34 +173,9 @@ namespace VIVE.OpenXR
|
||||
/// <param name="name"></param>
|
||||
public void AddRequiredFunction(string name)
|
||||
{
|
||||
Log.D(TAG, $"AddRequiredFunction({name})");
|
||||
if (!interceptors.ContainsKey(name))
|
||||
{
|
||||
Log.E(TAG, $"AddRequiredFunction({name}) failed. No such function.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!requiredFunctions.Contains(name))
|
||||
requiredFunctions.Add(name);
|
||||
|
||||
// If your function support unregister, you can add the reference count here.
|
||||
if (name == "xrLocateViews")
|
||||
xrLocateViewsReferenceCount++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If no need to use this hooked function, call this will remove your requirement.
|
||||
/// If all requirements are removed, the original function will be called directly.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void RemoveRequiredFunction(string name)
|
||||
{
|
||||
// If your function support unregister, you can add the reference count here.
|
||||
if (requiredFunctions.Contains(name))
|
||||
{
|
||||
if (name == "xrLocateViews")
|
||||
xrLocateViewsReferenceCount = Mathf.Max(xrLocateViewsReferenceCount--, 0);
|
||||
}
|
||||
if (requiredFunctions.Contains(name)) return;
|
||||
Debug.Log($"{TAG}: AddRequiredFunction({name})");
|
||||
requiredFunctions.Add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,21 +12,6 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrBeginSession")]
|
||||
private static XrResult OnHookXrBeginSession(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (xrBeginSessionOrigin == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
xrBeginSessionOrigin = Marshal.GetDelegateForFunctionPointer<xrBeginSessionDelegate>(function);
|
||||
}
|
||||
function = xrBeginSessionPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#region xrBeginSession
|
||||
public delegate XrResult xrBeginSessionDelegate(XrSession session, ref XrSessionBeginInfo beginInfo);
|
||||
private static xrBeginSessionDelegate xrBeginSessionOrigin = null;
|
||||
@@ -34,7 +19,7 @@ namespace VIVE.OpenXR
|
||||
[MonoPInvokeCallback(typeof(xrBeginSessionDelegate))]
|
||||
private static XrResult xrBeginSessionInterceptor(XrSession session, ref XrSessionBeginInfo beginInfo)
|
||||
{
|
||||
Profiler.BeginSample("VI:BeginSession");
|
||||
Profiler.BeginSample("ViveInterceptors:BeginSession");
|
||||
XrResult result = XrResult.XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
|
||||
if (xrBeginSessionOrigin != null)
|
||||
@@ -63,8 +48,7 @@ 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(")");
|
||||
Log.D(sb);
|
||||
sb.Clear().Append("xrBeginSessionInterceptor() beginInfo.next = (").Append(fsBeginInfo.type).Append(", ").Append(fsBeginInfo.mode).Append(")"); DEBUG(sb);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -72,7 +56,7 @@ namespace VIVE.OpenXR
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.E("xrBeginSessionInterceptor() Not assign xrBeginSession!");
|
||||
sb.Clear().Append("xrBeginSessionInterceptor() Not assign xrBeginSession!"); ERROR(sb);
|
||||
}
|
||||
Profiler.EndSample();
|
||||
|
||||
@@ -95,8 +79,7 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
m_EnableFrameSynchronization = active;
|
||||
m_FrameSynchronizationMode = mode;
|
||||
sb.Clear().Append("ActivateFrameSynchronization() ").Append(active ? "enable " : "disable ").Append(mode);
|
||||
Log.D(sb);
|
||||
sb.Clear().Append("ActivateFrameSynchronization() ").Append(active ? "enable " : "disable ").Append(mode); DEBUG(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using AOT;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrLocateViews")]
|
||||
private static XrResult OnHookXrLocateViews(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (xrLocateViewsOriginal == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
xrLocateViewsOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrLocateViews>(function);
|
||||
}
|
||||
function = xrLocateViewsInterceptorPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
public struct XrViewLocateInfo
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrViewConfigurationType viewConfigurationType;
|
||||
public XrTime displayTime;
|
||||
public XrSpace space;
|
||||
}
|
||||
|
||||
public struct XrView
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrPosef pose;
|
||||
public XrFovf fov;
|
||||
}
|
||||
|
||||
public enum XrViewStateFlags {
|
||||
ORIENTATION_VALID_BIT = 0x00000001,
|
||||
POSITION_VALID_BIT = 0x00000002,
|
||||
ORIENTATION_TRACKED_BIT = 0x00000004,
|
||||
POSITION_TRACKED_BIT = 0x00000008,
|
||||
}
|
||||
|
||||
public struct XrViewState
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrViewStateFlags viewStateFlags;
|
||||
}
|
||||
|
||||
public delegate XrResult DelegateXrLocateViews(XrSession session, IntPtr /*XrViewLocateInfo*/ viewLocateInfo, IntPtr /*XrViewState*/ viewState, uint viewCapacityInput, ref uint viewCountOutput, IntPtr /*XrView*/ views);
|
||||
|
||||
private static readonly DelegateXrLocateViews xrLocateViewsInterceptorHandle = new DelegateXrLocateViews(XrLocateViewsInterceptor);
|
||||
private static readonly IntPtr xrLocateViewsInterceptorPtr = Marshal.GetFunctionPointerForDelegate(xrLocateViewsInterceptorHandle);
|
||||
static DelegateXrLocateViews xrLocateViewsOriginal = null;
|
||||
static int xrLocateViewsReferenceCount = 0;
|
||||
|
||||
[MonoPInvokeCallback(typeof(DelegateXrLocateViews))]
|
||||
private static XrResult XrLocateViewsInterceptor(XrSession session, IntPtr viewLocateInfo, IntPtr viewState, uint viewCapacityInput, ref uint viewCountOutput, IntPtr views)
|
||||
{
|
||||
// Call the original function if the reference count is less than or equal to 0
|
||||
if (xrLocateViewsReferenceCount <= 0)
|
||||
return xrLocateViewsOriginal(session, viewLocateInfo, viewState, viewCapacityInput, ref viewCountOutput, views);
|
||||
|
||||
Profiler.BeginSample("VI:LocateViewsA");
|
||||
XrResult result = XrResult.XR_SUCCESS;
|
||||
if (instance.BeforeOriginalLocateViews != null)
|
||||
instance.BeforeOriginalLocateViews(session, viewLocateInfo, viewState, viewCapacityInput, ref viewCountOutput, views);
|
||||
Profiler.EndSample();
|
||||
result = xrLocateViewsOriginal(session, viewLocateInfo, viewState, viewCapacityInput, ref viewCountOutput, views);
|
||||
Profiler.BeginSample("VI:LocateViewsB");
|
||||
instance.AfterOriginalLocateViews?.Invoke(session, viewLocateInfo, viewState, viewCapacityInput, ref viewCountOutput, views);
|
||||
Profiler.EndSample();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If you return false, the original function will not be called.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public delegate bool DelegateXrLocateViewsInterceptor(XrSession session, IntPtr viewLocateInfo, IntPtr viewState, uint viewCapacityInput, ref uint viewCountOutput, IntPtr views);
|
||||
|
||||
/// <summary>
|
||||
/// Use this to intercept the original function. This will be called before the original function.
|
||||
/// </summary>
|
||||
public DelegateXrLocateViewsInterceptor BeforeOriginalLocateViews;
|
||||
|
||||
/// <summary>
|
||||
/// Use this to intercept the original function. This will be called after the original function.
|
||||
/// </summary>
|
||||
public DelegateXrLocateViewsInterceptor AfterOriginalLocateViews;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5dfd24c69475c3740975bf5538de3869
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -12,20 +12,6 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrPollEvent")]
|
||||
private static XrResult OnHookXrPollEvent(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (xrPollEventOrigin == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
xrPollEventOrigin = Marshal.GetDelegateForFunctionPointer<xrPollEventDelegate>(function);
|
||||
}
|
||||
function = xrPollEventPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
#region xrPollEvent
|
||||
public delegate XrResult xrPollEventDelegate(XrInstance instance, ref XrEventDataBuffer eventData);
|
||||
private static xrPollEventDelegate xrPollEventOrigin = null;
|
||||
@@ -33,7 +19,7 @@ namespace VIVE.OpenXR
|
||||
[MonoPInvokeCallback(typeof(xrPollEventDelegate))]
|
||||
private static XrResult xrPollEventInterceptor(XrInstance instance, ref XrEventDataBuffer eventData)
|
||||
{
|
||||
Profiler.BeginSample("VI:PollEvent");
|
||||
Profiler.BeginSample("ViveInterceptors:WaitFrame");
|
||||
XrResult result = XrResult.XR_SUCCESS;
|
||||
|
||||
if (xrPollEventOrigin != null)
|
||||
@@ -42,7 +28,7 @@ namespace VIVE.OpenXR
|
||||
|
||||
if (result == XrResult.XR_SUCCESS)
|
||||
{
|
||||
sb.Clear().Append("xrPollEventInterceptor() xrPollEvent ").Append(eventData.type); Log.D("PollEvent", sb);
|
||||
sb.Clear().Append("xrPollEventInterceptor() xrPollEvent ").Append(eventData.type); DEBUG(sb);
|
||||
switch(eventData.type)
|
||||
{
|
||||
case XrStructureType.XR_TYPE_EVENT_DATA_PASSTHROUGH_CONFIGURATION_IMAGE_RATE_CHANGED_HTC:
|
||||
@@ -55,7 +41,7 @@ namespace VIVE.OpenXR
|
||||
.Append(", fromImageRatesrc.dstImageRate: ").Append(fromImageRate.dstImageRate)
|
||||
.Append(", toImageRate.srcImageRate: ").Append(toImageRate.srcImageRate)
|
||||
.Append(", toImageRate.dstImageRate: ").Append(toImageRate.dstImageRate);
|
||||
Log.D("PollEvent", sb.ToString());
|
||||
DEBUG(sb);
|
||||
VivePassthroughImageRateChanged.Send(fromImageRate.srcImageRate, fromImageRate.dstImageRate, toImageRate.srcImageRate, toImageRate.dstImageRate);
|
||||
}
|
||||
break;
|
||||
@@ -67,7 +53,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);
|
||||
Log.D("PollEvent", sb);
|
||||
DEBUG(sb);
|
||||
VivePassthroughImageQualityChanged.Send(fromImageQuality.scale, toImageQuality.scale);
|
||||
}
|
||||
break;
|
||||
@@ -79,7 +65,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);
|
||||
Log.D("PollEvent", sb);
|
||||
DEBUG(sb);
|
||||
ViveDisplayRefreshRateChanged.Send(fromDisplayRefreshRate, toDisplayRefreshRate);
|
||||
}
|
||||
break;
|
||||
@@ -101,7 +87,7 @@ namespace VIVE.OpenXR
|
||||
.Append(", session: ").Append(eventDataSession.session)
|
||||
.Append(", state: ").Append(eventDataSession.state)
|
||||
.Append(", isUserPresent: ").Append(isUserPresent);
|
||||
Log.D("PollEvent", sb);
|
||||
DEBUG(sb);
|
||||
}
|
||||
break;
|
||||
case XrStructureType.XR_TYPE_EVENT_DATA_USER_PRESENCE_CHANGED_EXT:
|
||||
@@ -111,7 +97,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);
|
||||
Log.D("PollEvent", sb);
|
||||
DEBUG(sb);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -119,7 +105,7 @@ namespace VIVE.OpenXR
|
||||
}
|
||||
}
|
||||
|
||||
//sb.Clear().Append("xrPollEventInterceptor() xrPollEvent result: ").Append(result).Append(", isUserPresent: ").Append(isUserPresent); Log.d("PollEvent", sb);
|
||||
//sb.Clear().Append("xrPollEventInterceptor() xrPollEvent result: ").Append(result).Append(", isUserPresent: ").Append(isUserPresent); DEBUG(sb);
|
||||
}
|
||||
Profiler.EndSample();
|
||||
|
||||
|
||||
@@ -8,20 +8,6 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrEndFrame")]
|
||||
private static XrResult OnHookXrEndFrame(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (XrEndFrameOriginal == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
XrEndFrameOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrEndFrame>(function);
|
||||
}
|
||||
function = xrEndFrameInterceptorPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
public struct XrCompositionLayerBaseHeader
|
||||
{
|
||||
public XrStructureType type; // This base structure itself has no associated XrStructureType value.
|
||||
@@ -51,16 +37,15 @@ namespace VIVE.OpenXR
|
||||
// instance must not null
|
||||
//if (instance == null)
|
||||
// return XrEndFrameOriginal(session, ref frameEndInfo);
|
||||
Profiler.BeginSample("VI:EndFrameB");
|
||||
Profiler.BeginSample("VI:EndFrame");
|
||||
XrResult result = XrResult.XR_SUCCESS;
|
||||
bool ret = true;
|
||||
if (instance.BeforeOriginalEndFrame != null)
|
||||
ret = instance.BeforeOriginalEndFrame(session, ref frameEndInfo, ref result);
|
||||
Profiler.EndSample();
|
||||
if (!ret)
|
||||
if (instance.BeforeOriginalEndFrame != null &&
|
||||
!instance.BeforeOriginalEndFrame(session, ref frameEndInfo, ref result))
|
||||
{
|
||||
Profiler.EndSample();
|
||||
return result;
|
||||
}
|
||||
result = XrEndFrameOriginal(session, ref frameEndInfo);
|
||||
Profiler.BeginSample("VI:EndFrameA");
|
||||
instance.AfterOriginalEndFrame?.Invoke(session, ref frameEndInfo, ref result);
|
||||
Profiler.EndSample();
|
||||
return result;
|
||||
@@ -101,4 +86,4 @@ namespace VIVE.OpenXR
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using AOT;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrGetVisibilityMaskKHR")]
|
||||
private static XrResult OnHookXrGetVisibilityMaskKHR(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (xrGetVisibilityMaskKHROriginal == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
xrGetVisibilityMaskKHROriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrGetVisibilityMaskKHR>(function);
|
||||
}
|
||||
function = xrGetVisibilityMaskKHRInterceptorPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
public enum XrVisibilityMaskTypeKHR
|
||||
{
|
||||
HIDDEN_TRIANGLE_MESH_KHR = 1,
|
||||
VISIBLE_TRIANGLE_MESH_KHR = 2,
|
||||
LINE_LOOP_KHR = 3,
|
||||
}
|
||||
|
||||
public struct XrVisibilityMaskKHR
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public uint vertexCapacityInput;
|
||||
public uint vertexCountOutput;
|
||||
public IntPtr vertices; // XrVector2f array
|
||||
public uint indexCapacityInput;
|
||||
public uint indexCountOutput;
|
||||
public IntPtr indices; // uint array
|
||||
}
|
||||
|
||||
// XrCompositionLayerSpaceWarpInfoFlagsFB bits
|
||||
public delegate XrResult DelegateXrGetVisibilityMaskKHR(XrSession session, XrViewConfigurationType viewConfigurationType, uint viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, ref XrVisibilityMaskKHR visibilityMask);
|
||||
|
||||
private static readonly DelegateXrGetVisibilityMaskKHR xrGetVisibilityMaskKHRInterceptorHandle = new DelegateXrGetVisibilityMaskKHR(XrGetVisibilityMaskKHRInterceptor);
|
||||
private static readonly IntPtr xrGetVisibilityMaskKHRInterceptorPtr = Marshal.GetFunctionPointerForDelegate(xrGetVisibilityMaskKHRInterceptorHandle);
|
||||
static DelegateXrGetVisibilityMaskKHR xrGetVisibilityMaskKHROriginal = null;
|
||||
|
||||
[MonoPInvokeCallback(typeof(DelegateXrGetVisibilityMaskKHR))]
|
||||
private static XrResult XrGetVisibilityMaskKHRInterceptor(XrSession session, XrViewConfigurationType viewConfigurationType, uint viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, ref XrVisibilityMaskKHR visibilityMask)
|
||||
{
|
||||
// instance must not null
|
||||
//if (instance == null)
|
||||
// return XrGetVisibilityMaskKHROriginal(session, ref frameEndInfo);
|
||||
Profiler.BeginSample("VI:GetVMB");
|
||||
XrResult result = XrResult.XR_SUCCESS;
|
||||
bool ret = true;
|
||||
if (instance.BeforeOriginalGetVisibilityMaskKHR != null)
|
||||
ret = instance.BeforeOriginalGetVisibilityMaskKHR(session, viewConfigurationType, viewIndex, visibilityMaskType, ref visibilityMask, ref result);
|
||||
Profiler.EndSample();
|
||||
if (!ret)
|
||||
return result;
|
||||
result = xrGetVisibilityMaskKHROriginal(session, viewConfigurationType, viewIndex, visibilityMaskType, ref visibilityMask);
|
||||
Profiler.BeginSample("VI:GetVMA");
|
||||
instance.AfterOriginalGetVisibilityMaskKHR?.Invoke(session, viewConfigurationType, viewIndex, visibilityMaskType, ref visibilityMask, ref result);
|
||||
Profiler.EndSample();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If you return false, the original function will not be called.
|
||||
/// </summary>
|
||||
/// <param name="session"></param>
|
||||
/// <param name="frameEndInfo"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public delegate bool DelegateXrGetVisibilityMaskKHRInterceptor(XrSession session, XrViewConfigurationType viewConfigurationType, uint viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, ref XrVisibilityMaskKHR visibilityMask, ref XrResult result);
|
||||
|
||||
/// <summary>
|
||||
/// Use this to intercept the original function. This will be called before the original function.
|
||||
/// </summary>
|
||||
public DelegateXrGetVisibilityMaskKHRInterceptor BeforeOriginalGetVisibilityMaskKHR;
|
||||
|
||||
/// <summary>
|
||||
/// Use this to intercept the original function. This will be called after the original function.
|
||||
/// </summary>
|
||||
public DelegateXrGetVisibilityMaskKHRInterceptor AfterOriginalGetVisibilityMaskKHR;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4c00b0b7df78d34d89cd728c9de0672
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -9,20 +9,7 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
partial class ViveInterceptors
|
||||
{
|
||||
[HookHandler("xrWaitFrame")]
|
||||
private static XrResult OnHookXrWaitFrame(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
if (XrWaitFrameOriginal == null)
|
||||
{
|
||||
var ret = XrGetInstanceProcAddrOriginal(instance, name, out function);
|
||||
if (ret != XrResult.XR_SUCCESS)
|
||||
return ret;
|
||||
XrWaitFrameOriginal = Marshal.GetDelegateForFunctionPointer<DelegateXrWaitFrame>(function);
|
||||
}
|
||||
function = xrWaitFrameInterceptorPtr;
|
||||
return XrResult.XR_SUCCESS;
|
||||
}
|
||||
|
||||
#region XRWaitFrame
|
||||
public struct XrFrameWaitInfo
|
||||
{
|
||||
public XrStructureType type;
|
||||
@@ -116,5 +103,6 @@ namespace VIVE.OpenXR
|
||||
/// Use this to intercept the original function. This will be called after the original function.
|
||||
/// </summary>
|
||||
public DelegateXrWaitFrameInterceptor AfterOriginalWaitFrame;
|
||||
#endregion XRWaitFrame
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
using System.Text;
|
||||
// Non android will need UnityEngine
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
public static class Log
|
||||
{
|
||||
public const string TAG = "VIVE.OpenXR";
|
||||
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
[DllImport("liblog.so")]
|
||||
private static extern int __android_log_print(int prio, string tag, string fmt, string msg);
|
||||
#endif
|
||||
|
||||
// Use ("%s", message) instead of just (message) is because of the following reason:
|
||||
// In case message contains special characters like %, \n, \r, etc. It will be treated as format string.
|
||||
// This is a little waste of performance, but it's safer.
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void D(string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, TAG, "%s", message); // Android Debug
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void I(string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, TAG, "%s", message); // Android Info
|
||||
#else
|
||||
Debug.Log(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void W(string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, TAG, "%s", message); // Android Warning
|
||||
#else
|
||||
Debug.LogWarning(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void E(string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, TAG, "%s", message); // Android Error
|
||||
#else
|
||||
Debug.LogError(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void D(string tag, string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, tag, "%s", message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void I(string tag, string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, tag, "%s", message);
|
||||
#else
|
||||
Debug.LogFormat("{0}: {1}", tag, message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void W(string tag, string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, tag, "%s", message); // Android Warning
|
||||
#else
|
||||
Debug.LogWarningFormat("{0}: {1}", tag, message);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void E(string tag, string message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, tag, "%s", message); // Android Error
|
||||
#else
|
||||
Debug.LogErrorFormat("{0}: {1}", tag, message);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void D(StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, TAG, "%s", message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void I(StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, TAG, "%s", message.ToString());
|
||||
#else
|
||||
Debug.Log(message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void W(StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, TAG, "%s", message.ToString()); // Android Warning
|
||||
#else
|
||||
Debug.LogWarning(message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void E(StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, TAG, "%s", message.ToString()); // Android Error
|
||||
#else
|
||||
Debug.LogError(message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void D(string tag, StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, tag, "%s", message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void I(string tag, StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, tag, "%s", message.ToString());
|
||||
#else
|
||||
Debug.LogFormat("{0}: {1}", tag, message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void W(string tag, StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, tag, "%s", message.ToString()); // Android Warning
|
||||
#else
|
||||
Debug.LogWarningFormat("{0}: {1}", tag, message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void E(string tag, StringBuilder message)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, tag, "%s", message.ToString()); // Android Error
|
||||
#else
|
||||
Debug.LogErrorFormat("{0}: {1}", tag, message.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void DFmt(string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, TAG, "%s", string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void IFmt(string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, TAG, "%s", string.Format(fmt, args));
|
||||
#else
|
||||
Debug.LogFormat(fmt, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void WFmt(string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, TAG, "%s", string.Format(fmt, args)); // Android Warning
|
||||
#else
|
||||
Debug.LogWarningFormat(fmt, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void EFmt(string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, TAG, "%s", string.Format(fmt, args)); // Android Error
|
||||
#else
|
||||
Debug.LogErrorFormat(fmt, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not show in Standalone
|
||||
/// </summary>
|
||||
public static void DFmt(string tag, string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(3, tag, "%s", string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void IFmt(string tag, string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(4, tag, "%s", string.Format(fmt, args));
|
||||
#else
|
||||
Debug.LogFormat("{0}: {1}", tag, string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void WFmt(string tag, string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(5, tag, "%s", string.Format(fmt, args)); // Android Warning
|
||||
#else
|
||||
Debug.LogWarningFormat("{0}: {1}", tag, fmt, string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void EFmt(string tag, string fmt, params object[] args)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
__android_log_print(6, tag, "%s", string.Format(fmt, args)); // Android Error
|
||||
#else
|
||||
Debug.LogErrorFormat("{0}: {1}", tag, fmt, string.Format(fmt, args));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9750d8d4e8eb4994088534cb111510d3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -58,8 +58,7 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
isFree = true
|
||||
};
|
||||
pool.Insert(index, newItem);
|
||||
//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);
|
||||
Debug.Log("RT.MessagePool.Obtain() pool count=" + pool.Count);
|
||||
return newItem;
|
||||
}
|
||||
|
||||
@@ -102,13 +101,12 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
/// The queueSize should be the double count of message you want to pass to render thread in one frame.
|
||||
/// </summary>
|
||||
/// <param name="queueSize"></param>
|
||||
public PreAllocatedQueue(int queueSize = 2) : base()
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -156,7 +154,7 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
/// After use the Message, call Release() to the message.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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.
|
||||
@@ -165,12 +163,12 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
///
|
||||
/// <summary>
|
||||
/// 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.
|
||||
@@ -179,8 +177,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'.
|
||||
/// </summary>
|
||||
public class RenderThreadTask
|
||||
/// </summary>
|
||||
public class RenderThreadTask
|
||||
{
|
||||
private static IntPtr GetFunctionPointerForDelegate(Delegate del)
|
||||
{
|
||||
@@ -210,21 +208,20 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
/// <param name="render">The callback in render thread.</param>
|
||||
/// <param name="queueSize">If issue this event once in a frame, set queueSize as 2.</param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public RenderThreadTask(Receiver render, int queueSize = 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");
|
||||
receiver = render;
|
||||
if (receiver == null)
|
||||
throw new ArgumentNullException("receiver should not be null");
|
||||
|
||||
CommandList.Add(this);
|
||||
id = CommandList.IndexOf(this);
|
||||
}
|
||||
CommandList.Add(this);
|
||||
id = CommandList.IndexOf(this);
|
||||
}
|
||||
|
||||
~RenderThreadTask()
|
||||
~RenderThreadTask()
|
||||
{
|
||||
// Remove could be in a random order, and will cause orderId change. DO not remove any of them.
|
||||
//try { CommandList.Remove(this); } finally { }
|
||||
try { CommandList.RemoveAt(id); } finally { }
|
||||
}
|
||||
|
||||
void IssuePluginEvent(IntPtr callback, int eventID)
|
||||
@@ -285,36 +282,30 @@ 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;
|
||||
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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// 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<SampleMessage>();
|
||||
@@ -327,12 +318,12 @@ namespace VIVE.OpenXR.Common.RenderThread
|
||||
public void OnClicked()
|
||||
{
|
||||
// Reuse the same message type is ok.
|
||||
var msg = sampleRenderThreadTask2.Queue.Obtain<SampleMessage>();
|
||||
msg.dataPassedToRenderThread = 234;
|
||||
sampleRenderThreadTask2.Queue.Enqueue(msg);
|
||||
sampleRenderThreadTask2.IssueEvent();
|
||||
}
|
||||
}
|
||||
var msg = sampleRenderThreadTask2.Queue.Obtain<SampleMessage>();
|
||||
msg.dataPassedToRenderThread = 234;
|
||||
sampleRenderThreadTask2.Queue.Enqueue(msg);
|
||||
sampleRenderThreadTask2.IssueEvent();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ using UnityEngine.XR.OpenXR;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using VIVE.OpenXR.CompositionLayer;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
@@ -17,18 +16,15 @@ 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";
|
||||
|
||||
@@ -60,15 +56,6 @@ 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;
|
||||
@@ -87,66 +74,10 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
|
||||
[SerializeField]
|
||||
[Min(0.001f)]
|
||||
private float m_EquirectRadius = 1f;
|
||||
public float equirectRadius { get { return m_EquirectRadius; } }
|
||||
private float m_CylinderRadius = 1f;
|
||||
public float cylinderRadius { get { return m_CylinderRadius; } }
|
||||
#if UNITY_EDITOR
|
||||
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; } }
|
||||
public float CylinderRadius { get { return m_CylinderRadius; } set { m_CylinderRadius = value; } }
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
@@ -240,7 +171,6 @@ 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;
|
||||
@@ -262,7 +192,7 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
private bool placeholderGenerated = false;
|
||||
private static bool isSynchronized = false;
|
||||
private static RenderThreadSynchronizer synchronizer;
|
||||
public Camera hmd;
|
||||
private Camera hmd;
|
||||
|
||||
private ViveCompositionLayer compositionLayerFeature = null;
|
||||
|
||||
@@ -432,7 +362,6 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
previousLayerShape = layerShape;
|
||||
previousQuadWidth = m_QuadWidth;
|
||||
previousQuadHeight = m_QuadHeight;
|
||||
previousEquirectRadius = m_EquirectRadius;
|
||||
previousCylinderHeight = m_CylinderHeight;
|
||||
previousCylinderArcLength = m_CylinderArcLength;
|
||||
previousCylinderRadius = m_CylinderRadius;
|
||||
@@ -761,20 +690,6 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
compositionLayerCylinderFeature.Submit_CompositionLayerCylinder(AssignCompositionLayerParamsCylinder(eyeid, botheye), (OpenXR.CompositionLayer.LayerType)layerType, compositionDepth, (eyeid == 0) ? layerID : layerIDRight);
|
||||
}
|
||||
break;
|
||||
case LayerShape.Equirect:// TODO added code to submit
|
||||
ViveCompositionLayerEquirect compositionLayerEquicrectFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayerEquirect>();
|
||||
if (compositionLayerEquicrectFeature != null && compositionLayerEquicrectFeature.EquirectExtensionEnabled)
|
||||
{
|
||||
compositionLayerEquicrectFeature.Submit_CompositionLayerEquirect(AssignCompositionLayerParamsEquirect(eyeid), (OpenXR.CompositionLayer.LayerType)layerType, compositionDepth, (eyeid == 0) ? layerID : layerIDRight);
|
||||
}
|
||||
break;
|
||||
case LayerShape.Equirect2:// TODO added code to submit
|
||||
compositionLayerEquicrectFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayerEquirect>();
|
||||
if (compositionLayerEquicrectFeature != null && compositionLayerEquicrectFeature.Equirect2ExtensionEnabled)
|
||||
{
|
||||
compositionLayerEquicrectFeature.Submit_CompositionLayerEquirect2(AssignCompositionLayerParamsEquirect2(eyeid), (OpenXR.CompositionLayer.LayerType)layerType, compositionDepth, (eyeid == 0) ? layerID : layerIDRight);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -923,7 +838,7 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
else
|
||||
{
|
||||
XRInputSubsystem subsystem = null;
|
||||
SubsystemManager.GetSubsystems(inputSubsystems);
|
||||
SubsystemManager.GetInstances(inputSubsystems);
|
||||
if (inputSubsystems.Count > 0)
|
||||
{
|
||||
subsystem = inputSubsystems[0];
|
||||
@@ -958,97 +873,6 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
return CompositionLayerParamsQuad;
|
||||
}
|
||||
|
||||
XrCompositionLayerEquirectKHR CompositionLayerParamsEquirect = new XrCompositionLayerEquirectKHR();
|
||||
private XrCompositionLayerEquirectKHR AssignCompositionLayerParamsEquirect(int eyeid)
|
||||
{
|
||||
compositionLayerFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayer>();
|
||||
|
||||
CompositionLayerParamsEquirect.type = XrStructureType.XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR;
|
||||
CompositionLayerParamsEquirect.layerFlags = ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT | ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||
|
||||
if (!enabledColorScaleBiasInShader)
|
||||
{
|
||||
CompositionLayerParamsEquirect.layerFlags |= ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
|
||||
}
|
||||
|
||||
CompositionLayerParamsEquirect.subImage.imageRect = layerTextures[eyeid].textureLayout;
|
||||
CompositionLayerParamsEquirect.subImage.imageArrayIndex = 0;
|
||||
GetCompositionLayerPose(ref CompositionLayerParamsEquirect.pose); //Update isHeadLock
|
||||
|
||||
// HeadLock
|
||||
CompositionLayerParamsEquirect.space = compositionLayerFeature.HeadLockSpace;
|
||||
|
||||
switch (layerVisibility)
|
||||
{
|
||||
default:
|
||||
case Visibility.Both:
|
||||
CompositionLayerParamsEquirect.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_BOTH;
|
||||
break;
|
||||
case Visibility.Left:
|
||||
CompositionLayerParamsEquirect.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_LEFT;
|
||||
break;
|
||||
case Visibility.Right:
|
||||
CompositionLayerParamsEquirect.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_RIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
CompositionLayerParamsEquirect.subImage.imageRect = layerTextures[eyeid].textureLayout;
|
||||
CompositionLayerParamsEquirect.subImage.imageArrayIndex = 0;
|
||||
GetCompositionLayerPose(ref CompositionLayerParamsEquirect.pose);
|
||||
CompositionLayerParamsEquirect.radius = m_EquirectRadius;
|
||||
CompositionLayerParamsEquirect.scale.x = m_EquirectScaleX;
|
||||
CompositionLayerParamsEquirect.scale.y = m_EquirectScaleY;
|
||||
CompositionLayerParamsEquirect.bias.x = m_EquirectBiasX;
|
||||
CompositionLayerParamsEquirect.bias.y = m_EquirectBiasY;
|
||||
|
||||
return CompositionLayerParamsEquirect;
|
||||
}
|
||||
|
||||
XrCompositionLayerEquirect2KHR CompositionLayerParamsEquirect2 = new XrCompositionLayerEquirect2KHR();
|
||||
private XrCompositionLayerEquirect2KHR AssignCompositionLayerParamsEquirect2(int eyeid)
|
||||
{
|
||||
compositionLayerFeature = OpenXRSettings.Instance.GetFeature<ViveCompositionLayer>();
|
||||
|
||||
CompositionLayerParamsEquirect2.type = XrStructureType.XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR;
|
||||
CompositionLayerParamsEquirect2.layerFlags = ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT | ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||
|
||||
if (!enabledColorScaleBiasInShader)
|
||||
{
|
||||
CompositionLayerParamsEquirect2.layerFlags |= ViveCompositionLayerHelper.XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
|
||||
}
|
||||
|
||||
CompositionLayerParamsEquirect2.subImage.imageRect = layerTextures[eyeid].textureLayout;
|
||||
CompositionLayerParamsEquirect2.subImage.imageArrayIndex = 0;
|
||||
GetCompositionLayerPose(ref CompositionLayerParamsEquirect2.pose); //Update isHeadLock
|
||||
|
||||
// HeadLock
|
||||
CompositionLayerParamsEquirect2.space = compositionLayerFeature.HeadLockSpace;
|
||||
|
||||
switch (layerVisibility)
|
||||
{
|
||||
default:
|
||||
case Visibility.Both:
|
||||
CompositionLayerParamsEquirect2.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_BOTH;
|
||||
break;
|
||||
case Visibility.Left:
|
||||
CompositionLayerParamsEquirect2.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_LEFT;
|
||||
break;
|
||||
case Visibility.Right:
|
||||
CompositionLayerParamsEquirect2.eyeVisibility = XrEyeVisibility.XR_EYE_VISIBILITY_RIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
CompositionLayerParamsEquirect2.subImage.imageRect = layerTextures[eyeid].textureLayout;
|
||||
CompositionLayerParamsEquirect2.subImage.imageArrayIndex = 0;
|
||||
GetCompositionLayerPose(ref CompositionLayerParamsEquirect2.pose);
|
||||
CompositionLayerParamsEquirect2.radius = m_EquirectRadius;
|
||||
CompositionLayerParamsEquirect2.centralHorizontalAngle = Mathf.Deg2Rad * m_EquirectCentralHorizontalAngle;
|
||||
CompositionLayerParamsEquirect2.upperVerticalAngle = Mathf.Deg2Rad * m_EquirectUpperVerticalAngle;
|
||||
CompositionLayerParamsEquirect2.lowerVerticalAngle = Mathf.Deg2Rad * m_EquirectLowerVerticalAngle;
|
||||
|
||||
return CompositionLayerParamsEquirect2;
|
||||
}
|
||||
|
||||
XrCompositionLayerCylinderKHR CompositionLayerParamsCylinder = new XrCompositionLayerCylinderKHR();
|
||||
private XrCompositionLayerCylinderKHR AssignCompositionLayerParamsCylinder(int eyeid, bool botheye)
|
||||
{
|
||||
@@ -1069,7 +893,7 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
else
|
||||
{
|
||||
XRInputSubsystem subsystem = null;
|
||||
SubsystemManager.GetSubsystems(inputSubsystems);
|
||||
SubsystemManager.GetInstances(inputSubsystems);
|
||||
if (inputSubsystems.Count > 0)
|
||||
{
|
||||
subsystem = inputSubsystems[0];
|
||||
@@ -1298,15 +1122,7 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
bool isChanged = false;
|
||||
|
||||
if (layerShape == LayerShape.Equirect)
|
||||
{
|
||||
if (previousEquirectRadius != m_EquirectRadius)
|
||||
{
|
||||
previousEquirectRadius = m_EquirectRadius;
|
||||
isChanged = true;
|
||||
}
|
||||
}
|
||||
else if (layerShape == LayerShape.Cylinder)
|
||||
if (layerShape == LayerShape.Cylinder)
|
||||
{
|
||||
if (previousAngleOfArc != m_CylinderAngleOfArc ||
|
||||
previousCylinderArcLength != m_CylinderArcLength ||
|
||||
@@ -1767,9 +1583,6 @@ 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();
|
||||
@@ -1809,9 +1622,6 @@ 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);
|
||||
@@ -1847,26 +1657,6 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
|
||||
switch (layerShape)
|
||||
{
|
||||
case LayerShape.Equirect:
|
||||
generatedUnderlayMesh = new GameObject();
|
||||
generatedUnderlayMesh.name = EquirectUnderlayMeshName;
|
||||
generatedUnderlayMesh.transform.SetParent(transform);
|
||||
generatedUnderlayMesh.transform.localPosition = Vector3.zero;
|
||||
generatedUnderlayMesh.transform.localRotation = Quaternion.identity;
|
||||
|
||||
generatedUnderlayMesh.transform.localScale = GetNormalizedLocalScale(transform, Vector3.one);
|
||||
|
||||
generatedUnderlayMeshRenderer = generatedUnderlayMesh.AddComponent<MeshRenderer>();
|
||||
generatedUnderlayMeshFilter = generatedUnderlayMesh.AddComponent<MeshFilter>();
|
||||
if (solidEffect)
|
||||
generatedUnderlayMeshRenderer.sharedMaterial = new Material(Shader.Find("VIVE/OpenXR/CompositionLayer/UnderlayAlphaZeroSolid"));
|
||||
else
|
||||
generatedUnderlayMeshRenderer.sharedMaterial = new Material(Shader.Find("VIVE/OpenXR/CompositionLayer/UnderlayAlphaZero"));
|
||||
generatedUnderlayMeshRenderer.material.mainTexture = texture;
|
||||
|
||||
//Generate Mesh
|
||||
generatedUnderlayMeshFilter.mesh = MeshGenerationHelper.GenerateEquirectMesh(hmd, m_EquirectRadius);
|
||||
break;
|
||||
case LayerShape.Cylinder:
|
||||
//Generate vertices
|
||||
Vector3[] cylinderVertices = MeshGenerationHelper.GenerateCylinderVertex(m_CylinderAngleOfArc, m_CylinderRadius, m_CylinderHeight);
|
||||
@@ -1928,10 +1718,6 @@ 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);
|
||||
@@ -1988,8 +1774,6 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
Quad = 0,
|
||||
Cylinder = 1,
|
||||
Equirect = 2,
|
||||
Equirect2 = 3,
|
||||
}
|
||||
|
||||
public enum Visibility
|
||||
@@ -2256,92 +2040,6 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
return vertices;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector3 InverseTransformVert(in Vector3 vert, in Vector3 position, in Vector3 scale, float worldScale)
|
||||
{
|
||||
return new Vector3(
|
||||
(worldScale * vert.x - position.x) / scale.x,
|
||||
(worldScale * vert.y - position.y) / scale.y,
|
||||
(worldScale * vert.z - position.z) / scale.z);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector2 GetSphereUV(float theta, float phi, float expandScale)
|
||||
{
|
||||
float thetaU = expandScale * (theta / (2 * Mathf.PI) - 0.5f) + 0.5f;
|
||||
float phiV = expandScale * phi / Mathf.PI + 0.5f;
|
||||
|
||||
return new Vector2(thetaU, phiV);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector3 GetSphereVert(float theta, float phi)
|
||||
{
|
||||
return new Vector3(-Mathf.Sin(theta) * Mathf.Cos(phi), Mathf.Sin(phi), -Mathf.Cos(theta) * Mathf.Cos(phi));
|
||||
}
|
||||
|
||||
public static void BuildSphere(List<Vector3> verts, List<Vector2> uv, List<int> triangles, Vector3 position,
|
||||
Quaternion rotation, Vector3 scale, Rect rect, float worldScale = 800, int latitudes = 128,
|
||||
int longitudes = 128, float expandCoefficient = 1.0f)
|
||||
{
|
||||
position = Quaternion.Inverse(rotation) * position;
|
||||
|
||||
latitudes = Mathf.CeilToInt(latitudes * rect.height);
|
||||
longitudes = Mathf.CeilToInt(longitudes * rect.width);
|
||||
|
||||
float minTheta = Mathf.PI * 2.0f * rect.x;
|
||||
float minPhi = Mathf.PI * (0.5f - rect.y - rect.height);
|
||||
|
||||
float thetaScale = Mathf.PI * 2.0f * rect.width / longitudes;
|
||||
float phiScale = Mathf.PI * rect.height / latitudes;
|
||||
|
||||
float expandScale = 1.0f / expandCoefficient;
|
||||
|
||||
for (int j = 0; j < latitudes + 1; j += 1)
|
||||
{
|
||||
for (int k = 0; k < longitudes + 1; k++)
|
||||
{
|
||||
float theta = minTheta + k * thetaScale;
|
||||
float phi = minPhi + j * phiScale;
|
||||
|
||||
Vector2 suv = GetSphereUV(theta, phi, expandScale);
|
||||
uv.Add(new Vector2((suv.x - rect.x) / rect.width, (suv.y - rect.y) / rect.height));
|
||||
Vector3 vert = GetSphereVert(theta, phi);
|
||||
verts.Add(InverseTransformVert(in vert, in position, in scale, worldScale));
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < latitudes; j++)
|
||||
{
|
||||
for (int k = 0; k < longitudes; k++)
|
||||
{
|
||||
triangles.Add(j * (longitudes + 1) + k);
|
||||
triangles.Add((j + 1) * (longitudes + 1) + k);
|
||||
triangles.Add((j + 1) * (longitudes + 1) + k + 1);
|
||||
triangles.Add((j + 1) * (longitudes + 1) + k + 1);
|
||||
triangles.Add(j * (longitudes + 1) + k + 1);
|
||||
triangles.Add(j * (longitudes + 1) + k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Mesh GenerateEquirectMesh(Camera hmd, float equirectRadius)
|
||||
{
|
||||
Mesh eqicrectMesh = new Mesh();
|
||||
List<int> _Tris = new List<int>();
|
||||
List<Vector2> _UV = new List<Vector2>();
|
||||
List<Vector3> _Verts = new List<Vector3>();
|
||||
Rect _Rect = new Rect(0, 0, 1, 1);
|
||||
|
||||
BuildSphere(_Verts, _UV, _Tris, Camera.main.transform.position, Camera.main.transform.rotation, equirectRadius* Vector3.one, _Rect);
|
||||
|
||||
eqicrectMesh.SetVertices(_Verts);
|
||||
eqicrectMesh.SetTriangles(_Tris, 0);
|
||||
eqicrectMesh.SetUVs(0, _UV);
|
||||
eqicrectMesh.UploadMeshData(false);
|
||||
return eqicrectMesh;
|
||||
}
|
||||
|
||||
public static Mesh GenerateCylinderMesh(float cylinderAngleOfArc, Vector3[] vertices)
|
||||
{
|
||||
Mesh cylinderMesh = new Mesh();
|
||||
|
||||
@@ -416,7 +416,6 @@ namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
#if UNITY_ANDROID
|
||||
return passthroughFeature.HTCPassthrough_DestroyPassthrough(passthroughID);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -475,7 +474,6 @@ namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
else
|
||||
return false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -547,7 +545,6 @@ namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
#if UNITY_ANDROID
|
||||
return passthroughFeature.HTCPassthrough_SetMesh(passthroughID, (uint)vertexBuffer.Length, vertexBufferXrVector, (uint)indexBuffer.Length, indexBufferUint); ;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -626,7 +623,6 @@ namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
#if UNITY_ANDROID
|
||||
return passthroughFeature.HTCPassthrough_SetMeshTransform(passthroughID, passthroughFeature.GetXrSpaceFromSpaceType(spaceType), meshXrPose, meshXrScale);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -665,7 +661,7 @@ namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
#if UNITY_ANDROID
|
||||
return passthroughFeature.HTCPassthrough_SetLayerType(passthroughID, layerType, compositionDepth);
|
||||
#endif
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -706,7 +702,6 @@ namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
#if UNITY_ANDROID
|
||||
return passthroughFeature.HTCPassthrough_SetMeshTransformSpace(passthroughID, passthroughFeature.GetXrSpaceFromSpaceType(spaceType));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -769,7 +764,6 @@ namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
#if UNITY_ANDROID
|
||||
return passthroughFeature.HTCPassthrough_SetMeshTransformPosition(passthroughID, OpenXRHelper.ToOpenXRVector(trackingSpaceMeshPosition, convertFromUnityToOpenXR));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -832,7 +826,6 @@ namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
#if UNITY_ANDROID
|
||||
return passthroughFeature.HTCPassthrough_SetMeshTransformOrientation(passthroughID, OpenXRHelper.ToOpenXRQuaternion(trackingSpaceMeshRotation, convertFromUnityToOpenXR));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -874,7 +867,6 @@ namespace VIVE.OpenXR.CompositionLayer.Passthrough
|
||||
#if UNITY_ANDROID
|
||||
return passthroughFeature.HTCPassthrough_SetMeshTransformScale(passthroughID, OpenXRHelper.ToOpenXRVector(meshScale, false));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace VIVE.OpenXR.Editor.Interaction
|
||||
boxStyleWarning);
|
||||
GUILayout.EndHorizontal();
|
||||
EditorGUILayout.PropertyField(m_ViveXRTracker);
|
||||
/*
|
||||
|
||||
#if UNITY_ANDROID
|
||||
// ViveHandInteractionExt
|
||||
GUILayout.Space(20);
|
||||
@@ -88,7 +88,6 @@ namespace VIVE.OpenXR.Editor.Interaction
|
||||
GUILayout.EndHorizontal();
|
||||
EditorGUILayout.PropertyField(m_KHRHandInteraction);
|
||||
#endif
|
||||
*/
|
||||
#endregion
|
||||
|
||||
ViveInteractions myScript = target as ViveInteractions;
|
||||
@@ -97,7 +96,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
|
||||
@@ -117,7 +116,7 @@ namespace VIVE.OpenXR.Editor.Interaction
|
||||
feature.enabled = viveXrTracker;
|
||||
addPathEnumeration = viveXrTracker;
|
||||
}
|
||||
//if (feature is Hand.ViveHandInteractionExt) { feature.enabled = khrHandInteraction; }
|
||||
if (feature is Hand.ViveHandInteractionExt) { feature.enabled = khrHandInteraction; }
|
||||
}
|
||||
|
||||
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using AOT;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Composition Layer (Equirect)",
|
||||
Desc = "Enable this feature to enable the Composition Layer Equirect Extension",
|
||||
Company = "HTC",
|
||||
DocumentationLink = "..\\Documentation",
|
||||
OpenxrExtensionStrings = kOpenXRCylinderExtensionString,
|
||||
Version = "1.0.0",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class ViveCompositionLayerEquirect : OpenXRFeature
|
||||
{
|
||||
const string LOG_TAG = "VIVE.OpenXR.ViveCompositionLayer.Equirect";
|
||||
static void DEBUG(string msg) { Debug.Log(LOG_TAG + " " + msg); }
|
||||
static void WARNING(string msg) { Debug.LogWarning(LOG_TAG + " " + msg); }
|
||||
static void ERROR(string msg) { Debug.LogError(LOG_TAG + " " + msg); }
|
||||
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "vive.openxr.feature.compositionlayer.equirect";
|
||||
|
||||
private const string kOpenXRCylinderExtensionString = "XR_KHR_composition_layer_equirect XR_KHR_composition_layer_equirect2";
|
||||
|
||||
private bool m_EquirectExtensionEnabled = true;
|
||||
/// <summary>
|
||||
/// The extension "XR_KHR_composition_layer_equirect" is enabled or not.
|
||||
/// </summary>
|
||||
public bool EquirectExtensionEnabled
|
||||
{
|
||||
get { return m_EquirectExtensionEnabled; }
|
||||
}
|
||||
|
||||
private bool m_Equirect2ExtensionEnabled = true;
|
||||
/// <summary>
|
||||
/// The extension "XR_KHR_composition_layer_equirect2" is enabled or not.
|
||||
/// </summary>
|
||||
public bool Equirect2ExtensionEnabled
|
||||
{
|
||||
get { return m_Equirect2ExtensionEnabled; }
|
||||
}
|
||||
|
||||
|
||||
#region OpenXR Life Cycle
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
if (!OpenXRRuntime.IsExtensionEnabled("XR_KHR_composition_layer_equirect"))
|
||||
{
|
||||
WARNING("OnInstanceCreate() " + "XR_KHR_composition_layer_equirect" + " is NOT enabled.");
|
||||
|
||||
m_EquirectExtensionEnabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!OpenXRRuntime.IsExtensionEnabled("XR_KHR_composition_layer_equirect2"))
|
||||
{
|
||||
WARNING("OnInstanceCreate() " + "XR_KHR_composition_layer_equirect2" + " is NOT enabled.");
|
||||
|
||||
m_Equirect2ExtensionEnabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Wrapper Functions
|
||||
private const string ExtLib = "viveopenxr";
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "submit_CompositionLayerEquirect")]
|
||||
public static extern void VIVEOpenXR_Submit_CompositionLayerEquirect(XrCompositionLayerEquirectKHR equirect, LayerType layerType, uint compositionDepth, int layerID);
|
||||
/// <summary>
|
||||
/// submit compostion layer of type equirect.
|
||||
/// </summary>
|
||||
public void Submit_CompositionLayerEquirect(XrCompositionLayerEquirectKHR equirect, LayerType layerType, uint compositionDepth, int layerID)
|
||||
{
|
||||
if (!EquirectExtensionEnabled)
|
||||
{
|
||||
ERROR("Submit_CompositionLayerEquirect: " + "XR_KHR_composition_layer_equirect" + " is NOT enabled.");
|
||||
}
|
||||
|
||||
VIVEOpenXR_Submit_CompositionLayerEquirect(equirect, layerType, compositionDepth, layerID);
|
||||
}
|
||||
|
||||
[DllImportAttribute(ExtLib, EntryPoint = "submit_CompositionLayerEquirect2")]
|
||||
public static extern void VIVEOpenXR_Submit_CompositionLayerEquirect2(XrCompositionLayerEquirect2KHR equirect2, LayerType layerType, uint compositionDepth, int layerID);
|
||||
/// <summary>
|
||||
/// submit compostion layer of type equirect2.
|
||||
/// </summary>
|
||||
public void Submit_CompositionLayerEquirect2(XrCompositionLayerEquirect2KHR equirect2, LayerType layerType, uint compositionDepth, int layerID)
|
||||
{
|
||||
if (!Equirect2ExtensionEnabled)
|
||||
{
|
||||
ERROR("Submit_CompositionLayerEquirect2: " + "XR_KHR_composition_layer_equirect2" + " is NOT enabled.");
|
||||
}
|
||||
|
||||
VIVEOpenXR_Submit_CompositionLayerEquirect2(equirect2, layerType, compositionDepth, layerID);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec826264ff4d75d4081f2ca472a3e083
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -215,35 +215,6 @@ namespace VIVE.OpenXR.CompositionLayer
|
||||
public float aspectRatio;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrCompositionLayerEquirectKHR
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrCompositionLayerFlags layerFlags;
|
||||
public XrSpace space;
|
||||
public XrEyeVisibility eyeVisibility;
|
||||
public XrSwapchainSubImage subImage;
|
||||
public XrPosef pose;
|
||||
public float radius;
|
||||
public XrVector2f scale;
|
||||
public XrVector2f bias;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrCompositionLayerEquirect2KHR
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
public XrCompositionLayerFlags layerFlags;
|
||||
public XrSpace space;
|
||||
public XrEyeVisibility eyeVisibility;
|
||||
public XrSwapchainSubImage subImage;
|
||||
public XrPosef pose;
|
||||
public float radius;
|
||||
public float centralHorizontalAngle;
|
||||
public float upperVerticalAngle;
|
||||
public float lowerVerticalAngle;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct XrSwapchainSubImage
|
||||
{
|
||||
public XrSwapchain swapchain;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# 12.1. XR_HTC_frame_synchronization
|
||||
## Overview
|
||||
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.
|
||||
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.
|
||||
## Name String
|
||||
XR_HTC_frame_synchronization
|
||||
## Revision
|
||||
|
||||
@@ -209,7 +209,7 @@ namespace VIVE.OpenXR.Hand
|
||||
/// </summary>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(kDeviceLocalizedName); DEBUG(sb);
|
||||
sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(kDeviceLocalizedName); DEBUG(sb);
|
||||
InputSystem.RegisterLayout(typeof(HandInteractionDevice),
|
||||
kLayoutName,
|
||||
matches: new InputDeviceMatcher()
|
||||
@@ -222,7 +222,7 @@ namespace VIVE.OpenXR.Hand
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
InputSystem.RemoveLayout(kLayoutName);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ using UnityEngine.InputSystem;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
@@ -31,7 +30,7 @@ namespace VIVE.OpenXR.Hand
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of hand interaction profiles in OpenXR. It enables <see cref="ViveHandInteractionExt.kOpenxrExtensionString">XR_EXT_hand_interaction</see> in the underyling runtime.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "VIVE XR Hand Interaction Ext (Deprecated)",
|
||||
[OpenXRFeature(UiName = "VIVE XR Hand Interaction Ext",
|
||||
Hidden = true,
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
Company = "HTC",
|
||||
@@ -42,7 +41,6 @@ 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
|
||||
@@ -226,7 +224,7 @@ namespace VIVE.OpenXR.Hand
|
||||
#region Supported component paths
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/aim/pose' OpenXR Input Binding.<br></br>
|
||||
/// Typically used for aiming at objects out of arm<EFBFBD><EFBFBD>s reach. When using a hand interaction profile, it is typically paired with <see cref="pointerActivateValue"/> to optimize aiming ray stability while performing the gesture.<br></br>
|
||||
/// Typically used for aiming at objects out of arm¡¦s reach. When using a hand interaction profile, it is typically paired with <see cref="pointerActivateValue"/> to optimize aiming ray stability while performing the gesture.<br></br>
|
||||
/// When using a controller interaction profile, the "aim" pose is typically paired with a trigger or a button for aim and fire operations.
|
||||
/// </summary>
|
||||
public const string aim = "/input/aim/pose";
|
||||
@@ -245,7 +243,7 @@ namespace VIVE.OpenXR.Hand
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding.<br></br>
|
||||
/// Typically used for holding a large object in the user<EFBFBD><EFBFBD>s hand. When using a hand interaction profile, it is typically paired with <see cref="graspValue"/> for the user to directly manipulate an object held in a hand.<br></br>
|
||||
/// Typically used for holding a large object in the user¡¦s hand. When using a hand interaction profile, it is typically paired with <see cref="graspValue"/> for the user to directly manipulate an object held in a hand.<br></br>
|
||||
/// When using a controller interaction profile, the "grip" pose is typically paired with a "squeeze" button or trigger that gives the user the sense of tightly holding an object.
|
||||
/// </summary>
|
||||
public const string grip = "/input/grip/pose";
|
||||
@@ -319,7 +317,7 @@ namespace VIVE.OpenXR.Hand
|
||||
/// </summary>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(kDeviceLocalizedName); DEBUG(sb);
|
||||
sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(kDeviceLocalizedName); DEBUG(sb);
|
||||
InputSystem.RegisterLayout(typeof(HandInteractionExtDevice),
|
||||
kLayoutName,
|
||||
matches: new InputDeviceMatcher()
|
||||
@@ -332,7 +330,7 @@ namespace VIVE.OpenXR.Hand
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
InputSystem.RemoveLayout(kLayoutName);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,458 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using VIVE.OpenXR.Interaction;
|
||||
|
||||
#if UNITY_XR_HANDS
|
||||
using UnityEngine.XR.Hands;
|
||||
using UnityEngine.XR.Hands.ProviderImplementation;
|
||||
namespace VIVE.OpenXR.Hand
|
||||
{
|
||||
public class ViveHandProvider : XRHandSubsystemProvider
|
||||
{
|
||||
#region Hand Interaction
|
||||
private const string kFeatureAimPos = "PointerPosition";
|
||||
private const string kFeatureAimRot = "PointerRotation";
|
||||
private const string kFeatureAimValue = "PointerActivateValue";
|
||||
private const string kFeatureGripPos = "DevicePosition";
|
||||
private const string kFeatureGripRot = "DeviceRotation";
|
||||
private const string kFeatureGripValue = "GraspValue";
|
||||
private const string kFeaturePinchPos = "PinchPosition";
|
||||
private const string kFeaturePinchRot = "PinchRotation";
|
||||
private const string kFeaturePinchValue = "PinchValue";
|
||||
private const string kFeaturePokePos = "PokePosition";
|
||||
private const string kFeaturePokeRot = "PokeRotation";
|
||||
|
||||
private class HandDevice
|
||||
{
|
||||
public Pose aimPose => m_AimPose;
|
||||
public Pose gripPose => m_GripPose;
|
||||
public Pose pinchPose => m_PinchPose;
|
||||
public Pose pokePose => m_PokePose;
|
||||
public float aimActivateValue => m_AimActivateValue;
|
||||
public float graspValue => m_GraspValue;
|
||||
public float pinchValue => m_PinchValue;
|
||||
|
||||
private Pose m_AimPose = Pose.identity;
|
||||
private Pose m_GripPose = Pose.identity;
|
||||
private Pose m_PinchPose = Pose.identity;
|
||||
private Pose m_PokePose = Pose.identity;
|
||||
private float m_AimActivateValue = 0;
|
||||
private float m_GraspValue = 0;
|
||||
private float m_PinchValue = 0;
|
||||
|
||||
private InputDevice device = default(InputDevice);
|
||||
private Dictionary<string, InputFeatureUsage<Vector3>> posUsageMapping = new Dictionary<string, InputFeatureUsage<Vector3>>();
|
||||
private Dictionary<string, InputFeatureUsage<Quaternion>> rotUsageMapping = new Dictionary<string, InputFeatureUsage<Quaternion>>();
|
||||
private Dictionary<string, InputFeatureUsage<float>> valueUsageMapping = new Dictionary<string, InputFeatureUsage<float>>();
|
||||
|
||||
public HandDevice(InputDevice device)
|
||||
{
|
||||
this.device = device;
|
||||
|
||||
List<InputFeatureUsage> inputFeatures = new List<InputFeatureUsage>();
|
||||
device.TryGetFeatureUsages(inputFeatures);
|
||||
for (int i = 0; i < inputFeatures.Count; i++)
|
||||
{
|
||||
InputFeatureUsage feature = inputFeatures[i];
|
||||
switch (feature.name)
|
||||
{
|
||||
case kFeatureAimPos:
|
||||
case kFeatureGripPos:
|
||||
case kFeaturePinchPos:
|
||||
case kFeaturePokePos:
|
||||
posUsageMapping.Add(feature.name, feature.As<Vector3>());
|
||||
break;
|
||||
case kFeatureAimRot:
|
||||
case kFeatureGripRot:
|
||||
case kFeaturePinchRot:
|
||||
case kFeaturePokeRot:
|
||||
rotUsageMapping.Add(feature.name, feature.As<Quaternion>());
|
||||
break;
|
||||
case kFeatureAimValue:
|
||||
case kFeatureGripValue:
|
||||
case kFeaturePinchValue:
|
||||
valueUsageMapping.Add(feature.name, feature.As<float>());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateInputValue()
|
||||
{
|
||||
UpdatePosition();
|
||||
UpdateRotation();
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private void UpdatePosition()
|
||||
{
|
||||
var enumerator = posUsageMapping.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var feature = enumerator.Current;
|
||||
string featureName = feature.Key;
|
||||
InputFeatureUsage<Vector3> featureUsage = feature.Value;
|
||||
if (device.TryGetFeatureValue(featureUsage, out Vector3 position))
|
||||
{
|
||||
switch (featureName)
|
||||
{
|
||||
case kFeatureAimPos:
|
||||
m_AimPose.position = position;
|
||||
break;
|
||||
case kFeatureGripPos:
|
||||
m_GripPose.position = position;
|
||||
break;
|
||||
case kFeaturePinchPos:
|
||||
m_PinchPose.position = position;
|
||||
break;
|
||||
case kFeaturePokePos:
|
||||
m_PokePose.position = position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateRotation()
|
||||
{
|
||||
var enumerator = rotUsageMapping.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var feature = enumerator.Current;
|
||||
string featureName = feature.Key;
|
||||
InputFeatureUsage<Quaternion> featureUsage = feature.Value;
|
||||
if (device.TryGetFeatureValue(featureUsage, out Quaternion rotation))
|
||||
{
|
||||
switch (featureName)
|
||||
{
|
||||
case kFeatureAimRot:
|
||||
m_AimPose.rotation = rotation;
|
||||
break;
|
||||
case kFeatureGripRot:
|
||||
m_GripPose.rotation = rotation;
|
||||
break;
|
||||
case kFeaturePinchRot:
|
||||
m_PinchPose.rotation = rotation;
|
||||
break;
|
||||
case kFeaturePokeRot:
|
||||
m_PokePose.rotation = rotation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateValue()
|
||||
{
|
||||
var enumerator = valueUsageMapping.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var feature = enumerator.Current;
|
||||
string featureName = feature.Key;
|
||||
InputFeatureUsage<float> featureUsage = feature.Value;
|
||||
if (device.TryGetFeatureValue(featureUsage, out float value))
|
||||
{
|
||||
switch (featureName)
|
||||
{
|
||||
case kFeatureAimValue:
|
||||
m_AimActivateValue = value;
|
||||
break;
|
||||
case kFeatureGripValue:
|
||||
m_GraspValue = value;
|
||||
break;
|
||||
case kFeaturePinchValue:
|
||||
m_PinchValue = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static HandDevice leftHandDevice = null;
|
||||
private static HandDevice rightHandDevice = null;
|
||||
private const string kInteractionDeviceName = "Vive Hand Interaction Ext OpenXR";
|
||||
#endregion
|
||||
|
||||
private ViveHandTracking viveHand;
|
||||
|
||||
public override void Destroy() { }
|
||||
|
||||
public override void GetHandLayout(NativeArray<bool> handJointsInLayout)
|
||||
{
|
||||
handJointsInLayout[XRHandJointID.Palm.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.Wrist.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.ThumbMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.ThumbProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.ThumbDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.ThumbTip.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.IndexMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.IndexProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.IndexIntermediate.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.IndexDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.IndexTip.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.MiddleMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.MiddleProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.MiddleIntermediate.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.MiddleDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.MiddleTip.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.RingMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.RingProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.RingIntermediate.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.RingDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.RingTip.ToIndex()] = true;
|
||||
|
||||
handJointsInLayout[XRHandJointID.LittleMetacarpal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.LittleProximal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.LittleIntermediate.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.LittleDistal.ToIndex()] = true;
|
||||
handJointsInLayout[XRHandJointID.LittleTip.ToIndex()] = true;
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
Initialize();
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
InitHandInteractionDevices();
|
||||
InputDevices.deviceConnected += DeviceConnected;
|
||||
InputDevices.deviceDisconnected += DeviceDisconnected;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
InputDevices.deviceConnected -= DeviceConnected;
|
||||
InputDevices.deviceDisconnected -= DeviceDisconnected;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override XRHandSubsystem.UpdateSuccessFlags TryUpdateHands(XRHandSubsystem.UpdateType updateType, ref Pose leftHandRootPose, NativeArray<XRHandJoint> leftHandJoints, ref Pose rightHandRootPose, NativeArray<XRHandJoint> rightHandJoints)
|
||||
{
|
||||
XRHandSubsystem.UpdateSuccessFlags flags = XRHandSubsystem.UpdateSuccessFlags.None;
|
||||
if (UpdateHand(true, ref leftHandRootPose, ref leftHandJoints))
|
||||
{
|
||||
flags |= XRHandSubsystem.UpdateSuccessFlags.LeftHandRootPose | XRHandSubsystem.UpdateSuccessFlags.LeftHandJoints;
|
||||
}
|
||||
if (UpdateHand(false, ref rightHandRootPose, ref rightHandJoints))
|
||||
{
|
||||
flags |= XRHandSubsystem.UpdateSuccessFlags.RightHandRootPose | XRHandSubsystem.UpdateSuccessFlags.RightHandJoints;
|
||||
}
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
if (updateType == XRHandSubsystem.UpdateType.Dynamic && canSurfaceCommonPoseData)
|
||||
{
|
||||
UpdateHandInteraction();
|
||||
}
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
public override bool canSurfaceCommonPoseData => HandInteractionSupport();
|
||||
|
||||
public override bool TryGetAimPose(Handedness handedness, out Pose aimPose)
|
||||
{
|
||||
aimPose = Pose.identity;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
aimPose = handDevice.aimPose;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetAimActivateValue(Handedness handedness, out float aimActivateValue)
|
||||
{
|
||||
aimActivateValue = 0;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
aimActivateValue = handDevice.aimActivateValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetGripPose(Handedness handedness, out Pose gripPose)
|
||||
{
|
||||
gripPose = Pose.identity;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
gripPose = handDevice.gripPose;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetGraspValue(Handedness handedness, out float graspValue)
|
||||
{
|
||||
graspValue = 0;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
graspValue = handDevice.graspValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetPinchPose(Handedness handedness, out Pose pinchPose)
|
||||
{
|
||||
pinchPose = Pose.identity;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
pinchPose = handDevice.pinchPose;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetPinchValue(Handedness handedness, out float pinchValue)
|
||||
{
|
||||
pinchValue = 0;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
pinchValue = handDevice.pinchValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryGetPokePose(Handedness handedness, out Pose pokePose)
|
||||
{
|
||||
pokePose = Pose.identity;
|
||||
HandDevice handDevice = GetHandDevice(handedness);
|
||||
if (handDevice != null)
|
||||
{
|
||||
pokePose = handDevice.pokePose;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DeviceConnected(InputDevice inputDevice)
|
||||
{
|
||||
if (inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Left) &&
|
||||
inputDevice.name == kInteractionDeviceName)
|
||||
{
|
||||
leftHandDevice = new HandDevice(inputDevice);
|
||||
}
|
||||
if (inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Right) &&
|
||||
inputDevice.name == kInteractionDeviceName)
|
||||
{
|
||||
rightHandDevice = new HandDevice(inputDevice);
|
||||
}
|
||||
}
|
||||
|
||||
private void DeviceDisconnected(InputDevice inputDevice)
|
||||
{
|
||||
if (inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Left) &&
|
||||
inputDevice.name == kInteractionDeviceName)
|
||||
{
|
||||
leftHandDevice = default;
|
||||
}
|
||||
if (inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Right) &&
|
||||
inputDevice.name == kInteractionDeviceName)
|
||||
{
|
||||
rightHandDevice = default;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitHandInteractionDevices()
|
||||
{
|
||||
List<InputDevice> inputDevices = new List<InputDevice>();
|
||||
InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.HeldInHand |
|
||||
InputDeviceCharacteristics.HandTracking |
|
||||
InputDeviceCharacteristics.TrackedDevice, inputDevices);
|
||||
for (int i = 0; i < inputDevices.Count; i++)
|
||||
{
|
||||
InputDevice inputDevice = inputDevices[i];
|
||||
DeviceConnected(inputDevice);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHandInteraction()
|
||||
{
|
||||
if (leftHandDevice != null)
|
||||
{
|
||||
leftHandDevice.UpdateInputValue();
|
||||
}
|
||||
if (rightHandDevice != null)
|
||||
{
|
||||
rightHandDevice.UpdateInputValue();
|
||||
}
|
||||
}
|
||||
|
||||
private HandDevice GetHandDevice(Handedness handedness) => handedness == Handedness.Left ? leftHandDevice : rightHandDevice;
|
||||
|
||||
private bool HandInteractionSupport()
|
||||
{
|
||||
ViveInteractions viveInteractions = OpenXRSettings.Instance.GetFeature<ViveInteractions>();
|
||||
if (viveInteractions.enabled)
|
||||
{
|
||||
return viveInteractions.UseKhrHandInteraction();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
viveHand = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
}
|
||||
|
||||
private bool UpdateHand(bool isLeft, ref Pose handRootPose, ref NativeArray<XRHandJoint> handJoints)
|
||||
{
|
||||
if (!viveHand) { return false; }
|
||||
bool isValid = viveHand.GetJointLocations(isLeft, out XrHandJointLocationEXT[] viveJoints);
|
||||
|
||||
Handedness handedness = isLeft ? Handedness.Left : Handedness.Right;
|
||||
XRHandJointTrackingState trackingState = XRHandJointTrackingState.None;
|
||||
for (int jointIndex = XRHandJointID.BeginMarker.ToIndex(); jointIndex < XRHandJointID.EndMarker.ToIndex(); ++jointIndex)
|
||||
{
|
||||
XRHandJointID jointID = XRHandJointIDUtility.FromIndex(jointIndex);
|
||||
int viveIndex = XRHandJointIDToIndex(jointID);
|
||||
|
||||
Pose pose = Pose.identity;
|
||||
if (isValid)
|
||||
{
|
||||
pose.position = viveJoints[viveIndex].pose.position.ToUnityVector();
|
||||
pose.rotation = viveJoints[viveIndex].pose.orientation.ToUnityQuaternion();
|
||||
trackingState = XRHandJointTrackingState.Pose;
|
||||
}
|
||||
handJoints[jointIndex] = XRHandProviderUtility.CreateJoint(handedness, trackingState, jointID, pose);
|
||||
}
|
||||
handJoints[XRHandJointID.Wrist.ToIndex()].TryGetPose(out handRootPose);
|
||||
return isValid;
|
||||
}
|
||||
|
||||
private int XRHandJointIDToIndex(XRHandJointID id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case XRHandJointID.Palm:
|
||||
return 0;
|
||||
case XRHandJointID.Wrist:
|
||||
return 1;
|
||||
default:
|
||||
return (int)id - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68f6a3e78d49e1143a9aa0a111a04a0a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,102 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using VIVE.OpenXR.Interaction;
|
||||
|
||||
#if UNITY_XR_HANDS
|
||||
using UnityEngine.XR.Hands;
|
||||
using UnityEngine.XR.Hands.ProviderImplementation;
|
||||
namespace VIVE.OpenXR.Hand
|
||||
{
|
||||
public class ViveHandSubsystem : XRHandSubsystem
|
||||
{
|
||||
public const string featureId = "vive.openxr.feature.xrhandsubsystem";
|
||||
private static XRHandSubsystem subsystem = null;
|
||||
private XRHandProviderUtility.SubsystemUpdater subsystemUpdater = null;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void RegisterDescriptor()
|
||||
{
|
||||
if (!ViveHandTrackingSupport()) { return; }
|
||||
bool handInteractionSupport = HandInteractionSupport();
|
||||
|
||||
var handsSubsystemCinfo = new XRHandSubsystemDescriptor.Cinfo
|
||||
{
|
||||
id = featureId,
|
||||
providerType = typeof(ViveHandProvider),
|
||||
subsystemTypeOverride = typeof(ViveHandSubsystem),
|
||||
#if UNITY_XR_HANDS_1_5_0
|
||||
supportsAimPose = handInteractionSupport,
|
||||
supportsAimActivateValue = handInteractionSupport,
|
||||
supportsGraspValue = handInteractionSupport,
|
||||
supportsGripPose = handInteractionSupport,
|
||||
supportsPinchPose = handInteractionSupport,
|
||||
supportsPinchValue = handInteractionSupport,
|
||||
supportsPokePose = handInteractionSupport,
|
||||
#endif
|
||||
};
|
||||
XRHandSubsystemDescriptor.Register(handsSubsystemCinfo);
|
||||
}
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void StartSubsystem()
|
||||
{
|
||||
List<XRHandSubsystemDescriptor> descriptors = new List<XRHandSubsystemDescriptor>();
|
||||
if (subsystem == null || !subsystem.running)
|
||||
{
|
||||
descriptors.Clear();
|
||||
SubsystemManager.GetSubsystemDescriptors(descriptors);
|
||||
for (int i = 0; i < descriptors.Count; i++)
|
||||
{
|
||||
XRHandSubsystemDescriptor descriptor = descriptors[i];
|
||||
if (descriptor.id == featureId)
|
||||
{
|
||||
subsystem = descriptor.Create();
|
||||
subsystem.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
if (subsystemUpdater == null)
|
||||
{
|
||||
subsystemUpdater = new XRHandProviderUtility.SubsystemUpdater(subsystem);
|
||||
}
|
||||
subsystemUpdater.Start();
|
||||
|
||||
}
|
||||
|
||||
protected override void OnStop()
|
||||
{
|
||||
base.OnStop();
|
||||
subsystemUpdater.Stop();
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
subsystemUpdater.Destroy();
|
||||
subsystemUpdater = null;
|
||||
}
|
||||
|
||||
private static bool ViveHandTrackingSupport()
|
||||
{
|
||||
ViveHandTracking viveHand = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
return viveHand.enabled;
|
||||
}
|
||||
|
||||
private static bool HandInteractionSupport()
|
||||
{
|
||||
ViveInteractions viveInteractions = OpenXRSettings.Instance.GetFeature<ViveInteractions>();
|
||||
if (viveInteractions.enabled)
|
||||
{
|
||||
return viveInteractions.UseKhrHandInteraction();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ce39c25a1e4a794c807d9f723d37804
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -9,6 +9,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using AOT;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
|
||||
@@ -62,74 +63,48 @@ namespace VIVE.OpenXR.Hand
|
||||
private bool m_XrInstanceCreated = false;
|
||||
private XrInstance m_XrInstance = 0;
|
||||
private static IntPtr xrGetInstanceProcAddr_prev;
|
||||
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.
|
||||
|
||||
private static IntPtr WaitFrame_prev;
|
||||
private static XrFrameWaitInfo m_frameWaitInfo;
|
||||
private static XrFrameState m_frameState;
|
||||
protected override IntPtr HookGetInstanceProcAddr(IntPtr func)
|
||||
{
|
||||
ViveInterceptors.Instance.AddRequiredFunction("xrWaitFrame");
|
||||
if (ViveInterceptors.Instance.BeforeOriginalWaitFrame == null)
|
||||
{
|
||||
ViveInterceptors.Instance.BeforeOriginalWaitFrame = new ViveInterceptors.DelegateXrWaitFrameInterceptor(BeforeWaitFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViveInterceptors.Instance.BeforeOriginalWaitFrame += BeforeWaitFrame;
|
||||
}
|
||||
|
||||
if (ViveInterceptors.Instance.AfterOriginalWaitFrame == null)
|
||||
{
|
||||
ViveInterceptors.Instance.AfterOriginalWaitFrame = new ViveInterceptors.DelegateXrWaitFrameInterceptor(AfterWaitFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViveInterceptors.Instance.AfterOriginalWaitFrame += AfterWaitFrame;
|
||||
}
|
||||
return ViveInterceptors.Instance.HookGetInstanceProcAddr(func);
|
||||
UnityEngine.Debug.Log("EXT: registering our own xrGetInstanceProcAddr");
|
||||
xrGetInstanceProcAddr_prev = func;
|
||||
return Marshal.GetFunctionPointerForDelegate(m_intercept_xrWaitFrame_xrGetInstanceProcAddr);
|
||||
}
|
||||
|
||||
private bool BeforeWaitFrame(XrSession session, ref ViveInterceptors.XrFrameWaitInfo frameWaitInfo, ref ViveInterceptors.XrFrameState frameState, ref XrResult result)
|
||||
[MonoPInvokeCallback(typeof(OpenXRHelper.xrGetInstanceProcAddrDelegate))]
|
||||
private static XrResult intercept_xrWaitFrame_xrGetInstanceProcAddr(XrInstance instance, string name, out IntPtr function)
|
||||
{
|
||||
ViveInterceptors.XrFrameState nextFrameState = new ViveInterceptors.XrFrameState
|
||||
if (xrGetInstanceProcAddr_prev == null || xrGetInstanceProcAddr_prev == IntPtr.Zero)
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_PASSTHROUGH_HAND_TRACKER_FRAME_STATE_HTC,
|
||||
next = frameState.next,
|
||||
predictedDisplayPeriod = 0,
|
||||
predictedDisplayTime = 0,
|
||||
shouldRender = false
|
||||
};
|
||||
frameState.next = MemoryTools.ToIntPtr(nextFrameState);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool AfterWaitFrame(XrSession session, ref ViveInterceptors.XrFrameWaitInfo frameWaitInfo, ref ViveInterceptors.XrFrameState frameState, ref XrResult result)
|
||||
{
|
||||
m_predictedDisplayTime = frameState.predictedDisplayTime;
|
||||
m_predictedDisplayDuration = frameState.predictedDisplayPeriod;
|
||||
|
||||
IntPtr next = frameState.next;
|
||||
HashSet<IntPtr> visited = new HashSet<IntPtr>();
|
||||
int iterationCount = 0;
|
||||
int maxIterations = 10;
|
||||
while (next != IntPtr.Zero && !visited.Contains(next))
|
||||
{
|
||||
if (iterationCount++ > maxIterations) { break; }
|
||||
visited.Add(next);
|
||||
ViveInterceptors.XrFrameState nextFrameState = Marshal.PtrToStructure<ViveInterceptors.XrFrameState>(next);
|
||||
if (nextFrameState.type == XrStructureType.XR_TYPE_PASSTHROUGH_HAND_TRACKER_FRAME_STATE_HTC &&
|
||||
nextFrameState.predictedDisplayTime != 0)
|
||||
{
|
||||
m_predictedDisplayTime = nextFrameState.predictedDisplayTime;
|
||||
break;
|
||||
}
|
||||
next = nextFrameState.next;
|
||||
UnityEngine.Debug.LogError("xrGetInstanceProcAddr_prev is null");
|
||||
function = IntPtr.Zero;
|
||||
return XrResult.XR_ERROR_VALIDATION_FAILURE;
|
||||
}
|
||||
return true;
|
||||
|
||||
// Get delegate of old xrGetInstanceProcAddr.
|
||||
var xrGetProc = Marshal.GetDelegateForFunctionPointer<OpenXRHelper.xrGetInstanceProcAddrDelegate>(xrGetInstanceProcAddr_prev);
|
||||
XrResult result = xrGetProc(instance, name, out function);
|
||||
if (name == "xrWaitFrame")
|
||||
{
|
||||
WaitFrame_prev = function;
|
||||
m_intercept_xrWaitFrame = intercepted_xrWaitFrame;
|
||||
function = Marshal.GetFunctionPointerForDelegate(m_intercept_xrWaitFrame); ;
|
||||
UnityEngine.Debug.Log("Getting xrWaitFrame func");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
[MonoPInvokeCallback(typeof(OpenXRHelper.xrWaitFrameDelegate))]
|
||||
private static int intercepted_xrWaitFrame(ulong session, ref XrFrameWaitInfo frameWaitInfo, ref XrFrameState frameState)
|
||||
{
|
||||
// Get delegate of prev xrWaitFrame.
|
||||
var xrWaitFrame = Marshal.GetDelegateForFunctionPointer<OpenXRHelper.xrWaitFrameDelegate>(WaitFrame_prev);
|
||||
int res = xrWaitFrame(session, ref frameWaitInfo, ref frameState);
|
||||
m_frameWaitInfo = frameWaitInfo;
|
||||
m_frameState = frameState;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -165,14 +140,6 @@ 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;
|
||||
@@ -376,6 +343,9 @@ 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;
|
||||
|
||||
@@ -711,7 +681,7 @@ namespace VIVE.OpenXR.Hand
|
||||
{
|
||||
XRInputSubsystem subsystem = null;
|
||||
|
||||
SubsystemManager.GetSubsystems(s_InputSubsystems);
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
if (s_InputSubsystems.Count > 0)
|
||||
{
|
||||
subsystem = s_InputSubsystems[0];
|
||||
@@ -825,7 +795,7 @@ namespace VIVE.OpenXR.Hand
|
||||
return true;
|
||||
}
|
||||
|
||||
private int lastUpdateFrameL = -1, lastUpdateFrameR = -1, updateFrame = -1;
|
||||
private int lastUpdateFrameL = -1, lastUpdateFrameR = -1;
|
||||
private void UpdateCallback()
|
||||
{
|
||||
// Only allow updating poses once at BeforeRender & Dynamic per frame.
|
||||
@@ -835,10 +805,6 @@ namespace VIVE.OpenXR.Hand
|
||||
lastUpdateFrameL = -1;
|
||||
lastUpdateFrameR = -1;
|
||||
}
|
||||
if (InputState.currentUpdateType == InputUpdateType.BeforeRender)
|
||||
{
|
||||
updateFrame = Time.frameCount;
|
||||
}
|
||||
}
|
||||
private bool AllowUpdate(bool isLeft)
|
||||
{
|
||||
@@ -866,69 +832,90 @@ namespace VIVE.OpenXR.Hand
|
||||
public bool GetJointLocations(bool isLeft, out XrHandJointLocationEXT[] handJointLocation, out XrTime timestamp)
|
||||
{
|
||||
handJointLocation = isLeft ? jointLocationsL : jointLocationsR;
|
||||
long displayTime = m_predictedDisplayTime;
|
||||
if (Time.frameCount > updateFrame)
|
||||
{
|
||||
displayTime += m_predictedDisplayDuration;
|
||||
}
|
||||
timestamp = displayTime;
|
||||
timestamp = m_frameState.predictedDisplayTime;
|
||||
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: GetCurrentAppSpace(),
|
||||
in_time: displayTime);
|
||||
in_baseSpace: baseSpace,
|
||||
in_time: m_frameState.predictedDisplayTime);
|
||||
|
||||
/// Configures XrHandJointLocationsEXT
|
||||
locations.type = XrStructureType.XR_TYPE_HAND_JOINT_LOCATIONS_EXT;
|
||||
locations.next = IntPtr.Zero;
|
||||
locations.isActive = false;
|
||||
locations.jointCount = (uint)(handJointLocation.Length);
|
||||
locations.jointCount = (uint)(isLeft ? jointLocationsL.Length : jointLocationsR.Length);
|
||||
|
||||
int jointLocationsLength = 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);
|
||||
|
||||
if (handJointLocationsNativeBuffer == null || handJointLocationsNativeBuffer == IntPtr.Zero)
|
||||
long offset = 0;
|
||||
/*if (IntPtr.Size == 4)
|
||||
offset = locations.jointLocations.ToInt32();
|
||||
else
|
||||
offset = locations.jointLocations.ToInt64();
|
||||
|
||||
for (int i = 0; i < jointLocationsLength; i++)
|
||||
{
|
||||
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.");
|
||||
}
|
||||
IntPtr joint_location_ext_ptr = new IntPtr(offset);
|
||||
|
||||
locations.jointLocations = handJointLocationsNativeBuffer;
|
||||
if (isLeft)
|
||||
Marshal.StructureToPtr(jointLocationsL[i], joint_location_ext_ptr, false);
|
||||
else
|
||||
Marshal.StructureToPtr(jointLocationsR[i], joint_location_ext_ptr, false);
|
||||
|
||||
var retX = LocateHandJointsEXT(
|
||||
offset += Marshal.SizeOf(joint_location_ext_type);
|
||||
}*/
|
||||
|
||||
if (LocateHandJointsEXT(
|
||||
handTracker: (isLeft ? leftHandTracker : rightHandTracker),
|
||||
locateInfo: locateInfo,
|
||||
locations: ref locations);
|
||||
|
||||
if (retX == XrResult.XR_SUCCESS)
|
||||
locations: ref locations) == XrResult.XR_SUCCESS)
|
||||
{
|
||||
timestamp = locateInfo.time;
|
||||
|
||||
if (locations.isActive)
|
||||
{
|
||||
MemoryTools.CopyAllFromRawMemory(handJointLocation, handJointLocationsNativeBuffer);
|
||||
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;
|
||||
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(locations.jointLocations);
|
||||
|
||||
OpenXRHelper.Trace.End();
|
||||
return ret;
|
||||
}
|
||||
/// <summary>
|
||||
|
||||
@@ -172,10 +172,10 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// The alpha value of the passthrough in the range [0, 1].
|
||||
/// </summary>
|
||||
public float alpha;
|
||||
public XrPassthroughColorHTC(float in_alpha)
|
||||
public XrPassthroughColorHTC(XrStructureType in_type, IntPtr in_next, float in_alpha)
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_PASSTHROUGH_COLOR_HTC;
|
||||
next = IntPtr.Zero;
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
alpha = in_alpha;
|
||||
}
|
||||
};
|
||||
@@ -201,7 +201,7 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// <summary>
|
||||
/// An array of XrVector3f. The size of the array must be equal to vertexCount.
|
||||
/// </summary>
|
||||
public IntPtr vertices; // XrVector3f
|
||||
public XrVector3f[] vertices;
|
||||
/// <summary>
|
||||
/// The count of indices array in the mesh.
|
||||
/// </summary>
|
||||
@@ -209,7 +209,7 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// <summary>
|
||||
/// An array of triangle indices. The size of the array must be equal to indexCount.
|
||||
/// </summary>
|
||||
public IntPtr indices; // UInt32[]
|
||||
public UInt32[] indices;
|
||||
/// <summary>
|
||||
/// The XrSpace that defines the projected passthrough's base space for transformations.
|
||||
/// </summary>
|
||||
@@ -226,6 +226,21 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// The XrVector3f that defines the scale of the mesh
|
||||
/// </summary>
|
||||
public XrVector3f scale;
|
||||
public XrPassthroughMeshTransformInfoHTC(XrStructureType in_type, IntPtr in_next, UInt32 in_vertexCount,
|
||||
XrVector3f[] in_vertices, UInt32 in_indexCount, UInt32[] in_indices, XrSpace in_baseSpace, XrTime in_time,
|
||||
XrPosef in_pose, XrVector3f in_scale)
|
||||
{
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
vertexCount = in_vertexCount;
|
||||
vertices = in_vertices;
|
||||
indexCount = in_indexCount;
|
||||
indices = in_indices;
|
||||
baseSpace = in_baseSpace;
|
||||
time = in_time;
|
||||
pose = in_pose;
|
||||
scale = in_scale;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -258,12 +273,11 @@ namespace VIVE.OpenXR.Passthrough
|
||||
/// The XrPassthroughColorHTC describing the color information with the alpha value of the passthrough layer.
|
||||
/// </summary>
|
||||
public XrPassthroughColorHTC color;
|
||||
|
||||
public XrCompositionLayerPassthroughHTC(XrCompositionLayerFlags in_layerFlags,
|
||||
public XrCompositionLayerPassthroughHTC(XrStructureType in_type, IntPtr in_next, XrCompositionLayerFlags in_layerFlags,
|
||||
XrSpace in_space, XrPassthroughHTC in_passthrough, XrPassthroughColorHTC in_color)
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC;
|
||||
next = IntPtr.Zero;
|
||||
type = in_type;
|
||||
next = in_next;
|
||||
layerFlags = in_layerFlags;
|
||||
space = in_space;
|
||||
passthrough = in_passthrough;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace UnityEngine.XR.OpenXR.Features.Interactions
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(
|
||||
UiName = "HTC VIVE Tracker Profile",
|
||||
UiName = "HTC Vive Tracker Profile",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.WSA },
|
||||
Company = "MASSIVE",
|
||||
Desc = "Allows for mapping input to the HTC Vive Tracker interaction profile.",
|
||||
|
||||
@@ -208,7 +208,7 @@ namespace VIVE.OpenXR.Tracker
|
||||
/// </summary>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(kDeviceLocalizedName); DEBUG(sb);
|
||||
sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(kDeviceLocalizedName); DEBUG(sb);
|
||||
InputSystem.RegisterLayout(typeof(WristTrackerDevice),
|
||||
kLayoutName,
|
||||
matches: new InputDeviceMatcher()
|
||||
@@ -221,7 +221,7 @@ namespace VIVE.OpenXR.Tracker
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
InputSystem.RemoveLayout(kLayoutName);
|
||||
}
|
||||
|
||||
|
||||
@@ -581,7 +581,7 @@ namespace VIVE.OpenXR.Tracker
|
||||
/// </summary>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(@kProducts); DEBUG(sb);
|
||||
sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(@kProducts); DEBUG(sb);
|
||||
InputSystem.RegisterLayout(typeof(XrTrackerDevice),
|
||||
kLayoutName,
|
||||
matches: new InputDeviceMatcher()
|
||||
@@ -594,7 +594,7 @@ namespace VIVE.OpenXR.Tracker
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
InputSystem.RemoveLayout(kLayoutName);
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 763 B After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 237 KiB After Width: | Height: | Size: 131 B |
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb909cdbffc4cdc40887c53baeb6db76
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: bb909cdbffc4cdc40887c53baeb6db76
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6541b1cca7e65874aa164f80c6f23143
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 6541b1cca7e65874aa164f80c6f23143
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fe62d92a6498bd41994b44944d6b552
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 1fe62d92a6498bd41994b44944d6b552
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4acb42845551fe4b92933e1858633ad
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: f4acb42845551fe4b92933e1858633ad
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
|
Before Width: | Height: | Size: 318 KiB After Width: | Height: | Size: 131 B |
@@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using VIVE.OpenXR.Hand;
|
||||
|
||||
namespace VIVE.OpenXR.Models
|
||||
@@ -70,43 +69,16 @@ namespace VIVE.OpenXR.Models
|
||||
skinMeshRenderer = GetComponentInChildren<SkinnedMeshRenderer>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
Application.onBeforeRender += BeforeRenderUpdate;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Application.onBeforeRender -= BeforeRenderUpdate;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
UpdateHand();
|
||||
}
|
||||
if (skinMeshRenderer == null) { return; }
|
||||
|
||||
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);
|
||||
@@ -142,8 +114,6 @@ namespace VIVE.OpenXR.Models
|
||||
UpdateJointRotation(handJointLocation[(int)XrHandJointEXT.XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT], ref m_Little_Intermediate);
|
||||
UpdateJointRotation(handJointLocation[(int)XrHandJointEXT.XR_HAND_JOINT_LITTLE_DISTAL_EXT], ref m_Little_Distal);
|
||||
UpdateJointRotation(handJointLocation[(int)XrHandJointEXT.XR_HAND_JOINT_LITTLE_TIP_EXT], ref m_Little_Tip);
|
||||
Profiler.EndSample();
|
||||
Profiler.EndSample();
|
||||
}
|
||||
|
||||
private void UpdateJointPosition(XrHandJointLocationEXT pose, ref GameObject joint)
|
||||
|
||||
@@ -127,9 +127,6 @@ 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,
|
||||
@@ -547,24 +544,6 @@ namespace VIVE.OpenXR
|
||||
}
|
||||
}
|
||||
|
||||
public struct XrBaseStructure
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
public struct XrBaseOutStructure
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
public struct XrBaseInStructure
|
||||
{
|
||||
public XrStructureType type;
|
||||
public IntPtr next;
|
||||
}
|
||||
|
||||
#region 2.18. Coordinate System
|
||||
/// <summary>
|
||||
/// A two-dimensional vector is defined by the XrVector2f structure.
|
||||
@@ -3264,7 +3243,7 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
if (funcPtr != IntPtr.Zero)
|
||||
{
|
||||
Log.D("Get function pointer of " + name);
|
||||
Debug.Log("Get function pointer of " + name);
|
||||
func = Marshal.GetDelegateForFunctionPointer<Type>(funcPtr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
//using VIVE.OpenXR.Utils;
|
||||
using VIVE.OpenXR.Hand;
|
||||
@@ -60,7 +59,20 @@ namespace VIVE.OpenXR
|
||||
|
||||
if (m_JointLocations.isActive == 1)
|
||||
{
|
||||
MemoryTools.CopyFromRawMemory(handJointLocation, m_JointLocations.jointLocations, (int)m_JointLocations.jointCount);
|
||||
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);
|
||||
}
|
||||
|
||||
handJointLocation = s_JointLocation[isLeft];
|
||||
return true;
|
||||
|
||||
@@ -86,8 +86,13 @@ namespace VIVE.OpenXR
|
||||
{
|
||||
if (ASSERT_FEATURE())
|
||||
{
|
||||
if (feature.GetJointLocations(isLeft, out handJointLocation, out timestamp))
|
||||
if (feature.GetJointLocations(isLeft, out XrHandJointLocationEXT[] array, out timestamp))
|
||||
{
|
||||
if (l_HandJointLocation == null) { l_HandJointLocation = new List<XrHandJointLocationEXT>(); }
|
||||
l_HandJointLocation.Clear();
|
||||
for (int i = 0; i < array.Length; i++) { l_HandJointLocation.Add(array[i]); }
|
||||
|
||||
handJointLocation = l_HandJointLocation.ToArray();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,27 @@ namespace VIVE.OpenXR
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void GetOriginEndFrameLayerList(out List<IntPtr> layers)
|
||||
{
|
||||
ASSERT_FEATURE();
|
||||
layers = new List<IntPtr>();
|
||||
#if UNITY_STANDALONE
|
||||
if (feature)
|
||||
feature.GetOriginEndFrameLayerList(out layers);
|
||||
|
||||
else
|
||||
layers = new List<IntPtr>();
|
||||
#endif
|
||||
}
|
||||
public override void SubmitLayers(List<IntPtr> layers)
|
||||
{
|
||||
ASSERT_FEATURE();
|
||||
#if UNITY_STANDALONE
|
||||
if (feature)
|
||||
feature.SubmitLayers(layers);
|
||||
#endif
|
||||
}
|
||||
|
||||
public override XrSpace GetTrackingSpace()
|
||||
{
|
||||
ASSERT_FEATURE();
|
||||
@@ -56,8 +77,10 @@ namespace VIVE.OpenXR
|
||||
public override XrFrameState GetFrameState()
|
||||
{
|
||||
ASSERT_FEATURE();
|
||||
#if UNITY_STANDALONE
|
||||
if (feature)
|
||||
return feature.GetFrameState();
|
||||
#endif
|
||||
return new XrFrameState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
@@ -106,12 +107,6 @@ 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;
|
||||
@@ -120,18 +115,15 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
public HandEvent handEvent;
|
||||
public InputAction inputAction { get; private set; }
|
||||
|
||||
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 = "")
|
||||
public InputActionMapping(string bindingPath, DeviceCategory device,
|
||||
PoseState poseState = PoseState.None, ButtonEvent buttonEvent = ButtonEvent.None, HandEvent handEvent = HandEvent.None)
|
||||
{
|
||||
inputAction = new InputAction(binding: in_BindingPath, expectedControlType: in_Type);
|
||||
inputAction = new InputAction(binding: bindingPath);
|
||||
inputAction.Enable();
|
||||
this.device = in_Device;
|
||||
this.poseState = in_PoseState;
|
||||
this.buttonEvent = in_ButtonEvent;
|
||||
this.handEvent = in_HandEvent;
|
||||
this.device = device;
|
||||
this.poseState = poseState;
|
||||
this.buttonEvent = buttonEvent;
|
||||
this.handEvent = handEvent;
|
||||
}
|
||||
|
||||
public static InputActionMapping Identify => new InputActionMapping("", DeviceCategory.None);
|
||||
@@ -158,11 +150,11 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
public Vector3 position { get; private set; }
|
||||
public Quaternion rotation { get; private set; }
|
||||
|
||||
public JointData(bool in_IsValid, Vector3 in_Position, Quaternion in_Rotation)
|
||||
public JointData(bool isValid, Vector3 position, Quaternion rotation)
|
||||
{
|
||||
this.isValid = in_IsValid;
|
||||
this.position = in_Position;
|
||||
this.rotation = in_Rotation;
|
||||
this.isValid = isValid;
|
||||
this.position = position;
|
||||
this.rotation = rotation;
|
||||
}
|
||||
|
||||
public static JointData Identify => new JointData(false, Vector3.zero, Quaternion.identity);
|
||||
@@ -172,44 +164,18 @@ 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[] in_Joints)
|
||||
public HandData(JointData[] joints)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
this.joints = joints;
|
||||
isTracked = !this.joints.Any(x => x.isValid == false);
|
||||
updateTime = Time.frameCount;
|
||||
}
|
||||
|
||||
public void Update(JointData[] in_Joints)
|
||||
public void Update(JointData[] joints)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
this.joints = joints;
|
||||
isTracked = !this.joints.Any(x => x.isValid == false);
|
||||
updateTime = Time.frameCount;
|
||||
}
|
||||
|
||||
@@ -227,16 +193,12 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
}
|
||||
|
||||
private static bool m_IsInitInputActions = false;
|
||||
private static bool m_IsSupportViveHand = false;
|
||||
private static bool m_IsSupportXrHand = false;
|
||||
private static List<InputActionMapping> s_InputActions = new List<InputActionMapping>();
|
||||
private static HandData m_LeftHand = HandData.Identify;
|
||||
private static HandData m_RightHand = HandData.Identify;
|
||||
private static JointData[] m_JointBuffer = new JointData[(int)HandJointType.Count];
|
||||
private static bool isInitInputActions = false;
|
||||
private static List<InputActionMapping> inputActions = new List<InputActionMapping>();
|
||||
private static HandData leftHand = HandData.Identify;
|
||||
private static HandData rightHand = HandData.Identify;
|
||||
#if UNITY_XR_HANDS
|
||||
private static XRHandSubsystem m_HandSubsystem = null;
|
||||
private static List<XRHandSubsystem> m_HandSubsystems = new List<XRHandSubsystem>();
|
||||
private static XRHandSubsystem handSubsystem = null;
|
||||
#endif
|
||||
|
||||
#region Public Interface
|
||||
@@ -259,16 +221,18 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetInputActionMapping(device, poseState, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == device && x.poseState == poseState);
|
||||
if (inputActionMapping == null) { return false; }
|
||||
|
||||
try
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<float>() > 0;
|
||||
return true;
|
||||
}
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<float>() > 0;
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,16 +255,18 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetInputActionMapping(device, poseState, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == device && x.poseState == poseState);
|
||||
if (inputActionMapping == null) { return false; }
|
||||
|
||||
try
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kVector3Type)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<Vector3>();
|
||||
return true;
|
||||
}
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<Vector3>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,16 +289,18 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetInputActionMapping(device, poseState, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == device && x.poseState == poseState);
|
||||
if (inputActionMapping == null) { return false; }
|
||||
|
||||
try
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kQuaternionType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<Quaternion>();
|
||||
return true;
|
||||
}
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<Quaternion>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,14 +315,11 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = false;
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.WasPressedThisFrame();
|
||||
return true;
|
||||
}
|
||||
eventResult = inputActionMapping.inputAction.WasPressedThisFrame();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -370,14 +335,11 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = false;
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.WasReleasedThisFrame();
|
||||
return true;
|
||||
}
|
||||
eventResult = inputActionMapping.inputAction.WasReleasedThisFrame();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -393,16 +355,21 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = false;
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
try
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<float>() == 1;
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -416,16 +383,21 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = 0f;
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
try
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<float>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -439,14 +411,18 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = Vector2.zero;
|
||||
if (GetInputActionMapping(GetController(handedness), buttonEvent, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetController(handedness) && x.buttonEvent == buttonEvent);
|
||||
if (inputActionMapping != null)
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kVector2Type)
|
||||
try
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<Vector2>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -462,14 +438,18 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = 0;
|
||||
if (GetInputActionMapping(GetHand(handedness), handEvent, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetHand(handedness) && x.handEvent == handEvent);
|
||||
if (inputActionMapping != null)
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kFloatType)
|
||||
try
|
||||
{
|
||||
eventResult = inputActionMapping.inputAction.ReadValue<float>();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -485,19 +465,19 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
{
|
||||
CheckInitialize();
|
||||
eventResult = Pose.identity;
|
||||
if (GetInputActionMapping(GetHand(handedness), handEvent, out InputActionMapping inputActionMapping))
|
||||
InputActionMapping inputActionMapping = inputActions.FirstOrDefault(x => x.device == GetHand(handedness) && x.handEvent == handEvent);
|
||||
if (inputActionMapping != null)
|
||||
{
|
||||
var inputAction = inputActionMapping.inputAction;
|
||||
if (inputAction != null && inputAction.enabled && inputAction.expectedControlType == kPoseType)
|
||||
try
|
||||
{
|
||||
# if USE_INPUT_SYSTEM_POSE_CONTROL
|
||||
UnityEngine.InputSystem.XR.PoseState pose = inputActionMapping.inputAction.ReadValue<UnityEngine.InputSystem.XR.PoseState>();
|
||||
#else
|
||||
UnityEngine.XR.OpenXR.Input.Pose pose = inputActionMapping.inputAction.ReadValue<UnityEngine.XR.OpenXR.Input.Pose>();
|
||||
#endif
|
||||
eventResult = new Pose(pose.position, pose.rotation);
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -515,13 +495,13 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
jointPose = Pose.identity;
|
||||
if (handedness == Handedness.Left)
|
||||
{
|
||||
jointPose = new Pose(m_LeftHand.joints[(int)joint].position, m_LeftHand.joints[(int)joint].rotation);
|
||||
return m_LeftHand.joints[(int)joint].isValid;
|
||||
jointPose = new Pose(leftHand.joints[(int)joint].position, leftHand.joints[(int)joint].rotation);
|
||||
return leftHand.joints[(int)joint].isValid;
|
||||
}
|
||||
else
|
||||
{
|
||||
jointPose = new Pose(m_RightHand.joints[(int)joint].position, m_RightHand.joints[(int)joint].rotation);
|
||||
return m_RightHand.joints[(int)joint].isValid;
|
||||
jointPose = new Pose(rightHand.joints[(int)joint].position, rightHand.joints[(int)joint].rotation);
|
||||
return rightHand.joints[(int)joint].isValid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,27 +513,24 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
public static bool IsHandTracked(Handedness handedness)
|
||||
{
|
||||
CheckHandUpdated();
|
||||
return handedness == Handedness.Left ? m_LeftHand.isTracked : m_RightHand.isTracked;
|
||||
return handedness == Handedness.Left ? leftHand.isTracked : rightHand.isTracked;
|
||||
}
|
||||
|
||||
public static bool IsHandValidate()
|
||||
{
|
||||
if (!m_IsInitInputActions)
|
||||
ViveHandTracking viveHand = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
if (viveHand)
|
||||
{
|
||||
ViveHandTracking viveHand = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
if (viveHand)
|
||||
{
|
||||
m_IsSupportViveHand = true;
|
||||
}
|
||||
#if UNITY_XR_HANDS
|
||||
HandTracking xrHand = OpenXRSettings.Instance.GetFeature<HandTracking>();
|
||||
if (xrHand)
|
||||
{
|
||||
m_IsSupportXrHand = true;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return m_IsSupportViveHand || m_IsSupportXrHand;
|
||||
#if UNITY_XR_HANDS
|
||||
HandTracking xrHand = OpenXRSettings.Instance.GetFeature<HandTracking>();
|
||||
if (xrHand)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -561,233 +538,192 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
private static bool CheckInitialize()
|
||||
{
|
||||
if (!m_IsInitInputActions)
|
||||
if (!isInitInputActions)
|
||||
{
|
||||
Initialized();
|
||||
IsHandValidate();
|
||||
m_IsInitInputActions = true;
|
||||
isInitInputActions = true;
|
||||
}
|
||||
return m_IsInitInputActions;
|
||||
return isInitInputActions;
|
||||
}
|
||||
|
||||
private static void Initialized()
|
||||
{
|
||||
#region Head
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/isTracked", DeviceCategory.HMD, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyePosition", DeviceCategory.HMD, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeRotation", DeviceCategory.HMD, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeVelocity", DeviceCategory.HMD, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAngularVelocity", DeviceCategory.HMD, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAcceleration", DeviceCategory.HMD, in_PoseState: PoseState.Acceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAngularAcceleration", DeviceCategory.HMD, in_PoseState: PoseState.AngularAcceleration, in_Type: kVector3Type));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/isTracked", DeviceCategory.HMD, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyePosition", DeviceCategory.HMD, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeRotation", DeviceCategory.HMD, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeVelocity", DeviceCategory.HMD, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAngularVelocity", DeviceCategory.HMD, poseState: PoseState.AngularVelocity));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAcceleration", DeviceCategory.HMD, poseState: PoseState.Acceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRHMD>/centerEyeAngularAcceleration", DeviceCategory.HMD, poseState: PoseState.AngularAcceleration));
|
||||
#endregion
|
||||
#region Eye
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/isTracked", DeviceCategory.CenterEye, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/position", DeviceCategory.CenterEye, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/rotation", DeviceCategory.CenterEye, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/velocity", DeviceCategory.CenterEye, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<EyeGaze>/pose/angularVelocity", DeviceCategory.CenterEye, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/isTracked", DeviceCategory.CenterEye, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/position", DeviceCategory.CenterEye, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/rotation", DeviceCategory.CenterEye, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/velocity", DeviceCategory.CenterEye, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<EyeGaze>/pose/angularVelocity", DeviceCategory.CenterEye, poseState: PoseState.AngularVelocity));
|
||||
#endregion
|
||||
#region Controller
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/isTracked", DeviceCategory.LeftController, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/pointerPosition", DeviceCategory.LeftController, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/pointerRotation", DeviceCategory.LeftController, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceVelocity", DeviceCategory.LeftController, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAngularVelocity", DeviceCategory.LeftController, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAcceleration", DeviceCategory.LeftController, in_PoseState: PoseState.Acceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAngularAcceleration", DeviceCategory.LeftController, in_PoseState: PoseState.AngularAcceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{grip}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.GripValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{gripButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.GripPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{trigger}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.TriggerValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/triggerTouched", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.TriggerTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{triggerButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.TriggerPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxis}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Primary2DAxisValue, in_Type: kVector2Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxisTouch}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Primary2DAxisTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxisClick}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Primary2DAxisPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxis}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Secondary2DAxisValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxisTouch}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Secondary2DAxisTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxisClick}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Secondary2DAxisPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primaryButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.PrimaryButton, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondaryButton}", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.SecondaryButton, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/parkingTouched", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.ParkingTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{LeftHand}/menu", DeviceCategory.LeftController, in_ButtonEvent: ButtonEvent.Menu, in_Type: kFloatType));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/isTracked", DeviceCategory.LeftController, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/pointerPosition", DeviceCategory.LeftController, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/pointerRotation", DeviceCategory.LeftController, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceVelocity", DeviceCategory.LeftController, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAngularVelocity", DeviceCategory.LeftController, poseState: PoseState.AngularVelocity));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAcceleration", DeviceCategory.LeftController, poseState: PoseState.Acceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/deviceAngularAcceleration", DeviceCategory.LeftController, poseState: PoseState.AngularAcceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{grip}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.GripValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{gripButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.GripPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{trigger}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.TriggerValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/triggerTouched", DeviceCategory.LeftController, buttonEvent: ButtonEvent.TriggerTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{triggerButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.TriggerPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxis}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Primary2DAxisValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxisTouch}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Primary2DAxisTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primary2DAxisClick}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Primary2DAxisPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxis}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Secondary2DAxisValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxisTouch}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Secondary2DAxisTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondary2DAxisClick}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Secondary2DAxisPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{primaryButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.PrimaryButton));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/{secondaryButton}", DeviceCategory.LeftController, buttonEvent: ButtonEvent.SecondaryButton));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/parkingTouched", DeviceCategory.LeftController, buttonEvent: ButtonEvent.ParkingTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{LeftHand}/menu", DeviceCategory.LeftController, buttonEvent: ButtonEvent.Menu));
|
||||
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/isTracked", DeviceCategory.RightController, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/pointerPosition", DeviceCategory.RightController, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/pointerRotation", DeviceCategory.RightController, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceVelocity", DeviceCategory.RightController, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAngularVelocity", DeviceCategory.RightController, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAcceleration", DeviceCategory.RightController, in_PoseState: PoseState.Acceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAngularAcceleration", DeviceCategory.RightController, in_PoseState: PoseState.AngularAcceleration, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{grip}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.GripValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{gripButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.GripPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{trigger}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.TriggerValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/triggerTouched", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.TriggerTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{triggerButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.TriggerPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxis}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Primary2DAxisValue, in_Type: kVector2Type));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxisTouch}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Primary2DAxisTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxisClick}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Primary2DAxisPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxis}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Secondary2DAxisValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxisTouch}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Secondary2DAxisTouch, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxisClick}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.Secondary2DAxisPress, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primaryButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.PrimaryButton, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondaryButton}", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.SecondaryButton, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<XRController>{RightHand}/parkingTouched", DeviceCategory.RightController, in_ButtonEvent: ButtonEvent.ParkingTouch, in_Type: kFloatType));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/isTracked", DeviceCategory.RightController, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/pointerPosition", DeviceCategory.RightController, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/pointerRotation", DeviceCategory.RightController, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceVelocity", DeviceCategory.RightController, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAngularVelocity", DeviceCategory.RightController, poseState: PoseState.AngularVelocity));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAcceleration", DeviceCategory.RightController, poseState: PoseState.Acceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/deviceAngularAcceleration", DeviceCategory.RightController, poseState: PoseState.AngularAcceleration));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{grip}", DeviceCategory.RightController, buttonEvent: ButtonEvent.GripValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{gripButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.GripPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{trigger}", DeviceCategory.RightController, buttonEvent: ButtonEvent.TriggerValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/triggerTouched", DeviceCategory.RightController, buttonEvent: ButtonEvent.TriggerTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{triggerButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.TriggerPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxis}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Primary2DAxisValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxisTouch}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Primary2DAxisTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primary2DAxisClick}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Primary2DAxisPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxis}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Secondary2DAxisValue));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxisTouch}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Secondary2DAxisTouch));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondary2DAxisClick}", DeviceCategory.RightController, buttonEvent: ButtonEvent.Secondary2DAxisPress));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{primaryButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.PrimaryButton));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/{secondaryButton}", DeviceCategory.RightController, buttonEvent: ButtonEvent.SecondaryButton));
|
||||
inputActions.Add(new InputActionMapping("<XRController>{RightHand}/parkingTouched", DeviceCategory.RightController, buttonEvent: ButtonEvent.ParkingTouch));
|
||||
#endregion
|
||||
#region Hand
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/selectValue", DeviceCategory.LeftHand, in_HandEvent: HandEvent.PinchValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/pointerPose", DeviceCategory.LeftHand, in_HandEvent: HandEvent.PinchPose, in_Type: kPoseType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/gripValue", DeviceCategory.LeftHand, in_HandEvent: HandEvent.GraspValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/devicePose", DeviceCategory.LeftHand, in_HandEvent: HandEvent.GraspPose, in_Type: kPoseType));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/selectValue", DeviceCategory.LeftHand, handEvent: HandEvent.PinchValue));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/pointerPose", DeviceCategory.LeftHand, handEvent: HandEvent.PinchPose));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/gripValue", DeviceCategory.LeftHand, handEvent: HandEvent.GraspValue));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{LeftHand}/devicePose", DeviceCategory.LeftHand, handEvent: HandEvent.GraspPose));
|
||||
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/selectValue", DeviceCategory.RightHand, in_HandEvent: HandEvent.PinchValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/pointerPose", DeviceCategory.RightHand, in_HandEvent: HandEvent.PinchPose, in_Type: kPoseType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/gripValue", DeviceCategory.RightHand, in_HandEvent: HandEvent.GraspValue, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/devicePose", DeviceCategory.RightHand, in_HandEvent: HandEvent.GraspPose, in_Type: kPoseType));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/selectValue", DeviceCategory.RightHand, handEvent: HandEvent.PinchValue));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/pointerPose", DeviceCategory.RightHand, handEvent: HandEvent.PinchPose));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/gripValue", DeviceCategory.RightHand, handEvent: HandEvent.GraspValue));
|
||||
inputActions.Add(new InputActionMapping("<ViveHandInteraction>{RightHand}/devicePose", DeviceCategory.RightHand, handEvent: HandEvent.GraspPose));
|
||||
#endregion
|
||||
#region Tracker
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/isTracked", DeviceCategory.Tracker0, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePosition", DeviceCategory.Tracker0, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/deviceRotation", DeviceCategory.Tracker0, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/velocity", DeviceCategory.Tracker0, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/angularVelocity", DeviceCategory.Tracker0, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/isTracked", DeviceCategory.Tracker0, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePosition", DeviceCategory.Tracker0, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/deviceRotation", DeviceCategory.Tracker0, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/velocity", DeviceCategory.Tracker0, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 0}/devicePose/angularVelocity", DeviceCategory.Tracker0, poseState: PoseState.AngularVelocity));
|
||||
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/isTracked", DeviceCategory.Tracker1, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePosition", DeviceCategory.Tracker1, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/deviceRotation", DeviceCategory.Tracker1, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/velocity", DeviceCategory.Tracker1, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/angularVelocity", DeviceCategory.Tracker1, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/isTracked", DeviceCategory.Tracker1, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePosition", DeviceCategory.Tracker1, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/deviceRotation", DeviceCategory.Tracker1, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/velocity", DeviceCategory.Tracker1, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 1}/devicePose/angularVelocity", DeviceCategory.Tracker1, poseState: PoseState.AngularVelocity));
|
||||
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/isTracked", DeviceCategory.Tracker2, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePosition", DeviceCategory.Tracker2, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/deviceRotation", DeviceCategory.Tracker2, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/velocity", DeviceCategory.Tracker2, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/angularVelocity", DeviceCategory.Tracker2, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/isTracked", DeviceCategory.Tracker2, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePosition", DeviceCategory.Tracker2, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/deviceRotation", DeviceCategory.Tracker2, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/velocity", DeviceCategory.Tracker2, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 2}/devicePose/angularVelocity", DeviceCategory.Tracker2, poseState: PoseState.AngularVelocity));
|
||||
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/isTracked", DeviceCategory.Tracker3, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePosition", DeviceCategory.Tracker3, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/deviceRotation", DeviceCategory.Tracker3, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/velocity", DeviceCategory.Tracker3, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/angularVelocity", DeviceCategory.Tracker3, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/isTracked", DeviceCategory.Tracker3, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePosition", DeviceCategory.Tracker3, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/deviceRotation", DeviceCategory.Tracker3, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/velocity", DeviceCategory.Tracker3, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 3}/devicePose/angularVelocity", DeviceCategory.Tracker3, poseState: PoseState.AngularVelocity));
|
||||
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/isTracked", DeviceCategory.Tracker4, in_PoseState: PoseState.IsTracked, in_Type: kFloatType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePosition", DeviceCategory.Tracker4, in_PoseState: PoseState.Position, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/deviceRotation", DeviceCategory.Tracker4, in_PoseState: PoseState.Rotation, in_Type: kQuaternionType));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/velocity", DeviceCategory.Tracker4, in_PoseState: PoseState.Velocity, in_Type: kVector3Type));
|
||||
s_InputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/angularVelocity", DeviceCategory.Tracker4, in_PoseState: PoseState.AngularVelocity, in_Type: kVector3Type));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/isTracked", DeviceCategory.Tracker4, poseState: PoseState.IsTracked));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePosition", DeviceCategory.Tracker4, poseState: PoseState.Position));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/deviceRotation", DeviceCategory.Tracker4, poseState: PoseState.Rotation));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/velocity", DeviceCategory.Tracker4, poseState: PoseState.Velocity));
|
||||
inputActions.Add(new InputActionMapping("<ViveXRTracker>{Ultimate Tracker 4}/devicePose/angularVelocity", DeviceCategory.Tracker4, poseState: PoseState.AngularVelocity));
|
||||
#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()
|
||||
{
|
||||
int frameCount = Time.frameCount;
|
||||
if (frameCount > m_LeftHand.updateTime ||
|
||||
frameCount > m_RightHand.updateTime)
|
||||
if (Time.frameCount > leftHand.updateTime ||
|
||||
Time.frameCount > rightHand.updateTime)
|
||||
{
|
||||
#if UNITY_XR_HANDS
|
||||
if (m_IsSupportViveHand || m_IsSupportXrHand)
|
||||
ViveHandTracking viveHand = OpenXRSettings.Instance.GetFeature<ViveHandTracking>();
|
||||
if (viveHand)
|
||||
{
|
||||
if (m_HandSubsystem == null || !m_HandSubsystem.running)
|
||||
UpdateViveHand(true, viveHand);
|
||||
UpdateViveHand(false, viveHand);
|
||||
}
|
||||
|
||||
#if UNITY_XR_HANDS
|
||||
HandTracking xrHand = OpenXRSettings.Instance.GetFeature<HandTracking>();
|
||||
if (xrHand)
|
||||
{
|
||||
if (handSubsystem == null || !handSubsystem.running)
|
||||
{
|
||||
if (m_HandSubsystem != null)
|
||||
if (handSubsystem != null && !handSubsystem.running)
|
||||
{
|
||||
m_HandSubsystem.updatedHands -= OnUpdatedHands;
|
||||
m_HandSubsystem = null;
|
||||
handSubsystem.updatedHands -= OnUpdatedHands;
|
||||
handSubsystem = null;
|
||||
}
|
||||
|
||||
m_HandSubsystems.Clear();
|
||||
SubsystemManager.GetSubsystems(m_HandSubsystems);
|
||||
for (var i = 0; i < m_HandSubsystems.Count; ++i)
|
||||
var handSubsystems = new List<XRHandSubsystem>();
|
||||
SubsystemManager.GetSubsystems(handSubsystems);
|
||||
for (var i = 0; i < handSubsystems.Count; ++i)
|
||||
{
|
||||
var xrHand = m_HandSubsystems[i];
|
||||
if (xrHand.running)
|
||||
var xrHnad = handSubsystems[i];
|
||||
if (xrHnad.running)
|
||||
{
|
||||
m_HandSubsystem = xrHand;
|
||||
m_HandSubsystem.updatedHands += OnUpdatedHands;
|
||||
handSubsystem = xrHnad;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (handSubsystem != null && handSubsystem.running)
|
||||
{
|
||||
handSubsystem.updatedHands += OnUpdatedHands;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (m_IsSupportViveHand)
|
||||
{
|
||||
UpdateViveHand(true);
|
||||
UpdateViveHand(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateViveHand(bool isLeft)
|
||||
private static void UpdateViveHand(bool isLeft, ViveHandTracking viveHand)
|
||||
{
|
||||
bool isUpdated = XR_EXT_hand_tracking.Interop.GetJointLocations(isLeft, out XrHandJointLocationEXT[] viveJoints);
|
||||
for (int i = 0; i < m_JointBuffer.Length; i++)
|
||||
bool isUpdated = viveHand.GetJointLocations(isLeft, out XrHandJointLocationEXT[] viveJoints);
|
||||
JointData[] joints = new JointData[viveJoints.Length];
|
||||
for (int i = 0; i < joints.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();
|
||||
m_JointBuffer[i] = new JointData(isValid, position, rotation);
|
||||
joints[i] = new JointData(isValid, position, rotation);
|
||||
}
|
||||
if (isLeft)
|
||||
{
|
||||
m_LeftHand.Update(m_JointBuffer);
|
||||
leftHand.Update(joints);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RightHand.Update(m_JointBuffer);
|
||||
rightHand.Update(joints);
|
||||
}
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
@@ -796,48 +732,42 @@ namespace VIVE.OpenXR.Toolkits.Common
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateXRHand(bool isLeft, XRHandSubsystem xrHand, bool isUpdated)
|
||||
private static void UpdateXRHand(bool isLeft, XRHandSubsystem xrHnad, bool isUpdated)
|
||||
{
|
||||
for (int i = 0; i < m_JointBuffer.Length; i++)
|
||||
JointData[] joints = new JointData[(int)HandJointType.Count];
|
||||
for (int i = 0; i < joints.Length; i++)
|
||||
{
|
||||
XRHandJointID jointId = JointTypeToXRId(i);
|
||||
XRHandJoint joint = (isLeft ? xrHand.leftHand : xrHand.rightHand).GetJoint(jointId);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
||||
@@ -5,7 +5,8 @@ using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using VIVE.OpenXR;
|
||||
|
||||
namespace VIVE.OpenXR.Passthrough
|
||||
{
|
||||
@@ -26,7 +27,13 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Dictionary<XrPassthroughHTC, PassthroughLayer> layersDict = new Dictionary<XrPassthroughHTC, PassthroughLayer>();
|
||||
#if UNITY_STANDALONE
|
||||
private static Dictionary<XrPassthroughHTC, XrCompositionLayerPassthroughHTC> passthrough2Layer = new Dictionary<XrPassthroughHTC, XrCompositionLayerPassthroughHTC>();
|
||||
private static Dictionary<XrPassthroughHTC, IntPtr> passthrough2LayerPtr = new Dictionary<XrPassthroughHTC, IntPtr>();
|
||||
private static Dictionary<XrPassthroughHTC, bool> passthrough2IsUnderLay= new Dictionary<XrPassthroughHTC, bool>();
|
||||
private static Dictionary<XrPassthroughHTC, XrPassthroughMeshTransformInfoHTC> passthrough2meshTransform = new Dictionary<XrPassthroughHTC, XrPassthroughMeshTransformInfoHTC>();
|
||||
private static Dictionary<XrPassthroughHTC, IntPtr> passthrough2meshTransformInfoPtr = new Dictionary<XrPassthroughHTC, IntPtr>();
|
||||
#endif
|
||||
|
||||
#region Public APIs
|
||||
/// <summary>
|
||||
@@ -51,32 +58,42 @@ 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)
|
||||
{
|
||||
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);
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
#endif
|
||||
if (res == XrResult.XR_SUCCESS)
|
||||
{
|
||||
SetPassthroughAlpha(passthrough, alpha);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -121,34 +138,54 @@ 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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
#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);
|
||||
@@ -182,30 +219,54 @@ 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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
#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);
|
||||
@@ -214,18 +275,43 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return res;
|
||||
}
|
||||
|
||||
private static void SubmitLayer()
|
||||
{
|
||||
passthroughFeature.SubmitLayers(layersDict.Values.ToList());
|
||||
}
|
||||
#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<IntPtr> layerList);//GetOriginEndFrameLayers
|
||||
layerListCount = layerList.Count;
|
||||
foreach (var passthrough in passthrough2IsUnderLay.Keys)
|
||||
{
|
||||
//Get and submit layer list
|
||||
if (layerListCount != 0)
|
||||
{
|
||||
Marshal.StructureToPtr(passthrough2Layer[passthrough], passthrough2LayerPtr[passthrough], false);
|
||||
if (passthrough2IsUnderLay[passthrough])
|
||||
layerList.Insert(0, passthrough2LayerPtr[passthrough]);
|
||||
else
|
||||
layerList.Insert(1, passthrough2LayerPtr[passthrough]);
|
||||
}
|
||||
}
|
||||
if(layerListCount != 0)
|
||||
XR_HTC_passthrough.Interop.SubmitLayers(layerList);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// To Destroying a passthrough.
|
||||
/// You should call this function when the <see cref="VivePassthrough.OnPassthroughSessionDestroyDelegate">delegate</see> is invoked.
|
||||
/// </summary>
|
||||
/// <param name="passthrough">The created <see cref="XrPassthroughHTC"/></param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public static XrResult DestroyPassthrough(XrPassthroughHTC passthrough)
|
||||
/// <summary>
|
||||
/// To Destroying a passthrough.
|
||||
/// You should call this function when the <see cref="VivePassthrough.OnPassthroughSessionDestroyDelegate">delegate</see> is invoked.
|
||||
/// </summary>
|
||||
/// <param name="passthrough">The created <see cref="XrPassthroughHTC"/></param>
|
||||
/// <returns>XR_SUCCESS for success.</returns>
|
||||
public static XrResult DestroyPassthrough(XrPassthroughHTC passthrough)
|
||||
{
|
||||
XrResult res = XrResult.XR_ERROR_RUNTIME_FAILURE;
|
||||
|
||||
@@ -240,17 +326,23 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return res;
|
||||
}
|
||||
|
||||
if (layersDict.ContainsKey(passthrough))
|
||||
{
|
||||
XR_HTC_passthrough.xrDestroyPassthroughHTC(passthrough);
|
||||
var layer = layersDict[passthrough];
|
||||
layer.Dispose();
|
||||
layersDict.Remove(passthrough);
|
||||
}
|
||||
|
||||
#if UNITY_STANDALONE
|
||||
XrPassthroughHTC pt = passthrough2Layer[passthrough].passthrough;
|
||||
XR_HTC_passthrough.xrDestroyPassthroughHTC(pt);
|
||||
passthrough2IsUnderLay.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;
|
||||
}
|
||||
|
||||
@@ -276,18 +368,36 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (layersDict.ContainsKey(passthrough))
|
||||
#if UNITY_ANDROID
|
||||
if (autoClamp)
|
||||
{
|
||||
var layer = layersDict[passthrough];
|
||||
var xrLayer = layer.GetLayer();
|
||||
xrLayer.color.alpha = alpha;
|
||||
layer.SetLayer(xrLayer);
|
||||
|
||||
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;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -315,18 +425,45 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
XrVector3f[] vertexBufferXrVector = new XrVector3f[vertexBuffer.Length];
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
layer.SetMeshData(ref xrMesh, vertexBuffer, indexBuffer, convertFromUnityToOpenXR);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -371,22 +508,29 @@ namespace VIVE.OpenXR.Passthrough
|
||||
|
||||
XrVector3f meshXrScale = OpenXRHelper.ToOpenXRVector(meshScale, false);
|
||||
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
#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
|
||||
|
||||
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;
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransform(passthrough, passthroughFeature.GetXrSpaceFromSpaceType(spaceType), meshXrPose, meshXrScale);
|
||||
DEBUG("SetProjectedPassthroughMeshTransform() SetMeshTransform result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -406,18 +550,22 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
#if UNITY_STANDALONE
|
||||
if (passthrough2IsUnderLay.ContainsKey(passthrough))
|
||||
{
|
||||
passthrough2IsUnderLay[passthrough] = layerType == CompositionLayer.LayerType.Underlay ? true : false;
|
||||
SubmitLayer();
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
#endif
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
layer.LayerType = layerType;
|
||||
layer.Depth = (int)compositionDepth;
|
||||
|
||||
SubmitLayer();
|
||||
return true;
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetLayerType(passthrough, layerType, compositionDepth);
|
||||
DEBUG("SetPassthroughLayerType() SetLayerType result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -436,18 +584,28 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
ERROR("Passthrough layer not found.");
|
||||
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
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
xrMesh.baseSpace = passthroughFeature.GetXrSpaceFromSpaceType(spaceType);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransformSpace(passthrough, passthroughFeature.GetXrSpaceFromSpaceType(spaceType));
|
||||
DEBUG("SetProjectedPassthroughSpaceType() SetMeshTransformSpace result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -481,18 +639,30 @@ namespace VIVE.OpenXR.Passthrough
|
||||
trackingSpaceMeshPosition = trackingSpaceLayerPoseTRS.GetColumn(3); //4th Column of TRS Matrix is the position
|
||||
}
|
||||
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
#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
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
xrMesh.pose.position = OpenXRHelper.ToOpenXRVector(trackingSpaceMeshPosition, convertFromUnityToOpenXR);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransformPosition(passthrough, OpenXRHelper.ToOpenXRVector(trackingSpaceMeshPosition, convertFromUnityToOpenXR));
|
||||
DEBUG("SetProjectedPassthroughMeshPosition() SetMeshTransformPosition result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -526,18 +696,30 @@ namespace VIVE.OpenXR.Passthrough
|
||||
trackingSpaceMeshRotation = Quaternion.LookRotation(trackingSpaceLayerPoseTRS.GetColumn(2), trackingSpaceLayerPoseTRS.GetColumn(1));
|
||||
}
|
||||
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
ERROR("Passthrough layer not found.");
|
||||
return ret;
|
||||
}
|
||||
#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
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
xrMesh.pose.orientation = OpenXRHelper.ToOpenXRQuaternion(trackingSpaceMeshRotation, convertFromUnityToOpenXR);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransformOrientation(passthrough, OpenXRHelper.ToOpenXRQuaternion(trackingSpaceMeshRotation, convertFromUnityToOpenXR));
|
||||
DEBUG("SetProjectedPassthroughMeshOrientation() SetMeshTransformOrientation result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -556,18 +738,28 @@ namespace VIVE.OpenXR.Passthrough
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (layersDict[passthrough] == null)
|
||||
{
|
||||
ERROR("Passthrough layer not found.");
|
||||
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
|
||||
|
||||
var layer = layersDict[passthrough];
|
||||
var xrMesh = layer.GetMesh();
|
||||
xrMesh.scale = OpenXRHelper.ToOpenXRVector(meshScale, false);
|
||||
layer.SetMeshTransform(xrMesh);
|
||||
SubmitLayer();
|
||||
return true;
|
||||
#if UNITY_ANDROID
|
||||
ret = passthroughFeature.SetMeshTransformScale(passthrough, OpenXRHelper.ToOpenXRVector(meshScale, false));
|
||||
DEBUG("SetProjectedPassthroughScale() SetMeshTransformScale result: " + ret + ", passthrough: " + passthrough);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -699,7 +699,6 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4806409459047702211}
|
||||
- component: {fileID: 5568897672767345397}
|
||||
- component: {fileID: 1039589470112983849}
|
||||
- component: {fileID: 1039589470112983840}
|
||||
- component: {fileID: 1039589470112983852}
|
||||
@@ -726,19 +725,6 @@ Transform:
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &5568897672767345397
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4806409459047702212}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 52790aba0e3d55f4fb27aded6c698d8b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Handedness: 1
|
||||
--- !u!114 &1039589470112983849
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -858,7 +858,6 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7152668487518777764}
|
||||
- component: {fileID: 7057365311429264906}
|
||||
- component: {fileID: 3431167848623168894}
|
||||
- component: {fileID: 3431167848623168881}
|
||||
- component: {fileID: 3431167848623168882}
|
||||
@@ -885,19 +884,6 @@ Transform:
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &7057365311429264906
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7152668487518777765}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 52790aba0e3d55f4fb27aded6c698d8b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Handedness: 0
|
||||
--- !u!114 &3431167848623168894
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -8,13 +8,12 @@
|
||||
// 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.Linq;
|
||||
using System.Text;
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using System.Linq;
|
||||
|
||||
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
@@ -130,7 +129,6 @@ 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
|
||||
|
||||
@@ -158,7 +156,6 @@ 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()
|
||||
@@ -202,7 +199,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
}
|
||||
|
||||
if (IsEnterPressed())
|
||||
if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
|
||||
{
|
||||
FindNearInteractable();
|
||||
SavePoseWithCandidate();
|
||||
@@ -329,19 +326,6 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
return updated;
|
||||
}
|
||||
|
||||
private bool IsEnterPressed()
|
||||
{
|
||||
if (isNewInputSystem)
|
||||
{
|
||||
return (Keyboard.current.enterKey?.wasPressedThisFrame ?? false) ||
|
||||
(Keyboard.current.numpadEnterKey?.wasPressedThisFrame ?? false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the nearest interactable object to the hand.
|
||||
/// </summary>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
// 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;
|
||||
@@ -86,8 +87,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]
|
||||
@@ -182,9 +183,8 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
if (!isGrabbable || isGrabbed) { return 0; }
|
||||
Vector3 closestPoint = GetClosestPoint(grabberPos);
|
||||
float distanceSqr = (grabberPos - closestPoint).sqrMagnitude;
|
||||
float grabDistSqr = grabDistance * grabDistance;
|
||||
return distanceSqr > grabDistSqr ? 0 : 1 - (distanceSqr / grabDistSqr);
|
||||
float distacne = Vector3.Distance(grabberPos, closestPoint);
|
||||
return distacne > grabDistance ? 0 : 1 - (distacne / grabDistance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -263,41 +263,35 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
private Vector3 GetClosestPoint(Vector3 sourcePos)
|
||||
{
|
||||
Vector3 closestPoint = Vector3.zero;
|
||||
float shortDistanceSqr = float.MaxValue;
|
||||
float shortDistance = float.MaxValue;
|
||||
for (int i = 0; i < allColliders.Count; i++)
|
||||
{
|
||||
Collider collider = allColliders[i];
|
||||
Vector3 closePoint = collider.ClosestPointOnBounds(sourcePos);
|
||||
float distanceSqr = (sourcePos - closePoint).sqrMagnitude;
|
||||
if (distanceSqr < 0.001f)
|
||||
{
|
||||
return closePoint;
|
||||
}
|
||||
|
||||
float distance = Vector3.Distance(sourcePos, closePoint);
|
||||
if (collider.bounds.Contains(closePoint))
|
||||
{
|
||||
Vector3 direction = closePoint - sourcePos;
|
||||
direction.Normalize();
|
||||
int hitCount = Physics.RaycastNonAlloc(sourcePos, direction, hitResults, Mathf.Sqrt(distanceSqr));
|
||||
|
||||
int hitCount = Physics.RaycastNonAlloc(sourcePos, direction, hitResults, distance);
|
||||
for (int j = 0; j < hitCount; j++)
|
||||
{
|
||||
RaycastHit hit = hitResults[j];
|
||||
if (hit.collider == collider)
|
||||
{
|
||||
float hitDistanceSqr = (sourcePos - hit.point).sqrMagnitude;
|
||||
if (distanceSqr > hitDistanceSqr)
|
||||
float hitDistance = Vector3.Distance(sourcePos, hit.point);
|
||||
if (distance > hitDistance)
|
||||
{
|
||||
distanceSqr = hitDistanceSqr;
|
||||
distance = hitDistance;
|
||||
closePoint = hit.point;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shortDistanceSqr > distanceSqr)
|
||||
if (shortDistance > distance)
|
||||
{
|
||||
shortDistanceSqr = distanceSqr;
|
||||
shortDistance = distance;
|
||||
closestPoint = closePoint;
|
||||
}
|
||||
}
|
||||
@@ -367,12 +361,9 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// <param name="index">The index of the indicator to show.</param>
|
||||
private void ShowIndicatorByIndex(int index)
|
||||
{
|
||||
for (int i = 0; i < m_GrabPoses.Count; i++)
|
||||
foreach (var grabPose in m_GrabPoses)
|
||||
{
|
||||
if (index != i)
|
||||
{
|
||||
m_GrabPoses[i].indicator.SetActive(false);
|
||||
}
|
||||
grabPose.indicator.SetActive(false);
|
||||
}
|
||||
if (index >= 0 && index < m_GrabPoses.Count &&
|
||||
m_GrabPoses[index].indicator.enableIndicator)
|
||||
@@ -388,9 +379,9 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// <param name="isLeft">Whether the hand side is left.</param>
|
||||
private void ShowAllIndicator(bool isLeft)
|
||||
{
|
||||
for (int i = 0; i < m_GrabPoses.Count; i++)
|
||||
foreach (var grabPose in m_GrabPoses)
|
||||
{
|
||||
m_GrabPoses[i].indicator.SetActive(false);
|
||||
grabPose.indicator.SetActive(false);
|
||||
}
|
||||
foreach (var grabPose in m_GrabPoses)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
// 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;
|
||||
@@ -78,13 +79,6 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
private Pose wristPose = Pose.identity;
|
||||
private Vector3[] fingerTipPosition = new Vector3[(int)FingerId.Count];
|
||||
|
||||
private const int kMaxCacheSize = 100;
|
||||
private int lastBufferCount = 0;
|
||||
private Collider[] colliderBuffer = new Collider[50];
|
||||
private HandGrabInteractable[] grabbableBuffer = new HandGrabInteractable[50];
|
||||
private LinkedList<Collider> lruList = new LinkedList<Collider>();
|
||||
private Dictionary<Collider, LinkedListNode<Collider>> unusedColliders = new Dictionary<Collider, LinkedListNode<Collider>>();
|
||||
|
||||
#region MonoBehaviour
|
||||
private void Awake()
|
||||
{
|
||||
@@ -165,6 +159,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// </summary>
|
||||
private void FindCandidate()
|
||||
{
|
||||
currentCandidate = null;
|
||||
float distanceScore = float.MinValue;
|
||||
if (GetClosestGrabbable(m_GrabDistance, out HandGrabInteractable grabbable, out float score) && score > distanceScore)
|
||||
{
|
||||
@@ -194,47 +189,28 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
grabbable = null;
|
||||
maxScore = 0f;
|
||||
|
||||
for (int i = 0; i < lastBufferCount; i++)
|
||||
Collider[] nearColliders = Physics.OverlapSphere(wristPose.position, 0.5f);
|
||||
List<HandGrabInteractable> nearHandGrabInteractables = new List<HandGrabInteractable>();
|
||||
for (int i = 0; i < nearColliders.Length; i++)
|
||||
{
|
||||
HandGrabInteractable interactable = grabbableBuffer[i];
|
||||
HandGrabInteractable interactable = nearColliders[i].GetComponentInParent<HandGrabInteractable>();
|
||||
if (interactable && !nearHandGrabInteractables.Contains(interactable))
|
||||
{
|
||||
nearHandGrabInteractables.Add(interactable);
|
||||
continue;
|
||||
}
|
||||
interactable = nearColliders[i].GetComponentInChildren<HandGrabInteractable>();
|
||||
if (interactable && !nearHandGrabInteractables.Contains(interactable))
|
||||
{
|
||||
nearHandGrabInteractables.Add(interactable);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nearHandGrabInteractables.Count; i++)
|
||||
{
|
||||
HandGrabInteractable interactable = nearHandGrabInteractables[i];
|
||||
interactable.ShowIndicator(false, this);
|
||||
}
|
||||
|
||||
int colliderCount = Physics.OverlapSphereNonAlloc(wristPose.position, grabDistance * 5, colliderBuffer);
|
||||
int interactableCount = 0;
|
||||
for (int i = 0; i < colliderCount; i++)
|
||||
{
|
||||
Collider collider = colliderBuffer[i];
|
||||
if (unusedColliders.TryGetValue(collider, out _)) { continue; }
|
||||
|
||||
HandGrabInteractable interactable = collider.GetComponentInParent<HandGrabInteractable>()
|
||||
?? collider.GetComponentInChildren<HandGrabInteractable>();
|
||||
if (interactable != null)
|
||||
{
|
||||
bool isUnique = true;
|
||||
for (int j = 0; j < interactableCount; j++)
|
||||
{
|
||||
if (grabbableBuffer[j] == interactable)
|
||||
{
|
||||
isUnique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isUnique)
|
||||
{
|
||||
grabbableBuffer[interactableCount++] = interactable;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddUnusedColliders(collider);
|
||||
}
|
||||
}
|
||||
lastBufferCount = interactableCount;
|
||||
|
||||
for (int i = 0; i < interactableCount; i++)
|
||||
{
|
||||
HandGrabInteractable interactable = grabbableBuffer[i];
|
||||
for (int j = 0; j < fingerTipPosition.Length; j++)
|
||||
{
|
||||
float distanceScore = interactable.CalculateDistanceScore(fingerTipPosition[j], grabDistance);
|
||||
@@ -303,18 +279,5 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
m_Grabbable.UpdatePositionAndRotation(wristPose);
|
||||
}
|
||||
|
||||
private void AddUnusedColliders(Collider collider)
|
||||
{
|
||||
if (lruList.Count >= kMaxCacheSize)
|
||||
{
|
||||
var oldest = lruList.First;
|
||||
unusedColliders.Remove(oldest.Value);
|
||||
lruList.RemoveFirst();
|
||||
}
|
||||
|
||||
var node = lruList.AddLast(collider);
|
||||
unusedColliders[collider] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
@@ -84,11 +85,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
private Quaternion lastRotation;
|
||||
private bool isInit = false;
|
||||
private bool isTracked = true;
|
||||
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 List<Vector3> collisionDirections = new List<Vector3>();
|
||||
private bool isGrabbing = false;
|
||||
|
||||
#region MonoBehaviour
|
||||
@@ -166,11 +163,7 @@ 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;
|
||||
@@ -182,7 +175,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
private IEnumerator WaitForInit()
|
||||
{
|
||||
@@ -239,41 +232,33 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
Vector3 vel = (lastRootPos - rootJoint.position) / Time.deltaTime;
|
||||
if (IsValidVelocity(vel))
|
||||
{
|
||||
lock (collisionLock)
|
||||
if (collisionDirections.Count > 0)
|
||||
{
|
||||
if (currentCollisionCount > 0)
|
||||
float minAngle = float.MaxValue;
|
||||
Vector3 closestDirection = Vector3.zero;
|
||||
foreach (Vector3 direction in collisionDirections.ToList())
|
||||
{
|
||||
float minAngle = float.MaxValue;
|
||||
Vector3 closestDirection = Vector3.zero;
|
||||
float angle = Mathf.Abs(Vector3.Angle(direction, vel));
|
||||
if (angle < minAngle)
|
||||
{
|
||||
minAngle = angle;
|
||||
closestDirection = direction;
|
||||
}
|
||||
}
|
||||
collisionDirections.Clear();
|
||||
|
||||
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;
|
||||
Vector3 adjustedDirection = closestDirection;
|
||||
if (Vector3.Dot(vel, closestDirection) > 0)
|
||||
{
|
||||
adjustedDirection *= -1f;
|
||||
}
|
||||
vel = Vector3.ProjectOnPlane(vel, adjustedDirection);
|
||||
if (vel.magnitude > 1)
|
||||
{
|
||||
vel.Normalize();
|
||||
}
|
||||
}
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rootJointRigidbody.linearVelocity = vel;
|
||||
#else
|
||||
rootJointRigidbody.velocity = vel;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,7 +287,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
&& !float.IsInfinity(vector.x) && !float.IsInfinity(vector.y) && !float.IsInfinity(vector.z);
|
||||
}
|
||||
|
||||
#region Event CallBack
|
||||
#region Event CallBack
|
||||
|
||||
/// <summary>
|
||||
/// When tracking state changing, reset the pose and enable/disable collider.
|
||||
@@ -314,11 +299,7 @@ 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)
|
||||
@@ -374,21 +355,17 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
case JointCollider.CollisionState.Stay:
|
||||
if (collision.contactCount > 0 && (collision.rigidbody == null || collision.rigidbody.isKinematic))
|
||||
{
|
||||
lock (collisionLock)
|
||||
ContactPoint[] contactPoints = new ContactPoint[collision.contactCount];
|
||||
collision.GetContacts(contactPoints);
|
||||
foreach (ContactPoint contactPoint in contactPoints)
|
||||
{
|
||||
currentCollisionCount = Mathf.Min(contactPointsBuffer.Length, collision.contactCount);
|
||||
collision.GetContacts(contactPointsBuffer);
|
||||
|
||||
for (int i = 0; i < currentCollisionCount; i++)
|
||||
{
|
||||
collisionsDirection[i] = contactPointsBuffer[i].normal * -1f;
|
||||
}
|
||||
collisionDirections.Add(contactPoint.normal * -1f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,8 +635,6 @@ 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;
|
||||
@@ -773,16 +771,14 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
group = 0;
|
||||
index = jointId;
|
||||
|
||||
for (int i = 0; i < fingerGroup.Length; i++)
|
||||
// palm, wrist, thumb, index, middle, ring, pinky
|
||||
int[] fingerGroup = { 1, 1, 4, 5, 5, 5, 5 };
|
||||
while (index > fingerGroup[group])
|
||||
{
|
||||
if (index <= fingerGroup[i])
|
||||
{
|
||||
group = i;
|
||||
index -= 1; // Adjust to 0-based index
|
||||
return;
|
||||
}
|
||||
index -= fingerGroup[i];
|
||||
index -= fingerGroup[group];
|
||||
group += 1;
|
||||
}
|
||||
index -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -852,29 +848,32 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// <param name="isLeft">True if the hand is left; otherwise, false.</param>
|
||||
private static void GetFingerData(FingerId id, ref FingerData finger, bool isLeft)
|
||||
{
|
||||
JointType[] jointTypes = GetJointTypes(id);
|
||||
if (jointTypes == null) return;
|
||||
|
||||
float deltaTime = Time.deltaTime;
|
||||
Vector3 parentVel = Vector3.zero;
|
||||
|
||||
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;
|
||||
}
|
||||
for (int i = 0; i < jointTypes.Length; i++)
|
||||
{
|
||||
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;
|
||||
Vector3 parentVel = i == 0 ? Vector3.zero : finger.joints[i - 1].velocity;
|
||||
JointData lastJoint = finger.joints[i];
|
||||
GetJointData(jointTypes[i], ref finger.joints[i], isLeft);
|
||||
|
||||
//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 > joint.velocity.magnitude)
|
||||
if (parentVel.magnitude > finger.joints[i].velocity.magnitude)
|
||||
{
|
||||
joint.position += parentVel * deltaTime;
|
||||
lastJoint.position += parentVel * Time.deltaTime;
|
||||
finger.joints[i] = lastJoint;
|
||||
}
|
||||
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;
|
||||
@@ -886,19 +885,6 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
}
|
||||
|
||||
private static JointType[] GetJointTypes(FingerId id)
|
||||
{
|
||||
return id switch
|
||||
{
|
||||
FingerId.Thumb => s_ThumbJoints,
|
||||
FingerId.Index => s_IndexJoints,
|
||||
FingerId.Middle => s_MiddleJoints,
|
||||
FingerId.Ring => s_RingJoints,
|
||||
FingerId.Pinky => s_PinkyJoints,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the data for the left or right hand.
|
||||
/// </summary>
|
||||
@@ -1081,16 +1067,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;
|
||||
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));
|
||||
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));
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
@@ -1746,16 +1732,9 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
/// <param name="enable">True to enable the indicator, false to deactivate it.</param>
|
||||
public void SetActive(bool enable)
|
||||
{
|
||||
if (target)
|
||||
if (target != null)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
target.transform.localScale = Vector3.one;
|
||||
}
|
||||
else
|
||||
{
|
||||
target.transform.localScale = Vector3.zero;
|
||||
}
|
||||
target.SetActive(enable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
[SerializeField]
|
||||
private HandMeshManager m_HandMesh;
|
||||
|
||||
|
||||
private bool keepUpdate = false;
|
||||
|
||||
protected override void OnEnable()
|
||||
@@ -18,7 +18,11 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
keepUpdate = false;
|
||||
if (keepUpdate)
|
||||
{
|
||||
keepUpdate = false;
|
||||
StopCoroutine(UpdatePose());
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHandMeshRenderer(HandMeshManager handMeshRenderer)
|
||||
@@ -40,32 +44,39 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
yield return new WaitUntil(() => m_Initialized);
|
||||
base.OnEnable();
|
||||
keepUpdate = true;
|
||||
if (!keepUpdate)
|
||||
{
|
||||
keepUpdate = true;
|
||||
StartCoroutine(UpdatePose());
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
private IEnumerator UpdatePose()
|
||||
{
|
||||
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++)
|
||||
while (keepUpdate)
|
||||
{
|
||||
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))
|
||||
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++)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,11 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
keepUpdate = false;
|
||||
if (keepUpdate)
|
||||
{
|
||||
keepUpdate = false;
|
||||
StopCoroutine(UpdatePose());
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetType(HandPoseType poseType)
|
||||
@@ -39,33 +43,41 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
{
|
||||
yield return new WaitUntil(() => m_Initialized);
|
||||
base.OnEnable();
|
||||
keepUpdate = true;
|
||||
if (!keepUpdate)
|
||||
{
|
||||
keepUpdate = true;
|
||||
StartCoroutine(UpdatePose());
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
private IEnumerator UpdatePose()
|
||||
{
|
||||
if (!keepUpdate) { return; }
|
||||
HandData handData = CachedHand.Get(isLeft);
|
||||
m_IsTracked = handData.isTracked;
|
||||
if (!m_IsTracked) { return; }
|
||||
|
||||
Vector3 position = Vector3.zero;
|
||||
Quaternion rotation = Quaternion.identity;
|
||||
for (int i = 0; i < poseCount; i++)
|
||||
while (keepUpdate)
|
||||
{
|
||||
if (handData.GetJointPosition((JointType)i, ref position) && handData.GetJointRotation((JointType)i, ref rotation))
|
||||
yield return new WaitForEndOfFrame();
|
||||
|
||||
HandData handData = CachedHand.Get(isLeft);
|
||||
m_IsTracked = handData.isTracked;
|
||||
if (!m_IsTracked) { continue; }
|
||||
|
||||
for (int i = 0; i < poseCount; i++)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
@@ -10,15 +9,13 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
[SerializeField]
|
||||
private float forceMultiplier = 1.0f;
|
||||
|
||||
private const int MIN_POSE_SAMPLES = 2;
|
||||
private const int MAX_POSE_SAMPLES = 10;
|
||||
private readonly int MIN_POSE_SAMPLES = 2;
|
||||
private readonly int MAX_POSE_SAMPLES = 10;
|
||||
private readonly float MIN_VELOCITY = 0.5f;
|
||||
|
||||
private Rigidbody interactableRigidbody;
|
||||
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 List<Pose> movementPoses = new List<Pose>();
|
||||
private List<float> timestamps = new List<float>();
|
||||
private bool isBegin = false;
|
||||
private bool isEnd = false;
|
||||
private object lockVel = new object();
|
||||
@@ -39,11 +36,7 @@ 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();
|
||||
@@ -53,10 +46,8 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
}
|
||||
interactableRigidbody = null;
|
||||
|
||||
Array.Clear(movementPoses, 0, MAX_POSE_SAMPLES);
|
||||
Array.Clear(timestamps, 0, MAX_POSE_SAMPLES);
|
||||
currentPoseIndex = 0;
|
||||
poseCount = 0;
|
||||
movementPoses.Clear();
|
||||
timestamps.Clear();
|
||||
isEnd = false;
|
||||
}
|
||||
}
|
||||
@@ -64,29 +55,28 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
private void RecordMovement()
|
||||
{
|
||||
float time = Time.time;
|
||||
|
||||
int lastIndex = (currentPoseIndex + poseCount - 1) % MAX_POSE_SAMPLES;
|
||||
if (poseCount == 0 || timestamps[lastIndex] != time)
|
||||
if (movementPoses.Count == 0 ||
|
||||
timestamps[movementPoses.Count - 1] != time)
|
||||
{
|
||||
movementPoses[currentPoseIndex] = new Pose(interactableRigidbody.position, interactableRigidbody.rotation);
|
||||
timestamps[currentPoseIndex] = time;
|
||||
movementPoses.Add(new Pose(interactableRigidbody.position, interactableRigidbody.rotation));
|
||||
timestamps.Add(time);
|
||||
}
|
||||
|
||||
if (poseCount < MAX_POSE_SAMPLES)
|
||||
{
|
||||
poseCount++;
|
||||
}
|
||||
currentPoseIndex = (currentPoseIndex + 1) % MAX_POSE_SAMPLES;
|
||||
if (movementPoses.Count > MAX_POSE_SAMPLES)
|
||||
{
|
||||
movementPoses.RemoveAt(0);
|
||||
timestamps.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 CalculateVelocity()
|
||||
{
|
||||
if (poseCount >= MIN_POSE_SAMPLES)
|
||||
if (movementPoses.Count >= MIN_POSE_SAMPLES)
|
||||
{
|
||||
List<Vector3> velocities = new List<Vector3>();
|
||||
for (int i = 0; i < poseCount - 1; i++)
|
||||
for (int i = 0; i < movementPoses.Count - 1; i++)
|
||||
{
|
||||
for (int j = i + 1; j < poseCount; j++)
|
||||
for (int j = i + 1; j < movementPoses.Count; j++)
|
||||
{
|
||||
velocities.Add(GetVelocity(i, j));
|
||||
}
|
||||
@@ -99,9 +89,9 @@ namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction
|
||||
|
||||
private Vector3 GetVelocity(int idx1, int idx2)
|
||||
{
|
||||
if (idx1 < 0 || idx1 >= poseCount
|
||||
|| idx2 < 0 || idx2 >= poseCount
|
||||
|| poseCount < MIN_POSE_SAMPLES)
|
||||
if (idx1 < 0 || idx1 >= movementPoses.Count
|
||||
|| idx2 < 0 || idx2 >= movementPoses.Count
|
||||
|| movementPoses.Count < MIN_POSE_SAMPLES)
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"WindowsStandalone64"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
@@ -24,11 +24,6 @@
|
||||
"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",
|
||||
@@ -46,4 +41,4 @@
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
}
|
||||
@@ -282,7 +282,7 @@ namespace VIVE.OpenXR
|
||||
/// </summary>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
// Debug.LogFormat("VIVECosmosProfile RegisterDeviceLayout() {0} , product: {1}", kLayoutName, kDeviceLocalizedName);
|
||||
Debug.LogFormat("VIVECosmosProfile RegisterDeviceLayout() {0} , product: {1}", kLayoutName, kDeviceLocalizedName);
|
||||
InputSystem.RegisterLayout(typeof(ViveCosmosController),
|
||||
kLayoutName,
|
||||
matches: new InputDeviceMatcher()
|
||||
@@ -295,7 +295,7 @@ namespace VIVE.OpenXR
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
// Debug.LogFormat("VIVECosmosProfile UnregisterDeviceLayout() {0}", kLayoutName);
|
||||
Debug.LogFormat("VIVECosmosProfile UnregisterDeviceLayout() {0}", kLayoutName);
|
||||
InputSystem.RemoveLayout(kLayoutName);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.Log(LOG_TAG + msg); }
|
||||
void ERROR(StringBuilder msg) { Debug.LogError(LOG_TAG + msg); }
|
||||
void DEBUG(StringBuilder msg) { Debug.LogFormat("{0} {1}", LOG_TAG, msg); }
|
||||
void ERROR(StringBuilder msg) { Debug.LogErrorFormat("{0} {1}", LOG_TAG, msg); }
|
||||
#endregion
|
||||
|
||||
private static VIVEFocus3Profile m_Instance = null;
|
||||
@@ -88,13 +88,11 @@ namespace VIVE.OpenXR
|
||||
return m_sb;
|
||||
}
|
||||
}
|
||||
void DEBUG(StringBuilder msg) { Debug.Log(LOG_TAG + msg); }
|
||||
void ERROR(StringBuilder msg) { Debug.LogError(LOG_TAG + msg); }
|
||||
void DEBUG(StringBuilder msg) { Debug.LogFormat("{0} {1}", LOG_TAG, msg); }
|
||||
void ERROR(StringBuilder msg) { Debug.LogErrorFormat("{0} {1}", LOG_TAG, msg); }
|
||||
#endregion
|
||||
|
||||
#region Action Path
|
||||
|
||||
#region Button
|
||||
/// <summary>
|
||||
/// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents the <see cref="VIVEFocus3Profile.thumbstick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
@@ -147,7 +145,7 @@ namespace VIVE.OpenXR
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="triggerClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "indexButton", "triggerButton" }, usage = "TriggerButton")]
|
||||
public ButtonControl triggerPressed { get; private set; } // InputControl(offset = 20)
|
||||
public ButtonControl triggerPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="triggerTouch"/> OpenXR binding.
|
||||
@@ -159,7 +157,7 @@ namespace VIVE.OpenXR
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="thumbstickClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "JoystickOrPadPressed", "thumbstickClick", "joystickClicked", "primary2DAxisClick" }, usage = "Primary2DAxisClick")]
|
||||
public ButtonControl thumbstickClicked { get; private set; } // InputControl(offset = 22)
|
||||
public ButtonControl thumbstickClicked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="thumbstickTouch"/> OpenXR binding.
|
||||
@@ -171,31 +169,31 @@ namespace VIVE.OpenXR
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="thumbrest"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "ParkingTouched", "parkingTouched" })]
|
||||
public ButtonControl thumbrestTouched { get; private set; } // InputControl(offset = 24)
|
||||
#endregion
|
||||
public ButtonControl thumbrestTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="gripPose"/> OpenXR binding. The grip pose represents the location of the user's palm or holding a motion controller.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="VIVEFocus3Profile.aim"/> OpenXR binding. The pointer pose represents the tip of the controller pointing forward.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "aimPose", "pointerPose" }, usage = "Pointer")]
|
||||
public PoseControl pointer { get; private set; }
|
||||
|
||||
#if UNITY_ANDROID
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing the <see cref="VIVEFocus3Profile.pinchPose"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, usage = "Pinch")]
|
||||
public PoseControl pinchPose { get; private set; }
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing the <see cref="VIVEFocus3Profile.pokePose"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "indexTip", usage = "Poke")]
|
||||
public PoseControl pokePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing the <see cref="VIVEFocus3Profile.pinchPose"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, usage = "Pinch")]
|
||||
public PoseControl pinchPose { get; private set; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
@@ -229,29 +227,28 @@ namespace VIVE.OpenXR
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 104, noisy = true, alias = "pointerOrientation")]
|
||||
public QuaternionControl pointerRotation { get; private set; }
|
||||
|
||||
#if UNITY_ANDROID
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the pinch position. This value is equivalent to mapping pinchPose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 152, noisy = true)]
|
||||
public Vector3Control pinchPosition { get; private set; }
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the pinch orientation. This value is equivalent to mapping pinchPose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 164, noisy = true)]
|
||||
public QuaternionControl pinchRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the poke position. This value is equivalent to mapping pokePose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 212, noisy = true)]
|
||||
[Preserve, InputControl(offset = 152, noisy = true)]
|
||||
public Vector3Control pokePosition { get; private set; }
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the poke orientation. This value is equivalent to mapping pokePose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 224, noisy = true)]
|
||||
[Preserve, InputControl(offset = 164, noisy = true)]
|
||||
public QuaternionControl pokeRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the pinch position. This value is equivalent to mapping pinchPose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 212, noisy = true)]
|
||||
public Vector3Control pinchPosition { get; private set; }
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the pinch orientation. This value is equivalent to mapping pinchPose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 224, noisy = true)]
|
||||
public QuaternionControl pinchRotation { get; private set; }
|
||||
#endif
|
||||
/// <summary>
|
||||
/// A <see cref="HapticControl"/> that represents the <see cref="VIVEFocus3Profile.haptic"/> binding.
|
||||
@@ -500,7 +497,7 @@ namespace VIVE.OpenXR
|
||||
/// </summary>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(kDeviceLocalizedName); DEBUG(sb);
|
||||
sb.Clear().Append("RegisterDeviceLayout() ").Append(kLayoutName).Append(", product: ").Append(kDeviceLocalizedName); DEBUG(sb);
|
||||
InputSystem.RegisterLayout(typeof(VIVEFocus3Controller),
|
||||
kLayoutName,
|
||||
matches: new InputDeviceMatcher()
|
||||
@@ -513,7 +510,7 @@ namespace VIVE.OpenXR
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
// sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
sb.Clear().Append("UnregisterDeviceLayout() ").Append(kLayoutName); DEBUG(sb);
|
||||
InputSystem.RemoveLayout(kLayoutName);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,6 +43,12 @@ 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;
|
||||
@@ -50,14 +56,10 @@ namespace VIVE.OpenXR
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
private static readonly List<XRInputSubsystem> s_InputSubsystems = new List<XRInputSubsystem>();
|
||||
private static readonly object lockObj = new object();
|
||||
private float m_LastRecenteredTime = 0.0f;
|
||||
|
||||
#region MonoBehaviour
|
||||
static List<XRInputSubsystem> s_InputSubsystems = new List<XRInputSubsystem>();
|
||||
private void OnEnable()
|
||||
{
|
||||
UpdateInputSubsystems();
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
for (int i = 0; i < s_InputSubsystems.Count; i++)
|
||||
{
|
||||
s_InputSubsystems[i].trackingOriginUpdated += TrackingOriginUpdated;
|
||||
@@ -72,12 +74,29 @@ namespace VIVE.OpenXR
|
||||
}
|
||||
private void OnDisable()
|
||||
{
|
||||
UpdateInputSubsystems();
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
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)
|
||||
@@ -88,17 +107,37 @@ 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()
|
||||
{
|
||||
TrackingOriginModeFlags mode = GetTrackingOriginMode();
|
||||
if ((mode != m_TrackingOrigin || m_TrackingOriginEx != m_TrackingOrigin) &&
|
||||
m_TrackingOrigin != TrackingOriginModeFlags.Unknown &&
|
||||
SetTrackingOriginMode(m_TrackingOrigin))
|
||||
UpdateInputSystem();
|
||||
if (m_InputSystem != null)
|
||||
{
|
||||
mode = GetTrackingOriginMode();
|
||||
sb.Clear().Append("Update() Tracking mode is set to " + mode);
|
||||
m_TrackingOriginEx = 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_CameraOffset != null && m_TrackingOrigin == TrackingOriginModeFlags.Device)
|
||||
@@ -110,66 +149,5 @@ namespace VIVE.OpenXR
|
||||
m_CameraOffset.transform.localPosition = cameraPosOffset;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private bool SetTrackingOriginMode(TrackingOriginModeFlags value)
|
||||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
UpdateInputSubsystems();
|
||||
|
||||
for (int i = 0; i < s_InputSubsystems.Count; i++)
|
||||
{
|
||||
var subsys = s_InputSubsystems[i];
|
||||
if (!subsys.running)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (subsys.TrySetTrackingOriginMode(value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Debug.LogWarning($"Failed to set TrackingOriginModeFlags({value}) to XRInputSubsystem: {subsys.subsystemDescriptor?.id ?? "Unknown"}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private TrackingOriginModeFlags GetTrackingOriginMode()
|
||||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
UpdateInputSubsystems();
|
||||
|
||||
for(int i=0; i< s_InputSubsystems.Count; i++)
|
||||
{
|
||||
var subsys = s_InputSubsystems[i];
|
||||
if (!subsys.running)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return subsys.GetTrackingOriginMode();
|
||||
}
|
||||
return TrackingOriginModeFlags.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateInputSubsystems()
|
||||
{
|
||||
s_InputSubsystems.Clear();
|
||||
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
SubsystemManager.GetSubsystems(s_InputSubsystems);
|
||||
#else
|
||||
SubsystemManager.GetInstances(s_InputSubsystems);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void TrackingOriginUpdated(XRInputSubsystem obj)
|
||||
{
|
||||
m_LastRecenteredTime = Time.time;
|
||||
sb.Clear().Append("TrackingOriginUpdated() m_LastRecenteredTime: ").Append(m_LastRecenteredTime); DEBUG(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace VIVE.OpenXR.Samples.Anchor
|
||||
void GetXRInputSubsystem()
|
||||
{
|
||||
List<XRInputSubsystem> xrSubsystemList = new List<XRInputSubsystem>();
|
||||
SubsystemManager.GetSubsystems(xrSubsystemList);
|
||||
SubsystemManager.GetInstances(xrSubsystemList);
|
||||
foreach (var xrSubsystem in xrSubsystemList)
|
||||
{
|
||||
if (xrSubsystem.running)
|
||||
@@ -675,12 +675,6 @@ namespace VIVE.OpenXR.Samples.Anchor
|
||||
if (task.IsCompleted)
|
||||
{
|
||||
Task<(XrResult, string, byte[])> t = task as Task<(XrResult, string, byte[])>;
|
||||
if (t == null)
|
||||
{
|
||||
tasks.Remove(task);
|
||||
break;
|
||||
}
|
||||
|
||||
if (t.Result.Item1 == XrResult.XR_SUCCESS)
|
||||
{
|
||||
// write to file
|
||||
|
||||
@@ -349,9 +349,9 @@
|
||||
},
|
||||
{
|
||||
"name": "IsTracked",
|
||||
"type": "Button",
|
||||
"type": "Value",
|
||||
"id": "384094ab-6290-4de1-9b73-6dd7fae94298",
|
||||
"expectedControlType": "Button",
|
||||
"expectedControlType": "Analog",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": true
|
||||
@@ -1230,9 +1230,9 @@
|
||||
},
|
||||
{
|
||||
"name": "IsTracked",
|
||||
"type": "Button",
|
||||
"type": "Value",
|
||||
"id": "d1478f77-9424-45e1-bbe0-949fcfaec599",
|
||||
"expectedControlType": "Button",
|
||||
"expectedControlType": "Analog",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": true
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa549247e9994a84697e73e6d1288e2b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,71 +0,0 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.XR;
|
||||
using VIVE.OpenXR;
|
||||
|
||||
[RequireComponent(typeof(Text))]
|
||||
public class DebugIsTrackedOffset : MonoBehaviour
|
||||
{
|
||||
public InputActionReference isTracked1 = null;
|
||||
public InputActionReference isTracked2 = null;
|
||||
public InputActionReference isTracked3 = null;
|
||||
public InputActionReference isTracked4 = null;
|
||||
|
||||
private Text m_Text = null;
|
||||
private void Start()
|
||||
{
|
||||
m_Text = GetComponent<Text>();
|
||||
}
|
||||
void Update()
|
||||
{
|
||||
if (m_Text == null) { return; }
|
||||
|
||||
m_Text.text = "";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked1, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += isTracked1.action.name + ": " + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\n";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked2, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += isTracked2.action.name + ": " + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\n";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked3, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += isTracked3.action.name + ": " + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\n";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked4, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += isTracked4.action.name + ": " + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c5ffdf8ced75cf41a74cb761a3987dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,136 +0,0 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.XR;
|
||||
using VIVE.OpenXR;
|
||||
|
||||
[RequireComponent(typeof(Text))]
|
||||
public class DebugPoseData : MonoBehaviour
|
||||
{
|
||||
public string PoseName = "";
|
||||
public InputActionReference isTracked = null;
|
||||
public InputActionReference trackingState = null;
|
||||
public InputActionReference position = null;
|
||||
public InputActionReference rotation = null;
|
||||
public InputActionReference pose = null;
|
||||
|
||||
private Text m_Text = null;
|
||||
private void Start()
|
||||
{
|
||||
m_Text = GetComponent<Text>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (m_Text == null) { return; }
|
||||
|
||||
m_Text.text = PoseName + " ----";
|
||||
|
||||
if (isTracked != null)
|
||||
{
|
||||
m_Text.text += "\nisTracked: ";
|
||||
{
|
||||
if (OpenXRHelper.GetButton(isTracked, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trackingState != null)
|
||||
{
|
||||
m_Text.text += "\ntrackingState: ";
|
||||
{
|
||||
if (OpenXRHelper.GetInteger(trackingState, out InputTrackingState value, out string msg))
|
||||
{
|
||||
m_Text.text += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (position != null)
|
||||
{
|
||||
m_Text.text += "\nposition: ";
|
||||
{
|
||||
if (OpenXRHelper.GetVector3(position, out Vector3 value, out string msg))
|
||||
{
|
||||
m_Text.text += "(" + value.x.ToString("N3") + ", " + value.y.ToString("N3") + ", " + value.z.ToString("N3") + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rotation != null)
|
||||
{
|
||||
m_Text.text += "\nrotation: ";
|
||||
{
|
||||
if (OpenXRHelper.GetQuaternion(rotation, out Quaternion value, out string msg))
|
||||
{
|
||||
m_Text.text += "(" + value.x.ToString("N3") + ", " + value.y.ToString("N3") + ", " + value.z.ToString("N3") + ", " + value.w.ToString("N3") + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pose != null)
|
||||
{
|
||||
m_Text.text += "\npose.isTracked: ";
|
||||
{
|
||||
if (OpenXRHelper.GetPoseIsTracked(pose, out bool value, out string msg))
|
||||
{
|
||||
m_Text.text += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\npose.trackingState: ";
|
||||
{
|
||||
if (OpenXRHelper.GetPoseTrackingState(pose, out InputTrackingState value, out string msg))
|
||||
{
|
||||
m_Text.text += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\npose.position: ";
|
||||
{
|
||||
if (OpenXRHelper.GetPosePosition(pose, out Vector3 value, out string msg))
|
||||
{
|
||||
m_Text.text += "(" + value.x.ToString("N3") + ", " + value.y.ToString("N3") + ", " + value.z.ToString("N3") + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
m_Text.text += "\npose.rotation: ";
|
||||
{
|
||||
if (OpenXRHelper.GetPoseRotation(pose, out Quaternion value, out string msg))
|
||||
{
|
||||
m_Text.text += "(" + value.x.ToString("N3") + ", " + value.y.ToString("N3") + ", " + value.z.ToString("N3") + ", " + value.w.ToString("N3") + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Text.text += msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04725f4c022874d40a6e786b002b782a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -111,14 +111,7 @@ 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 129 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 129 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 129 B |