Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Tracciamento delle mani in OpenXR

Introduzione

Nota

Questa pagina si concentra specificamente sulle funzionalità esposte attraverso OpenXR. Alcune delle funzionalità qui presentate si applicano anche a WebXR e possono essere fornite da altre interfacce XR.

Quando si parla di tracciamento delle mani, è importante sapere che ci sono diverse opinioni su dove limitarsi. La conseguenza pratica è che ci sono differenze di implementazione tra i vari runtime OpenXR. Potrebbe capitare che l'hardware scelto non supporti un pezzo del puzzle o che funzioni in modo diverso abbastanza dalle altre piattaforme da richiedere un lavoro in più.

Detto questo, i recenti miglioramenti alla specifica OpenXR stanno colmando queste lacune e, man mano che le piattaforme implementano questi miglioramenti, ci avviciniamo a un futuro in cui avremo una portabilità completa tra le piattaforme o, quantomeno, un modo chiaro per rilevare le capacità di una piattaforma.

Analizzando i primi giorni della realtà virtuale, le principali piattaforme si concentravano sul tracciamento degli input basati su controller. Qui si tracciava un dispositivo fisico dotato di pulsanti per ulteriori input. Dai dati di tracciamento si poteva dedurre la posizione delle mani del giocatore, ma non si avevano altre informazioni. Tradizionalmente, era compito del gioco implementare un meccanismo per visualizzare la mano del giocatore e animare le dita in base agli input provenienti dal controller, che sia tramite la pressione dei pulsanti o tramite sensori di prossimità. Spesso, il posizionamento delle dita dipendeva anche dal contesto, da cosa l'utente stava tenendo in mano e dall'azione che stava eseguendo.

Più recentemente, il tracciamento ottico delle mani è diventato una soluzione popolare, in cui certe telecamere tracciano le mani dell'utente e rendono disponibili dati completi sulla posizione di mani e dita. Molti produttori hanno considerato questa tecnologia completamente separata dal tracciamento del controller e hanno introdotto API indipendenti per accedere ai dati relativi alla posizione e all'orientamento di mani e dita. Nella gestione degli input, spettava allo sviluppatore del gioco implementare un meccanismo per rilevare i gesti.

Questa distinzione esiste anche in OpenXR, dove il tracciamento del controller è gestito principalmente dal sistema di mappa di azioni, mentre il tracciamento ottico delle mani è gestito principalmente dall'estensione API di tracciamento delle mani.

Tuttavia, il mondo non è così bianco o nero e stiamo assistendo a una serie di scenari in cui oltrepassiamo i limiti imposti:

  • Dispositivi che rientrano in entrambe le categorie, come i guanti tracciati e i controller come l'Index, che tracciano anche le dita.

  • Runtime XR che implementano il tracciamento delle mani inferito dai dati del controller come mezzo per risolvere il problema del corretto posizionamento delle dita per più controller.

  • Applicazioni XR che desiderano passare, senza intoppi, tra il tracciamento del controller e quello delle mani, offrendo la stessa esperienza utente a prescindere dall'approccio utilizzato.

OpenXR sta rispondendo a questa esigenza introducendo ulteriori estensioni che ci consentono di interrogare le capacità del runtime/hardware XR o che aggiungono ulteriori funzionalità per superare questa distinzione. Il problema che attualmente rimane è la mancata adozione di queste estensioni, per cui alcune piattaforme non ne segnalano appieno le capacità. Pertanto, potrebbe essere necessario testare le funzionalità disponibili su hardware specifici e adattare adeguatamente il proprio approccio.

Progetto di dimostrazione

Le informazioni presentate in questa pagina sono state utilizzate per creare un progetto di dimostrazione che si trova qui.

L'API di tracciamento delle mani

Come accennato nell'introduzione, l'API di tracciamento delle mani è utilizzata principalmente con il tracciamento ottico e su molte piattaforme funziona solo quando l'utente non sta impugnando un controller. Alcune piattaforme supportano il tracciamento delle mani inferito dal controller, il che significa che si otterranno dati di tracciamento delle mani anche se l'utente sta impugnando un controller. Tra queste sono incluse SteamVR, MetaQuest (attualmente solo nativo, ma è probabile che il supporto per MetaLink arrivi presto) e, si spera, anche altre.

