DirectX での手とモーション コントローラーHands and motion controllers in DirectX


この記事は、従来の WinRT ネイティブ Api に関連しています。This article relates to the legacy WinRT native APIs. 新しいネイティブアプリプロジェクトの場合は、 OPENXR API を使用することをお勧めします。For new native app projects, we recommend using the OpenXR API.

Windows Mixed Reality では、ハンドコントローラー入力と モーションコントローラー 入力の両方が、windows の. UI. 空間名前空間にある空間入力 api を介して処理されます。In Windows Mixed Reality, both hand and motion controller input is handled through the spatial input APIs, found in the Windows.UI.Input.Spatial namespace. これにより、 選択 などの一般的なアクションを簡単に処理できるようになります。This enables you to easily handle common actions like Select presses the same way across both hands and motion controllers.

作業の開始Getting started

Windows Mixed Reality で空間入力にアクセスするには、SpatialInteractionManager インターフェイスから開始します。To access spatial input in Windows Mixed Reality, start with the SpatialInteractionManager interface. このインターフェイスにアクセスするには、通常はアプリの起動時に SpatialInteractionManager:: GetForCurrentViewを呼び出します。You can access this interface by calling SpatialInteractionManager::GetForCurrentView, typically sometime during app startup.

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

SpatialInteractionManager interactionManager = SpatialInteractionManager::GetForCurrentView();

SpatialInteractionManager の仕事は、入力のソースを表す SpatialInteractionSourcesへのアクセスを提供することです。The SpatialInteractionManager's job is to provide access to SpatialInteractionSources, which represent a source of input. システムで使用できる SpatialInteractionSources には3種類あります。There are three kinds of SpatialInteractionSources available in the system.

  • ハンド は、ユーザーの検出されたハンドを表します。Hand represents a user's detected hand. 手動ソースは、HoloLens の基本的なジェスチャから HoloLens 2 の完全な形の追跡まで、デバイスに基づいてさまざまな機能を提供します。Hand sources offer different features based on the device, ranging from basic gestures on HoloLens to fully articulated hand tracking on HoloLens 2.
  • コントローラー は、対になっているモーションコントローラーを表します。Controller represents a paired motion controller. モーションコントローラーは、さまざまな機能を提供できます。Motion controllers can offer a variety of capabilities. たとえば、トリガー、メニューボタン、ボタン、タッチパッド向け、および thumbsticks を選択します。For example: Select triggers, Menu buttons, Grasp buttons, touchpads and thumbsticks.
  • 音声 は、ユーザーの音声読み上げシステムで検出されたキーワードを表します。Voice represents the user's voice speaking system-detected keywords. たとえば、このソースでは、ユーザーが "Select" と表示されるたびに、Select press と release が挿入されます。For example, this source will inject a Select press and release whenever the user says "Select".

ソースのフレームごとのデータは、 SpatialInteractionSourceState インターフェイスによって表されます。Per-frame data for a source is represented by the SpatialInteractionSourceState interface. アプリケーションでイベントドリブンモデルとポーリングベースのモデルのどちらを使用するかに応じて、このデータにアクセスする2つの方法があります。There are two different ways to access this data, depending on whether you want to use an event-driven or polling-based model in your application.

イベントドリブン入力Event-driven input

SpatialInteractionManager は、アプリがリッスンできる多数のイベントを提供します。The SpatialInteractionManager provides a number of events that your app can listen for. 例として、 Sourcepressedれた、 SourceReleasedsourcepressedなどがあります。A few examples include SourcePressed, SourceReleased and SourceUpdated.

たとえば、次のコードは、MyApp イベントに対して MyApp:: OnSourcePressed れたイベントハンドラーをフックします。For example, the following code hooks up an event handler called MyApp::OnSourcePressed to the SourcePressed event. これにより、アプリは任意の種類の相互作用ソースの押下を検出できます。This allows your app to detect presses on any type of interaction source.

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

auto interactionManager = SpatialInteractionManager::GetForCurrentView();
interactionManager.SourcePressed({ this, &MyApp::OnSourcePressed });

この押されたイベントは、キーを押したときの対応する SpatialInteractionSourceState と共に、アプリに非同期的に送信されます。This pressed event is sent to your app asynchronously, along with the corresponding SpatialInteractionSourceState at the time the press happened. アプリまたはゲームエンジンでは、すぐに処理を実行したり、入力処理ルーチンでイベントデータをキューに入れたりすることが必要になる場合があります。Your app or game engine may want to perform some processing right away or you may want to queue up the event data in your input processing routine. 次に示すのは、SourcePressed れたイベントのイベントハンドラー関数で、[選択] ボタンが押されたかどうかを確認する方法を示しています。Here is an event handler function for the SourcePressed event, which shows how to check whether the select button was pressed.

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

