Skip to content

Commit 5d7f759

Browse files
authored
Merge pull request #9550 from keveleigh/xrsdk-controller-models
Add support for motion controller models at runtime in WMR/XRSDK
2 parents ef7eb15 + 7655a31 commit 5d7f759

13 files changed

+311
-126
lines changed

Assets/MRTK/Core/Definitions/Devices/MixedRealityControllerVisualizationSetting.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public struct MixedRealityControllerVisualizationSetting
2121
/// <param name="controllerType">Controller Type to instantiate at runtime.</param>
2222
/// <param name="handedness">The designated hand that the device is managing.</param>
2323
/// <param name="overrideModel">The controller model prefab to be rendered.</param>
24+
[Obsolete("This constructor doesn't need to be called directly.")]
2425
public MixedRealityControllerVisualizationSetting(string description, Type controllerType, Handedness handedness = Handedness.None, GameObject overrideModel = null) : this()
2526
{
2627
this.description = description;

Assets/MRTK/Core/Providers/BaseController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,14 @@ public void AssignControllerMappings(MixedRealityInteractionMapping[] mappings)
234234
/// <returns>True if a model was successfully loaded or model rendering is disabled. False if a model tried to load but failed.</returns>
235235
protected virtual bool TryRenderControllerModel(Type controllerType, InputSourceType inputSourceType)
236236
{
237-
GameObject controllerModel = null;
238-
239237
if (GetControllerVisualizationProfile() == null ||
240238
!GetControllerVisualizationProfile().RenderMotionControllers)
241239
{
242240
return true;
243241
}
244242

243+
GameObject controllerModel = null;
244+
245245
// If a specific controller template wants to override the global model, assign that instead.
246246
if (IsControllerMappingEnabled() &&
247247
GetControllerVisualizationProfile() != null &&

Assets/MRTK/Providers/WindowsMixedReality/Shared/Extensions/WindowsExtensions.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
// Licensed under the MIT License.
33

44
#if (UNITY_WSA && DOTNETWINRT_PRESENT) || WINDOWS_UWP
5+
using Microsoft.MixedReality.Toolkit.Input;
56
using Microsoft.MixedReality.Toolkit.Utilities;
67
#if WINDOWS_UWP
8+
using Windows.Perception;
79
using Windows.UI.Input.Spatial;
810
#elif DOTNETWINRT_PRESENT
11+
using Microsoft.Windows.Perception;
912
using Microsoft.Windows.UI.Input.Spatial;
1013
#endif
1114
#endif // (UNITY_WSA && DOTNETWINRT_PRESENT) || WINDOWS_UWP
@@ -37,6 +40,61 @@ public static Handedness ToMRTKHandedness(this SpatialInteractionSourceHandednes
3740
return Handedness.None;
3841
}
3942
}
43+
44+
/// <summary>
45+
/// Tries to get an active SpatialInteractionSource with the corresponding handedness and input source type.
46+
/// </summary>
47+
/// <param name="handedness">The handedness of the source to get.</param>
48+
/// <param name="inputSourceType">The input source type of the source to get.</param>
49+
/// <returns>The input source or null if none could be found.</returns>
50+
public static SpatialInteractionSource GetSpatialInteractionSource(Handedness handedness, InputSourceType inputSourceType)
51+
{
52+
SpatialInteractionSourceHandedness sourceHandedness;
53+
switch (handedness)
54+
{
55+
default:
56+
sourceHandedness = SpatialInteractionSourceHandedness.Unspecified;
57+
break;
58+
case Handedness.Left:
59+
sourceHandedness = SpatialInteractionSourceHandedness.Left;
60+
break;
61+
case Handedness.Right:
62+
sourceHandedness = SpatialInteractionSourceHandedness.Right;
63+
break;
64+
}
65+
66+
SpatialInteractionSourceKind sourceKind;
67+
switch (inputSourceType)
68+
{
69+
default:
70+
sourceKind = SpatialInteractionSourceKind.Other;
71+
break;
72+
case InputSourceType.Controller:
73+
sourceKind = SpatialInteractionSourceKind.Controller;
74+
break;
75+
case InputSourceType.Hand:
76+
sourceKind = SpatialInteractionSourceKind.Hand;
77+
break;
78+
}
79+
80+
System.Collections.Generic.IReadOnlyList<SpatialInteractionSourceState> sourceStates =
81+
WindowsMixedRealityUtilities.SpatialInteractionManager?.GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(System.DateTimeOffset.UtcNow));
82+
83+
if (sourceStates == null)
84+
{
85+
return null;
86+
}
87+
88+
foreach (SpatialInteractionSourceState sourceState in sourceStates)
89+
{
90+
if (sourceState.Source.Handedness == sourceHandedness && sourceState.Source.Kind == sourceKind)
91+
{
92+
return sourceState.Source;
93+
}
94+
}
95+
96+
return null;
97+
}
4098
#endif // (UNITY_WSA && DOTNETWINRT_PRESENT) || WINDOWS_UWP
4199
}
42100
}

