Mains et contrôleurs de mouvement dans DirectXHands and motion controllers in DirectX

Notes

Cet article s’applique aux API natives WinRT héritées.This article relates to the legacy WinRT native APIs. Pour les nouveaux projets d’application native, nous vous recommandons d’utiliser l' API OpenXR.For new native app projects, we recommend using the OpenXR API.

Dans Windows Mixed Reality, les entrées de la main et du contrôleur de mouvement sont gérées via les API d’entrée spatiale, qui se trouvent dans l’espace de noms Windows. UI. Input. spatial .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. Cela vous permet de gérer facilement des actions courantes telles que la sélection de la même façon sur les deux mains et les contrôleurs de mouvement.This enables you to easily handle common actions like Select presses the same way across both hands and motion controllers.

Prise en mainGetting started

Pour accéder aux entrées spatiales dans Windows Mixed Reality, commencez par l’interface SpatialInteractionManager.To access spatial input in Windows Mixed Reality, start with the SpatialInteractionManager interface. Vous pouvez accéder à cette interface en appelant SpatialInteractionManager :: GetForCurrentView, généralement au cours du démarrage de l’application.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();

Le travail du SpatialInteractionManager consiste à fournir l’accès à SpatialInteractionSources, qui représente une source d’entrée.The SpatialInteractionManager's job is to provide access to SpatialInteractionSources, which represent a source of input. Il existe trois types de SpatialInteractionSources disponibles dans le système.There are three kinds of SpatialInteractionSources available in the system.

  • La main représente la main détectée d’un utilisateur.Hand represents a user's detected hand. Les sources de main offrent différentes fonctionnalités basées sur l’appareil, allant des gestes de base sur HoloLens au suivi complet sur 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.
  • Le contrôleur représente un contrôleur de mouvement jumelé.Controller represents a paired motion controller. Les contrôleurs de mouvement peuvent offrir des fonctionnalités différentes, par exemple, sélectionner des déclencheurs, des boutons de menu, des boutons, des pavés tactiles et des Thumbsticks.Motion controllers can offer different capabilities, for example, Select triggers, Menu buttons, Grasp buttons, touchpads, and thumbsticks.
  • La voix représente les mots-clés détectés par le système vocal de l’utilisateur.Voice represents the user's voice speaking system-detected keywords. Par exemple, cette source injecte une pression SELECT et une mise en sortie chaque fois que l’utilisateur dit « Select ».For example, this source will inject a Select press and release whenever the user says "Select".

Les données par trame pour une source sont représentées par l’interface SpatialInteractionSourceState .Per-frame data for a source is represented by the SpatialInteractionSourceState interface. Il existe deux façons d’accéder à ces données, selon que vous souhaitez utiliser un modèle piloté par des événements ou basé sur l’interrogation dans votre application.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.

Entrée pilotée par les événementsEvent-driven input

SpatialInteractionManager fournit un certain nombre d’événements que votre application peut écouter.The SpatialInteractionManager provides a number of events that your app can listen for. Voici quelques exemples : SourcePressed, [SourceReleased et SourceUpdated.A few examples include SourcePressed, [SourceReleased, and SourceUpdated.

Par exemple, le code suivant raccorde un gestionnaire d’événements appelé MyApp :: OnSourcePressed à l’événement SourcePressed.For example, the following code hooks up an event handler called MyApp::OnSourcePressed to the SourcePressed event. Cela permet à votre application de détecter les presses sur n’importe quel type de source d’interaction.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 });

Cet événement appuyé est envoyé à votre application de manière asynchrone, avec les SpatialInteractionSourceState correspondants au moment où la pression s’est produite.This pressed event is sent to your app asynchronously, along with the corresponding SpatialInteractionSourceState at the time the press happened. Votre application ou moteur de jeu peut souhaiter commencer à traiter immédiatement ou placer en file d’attente les données d’événement dans votre routine de traitement d’entrée.Your app or game engine may want to start processing right away or queue up the event data in your input processing routine. Voici une fonction de gestionnaire d’événements pour l’événement SourcePressed, qui vérifie si le bouton Sélectionner a été enfoncé.Here's an event handler function for the SourcePressed event, which checks whether the select button has been 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
    }
}

