Tracciamento mano

Profilo di tracciamento manuale

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

Hand Tracking Profile

Prefab congiunti

I prefab congiunti vengono visualizzato usando prefab semplici. Le giunzioni Palm e Index Finger sono di particolare importanza e hanno il proprio prefab, mentre tutte le altre giunzioni condividono lo stesso prefab.

Per impostazione predefinita, i prefab delle giunzione della mano sono primitive geometriche semplici. Possono essere sostituiti, se lo si desidera. Se non viene specificato alcun prefab, vengono creati gameobject vuoti.

Avviso

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

Rappresentazione predefinita delle giunzione della mano Etichette congiunte
Articulated hand joints Input Hand joints

Prefab della mesh manuale

La mesh manuale viene usata se i dati della mesh completamente definiti vengono forniti dal dispositivo di rilevamento manuale. La mesh di cui è possibile eseguire il rendering nel prefab viene sostituita dai dati del dispositivo, quindi è sufficiente una mesh fittizia, ad esempio un cubo. Il materiale del prefab viene usato per la mesh manuale.

Input Hand Mesh

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

Impostazioni di visualizzazione manuale

Le visualizzazioni della mesh mano e delle giunzioni delle mani possono essere disattivate o attivate rispettivamente tramite l'impostazione Hand Mesh Visualization Modes (Modalità di visualizzazione della mesh manuale) e Hand Joint Visualization Modes (Modalità di visualizzazione mano giunzione). Queste impostazioni sono specifiche della modalità applicazione, vale a dire che è possibile attivare alcune funzionalità nell'editor (per visualizzare i giunzioni con la simulazione nell'editor, ad esempio) e avere le stesse funzionalità disattivate quando vengono distribuite nel dispositivo (nelle build del lettore).

Si noti che in genere è consigliabile che la visualizzazione con giunzione della mano sia attivata nell'editor (in modo che la simulazione nell'editor mostri dove si trova la giunzione della mano) e che la visualizzazione delle giunzioni delle mani e la visualizzazione della mesh della mano siano disattivate nel lettore (perché comportano un miglioramento delle prestazioni).

Scripting

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

In alternativa, il sistema consente l'accesso ai GameObject che seguono le giunzioni. Ciò può essere utile se un altro GameObject deve tenere traccia continuamente di un congiunto.

Le giunzioni disponibili sono elencate TrackedHandJoint nell'enumerazione .

Nota

L'oggetto congiunto viene eliminato quando si perde il tracciamento delle mani. Assicurarsi che tutti gli script che usano l'oggetto congiunto gestino correttamente il null caso per evitare errori.

Accesso a un determinato controller della mano

Spesso è disponibile un controller della mano specifico, ad esempio durante la gestione degli eventi di input. In questo caso i dati congiunti possono essere richiesti direttamente dal dispositivo, usando IMixedRealityHand l'interfaccia .

Posizione congiunta di polling dal controller

La TryGetJoint funzione restituisce se il false congiunto richiesto non è disponibile per qualche motivo. In tal caso, la posizione 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 mano

Gli oggetti congiunti 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 congiunti

Se non viene specificato alcun controller specifico, le classi di utilità vengono fornite per l'accesso pratico ai dati congiunti mano. Queste funzioni richiedono dati congiunti dal primo dispositivo a mano disponibile attualmente monitorato.

Posizione congiunta di polling da HandJointUtils

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

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

Trasformazione congiunta dal servizio hand joint

IMixedRealityHandJointService mantiene un set persistente di GameObject per tenere traccia delle giunzioni.

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

Eventi di rilevamento manuale

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

Eventi congiunti

IMixedRealityHandJointHandler gestisce gli aggiornamenti delle posizioni congiunte.

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 articolata della mano.

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 è possibile effettuare il marshalling dei puntatori da codice nativo IInspectable a codice gestito usando Marshal.GetObjectForIUnknown . MrTK usa questo oggetto per ottenere per ricevere i dati relativi a mani SpatialCoordinateSystem e occhi dalla piattaforma.

L'origine DLL è stata fornita come soluzione alternativa per questo problema, nel repo nativo di Mixed Reality 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 esistente, il nucleo della soluzione alternativa è:

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

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