Handspårning – MRTK2

Profil för handspårning

Handspårningsprofilen finns under profilen Indatasystem. Den innehåller inställningar för att anpassa handrepresentation.

Profil för handspårning

Gemensamma prefabs

Gemensamma prefabs visualiseras med hjälp av enkla prefabs. Handflatan och Pekfinger lederna är av särskild betydelse och har sin egen prefab, medan alla andra leder delar samma prefab.

Som standard är handledsprefaberna enkla geometriska primitiver. Dessa kan ersättas om du vill. Om ingen prefab anges alls skapas tomma GameObjects i stället.

Varning

Undvik att använda komplexa skript eller dyr rendering i gemensamma prefab, eftersom gemensamma objekt transformeras på varje ram och kan ha betydande prestandakostnader!

Standardhandledsrepresentation Gemensamma etiketter
Ledade handfogar Indatahandfogar

Handnätsprefab

Handnätet används om fullständigt definierade nätdata tillhandahålls av handspårningsenheten. Det nät som kan renderas i prefab ersätts av data från enheten, så det räcker med ett dummynät som t.ex. en kub. Materialet i prefab används för handnätet.

Handnät för indata

Handnätsvisning kan ha en märkbar prestandapåverkan, av den anledningen kan den inaktiveras helt genom att avmarkera alternativet Aktivera visualisering av handnät .

Inställningar för handvisualisering

Handnäts- och handfogningsvisualiseringarna kan stängas av eller aktiveras via inställningen Visualiseringslägen för handnät respektive handsammansättningslägen . De här inställningarna är specifika för programläge, vilket innebär att det är möjligt att aktivera vissa funktioner i redigeraren (till exempel för att se joints med simulering i redigeringsprogrammet) samtidigt som samma funktioner inaktiveras när de distribueras till enheten (i spelarversioner).

Observera att det vanligtvis rekommenderas att handledsvisualiseringen är aktiverad i redigeraren (så att simulering i redigeraren visar var handfogarna finns) och att både handledvisualisering och handnätvisualisering inaktiveras i spelaren (eftersom de ådrar sig en prestandaträff).

Skript

Position och rotation kan begäras från indatasystemet för varje enskild handfog som en MixedRealityPose.

Alternativt tillåter systemet åtkomst till GameObjects som följer lederna. Detta kan vara användbart om en annan GameObject ska spåra en joint kontinuerligt.

Tillgängliga leder listas i TrackedHandJoint uppräkningen.

Anteckning

Gemensamma föremål förstörs när handspårning går förlorad! Se till att alla skript som använder det gemensamma objektet hanterar ärendet null på ett smidigt sätt för att undvika fel!

Åtkomst till en viss handkontrollant

En specifik handkontrollant är ofta tillgänglig, t.ex. vid hantering av indatahändelser. I det här fallet kan gemensamma data begäras direkt från enheten med hjälp av IMixedRealityHand gränssnittet.

Avsökning av gemensam pose från kontrollant

Funktionen TryGetJoint returnerar false om den begärda jointen inte är tillgänglig av någon anledning. I så fall blir MixedRealityPose.ZeroIdentityden resulterande posen .

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

Gemensam transformering från handvisualisering

Gemensamma objekt kan begäras från kontrollantvisualiseraren.

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

Förenklad gemensam dataåtkomst

Om ingen specifik kontrollant ges tillhandahålls verktygsklasser för bekväm åtkomst till gemensamma handdata. Dessa funktioner begär gemensamma data från den första tillgängliga handenheten som för närvarande spåras.

Avsökning av gemensam pose från HandJointUtils

HandJointUtils är en statisk klass som frågar den första aktiva handenheten.

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

Gemensam transformering från handledstjänst

IMixedRealityHandJointService behåller en beständig uppsättning GameObjects för spårningsfogar.

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

Handspårningshändelser

Indatasystemet tillhandahåller även händelser, om det inte är önskvärt att avsöka data direkt från kontrollanter.

Gemensamma händelser

IMixedRealityHandJointHandler hanterar uppdateringar av gemensamma positioner.

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-händelser

IMixedRealityHandMeshHandler hanterar ändringar i det ledade handnätet.

Observera att handnät inte är aktiverade som standard.

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

            // ...
        }
    }
}

Kända problem

.NET Native

Det finns för närvarande ett känt problem med huvudversioner med hjälp av .NET-serverdelen. I .NET Native IInspectable kan pekare inte konverteras från intern till hanterad kod med hjälp av Marshal.GetObjectForIUnknown. MRTK använder detta för att hämta SpatialCoordinateSystem för att ta emot hand- och ögondata från plattformen.

Vi har angett DLL-källan som en lösning på det här problemet i den interna Mixed Reality Toolkit-lagringsplatsen. Följ anvisningarna i README där och kopiera de resulterande binärfilerna till en plugin-mapp i Dina Unity-tillgångar. Därefter löser skriptet WindowsMixedRealityUtilities som tillhandahålls i MRTK lösningen åt dig.

Om du vill skapa en egen DLL eller ta med den här lösningen i en befintlig, är lösningens kärna:

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

Och dess användning i din C# Unity-kod:

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