Pelacakan mata yang diperluas di Unity
Untuk mengakses repositori GitHub untuk sampel pelacakan mata yang diperluas:
Pelacakan mata yang diperluas adalah kemampuan baru dalam HoloLens 2. Ini adalah superset dari pelacakan mata standar, yang hanya menyediakan data tatapan mata gabungan. Pelacakan mata yang diperluas juga menyediakan data tatapan mata individu dan memungkinkan aplikasi untuk mengatur kecepatan bingkai yang berbeda untuk data tatapan, seperti 30, 60, dan 90fps. Fitur lain, seperti keterbukaan mata dan vergensi mata, tidak didukung oleh HoloLens 2 saat ini.
Extended Eye Tracking SDK memungkinkan aplikasi mengakses data dan fitur pelacakan mata yang diperluas. Ini dapat digunakan bersama dengan API OpenXR atau API WinRT warisan.
Artikel ini membahas cara menggunakan SDK pelacakan mata yang diperluas di Unity bersama dengan Plugin OpenXR Mixed Reality.
Penyusunan proyek
-
Siapkan proyek Unity untuk pengembangan HoloLens.
- Pilih kapabilitas Input Tatap
- Impor Mixed Reality OpenXR Plugin dari alat fitur MRTK.
- Impor paket Eye Tracking SDK NuGet ke dalam proyek Unity Anda.
- Unduh dan instal paket NuGetForUnity .
- Di editor Unity, buka
NuGet
->Manage NuGet Packages
, lalu cariMicrosoft.MixedReality.EyeTracking
- Klik tombol Instal untuk mengimpor versi terbaru paket NuGet.
- Tambahkan skrip pembantu Unity.
-
ExtendedEyeGazeDataProvider.cs
Tambahkan skrip dari sini ke proyek Unity Anda. - Buat adegan, lalu lampirkan
ExtendedEyeGazeDataProvider.cs
skrip ke GameObject apa pun.
-
- Gunakan fungsi
ExtendedEyeGazeDataProvider.cs
dan terapkan logika Anda. - Bangun dan sebarkan ke HoloLens.
Menggunakan fungsi ExtendedEyeGazeDataProvider
Catatan
ExtendedEyeGazeDataProvider
Skrip tergantung pada beberapa API dari Plugin OpenXR Mixed Reality untuk mengonversi koordinat data tatapan. Ini tidak dapat berfungsi jika proyek Unity Anda menggunakan plugin Windows XR yang tidak digunakan lagi atau XR Bawaan warisan dalam versi Unity yang lebih lama. Untuk membuat pelacakan mata yang diperluas juga berfungsi dalam skenario tersebut:
- Jika Anda hanya perlu mengakses pengaturan kecepatan bingkai, plugin OpenXR Mixed Reality tidak diperlukan, dan Anda dapat memodifikasi
ExtendedEyeGazeDataProvider
untuk hanya menyimpan logika terkait kecepatan bingkai. - Jika Anda masih perlu mengakses data tatapan mata individual, Anda perlu menggunakan API WinRT di Unity. Untuk melihat cara menggunakan SDK pelacakan mata yang diperluas dengan API WinRT, lihat bagian "Lihat Juga".
Kelas membungkus ExtendedEyeGazeDataProvider
API SDK pelacakan mata yang diperluas. Ini menyediakan fungsi untuk mendapatkan tatapan membaca di ruang dunia Unity atau relatif terhadap kamera utama.
Berikut adalah sampel kode yang akan dikonsumsi ExtendedEyeGazeDataProvider
untuk mendapatkan data tatap.
ExtendedEyeGazeDataProvider extendedEyeGazeDataProvider;
void Update() {
timestamp = DateTime.Now;
var leftGazeReadingInWorldSpace = extendedEyeGazeDataProvider.GetWorldSpaceGazeReading(extendedEyeGazeDataProvider.GazeType.Left, timestamp);
var rightGazeReadingInWorldSpace = extendedEyeGazeDataProvider.GetWorldSpaceGazeReading(extendedEyeGazeDataProvider.GazeType.Right, timestamp);
var combinedGazeReadingInWorldSpace = extendedEyeGazeDataProvider.GetWorldSpaceGazeReading(extendedEyeGazeDataProvider.GazeType.Combined, timestamp);
var combinedGazeReadingInCameraSpace = extendedEyeGazeDataProvider.GetCameraSpaceGazeReading(extendedEyeGazeDataProvider.GazeType.Combined, timestamp);
}
ExtendedEyeGazeDataProvider
Ketika skrip dijalankan, skrip mengatur kecepatan bingkai data tatapan ke opsi tertinggi, yang saat ini 90fps.
Referensi API dari SDK pelacakan mata yang diperluas
Selain menggunakan ExtendedEyeGazeDataProvider
skrip, Anda juga dapat membuat skrip Anda sendiri untuk menggunakan API SDK berikut secara langsung.
namespace Microsoft.MixedReality.EyeTracking
{
/// <summary>
/// Allow discovery of Eye Gaze Trackers connected to the system
/// This is the only class from the Extended Eye Tracking SDK that the application will instantiate,
/// other classes' instances will be returned by method calls or properties.
/// </summary>
public class EyeGazeTrackerWatcher
{
/// <summary>
/// Constructs an instance of the watcher
/// </summary>
public EyeGazeTrackerWatcher();
/// <summary>
/// Starts trackers enumeration.
/// </summary>
/// <returns>Task representing async action; completes when the initial enumeration is completed</returns>
public System.Threading.Tasks.Task StartAsync();
/// <summary>
/// Stop listening to trackers additions and removal
/// </summary>
public void Stop();
/// <summary>
/// Raised when an Eye Gaze tracker is connected
/// </summary>
public event System.EventHandler<EyeGazeTracker> EyeGazeTrackerAdded;
/// <summary>
/// Raised when an Eye Gaze tracker is disconnected
/// </summary>
public event System.EventHandler<EyeGazeTracker> EyeGazeTrackerRemoved;
}
/// <summary>
/// Represents an Eye Tracker device
/// </summary>
public class EyeGazeTracker
{
/// <summary>
/// True if Restricted mode is supported, which means the driver supports providing individual
/// eye gaze vector and frame rate
/// </summary>
public bool IsRestrictedModeSupported;
/// <summary>
/// True if Vergence Distance is supported by tracker
/// </summary>
public bool IsVergenceDistanceSupported;
/// <summary>
/// True if Eye Openness is supported by the driver
/// </summary>
public bool IsEyeOpennessSupported;
/// <summary>
/// True if individual gazes are supported
/// </summary>
public bool AreLeftAndRightGazesSupported;
/// <summary>
/// Get the supported target frame rates of the tracker
/// </summary>
public System.Collections.Generic.IReadOnlyList<EyeGazeTrackerFrameRate> SupportedTargetFrameRates;
/// <summary>
/// NodeId of the tracker, used to retrieve a SpatialLocator or SpatialGraphNode to locate the tracker in the scene
/// for the Perception API, use SpatialGraphInteropPreview.CreateLocatorForNode
/// for the Mixed Reality OpenXR API, use SpatialGraphNode.FromDynamicNodeId
/// </summary>
public Guid TrackerSpaceLocatorNodeId;
/// <summary>
/// Opens the tracker
/// </summary>
/// <param name="restrictedMode">True if restricted mode active</param>
/// <returns>Task representing async action; completes when the initial enumeration is completed</returns>
public System.Threading.Tasks.Task OpenAsync(bool restrictedMode);
/// <summary>
/// Closes the tracker
/// </summary>
public void Close();
/// <summary>
/// Changes the target frame rate of the tracker
/// </summary>
/// <param name="newFrameRate">Target frame rate</param>
public void SetTargetFrameRate(EyeGazeTrackerFrameRate newFrameRate);
/// <summary>
/// Try to get tracker state at a given timestamp
/// </summary>
/// <param name="timestamp">timestamp</param>
/// <returns>State if available, null otherwise</returns>
public EyeGazeTrackerReading TryGetReadingAtTimestamp(DateTime timestamp);
/// <summary>
/// Try to get tracker state at a system relative time
/// </summary>
/// <param name="time">time</param>
/// <returns>State if available, null otherwise</returns>
public EyeGazeTrackerReading TryGetReadingAtSystemRelativeTime(TimeSpan time);
/// <summary>
/// Try to get first first tracker state after a given timestamp
/// </summary>
/// <param name="timestamp">timestamp</param>
/// <returns>State if available, null otherwise</returns>
public EyeGazeTrackerReading TryGetReadingAfterTimestamp(DateTime timestamp);
/// <summary>
/// Try to get the first tracker state after a system relative time
/// </summary>
/// <param name="time">time</param>
/// <returns>State if available, null otherwise</returns>
public EyeGazeTrackerReading TryGetReadingAfterSystemRelativeTime(TimeSpan time);
}
/// <summary>
/// Represents a frame rate supported by an Eye Tracker
/// </summary>
public class EyeGazeTrackerFrameRate
{
/// <summary>
/// Frames per second of the frame rate
/// </summary>
public UInt32 FramesPerSecond;
}
/// <summary>
/// Snapshot of Gaze Tracker state
/// </summary>
public class EyeGazeTrackerReading
{
/// <summary>
/// Timestamp of state
/// </summary>
public DateTime Timestamp;
/// <summary>
/// Timestamp of state as system relative time
/// Its SystemRelativeTime.Ticks could provide the QPC time to locate tracker pose
/// </summary>
public TimeSpan SystemRelativeTime;
/// <summary>
/// Indicates of user calibration is valid
/// </summary>
public bool IsCalibrationValid;
/// <summary>
/// Tries to get a vector representing the combined gaze related to the tracker's node
/// </summary>
/// <param name="origin">Origin of the gaze vector</param>
/// <param name="direction">Direction of the gaze vector</param>
/// <returns></returns>
public bool TryGetCombinedEyeGazeInTrackerSpace(out System.Numerics.Vector3 origin, out System.Numerics.Vector3 direction);
/// <summary>
/// Tries to get a vector representing the left eye gaze related to the tracker's node
/// </summary>
/// <param name="origin">Origin of the gaze vector</param>
/// <param name="direction">Direction of the gaze vector</param>
/// <returns></returns>
public bool TryGetLeftEyeGazeInTrackerSpace(out System.Numerics.Vector3 origin, out System.Numerics.Vector3 direction);
/// <summary>
/// Tries to get a vector representing the right eye gaze related to the tracker's node position
/// </summary>
/// <param name="origin">Origin of the gaze vector</param>
/// <param name="direction">Direction of the gaze vector</param>
/// <returns></returns>
public bool TryGetRightEyeGazeInTrackerSpace(out System.Numerics.Vector3 origin, out System.Numerics.Vector3 direction);
/// <summary>
/// Tries to read vergence distance
/// </summary>
/// <param name="value">Vergence distance if available</param>
/// <returns>bool if value is valid</returns>
public bool TryGetVergenceDistance(out float value);
/// <summary>
/// Tries to get left Eye openness information
/// </summary>
/// <param name="value">Eye Openness if valid</param>
/// <returns>bool if value is valid</returns>
public bool TryGetLeftEyeOpenness(out float value);
/// <summary>
/// Tries to get right Eye openness information
/// </summary>
/// <param name="value">Eye openness if valid</param>
/// <returns>bool if value is valid</returns>
public bool TryGetRightEyeOpenness(out float value);
}
}