Controladores de mãos e de movimento no DirectXHands and motion controllers in DirectX

No Windows Mixed Reality, a entrada do controlador de movimento e a mão são manipuladas por meio de APIs de entrada espaciais, encontradas no namespace Windows. UI. Input. espacial .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. Isso permite que você manipule facilmente ações comuns, como Select , da mesma maneira em ambos os controladores de mãos e de movimento.This enables you to easily handle common actions like Select presses the same way across both hands and motion controllers.

IntroduçãoGetting started

Para acessar a entrada espacial na realidade mista do Windows, comece com a interface SpatialInteractionManager.To access spatial input in Windows Mixed Reality, start with the SpatialInteractionManager interface. Você pode acessar essa interface chamando SpatialInteractionManager:: GetForCurrentView, normalmente durante a inicialização do aplicativo.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();

O trabalho do SpatialInteractionManager é fornecer acesso ao SpatialInteractionSources, que representa uma fonte de entrada.The SpatialInteractionManager's job is to provide access to SpatialInteractionSources, which represent a source of input. Há três tipos de SpatialInteractionSources disponíveis no sistema.There are three kinds of SpatialInteractionSources available in the system.

  • A mão representa a mão detectada do usuário.Hand represents a user's detected hand. As fontes de mão oferecem diferentes recursos com base no dispositivo, variando de gestos básicos no HoloLens até o controle de mão totalmente articulado no 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.
  • O controlador representa um controlador de movimento emparelhado.Controller represents a paired motion controller. Os controladores de movimento podem oferecer uma variedade de recursos.Motion controllers can offer a variety of capabilities. Por exemplo: selecionar gatilhos, botões de menu, entender botões, touchpads e Thumbsticks.For example: Select triggers, Menu buttons, Grasp buttons, touchpads and thumbsticks.
  • Voz representa as palavras-chave detectadas pelo sistema de fala de voz do usuário.Voice represents the user's voice speaking system-detected keywords. Por exemplo, essa fonte injetará uma prensa e uma liberação Select sempre que o usuário disser "Select".For example, this source will inject a Select press and release whenever the user says "Select".

Os dados por quadro de uma fonte são representados pela interface SpatialInteractionSourceState .Per-frame data for a source is represented by the SpatialInteractionSourceState interface. Há duas maneiras diferentes de acessar esses dados, dependendo se você deseja usar um modelo controlado por eventos ou baseado em sondagem em seu aplicativo.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.

Entrada orientada por eventoEvent-driven input

O SpatialInteractionManager fornece vários eventos que seu aplicativo pode escutar.The SpatialInteractionManager provides a number of events that your app can listen for. Alguns exemplos incluem SourcePressed, SourceReleased e SourceUpdated.A few examples include SourcePressed, SourceReleased and SourceUpdated.

Por exemplo, o código a seguir conecta um manipulador de eventos chamado MyApp:: OnSourcePressed ao evento SourcePressed.For example, the following code hooks up an event handler called MyApp::OnSourcePressed to the SourcePressed event. Isso permite que seu aplicativo detecte pressionamentos em qualquer tipo de fonte de interação.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 });

Esse evento pressionado é enviado para seu aplicativo de forma assíncrona, junto com o SpatialInteractionSourceState correspondente no momento em que a ocorrência ocorreu.This pressed event is sent to your app asynchronously, along with the corresponding SpatialInteractionSourceState at the time the press happened. Seu aplicativo ou mecanismo de jogo pode querer executar algum processamento imediatamente ou você pode querer enfileirar os dados de evento em sua rotina de processamento de entrada.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. Aqui está uma função de manipulador de eventos para o evento SourcePressed, que mostra como verificar se o botão de seleção foi pressionado.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
    }
}

O código acima verifica apenas a prensa ' Select ', que corresponde à ação principal no dispositivo.The above code only checks for the 'Select' press, which corresponds to the primary action on the device. Os exemplos incluem fazer um AirTap no HoloLens ou extrair o gatilho em um controlador de movimento.Examples include doing an AirTap on HoloLens or pulling the trigger on a motion controller. "Select" Presss representam a intenção do usuário de ativar o holograma que eles estão direcionando.'Select' presses represent the user's intention to activate the hologram they are targeting. O evento SourcePressed será acionado para vários botões e gestos diferentes, e você poderá inspecionar outras propriedades no SpatialInteractionSource para testar esses casos.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.