L'implementazione del tracciamento delle mani in Godot è stata standardizzata attorno allo scheletro umanoide di Godot e funziona sia in OpenXR sia in WebXR. Le istruzioni seguenti saranno quindi valide in entrambi gli ambienti.

Per utilizzare l'API di tracciamento delle mani con OpenXR, bisogna prima abilitarla. Lo si può fare nelle impostazioni del progetto:

../../_images/xr_enable_handtracking.webp

Per alcuni dispositivi XR standalone bisognerà inoltre configurare l'estensione di tracciamento delle mani nelle impostazioni di esportazione, ad esempio per Meta Quest:

../../_images/openxr_enable_hand_tracking_meta.webp

Ora devi aggiungere 3 componenti alla tua scena, uno per ogni mano:

  • Un nodo tracciato per posizionare la mano.

  • Una mesh di mano, con una skin adeguatamente applicata e con uno scheletro.

  • Un modificatore dello scheletro che applica i dati di tracciamento delle dita allo scheletro.

../../_images/openxr_hand_tracking_nodes.webp

Nodo di tracciamento delle mani

Il sistema di tracciamento delle mani utilizza sensori separati per monitorare la posizione delle mani del giocatore dentro il nostro spazio di tracciamento.

Queste informazioni sono state separate per i seguenti casi d'uso:

  • Il tracciamento avviene nello spazio locale del nodo XROrigin3D. Questo nodo deve essere un figlio del nodo XROrigin3D per essere posizionato correttamente.

  • This node can be used as an IK target when an upper body mesh with arms is used instead of separate hand meshes.

  • Il posizionamento effettivo delle mani potrebbe essere vagamente associato al tracciamento in scenari come interfacce per la creazione di avatar, specchi fittizi o situazioni simili, portando a localizzare la mesh della mano e il tracciamento delle dita da qualche altra parte.

We'll concentrate on the first use case only.

For this you need to add an XRNode3D node to your XROrigin3D node.

  • On this node the tracker should be set to /user/hand_tracker/left or /user/hand_tracker/right for the left or right hand respectively.

  • The pose should remain set to default, no other option will work here.

  • The checkbox Show When Tracked will automatically hide this node if no tracking data is available, or make this node visible if tracking data is available.

Mesh di mano con rig

In order to display our hand we need a hand mesh that is properly rigged and skinned. For this Godot uses the hand bone structure as defined for the Godot Humanoid but optionally supporting an extra tip bone for each finger.

La demo di tracciamento delle mani di OpenXR contiene file glTF di esempio di mani con rigging correttamente applicato.

We will be using those here and add them as a child to our XRNode3D node. We also need to enable editable children to gain access to our Skeleton3D node.

Il modificatore di scheletro di mani

Finally we need to add an XRHandModifier3D node as a child to our Skeleton3D node. This node will obtain the finger tracking data from OpenXR and apply it the hand model.

You need to set the Hand Tracker property to either /user/hand_tracker/left or /user/hand_tracker/right depending on whether we are apply the tracking data of respectively the left or right hand.

È anche possibile impostare la modalità Bone Update su questo nodo.

  • Full applies the hand tracking data fully. This does mean that the skeleton positioning will potentially reflect the size of the actual hand of the user. This can lead to scrunching effect if meshes aren't weighted properly to account for this. Make sure you test your game with players of all sizes when optical hand tracking is used!

  • Rotation Only will only apply rotation to the bones of the hands and keep the bone length as is. In this mode the size of the hand mesh doesn't change.

With this added, when we run the project we should see the hand correctly displayed if hand tracking is supported.

La sorgente dei dati di tracciamento delle mani

This is an OpenXR extension that provides information about the source of the hand tracking data. At this moment only a few runtimes implement it but if it is available, Godot will activate it.