void MyApp::OnSourcePressed(SpatialInteractionManager const& sender, SpatialInteractionSourceEventArgs const& args)
    if (args.PressKind() == SpatialInteractionPressKind::Select)
        // Select button was pressed, update app state

上のコードでは、デバイスの主なアクションに対応する ' Select ' の押下だけがチェックされます。The above code only checks for the 'Select' press, which corresponds to the primary action on the device. たとえば、HoloLens でのエアタップの実行や、モーションコントローラーでのトリガーの取り出しなどです。Examples include doing an AirTap on HoloLens or pulling the trigger on a motion controller. ' Select ' は、ターゲットとしているホログラムをアクティブ化するユーザーの意図を表します。'Select' presses represent the user's intention to activate the hologram they are targeting. SourcePressed イベントは、さまざまなボタンとジェスチャに対して起動されます。また、SpatialInteractionSource の他のプロパティを調べて、そのようなケースをテストできます。The SourcePressed event will fire for a number of different buttons and gestures, and you can inspect other properties on the SpatialInteractionSource to test for those cases.

ポーリングベースの入力Polling-based input

また、SpatialInteractionManager を使用して、すべてのフレームに対する入力の現在の状態をポーリングすることもできます。You can also use SpatialInteractionManager to poll for the current state of input every frame. これを行うには、すべてのフレームで GetDetectedSourcesAtTimestamp を呼び出します。To do this, simply call GetDetectedSourcesAtTimestamp every frame. この関数は、アクティブなSpatialInteractionSourceごとに1つのSpatialInteractionSourceStateを含む配列を返します。This function returns an array containing one SpatialInteractionSourceState for every active SpatialInteractionSource. これは、アクティブなモーションコントローラーごとに1つ、つまり、' select ' コマンドが最近発音された場合は、1つずつ、もう1つは音声用です。This means one for each active motion controller, one for each tracked hand, and one for speech if a 'select' command was recently uttered. その後、各 SpatialInteractionSourceState のプロパティを調べて、アプリケーションへの入力を実行できます。You can then inspect the properties on each SpatialInteractionSourceState to drive input into your application.

ポーリング方法を使用して ' select ' アクションを確認する方法の例を次に示します。Here is an example of how to check for the 'select' action using the polling method. 予測 変数は HolographicFramePredictionオブジェクトを表すことに注意してください。これは HolographicFrameから取得できます。Note that the prediction variable represents a HolographicFramePrediction object, which can be obtained from the HolographicFrame.

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

auto interactionManager = SpatialInteractionManager::GetForCurrentView();
auto sourceStates = m_spatialInteractionManager.GetDetectedSourcesAtTimestamp(prediction.Timestamp());

for (auto& sourceState : sourceStates)
    if (sourceState.IsSelectPressed())
        // Select button is down, update app state

各 SpatialInteractionSource には ID があり、これを使用して新しいソースを識別し、フレーム間の既存のソースを関連付けることができます。Each SpatialInteractionSource has an ID, which you can use to identify new sources and correlate existing sources from frame to frame. ハンドは、移動するたびに新しい ID が割り当てられますが、セッションの間は、コントローラー Id は静的のままです。Hands are assigned a new ID every time they leave and enter the FOV, but controller IDs remain static for the duration of the session. SourcedetectedSourcedetectedなどの SpatialInteractionManager のイベントを使用して、ユーザーがデバイスのビューを手に入れたり、移動したりしたとき、またはモーションコントローラーがオン/オフになっているとき、またはペア/対になっていないときに反応することができます。You can use the events on SpatialInteractionManager such as SourceDetected and SourceLost, to react when hands enter or leave the device's view, or when motion controllers are turned on/off or are paired/unpaired.

予測と履歴のポーズPredicted vs. historical poses

GetDetectedSourcesAtTimestamp には timestamp パラメーターがあることに注意してください。Note that GetDetectedSourcesAtTimestamp has a timestamp parameter. これにより、予測または履歴の状態を要求し、データを供給することができるため、空間の相互作用を他の入力のソースと関連付けることができます。This enables you to request state and pose data that is either predicted or historical, letting you correlate spatial interactions with other sources of input. たとえば、現在のフレームに手の位置を表示する場合は、 HolographicFrameによって提供される予測タイムスタンプを渡すことができます。For example, when rendering the hand's position in the current frame, you can pass in the predicted timestamp provided by the HolographicFrame. これにより、システムは、描画されたフレーム出力と密接に一致するようにハンド位置を順方向に予測して、認識される待機時間を最小限に抑えることができます。This enables the system to forward-predict the hand position to closely align with the rendered frame output, minimizing perceived latency.

