Seguimiento de manos: MRTK2

Perfil de seguimiento de manos

El perfil seguimiento de manos se encuentra en el perfil sistema de entrada. Contiene la configuración para personalizar la representación manual.

Perfil de seguimiento de manos

Objetos prefabricados conjuntos

Los objetos prefabricados conjuntos se visualizan mediante objetos prefabricados simples. Las articulaciones Palm e Index Finger son de importancia especial y tienen su propio objeto prefabricado, mientras que todas las demás articulaciones comparten el mismo objeto prefabricado.

De forma predeterminada, los objetos prefabricados de la articulación de mano son primitivos geométricos simples. Se pueden reemplazar si lo desea. Si no se especifica ningún objeto prefabricado, se crean gameObjects vacíos en su lugar.

Advertencia

Evite el uso de scripts complejos o una representación costosa en objetos prefabricados conjuntos, ya que los objetos conjuntos se transforman en cada fotograma y pueden tener un costo de rendimiento significativo.

Representación de articulación manual predeterminada Etiquetas conjuntas
Articulaciones articuladas de la mano Juntas de mano de entrada

Objeto prefabricado de malla de mano

La malla de mano se usa si el dispositivo de seguimiento de manos proporciona datos de malla totalmente definidos. La malla que se puede representar en el objeto prefabricado se reemplaza por datos del dispositivo, por lo que una malla ficticía, como un cubo, es suficiente. El material del objeto prefabricado se utiliza para la malla de mano.

Malla de mano de entrada

La visualización de malla de mano puede tener un impacto notable en el rendimiento, por este motivo se puede deshabilitar completamente desactivando la opción Habilitar visualización de malla de mano .

Configuración de visualización manual

La malla de mano y las visualizaciones de articulaciones de mano se pueden desactivar o activar a través de la configuración De modos de visualización de malla de mano y Modos de visualización de articulación de mano respectivamente. Esta configuración es específica del modo de aplicación, lo que significa que es posible activar algunas características mientras está en el editor (para ver las articulaciones con la simulación en el editor, por ejemplo) mientras se desactivan las mismas características cuando se implementan en el dispositivo (en compilaciones del reproductor).

Tenga en cuenta que, por lo general, se recomienda que la visualización de las articulaciones de mano esté activada en el editor (para que la simulación en el editor muestre dónde se encuentran las articulaciones de la mano) y para que la visualización de la articulación de la mano y la visualización de malla de mano se desactiven en el reproductor (porque incurren en un impacto en el rendimiento).

Scripting

La posición y la rotación se pueden solicitar desde el sistema de entrada para cada articulación de mano individual como .MixedRealityPose

Como alternativa, el sistema permite el acceso a GameObjects que siguen las articulaciones. Esto puede ser útil si otro GameObject debe realizar un seguimiento continuo de una articulación.

Las articulaciones disponibles se enumeran en la TrackedHandJoint enumeración.

Nota

¡El objeto conjunto se destruye cuando se pierde el seguimiento de la mano! Asegúrese de que los scripts que usan el objeto conjunto controlan el null caso correctamente para evitar errores.

Acceso a un controlador de mano determinado

Un controlador de mano específico suele estar disponible, por ejemplo, al controlar eventos de entrada. En este caso, los datos conjuntos se pueden solicitar directamente desde el dispositivo, mediante la IMixedRealityHand interfaz .

Posición de la articulación de sondeo del controlador

La TryGetJoint función devuelve false si la articulación solicitada no está disponible por algún motivo. En ese caso, la posición 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)
    {
      // ...
    }
  }
}

Transformación conjunta del visualizador de manos

Los objetos conjuntos se pueden solicitar desde el visualizador del controlador.

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

Acceso simplificado a datos conjuntos

Si no se proporciona ningún controlador específico, se proporcionan clases de utilidad para un acceso cómodo a los datos de las articulaciones de mano. Estas funciones solicitan datos conjuntos del primer dispositivo disponible que se está realizando actualmente.

Posición de articulación de sondeo de HandJointUtils

HandJointUtils es una clase estática que consulta el primer dispositivo de mano activo.

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

Transformación conjunta del servicio conjunto a mano

IMixedRealityHandJointService mantiene un conjunto persistente de GameObjects para realizar un seguimiento de las articulaciones.

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

Eventos de seguimiento de manos

El sistema de entrada también proporciona eventos, si no es deseable sondear datos de controladores directamente.

Eventos conjuntos

IMixedRealityHandJointHandler controla las actualizaciones de las posiciones 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 malla

IMixedRealityHandMeshHandler controla los cambios de la malla de mano articulada.

Tenga en cuenta que las mallas de mano no están habilitadas de forma predeterminada.

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 conocidos

.NET Native

Actualmente hay un problema conocido con las compilaciones maestras mediante el back-end de .NET. En .NET Native, IInspectable los punteros no se pueden serializar de código nativo a administrado mediante Marshal.GetObjectForIUnknown. MRTK lo usa para obtener el SpatialCoordinateSystem para recibir datos de mano y ojo de la plataforma.

Hemos proporcionado un origen DLL como solución alternativa para este problema, en el repositorio nativo de Mixed Reality Toolkit. Siga las instrucciones del archivo Léame y copie los archivos binarios resultantes en una carpeta Plugins en los recursos de Unity. Después, el script WindowsMixedRealityUtilities proporcionado en MRTK resolverá la solución alternativa.

Si desea crear su propio archivo DLL o incluir esta solución alternativa en una existente, el núcleo de la solución alternativa es:

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

Y su uso en el código de Unity de 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;
    }
}