HoloLens 2から取得可能になったHand Jointの利用方法の解説をします.
HoloLens 2のHand情報
HoloLens 2からハンドトラッキングが強化されAirTapポーズ以外でもトラッキングが行えるようになりました.
また取得できるトラッキング情報もハンド位置のみから
左右の識別
回転情報
関節の位置,回転情報
形状メッシュ情報
が取得できるようになりました.
今回はHand Jointを取得するまでを行います.
開発環境
取得手順
Unityのプロジェクトの設定は前回のHoloLens 2で利用できるジェスチャー入力について(Unity 2018編) の設定を参考にしてください.
Hand Joint情報はUnityの関数からは取得できないためUWP関数から取得する必要があります.
1 2 3 4 5 6 7
#if WINDOWS_UWP
using UnityEngine.XR.WSA;
using System.Runtime.InteropServices;
using Windows.Perception.Spatial;
using Windows.Perception.People;
using Windows.UI.Input.Spatial;
#endif
Unityで利用できないUWP関数はWINDOWS_UWP
で切り分けを行い,UnityのThreadで取得できない機能はInvokeOnUIThread
でThreadを変更しておく必要があります.
Hand Jointは関節位置HandJointKind
とPose情報JointPose
をSpatialInteractionManager
のイベント内で取得することができます.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
void Start()
{
#if WINDOWS_UWP
handJoints = new HandJointKind[]
{
HandJointKind.Palm,
HandJointKind.Wrist,
HandJointKind.ThumbMetacarpal,
HandJointKind.ThumbProximal,
HandJointKind.ThumbDistal,
HandJointKind.ThumbTip,
HandJointKind.IndexMetacarpal,
HandJointKind.IndexProximal,
HandJointKind.IndexIntermediate,
HandJointKind.IndexDistal,
HandJointKind.IndexTip,
HandJointKind.MiddleMetacarpal,
HandJointKind.MiddleProximal,
HandJointKind.MiddleIntermediate,
HandJointKind.MiddleDistal,
HandJointKind.MiddleTip,
HandJointKind.RingMetacarpal,
HandJointKind.RingProximal,
HandJointKind.RingIntermediate,
HandJointKind.RingDistal,
HandJointKind.RingTip,
HandJointKind.LittleMetacarpal,
HandJointKind.LittleProximal,
HandJointKind.LittleIntermediate,
HandJointKind.LittleDistal,
HandJointKind.LittleTip
};
jointPoses = new JointPose[handJoints.Length];
rightHandJoints = new GameObject[handJoints.Length];
leftHandJoints = new GameObject[handJoints.Length];
for (int i = 0; i < rightHandJoints.Length; i++)
{
rightHandJoints[i] = GameObject.CreatePrimitive(PrimitiveType.Cube);
rightHandJoints[i].transform.localScale = Vector3.one * 0.01f;
leftHandJoints[i] = GameObject.CreatePrimitive(PrimitiveType.Cube);
leftHandJoints[i].transform.localScale = Vector3.one * 0.01f;
}
SpatialInteractionManager spatialInteraction = null;
spatialCoordinateSystem = Marshal.GetObjectForIUnknown(WorldManager.GetNativeISpatialCoordinateSystemPtr()) as SpatialCoordinateSystem;
UnityEngine.WSA.Application.InvokeOnUIThread(() =>
{
spatialInteraction = SpatialInteractionManager.GetForCurrentView();
}, true);
spatialInteraction.SourceUpdated += SpatialInteraction_SourceUpdated;
#endif
}
左右の手の判別と合わせることで各関節の位置と回転情報を取得することができます.
ただしUnityのTransformやGameObjectの値を入れる場合には,InvokeOnAppThread
を利用してUnityのThread内で処理を行う必要があります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
private void SpatialInteraction_SourceUpdated(SpatialInteractionManager sender, SpatialInteractionSourceEventArgs args)
{
var item = args.State;
var handPose = item.TryGetHandPose();
if (handPose != null && handPose.TryGetJoints(spatialCoordinateSystem, handJoints, jointPoses))
{
for (int i = 0; i < handJoints.Length; i++)
{
var joint = i;
var pos = jointPoses[(int)handJoints[joint]].Position;
var rot = jointPoses[(int)handJoints[joint]].Orientation;
if (item.Source.Handedness == SpatialInteractionSourceHandedness.Right)
{
UnityEngine.WSA.Application.InvokeOnAppThread(() =>
{
rightHandJoints[joint].transform.position = new Vector3(pos.X, pos.Y, -pos.Z);
rightHandJoints[joint].transform.rotation = new Quaternion(-rot.X, -rot.Y, rot.Z, rot.W);
}, false);
}
else if (item.Source.Handedness == SpatialInteractionSourceHandedness.Left)
{
UnityEngine.WSA.Application.InvokeOnAppThread(() =>
{
leftHandJoints[joint].transform.position = new Vector3(pos.X, pos.Y, -pos.Z);
leftHandJoints[joint].transform.rotation = new Quaternion(-rot.X, -rot.Y, rot.Z, rot.W);
}, false);
}
}
}
}
各Hand Jointの位置と回転を取得してCubeとして表示するサンプルプロジェクトを公開しています.
また動作時の動画が以下になります.
GitHub : HoloLens2HandJointSampleWithUnity
VIDEO
Windows XR Plugin対応
WorldManager.GetNativeISpatialCoordinateSystemPtr()
はUnityEngine.XR.WSA
の機能なのでUnity 2019以降のWindows XR Plugin
では利用できません.
代わりにWindowsMREnvironment.OriginSpatialCoordinateSystem
からSpatialCoordinateSystemを取得することができます.
Windows XR Plugin
の設定はHoloLens 2で利用できるジェスチャー入力について(Unity 2019編) へ
サンプルプロジェクト内でもUnity 2019以降はWindows XR Plugin
に対応するようにしています.
GitHub : HoloLens2HandJointSampleWithUnity
まとめ
UnityからHoloLens 2のHand Joint情報が取得できる
Unityの機能では取得できないのでWINDOWS_UWP
で切り分けを行う
UnityEngine.XR.WSA
とWindows XR Plugin
で利用できる関数が一部異なる
人差し指の位置が認識できるとオブジェクトをツンツンできる
頑張ればこんなのができる