ただし、このような予測によって、相互作用ソースをターゲットにするための最適なポイントが生成されるわけではありません。However, such a predicted pose does not produce an ideal pointing ray for targeting with an interaction source. たとえば、[モーションコントローラー] ボタンが押されている場合、そのイベントが Bluetooth 経由でオペレーティングシステムに対して20ミリ秒になるまでに最大で時間がかかることがあります。For example, when a motion controller button is pressed, it can take up to 20ms for that event to bubble up through Bluetooth to the operating system. 同様に、ユーザーが手の形でジェスチャを実行した後、システムがジェスチャを検出する前に一定の時間が経過し、アプリがそのジェスチャをポーリングします。Similarly, after a user performs a hand gesture, some amount of time may pass before the system detects the gesture and your app then polls for it. アプリが状態の変更をポーリングするまでに、その相互作用をターゲットとするために使用されるヘッドとハンドは、実際には過去に発生しました。By the time your app polls for a state change, the head and hand poses used to target that interaction actually happened in the past. 現在の HolographicFrame のタイムスタンプを GetDetectedSourcesAtTimestamp に渡すことによってターゲットを設定した場合は、フレームが表示された時点でターゲットの射線に対して、予測が前方に転送されます。これは将来の20ミリ秒よりも大きくなる可能性があります。If you target by passing your current HolographicFrame's timestamp to GetDetectedSourcesAtTimestamp, the pose will instead be forward predicted to the targeting ray at the time the frame will be displayed, which could be more than 20ms in the future. これは、相互作用ソースを レンダリング する場合に適していますが、ユーザーの対象が過去に発生したため、相互作用を 対象 とした時間の問題が複雑になります。This future pose is good for rendering the interaction source, but compounds our time problem for targeting the interaction, as the user's targeting occurred in the past.

幸いなことに、 Sourcepressedれた、 SourceReleased および sourcepressed イベントは、各入力イベントに関連付けられた履歴 状態 を提供します。Fortunately, the SourcePressed, SourceReleased and SourceUpdated events provide the historical State associated with each input event. これには、 Trygetポインターによって使用可能な履歴のヘッドとハンドのポーズと、他の api に渡してこのイベントと関連付けることができる履歴 タイムスタンプ が含まれます。This directly includes the historical head and hand poses available through TryGetPointerPose, along with a historical Timestamp that you can pass to other APIs to correlate with this event.

次のベストプラクティスに従って、各フレームでハンドおよびコントローラーをレンダリングして対象を設定します。That leads to the following best practices when rendering and targeting with hands and controllers each frame:

  • 各フレームを レンダリング するには、アプリは、現在のフレームの photon 時間における各相互作用ソースの フォワード予測ポーリング する必要があります。For hand/controller rendering each frame, your app should poll for the forward-predicted pose of each interaction source at the current frame’s photon time. 各フレーム GetDetectedSourcesAtTimestamp を呼び出し、 HolographicFrame:: currentpredictionによって提供される予測タイムスタンプを渡すことによって、すべての相互作用ソースをポーリングできます。You can poll for all interaction sources by calling GetDetectedSourcesAtTimestamp each frame, passing in the predicted timestamp provided by HolographicFrame::CurrentPrediction.
  • プレスまたはリリースを対象とする手動または コントローラー の場合、アプリでは、そのイベントの 履歴 ヘッドまたはハンド raycasting に基づいて、押されたイベントまたは解放された イベント を処理する必要があります。For hand/controller targeting upon a press or release, your app should handle pressed/released events, raycasting based on the historical head or hand pose for that event. このターゲット設定を取得するには、 Sourcepressed れたイベントまたは SourceReleased イベントを処理し、イベント引数から State プロパティを取得して、その trygetポインタポーズ メソッドを呼び出します。You get this targeting ray by handling the SourcePressed or SourceReleased event, getting the State property from the event arguments, and then calling its TryGetPointerPose method.

デバイス間の入力プロパティCross-device input properties

