Skip to content

Commit 5ff69c1

Browse files
committed
Support for Generic Hands models from the WebXR Input Profiles
1 parent 9c75443 commit 5ff69c1

File tree

10 files changed

+282
-32
lines changed

10 files changed

+282
-32
lines changed

MainProject/Packages/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
}
1111
],
1212
"dependencies": {
13-
"com.de-panther.webxr-input-profiles-loader": "0.3.5",
13+
"com.de-panther.webxr-input-profiles-loader": "0.3.6",
1414
"com.unity.ide.rider": "2.0.5",
1515
"com.unity.ide.vscode": "1.2.3",
1616
"com.unity.test-framework": "1.1.16",

MainProject/Packages/packages-lock.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"dependencies": {
33
"com.atteneder.gltfast": {
4-
"version": "3.0.2",
4+
"version": "3.2.1",
55
"depth": 1,
66
"source": "registry",
77
"dependencies": {
@@ -21,12 +21,12 @@
2121
}
2222
},
2323
"com.de-panther.webxr-input-profiles-loader": {
24-
"version": "0.3.5",
24+
"version": "0.3.6",
2525
"depth": 0,
2626
"source": "registry",
2727
"dependencies": {
2828
"com.unity.nuget.newtonsoft-json": "2.0.0",
29-
"com.atteneder.gltfast": "3.0.2"
29+
"com.atteneder.gltfast": "3.2.1"
3030
},
3131
"url": "https://package.openupm.com"
3232
},

Packages/webxr-interactions/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Added
9+
- Support for Generic Hands models from the WebXR Input Profiles.
10+
11+
### Changed
12+
- Minimum WebXR Input Profiles Loader version 0.3.6.
813

914
## [0.9.0] - 2021-04-16
1015
### Changed

Packages/webxr-interactions/Runtime/Prefabs/WebXRCameraSet.prefab

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ Transform:
283283
m_Children:
284284
- {fileID: 4008237015318879989}
285285
- {fileID: 1218315907877956796}
286+
- {fileID: 2202373014578844308}
286287
m_Father: {fileID: 4545079059221816}
287288
m_RootOrder: 0
288289
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -351,6 +352,7 @@ MonoBehaviour:
351352
useInputProfile: 1
352353
inputProfileObject: {fileID: 1611361787474004}
353354
inputProfileModelParent: {fileID: 1469228564561163144}
355+
inputProfileHandModelParent: {fileID: 3331348236738357118}
354356
--- !u!114 &7185579886917944061
355357
MonoBehaviour:
356358
m_ObjectHideFlags: 0
@@ -496,6 +498,7 @@ Transform:
496498
m_Children:
497499
- {fileID: 3110396931964762061}
498500
- {fileID: 3819867499605581648}
501+
- {fileID: 1956285881968495143}
499502
m_Father: {fileID: 4545079059221816}
500503
m_RootOrder: 1
501504
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -564,6 +567,7 @@ MonoBehaviour:
564567
useInputProfile: 1
565568
inputProfileObject: {fileID: 1611361787474004}
566569
inputProfileModelParent: {fileID: 599836867309221058}
570+
inputProfileHandModelParent: {fileID: 8661450511316122934}
567571
--- !u!114 &1966769163579045322
568572
MonoBehaviour:
569573
m_ObjectHideFlags: 0
@@ -837,6 +841,36 @@ Camera:
837841
m_OcclusionCulling: 1
838842
m_StereoConvergence: 10
839843
m_StereoSeparation: 0.022
844+
--- !u!1 &3331348236738357118
845+
GameObject:
846+
m_ObjectHideFlags: 0
847+
m_CorrespondingSourceObject: {fileID: 0}
848+
m_PrefabInstance: {fileID: 0}
849+
m_PrefabAsset: {fileID: 0}
850+
serializedVersion: 6
851+
m_Component:
852+
- component: {fileID: 2202373014578844308}
853+
m_Layer: 0
854+
m_Name: HandInputModel
855+
m_TagString: Untagged
856+
m_Icon: {fileID: 0}
857+
m_NavMeshLayer: 0
858+
m_StaticEditorFlags: 0
859+
m_IsActive: 1
860+
--- !u!4 &2202373014578844308
861+
Transform:
862+
m_ObjectHideFlags: 0
863+
m_CorrespondingSourceObject: {fileID: 0}
864+
m_PrefabInstance: {fileID: 0}
865+
m_PrefabAsset: {fileID: 0}
866+
m_GameObject: {fileID: 3331348236738357118}
867+
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
868+
m_LocalPosition: {x: 0, y: 0, z: 0}
869+
m_LocalScale: {x: 1, y: 1, z: 1}
870+
m_Children: []
871+
m_Father: {fileID: 4427160273819458}
872+
m_RootOrder: 2
873+
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
840874
--- !u!1 &3858442981242374931
841875
GameObject:
842876
m_ObjectHideFlags: 0
@@ -1043,3 +1077,33 @@ Camera:
10431077
m_OcclusionCulling: 1
10441078
m_StereoConvergence: 10
10451079
m_StereoSeparation: 0.022
1080+
--- !u!1 &8661450511316122934
1081+
GameObject:
1082+
m_ObjectHideFlags: 0
1083+
m_CorrespondingSourceObject: {fileID: 0}
1084+
m_PrefabInstance: {fileID: 0}
1085+
m_PrefabAsset: {fileID: 0}
1086+
serializedVersion: 6
1087+
m_Component:
1088+
- component: {fileID: 1956285881968495143}
1089+
m_Layer: 0
1090+
m_Name: HandInputModel
1091+
m_TagString: Untagged
1092+
m_Icon: {fileID: 0}
1093+
m_NavMeshLayer: 0
1094+
m_StaticEditorFlags: 0
1095+
m_IsActive: 1
1096+
--- !u!4 &1956285881968495143
1097+
Transform:
1098+
m_ObjectHideFlags: 0
1099+
m_CorrespondingSourceObject: {fileID: 0}
1100+
m_PrefabInstance: {fileID: 0}
1101+
m_PrefabAsset: {fileID: 0}
1102+
m_GameObject: {fileID: 8661450511316122934}
1103+
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
1104+
m_LocalPosition: {x: 0, y: 0, z: 0}
1105+
m_LocalScale: {x: 1, y: 1, z: 1}
1106+
m_Children: []
1107+
m_Father: {fileID: 4446684710817404}
1108+
m_RootOrder: 2
1109+
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

Packages/webxr-interactions/Runtime/Scripts/ControllerInteraction.cs

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,19 @@ public class ControllerInteraction : MonoBehaviour
3030

3131
private GameObject[] handJointsVisuals = new GameObject[25];
3232
private Dictionary<int, Transform> handJoints = new Dictionary<int, Transform>();
33+
public GameObject inputProfileHandModelParent;
3334

3435
#if WEBXR_INPUT_PROFILES
3536
private InputProfileLoader inputProfileLoader;
3637
private InputProfileModel inputProfileModel;
3738
private bool hasProfileList = false;
3839
private bool loadedModel = false;
3940
private string loadedProfile = null;
41+
42+
private InputProfileModel inputProfileHandModel;
43+
private bool loadedHandModel = false;
44+
private string loadedHandProfile = null;
45+
private Dictionary<int, Transform> handModelJoints = new Dictionary<int, Transform>();
4046
#endif
4147

4248
private void Awake()
@@ -206,6 +212,27 @@ private void SetHandJointsVisible(bool visible)
206212
{
207213
handJointsVisible = visible;
208214
Drop();
215+
#if WEBXR_INPUT_PROFILES
216+
// We want to use WebXR Input Profiles
217+
if (visible && useInputProfile)
218+
{
219+
if (inputProfileHandModel != null && loadedHandModel)
220+
{
221+
// There's a loaded Input Profile Model
222+
inputProfileHandModelParent.SetActive(true);
223+
return;
224+
}
225+
else if (inputProfileHandModel == null)
226+
{
227+
// There's no loaded Input Profile Model and it's not in loading process
228+
LoadHandInputProfile();
229+
}
230+
}
231+
else
232+
{
233+
inputProfileHandModelParent.SetActive(false);
234+
}
235+
#endif
209236
foreach (var visual in handJointsVisuals)
210237
{
211238
visual?.SetActive(visible);
@@ -224,7 +251,25 @@ private void OnHandUpdate(WebXRHandData handData)
224251
}
225252
Quaternion rotationOffset = Quaternion.Inverse(handData.joints[0].rotation);
226253

227-
for (int i = 0; i <= WebXRHandData.LITTLE_PHALANX_TIP; i++)
254+
#if WEBXR_INPUT_PROFILES
255+
if (useInputProfile && loadedHandModel)
256+
{
257+
for (int i = 0; i <= (int)WebXRHandJoint.pinky_finger_tip; i++)
258+
{
259+
if (handData.joints[i].enabled)
260+
{
261+
if (handModelJoints.ContainsKey(i))
262+
{
263+
handModelJoints[i].localPosition = rotationOffset * (handData.joints[i].position - handData.joints[0].position);
264+
handModelJoints[i].localRotation = rotationOffset * handData.joints[i].rotation;
265+
}
266+
}
267+
}
268+
return;
269+
}
270+
#endif
271+
272+
for (int i = 0; i <= (int)WebXRHandJoint.pinky_finger_tip; i++)
228273
{
229274
if (handData.joints[i].enabled)
230275
{
@@ -284,6 +329,13 @@ private void LoadInputProfile()
284329
}
285330
}
286331

332+
private void LoadHandInputProfile()
333+
{
334+
// Start loading the generic hand profile
335+
loadedHandProfile = "generic-hand";
336+
inputProfileLoader.LoadProfile(new string[] {loadedHandProfile}, OnHandProfileLoaded);
337+
}
338+
287339
private void OnProfileLoaded(bool success)
288340
{
289341
if (success)
@@ -293,6 +345,15 @@ private void OnProfileLoaded(bool success)
293345
// Nothing to do if profile didn't load
294346
}
295347

348+
private void OnHandProfileLoaded(bool success)
349+
{
350+
if (success)
351+
{
352+
LoadHandInputModel();
353+
}
354+
// Nothing to do if profile didn't load
355+
}
356+
296357
private void LoadInputModel()
297358
{
298359
inputProfileModel = inputProfileLoader.LoadModelForHand(
@@ -306,6 +367,14 @@ private void LoadInputModel()
306367
}
307368
}
308369

370+
private void LoadHandInputModel()
371+
{
372+
inputProfileHandModel = inputProfileLoader.LoadModelForHand(
373+
loadedHandProfile,
374+
(InputProfileLoader.Handedness)controller.hand,
375+
HandleHandModelLoaded);
376+
}
377+
309378
private void HandleModelLoaded(bool success)
310379
{
311380
loadedModel = success;
@@ -333,6 +402,44 @@ private void HandleModelLoaded(bool success)
333402
}
334403
}
335404

405+
private void HandleHandModelLoaded(bool success)
406+
{
407+
loadedHandModel = success;
408+
if (loadedHandModel)
409+
{
410+
// Set parent only after successful loading, to not interupt loading in case of disabled object
411+
var inputProfileModelTransform = inputProfileHandModel.transform;
412+
inputProfileModelTransform.SetParent(inputProfileHandModelParent.transform);
413+
inputProfileModelTransform.localPosition = Vector3.zero;
414+
inputProfileModelTransform.localRotation = Quaternion.identity;
415+
inputProfileModelTransform.localScale = Vector3.one;
416+
for (int i = 0; i <= (int)WebXRHandJoint.pinky_finger_tip; i++)
417+
{
418+
handModelJoints.Add(i, inputProfileHandModel.GetChildTransform(((WebXRHandJoint)i).ToString().Replace('_','-')));
419+
// It took at least one frame with hand data, there should be hand joint transform
420+
if (handJoints.ContainsKey(i))
421+
{
422+
handModelJoints[i].SetPositionAndRotation(handJoints[i].position, handJoints[i].rotation);
423+
var collider = handModelJoints[i].gameObject.AddComponent<SphereCollider>();
424+
collider.radius = handJoints[i].localScale.x;
425+
collider.isTrigger = true;
426+
}
427+
}
428+
if (handJointsVisible)
429+
{
430+
inputProfileHandModelParent.SetActive(true);
431+
foreach (var visual in handJointsVisuals)
432+
{
433+
visual?.SetActive(false);
434+
}
435+
}
436+
}
437+
else
438+
{
439+
Destroy(inputProfileHandModel.gameObject);
440+
}
441+
}
442+
336443
private void UpdateModelInput()
337444
{
338445
for (int i = 0; i < 6; i++)

Packages/webxr-interactions/Runtime/Scripts/WebXR.Interactions.asmdef

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"versionDefines": [
1515
{
1616
"name": "com.de-panther.webxr-input-profiles-loader",
17-
"expression": "0.3.5",
17+
"expression": "0.3.6",
1818
"define": "WEBXR_INPUT_PROFILES"
1919
}
2020
],

0 commit comments

Comments
 (0)