Le code ci-dessus vérifie uniquement l’appui sur « Select », qui correspond à l’action principale sur l’appareil.The above code only checks for the 'Select' press, which corresponds to the primary action on the device. Les exemples incluent la réalisation d’un AirTap sur HoloLens ou l’extraction du déclencheur sur un contrôleur de mouvement.Examples include doing an AirTap on HoloLens or pulling the trigger on a motion controller. Les presses « Select » représentent l’intention de l’utilisateur d’activer l’hologramme qu’il cible.'Select' presses represent the user's intention to activate the hologram they're targeting. L’événement SourcePressed se déclenche pour un certain nombre de boutons et de mouvements différents. vous pouvez inspecter les autres propriétés sur le SpatialInteractionSource pour tester ces cas-là.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.

Entrée basée sur l’interrogationPolling-based input

Vous pouvez également utiliser SpatialInteractionManager pour interroger l’état actuel de l’entrée dans chaque cadre.You can also use SpatialInteractionManager to poll for the current state of input every frame. Pour ce faire, appelez GetDetectedSourcesAtTimestamp chaque frame.To do this, call GetDetectedSourcesAtTimestamp every frame. Cette fonction retourne un tableau contenant un SpatialInteractionSourceState pour chaque SpatialInteractionSourceactif.This function returns an array containing one SpatialInteractionSourceState for every active SpatialInteractionSource. Cela signifie un pour chaque contrôleur de mouvement actif, un pour chaque main suivie et un pour la parole si une commande « Select » a été récemment mise en circulation.This means one for each active motion controller, one for each tracked hand, and one for speech if a 'select' command was recently uttered. Vous pouvez ensuite inspecter les propriétés sur chaque SpatialInteractionSourceState pour piloter l’entrée dans votre application.You can then inspect the properties on each SpatialInteractionSourceState to drive input into your application.

Voici un exemple de vérification de l’action « Select » à l’aide de la méthode d’interrogation.Here's an example of how to check for the 'select' action using the polling method. La variable de prédiction représente un objet HolographicFramePrediction , qui peut être obtenu à partir du HolographicFrame.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
    }
}

Chaque SpatialInteractionSource a un ID, que vous pouvez utiliser pour identifier les nouvelles sources et mettre en corrélation les sources existantes d’une image à l’autre.Each SpatialInteractionSource has an ID, which you can use to identify new sources and correlate existing sources from frame to frame. Les mains reçoivent un nouvel ID à chaque fois qu’ils sortent et entrent dans l’angle de la connexion, mais les ID de contrôleur restent statiques pendant la durée de la session.Hands get a new ID every time they leave and enter the FOV, but controller IDs remain static for the duration of the session. Vous pouvez utiliser les événements sur SpatialInteractionManager tels que SourceDetected et SourceLost, pour réagir quand les mains entrent ou quittent la vue de l’appareil, ou lorsque les contrôleurs de mouvement sont activés/désactivés ou sont jumelés/non couplés.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.

Différences entre les poses prédites et l’historiquePredicted vs. historical poses

GetDetectedSourcesAtTimestamp a un paramètre timestamp.GetDetectedSourcesAtTimestamp has a timestamp parameter. Cela vous permet de demander l’État et de créer des données qui sont prédites ou historiques, ce qui vous permet de mettre en corrélation les interactions spatiales avec d’autres sources d’entrée.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. Par exemple, lors du rendu de la position de la main dans le frame actuel, vous pouvez transmettre l’horodatage prédit fourni par HolographicFrame.For example, when rendering the hand's position in the current frame, you can pass in the predicted timestamp provided by the HolographicFrame. Cela permet au système de prédire la position de la main pour s’aligner étroitement avec la sortie du frame rendu, réduisant ainsi la latence perçue.This enables the system to forward-predict the hand position to closely align with the rendered frame output, minimizing perceived latency.