SpatialInteractionSource API では、さまざまな機能を備えたコントローラーおよびハンドトラッキングシステムがサポートされています。The SpatialInteractionSource API supports controllers and hand tracking systems with a wide range of capabilities. これらの機能の多くは、デバイスの種類によって一般的です。A number of these capabilities are common between device types. たとえば、ハンドトラッキングとモーションコントローラーは、どちらも ' select ' アクションと3D 位置を提供します。For example, hand tracking and motion controllers both provide a 'select' action and a 3D position. 可能な限り、API はこれらの共通機能を SpatialInteractionSource の同じプロパティにマップします。Wherever possible, the API maps these common capabilities to the same properties on the SpatialInteractionSource. これにより、アプリケーションは幅広い種類の入力をより簡単にサポートできるようになります。This enables applications to more easily support a wide range of input types. 次の表では、サポートされるプロパティと、入力の種類間での比較方法について説明します。The following table describes the properties that are supported, and how they compare across input types.

プロパティProperty 説明Description HoloLens (第1世代) ジェスチャHoloLens(1st gen) Gestures モーションコントローラーMotion Controllers 手によるハンドArticulated Hands
SpatialInteractionSource::ききSpatialInteractionSource::Handedness Right または left/controller。Right or left hand / controller. サポートされていませんNot Supported サポートされていますSupported サポートSupported
SpatialInteractionSourceState::Isselectpressed れましたSpatialInteractionSourceState::IsSelectPressed プライマリボタンの現在の状態。Current state of the primary button. エアタップAir Tap トリガーTrigger 緩やかに出た空気タップ (垂直ピンチ)Relaxed Air Tap (upright pinch)
SpatialInteractionSourceState::IsGraspedSpatialInteractionSourceState::IsGrasped グラブボタンの現在の状態です。Current state of the grab button. サポートしていません。Not Supported グラブボタンGrab button ピンチまたは閉じた手Pinch or Closed Hand
SpatialInteractionSourceState::IsMenuPressedSpatialInteractionSourceState::IsMenuPressed メニューボタンの現在の状態。Current state of the menu button. サポートしていません。Not Supported メニューボタンMenu Button サポートしていません。Not Supported
SpatialInteractionSourceLocation::PositionSpatialInteractionSourceLocation::Position コントローラー上の手またはグリップ位置の XYZ 位置。XYZ location of the hand or grip position on the controller. パームの場所Palm location グリップの発生位置Grip pose position パームの場所Palm location
SpatialInteractionSourceLocation::OrientationSpatialInteractionSourceLocation::Orientation コントローラー上の手やグリップの向きを表す四元数。Quaternion representing the orientation of the hand or grip pose on the controller. サポートしていません。Not Supported グリップの向きGrip pose orientation パームの向きPalm orientation
SpatialPointerInteractionSourcePose::PositionSpatialPointerInteractionSourcePose::Position ポイントの原点。Origin of the pointing ray. サポートされていませんNot Supported サポートされていますSupported サポートSupported
SpatialPointerInteractionSourcePose::ForwarddirectionSpatialPointerInteractionSourcePose::ForwardDirection ポイントの方向。Direction of the pointing ray. サポートされていませんNot Supported サポートされていますSupported サポートSupported

上記のプロパティの一部は、すべてのデバイスで使用できるわけではありません。 API には、このことをテストする手段が用意されています。Some of the above properties are not available on all devices, and the API provides a means to test for this. たとえば、 SpatialInteractionSource:: IsGraspSupported プロパティを調べて、ソースがつかみアクションを提供するかどうかを判断できます。For example, you can inspect the SpatialInteractionSource::IsGraspSupported property to determine whether the source provides a grasp action.

グリップポーズとポインティングポーズGrip pose vs. pointing pose

Windows Mixed Reality では、さまざまなフォームファクターでモーションコントローラーをサポートしています。Windows Mixed Reality supports motion controllers in a variety of form factors. また、独自の追跡システムもサポートしています。It also supports articulated hand tracking systems. これらのシステムはすべて、ユーザーの手の中でオブジェクトをポイントまたは表示するためにアプリが使用する必要がある自然な位置と自然な "転送" 方向との間には異なる関係があります。All of these systems have different relationships between the hand position and the natural "forward" direction that apps should use for pointing or rendering objects in the user's hand. これらのすべてをサポートするために、ハンドトラッキングとモーションコントローラーの両方に3種類の3D が用意されています。To support all of this, there are two types of 3D poses provided for both hand tracking and motion controllers. 1つ目は、ユーザーの手の位置を表すグリップです。The first is grip pose, which represents the user's hand position. 2つ目の方法は、ユーザーの手またはコントローラーからのポイントを示すポイントを指します。The second is pointing pose, which represents a pointing ray originating from the user's hand or controller. そのため、 ユーザーの手 や、剣や銃などの ユーザーの手に保持 されているオブジェクトをレンダリングする場合は、グリップを使用します。So, if you want to render the user's hand or an object held in the user's hand, such as a sword or gun, use the grip pose. ユーザーが UI をポイント しているときなど、コントローラーまたはハンドから raycast する場合は、ポイントアンドポーズを使用します。If you want to raycast from the controller or hand, for example when the user is pointing at UI , use the pointing pose.

