Fej-tekintet és szem-tekintet bemenet a DirectX-ben
Megjegyzés
Ez a cikk az örökölt WinRT natív API-kkal kapcsolatos. Új natív alkalmazásprojektek esetén az OpenXR API használatát javasoljuk.
A Windows Mixed Reality szem- és fejnézet bemenete határozza meg, hogy mit néz a felhasználó. Az adatokkal olyan elsődleges bemeneti modelleket hajthat végre, mint a tekintet és a véglegesítés, és kontextust biztosíthat a különböző interakciótípusokhoz. Az API-val kétféle tekintetvektor érhető el: a fej-tekintet és a tekintet. Mindkettő háromdimenziós sugárként van megadva, amelynek eredete és iránya van. Az alkalmazások ezután besugárzhatják a jeleneteiket vagy a valós világot, és megállapíthatják, hogy a felhasználó mit céloz meg.
A fej-tekintet azt az irányt jelöli, amelybe a felhasználó feje mutat. Gondoljon a fej-tekintetre úgy, mint az eszköz helyzetére és előre irányára, a két kijelző közötti középponttal. A tekintet minden Mixed Reality eszközön elérhető.
A szempillantás azt az irányt jelöli, amelyet a felhasználó szeme keres. A forrás a felhasználó szeme között található. Olyan Mixed Reality eszközökön érhető el, amelyek szemkövető rendszert is tartalmaznak.
A head és a eye-gaze sugarak is elérhetők a SpatialPointerPose API-val. Hívja meg a SpatialPointerPose::TryGetAtTimestamp parancsot egy új SpatialPointerPose objektum fogadásához a megadott időbélyegzőn és koordinátarendszeren. Ez a SpatialPointerPose egy szempillantású forrást és irányt tartalmaz. Emellett szem-tekintet forrást és irányt is tartalmaz, ha elérhető a szemkövetés.
Eszköztámogatás
Szolgáltatás | HoloLens (1. generációs) | HoloLens 2 | Modern headsetek |
Fej-tekintet | ✔️ | ✔️ | ✔️ |
Szempillantás | ❌ | ✔️ | ❌ |
Fej-tekintet használata
A tekintethez való hozzáféréshez először hívja meg a SpatialPointerPose::TryGetAtTimestamp parancsot egy új SpatialPointerPose objektum fogadásához. Adja meg az alábbi paramétereket.
- Egy SpatialCoordinateSystem, amely a fej-tekintethez használni kívánt koordinátarendszert jelöli. Ezt a koordinátaRendszer változó jelöli az alábbi kódban. További információt a koordinátarendszerek fejlesztői útmutatójában talál.
- Egy időbélyeg, amely a kért fejpóz pontos idejét jelöli. Általában olyan időbélyeget használ, amely megfelel az aktuális keret megjelenítésének időpontjának. Ezt az előrejelzett megjelenítési időbélyeget egy HolographicFramePrediction objektumból szerezheti be, amely az aktuális HolographicFrame-keretrendszeren keresztül érhető el. Ezt a HolographicFramePrediction objektumot az előrejelzési változó jelöli az alábbi kódban.
Ha már rendelkezik érvényes SpatialPointerPose-tal, a fej pozíciója és az előre mutató irány tulajdonságokként lesz elérhető. Az alábbi kód bemutatja, hogyan érheti el őket.
using namespace winrt::Windows::UI::Input::Spatial;
using namespace winrt::Windows::Foundation::Numerics;
SpatialPointerPose pointerPose = SpatialPointerPose::TryGetAtTimestamp(coordinateSystem, prediction.Timestamp());
if (pointerPose)
{
float3 headPosition = pointerPose.Head().Position();
float3 headForwardDirection = pointerPose.Head().ForwardDirection();
// Do something with the head-gaze
}
Szempillantás használata
Ahhoz, hogy a felhasználók szem-tekintet bemenetet használjanak, minden felhasználónak át kell mennie egy szemkövető felhasználó kalibrálásán az eszköz első használatakor. A szem-tekintet API hasonló a fej-tekintethez. Ugyanazt a SpatialPointerPose API-t használja, amely egy sugár eredetét és irányát biztosítja, amelyet a jeleneten átsugározhat. Az egyetlen különbség az, hogy a használat előtt explicit módon engedélyeznie kell a szemkövetést:
- Kérjen felhasználói engedélyt a szemkövetés használatára az alkalmazásban.
- Engedélyezze a "Tekintet bemenete" funkciót a csomagjegyzékben.
Hozzáférés kérése a szempillantás bemenetéhez
Az alkalmazás indításakor hívja fel a EyesPose::RequestAccessAsync parancsot, hogy hozzáférést kérjen a szemkövetéshez. A rendszer szükség esetén rákérdez a felhasználóra, és visszaadja a GazeInputAccessStatus::Allowed értéket a hozzáférés megadása után. Ez egy aszinkron hívás, ezért egy kis extra felügyeletet igényel. Az alábbi példa egy leválasztott std::szálat hoz létre, amely megvárja az eredményt, amelyet egy m_isEyeTrackingEnabled nevű tagváltozóban tárol.
using namespace winrt::Windows::Perception::People;
using namespace winrt::Windows::UI::Input;
std::thread requestAccessThread([this]()
{
auto status = EyesPose::RequestAccessAsync().get();
if (status == GazeInputAccessStatus::Allowed)
m_isEyeTrackingEnabled = true;
else
m_isEyeTrackingEnabled = false;
});
requestAccessThread.detach();
A leválasztott szálak indítása csak egy lehetőség az aszinkron hívások kezelésére. Használhatja a C++/WinRT által támogatott új co_await funkciót is. Íme egy másik példa a felhasználói engedély kérésére:
- EyesPose::IsSupported() lehetővé teszi, hogy az alkalmazás csak akkor aktiválja az engedély párbeszédpanelt, ha van szemkövető.
- GazeInputAccessStatus m_gazeInputAccessStatus; Ennek célja, hogy megakadályozza az engedélykérés ismételt és ismételt felbukkanását.
GazeInputAccessStatus m_gazeInputAccessStatus; // This is to prevent popping up the permission prompt over and over again.
// This will trigger to show the permission prompt to the user.
// Ask for access if there is a corresponding device and registry flag did not disable it.
if (Windows::Perception::People::EyesPose::IsSupported() &&
(m_gazeInputAccessStatus == GazeInputAccessStatus::Unspecified))
{
Concurrency::create_task(Windows::Perception::People::EyesPose::RequestAccessAsync()).then(
[this](GazeInputAccessStatus status)
{
// GazeInputAccessStatus::{Allowed, DeniedBySystem, DeniedByUser, Unspecified}
m_gazeInputAccessStatus = status;
// Let's be sure to not ask again.
if(status == GazeInputAccessStatus::Unspecified)
{
m_gazeInputAccessStatus = GazeInputAccessStatus::DeniedBySystem;
}
});
}
A tekintet bemenetének deklarálása
Kattintson duplán az appxmanifest fájlra a Megoldáskezelőben. Ezután lépjen a Képességek szakaszra, és ellenőrizze a Tekintet bemenete képességet.
Ez hozzáadja a következő sorokat az appxmanifest fájl Csomag szakaszához:
<Capabilities>
<DeviceCapability Name="gazeInput" />
</Capabilities>
A szem-tekintet sugarának lekérése
Miután megkapta a hozzáférést az ET-hez, minden képkockán szabadon megragadhatja a szem-tekintet sugarát. A head-tekintethez hasonlóan a SpatialPointerPose::TryGetAtTimestamp hívásával is beszerezheti a SpatialPointerPose-t a kívánt időbélyeggel és koordinátarendszerrel. A SpatialPointerPose egy EyesPose objektumot tartalmaz a Eyes tulajdonságon keresztül. Ez csak akkor nem null értékű, ha a szemkövetés engedélyezve van. Innen a EyesPose:IsCalibrationValid hívásával ellenőrizheti, hogy az eszköz felhasználója rendelkezik-e szemkövetési kalibrációval. Ezután használja a Tekintet tulajdonságot a szem-tekintet pozíciót és irányt tartalmazó SpatialRay lekéréséhez. A Tekintet tulajdonság néha null értékű is lehet, ezért mindenképpen ellenőrizze ezt. Ez akkor fordulhat elő, ha egy kalibrált felhasználó ideiglenesen bezárja a szemét.
Az alábbi kód bemutatja, hogyan lehet hozzáférni a szem-tekintet sugarához.
using namespace winrt::Windows::UI::Input::Spatial;
using namespace winrt::Windows::Foundation::Numerics;
SpatialPointerPose pointerPose = SpatialPointerPose::TryGetAtTimestamp(coordinateSystem, prediction.Timestamp());
if (pointerPose)
{
if (pointerPose.Eyes() && pointerPose.Eyes().IsCalibrationValid())
{
if (pointerPose.Eyes().Gaze())
{
auto spatialRay = pointerPose.Eyes().Gaze().Value();
float3 eyeGazeOrigin = spatialRay.Origin;
float3 eyeGazeDirection = spatialRay.Direction;
// Do something with the eye-gaze
}
}
}
Tartalék, ha a szemkövetés nem érhető el
Amint azt a szemkövetési tervezési dokumentációnkban is említettük, a tervezőknek és a fejlesztőknek is tisztában kell lenniük azokkal a példányokkal, ahol a szemkövetési adatok nem érhetők el.
Az adatok nem érhetők el különböző okokból:
- A felhasználó nincs kalibrálva
- Egy felhasználó megtagadta az alkalmazás hozzáférését a szemkövetési adataihoz
- Ideiglenes interferenciák, például a HoloLens-viszoron vagy a felhasználó szemét elzáró hajon történő elmosódások.
Bár az API-k némelyike már szerepel ebben a dokumentumban, a következőkben röviden bemutatjuk, hogyan észlelhető a szemkövetés gyorshivatkozásként:
Ellenőrizze, hogy a rendszer egyáltalán támogatja-e a szemkövetést. Hívja meg a következő metódust: Windows.Perception.Kapcsolatok. EyesPose.IsSupported()
Ellenőrizze, hogy a felhasználó kalibrálva van-e. Hívja meg a következő tulajdonságot: Windows.Perception.Kapcsolatok. EyesPose.IsCalibrationValid
Ellenőrizze, hogy a felhasználó engedélyt adott-e az alkalmazásnak a szemkövetési adataik használatára: Kérje le az aktuális "GazeInputAccessStatus" kifejezést. Ennek módjára egy példát a Tekintet bemenetéhez való hozzáférés kérése című témakörben ismertetünk.
Azt is érdemes ellenőrizni, hogy a szemkövetési adatok nem elavultak-e, ha időtúllépést ad hozzá a kapott szemkövetési adatok frissítései között, és ellenkező esetben visszaesik a tekintetre az alábbiakban ismertetett módon. További információért tekintse meg a tartalék kialakítással kapcsolatos szempontokat .
Tekintet korrelálása más bemenetekkel
Előfordulhat, hogy olyan SpatialPointerPose-ra van szüksége, amely megfelel egy múltbeli eseménynek. Ha például a felhasználó légi koppintással végzi el a műveletet, előfordulhat, hogy az alkalmazás tudni szeretné, hogy mit néztek. Ehhez egyszerűen használja a SpatialPointerPose::TryGetAtTimestamp paramétert az előrejelzett keretidővel, mert a rendszer bemenetének feldolgozása és a megjelenítési idő közötti késés miatt pontatlan. Továbbá, ha szem-tekintetet használ a célzáshoz, a szemünk hajlamosak továbblépni még a véglegesítési művelet befejezése előtt is. Ez kevésbé jelent problémát egy egyszerű légcsapolás esetében, de kritikusabbá válik a hosszú hangparancsok és a gyors szemmozgások kombinálásakor. Ennek a forgatókönyvnek az egyik módja, ha egy további hívást kezdeményez a SpatialPointerPose::TryGetAtTimestamp felé a bemeneti eseménynek megfelelő előzményidőbélyeg használatával.
A SpatialInteractionManageren áthaladó bemenetek esetében azonban van egy egyszerűbb módszer. A SpatialInteractionSourceState saját TryGetAtTimestamp függvénnyel rendelkezik. Olyan hívás, amely tökéletesen korrelált SpatialPointerPose-t biztosít a találgatások nélkül. A SpatialInteractionSourceStates használatával kapcsolatos további információkért tekintse meg a kéz- és mozgásvezérlőket a DirectX dokumentációjában .
Kalibrációs
Ahhoz, hogy a szemkövetés pontosan működjön, minden felhasználónak át kell mennie egy szemkövető felhasználó kalibrálásán. Ez lehetővé teszi az eszköz számára a rendszer beállítását a felhasználó számára kényelmesebb és jobb minőségű megtekintési élmény érdekében, valamint a pontos szemkövetés egyidejű biztosításához. A fejlesztőknek nem kell semmit tenniük a felhasználói kalibrálás kezeléséhez. A rendszer biztosítja, hogy a rendszer a következő körülmények között kérje meg a felhasználót az eszköz kalibrálására:
- A felhasználó első alkalommal használja az eszközt
- A felhasználó korábban letiltotta a kalibrálási folyamatot
- A kalibrálási folyamat nem sikerült, amikor a felhasználó utoljára használta az eszközt
A fejlesztőknek gondoskodniuk kell arról, hogy megfelelő támogatást nyújtsanak azoknak a felhasználóknak, ahol a szemkövetési adatok nem érhetők el. További információ a tartalék megoldások megfontolandó szempontjairól a Szemkövetés a HoloLens 2 oldalon.