Entrada baseada em sondagemPolling-based input

Você também pode usar SpatialInteractionManager para sondar o estado atual de entrada de cada quadro.You can also use SpatialInteractionManager to poll for the current state of input every frame. Para fazer isso, basta chamar GetDetectedSourcesAtTimestamp todos os quadros.To do this, simply call GetDetectedSourcesAtTimestamp every frame. Essa função retorna uma matriz que contém um SpatialInteractionSourceState para cada SpatialInteractionSourceativo.This function returns an array containing one SpatialInteractionSourceState for every active SpatialInteractionSource. Isso significa que um para cada controlador de movimento ativo, um para cada mão controlada e outro para fala se um comando ' Select ' foi recentemente desmarcado.This means one for each active motion controller, one for each tracked hand, and one for speech if a 'select' command was recently uttered. Em seguida, você pode inspecionar as propriedades em cada SpatialInteractionSourceState para direcionar a entrada para o seu aplicativo.You can then inspect the properties on each SpatialInteractionSourceState to drive input into your application.

Aqui está um exemplo de como verificar a ação ' Select ' usando o método de sondagem.Here is an example of how to check for the 'select' action using the polling method. Observe que a variável de previsão representa um objeto HolographicFramePrediction , que pode ser obtido do 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
    }
}

Cada SpatialInteractionSource tem uma ID, que pode ser usada para identificar novas fontes e correlacionar as fontes existentes do quadro ao quadro.Each SpatialInteractionSource has an ID, which you can use to identify new sources and correlate existing sources from frame to frame. As mãos recebem uma nova ID toda vez que deixam e inserem o FOV, mas as IDs de controlador permanecem estáticas durante a sessão.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. Você pode usar os eventos em SpatialInteractionManager, como SourceDetected e SourceLost, para reagir quando as mãos entrarem ou saírem do modo de exibição do dispositivo ou quando os controladores de movimento estiverem ativados ou desligados ou estiverem emparelhados/não emparelhados.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.

Previstos versus histórico de posesPredicted vs. historical poses

Observe que GetDetectedSourcesAtTimestamp tem um parâmetro timestamp.Note that GetDetectedSourcesAtTimestamp has a timestamp parameter. Isso permite solicitar o estado e representar os dados que são previstos ou históricos, permitindo que você correlacione as interações espaciais com outras fontes de entrada.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. Por exemplo, ao renderizar a posição da mão no quadro atual, você pode passar o carimbo de data/hora previsto fornecido pelo HolographicFrame.For example, when rendering the hand's position in the current frame, you can pass in the predicted timestamp provided by the HolographicFrame. Isso permite que o sistema faça uma previsão antecipada da posição da mão para alinhar fortemente com a saída do quadro renderizado, minimizando a latência percebida.This enables the system to forward-predict the hand position to closely align with the rendered frame output, minimizing perceived latency.

No entanto, tal pose prevista não produz um apontador ideal para direcionar com uma fonte de interação.However, such a predicted pose does not produce an ideal pointing ray for targeting with an interaction source. Por exemplo, quando um botão de controlador de movimento é pressionado, pode levar até 20 ms para que esse evento seja emergido por meio do Bluetooth para o sistema operacional.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. Da mesma forma, depois que um usuário executa um gesto de mão, uma quantidade de tempo pode passar antes que o sistema detecte o gesto e seu aplicativo o sonda para ele.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. Quando o aplicativo sonda uma alteração de estado, a cabeça e a mão são usadas para direcionar essa interação realmente ocorrida no passado.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. Se você se destinar passando o carimbo de data/hora atual do HolographicFrame para GetDetectedSourcesAtTimestamp, a pose será encaminhada prevista para o destino Ray no momento em que o quadro será exibido, o que poderia ser mais de 20 ms no futuro.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. Essa futura pose é boa para renderizar a origem da interação, mas aumenta nosso problema de tempo para direcionar a interação, já que o direcionamento do usuário ocorreu no passado.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.