グリップ にアクセスするには、 SpatialInteractionSourceState::P R.:: trygetlocation (...)を使用します。 次のように定義されています。You can access the grip pose through SpatialInteractionSourceState::Properties::TryGetLocation(...). It is defined as follows:

  • グリップの位置: コントローラーを自然に保持するときのパーム重心。グリップ内の位置を中央に配置するように左右に調整されます。The grip position: The palm centroid when holding the controller naturally, adjusted left or right to center the position within the grip.
  • グリップの向きの右軸: 手を完全に開いて平らな5本の指を作成した場合 (左側のパームから前方、右側のパームから後方)、The grip orientation's Right axis: When you completely open your hand to form a flat 5-finger pose, the ray that is normal to your palm (forward from left palm, backward from right palm)
  • グリップの向きの前方軸: ハンドを部分的に閉じた場合 (コントローラーを保持している場合と同様)、非表示の指で形成されたチューブを通過する光線。The grip orientation's Forward axis: When you close your hand partially (as if holding the controller), the ray that points "forward" through the tube formed by your non-thumb fingers.
  • グリップの向きの上位軸: 右および順方向の定義によって暗黙的に示される上位軸。The grip orientation's Up axis: The Up axis implied by the Right and Forward definitions.

ポインターSpatialInteractionSourceState::P R.:: trygetlocation (...):: sourcepointer ポーズまたは SpatialInteractionSourceState:: trygetlocation ポーズ (...):: Trygetinteractionsourceポーズにアクセスできます。You can access the pointer pose through SpatialInteractionSourceState::Properties::TryGetLocation(...)::SourcePointerPose or SpatialInteractionSourceState::TryGetPointerPose(...)::TryGetInteractionSourcePose.

コントローラー固有の入力プロパティController-specific input properties

コントローラーの場合、SpatialInteractionSource には追加機能を持つコントローラープロパティがあります。For controllers, the SpatialInteractionSource has a Controller property with additional capabilities.

  • Hasthumbstick: True の場合、コントローラーにはサムスティックがあります。HasThumbstick: If true, the controller has a thumbstick. SpatialInteractionSourceState の " コントローラーのプロパティ " プロパティを調べて、スティックの x 値と y 値 (ThumbstickX と ThumbstickY) と押された状態 (IsThumbstickPressed) を取得します。Inspect the ControllerProperties property of the SpatialInteractionSourceState to acquire the thumbstick x and y values (ThumbstickX and ThumbstickY), as well as its pressed state (IsThumbstickPressed).
  • HasTouchpad: True の場合、コントローラーにはタッチパッドがあります。HasTouchpad: If true, the controller has a touchpad. SpatialInteractionSourceState の "コントローラーのプロパティ" プロパティを調べて、タッチパッドの x 値と y 値 (TouchpadX と TouchpadY) を取得し、ユーザーがパッドに触れている (IsTouchpadTouched) ことを確認し、タッチパッドを押す (Istouchpadtouched れた) かどうかを確認します。Inspect the ControllerProperties property of the SpatialInteractionSourceState to acquire the touchpad x and y values (TouchpadX and TouchpadY), and to know if the user is touching the pad (IsTouchpadTouched) and if they are pressing the touchpad down (IsTouchpadPressed).
  • SimpleHapticsController: コントローラーの SimpleHapticsController API を使用すると、コントローラーの haptics 機能を調べることができます。また、haptic フィードバックを制御することもできます。SimpleHapticsController: The SimpleHapticsController API for the controller allows you to inspect the haptics capabilities of the controller, and it also allows you to control haptic feedback.

タッチパッドとサムスティックの範囲は、両方の軸 (下から上、左から右) に対して-1 から1までの範囲であることに注意してください。Note that the range for touchpad and thumbstick is -1 to 1 for both axes (from bottom to top, and from left to right). SpatialInteractionSourceState:: SelectPressedValue プロパティを使用してアクセスされる、アナログトリガーの範囲には、0 ~ 1 の範囲があります。The range for the analog trigger, which is accessed using the SpatialInteractionSourceState::SelectPressedValue property, has a range of 0 to 1. 値1は、IsSelectPressed れた値が true であると相関します。その他の値は、IsSelectPressed れた値が false と関連付けられます。A value of 1 correlates with IsSelectPressed being equal to true; any other value correlates with IsSelectPressed being equal to false.

手による追跡Articulated hand tracking