Toutefois, une telle pose prédite ne produit pas un rayon de pointage idéal pour le ciblage avec une source d’interaction.However, such a predicted pose doesn't produce an ideal pointing ray for targeting with an interaction source. Par exemple, quand vous appuyez sur un bouton de contrôleur de mouvement, il peut falloir jusqu’à 20 ms pour que cet événement se propage via Bluetooth au système d’exploitation.For example, when a motion controller button is pressed, it can take up to 20 ms for that event to bubble up through Bluetooth to the operating system. De même, une fois qu’un utilisateur a fait un mouvement manuel, un certain laps de temps peut s’écouler avant que le système ne détecte le geste et que votre application l’interroge.Similarly, after a user does a hand gesture, some amount of time may pass before the system detects the gesture and your app then polls for it. Au moment où votre application interroge une modification d’État, les points de vue et de main sont utilisés pour cibler cette interaction qui s’est effectivement produite dans le passé.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. Si vous ciblez en passant l’horodatage de votre HolographicFrame actuel à GetDetectedSourcesAtTimestamp, le pose sera au contraire prévisible dans le rayon cible au moment de l’affichage de l’image, ce qui peut être supérieur à 20 ms à l’avenir.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 20 ms in the future. Ce nouveau point est idéal pour le rendu de la source d’interaction, mais il compose notre problème de temps pour cibler l’interaction, car le ciblage de l’utilisateur s’est produit dans le passé.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.

