Hände und Motion-Controller in DirectX
Hinweis
Dieser Artikel bezieht sich auf die älteren nativen WinRT-APIs. Für neue native App-Projekte empfehlen wir die Verwendung der OpenXR-API.
In Windows Mixed Reality werden sowohl Hand- als auch Bewegungscontrollereingaben über die räumlichen Eingabe-APIs verarbeitet, die sich im Windows.UI.Input.Spatial-Namespace befinden. Auf diese Weise können Sie gängige Aktionen wie Select-Drücken auf die gleiche Weise sowohl für Hände als auch für Bewegungscontroller verarbeiten.
Erste Schritte
Um auf räumliche Eingaben in Windows Mixed Reality zuzugreifen, beginnen Sie mit der SpatialInteractionManager-Schnittstelle. Sie können auf diese Schnittstelle zugreifen, indem Sie SpatialInteractionManager::GetForCurrentView aufrufen, in der Regel irgendwann während des App-Startes.
using namespace winrt::Windows::UI::Input::Spatial;
SpatialInteractionManager interactionManager = SpatialInteractionManager::GetForCurrentView();
Der Auftrag des SpatialInteractionManagers besteht darin, den Zugriff auf SpatialInteractionSources zu ermöglichen, die eine Eingabequelle darstellen. Es gibt drei Arten von SpatialInteractionSources im System.
- Hand stellt die erkannte Hand eines Benutzers dar. Handquellen bieten verschiedene Funktionen basierend auf dem Gerät, die von einfachen Gesten auf HoloLens bis hin zur vollständig artikulierten Handnachverfolgung auf HoloLens 2 reichen.
- Controller stellt einen gekoppelten Bewegungscontroller dar. Bewegungscontroller können unterschiedliche Funktionen bieten, z. B. Trigger auswählen, Menüschaltflächen, Tasten, Touchpads und Fingersticks.
- Voice stellt die vom System erkannten Sprachbegriffe des Benutzers dar. Beispielsweise fügt diese Quelle eine Select-Pressemitteilung ein, wenn der Benutzer "Auswählen" sagt.
Framebezogene Daten für eine Quelle werden durch die SpatialInteractionSourceState-Schnittstelle dargestellt. Es gibt zwei verschiedene Möglichkeiten, auf diese Daten zuzugreifen, je nachdem, ob Sie ein ereignisgesteuertes oder abfragebasiertes Modell in Ihrer Anwendung verwenden möchten.
Ereignisgesteuerte Eingabe
Der SpatialInteractionManager stellt eine Reihe von Ereignissen bereit, auf die Ihre App lauschen kann. Einige Beispiele sind SourcePressed, [SourceReleased und SourceUpdated.
Der folgende Code verknüpft beispielsweise einen Ereignishandler namens MyApp::OnSourcePressed mit dem SourcePressed-Ereignis. Dadurch kann Ihre App Druckvorgänge für jede Art von Interaktionsquelle erkennen.
using namespace winrt::Windows::UI::Input::Spatial;
auto interactionManager = SpatialInteractionManager::GetForCurrentView();
interactionManager.SourcePressed({ this, &MyApp::OnSourcePressed });
Dieses gedrückte Ereignis wird asynchron an Ihre App gesendet, zusammen mit dem entsprechenden SpatialInteractionSourceState zum Zeitpunkt des Drückens. Ihre App oder Spiel-Engine möchte möglicherweise sofort mit der Verarbeitung beginnen oder die Ereignisdaten in der Eingabeverarbeitungsroutine in die Warteschlange stellen. Hier sehen Sie eine Ereignishandlerfunktion für das SourcePressed-Ereignis, mit der überprüft wird, ob die Auswahlschaltfläche gedrückt wurde.
using namespace winrt::Windows::UI::Input::Spatial;
void MyApp::OnSourcePressed(SpatialInteractionManager const& sender, SpatialInteractionSourceEventArgs const& args)
{
if (args.PressKind() == SpatialInteractionPressKind::Select)
{
// Select button was pressed, update app state
}
}
Mit dem obigen Code wird nur die "Select"-Taste überprüft, die der primären Aktion auf dem Gerät entspricht. Beispiele hierfür sind das Ausführen eines AirTap auf HoloLens oder das Ziehen des Triggers auf einem Bewegungscontroller. "Select"-Drücken stellen die Absicht des Benutzers dar, das Hologramm zu aktivieren, auf das er abzielt. Das SourcePressed-Ereignis wird für eine Reihe verschiedener Schaltflächen und Gesten ausgelöst, und Sie können andere Eigenschaften der SpatialInteractionSource untersuchen, um sie für diese Fälle zu testen.
Abfragebasierte Eingabe
Sie können auch SpatialInteractionManager verwenden, um den aktuellen Status der Eingabe für jeden Frame abzufragen. Rufen Sie hierzu getDetectedSourcesAtTimestamp jeden Frame auf. Diese Funktion gibt ein Array zurück, das einen SpatialInteractionSourceState für jede aktive SpatialInteractionSource enthält. Dies bedeutet einen für jeden aktiven Bewegungscontroller, einen für jede nachverfolgte Hand und einen für sprache, wenn kürzlich ein "Select"-Befehl ausgesprochen wurde. Anschließend können Sie die Eigenschaften für jeden SpatialInteractionSourceState überprüfen, um Eingaben in Ihre Anwendung zu steuern.
Hier sehen Sie ein Beispiel dafür, wie Sie mithilfe der Abfragemethode nach der Aktion "Auswählen" suchen. Die Vorhersagevariable stellt ein HolographicFramePrediction-Objekt dar, das aus dem HolographicFrame abgerufen werden kann.
using namespace winrt::Windows::UI::Input::Spatial;
auto interactionManager = SpatialInteractionManager::GetForCurrentView();
auto sourceStates = m_spatialInteractionManager.GetDetectedSourcesAtTimestamp(prediction.Timestamp());
for (auto& sourceState : sourceStates)
{
if (sourceState.IsSelectPressed())
{
// Select button is down, update app state
}
}
Jede SpatialInteractionSource verfügt über eine ID, mit der Sie neue Quellen identifizieren und vorhandene Quellen von Frame zu Frame korrelieren können. Die Hände erhalten bei jedem Verlassen eine neue ID und geben den FOV ein, aber Controller-IDs bleiben für die Dauer der Sitzung statisch. Sie können die Ereignisse auf SpatialInteractionManager wie SourceDetected und SourceLost verwenden, um zu reagieren, wenn Hände die Geräteansicht betreten oder verlassen oder wenn Bewegungscontroller aktiviert/deaktiviert oder gekoppelt/entkoppelt werden.
Vorhergesagte im Vergleich zu historischen Posen
GetDetectedSourcesAtTimestamp verfügt über einen Zeitstempelparameter. Auf diese Weise können Sie Zustands- und Posedaten anfordern, die entweder vorhergesagt oder historisch sind, sodass Sie räumliche Interaktionen mit anderen Eingabequellen korrelieren können. Wenn Sie beispielsweise die Position der Hand im aktuellen Frame rendern, können Sie den vorhergesagten Zeitstempel übergeben, der vom HolographicFrame bereitgestellt wird. Dadurch kann das System die Handposition voraussagen, um sich eng an der gerenderten Frameausgabe auszurichten, wodurch die wahrgenommene Latenz minimiert wird.
Eine solche vorhergesagte Pose erzeugt jedoch keinen idealen Zeigerstrahl für das Targeting mit einer Interaktionsquelle. Wenn beispielsweise eine Motion Controller-Taste gedrückt wird, kann es bis zu 20 ms dauern, bis dieses Ereignis über Bluetooth an das Betriebssystem weitergeleitet wird. Ebenso kann nach dem Ausführen einer Handbewegung ein gewisser Zeitraum vergehen, bis das System die Geste erkennt und Ihre App sie dann abruft. Wenn Ihre App nach einer Zustandsänderung fragt, wurden die Kopf- und Handhaltungen verwendet, um auf diese Interaktion in der Vergangenheit zu abzielen. Wenn Sie den Zeitstempel Ihres aktuellen HolographicFrames an GetDetectedSourcesAtTimestamp übergeben, wird die Pose stattdessen an den Zielstrahl weitergeleitet, wenn der Frame angezeigt wird, was in zukunft mehr als 20 ms betragen könnte. Diese zukünftige Pose ist gut für das Rendern der Interaktionsquelle, erhöht aber unser Zeitproblem für die Interaktion , da das Ziel des Benutzers in der Vergangenheit aufgetreten ist.
Glücklicherweise stellen die Ereignisse SourcePressed, [SourceReleased und SourceUpdated den verlaufsbasierten Zustand bereit, der jedem Eingabeereignis zugeordnet ist. Dies umfasst direkt die über TryGetPointerPose verfügbaren historischen Kopf- und Handposen sowie einen historischen Zeitstempel , den Sie an andere APIs übergeben können, um mit diesem Ereignis zu korrelieren.
Dies führt zu den folgenden bewährten Methoden beim Rendern und Zielen mit Händen und Controllern für jeden Frame:
- Beim Rendern von Hand/Controllern für jeden Frame sollte Ihre App die vorausgesagte Pose jeder Interaktionsquelle zur Photonenzeit des aktuellen Frames abfragen. Sie können alle Interaktionsquellen abfragen, indem Sie getDetectedSourcesAtTimestamp jeden Frame aufrufen und den vorhergesagten Zeitstempel übergeben, der von HolographicFrame::CurrentPrediction bereitgestellt wird.
- Bei Hand-/Controllern, die auf eine Pressemitteilung oder Veröffentlichung abzielen, sollte Ihre App gepresste/freigegebene Ereignisse verarbeiten, raycasting basierend auf dem historischen Kopf oder der Handpose für dieses Ereignis. Sie erhalten diesen Zielstrahl, indem Sie das SourcePressed- oder SourceReleased-Ereignis behandeln, die State-Eigenschaft aus den Ereignisargumenten abrufen und dann die TryGetPointerPose-Methode aufrufen.
Geräteübergreifende Eingabeeigenschaften
Die SpatialInteractionSource-API unterstützt Controller und Handnachverfolgungssysteme mit einer Vielzahl von Funktionen. Eine Reihe dieser Funktionen sind für Gerätetypen üblich. Beispielsweise bieten Handverfolgungs- und Bewegungscontroller sowohl eine "Auswählen"-Aktion als auch eine 3D-Position. Nach Möglichkeit ordnet die API diese allgemeinen Funktionen den gleichen Eigenschaften für SpatialInteractionSource zu. Dadurch können Anwendungen eine vielzahl von Eingabetypen einfacher unterstützen. In der folgenden Tabelle werden die unterstützten Eigenschaften und deren Vergleich zwischen Eingabetypen beschrieben.
Eigenschaft | BESCHREIBUNG | HoloLens(1. Generation) Gesten | Bewegungscontroller | Gelenkhände |
---|---|---|---|---|
SpatialInteractionSource::Handedness | Rechte oder linke Hand / Controller. | Nicht unterstützt | Unterstützt | Unterstützt |
SpatialInteractionSourceState::IsSelectPressed | Aktueller Status der primären Schaltfläche. | Luft tippen | Trigger | Relax Air Tap (aufrechter Pinch) |
SpatialInteractionSourceState::IsGrasped | Aktueller Status der Schaltfläche "Grab". | Nicht unterstützt | Schaltfläche "Grab" | Anheften oder geschlossene Hand |
SpatialInteractionSourceState::IsMenuPressed | Aktueller Status der Menüschaltfläche. | Nicht unterstützt | Menüschaltfläche | Nicht unterstützt |
SpatialInteractionSourceLocation::Position | XYZ-Position der Hand- oder Griffposition auf dem Controller. | Standort der Palme | Position der Griffposition | Standort der Palme |
SpatialInteractionSourceLocation::Orientation | Quaternion, die die Ausrichtung der Hand- oder Griffposition auf dem Controller darstellt. | Nicht unterstützt | Ausrichtung der Griffposition | Handflächenausrichtung |
SpatialPointerInteractionSourcePose::Position | Ursprung des zeigenden Strahls. | Nicht unterstützt | Unterstützt | Unterstützt |
SpatialPointerInteractionSourcePose::ForwardDirection | Richtung des zeigenden Strahls. | Nicht unterstützt | Unterstützt | Unterstützt |
Einige der oben genannten Eigenschaften sind nicht auf allen Geräten verfügbar, und die API bietet eine Möglichkeit, dies zu testen. Sie können beispielsweise die SpatialInteractionSource::IsGraspSupported-Eigenschaft untersuchen, um zu ermitteln, ob die Quelle eine Erfassungsaktion bereitstellt.
Griffpose im Vergleich zu zeigernden Posen
Windows Mixed Reality unterstützt Motion Controller in verschiedenen Formfaktoren. Es unterstützt auch handgelenkte Nachverfolgungssysteme. Alle diese Systeme haben unterschiedliche Beziehungen zwischen der Handposition und der natürlichen "Vorwärts"-Richtung, die Apps zum Zeigen oder Rendern von Objekten in der Hand des Benutzers verwenden sollten. Um all dies zu unterstützen, gibt es zwei Arten von 3D-Posen, die sowohl für die Handverfolgung als auch für Bewegungscontroller bereitgestellt werden. Die erste ist die Griffhaltung, die die Handposition des Benutzers darstellt. Die zweite ist die zeigende Pose, die einen zeigenden Strahl darstellt, der von der Hand oder dem Controller des Benutzers stammt. Wenn Sie also die Hand des Benutzers oder ein Objekt in der Hand des Benutzers rendern möchten, z. B. ein Schwert oder eine Waffe, verwenden Sie die Griffhaltung. Wenn Sie vom Controller oder der Hand raycasten möchten, z. B. wenn der Benutzer **auf die Benutzeroberfläche zeigt, verwenden Sie die zeigende Pose.
Sie können über SpatialInteractionSourceState::P roperties::TryGetLocation(...) auf die Griffposition zugreifen. Sie wird wie folgt definiert:
- Die Griffposition: Die Handfläche beim natürlichen Halten des Controllers, links oder rechts eingestellt, um die Position innerhalb des Griffs zu zentrieren.
- Die rechte Achse der Griffausrichtung: Wenn Sie Ihre Hand vollständig öffnen, um eine flache 5-Finger-Pose zu bilden, der Strahl, der für Ihre Handfläche normal ist (vorwärts von der linken Handfläche, rückwärts von der rechten Handfläche)
- Die Vorwärtsachse der Griffausrichtung: Wenn Sie Ihre Hand teilweise schließen (so, als ob Sie den Controller halten), der Strahl, der "vorwärts" durch den Schlauch zeigt, der von Ihren Nicht-Daumenfingern gebildet wird.
- Die Up-Achse der Griffausrichtung: Die nach oben gerichtete Achse, die von den Definitionen Rechts und Vorwärts impliziert wird.
Sie können über SpatialInteractionSourceState::P roperties::TryGetLocation(...)::SourcePointerPose oder SpatialInteractionSourceState::TryGetPointerPose(...)::TryGetInteractionSourcePose auf die Zeigerpose zugreifen.
Controllerspezifische Eingabeeigenschaften
Für Controller verfügt die SpatialInteractionSource über eine Controller-Eigenschaft mit zusätzlichen Funktionen.
- HasThumbstick: Wenn true, verfügt der Controller über einen Fingerabdruckstick. Überprüfen Sie die ControllerProperties-Eigenschaft von SpatialInteractionSourceState, um die Thumbstick-x- und y-Werte (ThumbstickX und ThumbstickY) sowie den gedrückten Zustand (IsThumbstickPressed) abzurufen.
- HasTouchpad: Wenn true, verfügt der Controller über ein Touchpad. Überprüfen Sie die ControllerProperties-Eigenschaft des SpatialInteractionSourceState, um die Touchpad-x- und y-Werte (TouchpadX und TouchpadY) abzurufen, und um zu ermitteln, ob der Benutzer das Pad berührt (IsTouchpadTouched) und ob er das Touchpad nach unten drückt (IsTouchpadPressed).
- SimpleHapticsController: Mit der SimpleHapticsController-API für den Controller können Sie die haptischen Funktionen des Controllers überprüfen und haptisches Feedback steuern.
Der Bereich für Touchpad und Thumbstick beträgt -1 bis 1 für beide Achsen (von unten nach oben und von links nach rechts). Der Bereich für den analogen Trigger, auf den mithilfe der SpatialInteractionSourceState::SelectPressedValue-Eigenschaft zugegriffen wird, weist einen Bereich von 0 bis 1 auf. Der Wert 1 korreliert mit dem Wert "IsSelectPressed", der gleich "true" ist. jeder andere Wert korreliert mit IsSelectPressed, der gleich false ist.
Handverfolgung mit Gelenk
Die Windows Mixed Reality-API bietet vollständige Unterstützung für die artikulierte Handnachverfolgung, z. B. auf HoloLens 2. Die artikulierte Handnachverfolgung kann verwendet werden, um direkte Manipulations- und Point-and-Commit-Eingabemodelle in Ihren Anwendungen zu implementieren. Es kann auch verwendet werden, um vollständig benutzerdefinierte Interaktionen zu erstellen.
Handskelett
Die Artikulierte Handnachverfolgung bietet ein 25 Gelenkskelett, das viele verschiedene Arten von Interaktionen ermöglicht. Das Skelett verfügt über fünf Gelenke für den Index/Mitte/Ring/kleine Finger, vier Gelenke für den Daumen und ein Handgelenk. Das Handgelenk dient als Basis der Hierarchie. Die folgende Abbildung veranschaulicht das Layout des Skeletts.
In den meisten Fällen wird jedes Gelenk basierend auf dem Knochen benannt, den es darstellt. Da es an jedem Gelenk zwei Knochen gibt, verwenden wir eine Konvention der Benennung jedes Gelenks basierend auf dem Kinderknochen an dieser Stelle. Der Kinderknochen ist definiert als der Knochen, der weiter vom Handgelenk entfernt ist. Das "Index Proximal"-Gelenk enthält beispielsweise die Anfangsposition des proximalen Indexknochens und die Ausrichtung dieses Knochens. Es enthält nicht die Endposition des Knochens. Wenn Sie dies benötigen, erhalten Sie es vom nächsten Joint in der Hierarchie, dem "Index Intermediate"-Gelenk.
Neben den 25 hierarchischen Gelenken stellt das System ein Handgelenk bereit. Die Handfläche wird in der Regel nicht als Teil der Skelettstruktur betrachtet. Es wird nur als bequeme Möglichkeit bereitgestellt, die Gesamtposition und Ausrichtung der Hand zu erhalten.
Die folgenden Informationen werden für jede Verbindung bereitgestellt:
Name | BESCHREIBUNG |
---|---|
Position | 3D-Position des Gelenks, verfügbar in jedem angeforderten Koordinatensystem. |
Ausrichtung | 3D-Ausrichtung des Knochens, verfügbar in jedem angeforderten Koordinatensystem. |
Radius | Abstand zur Oberfläche der Haut an der Gelenkposition. Nützlich zum Optimieren direkter Interaktionen oder Visualisierungen, die auf der Fingerbreite basieren. |
Genauigkeit | Gibt einen Hinweis darauf, wie sicher sich das System mit den Informationen dieses Gelenks fühlt. |
Sie können über eine Funktion in SpatialInteractionSourceState auf die Handskelettdaten zugreifen. Die Funktion heißt TryGetHandPose und gibt ein Objekt namens HandPose zurück. Wenn die Quelle keine artikulierten Hände unterstützt, gibt diese Funktion NULL zurück. Sobald Sie über einen HandPose verfügen, können Sie aktuelle gemeinsame Daten abrufen, indem Sie TryGetJoint mit dem Namen des Joints aufrufen, an dem Sie interessiert sind. Die Daten werden als JointPose-Struktur zurückgegeben. Der folgende Code ruft die Position der Zeigefingerspitze ab. Die Variable currentState stellt eine instance von SpatialInteractionSourceState dar.
using namespace winrt::Windows::Perception::People;
using namespace winrt::Windows::Foundation::Numerics;
auto handPose = currentState.TryGetHandPose();
if (handPose)
{
JointPose joint;
if (handPose.TryGetJoint(desiredCoordinateSystem, HandJointKind::IndexTip, joint))
{
float3 indexTipPosition = joint.Position;
// Do something with the index tip position
}
}
Handgitter
Die Artikulierte Handverfolgungs-API ermöglicht ein vollständig verformbares Dreieckshandgeflecht. Dieses Gitter kann sich zusammen mit dem Handskelett in Echtzeit verformen und ist nützlich für visualisierungs- und fortgeschrittene Physiktechniken. Um auf das Handgitter zuzugreifen, müssen Sie zunächst ein HandMeshObserver-Objekt erstellen, indem Sie TryCreateHandMeshObserverAsync auf der SpatialInteractionSource aufrufen. Dies muss nur einmal pro Quelle erfolgen, in der Regel beim ersten Anzeigen. Das bedeutet, dass Sie diese Funktion aufrufen, um ein HandMeshObserver-Objekt zu erstellen, wenn eine Hand in den FOV eintritt. Dies ist eine asynchrone Funktion, sodass Sie hier mit ein wenig Parallelität umgehen müssen. Sobald sie verfügbar ist, können Sie das HandMeshObserver-Objekt nach dem Dreiecksindexpuffer fragen, indem Sie GetTriangleIndices aufrufen. Indizes ändern frame-over-frame nicht, sodass Sie diese einmal abrufen und für die Lebensdauer der Quelle zwischenspeichern können. Indizes werden im Uhrzeigersinn bereitgestellt.
Der folgende Code führt ein losgelöstes std::thread aus, um den Gitterbeobachter zu erstellen, und extrahiert den Indexpuffer, sobald der Gitterbeobachter verfügbar ist. Sie beginnt mit einer Variablen namens currentState, bei der es sich um eine instance von SpatialInteractionSourceState handelt, die eine nachverfolgte Hand darstellt.
using namespace Windows::Perception::People;
std::thread createObserverThread([this, currentState]()
{
HandMeshObserver newHandMeshObserver = currentState.Source().TryCreateHandMeshObserverAsync().get();
if (newHandMeshObserver)
{
unsigned indexCount = newHandMeshObserver.TriangleIndexCount();
vector<unsigned short> indices(indexCount);
newHandMeshObserver.GetTriangleIndices(indices);
// Save the indices and handMeshObserver for later use - and use a mutex to synchronize access if needed!
}
});
createObserverThread.detach();
Das Starten eines getrennten Threads ist nur eine Option für die Behandlung asynchroner Aufrufe. Alternativ können Sie die neue co_await-Funktionalität verwenden, die von C++/WinRT unterstützt wird.
Sobald Sie über ein HandMeshObserver-Objekt verfügen, sollten Sie es für die Dauer beibehalten, für die die entsprechende SpatialInteractionSource aktiv ist. Anschließend können Sie jeden Frame nach dem neuesten Vertexpuffer fragen, der die Hand darstellt, indem Sie GetVertexStateForPose aufrufen und eine HandPose-instance übergeben, die die Pose darstellt, für die Sie Scheitelpunkte benötigen. Jeder Scheitelpunkt im Puffer hat eine Position und eine normale Position. Hier sehen Sie ein Beispiel zum Abrufen der aktuellen Scheitelpunkte für ein Handgitter. Wie zuvor stellt die currentState-Variable eine instance von SpatialInteractionSourceState dar.
using namespace winrt::Windows::Perception::People;
auto handPose = currentState.TryGetHandPose();
if (handPose)
{
std::vector<HandMeshVertex> vertices(handMeshObserver.VertexCount());
auto vertexState = handMeshObserver.GetVertexStateForPose(handPose);
vertexState.GetVertices(vertices);
auto meshTransform = vertexState.CoordinateSystem().TryGetTransformTo(desiredCoordinateSystem);
if (meshTransform != nullptr)
{
// Do something with the vertices and mesh transform, along with the indices that you saved earlier
}
}
Im Gegensatz zu Skelettgelenken lässt die Handgitter-API nicht zu, ein Koordinatensystem für die Scheitelpunkte anzugeben. Stattdessen gibt HandMeshVertexState das Koordinatensystem an, in dem die Scheitelpunkte bereitgestellt werden. Sie können dann eine Gittertransformation abrufen, indem Sie TryGetTransformTo aufrufen und das gewünschte Koordinatensystem angeben. Sie müssen diese Gittertransformation verwenden, wenn Sie mit den Scheitelpunkten arbeiten. Dieser Ansatz reduziert den CPU-Aufwand, insbesondere wenn Sie das Gitter nur zu Renderingzwecken verwenden.
Zusammengesetzte Gesten "Blick" und "Commit"
Für Anwendungen, die das Gaze-and-Commit-Eingabemodell verwenden, insbesondere für HoloLens (erste Generation), stellt die Spatial Input-API einen optionalen SpatialGestureRecognizer bereit, mit dem zusammengesetzte Gesten aktiviert werden können, die auf dem Select-Ereignis basieren. Durch das Weiterleiten von Interaktionen vom SpatialInteractionManager an das SpatialGestureRecognizer eines Hologramms können Apps Tap-, Hold-, Manipulations- und Navigationsereignisse gleichmäßig über Hände, Sprache und räumliche Eingabegeräte hinweg erkennen, ohne Dass Druckvorgänge und Freigaben manuell verarbeitet werden müssen.
SpatialGestureRecognizer führt nur die minimale Mehrdeutigkeit zwischen den von Ihnen gewünschten Gesten aus. Wenn Sie beispielsweise einfach tippen anfordern, kann der Benutzer seinen Finger so lange gedrückt halten, wie er möchte, und es wird weiterhin tippen. Wenn Sie sowohl Tippen als auch Halten anfordern, wird die Geste nach etwa einer Sekunde gedrückt gehalten, und ein Tippen tritt nicht mehr auf.
Um SpatialGestureRecognizer zu verwenden, behandeln Sie das InteractionDetected-Ereignis des SpatialInteractionManagers, und greifen Sie nach dem Dort verfügbar gemachten SpatialPointerPose. Verwenden Sie den Kopfblickstrahl des Benutzers aus dieser Pose, um sich mit den Hologrammen und Oberflächengittern in der Umgebung des Benutzers zu überschneiden, um zu bestimmen, mit was der Benutzer interagieren möchte. Leiten Sie dann die SpatialInteraction in den Ereignisargumenten mithilfe der CaptureInteraction-Methode an das SpatialGestureRecognizer des Zielhologramms weiter. Dies beginnt mit der Interpretation dieser Interaktion gemäß dem SpatialGestureSettings-Satz , der für diese Erkennung zur Erstellungszeit festgelegt ist , oder nach TrySetGestureSettings.
Bei HoloLens (first gen) sollten Interaktionen und Gesten ihre Zielrichtung vom Kopfausblick des Benutzers abgeleitet werden, anstatt an der Position der Hand zu rendern oder zu interagieren. Sobald eine Interaktion gestartet wurde, können relative Bewegungen der Hand verwendet werden, um die Geste zu steuern, wie bei der Bearbeitungs- oder Navigationsgeste.