Assets/MRTK/Providers/WindowsMixedReality/Shared/MRTK.WMR.Shared.asmdef

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"name": "Microsoft.MixedReality.Toolkit.Providers.WindowsMixedReality.Shared",
33
"references": [
4-
"Microsoft.MixedReality.Toolkit"
4+
"Microsoft.MixedReality.Toolkit",
5+
"Microsoft.MixedReality.Toolkit.Gltf"
56
],
67
"includePlatforms": [
78
"Editor",
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.MixedReality.Toolkit.Utilities;
5+
6+
#if WINDOWS_UWP
7+
using Microsoft.MixedReality.Toolkit.Input;
8+
using Microsoft.MixedReality.Toolkit.Utilities.Gltf.Serialization;
9+
using System;
10+
using System.Collections.Generic;
11+
using System.Threading.Tasks;
12+
using UnityEngine;
13+
using Windows.Storage.Streams;
14+
using Windows.UI.Input.Spatial;
15+
#endif
16+
17+
namespace Microsoft.MixedReality.Toolkit.WindowsMixedReality
18+
{
19+
/// <summary>
20+
/// Queries the WinRT APIs for a renderable controller model.
21+
/// </summary>
22+
public class WindowsMixedRealityControllerModelProvider
23+
{
24+
public WindowsMixedRealityControllerModelProvider(Handedness handedness)
25+
{
26+
#if WINDOWS_UWP
27+
spatialInteractionSource = WindowsExtensions.GetSpatialInteractionSource(handedness, InputSourceType.Controller);
28+
#endif // WINDOWS_UWP
29+
}
30+
31+
#if WINDOWS_UWP
32+
private readonly SpatialInteractionSource spatialInteractionSource;
33+
34+
private static readonly Dictionary<string, GameObject> ControllerModelDictionary = new Dictionary<string, GameObject>(2);
35+
36+
/// <summary>
37+
/// Attempts to load the glTF controller model from the Windows SDK.
38+
/// </summary>
39+
/// <returns>The controller model as a GameObject or null if it was unobtainable.</returns>
40+
public async Task<GameObject> TryGenerateControllerModelFromPlatformSDK()
41+
{
42+
if (spatialInteractionSource == null)
43+
{
44+
return null;
45+
}
46+
47+
// See if we've generated this model before and if we can return it
48+
if (ControllerModelDictionary.TryGetValue(GenerateKey(spatialInteractionSource), out GameObject controllerModel))
49+
{
50+
controllerModel.SetActive(true);
51+
return controllerModel;
52+
}
53+
54+
Debug.Log("Trying to load controller model from platform SDK");
55+
byte[] fileBytes = null;
56+
57+
var controllerModelStream = await spatialInteractionSource.Controller.TryGetRenderableModelAsync();
58+
if (controllerModelStream == null ||
59+
controllerModelStream.Size == 0)
60+
{
61+
Debug.LogError("Failed to obtain controller model from driver");
62+
}
63+
else
64+
{
65+
fileBytes = new byte[controllerModelStream.Size];
66+
using (DataReader reader = new DataReader(controllerModelStream))
67+
{
68+
await reader.LoadAsync((uint)controllerModelStream.Size);
69+
reader.ReadBytes(fileBytes);
70+
}
71+
}
72+
73+
GameObject gltfGameObject = null;
74+
if (fileBytes != null)
75+
{
76+
Utilities.Gltf.Schema.GltfObject gltfObject = GltfUtility.GetGltfObjectFromGlb(fileBytes);
77+
gltfGameObject = await gltfObject.ConstructAsync();
78+
if (gltfGameObject != null)
79+
{
80+
ControllerModelDictionary.Add(GenerateKey(spatialInteractionSource), gltfGameObject);
81+
}
82+
}
83+
84+
return gltfGameObject;
85+
}
86+
87+
private string GenerateKey(SpatialInteractionSource spatialInteractionSource)
88+
{
89+
return spatialInteractionSource.Controller.VendorId + "/" + spatialInteractionSource.Controller.ProductId + "/" + spatialInteractionSource.Controller.Version + "/" + spatialInteractionSource.Handedness;
90+
}
91+
#endif // WINDOWS_UWP
92+
}
93+
}

Assets/MRTK/Providers/WindowsMixedReality/Shared/WindowsMixedRealityControllerModelProvider.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.

0 commit comments

Comments
 (0)