Heureusement, les événements SourcePressed, [SourceReleased et SourceUpdated fournissent l' État historique associé à chaque événement d’entrée.Fortunately, the SourcePressed, [SourceReleased, and SourceUpdated events provide the historical State associated with each input event. Cela comprend directement les mises à disposition de l’historique et des handles disponibles via TryGetPointerPose, ainsi qu’un horodateur historique que vous pouvez transmettre à d’autres API pour établir une corrélation avec cet événement.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.

Cela entraîne les meilleures pratiques suivantes lors du rendu et du ciblage avec les mains et les contrôleurs de chaque cadre :That leads to the following best practices when rendering and targeting with hands and controllers each frame:

  • Pour le rendu de la main/du contrôleur de chaque trame, votre application doit interroger la partie préprédite de chaque source d’interaction au moment de la photonique du frame actuel.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. Vous pouvez interroger toutes les sources d’interaction en appelant GetDetectedSourcesAtTimestamp chaque frame, en transmettant l’horodatage prédit fourni par HolographicFrame :: CurrentPrediction.You can poll for all interaction sources by calling GetDetectedSourcesAtTimestamp each frame, passing in the predicted timestamp provided by HolographicFrame::CurrentPrediction.
  • Pour le ciblage de la main/du contrôleur sur une presse ou une mise en version, votre application doit gérer les événements appuyés/libérés, Raycasting en fonction de la position de l' historique ou de la main pour cet événement.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. Pour ce faire, vous devez gérer l’événement SourcePressed ou SourceReleased , obtenir la propriété State à partir des arguments d’événement, puis appeler sa méthode TryGetPointerPose .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.

Propriétés d’entrée entre appareilsCross-device input properties

L’API SpatialInteractionSource prend en charge les contrôleurs et les systèmes de suivi de main avec un large éventail de fonctionnalités.The SpatialInteractionSource API supports controllers and hand tracking systems with a wide range of capabilities. Un certain nombre de ces fonctionnalités sont communes entre les types d’appareils.A number of these capabilities are common between device types. Par exemple, le suivi des mains et les contrôleurs de mouvement fournissent tous deux une action « sélectionner » et une position 3D.For example, hand tracking and motion controllers both provide a 'select' action and a 3D position. Dans la mesure du possible, l’API mappe ces fonctionnalités communes aux mêmes propriétés sur le SpatialInteractionSource.Wherever possible, the API maps these common capabilities to the same properties on the SpatialInteractionSource. Cela permet aux applications de prendre en charge plus facilement un large éventail de types d’entrée.This enables applications to more easily support a wide range of input types. Le tableau suivant décrit les propriétés prises en charge et leur comparaison entre les types d’entrée.The following table describes the properties that are supported, and how they compare across input types.

PropriétéProperty DescriptionDescription Gestes HoloLens (1ère génération)HoloLens(1st gen) Gestures Contrôleurs de mouvementMotion Controllers Mains articuléesArticulated Hands
SpatialInteractionSource ::mainSpatialInteractionSource::Handedness La main droite ou gauche/le contrôleur.Right or left hand / controller. Non pris en chargeNot Supported Prise en chargeSupported Prise en chargeSupported
SpatialInteractionSourceState ::IsSelectPressedSpatialInteractionSourceState::IsSelectPressed État actuel du bouton principal.Current state of the primary button. Robinet d’airAir Tap DéclencheurTrigger Robinet à air lâche (pincement vertical)Relaxed Air Tap (upright pinch)
SpatialInteractionSourceState ::IsGraspedSpatialInteractionSourceState::IsGrasped État actuel du bouton de manipulation.Current state of the grab button. Non pris en chargeNot Supported Bouton de manipulationGrab button Pincer ou fermer la mainPinch or Closed Hand
SpatialInteractionSourceState ::IsMenuPressedSpatialInteractionSourceState::IsMenuPressed État actuel du bouton de menu.Current state of the menu button. Non pris en chargeNot Supported Bouton de menuMenu Button Non pris en chargeNot Supported
SpatialInteractionSourceLocation ::positionSpatialInteractionSourceLocation::Position Emplacement XYZ de la main ou de la position de la poignée sur le contrôleur.XYZ location of the hand or grip position on the controller. Emplacement PalmPalm location Poignée de pose positionGrip pose position Emplacement PalmPalm location
SpatialInteractionSourceLocation ::orientationSpatialInteractionSourceLocation::Orientation Quaternion représentant l’orientation de la main ou de la poignée sur le contrôleur.Quaternion representing the orientation of the hand or grip pose on the controller. Non pris en chargeNot Supported Poignée d’orientation de poseGrip pose orientation Orientation PalmPalm orientation
SpatialPointerInteractionSourcePose ::positionSpatialPointerInteractionSourcePose::Position Origine du rayon de pointage.Origin of the pointing ray. Non pris en chargeNot Supported Prise en chargeSupported Prise en chargeSupported
SpatialPointerInteractionSourcePose ::ForwardDirectionSpatialPointerInteractionSourcePose::ForwardDirection Direction du rayon de pointage.Direction of the pointing ray. Non pris en chargeNot Supported Prise en chargeSupported Prise en chargeSupported

Certaines des propriétés ci-dessus ne sont pas disponibles sur tous les appareils, et l’API fournit un moyen de les tester.Some of the above properties aren't available on all devices, and the API provides a means to test for this. Par exemple, vous pouvez inspecter la propriété SpatialInteractionSource :: IsGraspSupported pour déterminer si la source fournit une action saisissante.For example, you can inspect the SpatialInteractionSource::IsGraspSupported property to determine whether the source provides a grasp action.

Poignée de pose et pose de pointageGrip pose vs. pointing pose

Windows Mixed Reality prend en charge les contrôleurs de mouvement dans différents facteurs de forme.Windows Mixed Reality supports motion controllers in different form factors. Il prend également en charge les systèmes de suivi articulés.It also supports articulated hand tracking systems. Tous ces systèmes ont des relations différentes entre la position de la main et la direction « avant » naturelle que les applications doivent utiliser pour le pointage ou le rendu des objets dans la main de l’utilisateur.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. Pour prendre en charge tout cela, il existe deux types de poses 3D fournis pour le suivi des mains et les contrôleurs de mouvement.To support all of this, there are two types of 3D poses provided for both hand tracking and motion controllers. La première est la poignée, qui représente la position de l’utilisateur.The first is grip pose, which represents the user's hand position. Le deuxième point de pose, qui représente un rayon de pointage provenant de la main ou du contrôleur de l’utilisateur.The second is pointing pose, which represents a pointing ray originating from the user's hand or controller. Par conséquent, si vous souhaitez afficher la main de l’utilisateur ou un objet détenu par l’utilisateur, tel qu’un épée ou un pistolet, utilisez la poignée.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. Si vous souhaitez raycast du contrôleur ou de la main, par exemple quand l’utilisateur est * * pointant sur l’interface utilisateur, utilisez le point de pose.If you want to raycast from the controller or hand, for example when the user is **pointing at UI, use the pointing pose.

Vous pouvez accéder à la poignée à l’aide de SpatialInteractionSourceState ::P ropriétés :: TryGetLocation (...). Elle est définie comme suit :You can access the grip pose through SpatialInteractionSourceState::Properties::TryGetLocation(...). It's defined as follows:

  • Position de la poignée: le centre de la poche quand il maintient le contrôleur naturellement, ajusté à gauche ou à droite pour centrer la position au sein de la poignée.The grip position: The palm centroid when holding the controller naturally, adjusted left or right to center the position within the grip.
  • Axe droit de l’orientation de la poignée: lorsque vous ouvrez complètement votre main pour former une pose plate à 5 doigts, le rayon normal à votre paume (en avant à partir de la poche de gauche, en arrière depuis la paume de droite)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)
  • Axe avant de l’orientation de la poignée: quand vous fermez partiellement votre main (comme si vous détenir le contrôleur), le rayon qui pointe vers l’avant dans le tube formé par vos doigts non thumbs.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.
  • Axe vers le haut de l’orientation: l’axe vers le haut, impliqué dans les définitions Right et Forward.The grip orientation's Up axis: The Up axis implied by the Right and Forward definitions.

