Skip to Content
This documentation is provided with the HEAT environment and describes this HEAT instance.

Data produced by the Varjo gaze module

This module parses and republishes whatever SimulationFrame bytes the bundled native bridge produces - it does not rebuild the frame or generate its own entity id or name.

Entity

Every frame carries a single fixed entity: id 0x56415246, name Varjo_Data.

Gaze and head pose - every tick, independent of video

The bridge emits head pose and gaze/pupillometry as their own frame every tick, decoupled from whether video capture is running. If the Varjo runtime reports no valid gaze for a tick - the headset removed, gaze tracking not calibrated, and so on - no frame is emitted for that tick at all, rather than one with zeroed fields. Check GetGazeTrackingStatus behavior in Troubleshooting before assuming a gap is a bug.

Populated on GazeComponent: IPD, gaze_origin, left_gaze_origin, right_gaze_origin, gaze_direction, left_gaze_direction, right_gaze_direction, left_eye_occluded, right_eye_occluded, blink. Not populated: has_glasses, gaze_point, gaze_screen_point, or any *_quality field.

The direction fields’ Z axis is sign-flipped from Varjo’s own coordinate convention before publishing - a deliberate axis conversion in the bridge, applied identically to the combined and both per-eye direction vectors.

left_eye_occluded/right_eye_occluded come directly from Varjo’s own per-eye gaze validity status, not from an eyelid-openness measurement; blink is then derived as left_eye_occluded OR right_eye_occluded. This is the reverse of how some other eye-tracking modules in this catalogue derive the two - here, occlusion is the primary signal and blink is derived from it, not the other way round.

Populated on PupillometryDataComponent: left_eyelid_openness, right_eyelid_openness, left_eye_pupil_diameter, right_eye_pupil_diameter. Not populated: the combined eyelid_openness or pupil_diameter fields (this bridge does not average left and right into a combined value), any *_quality field, or other_pupil_data.

Video - only when enabled and licensed

When EnableVideoCapture is on, each eye’s encoder emits its own independent frame as its H264 access unit completes - the two eyes are not combined into one frame. Each video frame also carries the same head pose for that tick on SpatialComponent.pose, and may additionally carry its own copy of that tick’s gaze/pupillometry snapshot. If a video frame does carry gaze data, treat it as the same sample already seen on that tick’s dedicated gaze frame, not a second, independent reading - do not double-count or average the two.

Carried on StreamComponent, as one VideoSource per frame, named eye.left or eye.right:

ParameterValue
CodecH264, Annex-B access units, one independent stream per eye
Bitrate~8 Mbps per eye, constant bitrate
GOP size90 frames (~1 second at native cadence), no B-frames

This module does not decode H264 or inspect its content; a consumer needs its own H264 decoder, and must feed each eye’s access units to it in the order received - the encoding depends on frame order, so skipping one corrupts everything after it until the next keyframe.

Backpressure

The bridge holds up to about a second of frames (gaze and video together) in a bounded queue. If this module does not drain it fast enough, the bridge drops the oldest queued entry and forces a fresh keyframe on the affected eye rather than let the queue grow further - a visible discontinuity in that eye’s video, not a delay. See Configure for the setting that controls how often this module drains the queue.

Opens your browser's print dialog. Choose "Save as PDF" as the destination.