Windows Mixed Reality API は、HoloLens 2 でのように、独自の追跡を完全にサポートしています。The Windows Mixed Reality API provides full support for articulated hand tracking, for example on HoloLens 2. 独自の追跡を使用すると、アプリケーションに直接操作やポイントアンドコミット入力モデルを実装できます。Articulated hand tracking can be used to implement direct manipulation and point-and-commit input models in your applications. また、完全にカスタムな対話を作成するために使用することもできます。It can also be used to author fully custom interactions.

手スケルトンHand skeleton

トレーラー型の追跡では、さまざまな種類の相互作用を可能にする25のジョイントスケルトンが提供されます。Articulated hand tracking provides a 25 joint skeleton that enables many different types of interactions. スケルトンには、インデックス/中間/リング/リトルフィンガー、4個の関節 (つまみ)、および1つの手首結合に対して5つの接合が用意されています。The skeleton provides 5 joints for the index/middle/ring/little fingers, 4 joints for the thumb, and 1 wrist joint. この手首は、階層のベースとして機能します。The wrist joint serves as the base of the hierarchy. 次の図は、スケルトンのレイアウトを示しています。The following picture illustrates the layout of the skeleton.


ほとんどの場合、各結合には、それが表すボーンに基づいた名前が付けられます。In most cases, each joint is named based on the bone that it represents. すべてのジョイントに2つのボーンがあるため、その場所の子ボーンに基づいて各結合に名前を付ける規則を使用します。Since there are two bones at every joint, we use a convention of naming each joint based on the child bone at that location. 子ボーンは、手首からさらにボーンとして定義されます。The child bone is defined as the bone further from the wrist. たとえば、"Index 位" という結合には、インデックス位ボーンの開始位置とそのボーンの方向が含まれます。For example, the "Index Proximal" joint contains the beginning position of the index proximal bone, and the orientation of that bone. これには、ボーンの終了位置は含まれません。It does not contain the ending position of the bone. これが必要な場合は、階層内の次の結合 ("中間インデックス" という結合) から取得します。If you need that, you'd get it from the next joint in the hierarchy, the "Index Intermediate" joint.

25の階層結合に加えて、システムには、パームジョイントが用意されています。In addition to the 25 hierarchical joints, the system provides a palm joint. 通常、palm は骨格構造の一部とは見なされません。The palm is not typically considered part of the skeletal structure. これは、手の形と向きを取得するための便利な方法としてのみ提供されています。It is provided only as a convenient way to get the hand's overall position and orientation.

各結合について、次の情報が提供されています。The following information is provided for each joint:

名前Name 説明Description
位置Position 要求されたすべての座標系で使用可能な、ジョイントの3D 位置。3D position of the joint, available in any requested coordinate system.
OrientationOrientation 要求されたすべての座標系で使用可能な、ボーンの3D の向き。3D orientation of the bone, available in any requested coordinate system.
RadiusRadius ジョイント位置のスキンの表面までの距離。Distance to surface of the skin at the joint position. 指の幅に依存する直接の対話や視覚エフェクトをチューニングする場合に便利です。Useful for tuning direct interactions or visualizations that rely on finger width.
精度Accuracy この共同の情報についてシステムがどの程度自信を持っているかについてのヒントを提供します。Provides a hint on how confident the system feels about this joint's information.

SpatialInteractionSourceStateの関数を使用して、ハンドスケルトンデータにアクセスできます。You can access the hand skeleton data through a function on the SpatialInteractionSourceState. 関数は TryGetHandPoseと呼ばれ、この関数は、"" と いう名前のオブジェクトを返します。The function is called TryGetHandPose, and it returns an object called HandPose. 変換元が変換をサポートしていない場合、この関数は null を返します。If the source does not support articulated hands, then this function will return null. 手を付けたら、 Trygetjointを呼び出して現在のジョイントデータを取得できます。これには、興味のあるジョイントの名前を付けます。Once you have a HandPose, you can get current joint data by calling TryGetJoint, with the name of the joint you are interested in. データは JointPose 構造体として返されます。The data is returned as a JointPose structure. 次のコードは、インデックスのフィンガーヒントの位置を取得します。The following code gets the position of the index finger tip. 変数は SpatialInteractionSourceStateインスタンスを表し ます。The variable currentState represents an instance of SpatialInteractionSourceState.

using namespace winrt::Windows::Perception::People;
using namespace winrt::Windows::Foundation::Numerics;

auto handPose = currentState.TryGetHandPose();
if (handPose)
    JointPose joint;
    if (handPose.TryGetJoint(desiredCoordinateSystem, HandJointKind::IndexTip, joint))
        float3 indexTipPosition = joint.Position;

        // Do something with the index tip position