Vous pouvez accéder à la pose du pointeur par le biais de SpatialInteractionSourceState ::P ropriétés :: TryGetLocation (...) :: SourcePointerPose ou SpatialInteractionSourceState :: TryGetPointerPose (...) :: TryGetInteractionSourcePose.You can access the pointer pose through SpatialInteractionSourceState::Properties::TryGetLocation(...)::SourcePointerPose or SpatialInteractionSourceState::TryGetPointerPose(...)::TryGetInteractionSourcePose.

Propriétés d’entrée spécifiques au contrôleurController-specific input properties

Pour les contrôleurs, SpatialInteractionSource a une propriété de contrôleur avec des fonctionnalités supplémentaires.For controllers, the SpatialInteractionSource has a Controller property with additional capabilities.

  • HasThumbstick : Si la valeur est true, le contrôleur a un stick analogique.HasThumbstick: If true, the controller has a thumbstick. Inspectez la propriété ControllerProperties de SpatialInteractionSourceState pour obtenir les valeurs de stick analogique x et y (ThumbstickX et ThumbstickY), ainsi que l’état enfoncé (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 : Si la valeur est true, le contrôleur a un pavé tactile.HasTouchpad: If true, the controller has a touchpad. Inspectez la propriété ControllerProperties de SpatialInteractionSourceState pour obtenir les valeurs de pavé tactile x et y (TouchpadX et touchpad), et pour savoir si l’utilisateur touche le bloc (IsTouchpadTouched) et s’il appuie sur le pavé tactile (IsTouchpadPressed).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're pressing the touchpad down (IsTouchpadPressed).
  • SimpleHapticsController : L’API SimpleHapticsController pour le contrôleur vous permet d’inspecter les fonctionnalités haptique du contrôleur et vous permet également de contrôler les commentaires haptique.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.

La plage du pavé tactile et du stick analogique est comprise entre-1 et 1 pour les deux axes (de bas en haut et de gauche à droite).The range for touchpad and thumbstick is -1 to 1 for both axes (from bottom to top, and from left to right). La plage du déclencheur analogique, accessible à l’aide de la propriété SpatialInteractionSourceState :: SelectPressedValue, a une plage comprise entre 0 et 1.The range for the analog trigger, which is accessed using the SpatialInteractionSourceState::SelectPressedValue property, has a range of 0 to 1. La valeur 1 est corrélée avec IsSelectPressed égal à true ; toute autre valeur est corrélée avec IsSelectPressed égal à false.A value of 1 correlates with IsSelectPressed being equal to true; any other value correlates with IsSelectPressed being equal to false.

Suivi articuléArticulated hand tracking

L’API Windows Mixed Reality assure une prise en charge complète du suivi articulé, par exemple sur HoloLens 2.The Windows Mixed Reality API provides full support for articulated hand tracking, for example on HoloLens 2. Le suivi articulé peut être utilisé pour implémenter la manipulation directe et les modèles d’entrée de point et de validation dans vos applications.Articulated hand tracking can be used to implement direct manipulation and point-and-commit input models in your applications. Il peut également être utilisé pour créer des interactions entièrement personnalisées.It can also be used to author fully custom interactions.

Squelette de mainHand skeleton

Le suivi articulé fournit un squelette de 25 jointures qui permet de nombreux types différents d’interactions.Articulated hand tracking provides a 25 joint skeleton that enables many different types of interactions. La structure fournit cinq jointures pour l’index/le milieu/l’anneau/les petits doigts, quatre articulations pour le pouce et une articulation du poignet.The skeleton provides five joints for the index/middle/ring/little fingers, four joints for the thumb, and one wrist joint. L’articulation du poignet sert de base de la hiérarchie.The wrist joint serves as the base of the hierarchy. L’image suivante illustre la disposition du squelette.The following picture illustrates the layout of the skeleton.

Squelette de main

Dans la plupart des cas, chaque joint est nommé en fonction du segment qu’il représente.In most cases, each joint is named based on the bone that it represents. Étant donné qu’il y a deux segments à chaque articulation, nous utilisons une convention pour nommer chaque jointure en fonction du segment enfant à cet emplacement.Since there are two bones at every joint, we use a convention of naming each joint based on the child bone at that location. Le segment enfant est défini comme le segment du poignet.The child bone is defined as the bone further from the wrist. Par exemple, l’articulation « index proximal » contient la position de début de l’index de l’OS proximal et l’orientation de ce segment.For example, the "Index Proximal" joint contains the beginning position of the index proximal bone, and the orientation of that bone. Elle ne contient pas la position de fin du segment.It doesn't contain the ending position of the bone. Si vous en avez besoin, vous pouvez le faire à partir de la jointure suivante dans la hiérarchie, l’articulation « index intermédiaire ».If you need that, you'd get it from the next joint in the hierarchy, the "Index Intermediate" joint.

Outre les 25 articulations hiérarchiques, le système fournit un joint Palm.In addition to the 25 hierarchical joints, the system provides a palm joint. La paume n’est généralement pas considérée comme faisant partie de la structure squelettique.The palm isn't typically considered part of the skeletal structure. Elle est fournie uniquement comme un moyen pratique d’obtenir la position et l’orientation globales de la main.It's provided only as a convenient way to get the hand's overall position and orientation.

Les informations suivantes sont fournies pour chaque jointure :The following information is provided for each joint:

NomName DescriptionDescription
PositionPosition position 3D de la jointure, disponible dans n’importe quel système de coordonnées demandé.3D position of the joint, available in any requested coordinate system.
OrientationOrientation orientation 3D du segment, disponible dans n’importe quel système de coordonnées demandé.3D orientation of the bone, available in any requested coordinate system.
RadiusRadius Distance à la surface de l’apparence à la position conjointe.Distance to surface of the skin at the joint position. Utile pour le paramétrage des interactions directes ou des visualisations qui reposent sur la largeur du doigt.Useful for tuning direct interactions or visualizations that rely on finger width.
PrécisionAccuracy Fournit une indication sur la confiance que le système estime sur les informations de cette articulation.Provides a hint on how confident the system feels about this joint's information.

Vous pouvez accéder aux données squelettes à l’aide d’une fonction sur le SpatialInteractionSourceState.You can access the hand skeleton data through a function on the SpatialInteractionSourceState. La fonction est appelée TryGetHandPoseet retourne un objet appelé HandPose.The function is called TryGetHandPose, and it returns an object called HandPose. Si la source ne prend pas en charge les mains articulées, cette fonction retournera la valeur null.If the source doesn't support articulated hands, then this function will return null. Une fois que vous disposez d’un HandPose, vous pouvez obtenir les données communes actuelles en appelant TryGetJoint, avec le nom de la jointure qui vous intéresse.Once you have a HandPose, you can get current joint data by calling TryGetJoint, with the name of the joint you're interested in. Les données sont retournées sous la forme d’une structure JointPose .The data is returned as a JointPose structure. Le code suivant obtient la position de l’info-bulle de l’index.The following code gets the position of the index finger tip. La variable CurrentState représente une instance de 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
    }
}

