Suivi des mains — MRTK2

Profil de suivi des mains

Le profil de suivi des mains se trouve sous le profil système d’entrée. Il contient des paramètres pour la personnalisation de la représentation manuelle.

Hand Tracking Profile

Préfabriqués joints

Les préfabriqués joints sont visualisées à l’aide de préfabriqués simples. Les articulations Palm et Index Finger sont d’importance particulière et ont leur propre préfabriqué, tandis que toutes les autres articulations partagent le même préfabriqué.

Par défaut, les préfabriqués de jointure de main sont des primitives géométriques simples. Celles-ci peuvent être remplacées si vous le souhaitez. Si aucun préfab n’est spécifié, les GameObject vides sont créés à la place.

Avertissement

Évitez d’utiliser des scripts complexes ou un rendu coûteux dans les préfabriqués joints, car les objets joints sont transformés sur chaque cadre et peuvent avoir un coût de performance significatif !

Représentation conjointe de main par défaut Étiquettes communes
Articulated hand joints Input Hand joints

Préfabriqué de maillage à main

Le maillage de main est utilisé si les données de maillage entièrement définies sont fournies par l’appareil de suivi des mains. Le maillage pouvant être rendu dans le préfab est remplacé par des données de l’appareil, de sorte qu’un maillage factice tel qu’un cube soit suffisant. Le matériau du préfabriqué est utilisé pour le maillage de main.

Input Hand Mesh

L’affichage de maillage de main peut avoir un impact notable sur les performances, pour cette raison, il peut être désactivé entièrement en décochant l’option Activer la Mesh visualisation de main.

Paramètres de visualisation de main

Les visualisations de maillage de main et de jointure de main peuvent être désactivées ou activées via le paramètre Modes de visualisation de main Mesh et les modes de visualisation des jointure de main respectivement. Ces paramètres sont spécifiques au mode application, ce qui signifie qu’il est possible d’activer certaines fonctionnalités dans l’éditeur (pour voir les jointures avec la simulation dans l’éditeur, par exemple) tandis que les mêmes fonctionnalités sont désactivées quand elles sont déployées sur l’appareil (dans les builds du lecteur).

Notez qu’il est généralement recommandé d’activer la visualisation conjointe de main dans l’éditeur (afin que la simulation de l’éditeur montre où sont les articulations de main), et que la visualisation de jointure de main et la visualisation de maillage de main soient désactivées dans le lecteur (car elles entraînent une atteinte aux performances).

Création de scripts

La position et la rotation peuvent être demandées à partir du système d’entrée pour chaque jointure de main individuelle en tant que MixedRealityPose.

Le système autorise également l’accès à GameObjects qui suivent les jointures. Cela peut être utile si un autre GameObject doit suivre une jointure en continu.

Les joints disponibles sont répertoriés dans l’énumération TrackedHandJoint .

Notes

L’objet joint est détruit lorsque le suivi des mains est perdu ! Assurez-vous que tous les scripts utilisant l’objet joint gèrent correctement le null cas pour éviter les erreurs !

Accès à un contrôleur de main donné

Un contrôleur de main spécifique est souvent disponible, par exemple lors de la gestion des événements d’entrée. Dans ce cas, les données conjointes peuvent être demandées directement à partir de l’appareil, à l’aide de l’interface IMixedRealityHand .

Interrogation d’une pose conjointe à partir du contrôleur

La TryGetJoint fonction retourne false si la jointure demandée n’est pas disponible pour une raison quelconque. Dans ce cas, la pose résultante sera MixedRealityPose.ZeroIdentity.

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

Transformation conjointe à partir du visualiseur de main

Les objets joints peuvent être demandés à partir du visualiseur du contrôleur.

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

Accès simplifié aux données conjointes

Si aucun contrôleur spécifique n’est donné, les classes utilitaires sont fournies pour un accès pratique aux données jointes de main. Ces fonctions demandent des données conjointes à partir du premier appareil disponible actuellement suivi.

Interrogation d’une pose commune de HandJointUtils

HandJointUtils est une classe statique qui interroge le premier appareil actif.

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

Transformation conjointe à partir d’un service de jointure de main

IMixedRealityHandJointService conserve un ensemble persistant de GameObjects pour les jointures de suivi.

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

Événements de suivi des mains

Le système d’entrée fournit également des événements, si les données d’interrogation des contrôleurs directement ne sont pas souhaitables.

Événements conjoints

IMixedRealityHandJointHandler gère les mises à jour des positions conjointes.

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

événements Mesh

IMixedRealityHandMeshHandler gère les modifications du maillage de main articulé.

Notez que les maillages de main ne sont pas activés par défaut.

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

            // ...
        }
    }
}

Problèmes connus

.NET Native

Il existe actuellement un problème connu avec les builds Master à l’aide du back-end .NET. Dans .NET Native, IInspectable les pointeurs ne peuvent pas être marshalés du code natif au code managé à l’aide Marshal.GetObjectForIUnknownde . Le MRTK l’utilise pour obtenir les SpatialCoordinateSystem données de main et d’œil de la plateforme.

Nous avons fourni une source DLL comme solution de contournement pour ce problème, dans le dépôt natif Mixed Reality Toolkit. Suivez les instructions de README et copiez les fichiers binaires résultants dans un dossier Plug-ins de vos ressources Unity. Après cela, le script WindowsMixedRealityUtilities fourni dans MRTK résout la solution de contournement pour vous.

Si vous souhaitez créer votre propre DLL ou inclure cette solution de contournement dans une solution existante, le cœur de la solution de contournement est :

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

Et son utilisation dans votre code 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;
    }
}