Felizmente, os eventos SourcePressed, SourceReleased e SourceUpdated fornecem o estado histórico associado a cada evento de entrada.Fortunately, the SourcePressed, SourceReleased and SourceUpdated events provide the historical State associated with each input event. Isso inclui diretamente o cabeçalho histórico e as poses de mão disponíveis por meio de TryGetPointerPose, juntamente com um carimbo de data/hora histórico que você pode passar para outras APIs para correlacionar com esse evento.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.

Isso leva às seguintes práticas recomendadas ao renderizar e direcionar com mãos e controladores a cada quadro:That leads to the following best practices when rendering and targeting with hands and controllers each frame:

  • Para renderização à mão/controlador em cada quadro, seu aplicativo deve sondar a pose previsível de cada fonte de interação na hora do Photon do quadro atual.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. Você pode sondar todas as fontes de interação chamando GetDetectedSourcesAtTimestamp a cada quadro, passando o carimbo de data/hora previsto fornecido por HolographicFrame:: CurrentPrediction.You can poll for all interaction sources by calling GetDetectedSourcesAtTimestamp each frame, passing in the predicted timestamp provided by HolographicFrame::CurrentPrediction.
  • Para direcionamento à mão/controlador em um Press ou Release, seu aplicativo deve lidar com eventosprensados/liberados, raycasting com base na cabeça histórica ou na pose do evento.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. Você obtém esse destino Ray manipulando o evento SourcePressed ou SourceReleased , obtendo a propriedade State dos argumentos do evento e, em seguida, chamando seu método 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.

Propriedades de entrada de dispositivo cruzadoCross-device input properties

A API do SpatialInteractionSource dá suporte a controladores e sistemas de acompanhamento de mão com uma ampla gama de recursos.The SpatialInteractionSource API supports controllers and hand tracking systems with a wide range of capabilities. Vários desses recursos são comuns entre os tipos de dispositivo.A number of these capabilities are common between device types. Por exemplo, o rastreamento de mão e os controladores de movimento fornecem uma ação ' Select ' e uma posição 3D.For example, hand tracking and motion controllers both provide a 'select' action and a 3D position. Sempre que possível, a API mapeia esses recursos comuns para as mesmas propriedades no SpatialInteractionSource.Wherever possible, the API maps these common capabilities to the same properties on the SpatialInteractionSource. Isso permite que os aplicativos ofereçam suporte mais facilmente a uma ampla gama de tipos de entrada.This enables applications to more easily support a wide range of input types. A tabela a seguir descreve as propriedades com suporte e como elas são comparadas entre os tipos de entrada.The following table describes the properties that are supported, and how they compare across input types.

PropriedadeProperty DescriçãoDescription Gestos de HoloLens (1º gen)HoloLens(1st gen) Gestures Controladores de movimentoMotion Controllers Mãos articuladasArticulated Hands
SpatialInteractionSource::destro/canhotoSpatialInteractionSource::Handedness À direita ou à esquerda/controlador.Right or left hand / controller. Sem suporteNot Supported Com suporteSupported Com suporteSupported
SpatialInteractionSourceState::IsSelectPressedSpatialInteractionSourceState::IsSelectPressed Estado atual do botão primário.Current state of the primary button. Toque de arAir Tap DisparadorTrigger Toque de ar relaxado (pinçagem vertical)Relaxed Air Tap (upright pinch)
SpatialInteractionSourceState::IsseguredSpatialInteractionSourceState::IsGrasped Estado atual do botão de captura.Current state of the grab button. Sem suporteNot Supported Botão de capturaGrab button Apertar ou fechar mãoPinch or Closed Hand
SpatialInteractionSourceState::IsMenuPressedSpatialInteractionSourceState::IsMenuPressed Estado atual do botão de menu.Current state of the menu button. Sem suporteNot Supported Botão de menuMenu Button Sem suporteNot Supported
SpatialInteractionSourceLocation::PositionSpatialInteractionSourceLocation::Position Local XYZ da posição da mão ou de alças no controlador.XYZ location of the hand or grip position on the controller. Local do PalmPalm location Segurar posição de poseGrip pose position Local do PalmPalm location
SpatialInteractionSourceLocation::OrientationSpatialInteractionSourceLocation::Orientation Quaternion representando a orientação da posição de mão ou de alça no controlador.Quaternion representing the orientation of the hand or grip pose on the controller. Sem suporteNot Supported Segure a orientação da poseGrip pose orientation Orientação de PalmPalm orientation
SpatialPointerInteractionSourcePose::PositionSpatialPointerInteractionSourcePose::Position Origem do raio de apontar.Origin of the pointing ray. Sem suporteNot Supported Com suporteSupported Com suporteSupported
SpatialPointerInteractionSourcePose::ForwardDirectionSpatialPointerInteractionSourcePose::ForwardDirection Direção do raio de apontar.Direction of the pointing ray. Sem suporteNot Supported Com suporteSupported Com suporteSupported