Maille manuelleHand mesh

L’API de suivi articulé permet d’obtenir un maillage de handles de triangle entièrement déformable.The articulated hand tracking API allows for a fully deformable triangle hand mesh. Ce maillage peut se déstructurer en temps réel, ainsi que le squelette de la main, et est utile pour la visualisation et les techniques de physique avancées.This mesh can deform in real time along with the hand skeleton, and is useful for visualization and advanced physics techniques. Pour accéder à la maille manuelle, vous devez d’abord créer un objet HandMeshObserver en appelant TryCreateHandMeshObserverAsync sur SpatialInteractionSource.To access the hand mesh, you need to first create a HandMeshObserver object by calling TryCreateHandMeshObserverAsync on the SpatialInteractionSource. Cette opération ne doit être effectuée qu’une seule fois par source, généralement la première fois que vous la voyez.This only needs to be done once per source, typically the first time you see it. Cela signifie que vous appellerez cette fonction pour créer un objet HandMeshObserver chaque fois qu’une main entre dans l’angle de la montre.That means you'll call this function to create a HandMeshObserver object whenever a hand enters the FOV. Il s’agit d’une fonction Async. vous devez donc traiter un peu d’accès concurrentiel ici.This is an async function, so you'll have to deal with a bit of concurrency here. Une fois disponible, vous pouvez demander à l’objet HandMeshObserver pour la mémoire tampon d’index de triangle en appelant GetTriangleIndices.Once available, you can ask the HandMeshObserver object for the triangle index buffer by calling GetTriangleIndices. Les index ne changent pas le frame sur le frame, ce qui vous permet de les obtenir et de les mettre en cache pendant la durée de vie de la source.Indices don't change frame over frame, so you can get those once and cache them for the lifetime of the source. Les index sont fournis dans l’ordre d’enroulement dans le sens des aiguilles d’une montre.Indices are provided in clockwise winding order.

