MRが楽しい

MRやVRについて学習したことを書き残す

MRTK v2のドキュメントを少しずつ読み解く Eye-supported target selection その1

本日は MRTKv2 の調査枠です。
MRTKv2 の Guides ドキュメントを少しずつ読み進めていきます。

MRTKv2のGuidesドキュメント

以下のドキュメントを読み進めていきます。
microsoft.github.io

以下のページでは有志による本ドキュメントの日本語翻訳が行われています。
投稿時点でこちらで未翻訳、または著者が興味のある部分について記事にしていきます。
hololabinc.github.io

本記事では以下のページを読み進めます。
microsoft.github.io
f:id:bluebirdofoz:20200225092304j:plain

Eye-supported target selection

f:id:bluebirdofoz:20200225092418j:plain

このページでは視線データにアクセスするための様々なオプションと、MRTK でターゲットを選択するための視線固有のイベントについて説明します。
アイトラッキングを使用すると、ユーザーが見ているものに関する情報と、ハンドトラッキングや音声コマンドなどを組み合わせてターゲットを選択することができます。
・視線と音声コマンド「Select」(デフォルトコマンド)
・視線と音声コマンド「Explode」または「Pop」(カスタムコマンド)
・視線と Bluetooth ボタン
・視線とピンチ操作(親指と人差し指を合わせる)

視線を使用してホログラフィックコンテンツを選択するにはいくつかのオプションがあります。

1.プライマリフォーカスポインターを使用します。

これは優先的なカーソルとして利用できます。デフォルトでは手が表示されている場合、プライマリフォーカスポインターはハンドレイになります。
手が見えない場合、優先順位の高いポインターはヘッドレイまたは視線になります。
したがってハンドレイが使用される場合、ヘッドレイまたは視線のカーソル入力が抑制されることに注意してください。

例えば、ユーザーが遠くのホログラフィックボタンを選択するシーンを想定します。
開発者として、ユーザーが様々な条件でこのタスクを達成できる柔軟なソリューションの提供を検討してみます。

・ボタンまで歩いて押す
・遠くから見て「Select」と言う
・ハンドレイを使用してボタンをターゲットにピンチを実行します。
この場合、最も柔軟なソリューションはプライマリフォーカスハンドラーを使用することです。
ハンドレイが有効になっている場合、ヘッドレイまたは視線のフォーカスポインターは手が見えると無効になります。

重要

ハンドレイが有効になっている場合、ヘッドレイまたは視線のフォーカスポインターは、手が見えるとすぐに無効になります。
「視線とピンチ」インタラクションをサポートする場合は、ハンドレイを無効にする必要があります。
アイトラッキングサンプルシーンではハンドレイを無効にして、目線と手の動きを使用してより豊かなインタラクションを紹介できるようにしています。

2.視線とハンドレイの両方を同時に使用します。

特定のイベントをトリガーするとき、複数の遠距離相互作用を同時に使用できるフォーカスポインターのタイプを具体的にしたい場合があります。

アプリではユーザーは遠距離レイを使用して、ホログラフィックを操作できます。
例えば、遠くのホログラフィックエンジンパーツを掴んで所定の位置に保持できます。
その間、ユーザーはいくつかの指示を実行し、いくつかのチェックボックスをオフにして進行状況を記録するとします。
ユーザーの手が塞がっていない場合はチェックボックスをタッチするか、ハンドレイを使用して選択するのが直感的です。
ただし、ホログラフィックエンジンの一部を所定の位置に保持する場合のように、ユーザーの両手が塞がっていることがあります。
この場合、ユーザーが視線を使用して指示をシームレスにスクロールできるようにし、チェックボックスを見て「check it!」と言います。

これを有効にするには、MRTK FocusHandlers から独立した EyeTrackingTarget スクリプトを使用する必要があります。
これについては以下で詳しく説明します。

1.汎用フォーカスおよびポインターハンドラーを使用する

アイトラッキングが正しく設定されている場合、ユーザーが目線でホログラムを選択できるようにする手順は他のフォーカス入力と同じです。
これには大きな利点があります。
コードに手を加えずに、ユーザーのニーズに応じて MRTK 入力ポインタープロファイルでメインフォーカスタイプを定義できます。
これにより、遠方の相互作用のためにハンドレイを目線の照準に置き換えたりすることなく、操作を切り替えることができます。

ホログラムに焦点を当てる

