MagicLeapToolkitに依存しない形でのハンドポインタ作成
とりあえず以前作成したQiitaのアドベントカレンダーように作成したハンドポインタをベースに作るか
MagicLeapToolKitはもう一年以上更新されてないような感じだし...
MRTK使ってもいいしれんけどなんとなく自作したいよね
とりあえずハンドポインター表示までは出来た、Eyeトラッキングは今回は使わないようにしよう
MainCameraの向きをある程度ポインタの向きに反映したほうがいいかも?
MLHandTrackingのHandKeyPoseはこんな感じの定義
/// <summary>
/// Static key pose types which are available when both hands are separated.
/// </summary>
public enum HandKeyPose
{
/// <summary>
/// Index finger.
/// </summary>
Finger,
/// <summary>A
/// A closed fist.
/// </summary>
Fist,
/// <summary>
/// A pinch.
/// </summary>
Pinch,
/// <summary>
/// A closed fist with the thumb pointed up.
/// </summary>
Thumb,
/// <summary>
/// An L shape
/// </summary>
L,
/// <summary>
/// An open hand.
/// </summary>
OpenHand = 5,
/// <summary>
/// A pinch with all fingers, except the index finger and the thumb, extended out.
/// </summary>
Ok,
/// <summary>
/// A rounded 'C' alphabet shape.
/// </summary>
C,
/// <summary>
/// No pose was recognized.
/// </summary>
NoPose,
/// <summary>
/// No hand was detected. Should be the last pose.
/// </summary>
NoHand
}
HandPoseのイベントの取得はこんな感じ
MLHandTracking.KeyPoseManager.OnKeyPoseBegin += (pose, type) =>
{
Debug.Log($"Begin pose : {pose} | type {type}");
};
MLHandTracking.KeyPoseManager.OnKeyPoseEnd += (pose, type) =>
{
Debug.Log($"End pose : {pose} | type {type}");
};
まずは順当にMLHandTracking使うようにするか...
疎結合とかその辺は追々考えよう
できるだけ外部ライブラリを利用しないシンプルなつくりにしたい...
親指と人差し指の付け根の中間にするか
親指の先と人差し指の先の中間にするか ( こっちの方がOculusQuest2のハンドトラッキングに近い )
Questの形式を真似したらPinchのジェスチャでのStartPointが結構大きくぶれる -> Rayが大きくぶれるから取りやめ、人差し指と親指の根元の中間をStartPointとした
選択時、選択中はPointerSelectクラス( 仮 )で他クラスから参照できるようにする?
そういえばすでにSelectedObjectなるものを作成していたな...それにデータを持たせるか
とりまこんな感じ
/// <summary>
/// HandPointerで選択したものをカプセル化したクラス.
/// </summary>
public class SelectedObject
{
public bool IsHit => Hit.collider != null;
public RaycastHit Hit { get; }
public Vector3 Position => Hit.point;
public GameObject Object => Hit.collider.gameObject;
public HandPointer.HandPointerState State { get; }
public SelectedObject(
RaycastHit hit,
HandPointer.HandPointerState state)
{
Hit = hit;
State = state;
}
}
SelectedObjectがStateを持つ必要ないな、OnSelectBegin, OnSelectContinue, OnSelectEndのイベントを作成したからそいつらが外部から見た選択状態になる
内部的には
public enum HandPointerState
{
NotSelected,
Selected,
SelectContinue
}
こんな感じでステートを保持しておく、今これは生のフィールドだけど値オブジェクトにしてもいいかもな
多分一通り移植は完了したな
一旦今のチケットはこれで完了としてdevelopにマージしよう
現時点でのシーンの最小構成
HandPointerの各種パラメータはデフォルトで扱える、カスタムしたいときは適当にいじる感じ
MainCameraはとりあえず参照つけなくてもスクリプトの中でMainCameraを探すからとりあえずは大丈夫だと思う
シーンに配置されているMain CameraオブジェクトはMagicLeapのMain Cameraプレハブを配置してる
まだ選択したオブジェクトを移動するといった機能は実装していない、どうやって実装しようかは今の所まだ決めてない
OnSelectContinueのときにLock的なことをするかはまだ未定、このへんはHoloLensの動作とかを参考にしてみるか
HandPointer.cs一つで両手を管理する方法をやめて1コンポーネント1ハンドにした
理由としては片方の手だけ利用したいとかの場合や場合分けの分岐が増え、コード量が増加するためインスペクタで選択したLeft,Rightに合わせて使うHandPointerを生成するようにした
HandPointerを二つ利用すれば両手での操作も可能
現在のHandPointerのパラメータ、画像のInspectorでは両手を使うためにHandPointerコンポーネントを二つ利用している
あとできるだけ生のMLHandTracking周りのクラスをHandPointerで扱いたくはない気がする
今のHandPointerクラスがRaycast飛ばしてhitしたオブジェクトを返す的な動作はなんか違和感HandPointerCursorがRayを飛ばしてhitしたものをイベントとかで返す形が自然な気がする
Handのボーンを表示する仕組みも作っておく必要がありそう、MagicLeapToolKitには似たようなやつがあったけどあれはシーン上にオブジェクトをぶちまけてたからできればHand > 各関節 みたいにコンパクトに収めたいところ