Acompanhamento manual – MRTK2

Perfil de acompanhamento manual

O perfil acompanhamento manual é encontrado no perfil sistema de entrada. Ele contém configurações para personalizar a representação manual.

Perfil de acompanhamento manual

Pré-fabricados conjuntos

Pré-fabricados conjuntos são visualizados usando pré-fabricados simples. As articulações Palm e Index Finger são de especial importância e têm seu próprio pré-fabricado, enquanto todas as outras articulações compartilham o mesmo pré-fabricado.

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

Aviso

Evite usar scripts complexos ou renderização cara em pré-fabricados conjuntos, pois os objetos conjuntos são transformados em cada quadro e podem ter um custo de desempenho significativo!

Representação da articulação da mão padrão Rótulos conjuntos
Articulações de mão Articulações da mão de entrada

Pré-fabricado de malha manual

A malha manual será usada se os dados de malha totalmente definidos forem fornecidos pelo dispositivo de acompanhamento manual. A malha renderizável no pré-fabricado é substituída por dados do dispositivo, portanto, uma malha fictícia, como um cubo, é suficiente. O material do pré-fabricado é usado para a malha manual.

Malha manual de entrada

A tela de malha manual pode ter um impacto perceptível no desempenho, por esse motivo, ela pode ser totalmente desabilitada desmarcando a opção Habilitar Visualização de Malha Manual .

Configurações de visualização manual

As visualizações de malha manual e articulação manual podem ser desativadas ou ativadas por meio da configuração Modos de Visualização de Malha Manual e Modos de Visualização da Articulação da Mão , respectivamente. Essas configurações são específicas do modo de aplicativo, o que significa que é possível ativar alguns recursos no editor (para ver as articulações com simulação no editor, por exemplo) ao ter os mesmos recursos desativados quando implantados no dispositivo (em builds de player).

Observe que geralmente é recomendável ativar a visualização da articulação manual no editor (para que a simulação no editor mostre onde estão as articulações das mãos) e ter a visualização da articulação da mão e a visualização da malha manual desativadas no player (porque elas incorrem em um impacto no desempenho).

Scripting

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

Como alternativa, o sistema permite o acesso a GameObjects que seguem as articulações. Isso pode ser útil se outro GameObject deve acompanhar uma articulação continuamente.

As articulações disponíveis são listadas na TrackedHandJoint enumeração .

Observação

O objeto joint é destruído quando o rastreamento de mão é perdido! Verifique se todos os scripts que usam o objeto de conjunto lidam com o null caso normalmente para evitar erros!

Acessando um determinado controlador de mão

Um controlador de mão específico geralmente está disponível, por exemplo, ao manipular eventos de entrada. Nesse caso, os dados conjuntos podem ser solicitados diretamente do dispositivo, usando a IMixedRealityHand interface .

Pose da articulação de sondagem do controlador

A TryGetJoint função retornará 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 conjunta do visualizador manual

Objetos de articulação podem ser solicitados do 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 a dados conjuntos

Se nenhum controlador específico for fornecido, as classes de utilitário serão fornecidas para acesso conveniente aos dados de articulação manual. Essas funções solicitam dados conjuntos do primeiro dispositivo disponível atualmente rastreado.

Pose conjunta de sondagem de HandJointUtils

HandJointUtils é uma classe estática que consulta o primeiro dispositivo ativo.

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

Transformação conjunta do serviço de articulação manual

IMixedRealityHandJointService mantém um conjunto persistente de GameObjects para acompanhamento de articulações.

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

Eventos de acompanhamento manual

O sistema de entrada também fornece eventos, se a sondagem de dados de controladores diretamente não for desejável.

Eventos conjuntos

IMixedRealityHandJointHandler manipula 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 manipula alterações da malha de mão articulada.

Observe que as malhas muárias não estão habilitadas por padrão.

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 Nativo

Atualmente, há um problema conhecido com builds mestre usando o back-end do .NET. No .NET Native, IInspectable os ponteiros não podem ter marshaling de código nativo para gerenciado usando Marshal.GetObjectForIUnknown. O MRTK usa isso para obter o SpatialCoordinateSystem para receber dados de mão e olho da plataforma.

Fornecemos a origem da DLL como uma solução alternativa para esse problema, no repositório nativo Realidade Misturada Toolkit. Siga as instruções no LEIAME e copie os binários resultantes em uma pasta Plug-ins em seus ativos do Unity. Depois disso, o script WindowsMixedRealityUtilities fornecido no MRTK resolve a solução alternativa para você.

Se você quiser criar sua própria DLL ou incluir essa solução alternativa em uma existente, o núcleo da solução alternativa será:

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

E seu uso no código do Unity em 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;
    }
}