Le code suivant permet de tourner un std :: thread détaché pour créer l’observateur de maillage et d’extraire le tampon d’index une fois que l’observateur de maillage est disponible.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. Il démarre à partir d’une variable appelée CurrentState, qui est une instance de SpatialInteractionSourceState représentant une main.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);
        newHandMeshObserver.GetTriangleIndices(indices);

        // Save the indices and handMeshObserver for later use - and use a mutex to synchronize access if needed!
     }
});
createObserverThread.detach();

Le démarrage d’un thread détaché n’est qu’une option pour gérer les appels asynchrones.Starting a detached thread is just one option for handling async calls. Vous pouvez également utiliser les nouvelles fonctionnalités de co_await prises en charge par C++/WinRT.Alternatively, you could use the new co_await functionality supported by C++/WinRT.

Une fois que vous avez un objet HandMeshObserver, vous devez le conserver pendant la durée pendant laquelle son SpatialInteractionSource correspondant est actif.Once you have a HandMeshObserver object, you should hold onto it for the duration that its corresponding SpatialInteractionSource is active. Ensuite, chaque frame, vous pouvez lui demander la dernière mémoire tampon de vertex qui représente la main en appelant GetVertexStateForPose et en passant une instance HandPose qui représente le pose pour lequel vous souhaitez obtenir des sommets.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. Chaque vertex de la mémoire tampon a une position et un normal.Each vertex in the buffer has a position and a normal. Voici un exemple d’obtention de l’ensemble actuel de vertex pour une maille.Here's an example of how to get the current set of vertices for a hand mesh. Comme précédemment, la variable CurrentState représente une instance de SpatialInteractionSourceState.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);
    vertexState.GetVertices(vertices);

    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
    }
}

