Head、目が視線の DirectX の入力Head and eye gaze input in DirectX

Windows Mixed Reality、目およびヘッド視線の先では、入力はで、ユーザーの必要な情報を確認に使用されます。In Windows Mixed Reality, eye and head gaze input is used to determine what the user is looking at. これは、ドライブのように、プライマリの入力モデルを使用できますが注視し、コミットをヘッド、相互作用の種類のコンテキストをしたりすることです。This can be used to drive primary input models such as head gaze and commit, and also to provide context for types of interactions. API を介して使用可能なベクトルの 2 種類の視線の先がある: 注視し目視線の先に移動します。There are two types of gaze vectors available through the API: head gaze and eye gaze. 3 として両方に提供される次元光線の原点と方向。Both are provided as a three dimensional ray with an origin and direction. そのシーンまたは実際には、アプリケーションに raycast できますし、ユーザーが対象とする内容を確認します。Applications can then raycast into their scenes, or the real world, and determine what the user is targeting.

Head 視線でユーザーの頭が示される方向を表します。Head gaze represents the direction that the user's head is pointed in. 位置と、デバイス自体の前方向と見なす、中心を表す位置を 2 つのディスプレイ間でポイントします。Think of this as the position and forward direction of the device itself, with the position representing the center point between the two displays. Head 視線の先は、すべての複合現実デバイスで利用可能です。Head gaze is available on all Mixed Reality devices.

目の視線入力に対するユーザーの目を参照する方向を表します。Eye gaze represents the direction that the user's eyes are looking towards. 原点は、ユーザーの目の間にあります。The origin is located between the user's eyes. システムの視線を含む複合現実デバイスで利用可能になります。It is available on Mixed Reality devices that include an eye tracking system.

Head と監視の両方の視線の先光線がからアクセスできる、 SpatialPointerPose API。Both head and eye gaze rays are accessible through the SpatialPointerPose API. 呼び出すだけでSpatialPointerPose::TryGetAtTimestamp 、指定したタイムスタンプで新しい SpatialPointerPose オブジェクトを受信して座標系します。Simply call SpatialPointerPose::TryGetAtTimestamp to receive a new SpatialPointerPose object at the specified timestamp and coordinate system. この SpatialPointerPose には、ヘッドの視線の原点と方向が含まれています。This SpatialPointerPose contains a head gaze origin and direction. それも含まれています目視線の先の原点と方向視線が使用可能な場合。It also contains an eye gaze origin and direction if eye tracking is available.

ヘッド視線の先を使用します。Using head gaze

ヘッド視線の先にアクセスするには、呼び出すことによって開始SpatialPointerPose::TryGetAtTimestamp新しい SpatialPointerPose オブジェクトを受信します。To access the head gaze, start by calling SpatialPointerPose::TryGetAtTimestamp to receive a new SpatialPointerPose object. 次のパラメーターを渡す必要があります。You need to pass the following parameters.

  • A SpatialCoordinateSystemヘッド視線の先の目的の座標系を表します。A SpatialCoordinateSystem that represents the desired coordinate system for the head gaze. これは、 coordinateSystem次のコードに変数。This is represented by the coordinateSystem variable in the following code. 詳細については、次を参照してください。 この座標系開発者ガイド。For more information, visit our coordinate systems developer guide.
  • Aタイムスタンプ要求ヘッド姿勢の正確な時間を表します。A Timestamp that represents the exact time of the head pose requested. 通常は、現在のフレームの表示される場合の時間に対応するタイムスタンプを使用します。Typically you will use a timestamp that corresponds to the time when the current frame will be displayed. この予測された表示のタイムスタンプから取得できます、 HolographicFramePredictionオブジェクトは、現在からアクセスできるHolographicFrameYou can get this predicted display timestamp from a HolographicFramePrediction object, which is accessible through the current HolographicFrame. この HolographicFramePrediction オブジェクトとして表されます、予測次のコードに変数。This HolographicFramePrediction object is represented by the prediction variable in the following code.

有効な SpatialPointerPose したら、ヘッドの位置と順方向はプロパティとしてアクセスできます。Once you have a valid SpatialPointerPose, the head position and forward direction are accessible as properties. 次のコードでは、それらにアクセスする方法を示します。The following code shows how to access them.

using namespace winrt::Windows::UI::Input::Spatial;
using namespace winrt::Windows::Foundation::Numerics;

SpatialPointerPose pointerPose = SpatialPointerPose::TryGetAtTimestamp(coordinateSystem, prediction.Timestamp());
if (pointerPose)
{
   float3 headPosition = pointerPose.Head().Position();
   float3 headForwardDirection = pointerPose.Head().ForwardDirection();

   // Do something with the head gaze
}

