XRHandInput Class
The XRHandInput class emulates hand input within WebXR environments. It supports detailed hand pose emulation and gesture recognition, allowing for immersive interactions within the virtual space.
Properties
poseId
Specifies the current hand pose being emulated, such as default, pinch, fist, or other custom poses defined in the configuration.
- Type:
string - Allows dynamic update to the hand pose through a setter. Changing the
poseIdtriggers an update in the hand's pose based on the configuration associated with the new pose ID, and clears any finger blends. It also ends a pose change in progress (beginPoseTransition): the hand snaps to the new pose.
poseIds
Every pose id this hand can take: the built-in library (BUILTIN_HAND_POSE_IDS) for the default config, or the keys of a custom config's poses.
- Type:
string[] - Readonly
fingerPoses
Fingers currently taken from other poses on top of poseId, keyed by finger (thumb, index, middle, ring, pinky). Each read returns a copy; change blends with setFingerPose and clearFingerPoses.
- Type:
Partial<Record<XRHandFinger, { poseId: string; weight: number }>> - Readonly
poseTransitionProgress
How far a pose change begun with beginPoseTransition has got, from 0 to 1, or null when no change is in progress. Setting it to 1 or more (or null) ends the change.
- Type:
number | null
poseTransitionFrom
The pose a change in progress fades from (the pose set before it), or null when no change is in progress.
- Type:
string | null - Readonly
thumbMotion
A thumb movement shown on top of the pose, or null: the thumb is weight of the way from its place in from to its place in to (two hand poses), relative to the displayed palm. Nothing else moves, and anchors (grasp included) keep the displayed pose, so a pinned hand stays where it is. Remote control's microgestures set it every frame and clear it when they end.
- Type:
ThumbMotion | null({ from: HandPose; to: HandPose; weight: number })
pin
Where remote control holds the hand (see setPin), or null.
- Type:
HandPin | null({ anchor, target, wristRotation?, graspPinch? }, GlobalSpace) - Readonly
pinchValue
Indicates the current level of the pinch gesture being emulated, with a range from 0 (no pinch) to 1 (full pinch). The pinch closes the thumb and index onto each other, relative to the palm; the wrist, the grip and the other fingers keep the pose. The hand selects when the pinch reaches 0.9 (gamepad button 0 pressed, selectstart) and lets go when it falls to 0.7 or below (select, then selectend); see pinchThresholds in XRHandInputConfig.
- Type:
number - Readonly
The hand's gamepad has Quest Browser's layout: mapping xr-standard, 10 buttons, no axes. Button 0 is the pinch (the only button that fires events), buttons 1 to 3 are empty, 4 is the menu gesture and 5 to 9 are the microgestures: swipe left, swipe right, swipe forward, swipe backward and thumb tap (see updateGestureButton).
connected
Reflects the connection status of the hand input, showing whether it's actively recognized and tracked within the XR session.
- Type:
boolean
position
The current 3D position of the hand input, allowing for movement tracking within the virtual environment.
- Type:
Vector3 - Readonly
quaternion
The current orientation of the hand input, represented as a quaternion for accurate gesture and direction tracking.
- Type:
Quaternion - Readonly
inputSource
Provides access to the XRInputSource associated with this hand input, integrating it with the XR input system.
- Type:
XRInputSource - Readonly
Methods
updateHandPose
Executes the pose update logic, adjusting the virtual hand's current pose based on the active poseId, finger blends, any pose change in progress and pinchValue, then re-applies the pin (setPin). Runs every frame.
updateHandPose(): voidbeginPoseTransition
Starts a timed change to poseId (with optional finger blends): the hand fades from what it shows now, before pinch and mid-change included, as poseTransitionProgress goes from 0 to 1. poseId and fingerPoses report the new pose right away. Joints blend relative to their parents along the shortest arc, as finger blends do. Returns false for an unknown pose. Remote control's set_hand_pose with a duration drives this.
beginPoseTransition(poseId: string, fingers?: Partial<Record<XRHandFinger, FingerPoseBlend>>): booleansetPin
Holds a point of the hand at a position from now on: after every shape update (pose, finger blends, pose change, pinch), the target ray moves so that anchor sits on target. With wristRotation, the target ray also turns so the wrist keeps that rotation. Applies right away; pass null to let go. Remote control's anchor parameter sets pins, and drops them when it lets go of the device.
setPin(pin: HandPin | null): voidanchor: HandAnchor -target-ray,wrist,grip,grasp(where the thumb and index tips meet in a full pinch),index-tip,thumb-tip, or any WebXR joint name.target: vec3 - GlobalSpace position.wristRotation: quat - Optional GlobalSpace wrist rotation.graspPinch: number - Forgrasp: the pinch value the point is taken at (default1).
anchorOffset
An anchor's position in the target-ray frame for the hand as shown now. grasp is fixed for the displayed pose (it does not move with the pinch).
anchorOffset(anchor: HandAnchor, out?: vec3, graspPinch?: number): vec3wristRotation
The wrist's rotation in GlobalSpace for the hand as shown now.
wristRotation(out?: quat): quathandAxes
The hand's directions in the target-ray frame, from the displayed wrist: fingers (wrist −Z), palm (wrist −Y, the way the palm faces) and thumb (toward the thumb side, on either hand).
handAxes(): { fingers: vec3; palm: vec3; thumb: vec3 }setFingerPose
Takes one finger from another pose while the rest of the hand keeps poseId. Each joint blends relative to its parent joint and the finger stays attached to the base pose's palm. At a partial weight, each bone's length lies between its lengths in the two poses. The 21 generated poses are built on the captured default skeleton, so between them each finger's bones keep exactly the same lengths; the captured pinch and point come from other captures and differ slightly.
The blended finger is computed when poseId, setFingerPose or clearFingerPoses changes, not every frame.
setFingerPose(finger: XRHandFinger, poseId: string, weight?: number): voidfinger: XRHandFinger -thumb,index,middle,ringorpinky.poseId: string - The pose to take the finger from.weight: number -0keeps the base pose's finger,1(default) uses the finger fromposeId.
clearFingerPoses
Clears the blend for one finger, or for every finger if called without arguments.
clearFingerPoses(finger?: XRHandFinger): voidupdateGestureButton
Writes one of the gamepad's gesture buttons for the next frame: 1 pressed, 0 released. These buttons fire no session events; apps read them from the gamepad. Quest holds a recognized microgesture down for about 35 ms; remote control's microgesture does the same and moves the thumb too.
updateGestureButton(id: HandGestureButton, value: 0 | 1): voidid: HandGestureButton -menu(button 4),swipe-left,swipe-right,swipe-forward,swipe-backwardortap(buttons 5 to 9).
updatePinchValue
Modifies the emulation level of the pinch gesture. This method allows for the simulation of pinch gestures to various degrees, enhancing interaction realism within the virtual environment.
updatePinchValue(value: number): voidvalue: number - The new pinch intensity, where0indicates no pinch and1indicates a fully engaged pinch gesture.