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 y Index Finger son de especial importancia y tienen su propio prefabricado, mientras que todas las demás articulaciones comparten el mismo 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 usar 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 predeterminada de las articulaciones de mano Etiquetas conjuntas
Articulaciones de mano articuladas Juntas de la mano de entrada

Prefabricado de malla de mano

La malla manual se usa si el dispositivo de seguimiento de manos proporciona datos de malla totalmente definidos. La malla representada 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 pantalla 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 de manos

La malla de mano y las visualizaciones de articulaciones de mano se pueden desactivar o activar a través de la opción Modos de visualización de malla de mano y Modos de visualización de articulaciones 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 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 activar la visualización de la articulación manual en el editor (para que la simulación en el editor muestre dónde están 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 golpe de 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 unió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 usen el objeto conjunto controlen 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 conjunta 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 de articulaciones desde el 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 a datos conjuntos simplificado

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 de mano al que se realiza el seguimiento actualmente.

Posición de articulación de sondeo de HandJointUtils

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

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

Transformación conjunta de 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 manos y ojos 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 automáticamente.

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