Algumas das propriedades acima não estão disponíveis em todos os dispositivos, e a API fornece um meio de testar isso.Some of the above properties are not available on all devices, and the API provides a means to test for this. Por exemplo, você pode inspecionar a propriedade SpatialInteractionSource:: IsGraspSupported para determinar se a origem fornece uma ação de compreensão.For example, you can inspect the SpatialInteractionSource::IsGraspSupported property to determine whether the source provides a grasp action.

Segurar pose vs. ponto de apontarGrip pose vs. pointing pose

O Windows Mixed Reality dá suporte a controladores de movimento em uma variedade de fatores forma.Windows Mixed Reality supports motion controllers in a variety of form factors. Ele também dá suporte a sistemas de controle de mão articulados.It also supports articulated hand tracking systems. Todos esses sistemas têm diferentes relações entre a posição da mão e a direção natural "encaminhar" que os aplicativos devem usar para apontar ou renderizar objetos na mão do usuário.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. Para dar suporte a tudo isso, há dois tipos de poses 3D fornecidos para os controladores de rastreamento e de movimento à mão.To support all of this, there are two types of 3D poses provided for both hand tracking and motion controllers. A primeira é Segure pose, que representa a posição da mão do usuário.The first is grip pose, which represents the user's hand position. A segunda é a pose de ponto, que representa um ponteiro de raio originário da mão do usuário ou do controlador.The second is pointing pose, which represents a pointing ray originating from the user's hand or controller. Portanto, se você quiser renderizar a mão do usuário ou um objeto mantido na mão do usuário, como uma gumes ou uma arma, use a pose de alça.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. Se você quiser Raycast do controlador ou da mão, por exemplo, quando o usuário estiver apontando para a interface de usuário, use a pose de ponteiro.If you want to raycast from the controller or hand, for example when the user is pointing at UI , use the pointing pose.

Você pode acessar a alça de pose por meio de SpatialInteractionSourceState::P Propriedades:: TryGetLocation (...). Ele é definido da seguinte maneira:You can access the grip pose through SpatialInteractionSourceState::Properties::TryGetLocation(...). It is defined as follows:

  • A posição de alça: o Palm centróide ao manter o controlador naturalmente, ajustado para a esquerda ou para a direita para centralizar a posição dentro da alça.The grip position: The palm centroid when holding the controller naturally, adjusted left or right to center the position within the grip.
  • O eixo direito da orientação de alça: quando você abre completamente a mão para formar uma pose plana de 5 dedos, o raio normal para o Palm (para frente do Palm esquerdo, para trás do Palm direito)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)
  • O eixo de encaminhamento da orientação de alça: quando você fecha a sua mão parcialmente (como se você mantiver o controlador), o raio que aponta para "encaminhar" por meio do tubo formado por seus dedos não-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.
  • O eixo superior da orientação de alça: o eixo superior implícito pelas definições direita e avançar.The grip orientation's Up axis: The Up axis implied by the Right and Forward definitions.

Você pode acessar o ponteiro de pose por meio de SpatialInteractionSourceState::P Propriedades:: TryGetLocation (...):: SourcePointerPose ou SpatialInteractionSourceState:: TryGetPointerPose (...):: TryGetInteractionSourcePose.You can access the pointer pose through SpatialInteractionSourceState::Properties::TryGetLocation(...)::SourcePointerPose or SpatialInteractionSourceState::TryGetPointerPose(...)::TryGetInteractionSourcePose.

Propriedades de entrada específicas do controladorController-specific input properties