Contrairement aux jointures squelettes, l’API de maillage de la main ne vous permet pas de spécifier un système de coordonnées pour les vertex.In contrast to skeleton joints, the hand mesh API doesn't allow you to specify a coordinate system for the vertices. Au lieu de cela, le HandMeshVertexState spécifie le système de coordonnées dans lequel les vertex sont fournis.Instead, the HandMeshVertexState specifies the coordinate system that the vertices are provided in. Vous pouvez ensuite obtenir une transformation de maillage en appelant TryGetTransformTo et en spécifiant le système de coordonnées souhaité.You can then get a mesh transform by calling TryGetTransformTo and specifying the coordinate system you want. Vous devez utiliser cette transformation de maille chaque fois que vous travaillez avec les vertex.You'll need to use this mesh transform whenever you work with the vertices. Cette approche réduit la surcharge du processeur, en particulier si vous utilisez uniquement la maille à des fins de rendu.This approach reduces CPU overhead, especially if you're only using the mesh for rendering purposes.

Mouvements composites de point de regard et de validationGaze and Commit composite gestures

Pour les applications qui utilisent le modèle d’entrée de point de vue et de validation, en particulier sur HoloLens (First Gen), l’API d’entrée spatiale fournit un SpatialGestureRecognizer facultatif qui peut être utilisé pour activer les gestes composites reposant sur l’événement « 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 enable composite gestures built on top of the 'select' event. En acheminant les interactions entre le SpatialInteractionManager et le SpatialGestureRecognizer d’un hologramme, les applications peuvent détecter les événements de TAP, de maintien, de manipulation et de navigation uniformément entre les mains, les voix et les périphériques d’entrée spatiales, sans avoir à gérer manuellement les presses et les mises en production.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 effectue uniquement une ambiguïté minimale entre l’ensemble de mouvements que vous demandez.SpatialGestureRecognizer does only the minimal disambiguation between the set of gestures that you request. Par exemple, si vous demandez simplement TAP, l’utilisateur peut conserver son doigt tant qu’il le souhaite et un TAP continue à se produire.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. Si vous demandez un tap-and-hold, une fois que vous avez appuyé sur une seconde du doigt, le geste passe à un blocage et un TAP ne se produit plus.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.

Pour utiliser SpatialGestureRecognizer, gérez l’événement InteractionDetected de SpatialInteractionManager et récupérez le SpatialPointerPose qui y est exposé.To use SpatialGestureRecognizer, handle the SpatialInteractionManager's InteractionDetected event and grab the SpatialPointerPose exposed there. Utilisez le point de vue de la tête du point de vue de l’utilisateur pour croiser les hologrammes et les maillages des surfaces dans l’environnement de l’utilisateur afin de déterminer ce à quoi l’utilisateur a l’intention d’interagir.Use the user's head gaze ray from this pose to intersect with the holograms and surface meshes in the user's surroundings to determine what the user is intending to interact with. Ensuite, acheminez le SpatialInteraction dans les arguments d’événement vers le SpatialGestureRecognizer de l’hologramme cible, à l’aide de sa méthode CaptureInteraction .Then, route the SpatialInteraction in the event arguments to the target hologram's SpatialGestureRecognizer, using its CaptureInteraction method. Cela commence à interpréter cette interaction en fonction du SpatialGestureSettings défini sur ce module de reconnaissance au moment de la création, ou par TrySetGestureSettings.This starts interpreting that interaction according to the SpatialGestureSettings set on that recognizer at creation time - or by TrySetGestureSettings.

Sur HoloLens (First Gen), les interactions et les gestes doivent dériver leur ciblage du point de regard de l’utilisateur, plutôt que de rendre ou d’interagir à l’emplacement de la main.On HoloLens (first gen), interactions and gestures should derive their targeting from the user's head gaze, rather than rendering or interacting at the hand's location. Une fois qu’une interaction a démarré, les mouvements relatifs de la main peuvent être utilisés pour contrôler le mouvement, comme avec la manipulation ou le mouvement de navigation.Once an interaction has started, relative motions of the hand may be used to control the gesture, as with the Manipulation or Navigation gesture.

Voir aussiSee also