手動メッシュHand mesh

修飾されたハンドトラッキング API を使用すると、完全に非フォーム化可能な三角形ハンドメッシュが可能になります。The articulated hand tracking API allows for a fully deformable triangle hand mesh. このメッシュは、ハンドスケルトンと共にリアルタイムで変形できます。また、視覚化や高度な物理手法にも役立ちます。This mesh can deform in real time along with the hand skeleton, and is useful for visualization as well as advanced physics techniques. 手メッシュにアクセスするには、最初にSpatialInteractionSourceTryCreateHandMeshObserverAsyncを呼び出してHandMeshObserverオブジェクトを作成する必要があります。To access the hand mesh, you need to first create a HandMeshObserver object by calling TryCreateHandMeshObserverAsync on the SpatialInteractionSource. これは、ソースごとに1回だけ実行する必要があります。通常は、最初に表示されます。This only needs to be done once per source, typically the first time you see it. つまり、この関数を呼び出して、手動で視界に入ったときに HandMeshObserver オブジェクトを作成します。That means you'll call this function to create a HandMeshObserver object whenever a hand enters the FOV. これは非同期関数であるため、ここで少しの同時実行を処理する必要があります。Note that this is an async function, so you'll have to deal with a bit of concurrency here. 使用できるようになったら、 GetTriangleIndicesを呼び出して、三角形インデックスバッファーの HandMeshObserver オブジェクトに要求できます。Once available, you can ask the HandMeshObserver object for the triangle index buffer by calling GetTriangleIndices. インデックスはフレームに対して変更されないため、これらを一度取得し、ソースの有効期間にわたってキャッシュすることができます。Indices don't change frame over frame, so you can get those once and cache them for the lifetime of the source. インデックスは、回転順に指定します。Indices are provided in clockwise winding order.

次のコードは、切り離された std:: thread をスピンアップしてメッシュオブザーバーを作成し、メッシュオブザーバーが使用可能になったときにインデックスバッファーを抽出します。The following code spins up a detached std::thread to create the mesh observer and extracts the index buffer once the mesh observer is available. SpatialInteractionSourceState と呼ばれる変数から開始します。これ は、追跡 されたハンドを表す、 SpatialInteractionSourceStateのインスタンスです。It starts from a variable called currentState, which is an instance of SpatialInteractionSourceState representing a tracked hand.

using namespace Windows::Perception::People;