Para controladores, o SpatialInteractionSource tem uma propriedade de controlador com recursos adicionais.For controllers, the SpatialInteractionSource has a Controller property with additional capabilities.

  • HasThumbstick: Se for true, o controlador terá um Thumbstick.HasThumbstick: If true, the controller has a thumbstick. Inspecione a propriedade controllerproperties do SpatialInteractionSourceState para adquirir os valores x e y de Thumbstick (ThumbstickX e ThumbstickY), bem como seu estado pressionado (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: Se for true, o controlador terá um touchpad.HasTouchpad: If true, the controller has a touchpad. Inspecione a propriedade Controllerproperties do SpatialInteractionSourceState para adquirir os valores x e y do Touchpad (TouchpadX e touchpad) e para saber se o usuário está tocando no Pad (IsTouchpadTouched) e se eles estão pressionando o touchpad ( 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 are pressing the touchpad down (IsTouchpadPressed).
  • SimpleHapticsController: A API do SimpleHapticsController para o controlador permite inspecionar os recursos do haptics do controlador e também permite que você controle os comentários do 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.

Observe que o intervalo para Touchpad e Thumbstick é de-1 a 1 para ambos os eixos (de baixo para cima e da esquerda para a direita).Note that the range for touchpad and thumbstick is -1 to 1 for both axes (from bottom to top, and from left to right). O intervalo para o gatilho analógico, que é acessado usando a propriedade SpatialInteractionSourceState:: SelectPressedValue, tem um intervalo de 0 a 1.The range for the analog trigger, which is accessed using the SpatialInteractionSourceState::SelectPressedValue property, has a range of 0 to 1. Um valor de 1 se correlaciona com IsSelectPressed sendo igual a true; qualquer outro valor se correlaciona com IsSelectPressed sendo igual a false.A value of 1 correlates with IsSelectPressed being equal to true; any other value correlates with IsSelectPressed being equal to false.

Acompanhamento de mão articuladaArticulated hand tracking

A API do Windows Mixed Reality fornece suporte completo para acompanhamento de mão articulada, por exemplo, no HoloLens 2.The Windows Mixed Reality API provides full support for articulated hand tracking, for example on HoloLens 2. O controle de mão articulado pode ser usado para implementar a manipulação direta e modelos de entrada de ponto e confirmação em seus aplicativos.Articulated hand tracking can be used to implement direct manipulation and point-and-commit input models in your applications. Ele também pode ser usado para criar interações totalmente personalizadas.It can also be used to author fully custom interactions.

Esqueleto da mãoHand skeleton

O controle de mão articulado fornece um esqueleto de 25 conjunta que permite muitos tipos diferentes de interações.Articulated hand tracking provides a 25 joint skeleton that enables many different types of interactions. O esqueleto fornece 5 junções para o índice/meio/anel/pequenos dedos, 4 junções para o Thumb e 1 junta de pulso.The skeleton provides 5 joints for the index/middle/ring/little fingers, 4 joints for the thumb, and 1 wrist joint. A junta do pulso serve como a base da hierarquia.The wrist joint serves as the base of the hierarchy. A figura a seguir ilustra o layout do esqueleto.The following picture illustrates the layout of the skeleton.

Esqueleto da mão

Na maioria dos casos, cada conjunto é nomeado com base no Bone que ele representa.In most cases, each joint is named based on the bone that it represents. Como há dois Bones em cada conjunto, usamos uma Convenção de nomear cada conjunto com base no Bone filho nesse local.Since there are two bones at every joint, we use a convention of naming each joint based on the child bone at that location. O Bone filho é definido como o Bone além do pulso.The child bone is defined as the bone further from the wrist. Por exemplo, a junção "index proximal" contém a posição inicial do proximal Bone do índice e a orientação desse Bone.For example, the "Index Proximal" joint contains the beginning position of the index proximal bone, and the orientation of that bone. Ele não contém a posição final do Bone.It does not contain the ending position of the bone. Se precisar disso, você o obteria do próximo conjunto na hierarquia, a junção de "índice intermediário".If you need that, you'd get it from the next joint in the hierarchy, the "Index Intermediate" joint.

Além das 25 junções hierárquicas, o sistema fornece um conjunto de Palm.In addition to the 25 hierarchical joints, the system provides a palm joint. A Palm normalmente não é considerada parte da estrutura estrutural.The palm is not typically considered part of the skeletal structure. Ele é fornecido apenas como uma maneira conveniente de obter a posição e a orientação gerais do manual.It is provided only as a convenient way to get the hand's overall position and orientation.

As informações a seguir são fornecidas para cada conjunto:The following information is provided for each joint:

NomeName DescriçãoDescription
PosiçãoPosition posição 3D da junção, disponível em qualquer sistema de coordenadas solicitado.3D position of the joint, available in any requested coordinate system.
OrientaçãoOrientation orientação 3D do Bone, disponível em qualquer sistema de coordenadas solicitado.3D orientation of the bone, available in any requested coordinate system.
RadiusRadius Distância da superfície da capa na posição conjunta.Distance to surface of the skin at the joint position. Útil para ajustar interações diretas ou visualizações que dependem da largura do dedo.Useful for tuning direct interactions or visualizations that rely on finger width.
PrecisãoAccuracy Fornece uma dica sobre a confiança do sistema sobre as informações deste conjunto.Provides a hint on how confident the system feels about this joint's information.

Você pode acessar os dados de esqueleto da mão por meio de uma função no SpatialInteractionSourceState.You can access the hand skeleton data through a function on the SpatialInteractionSourceState. A função é chamada de TryGetHandPosee retorna um objeto chamado HandPose.The function is called TryGetHandPose, and it returns an object called HandPose. Se a origem não der suporte a mãos articuladas, essa função retornará NULL.If the source does not support articulated hands, then this function will return null. Depois de ter um HandPose, você pode obter os dados concorrentes atuais chamando TryGetJoint, com o nome da junção em que você está interessado.Once you have a HandPose, you can get current joint data by calling TryGetJoint, with the name of the joint you are interested in. Os dados são retornados como uma estrutura JointPose .The data is returned as a JointPose structure. O código a seguir obtém a posição da dica de dedo do índice.The following code gets the position of the index finger tip. A variável CurrentState representa uma instância 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
    }
}