If this extension is not supported and thus unknown is returned, you can make the following assumptions:

  • If you are using SteamVR (including Steam link), only controller based hand tracking is supported.

  • For any other runtime, if hand tracking is supported, only optical hand tracking is supported (Note, Meta Link currently fall into this category).

  • In tutti gli altri casi, il tracciamento delle mani non è supportato.

È possibile accedere a queste informazioni tramite codice:

var hand_tracker : XRHandTracker = XRServer.get_tracker('/user/hand_tracker/left')
if hand_tracker:
    if hand_tracker.has_tracking_data:
        if hand_tracker.hand_tracking_source == XRHandTracker.HAND_TRACKING_SOURCE_UNKNOWN:
            print("Hand tracking source unknown")
        elif hand_tracker.hand_tracking_source == XRHandTracker.HAND_TRACKING_SOURCE_UNOBSTRUCTED:
            print("Hand tracking source is optical hand tracking")
        elif hand_tracker.hand_tracking_source == XRHandTracker.HAND_TRACKING_SOURCE_CONTROLLER:
            print("Hand tracking data is inferred from controller data")
        else:
            print("Unknown hand tracking source ", hand_tracker.hand_tracking_source)
    else:
        print("Hand is currently not being tracked")
else:
    print("No hand tracker registered")

Questo esempio registra lo stato della mano sinistra.

If in this example no hand tracker is returned by get_tracker, this means the hand tracking API is not supported on the XR runtime at all.

If there is a tracker but has_tracking_data is false, the user's hand is currently not being tracked. This is likely caused by one of the following reasons:

  • The player's hand is not visible by any of the tracking cameras on the headset

  • The player is currently using a controller and the headset only supports optical hand tracking

  • The controller is turned off and only controller hand tracking is supported.

Gestione degli input dell'utente

Reacting to actions performed by the user is handled through La mappa di azioni XR if controllers are used. In the action map you can map various inputs like the trigger or joystick on the controller to an action. This can then drive logic in your game.

When hand tracking is used we originally had no such inputs, inputs are driven by gestures made by the user such as making a fist to grab or pinching the thumb and index finger together to select something. It was up to the game developer to implement this.

Recognizing that there is an increasing demand for applications that can switch seamlessly between controller and hand tracking and the need some form of basic input capability, a number of extensions were added to the specification that provide some basic gesture recognition and can be used with the action map.

Il profilo di interazione della mano

The hand interaction profile extension is a new core extension which supports pinch, grasp, and poke gestures and related poses. There is still limited support for this extension but it should become available in more runtimes in the near future.

../../_images/openxr_hand_interaction_profile.webp

The pinch gesture is triggered by pinching your thumb and index finger together. This is often used as a select gesture for menu systems, similar to using your controller to point at an object and press the trigger to select and is thus often mapped as such.

  • The pinch pose is a pose positioned in the middle between the tip of the thumb and the tip of the index finger and oriented such that a ray cast can be used to identify a target.

  • The pinch float input is a value between 0.0 (the tip of the thumb and index finger are apart) and 1.0 (the tip of the thumb and index finger are touching).

  • The pinch ready input is true when the tips of the fingers are (close to) touching.

The grasp gesture is triggered by making a fist and is often used to pick items up, similar to engaging the squeeze input on controllers.

  • The grasp float input is a value between 0.0 (open hand) and 1.0 (fist).

  • The grasp ready input is true when the user made a fist.

The poke gesture is triggered by extending your index finger, this one is a bit of an exception as the pose at the tip of your index finger is often used to poke an interactable object. The poke pose is a pose positioned on the tip of the index finger.

Finally the aim activate (ready) input is defined as an input that is 1.0/true when the index finger is extended and pointing at a target that can be activated. How runtimes interpret this, is not clear.

With this setup the normal left_hand and right_hand trackers are used and you can thus seamlessly switch between controller and hand tracking input.

Nota

You need to enable the hand interaction profile extension in the OpenXR project settings.

Microsoft hand interaction profile

