Partilhar via


Controlo manual — MRTK2

Perfil de controlo manual

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

Perfil de Controlo manual

Pré-fabricados conjuntos

Os pré-fabricados conjuntos são visualizados através de pré-fabricados simples. As juntas De Dedo De Palma e Índice são de especial importância e têm a sua própria pré-fabricada, enquanto todas as outras articulações partilham a mesma pré-fabricada.

Por predefinição, os prefáculos da articulação manual são primitivos geométricos simples. Estes podem ser substituídos se assim o desejarem. Se não for especificado qualquer prefáb, são criados gameObjects vazios .

Aviso

Evite utilizar scripts complexos ou composição dispendiosa em prefabs articulares, uma vez que os objetos de articulação são transformados em cada frame e podem ter um custo de desempenho significativo!

Representação Predefinida da Articulação Manual Etiquetas Conjuntas
Articulações articuladas Articulações da Mão de Entrada

Pré-fabricada de malha manual

A malha manual é utilizada se os dados de malha totalmente definidos forem fornecidos pelo dispositivo de controlo manual. A malha renderizável na pré-fabricada é substituída por dados do dispositivo, pelo que uma malha fictícia, como um cubo, é suficiente. O material da pré-fabricada é utilizado para a malha manual.

Input Hand Mesh

O ecrã de malha manual pode ter um impacto de desempenho notável, pelo que pode ser totalmente desativado ao desmarcar a opção Ativar Visualização do Hand Mesh .

Definições de visualização manual

As visualizações de malha manual e articulação manual podem ser desativadas ou ativadas através da definição Modos de Visualização do Hand Mesh e dos Modos de Visualização Articular Manual , respetivamente. Estas definições são específicas do modo de aplicação, o que significa que é possível ativar algumas funcionalidades enquanto estiver no editor (para ver articulações com a simulação no editor, por exemplo) ao mesmo tempo que tem as mesmas funcionalidades desativadas quando implementadas no dispositivo (em compilações de leitores).

Tenha em atenção que é geralmente recomendado ter a visualização articular manual ativada no editor (para que a simulação no editor mostre onde estão as articulações da mão) e que a visualização da articulação manual e a visualização da malha manual sejam desativadas no leitor (porque incorrem num impacto no desempenho).

Scripting

A posição e a rotação podem ser pedidas no sistema de entrada para cada articulação manual individual como um MixedRealityPose.

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

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

Nota

O objeto da articulação é destruído quando o controlo manual é perdido! Certifique-se de que os scripts que utilizam o objeto de articulação processam o null caso corretamente para evitar erros!

Aceder a um determinado controlador manual

Um controlador manual específico está muitas vezes disponível, por exemplo, ao processar eventos de entrada. Neste caso, os dados conjuntos podem ser pedidos diretamente a partir do dispositivo, utilizando a IMixedRealityHand interface.

Pose da junta de consulta do controlador

A TryGetJoint função devolve false se a articulação pedida 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

Os objetos conjuntos podem ser pedidos 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 a dados conjuntos simplificados

Se não for fornecido nenhum controlador específico, as classes de utilitários são fornecidas para acesso conveniente a dados conjuntos de mãos. Estas funções solicitam dados conjuntos do primeiro dispositivo manual disponível atualmente controlado.

Pose de conjunto de sondagens da 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 conjunto manual

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

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

Eventos de controlo manual

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

Eventos conjuntos

IMixedRealityHandJointHandler processa 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 processa as alterações da malha manual articulada.

Tenha em atenção que as malhas mano não estão ativadas por predefiniçã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 Native

Atualmente, existe um problema conhecido com as compilações mestras com o back-end do .NET. No .NET Native, IInspectable os ponteiros não podem ser geridos de nativo para código gerido com Marshal.GetObjectForIUnknown. O MRTK utiliza esta opção para obter os SpatialCoordinateSystem dados manos e oculares da plataforma.

Fornecemos a origem DLL como solução para este problema, no repositório Mixed Reality Toolkit nativo. Siga as instruções no README e copie os binários resultantes para uma pasta Plug-ins nos seus recursos do Unity. Depois disso, o script WindowsMixedRealityUtilities fornecido no MRTK resolverá a solução para si.

Se quiser criar a sua própria 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 código C# Unity:

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