Malha à mãoHand mesh

A API de acompanhamento de mão articulada permite uma malha à mão do triângulo totalmente reformado.The articulated hand tracking API allows for a fully deformable triangle hand mesh. Essa malha pode Deform em tempo real junto com o esqueleto da mão e é útil para visualização, bem como técnicas de física avançadas.This mesh can deform in real time along with the hand skeleton, and is useful for visualization as well as advanced physics techniques. Para acessar a malha à mão, primeiro você precisa criar um objeto HandMeshObserver chamando TryCreateHandMeshObserverAsync no SpatialInteractionSource.To access the hand mesh, you need to first create a HandMeshObserver object by calling TryCreateHandMeshObserverAsync on the SpatialInteractionSource. Isso só precisa ser feito uma vez por fonte, normalmente na primeira vez que você o vê.This only needs to be done once per source, typically the first time you see it. Isso significa que você chamará essa função para criar um objeto HandMeshObserver sempre que uma mão inserir o FOV.That means you'll call this function to create a HandMeshObserver object whenever a hand enters the FOV. Observe que essa é uma função assíncrona, portanto, você terá que lidar com um pouco de simultaneidade aqui.Note that this is an async function, so you'll have to deal with a bit of concurrency here. Uma vez disponível, você pode solicitar ao objeto HandMeshObserver para o buffer de índice de triângulo chamando GetTriangleIndices.Once available, you can ask the HandMeshObserver object for the triangle index buffer by calling GetTriangleIndices. Os índices não alteram o quadro no quadro, para que você possa obtê-los uma vez e armazená-los em cache durante o tempo de vida da origem.Indices don't change frame over frame, so you can get those once and cache them for the lifetime of the source. Os índices são fornecidos na ordem de enrolamento no sentido horário.Indices are provided in clockwise winding order.

O código a seguir gira um std:: thread desanexado para criar o observador de malha e extrai o buffer de índice quando o observador de malha está disponível.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. Ele começa com uma variável chamada CurrentState, que é uma instância de SpatialInteractionSourceState que representa uma mão controlada.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();

Iniciar um thread desanexado é apenas uma opção para lidar com chamadas assíncronas.Starting a detached thread is just one option for handling async calls. Como alternativa, você pode usar a nova funcionalidade de co_await com C++suporte do/WinRT.Alternatively, you could use the new co_await functionality supported by C++/WinRT.

