Bagikan melalui


Pelacakan tangan — MRTK2

Profil pelacakan tangan

Profil Pelacakan Tangan ditemukan di bawah profil Sistem Input. Ini berisi pengaturan untuk menyesuaikan representasi tangan.

Profil Pelacakan Tangan

Prefab bersama

Prefab bersama divisualisasikan menggunakan prefab sederhana. Sambungan Palm dan Index Finger sangat penting dan memiliki prefab sendiri, sementara semua sendi lainnya memiliki prefab yang sama.

Secara default prefab sendi tangan adalah primitif geometris sederhana. Ini dapat diganti jika diinginkan. Jika tidak ada prefab yang ditentukan sama sekali, GameObjects kosong akan dibuat sebagai gantinya.

Peringatan

Hindari menggunakan skrip kompleks atau rendering mahal dalam prefab bersama, karena objek bersama diubah pada setiap bingkai dan dapat memiliki biaya performa yang signifikan!

Representasi Sendi Tangan Default Label Bersama
Sendi tangan artikulasi Input Sendi Tangan

Prefab jala tangan

Jala tangan digunakan jika data jala yang sepenuhnya ditentukan disediakan oleh perangkat pelacakan tangan. Jala yang dapat dirender dalam prefab digantikan oleh data dari perangkat, sehingga jala dummy seperti kubus sudah cukup. Bahan prefab digunakan untuk jala tangan.

Input Hand Mesh

Tampilan jala tangan dapat memiliki dampak performa yang nyata, karena alasan ini dapat dinonaktifkan sepenuhnya dengan menghapus centang opsi Aktifkan Visualisasi Jala Tangan .

Pengaturan visualisasi tangan

Visualisasi jala tangan dan sendi tangan dapat dimatikan atau dinyalakan melalui pengaturan Mode Visualisasi Jala Tangan dan Mode Visualisasi Sendi Tangan masing-masing. Pengaturan ini spesifik mode aplikasi, yang berarti dimungkinkan untuk mengaktifkan beberapa fitur saat berada di editor (untuk melihat sambungan dengan simulasi dalam editor, misalnya) sambil menonaktifkan fitur yang sama saat disebarkan ke perangkat (dalam build pemutar).

Perhatikan bahwa umumnya disarankan untuk mengaktifkan visualisasi bersama tangan di editor (sehingga simulasi dalam editor akan menunjukkan di mana sendi tangan berada), dan agar visualisasi sendi tangan dan visualisasi jala tangan dimatikan di pemutar (karena mereka menimbulkan hit performa).

Pembuatan skrip

Posisi dan rotasi dapat diminta dari sistem input untuk setiap sambungan tangan individu sebagai MixedRealityPose.

Atau sistem memungkinkan akses ke GameObjects yang mengikuti sendi. Ini dapat berguna jika GameObject lain harus melacak sambungan terus menerus.

Sambungan yang tersedia tercantum dalam TrackedHandJoint enum.

Catatan

Objek bersama dihancurkan ketika pelacakan tangan hilang! Pastikan bahwa setiap skrip yang menggunakan objek bersama menangani null kasus dengan anggun untuk menghindari kesalahan!

Mengakses pengontrol tangan tertentu

Pengontrol tangan tertentu sering tersedia, misalnya saat menangani peristiwa input. Dalam hal ini data bersama dapat diminta langsung dari perangkat, menggunakan IMixedRealityHand antarmuka .

Pose bersama pose polling dari pengontrol

Fungsi TryGetJoint mengembalikan false jika sambungan yang diminta tidak tersedia karena alasan tertentu. Dalam hal ini pose yang dihasilkan akan menjadi MixedRealityPose.ZeroIdentity.

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

Transformasi bersama dari penvisualisasi tangan

Objek gabungan dapat diminta dari penampil visual pengontrol.

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

Akses data bersama yang disederhanakan

Jika tidak ada pengontrol tertentu yang diberikan, maka kelas utilitas disediakan untuk akses yang nyaman ke data bersama tangan. Fungsi-fungsi ini meminta data bersama dari perangkat tangan pertama yang tersedia yang saat ini dilacak.

Pose bersama pose polling dari HandJointUtils

HandJointUtils adalah kelas statis yang mengkueri perangkat tangan aktif pertama.

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

Transformasi bersama dari layanan bersama tangan

IMixedRealityHandJointService menyimpan sekumpulan GameObjects persisten untuk melacak sambungan.

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

Peristiwa pelacakan tangan

Sistem input juga menyediakan peristiwa, jika polling data dari pengontrol secara langsung tidak diinginkan.

Peristiwa bersama

IMixedRealityHandJointHandler menangani pembaruan posisi bersama.

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

Peristiwa jala

IMixedRealityHandMeshHandler menangani perubahan jala tangan artikulasi.

Perhatikan bahwa jala tangan tidak diaktifkan secara default.

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

            // ...
        }
    }
}

Masalah yang diketahui

.NET Native

Saat ini ada masalah yang diketahui dengan build Master menggunakan backend .NET. Di .NET Native, IInspectable pointer tidak dapat dinamai dari asli ke kode terkelola menggunakan Marshal.GetObjectForIUnknown. MRTK menggunakan ini untuk mendapatkan SpatialCoordinateSystem untuk menerima data tangan dan mata dari platform.

Kami telah menyediakan sumber DLL sebagai solusi untuk masalah ini, dalam repositori Mixed Reality Toolkit asli. Silakan ikuti instruksi di README di sana dan salin biner yang dihasilkan ke dalam folder Plugin di aset Unity Anda. Setelah itu, skrip WindowsMixedRealityUtilities yang disediakan di MRTK akan menyelesaikan solusi untuk Anda.

Jika Anda ingin membuat DLL Anda sendiri atau menyertakan solusi ini di yang sudah ada, inti dari solusinya adalah:

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

Dan penggunaannya dalam kode C# Unity Anda:

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