std::thread createObserverThread([this, currentState]()
    HandMeshObserver newHandMeshObserver = currentState.Source().TryCreateHandMeshObserverAsync().get();
    if (newHandMeshObserver)
        unsigned indexCount = newHandMeshObserver.TriangleIndexCount();
        vector<unsigned short> indices(indexCount);

        // Save the indices and handMeshObserver for later use - and use a mutex to synchronize access if needed!

デタッチされたスレッドの開始は、非同期呼び出しを処理するためのオプションの1つにすぎません。Starting a detached thread is just one option for handling async calls. または、C++/winrtでサポートされている新しい co_await 機能を使用することもできます。Alternatively, you could use the new co_await functionality supported by C++/WinRT.

HandMeshObserver オブジェクトを作成したら、それに対応する SpatialInteractionSource がアクティブになるまで、そのオブジェクトを保持する必要があります。Once you have a HandMeshObserver object, you should hold onto it for the duration that its corresponding SpatialInteractionSource is active. 次に、各フレームに対して、 Getvertexstateforpose を呼び出して、頂点の対象と なるポーズを 表すのに渡すことによって、ハンドを表す最新の頂点バッファーを要求できます。Then each frame, you can ask it for the latest vertex buffer that represents the hand by calling GetVertexStateForPose and passing in a HandPose instance that represents the pose that you want vertices for. バッファー内の各頂点は、位置と法線を持ちます。Each vertex in the buffer has a position and a normal. 手メッシュの頂点の現在のセットを取得する方法の例を次に示します。Here's an example of how to get the current set of vertices for a hand mesh. 前と同様に、 SpatialInteractionSourceState変数は、の インスタンスを表します。Just as before, the currentState variable represents an instance of SpatialInteractionSourceState.

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

auto handPose = currentState.TryGetHandPose();
if (handPose)
    std::vector<HandMeshVertex> vertices(handMeshObserver.VertexCount());
    auto vertexState = handMeshObserver.GetVertexStateForPose(handPose);

    auto meshTransform = vertexState.CoordinateSystem().TryGetTransformTo(desiredCoordinateSystem);
    if (meshTransform != nullptr)
        // Do something with the vertices and mesh transform, along with the indices that you saved earlier

スケルトンジョイントとは対照的に、ハンドメッシュ API では、頂点の座標系を指定することはできません。In contrast to skeleton joints, the hand mesh API does not allow you to specify a coordinate system for the vertices. 代わりに、 HandMeshVertexState は、頂点が提供される座標系を指定します。Instead, the HandMeshVertexState specifies the coordinate system that the vertices are provided in. に、Trygettransformto 呼び出して必要な座標系を指定することで、メッシュ変換を取得できます。You can then get a mesh transform by calling TryGetTransformTo and specifying your desired coordinate system. 頂点を操作するときは常に、このメッシュ変換を使用する必要があります。You'll need to use this mesh transform whenever you work with the vertices. この方法では、特にレンダリング専用のメッシュを使用している場合に、CPU のオーバーヘッドが軽減されます。This approach reduces CPU overhead, especially if you are only using the mesh for rendering purposes.

複合ジェスチャを見つめてコミットするGaze and Commit composite gestures

特に HoloLens (最初の gen) で、SpatialGestureRecognizer 入力モデルを使用するアプリケーションの場合、空間入力 API は省略可能なSpatialGestureRecognizerを提供します。このオプションを使用して、"select" イベントの上に構築された複合ジェスチャを有効にすることができます。For applications using the gaze-and-commit input model, particularly on HoloLens (first gen), the Spatial Input API provides an optional SpatialGestureRecognizer that can be used to to enable composite gestures built on top of the 'select' event. アプリでは、SpatialInteractionManager からホログラムの SpatialGestureRecognizer に対する相互作用をルーティングすることにより、手動での押下と解放を処理することなく、両手、音声、および空間入力デバイス全体で、タップ、ホールド、操作、およびナビゲーションイベントを一貫して検出できます。By routing interactions from the SpatialInteractionManager to a hologram's SpatialGestureRecognizer, apps can detect Tap, Hold, Manipulation, and Navigation events uniformly across hands, voice, and spatial input devices, without having to handle presses and releases manually.

SpatialGestureRecognizer は、要求した一連のジェスチャ間で最小限のあいまいさだけを実行します。SpatialGestureRecognizer performs only the minimal disambiguation between the set of gestures that you request. たとえば、Tap を要求した場合、ユーザーは指を好きな限り下に置くことができ、タップが引き続き発生する可能性があります。For example, if you request just Tap, the user may hold their finger down as long as they like and a Tap will still occur. タップとホールドの両方を要求した場合、指を押したままにしておくと、ジェスチャがホールドに昇格し、タップが発生しなくなります。If you request both Tap and Hold, after about a second of holding down their finger, the gesture will promote to a Hold and a Tap will no longer occur.

SpatialGestureRecognizer を使用するには、SpatialInteractionManager の Interactiondetected イベントを処理し、そこで公開されている SpatialPointerPose を取得します。To use SpatialGestureRecognizer, handle the SpatialInteractionManager's InteractionDetected event and grab the SpatialPointerPose exposed there. ユーザーがどのような操作を行っているかを判断するために、ユーザーの周囲のホログラムとサーフェスメッシュとの交差部分を使用して、ユーザーの頭を見つめます。Use the user's head gaze ray from this pose to intersect with the holograms and surface meshes in the user's surroundings, in order to determine what the user is intending to interact with. 次に、 CaptureInteraction メソッドを使用して、イベント引数の SpatialInteraction をターゲットホログラムの SpatialGestureRecognizer にルーティングします。Then, route the SpatialInteraction in the event arguments to the target hologram's SpatialGestureRecognizer, using its CaptureInteraction method. これにより、作成時に、またはTrySetGestureSettingsによって、その認識エンジンで設定されたSpatialGestureSettingsに従って、その相互作用の解釈が開始されます。This starts interpreting that interaction according to the SpatialGestureSettings set on that recognizer at creation time - or by TrySetGestureSettings.

HoloLens (最初の世代) では、相互作用とジェスチャは、通常、ユーザーのヘッドからのターゲットを導き出す必要があります。これは、直接の位置でのレンダリングや対話を試行することではありません。On HoloLens (first gen), interactions and gestures should generally derive their targeting from the user's head gaze, rather than trying to render or interact at the hand's location directly. 相互作用が開始されたら、操作やナビゲーションジェスチャと同様に、ハンドの相対的な動きを使ってジェスチャを制御できます。Once an interaction has started, relative motions of the hand may be used to control the gesture, as with the Manipulation or Navigation gesture.

関連項目See also