Depois de ter um objeto HandMeshObserver, você deve mantê-lo durante a duração em que seu SpatialInteractionSource correspondente está ativo.Once you have a HandMeshObserver object, you should hold onto it for the duration that its corresponding SpatialInteractionSource is active. Em seguida, cada quadro pode ser solicitado para o último buffer de vértice que representa a mão chamando GetVertexStateForPose e passando uma instância HandPose que represente a pose para a qual você deseja vértices.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. Cada vértice no buffer tem uma posição e um normal.Each vertex in the buffer has a position and a normal. Aqui está um exemplo de como obter o conjunto atual de vértices para uma malha à mão.Here's an example of how to get the current set of vertices for a hand mesh. Assim como antes, a variável CurrentState representa uma instância de 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);
    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
    }
}

Ao contrário das junções de esqueleto, a API de malha à mão não permite que você especifique um sistema de coordenadas para os vértices.In contrast to skeleton joints, the hand mesh API does not allow you to specify a coordinate system for the vertices. Em vez disso, o HandMeshVertexState especifica o sistema de coordenadas no qual os vértices são fornecidos.Instead, the HandMeshVertexState specifies the coordinate system that the vertices are provided in. Em seguida, você pode obter uma transformação de malha chamando TryGetTransformTo e especificando o sistema de coordenadas desejado.You can then get a mesh transform by calling TryGetTransformTo and specifying your desired coordinate system. Você precisará usar essa transformação de malha sempre que trabalhar com os vértices.You'll need to use this mesh transform whenever you work with the vertices. Essa abordagem reduz a sobrecarga da CPU, especialmente se você estiver usando apenas a malha para fins de processamento.This approach reduces CPU overhead, especially if you are only using the mesh for rendering purposes.

Gestos de composição olhar e CommitGaze and Commit composite gestures

Para aplicativos que usam o modelo de entrada olhar-and-Commit, especialmente no HoloLens (primeira gen), a API de entrada espacial fornece um SpatialGestureRecognizer opcional que pode ser usado para habilitar gestos compostos criados sobre o evento ' 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. Ao rotear interações do SpatialInteractionManager para o SpatialGestureRecognizer de um holograma, os aplicativos podem detectar eventos de toque, retenção, manipulação e navegação uniformemente entre dispositivos de entrada de teclado, de voz e espaciais, sem a necessidade de lidar com prensas e libera manualmente.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 executa apenas a Desambigüidade mínima entre o conjunto de gestos que você solicita.SpatialGestureRecognizer performs only the minimal disambiguation between the set of gestures that you request. Por exemplo, se você solicitar apenas o toque, o usuário poderá manter seu dedo no mesmo tempo que desejar e um toque ainda ocorrerá.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. Se você solicitar tocar e segurar, depois de cerca de um segundo de manter o dedo, o gesto será promovido para uma espera e um toque não ocorrerá mais.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.

Para usar o SpatialGestureRecognizer, manipule o evento InteractionDetected do SpatialInteractionManager e pegue o SpatialPointerPose exposto lá.To use SpatialGestureRecognizer, handle the SpatialInteractionManager's InteractionDetected event and grab the SpatialPointerPose exposed there. Use o cabeçalho do usuário olhar Ray desta pose para fazer a interseção com os hologramas e as malhas de superfície no ambiente do usuário, a fim de determinar o que o usuário está pretendendo a interagir com o.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. Em seguida, encaminhe o SpatialInteraction nos argumentos do evento para o SpatialGestureRecognizer do holograma de destino, usando seu método CaptureInteraction .Then, route the SpatialInteraction in the event arguments to the target hologram's SpatialGestureRecognizer, using its CaptureInteraction method. Isso começa a interpretar essa interação de acordo com o SpatialGestureSettings definido no reconhecedor no momento da criação-ou por TrySetGestureSettings.This starts interpreting that interaction according to the SpatialGestureSettings set on that recognizer at creation time - or by TrySetGestureSettings.

No HoloLens (primeira gen), as interações e gestos geralmente devem derivar seu direcionamento do olhar de cabeça do usuário, em vez de tentar renderizar ou interagir diretamente no local da mão.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. Depois que uma interação for iniciada, movimentos relativos da mão poderão ser usados para controlar o gesto, assim como com o gesto de manipulação ou de navegação.Once an interaction has started, relative motions of the hand may be used to control the gesture, as with the Manipulation or Navigation gesture.

Consulte tambémSee also