Rastreio de mãos

Perfil de rastreio de mão

O perfil de rastreio de mão encontra-se no perfil do Sistema de Entrada. Contém definições para personalizar a representação manual.

Perfil de rastreio de mão

Pré-fabricados articulares

Os pré-fabricados articulares são visualizados utilizando pré-fabricados simples. As articulações Palm and Index Finger são de especial importância e têm o seu próprio pré-fabricado, enquanto todas as outras articulações partilham o mesmo prefácio.

Por defeito, os pré-fabricados da articulação da mão são primitivos geométricos simples. Estes podem ser substituídos se desejar. Se não for especificado nenhum pré-fabricado, os GameObjects vazios são criados.

Aviso

Evite utilizar scripts complexos ou renderização dispendiosa em pré-fabricados articulares, uma vez que os objetos articulares são transformados em cada quadro e podem ter um custo de desempenho significativo!

Representação conjunta da mão padrão Etiquetas conjuntas
Articuladas articuladas articuladas Articulações de mão de entrada

Pré-fabricado de malha de mão

A malha manual é utilizada se os dados de malha totalmente definidos forem fornecidos pelo dispositivo de localização manual. A malha renderizável no pré-fabricado é substituída por dados do dispositivo, pelo que uma malha falsa como um cubo é suficiente. O material do pré-fabricado é utilizado para a malha manual.

Malha de mão de entrada

O ecrã de malha manual pode ter um impacto de desempenho notável, por esta razão pode ser totalmente desativado por desmarcar a opção de visualização da malha manual.

Definições de visualização da mão

As visualizações da malha manual e da articulação da mão podem ser desligadas ou ligadas através da definição de Modos de Visualização de Malha Manual e dos Modos de Visualização da Articulação da Mão, respectivamente. Estas definições são específicas do modo de aplicação, o que significa que é possível ligar algumas funcionalidades enquanto estiver no editor (ver articulações com simulação de editor, por exemplo) enquanto tem as mesmas funcionalidades desligadas quando implementadas no dispositivo (nas construções dos jogadores).

Note que é geralmente recomendado ter visualização articular manual ligada no editor (de modo que a simulação no editor mostrará onde estão as articulações das mãos), e ter tanto a visualização da articulação da mão como a visualização da malha de mão desligada no leitor (porque incorrem num sucesso de desempenho).

Scripting

A posição e a rotação podem ser solicitadas no sistema de entrada para cada articulação de cada mão como MixedRealityPose .

Em alternativa, o sistema permite o acesso aos GameObjects que seguem as articulações. Isto pode ser útil se outro GameObject seguir uma articulação continuamente.

As juntas disponíveis estão listadas no TrackedHandJoint enum.

Nota

O objeto da articulação é destruído quando se perde o rastreio manual! Certifique-se de que quaisquer scripts que utilizem o objeto articular manuseiem a null caixa graciosamente para evitar erros!

Acesso a um determinado controlador de mão

Um controlador de mão específico está frequentemente disponível, por exemplo, ao lidar com eventos de entrada. Neste caso, os dados conjuntos podem ser solicitados diretamente do dispositivo, utilizando a IMixedRealityHand interface.

Pose conjunta de sondagens do controlador

A TryGetJoint função retorna false se a articulação solicitada não estiver disponível por algum motivo. Nesse caso, a pose resultante será MixedRealityPose.ZeroIdentity .