目視線の先を使用します。Using eye gaze

目の視線の先の API は、ヘッド視線の先によく似ています。The eye gaze API is very similar to head gaze. 使用して同じSpatialPointerPose API で、原点と方向が、シーンに対して raycast ことに伸びる射線を提供します。It uses the same SpatialPointerPose API, which provides a ray origin and direction that you can raycast against your scene. 唯一の違いは、明示的に使用する前に目の追跡を有効にする必要があります。The only difference is that you need to explicitly enable eye tracking before using it. これは、2 つの手順を実行する必要があります。For this, you need to do two steps:

  1. アプリでの視線を使用するユーザーのアクセス許可を要求します。Request user permission to use eye tracking in your app.
  2. パッケージ マニフェストで「視線入力」機能を有効にします。Enable the "Gaze Input" capability in your package manifest.

視線入力へのアクセスを要求します。Requesting access to gaze input

アプリが起動するときに呼び出すEyesPose::RequestAccessAsync目追跡へのアクセスを要求します。When your app is starting up, call EyesPose::RequestAccessAsync to request access to eye tracking. システムが必要な場合、ユーザーに確認し、返すGazeInputAccessStatus::Allowedアクセスが許可されているとします。The system will prompt the user if needed, and return GazeInputAccessStatus::Allowed once access has been granted. これは、少し余分な管理のための非同期呼び出しです。This is an asynchronous call, so it requires a bit of extra management. 次の例のスピンアップと呼ばれるメンバー変数に格納するいると、結果を待つデタッチ std::thread m_isEyeTrackingEnabledします。The following example spins up a detached std::thread to wait for the result, which it stores to a member variable called m_isEyeTrackingEnabled.

using namespace winrt::Windows::Perception::People;
using namespace winrt::Windows::UI::Input;

std::thread requestAccessThread([this]()
{
    auto status = EyesPose::RequestAccessAsync().get();

    if (status == GazeInputAccessStatus::Allowed)
        m_isEyeTrackingEnabled = true;
    else
        m_isEyeTrackingEnabled = false;
});

requestAccessThread.detach();

非同期呼び出しを処理するための 1 つのオプションは、デタッチ スレッドを開始します。Starting a detached thread is just one option for handling async calls. またはを使って新しいco_awaitでサポートされる機能C++/WinRT です。Alternatively, you could use the new co_await functionality supported by C++/WinRT. ユーザーの許可を確認するための別の例を次に示します。Here is another example for asking for user permission:

  • EyesPose::IsSupported() により、目の追跡ツールがある場合にのみ、アクセス許可ダイアログをトリガーするアプリケーションです。EyesPose::IsSupported() allows the application to trigger the permission dialog only if there is an eye tracker.
  • GazeInputAccessStatus m_gazeInputAccessStatus;これは、アクセス許可プロンプトを何度もポップアップを防止します。GazeInputAccessStatus m_gazeInputAccessStatus; // This is to prevent popping up the permission prompt over and over again.
GazeInputAccessStatus m_gazeInputAccessStatus; // This is to prevent popping up the permission prompt over and over again.

// This will trigger to show the permission prompt to the user.
// Ask for access if there is a corresponding device and registry flag did not disable it.
if (Windows::Perception::People::EyesPose::IsSupported() &&
   (m_gazeInputAccessStatus == GazeInputAccessStatus::Unspecified))
{ 
    Concurrency::create_task(Windows::Perception::People::EyesPose::RequestAccessAsync()).then(
    [this](GazeInputAccessStatus status)
    {
        // GazeInputAccessStatus::{Allowed, DeniedBySystem, DeniedByUser, Unspecified}
            m_gazeInputAccessStatus = status;
        
        // Let's be sure to not ask again.
        if(status == GazeInputAccessStatus::Unspecified)
        {
                m_gazeInputAccessStatus = GazeInputAccessStatus::DeniedBySystem;    
        }
    });
}

宣言、視線入力機能Declaring the Gaze Input capability

Appxmanifest ファイルをダブルクリックしますソリューション エクスプ ローラーします。Double click the appxmanifest file in Solution Explorer. 移動し、機能セクションし、確認、視線入力機能します。Then navigate to the Capabilities section and check the Gaze Input capability.

視線入力機能

次の行を追加、パッケージappxmanifest ファイルのセクション。This adds the following lines to the Package section in the appxmanifest file:

  <Capabilities>
    <DeviceCapability Name="gazeInput" />
  </Capabilities>