The Microsoft hand interaction profile extension was introduced by Microsoft and loosely mimics the simple controller profile. Meta has also added support for this extension but only on their native OpenXR client, it is currently not available over Meta Link.

../../_images/openxr_msft_hand_interaction_profile.webp

Pinch support is exposed through the select input, the value of which is 0.0 when the tip of the thumb and index finger are apart and 1.0 when they are together.

Note that in this profile the aim pose is redefined as a pose between thumb and index finger, oriented so a ray cast can be used to identify a target.

Grasp support is exposed through the squeeze input, the value of which is 0.0 when the hand is open, and 1.0 when a fist is made.

With this setup the normal left_hand and right_hand trackers are used and you can thus seamlessly switch between controller and hand tracking input.

Profilo di interazione della mano HTC

L'estensione di HTC per il profilo di interazione delle mani è stata introdotta da HTC ed è definita in modo simile all'estensione di Microsoft. È supportata da HTC solo per i visori Focus 3 ed Elite XR.

../../_images/openxr_htc_hand_interaction_profile.webp

Consultare il profilo di interazione delle mani di Microsoft per il supporto dei gesti.

La differenza sostanziale è che questa estensione introduce due nuovi tracker, /user/hand_htc/left e /user/hand_htc/right. Significa che è necessario implementare una logica in più per passare dai tracker predefiniti a quelli specifici di HTC quando l'utente appoggia, o riprende in mano, il controller.

Profilo di controller semplice

Il profilo di controller semplice è un profilo standard, definito come profilo di riserva quando si utilizza un controller per il quale non esiste un profilo specifico.

Ci sono un numero di runtime OpenXR che emulano i controller tramite il profilo di controller semplice quando si utilizza il tracciamento delle mani.

Purtroppo non esiste un metodo affidabile per determinare se si utilizza un controller sconosciuto o se il tracciamento delle mani sta emulando un controller tramite questo profilo.

../../_images/openxr_simple_controller_hand.webp

Gli ambienti di runtime XR sono liberi di definire come funziona il profilo di controller semplice, quindi non vi è alcuna certezza su come questo profilo sia mappato ai gesti.

La mappatura più comune sembra essere che select click sia true quando la punta del pollice e dell'indice si toccano mentre il palmo dell'utente è rivolto lontano da sé, e che menu click sia true quando la punta del pollice e dell'indice si toccano mentre il palmo dell'utente è rivolto verso di sé.

With this setup the normal left_hand and right_hand trackers are used and you can thus seamlessly switch between controller and hand tracking input.

Nota

Poiché alcuni di questi profili di interazione si sovrappongono, è importante sapere che è possibile aggiungere ciascun profilo alla mappa di azioni e il runtime XR sceglierà il profilo più adatto.

Ad esempio, un Meta Quest supporta sia il profilo di interazione delle mani di Microsoft, sia il profilo di controller semplice. Se entrambi sono specificati, il profilo di interazione delle mani di Microsoft avrà la precedenza e sarà utilizzato.

Ci si aspetta che, una volta che Meta supporterà l'estensione base del profilo di interazione delle mani, tale profilo avrà la precedenza sia sul profilo Microsoft sia sul profilo di controller semplice.

Input basato sui gesti

Se la piattaforma non supporta alcun profilo di interazione quando si utilizza il tracciamento delle mani, o se stai sviluppando un'applicazione che richiede un supporto per gesti più complessi, sarà necessario creare un proprio sistema di riconoscimento dei gesti.

È possibile ottenere i dati completi di tracciamento delle mani tramite la risorsa XRHandTracker per ciascuna mano. È possibile ottenere il tracker della mano chiamando XRServer.get_tracker e utilizzando /user/hand_tracker/left o /user/hand_tracker/left come tracker. Questa risorsa fornisce l'accesso a tutte le informazioni sulle articolazioni per la mano specificata.

Descrivere in dettaglio un algoritmo completo per il riconoscimento dei gesti va oltre lo scopo di questo manuale, tuttavia esistono diversi progetti della comunità a cui puoi dare un'occhiata: