Skip to content

Commit 00609ff

Browse files
committed
Add MicrosoftControllerModelProvider and integration
1 parent 0386c53 commit 00609ff

File tree

5 files changed

+243
-1
lines changed

5 files changed

+243
-1
lines changed

Assets/MRTK/Providers/OpenXR/Profiles/ObsoleteOpenXRControllerVisualizationProfile.asset

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,26 @@ MonoBehaviour:
2828
type: 3}
2929
globalRightHandVisualizer: {fileID: 1788309537287834, guid: 132c9402d5843aa4f94380840186fd41,
3030
type: 3}
31-
controllerVisualizationSettings: []
31+
controllerVisualizationSettings:
32+
- description: Microsoft Motion Controller
33+
controllerType:
34+
reference: Microsoft.MixedReality.Toolkit.XRSDK.OpenXR.MicrosoftMotionController,
35+
Microsoft.MixedReality.Toolkit.Providers.OpenXR
36+
handedness: 3
37+
usePlatformModels: 1
38+
platformModelMaterial: {fileID: 0}
39+
overrideModel: {fileID: 0}
40+
controllerVisualizationType:
41+
reference: Microsoft.MixedReality.Toolkit.Input.WindowsMixedRealityControllerVisualizer,
42+
Microsoft.MixedReality.Toolkit.SDK
43+
- description: HP Reverb G2 Controller
44+
controllerType:
45+
reference: Microsoft.MixedReality.Toolkit.XRSDK.OpenXR.HPReverbG2Controller,
46+
Microsoft.MixedReality.Toolkit.Providers.OpenXR
47+
handedness: 3
48+
usePlatformModels: 1
49+
platformModelMaterial: {fileID: 0}
50+
overrideModel: {fileID: 0}
51+
controllerVisualizationType:
52+
reference: Microsoft.MixedReality.Toolkit.Input.WindowsMixedRealityControllerVisualizer,
53+
Microsoft.MixedReality.Toolkit.SDK

Assets/MRTK/Providers/OpenXR/Scripts/HPReverbG2Controller.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,74 @@ protected override void UpdatePoseData(MixedRealityInteractionMapping interactio
6767
}
6868
}
6969
}
70+
71+
#if MSFT_OPENXR_0_9_4_OR_NEWER
72+
private MicrosoftControllerModelProvider controllerModelProvider;
73+
74+
/// <inheritdoc />
75+
protected override bool TryRenderControllerModel(System.Type controllerType, InputSourceType inputSourceType)
76+
{
77+
if (GetControllerVisualizationProfile() == null ||
78+
!GetControllerVisualizationProfile().GetUsePlatformModelsOverride(GetType(), ControllerHandedness))
79+
{
80+
return base.TryRenderControllerModel(controllerType, inputSourceType);
81+
}
82+
else
83+
{
84+
TryRenderControllerModelWithModelProvider();
85+
return true;
86+
}
87+
}
88+
89+
private async void TryRenderControllerModelWithModelProvider()
90+
{
91+
if (controllerModelProvider == null)
92+
{
93+
controllerModelProvider = new MicrosoftControllerModelProvider(ControllerHandedness);
94+
}
95+
96+
GameObject controllerModel = await controllerModelProvider.TryGenerateControllerModelFromPlatformSDK();
97+
98+
if (controllerModel != null)
99+
{
100+
if (this != null)
101+
{
102+
var visualizationProfile = GetControllerVisualizationProfile();
103+
if (visualizationProfile != null)
104+
{
105+
var visualizationType = visualizationProfile.GetControllerVisualizationTypeOverride(GetType(), ControllerHandedness);
106+
if (visualizationType != null)
107+
{
108+
// Set the platform controller model to not be destroyed when the source is lost. It'll be disabled instead,
109+
// and re-enabled when the same controller is re-detected.
110+
if (controllerModel.EnsureComponent(visualizationType.Type) is IMixedRealityControllerPoseSynchronizer visualizer)
111+
{
112+
visualizer.DestroyOnSourceLost = false;
113+
}
114+
115+
if (TryAddControllerModelToSceneHierarchy(controllerModel))
116+
{
117+
return;
118+
}
119+
}
120+
else
121+
{
122+
Debug.LogError("Controller visualization type not defined for controller visualization profile");
123+
}
124+
}
125+
else
126+
{
127+
Debug.LogError("Failed to obtain a controller visualization profile");
128+
}
129+
130+
Debug.LogWarning("Failed to create controller model from driver; defaulting to BaseController behavior.");
131+
base.TryRenderControllerModel(GetType(), InputSource.SourceType);
132+
}
133+
134+
// If we didn't successfully set up the model and add it to the hierarchy (which returns early), set it inactive.
135+
controllerModel.SetActive(false);
136+
}
137+
}
138+
#endif // MSFT_OPENXR_0_9_4_OR_NEWER
70139
}
71140
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System.Threading.Tasks;
5+
using UnityEngine;
6+
7+
#if MSFT_OPENXR_0_9_4_OR_NEWER
8+
using Microsoft.MixedReality.OpenXR;
9+
using Microsoft.MixedReality.Toolkit.Utilities.Gltf.Serialization;
10+
using System.Collections.Generic;
11+
#endif // MSFT_OPENXR_0_9_4_OR_NEWER
12+
13+
namespace Microsoft.MixedReality.Toolkit.XRSDK.OpenXR
14+
{
15+
/// <summary>
16+
/// Queries the OpenXR APIs for a renderable controller model.
17+
/// </summary>
18+
internal class MicrosoftControllerModelProvider
19+
{
20+
public MicrosoftControllerModelProvider(Utilities.Handedness handedness)
21+
{
22+
#if MSFT_OPENXR_0_9_4_OR_NEWER
23+
controllerModelProvider = handedness == Utilities.Handedness.Left ? ControllerModel.Left : ControllerModel.Right;
24+
#endif // MSFT_OPENXR_0_9_4_OR_NEWER
25+
}
26+
27+
#if MSFT_OPENXR_0_9_4_OR_NEWER
28+
private static readonly Dictionary<ulong, GameObject> ControllerModelDictionary = new Dictionary<ulong, GameObject>(2);
29+
private readonly ControllerModel controllerModelProvider;
30+
#endif // MSFT_OPENXR_0_9_4_OR_NEWER
31+
32+
#if MSFT_OPENXR_0_9_4_OR_NEWER
33+
/// <summary>
34+
/// Attempts to load the glTF controller model from OpenXR.
35+
/// </summary>
36+
/// <returns>The controller model as a GameObject or null if it was unobtainable.</returns>
37+
public async Task<GameObject> TryGenerateControllerModelFromPlatformSDK()
38+
{
39+
if (!controllerModelProvider.TryGetControllerModelKey(out ulong modelKey))
40+
{
41+
Debug.LogError("Failed to obtain controller model key from platform.");
42+
return null;
43+
}
44+
45+
if (ControllerModelDictionary.TryGetValue(modelKey, out GameObject controllerModel))
46+
{
47+
controllerModel.SetActive(true);
48+
return controllerModel;
49+
}
50+
51+
byte[] modelStream = await controllerModelProvider.TryGetControllerModel(modelKey);
52+
53+
if (modelStream == null || modelStream.Length == 0)
54+
{
55+
Debug.LogError("Failed to obtain controller model from platform.");
56+
return null;
57+
}
58+
59+
Utilities.Gltf.Schema.GltfObject gltfObject = GltfUtility.GetGltfObjectFromGlb(modelStream);
60+
GameObject gltfGameObject = await gltfObject.ConstructAsync();
61+
62+
if (gltfGameObject != null)
63+
{
64+
ControllerModelDictionary.Add(modelKey, gltfGameObject);
65+
}
66+
67+
return gltfGameObject;
68+
}
69+
#endif // MSFT_OPENXR_0_9_4_OR_NEWER
70+
}
71+
}

