Tracciamento della mano - MRTK2

Profilo di tracciamento della mano

Il profilo di rilevamento della mano si trova nel profilo del sistema di input. Contiene le impostazioni per la personalizzazione della rappresentazione manuale.

Profilo tracciamento mano

Prefab comuni

I prefab comuni vengono visualizzati usando prefab semplici. Le articolazioni palmo e indice sono di particolare importanza e hanno il proprio prefab, mentre tutte le altre articolazioni condividono lo stesso prefab.

Per impostazione predefinita, i prefab delle articolazioni della mano sono semplici primitive geometriche. Queste possono essere sostituite, se necessario. Se non viene specificato alcun prefab, vengono creati invece gameobject vuoti.

Avviso

Evitare di usare script complessi o un rendering costoso nei prefab comuni, poiché gli oggetti joint vengono trasformati in ogni frame e possono avere un costo significativo per le prestazioni.

Rappresentazione congiunta manuale predefinita Etichette comuni
Articolazioni della mano articolate Articolazioni della mano di input

Prefab mesh a mano

La mesh manuale viene utilizzata se i dati mesh completamente definiti vengono forniti dal dispositivo di tracciamento della mano. Il rendering della mesh nel prefab viene sostituito dai dati del dispositivo, quindi è sufficiente una mesh fittizia, ad esempio un cubo. Il materiale del prefab viene usato per la mesh a mano.

Mesh a mano di input

La visualizzazione mesh a mano può avere un impatto notevole sulle prestazioni, per questo motivo può essere disabilitata completamente deselezionando l'opzione Abilita visualizzazione mesh manuale .

Impostazioni di visualizzazione della mano

Le visualizzazioni della mesh a mano e delle mani possono essere disattivate o attivate rispettivamente tramite l'impostazione Modalità di visualizzazione Mesh mano e Le modalità di visualizzazione delle mani. Queste impostazioni sono specifiche della modalità applicazione, ovvero è possibile attivare alcune funzionalità durante l'editor (per visualizzare le articolazioni con simulazione nell'editor, ad esempio) con le stesse funzionalità disattivate quando vengono distribuite nel dispositivo (nelle build del lettore).

Si noti che in genere è consigliabile attivare la visualizzazione delle articolazioni della mano nell'editor (in modo che la simulazione nell'editor mostri dove si trovano le articolazioni della mano) e di avere sia la visualizzazione delle articolazioni della mano che la visualizzazione della mesh della mano disattivata nel giocatore (perché comportano un riscontro delle prestazioni).

Scripting

La posizione e la rotazione possono essere richieste dal sistema di input per ogni singola articolazione della mano come .MixedRealityPose

In alternativa, il sistema consente l'accesso a GameObjects che seguono le articolazioni. Ciò può essere utile se un altro GameObject deve tenere traccia di un'articolazione in modo continuo.

Le articolazioni disponibili sono elencate nell'enumerazione TrackedHandJoint .

Nota

L'oggetto giunto viene distrutto quando si perde il tracciamento della mano! Assicurarsi che tutti gli script che usano l'oggetto comune gestiscono normalmente il null caso per evitare errori.

Accesso a un determinato controller della mano

Un controller della mano specifico è spesso disponibile, ad esempio quando si gestiscono gli eventi di input. In questo caso i dati comuni possono essere richiesti direttamente dal dispositivo, usando l'interfaccia IMixedRealityHand .

Polling joint pose from controller

La TryGetJoint funzione restituisce false se il giunto richiesto non è disponibile per qualche motivo. In tal caso la posa risultante sarà MixedRealityPose.ZeroIdentity.

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

Trasformazione congiunta dal visualizzatore a mano

Gli oggetti joint possono essere richiesti dal visualizzatore controller.

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

Accesso semplificato ai dati comuni

Se non viene fornito alcun controller specifico, vengono fornite classi di utilità per un accesso pratico ai dati comuni. Queste funzioni richiedono dati comuni dal primo dispositivo a mano attualmente monitorato.

Polling joint pose from HandJointUtils

HandJointUtils è una classe statica che esegue una query sul primo dispositivo a mano attiva.

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

Trasformazione congiunta dal servizio congiunto a mano

IMixedRealityHandJointService mantiene un set persistente di GameObjects per tenere traccia delle articolazioni.

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

Eventi di rilevamento della mano

Anche il sistema di input fornisce eventi, se non è consigliabile eseguire direttamente il polling dei dati dai controller.

Eventi comuni

IMixedRealityHandJointHandler gestisce gli aggiornamenti delle posizioni comuni.

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))
            {
                // ...
            }
        }
    }
}

Eventi mesh

IMixedRealityHandMeshHandler gestisce le modifiche della mesh a mano articolata.

Si noti che le mesh a mano non sono abilitate per impostazione predefinita.

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

            // ...
        }
    }
}

Problemi noti

.NET Native

Esiste attualmente un problema noto con le compilazioni master che usano il back-end .NET. In .NET Native non IInspectable è possibile effettuare il marshalling dei puntatori dal codice nativo al codice gestito usando Marshal.GetObjectForIUnknown. MRTK usa questa opzione per ottenere l'oggetto SpatialCoordinateSystem per ricevere dati di mano e occhio dalla piattaforma.

L'origine DLL è stata fornita come soluzione alternativa per questo problema, nel repository nativo di Realtà mista Toolkit. Seguire le istruzioni nel file LEGGIMI e copiare i file binari risultanti in una cartella Plugins negli asset di Unity. Successivamente, lo script WindowsMixedRealityUtilities fornito in MRTK risolverà automaticamente la soluzione alternativa.

Se si vuole creare una DLL personalizzata o includere questa soluzione alternativa in una soluzione esistente, il nucleo della soluzione alternativa è:

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

E il relativo uso nel codice Unity 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;
    }
}