Handtracering — MRTK2

Handtraceringsprofiel

Het profiel Handtracering vindt u onder het profiel Invoersysteem. Het bevat instellingen voor het aanpassen van handweergave.

Handtraceringsprofiel

Gezamenlijke prefabs

Gezamenlijke prefabs worden gevisualiseerd met behulp van eenvoudige prefabs. De palm - en wijsvingerverbindingen zijn van bijzonder belang en hebben hun eigen prefab, terwijl alle andere voegen dezelfde prefab delen.

Standaard zijn de handvoeg prefabs eenvoudige geometrische primitieven. Deze kunnen desgewenst worden vervangen. Als er helemaal geen prefab is opgegeven, worden in plaats daarvan lege GameObjects gemaakt.

Waarschuwing

Vermijd het gebruik van complexe scripts of dure rendering in gezamenlijke prefabs, omdat gezamenlijke objecten op elk frame worden getransformeerd en aanzienlijke prestatiekosten kunnen hebben!

Standaardweergave van handgezamen Gezamenlijke labels
Gelede handgewrichten Invoerhandverbindingen

Prefab van handgaas

Het handgaas wordt gebruikt als er volledig gedefinieerde mesh-gegevens worden geleverd door het handtraceringsapparaat. De mesh die in de prefab kan worden gerenderd, wordt vervangen door gegevens van het apparaat, dus een dummy-mesh zoals een kubus is voldoende. Het materiaal van de prefab wordt gebruikt voor het handgaas.

Invoer handgaas

Handgaasweergave kan een merkbare invloed hebben op de prestaties. Daarom kan het volledig worden uitgeschakeld door de optie Visualisatie van handgaas inschakelen uit te schakelen.

Instellingen voor handvisualisatie

De visualisaties van handgaas en handverbinding kunnen worden in- of uitgeschakeld via respectievelijk de visualisatiemodi Hand mesh en handgewrichtvisualisatiemodi . Deze instellingen zijn specifiek voor de toepassingsmodus, wat betekent dat het mogelijk is om bepaalde functies in de editor in te schakelen (bijvoorbeeld om combinaties te zien met simulatie in de editor) terwijl dezelfde functies zijn uitgeschakeld wanneer deze worden geïmplementeerd op het apparaat (in spelerbuilds).

Houd er rekening mee dat het over het algemeen wordt aanbevolen om gezamenlijke handvisualisatie in te schakelen in de editor (zodat simulatie in de editor laat zien waar de handgewrichten zich bevinden) en om zowel handgewrichten als visualisaties met handgaas uit te schakelen in de speler (omdat ze een prestatietreffer krijgen).

Uitvoeren van scripts

Positie en draaiing kunnen worden aangevraagd vanuit het invoersysteem voor elke afzonderlijke handverbinding als een MixedRealityPose.

Het systeem staat ook toegang toe tot GameObjects die de verbindingen volgen. Dit kan handig zijn als een ander GameObject continu een joint moet volgen.

Beschikbare verbindingen worden vermeld in de TrackedHandJoint opsomming.

Notitie

Gezamenlijke objecten worden vernietigd wanneer handtracering verloren gaat! Zorg ervoor dat scripts die gebruikmaken van het gezamenlijke object de null case probleemloos verwerken om fouten te voorkomen.

Toegang tot een bepaalde handcontroller

Een specifieke handcontroller is vaak beschikbaar, bijvoorbeeld bij het verwerken van invoergebeurtenissen. In dit geval kunnen de gezamenlijke gegevens rechtstreeks vanaf het apparaat worden opgevraagd via de IMixedRealityHand interface.

Polling joint pose van controller

De TryGetJoint functie retourneert false als de aangevraagde verbinding om een of andere reden niet beschikbaar is. In dat geval is MixedRealityPose.ZeroIdentityde resulterende pose .

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

Gezamenlijke transformatie van hand visualiseren

Gezamenlijke objecten kunnen worden aangevraagd via de controller visualizer.

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

Vereenvoudigde toegang tot gezamenlijke gegevens

Als er geen specifieke controller wordt gegeven, worden hulpprogrammaklassen geboden voor handige toegang tot hand gezamenlijke gegevens. Deze functies vragen om gezamenlijke gegevens van het eerste beschikbare handapparaat dat momenteel wordt bijgehouden.

Polling joint pose from HandJointUtils

HandJointUtils is een statische klasse die query's uitvoert op het eerste actieve apparaat.

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

Gezamenlijke transformatie van hand gezamenlijke service

IMixedRealityHandJointService bewaart een permanente set GameObjects voor het bijhouden van verbindingen.

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

Handtraceringsevenementen

Het invoersysteem biedt ook gebeurtenissen, als polling van gegevens van controllers rechtstreeks niet wenselijk is.

Gezamenlijke gebeurtenissen

IMixedRealityHandJointHandler verwerkt updates van gemeenschappelijke standpunten.

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

Mesh-gebeurtenissen

IMixedRealityHandMeshHandler verwerkt wijzigingen van het gearticuleerde handgaas.

Houd er rekening mee dat handgaas niet standaard is ingeschakeld.

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

            // ...
        }
    }
}

Bekende problemen

systeemeigen .NET

Er is momenteel een bekend probleem met master-builds die de .NET-back-end gebruiken. In systeemeigen .NET IInspectable kunnen aanwijzers niet worden verwijderd van systeemeigen naar beheerde code met behulp van Marshal.GetObjectForIUnknown. MRTK gebruikt dit om de SpatialCoordinateSystem te verkrijgen om hand- en ooggegevens van het platform te ontvangen.

We hebben een DLL-bron beschikbaar gesteld als tijdelijke oplossing voor dit probleem, in de systeemeigen Mixed Reality Toolkit-opslagplaats. Volg de instructies in de LEESMIJ daar en kopieer de resulterende binaire bestanden naar de map Plugins in uw Unity-assets. Daarna wordt de tijdelijke oplossing opgelost met het script WindowsMixedRealityUtilities in MRTK.

Als u uw eigen DLL wilt maken of deze tijdelijke oplossing wilt opnemen in een bestaande, is de kern van de tijdelijke oplossing:

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

En het gebruik ervan in uw C#Unity-code:

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