Assets/MRTK/Providers/OpenXR/Scripts/MicrosoftControllerModelProvider.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/MRTK/Providers/OpenXR/Scripts/MicrosoftMotionController.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,74 @@ protected override void UpdatePoseData(MixedRealityInteractionMapping interactio
7171
}
7272
}
7373
}
74+
75+
#if MSFT_OPENXR_0_9_4_OR_NEWER
76+
private MicrosoftControllerModelProvider controllerModelProvider;
77+
78+
/// <inheritdoc />
79+
protected override bool TryRenderControllerModel(System.Type controllerType, InputSourceType inputSourceType)
80+
{
81+
if (GetControllerVisualizationProfile() == null ||
82+
!GetControllerVisualizationProfile().GetUsePlatformModelsOverride(GetType(), ControllerHandedness))
83+
{
84+
return base.TryRenderControllerModel(controllerType, inputSourceType);
85+
}
86+
else
87+
{
88+
TryRenderControllerModelWithModelProvider();
89+
return true;
90+
}
91+
}
92+
93+
private async void TryRenderControllerModelWithModelProvider()
94+
{
95+
if (controllerModelProvider == null)
96+
{
97+
controllerModelProvider = new MicrosoftControllerModelProvider(ControllerHandedness);
98+
}
99+
100+
GameObject controllerModel = await controllerModelProvider.TryGenerateControllerModelFromPlatformSDK();
101+
102+
if (controllerModel != null)
103+
{
104+
if (this != null)
105+
{
106+
var visualizationProfile = GetControllerVisualizationProfile();
107+
if (visualizationProfile != null)
108+
{
109+
var visualizationType = visualizationProfile.GetControllerVisualizationTypeOverride(GetType(), ControllerHandedness);
110+
if (visualizationType != null)
111+
{
112+
// Set the platform controller model to not be destroyed when the source is lost. It'll be disabled instead,
113+
// and re-enabled when the same controller is re-detected.
114+
if (controllerModel.EnsureComponent(visualizationType.Type) is IMixedRealityControllerPoseSynchronizer visualizer)
115+
{
116+
visualizer.DestroyOnSourceLost = false;
117+
}
118+
119+
if (TryAddControllerModelToSceneHierarchy(controllerModel))
120+
{
121+
return;
122+
}
123+
}
124+
else
125+
{
126+
Debug.LogError("Controller visualization type not defined for controller visualization profile");
127+
}
128+
}
129+
else
130+
{
131+
Debug.LogError("Failed to obtain a controller visualization profile");
132+
}
133+
134+
Debug.LogWarning("Failed to create controller model from driver; defaulting to BaseController behavior.");
135+
base.TryRenderControllerModel(GetType(), InputSource.SourceType);
136+
}
137+
138+
// If we didn't successfully set up the model and add it to the hierarchy (which returns early), set it inactive.
139+
controllerModel.SetActive(false);
140+
}
141+
}
142+
#endif // MSFT_OPENXR_0_9_4_OR_NEWER
74143
}
75144
}

0 commit comments

Comments
 (0)