本日はHoloLens 2の表現の調査枠です。
昨日指の伸びを検知するジェスチャー判定の機能を作成しました。
本日はさらに改造して手の平の向きに合わせてイベントを発動できるようにします。
〇手の向きを検知する
今回はHandTrackingで検知できるJointの中からPalm(手のひら)を使用します。

Palmは手のひらを検知しているため、Palmのもつ開店情報はそれすなわち手自体の向きに相当します。
昨日のコードを編集しました。
void Update()
{
handdetected = HandJointUtils.FindHand(handType)?.TryGetJoint(TrackedHandJoint.Palm, out MixedRealityPose PalmPose);
if ( handdetected != null&& handdetected==true && HanddirDetected())
{
if (indexfingerDetected())
{
IndexFingerDetectEvent.Invoke();
}
else
{
Debug.Log("b");
IndexFingerLostEvent.Invoke();
}
if (middlefingerDetected())
{
Debug.Log("c");
MiddleFingerDetectEvent.Invoke();
}
else
{
Debug.Log("d");
MiddleFingerLostEvent.Invoke();
}
}
}
private bool HanddirDetected()
{
var jointedHand = HandJointUtils.FindHand(handType);
if (jointedHand.TryGetJoint(TrackedHandJoint.Palm,out MixedRealityPose palmPose))
{
if (Vector3.Angle(palmPose.Up, CameraCache.Main.transform.forward) < facingThreshold)
{
return true;
}
}
return false;
}
Vector3.Angleは二点間のベクトルの角度をfloat型で返します。ここではPalmの鉛直軸と実行中のカメラ(=ユーザー)の角度を求め、facingThresholdよりも小さい角度である場合Trueを返します。
つまり、Palmのup(鉛直軸)というのはそのまま手の向きに相当するので、手を向けている場合Trueになるという処理に相当します。
以上でジェスチャー判定に手の向きという条件を追加できました。
MixedRealityPoseは複数個所に当たって使用するため読みやすいようにコードを整理する必要がありそうです。
〇コード全文
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit;
using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit.Utilities;
using UnityEngine.Events;
using UnityEngine.XR;
public class FingerDitected : MonoBehaviour
{
[SerializeField,Header("Target"),Tooltip("Serect Detect Hands")]
Handedness handType;
[SerializeField,Range(0,90),Tooltip("Index Finger")]
private float indexThreshold = 5;
[SerializeField,Range(0,90)]
private float middleThreshold = 5;
[SerializeField, Range(0, 90)]
private float facingThreshold;
[SerializeField,Header("Events")]
UnityEvent IndexFingerDetectEvent;
[SerializeField]
UnityEvent IndexFingerLostEvent;
[SerializeField]
UnityEvent MiddleFingerDetectEvent;
[SerializeField]
UnityEvent MiddleFingerLostEvent;
private bool? handdetected;
// Start is called before the first frame update
// Update is called once per frame
void Update()
{
handdetected = HandJointUtils.FindHand(handType)?.TryGetJoint(TrackedHandJoint.Palm, out MixedRealityPose PalmPose);
if ( handdetected != null&& handdetected==true && HanddirDetected())
{
if (indexfingerDetected())
{
IndexFingerDetectEvent.Invoke();
}
else
{
Debug.Log("b");
IndexFingerLostEvent.Invoke();
}
if (middlefingerDetected())
{
Debug.Log("c");
MiddleFingerDetectEvent.Invoke();
}
else
{
Debug.Log("d");
MiddleFingerLostEvent.Invoke();
}
}
}
private bool HanddirDetected()
{
var jointedHand = HandJointUtils.FindHand(handType);
if (jointedHand.TryGetJoint(TrackedHandJoint.Palm,out MixedRealityPose palmPose))
{
if (Vector3.Angle(palmPose.Up, CameraCache.Main.transform.forward) < facingThreshold)
{
return true;
}
}
return false;
}
private bool indexfingerDetected()
{
var jointedHand = HandJointUtils.FindHand(handType);
if (jointedHand.TryGetJoint(TrackedHandJoint.Palm,out MixedRealityPose PalmPose))
{
//各関節のpose
MixedRealityPose indexTipPose,indexDistalPose,IndexKnucklePose,indexMiddlePose;
if(jointedHand.TryGetJoint(TrackedHandJoint.IndexTip,out indexTipPose)&& jointedHand.TryGetJoint(TrackedHandJoint.IndexDistalJoint,out indexDistalPose)&&jointedHand.TryGetJoint(TrackedHandJoint.IndexMiddleJoint,out indexMiddlePose)&& jointedHand.TryGetJoint(TrackedHandJoint.IndexKnuckle,out IndexKnucklePose))
{
Vector3 hoge = IndexKnucklePose.Position - PalmPose.Position;
Vector3 hogege = indexMiddlePose.Position - IndexKnucklePose.Position;
Vector3 hogegege = indexDistalPose.Position - indexMiddlePose.Position;
Vector3 ho = indexTipPose.Position - indexDistalPose.Position;
float c = Vector3.Angle(PalmPose.Position, hoge);
float d = Vector3.Angle(hoge, hogege);
float e = Vector3.Angle(hogege, hogegege);
float f = Vector3.Angle(hogegege, ho);
float aba = (Mathf.Abs(d) + Mathf.Abs(e) + Mathf.Abs(f)) / 3;
if (aba < indexThreshold)
{
return true;
}
}
}
return false;
}
private bool middlefingerDetected()
{
var jointedHand = HandJointUtils.FindHand(handType);
if (jointedHand.TryGetJoint(TrackedHandJoint.Palm, out MixedRealityPose PalmPose))
{
MixedRealityPose middleTipsPose,middleDistalPose, middleKnucklePose,middleMiddlePose;
if (jointedHand.TryGetJoint(TrackedHandJoint.MiddleTip, out middleTipsPose) &&
jointedHand.TryGetJoint(TrackedHandJoint.MiddleDistalJoint, out middleDistalPose) &&
jointedHand.TryGetJoint(TrackedHandJoint.MiddleKnuckle, out middleKnucklePose)&&jointedHand.TryGetJoint(TrackedHandJoint.MiddleMiddleJoint,out middleMiddlePose))
{
Vector3 hoge = middleKnucklePose.Position - PalmPose.Position;
Vector3 hogege = middleMiddlePose.Position - middleKnucklePose.Position;
Vector3 hogegege = middleDistalPose.Position - middleMiddlePose.Position;
Vector3 ho = middleTipsPose.Position - middleDistalPose.Position;
float c = Vector3.Angle(PalmPose.Position, hoge);
float d = Vector3.Angle(hoge, hogege);
float e = Vector3.Angle(hogege, hogegege);
float f = Vector3.Angle(hogegege, ho);
float aba = (Mathf.Abs(d) + Mathf.Abs(e) + Mathf.Abs(f)) / 3;
if (aba < middleThreshold)
{
return true;
}
}
}
return false;
}
}