public void OnSourceDetected(SourceStateEventData eventData)
{
  var hand = eventData.Controller as IMixedRealityHand;
  if (hand != null)
  {
    if (hand.TryGetJoint(TrackedHandJoint.IndexTip, out MixedRealityPose jointPose)
    {
      // ...
    }
  }
}

Transformação articular a partir de visualizador de mãos

Os objetos articulares podem ser solicitados ao visualizador do controlador.

public void OnSourceDetected(SourceStateEventData eventData)
{
  var handVisualizer = eventData.Controller.Visualizer as IMixedRealityHandVisualizer;
  if (handVisualizer != null)
  {
    if (handVisualizer.TryGetJointTransform(TrackedHandJoint.IndexTip, out Transform jointTransform)
    {
      // ...
    }
  }
}

Acesso simplificado de dados conjuntos

Se não for dado nenhum controlador específico, as classes de utilidade são fornecidas para um acesso conveniente aos dados da articulação da mão. Estas funções solicitam dados conjuntos do primeiro dispositivo manual disponível atualmente rastreado.

Pose conjunta de sondagens da HandJointUtils

HandJointUtils é uma classe estática que consulta o primeiro dispositivo de mão ativa.

if (HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexTip, Handedness.Right, out MixedRealityPose pose))
{
    // ...
}

Transformação conjunta do serviço de articulação da mão

IMixedRealityHandJointService mantém um conjunto persistente de IMixedRealityHandJointService para as juntas de rastreio.

var handJointService = CoreServices.GetInputSystemDataProvider<IMixedRealityHandJointService>();
if (handJointService != null)
{
    Transform jointTransform = handJointService.RequestJointTransform(TrackedHandJoint.IndexTip, Handedness.Right);
    // ...
}

Eventos de rastreio de mãos

O sistema de entrada também fornece eventos, se os dados das sondagens dos controladores diretamente não forem desejáveis.

Eventos conjuntos

IMixedRealityHandJointHandler lida com atualizações de posições conjuntas.

public class MyHandJointEventHandler : IMixedRealityHandJointHandler
{
    public Handedness myHandedness;

    void IMixedRealityHandJointHandler.OnHandJointsUpdated(InputEventData<IDictionary<TrackedHandJoint, MixedRealityPose>> eventData)
    {
        if (eventData.Handedness == myHandedness)
        {
            if (eventData.InputData.TryGetValue(TrackedHandJoint.IndexTip, out MixedRealityPose pose))
            {
                // ...
            }
        }
    }
}

Eventos de malha

IMixedRealityHandMeshHandler lida com as alterações da malha articulada da mão.

Note que as malhas manuais não são ativadas por defeito.

public class MyHandMeshEventHandler : IMixedRealityHandMeshHandler
{
    public Handedness myHandedness;
    public Mesh myMesh;

    public void OnHandMeshUpdated(InputEventData<HandMeshInfo> eventData)
    {
        if (eventData.Handedness == myHandedness)
        {
            myMesh.vertices = eventData.InputData.vertices;
            myMesh.normals = eventData.InputData.normals;
            myMesh.triangles = eventData.InputData.triangles;

            if (eventData.InputData.uvs != null && eventData.InputData.uvs.Length > 0)
            {
                myMesh.uv = eventData.InputData.uvs;
            }

            // ...
        }
    }
}

Problemas conhecidos

.NET Native

Existe atualmente um problema conhecido com as construções Master utilizando o backend .NET. Em .NET Native, IInspectable os ponteiros não podem ser geridos de nativo para código gerido usando Marshal.GetObjectForIUnknown . O MRTK utiliza-o para obter os SpatialCoordinateSystem dados manuais e oculares da plataforma.

Fornecemos a fonte DLL como uma solução alternativa para este problema, no repo de Ferramentas de Realidade Mista nativa. Por favor, siga as instruções na README e copie os binários resultantes numa pasta Plugins nos seus ativos Unidade. Depois disso, o script WindowsMixedRealityUtilities fornecido no MRTK resolverá a solução para si.

Se quiser criar o seu próprio DLL ou incluir esta solução numa existente, o núcleo da solução é:

extern "C" __declspec(dllexport) void __stdcall MarshalIInspectable(IUnknown* nativePtr, IUnknown** inspectable)
{
    *inspectable = nativePtr;
}

E a sua utilização no seu código de unidade C#:

[DllImport("DotNetNativeWorkaround.dll", EntryPoint = "MarshalIInspectable")]
private static extern void GetSpatialCoordinateSystem(IntPtr nativePtr, out SpatialCoordinateSystem coordinateSystem);

private static SpatialCoordinateSystem GetSpatialCoordinateSystem(IntPtr nativePtr)
{
    try
    {
        GetSpatialCoordinateSystem(nativePtr, out SpatialCoordinateSystem coordinateSystem);
        return coordinateSystem;
    }
    catch
    {
        UnityEngine.Debug.LogError("Call to the DotNetNativeWorkaround plug-in failed. The plug-in is required for correct behavior when using .NET Native compilation");
        return Marshal.GetObjectForIUnknown(nativePtr) as SpatialCoordinateSystem;
    }
}