目の視線の先光線を取得します。Getting the eye gaze ray

ET へのアクセスを受け取った後は自由に目注視光線にすべてのフレームを取得します。Once you have received access to ET, you are free to grab the eye gaze ray every frame. ヘッドの視線入力と同様に、取得、 SpatialPointerPose呼び出してSpatialPointerPose::TryGetAtTimestamp目的のタイムスタンプと座標系を使用します。Just as with head gaze, get the SpatialPointerPose by calling SpatialPointerPose::TryGetAtTimestamp with a desired timestamp and coordinate system. 含まれています、SpatialPointerPose、 EyesPoseオブジェクト、プロパティ。The SpatialPointerPose contains an EyesPose object through the Eyes property. これは、目の追跡が有効になっている場合にのみ null 以外です。This is non-null only if eye tracking is enabled. そこから、デバイスでユーザーが監視の調整を呼び出すことで追跡を確認できますEyesPose::IsCalibrationValidします。From there you can check if the user in the device has an eye tracking calibration by calling EyesPose::IsCalibrationValid. 次に、使用、視線を取得するプロパティのSpatialRay contianing 目視線の位置および方向。Next, use the Gaze property to get the a SpatialRay contianing the eye gaze position and direction. 視線入力プロパティは、null にすることがあります、これを必ずこれを確認します。The Gaze property can sometimes be null, so be sure to check for this. このことができますでは、行われる調整したユーザーが自分以外を一時的に閉じるかどうかです。This can happen is if a calibrated user temporarily closes their eyes.

次のコードでは、目の視線の先光線にアクセスする方法を示します。The following code shows how to access the eye gaze ray.

using namespace winrt::Windows::UI::Input::Spatial;
using namespace winrt::Windows::Foundation::Numerics;

SpatialPointerPose pointerPose = SpatialPointerPose::TryGetAtTimestamp(coordinateSystem, prediction.Timestamp());
if (pointerPose)
{
    if (pointerPose.Eyes() && pointerPose.Eyes().IsCalibrationValid())
    {
        if (pointerPose.Eyes().Gaze())
        {
            auto spatialRay = pointerPose.Eyes().Gaze().Value();
            float3 eyeGazeOrigin = spatialRay.Origin;
            float3 eyeGazeDirection = spatialRay.Direction;
            
            // Do something with the eye gaze
        }
    }
}

その他の入力と視線の先の関連付けCorrelating gaze with other inputs

必要があることもあります、 SpatialPointerPose過去のイベントに対応します。Sometimes you may find that you need a SpatialPointerPose that corresponds with an event in the past. たとえば、ユーザーは、エア タップを実行する場合、アプリ可能性がありますを探していたを知りたいとします。For example, if the user performs an Air Tap, your app might want to know what they were looking at. そのために、次を使用して単にSpatialPointerPose::TryGetAtTimestampフレームの予測と時間が不正確にシステムの入力の処理と表示時間の間の待機時間のためです。For this purpose, simply using SpatialPointerPose::TryGetAtTimestamp with the predicted frame time would be inaccurate because of the latency between system input processing and display time. さらに、目視線の先を使用して、対象とするため場合、人間の目をコミット操作を終了する前にも移動する傾向があります。In addition, if using eye gaze for targeting, our eyes tend to move on even before finishing a commit action. これを単純なエア タップして、問題の少ないが、高速の目の動きを時間の長い音声コマンドを結合するときにより重要になります。This is less of an issue for a simple Air Tap, but becomes more critical when combining long voice commands with fast eye movements. このシナリオを処理する方法の 1 つは、する追加の呼び出しを行うにはSpatialPointerPose::TryGetAtTimestamp、入力イベントに対応する履歴のタイムスタンプを使用します。One way to handle this scenario is to make an additional call to SpatialPointerPose::TryGetAtTimestamp, using a historical timestamp that corresponds to the input event.

ただし、SpatialInteractionManager を介してルーティングを入力する場合を簡単があります。However, for input that routes through the SpatialInteractionManager, there's an easier method. SpatialInteractionSourceStateが非常に独自TryGetAtTimestamp関数。The SpatialInteractionSourceState has its very own TryGetAtTimestamp function. 完全に相関を提供する通話SpatialPointerPoseせず、当て推量を排除します。Calling that will provide a perfectly correlated SpatialPointerPose without the guesswork. SpatialInteractionSourceStates の操作方法の詳細についてを参照してください、手および DirectX でモーション コント ローラードキュメント。For more information on working with SpatialInteractionSourceStates, take a look at the Hands and Motion Controllers in DirectX documentation.

関連項目See also