ホログラムの焦点が合っていることを検出するには IMixedRealityFocusHandler インターフェイスを使用します。
これは OnFocusEnter と OnFocusExit の2つのインターフェイスメンバーを提供します。

以下は見たときにホログラムの色を変更する ColorTap.cs の簡単な例です。

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler
{
    void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
    {
        material.color = color_OnHover;
    }

    void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
    {
        material.color = color_IdleState;
    }
    ...
}

フォーカスされたホログラムを選択する

フォーカスされたホログラムを選択するには PointerHandler を使用して入力イベントをリッスンします。
例えば IMixedRealityPointerHandler を追加すると、単純なポインター入力に反応するようになります。
IMixedRealityPointerHandler のインターフェイスは以下の3つのインターフェイスを実装する必要があります。
・OnPointerUp
・OnPointerDown
・OnPointerClicked

以下の例ではホログラムを見た状態で、ピンチ操作を行うか「Select」と言うことでホログラムの色を変更します。

イベントをトリガーするために必要なアクションは eventData.MixedRealityInputAction == selectActionに よって定義されます。
UnityEditor 上で selectAction のタイプを設定できます。デフォルトでは「Select」アクションです。
利用可能な MixedRealityInputActions のタイプは、プロファイルの Input -> Input Action から構成できます。

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
    // Allow for editing the type of select action in the Unity Editor.
    [SerializeField]
    private MixedRealityInputAction selectAction = MixedRealityInputAction.None;
    ...

    void IMixedRealityPointerHandler.OnPointerUp(MixedRealityPointerEventData eventData)
    {
        if (eventData.MixedRealityInputAction == selectAction)
        {
            material.color = color_OnHover;
        }
    }

    void IMixedRealityPointerHandler.OnPointerDown(MixedRealityPointerEventData eventData)
    {
        if (eventData.MixedRealityInputAction == selectAction)
        {
            material.color = color_OnSelect;
        }
    }

    void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData) { }
}

視線固有のBaseEyeFocusHandler

視線は他のポインター入力とは大きく異なります。
このため、視線がプライマリ入力ポインタである場合にのみ、フォーカス入力に反応するようにしたい場合があります。

これを実現するには、アイトラッキングに固有で、BaseFocusHandler から派生した BaseEyeFocusHandler を使用します。
前述したように、視線が現在のプライマリ入力ポインタである場合(アクティブなハンドレイがない場合)にのみトリガーされます。
詳細については How to support eye gaze + hand gestures をご覧ください。
microsoft.github.io

EyeTrackingDemo-03-Navigation.unity の例を次に示します。
このデモではオブジェクトのどの部分を見ているかに応じて回転する2つの3Dホログラムがあります。
ユーザーがホログラムの左側を見ると、その部分はゆっくりとユーザーに向かって回転します。
右側を見ると、右側がユーザーに向かって回転します。

これは常にアクティブにしたくない振る舞いです。ハンドレイまたはヘッドレイによって誤ってトリガーさせたくないものです。

OnLookAtRotateByEyeGaze をアタッチすると、GameObject は見られたときにのみ回転します。

public class OnLookAtRotateByEyeGaze : BaseEyeFocusHandler
{
    ...

    protected override void OnEyeFocusStay()
    {
        // Update target rotation
        RotateHitTarget();
    }

    ...

    ///
    /// This function computes the rotation of the target to move the currently
    /// looked at aspect slowly to the front.
    /// この関数はターゲットの回転を計算して、現在見ているアスペクトをゆっくりと前方に移動します。
    ///
    private void RotateHitTarget()
    {
        // Example for querying the hit position of the eye gaze ray using EyeGazeProvider
        // EyeGazeProvider を使用して視線のヒット位置を照会するサンプル
        Vector3 TargetToHit = (this.gameObject.transform.position - InputSystem.EyeGazeProvider.HitPosition).normalized;

        ...
    }
}

BaseEyeFocusHandler の使用可能なイベントの完全なリストについては、APIドキュメントを確認してください。

・OnEyeFocusStart:視線がこのターゲットのコライダーと交差し始めるとトリガーされます。
・OnEyeFocusStay:視線がこのターゲットのコライダーと交差しているときにトリガーされます。
・OnEyeFocusStop:視線がこのターゲットのコライダーとの交差を停止するとトリガーされます。
・OnEyeFocusDwell:視線がこのターゲットのコライダーと指定された時間にわたって交差するとトリガーされます。

microsoft.github.io