PsychVRHMD

>Psychtoolbox>PsychHardware>PsychVRToolbox

PsychVRHMD() - High level driver for VR HMD devices.

This driver bundles all the common high level functionality
of different Virtual Reality Head mounted displays into one
function.

It dispatches generic calls into appropriate device specific
drivers as needed.

Usage:

hmd = PsychVRHMD(‘AutoSetupHMD’ [, basicTask][, basicRequirements][, basicQuality][, vendor][, deviceIndex]);

  • Automatically detect the first connected HMD, set it up with reasonable
    default parameters, and return a device handle ‘hmd’ to it. If the system
    does not support any HMDs, not even emulated ones, just does nothing and
    returns an empty handle, ie., hmd = [], so caller can cope with that.

Optional parameters: ‘basicTask’ what kind of task should be implemented.
The default is ‘Tracked3DVR’, which means to setup for stereoscopic 3D
rendering, driven by head motion tracking, for a fully immersive experience
in some kind of 3D virtual world. This is the default if omitted. ‘3DVR’ sets
up for stereoscopic 3D rendering that is not driven by head motion tracking.

The task ‘Stereoscopic’ sets up for display of stereoscopic stimuli, but without
head tracking. ‘Monoscopic’ sets up for display of monocular stimuli, ie.
the HMD is just used as a special kind of standard display monitor.

In monoscopic or stereoscopic mode, you can change the imaging parameters, ie.,
apparent size and location of the 2D views used with the following command to
optimize visual display:

PsychVRHMD(‘View2DParameters’, hmd, eye [, position][, size][, orientation]);
The command is fully supported under the OpenXR driver, but does nothing
and only returns NaN results on other drivers like the old Oculus,
Oculus-1 and OpenHMD drivers.

‘basicRequirements’ defines basic requirements for the task. Currently
defined are the following strings which can be combined into a single
‘basicRequirements’ string:

‘DebugDisplay’ = Show the output which is displayed on the HMD inside the
Psychtoolbox onscreen window as well. This will have a negative impact on
performance, latency and timing of the HMD visual presentation, so should only
be used for debugging, as it may cause a seriously degraded VR experience.
By default, no such debug output is produced and the Psychtoolbox onscreen
window is not actually displayed on the desktop. This option is silently ignored
on the old classic Oculus driver at the moment.

‘Float16Display’ = Request rendering, compositing and display in 16 bpc float
format on some HMD’s and drivers. This will ask Psychtoolbox to render and
post-process stimuli in 16 bpc linear floating point format, and allocate 16 bpc
half-float textures as final renderbuffers to be sent to the VR compositor.
If the VR compositor takes advantage of the high source image precision is at
the discretion of the compositor and HMD. By default, if this request is omitted,
processing and display in sRGB format is requested from Psychtoolbox and the compositor
on some drivers, e.g., for the Oculus 1.11+ runtime and Rift CV1, ie., a roughly
gamma 2.2 8 bpc format is used, which is optimized for the gamma response curve of
at least the Oculus Rift CV1 display. On other HMDs or drivers, this option may do
nothing and get silently ignored.

‘ForceSize=widthxheight’ = Enforce a specific fixed size of the stimulus
image buffer in pixels, overriding the recommmended value by the runtime,
e.g., ‘ForceSize=2200x1200’ for a 2200 pixels wide and 1200 pixels high
image buffer. By default the driver will choose values that provide good
quality for the given VR/AR/MR/XR display device, which can be scaled up
or down with the optional ‘pixelsPerDisplay’ parameter for a different
quality vs. performance tradeoff in the function PsychVRHMD(‘SetupRenderingParameters’);
The specified values are clamped against the maximum values supported by
the given hardware + driver combination.

‘ForbidMultiThreading’ = Forbid any use of multi-threading for visual
presentation by the driver for any means or purposes! This is meant to
get your setup going in case of severe bugs in proprietary OpenXR
runtimes that can cause instability, hangs, crashes or other malfunctions
when multi-threading is used. Or if one wants to squeeze out every last
bit of performance, no matter the consequences (“Fast and furious mode”).
On many proprietary OpenXR runtimes, this will prevent any reliable,
trustworthy, robust or accurate presentation timing or timestamping, and
may cause severe visual glitches under some modes of operation. See the
following keywords below for descriptions of various more nuanced
approaches to multi-threading vs. single-threading to choose fine-tuned
tradeoffs between performance, stability and correctness for your
specific experimental needs.

‘Use2DViewsWhen3DStopped’ = Ask the driver to switch to use of the same 2D views
and geometry during the ‘3DVR’ or ‘Tracked3DVR’ basicTask as would be used
for pure 2D display in basicTask ‘Stereoscopic’ whenever the user script
signals it does not execute a tight tracking and animation loop, ie.
whenever the script calls PsychVRHMD(‘Stop’, hmd). Switch back to regular
3D projected geometry and views after a consecutive PsychVRHMD(‘Start’, hmd).
This is useful if have phases in your experiment session when you want to
display non-tracked content, e.g., instructions or feedback to the
subject between trials, fixation crosses, etc., or pause script execution
for more than a few milliseconds, but still want the visual display to
stay stable. If this keyword is omitted, depending on the specific OpenXR
runtime in use, the driver will stabilize the regular 3D projected
display by use of multi-threaded operation when calling PsychVRHMD(‘Stop’, hmd),
and resume single-threaded operation after PsychVRHMD(‘Start’, hmd). This
higher overhead mode of operation via multi-threading will possibly have
degraded performance, and not only between the ‘Stop’ and ‘Start’ calls,
but throughout the whole session! This is why it can be advisable to
evaulate if use of the ‘Use2DViewsWhen3DStopped’ keyword is a better
solution for your specific experiment paradigm. The switching between 3D
projected view and standard 2D stereoscopic view will change the image
though, which may disorient the subject for a moment while the subjects
eyes need to adapt their accomodation, vergence and focus point. You can
change the imaging parameters, ie., apparent size and location of the 2D
views used in this mode with the following command to minimize visual
disorientation:

PsychVRHMD(‘View2DParameters’, hmd, eye [, position][, size][, orientation]);

For such 2D views you can also specify the distance of the virtual
viewscreen in meters in front of the eyes of the subject. By default the
distance is 1 meter and the size and position is set up to fill out the
field of view in a meaningful way, essentially covering the whole
available field of view. By overriding the distance to a smaller or
bigger distance than 1 meter, you can “zoom in” to the image, or make
sure that also the corners and edges of the image are visible. E.g., the
following keyword would place the virtual screen at 2.1 meters distance:

‘2DViewDistMeters=2.1’

‘DontCareAboutVisualGlitchesWhenStopped’ = Tell the driver that you don’t
care about potential significant visual presentation glitches happening if
your script does not run a continuous animation with high framerate, e.g.,
after calling PsychVRHMD(‘Stop’, hmd), pausing, etc. This makes sense if
you don’t care, or if your script does not ever pause or slow down during
a session or at least an ongoing trial. This will avoid multi-threading
for glitch prevention in such cases, possibly allowing to side-step
certain bugs in proprietary OpenXR runtimes, or to squeeze out higher
steady-state performance.

‘TimingPrecisionIsCritical’ = Signal that visual presentation timing and
timestamping of visual stimuli should be given highest importance -
essentially above all else. You still need to specify the following
keywords relating to the specifics of your timing/timestamping needs, but
this specific requirement is a signal to make all tradeoffs, including
choice of drivers to use, almost solely based on their timing properties.

‘NoTimingSupport’ = Signal no need at all for high precision and reliability
timing for presentation. If you don’t need any timing precision or
reliability in your script, specifying this keyword may allow the driver
to optimize for higher performance. See ‘TimingSupport’ explanation right
below:

‘TimingSupport’ = Use high precision and reliability timing for presentation.
Please note that generally only the special Linux VR/AR/MR/XR drivers are
currently capable of robust, reliable, trustworthy and accurate timing,
and sometimes even they need special configuration or have some caveats,
specifically:

  • The original PsychOculusVR driver has perfect timing, but only works on
    Linux/X11 with a separate X-Screen for the HMD, and only works with the
    original Oculus Rift DK1 and DK2 VR HMDs.

  • The PsychOpenHMDVR driver has perfect timing, but only works on
    Linux/X11 with a separate X-Screen for the HMD, and only works with the
    subset of VR HMDs supported by OpenHMD, and often various caveats
    apply for those HMDs, like imperfect optical undistortion, or lack of
    full 6 DoF head tracking - Often only 3 DoF orientation tracking is
    supported.

  • The PsychOculusVR1 driver for the Oculus VR 1.x runtime on MS-Windows
    has essentially unreliable/not trustworthy timing and timestamping.

  • The timing properties of the PsychOpenXR driver are highly dependent on
    the OpenXR runtime at use. Citing from the ‘help PsychOpenXR’:

    The current OpenXR specification, as of OpenXR version v1.0.26 from January 2023,
    does not provide any means of reliable, trustworthy, accurate timestamping of
    presentation, and all so far tested proprietary OpenXR runtime implementations
    have severely broken and defective timing support. Only the open-source
    Monado OpenXR runtime on Linux provides a reliable and accurate timing
    implementation. Therefore this driver has to use a workaround on non-Monado
    OpenXR runtimes to achieve at least ok’ish timing if you require it, and
    that workaround involves multi-threaded operation. This multi-threading
    in turn can severely degrade performance, possibly reducing achievable
    presentation framerates to (less than) half of the maximum video refresh
    rate of your HMD! For this reason you should only request ‘TimingSupport’
    on non-Monado if you really need it and be willing to pay the performance
    price.

    If you omit this keyword, the driver will try to guess if you need
    precise presentation timing for your session or not. As long as you only
    call Screen(‘Flip’, window) or Screen(‘Flip’, window, [], …), ie. don’t
    specify a requested stimulus onset time, the driver assumes you don’t
    need precise timing, just presenting as soon as possible after a
    Screen(‘Flip’), and also that you don’t care about accurate or trustworthy
    or correct presentation timestamps to be returned by Screen(‘Flip’). Once
    you specify a target onset time tWhen, ie. via calling ‘Flip’ as
    Screen(‘Flip’, window, tWhen [, …]), the driver assumes from then on
    and for the rest of the session that you want reasonably accurate
    presentation timing. It will then switch to multi-threaded operation with
    better timing, but potentially drastically reduced performance.

‘TimestampingSupport’ = Use high precision and reliability timestamping for presentation.
‘NoTimestampingSupport’ = Do not need high precision and reliability timestamping for presentation.
Those keywords let you specify if you definitely need or don’t need
trustworthy, reliable, robust, precise presentation timestamps, ie. the
‘timestamp’ return values of timestamp = Screen(‘Flip’) should be high
quality, or if you don’t care. If you omit both keywords, the driver will
try to guess what you wanted. On most current OpenXR runtimes, use of
timestamping will imply multi-threaded operation with the performance
impacts and problems mentioned above in the section about ‘TimingSupport’,
that is why it is advisable to explicitely state your needs, to allow the
driver to optimize for the best precision/reliability/performance
tradeoff on all the runtimes where such a tradeoff is required.
Notable exceptions are the Linux PsychOculus and PsychOpenHMDVR
drivers when used on separate X-Screens for their HMDs, and some
configurations of the Monado OpenXR runtime on Linux, where
timestamps are trustworthy without performance tradeoffs or other
known problems. The PsychOculusVR1 driver on MS-Windows always
provides untrustworthy timestamps, no matter what.

‘TimeWarp’ = Enable per eye image 2D timewarping via prediction of eye
poses at scanout time. This mostly only makes sense for head-tracked 3D
rendering. Depending on ‘basicQuality’ a more cheap or more expensive
procedure is used. On the v1.11 Oculus runtime and Rift CV1, ‘TimeWarp’
is always active, so this option is redundant.

‘LowPersistence’ = Try to keep exposure time of visual images on the retina
low if possible, ie., try to approximate a pulse-type display instead of a
hold-type display if possible. On the Oculus Rift DK2 with the original Oculus
runtime on Linux, it will enable low persistence scanning of the OLED
display panel, to light up each pixel only a fraction of a video refresh
cycle duration. On any other HMD hardware or runtime this setting does
not have any effect and is thereby pretty much redundant.

‘PerEyeFOV’ = Request use of per eye individual and asymmetric fields of view, even
when the ‘basicTask’ was selected to be ‘Monoscopic’ or ‘Stereoscopic’. This allows
for wider field of view in these tasks, but requires the usercode to adapt to these
different and asymmetric fields of view for each eye, e.g., by selecting proper 3D
projection matrices for each eye. If a ‘basicTask’ of ‘3DVR’ for non-tracked 3D, or
(the default) ‘Tracked3DVR’ for head tracking driven 3D is selected, then that implies
per-eye individual and asymmetric fields of view, iow. ‘PerEyeFOV’ is implied. For pure
‘basicTask’ of ‘Monoscopic’ or ‘Stereoscopic’ for Screen() 2D drawing, the system uses
identical and symmetric fields of view for both eyes by default, so ‘PerEyeFOV’ would
be needed to override this choice. COMPATIBILITy NOTE: Psychtoolbox-3 releases before
June 2017 always used identical and symmetric fields of view for both eyes, which was
a bug. However the error made was very small, due to the imaging properties of the
Oculus Rift DK2, essentially imperceptible to the unknowing observer with the naked
eye. Releases starting June 2017 now use separate fields of view in 3D rendering
modes, and optionally for 2D mono/stereo modes with this ‘PerEyeFOV’ opt-in parameter,
so stimulus display may change slightly for the same HMD hardware and user-code,
compared to older Psychtoolbox-3 releases. This change was crucial to accomodate the
rather different imaging properties of the Oculus Rift CV1 and possible other future
HMD’s. Note: This requirement is currently ignored with the standard OpenXR backend,
as the OpenXR runtimes decide by themselves what is best here.

‘FastResponse’ = Try to switch images with minimal delay and fast
pixel switching time. This will enable OLED panel overdrive processing
on the Oculus Rift DK1 and DK2. OLED panel overdrive processing is a
relatively expensive post processing step. On any other VR device and
runtime other than Oculus Rift DK1/DK2 this option currently has no
effect and is therefore redundant.

‘Eyetracking’ = Request eye gaze tracking via a supported HMD builtin eye tracker.
This keyword asks the driver to enable eye gaze tracking. A given combo
of VR/AR/MR device (and its builtin eye tracker), operating system, OpenXR
runtime and additional optionally installed eye tracking software, may
support multiple different gaze tracking api’s and runtimes. By default,
the driver will try to use the most capable gaze tracking api, ie. the
one which provides the most detailed and exhaustive information about the
users gaze, at the highest sampling rate, with the most flexibility. It
will fall back to less capable or efficient tracking api’s if more
capable ones are not supported or available. For this reason, the amount
of information can differ widely between the most capable api’s and the
most basic api’s. User scripts which strive to be usable on different
operating systems, software setups or eyetracking hardware and HMDs must
therefore be written in a defensive and adaptive way to be able to work
with only the minimal subset of information guaranteed to be available on
all implementations. The info struct returned by info = PsychVRHMD(‘GetInfo’);
contains info about basic gaze tracking capabilities as a bitmask in
info.eyeTrackingSupported: A value of +1 means at least one gaze vector
is reported. A value of +2 means reporting of binocular eye tracking data
is supported. A value of +1024 means that HTC’s proprietary SRAnipal
eyetracking is used for more extensive gaze data reporting.

If eye tracking is requested via the keyword and supported, then the user
script can request return of the most recent eye gaze tracking sample
data by calling the state = PsychVRHMD(‘PrepareRender’, …, reqmask, …)
function with reqmask flag +4. This will cause the returned ‘state’ struct
to contain additional fields with information about the most recent gaze.
See help text for the ‘PrepareRender’ function for more detailed info.

The current driver supports the following gazetracking implementations:

  • With HTC VR HMDs with eyetracking support, under Microsoft Windows, in
    combination with the optional HTC SRAnipal runtime DLL’s installed, and
    using Matlab, an optional SRAnipal mex driver can be used to provide both
    binocular per-eye gaze tracking data, separate for the subjects left and
    right eye, and a virtual 3rd “cyclops eye” which is synthesized info from
    both hardware eye trackers, sometimes of higher quality due to sensor
    fusion of the two gaze tracker data streams. For each of both eyes, in
    addition to eye gaze position and direction, estimated pupil size in
    millimeters and a measure of eye openess is reported, e.g., for eye
    blink detection or estimation of gaze data reliability. Reported times
    are hardware timestamps of when a gaze sample was measured. On the tested
    “HTC Vive Pro Eye” HMD sampling rates of up to 120 Hz were possible.

  • On other device + operating system + OpenXR runtime combos with OpenXR
    gazetracking support, information from the XR_EXT_eye_gaze_interaction
    gaze tracking extension is returned. This extension is supported on a wider
    range of XR devices, but the returned information is more limited: A
    single eye gaze vector and position, but without any information about the
    subjects eye openess, pupil size or of the systems confidence in the quality
    of the measured gaze. The gaze vector is of unspecified origin. It could
    be measured gaze from a monocular eye tracker, ie. either left or right eye
    gaze, or it could be a “cyclops eye” synthesized gaze computed via sensor
    fusion of gaze data from a binocular gaze tracker. The gaze data may be
    measured data from a time in the past, or interpolated or extrapolated
    gaze data from one or more past measured eye gaze samples. The returned
    gaze sample timestamp may be a hardware timestamp of when the gaze sample
    was measured, but could also be the time for which gaze was predicted via
    interpolation or extrapolation of past hardware measured gaze samples.
    Temporal resolution of the gaze data is also unspecified. On the tested
    HTC Vive Pro Eye, the reported gaze seems to correspond to the sensor
    fusion of gaze samples from the binocular eye tracker, and the temporal
    resolution is reduced to at best 16.6 msecs for at most 60 gaze samples
    per second.

‘Handtracking’ = Request articulated hand and finger tracking via a supported
hand tracker. This keyword asks the driver to enable articulated hand tracking.
Typical methods are markerless vision based hand and finger tracking, e.g.,
from external cameras or HMD builtin cameras, or marker based optical tracking,
or sensor equipped hand gloves, or other technologies, depending on your OpenXR
runtime. The info struct returned by info = PsychVRHMD(‘GetInfo’); contains info
about hand tracking capabilities as a bitmask in info.articulatedHandTrackingSupported:
A value of +1 means that basic OpenXR hand tracking of finger and hand joint poses,
typically for both hands of a user, is supported. A value of zero means lack of
any support. NOTE: Current Psychtoolbox releases do not yet support hand tracking,
this help text is preparation for future use and subject to incompatible changes!

If hand tracking is requested via the keyword, and supported, then the user
script can request return of hand tracking sample data by calling the
state = PsychVRHMD(‘PrepareRender’, …, reqmask, …) function with reqmask
flag +8. This will cause the returned ‘state’ struct to contain additional fields
with information about recently tracked articulated hand configuration. See the
help text for the ‘PrepareRender’ function for details.

These basic requirements get translated into a device specific set of
settings. The settings can also be specific to the selected ‘basicTask’,
and if a quality vs. performance / system load tradeoff is unavoidable
then the ‘basicQuality’ parameter may modulate the strategy.

‘basicQuality’ defines the basic tradeoff between quality and required
computational power. A setting of 0 gives lowest quality, but with the
lowest performance requirements. A setting of 1 gives maximum quality at
maximum computational load. Values between 0 and 1 change the quality to
performance tradeoff.

By default all currently supported types of HMDs from different
vendors are probed and the first one found is used. If the optional
parameter ‘vendor’ is provided, only devices from that vendor are
detected and the first detected device is chosen.

If additionally the optional ‘deviceIndex’ parameter is provided then
that specific device ‘deviceIndex’ from that ‘vendor’ is opened and set up.

PsychVRHMD(‘SetAutoClose’, hmd, mode);

  • Set autoclose mode for HMD with handle ‘hmd’. ‘mode’ can be
    0 (this is the default) to not do anything special. 1 will close
    the HMD ‘hmd’ when the onscreen window is closed which displays
    on the HMD. 2 will do the same as 1, but close all open HMDs and
    shutdown the complete driver and runtime - a full cleanup.

isOpen = PsychVRHMD(‘IsOpen’, hmd);

  • Returns 1 if ‘hmd’ corresponds to an open HMD, 0 otherwise.

PsychVRHMD(‘Close’ [, hmd])

  • Close provided HMD device ‘hmd’. If no ‘hmd’ handle is provided,
    all HMDs will be closed and the driver will be shutdown.

PsychVRHMD(‘Controllers’, hmd);

  • Return a bitmask of all connected controllers: Can be the bitand
    of the OVR.ControllerType_XXX flags described in ‘GetInputState’.
    This does not detect if controllers are hot-plugged or unplugged after
    the HMD was opened. Iow. only probed at ‘Open’.

info = PsychVRHMD(‘GetInfo’, hmd);

  • Retrieve a struct ‘info’ with information about the HMD ‘hmd’.
    The returned info struct contains at least the following standardized
    fields with information:
    handle = Driver internal handle for the specific HMD.
    driver = Function handle to the actual driver for the HMD, e.g., @PsychOculusVR.
    type = Defines the type/vendor of the device, e.g., ‘Oculus’.
    subtype = Defines the type of driver more specific, e.g., ‘Oculus-classic’ or ‘Oculus-1’.
    modelName = Name string with the name of the model of the device, e.g., ‘Rift DK2’.

separateEyePosesSupported = 1 if use of PsychVRHMD(‘GetEyePose’) will improve
the quality of the VR experience, 0 if no improvement
is to be expected, so ‘GetEyePose’ can be avoided
to save processing time without a loss of quality.
This will be zero (== no benefit) for all modern runtimes.

VRControllersSupported = 1 if use of PsychVRHMD(‘GetInputState’) will provide input
from actual dedicated VR controllers. Value is 0 if
controllers are only emulated to some limited degree,
e.g., by abusing a regular keyboard as a button controller,
ie. mapping keyboard keys to OVR.Button_XXX buttons.

handTrackingSupported = 1 if PsychVRHMD(‘PrepareRender’) with reqmask +2 will provide
valid tracked hand controller info, 0 if this is not supported
and will just report fake values. A driver may report 1 here but
still don’t provide meaningful info at runtime, e.g., if required
tracking hardware is missing or gets disconnected. The flag
just aids extra performance optimizations in your code.

hapticFeedbackSupported = 1 if basic haptic feedback is supported in principle on some controllers.
0 otherwise. A flag of zero means no haptic feedback support, but
a flag of 1 may still mean no actual feedback, e.g., if suitable
hardware is not configured and present. Flags higher than 1 can
signal presence of more advanced haptic feedback, so you should
test for a setting == 1 to know if PsychVRHMD(‘HapticPulse’) works
in principle, which is considered basic feedback ability.

eyeTrackingSupported = Info about eye gaze tracking capabilities of the given VR/AR/MR device and
software setup. A value of 0 means that eye gaze tracking is not supported.
A value of +1 means at least one gaze vector is reported. A value of +2 means
reporting of binocular per-eye tracking data is supported. A value of
+1024 means that HTC’s proprietary SRAnipal eyetracking is available for
more extensive gaze data reporting.

articulatedHandTrackingSupported = Info about hand tracking capabilities. A
value of +1 means that basic articulated hand tracking is supported, usually
for both hands. Zero means no support for articulated hand tracking. The hand
tracking methods could be based on cameras and computer-vision markerless optical
tracking, or on marker based tracking, or it could be, e.g., with some sensor
glove input device, or with any other suitable future modality supported by your
OpenXR runtime.

The info struct may contain much more vendor specific information, but the above
set is supported across all devices.

[isVisible, playAreaBounds, OuterAreaBounds] = PsychVRHMD(‘VRAreaBoundary’, hmd [, requestVisible]);

  • Request visualization of the VR play area boundary for ‘hmd’ and returns its
    current extents.

‘requestVisible’ 1 = Request showing the boundary area markers, 0 = Don’t
request showing the markers.
If the driver can control area boundary visibility is highly dependent on the VR
driver in use. This flag gets ignored by most drivers. See driver specific help, e.g.,
“help PsychOculusVR1”, for behaviour of a specific driver.

Some drivers or hardware setups may not support VR area boundaries at all, in
which case the function will return empty boundaries.

Returns in ‘isVisible’ the current visibility status of the VR area boundaries.

‘playAreaBounds’ is a 3-by-n matrix defining the play area boundaries. Each
column represents the [x;y;z] coordinates of one 3D definition point. Connecting
successive points by line segments defines the boundary, as projected onto the
floor. Points are listed in clock-wise direction. An empty return argument means
that the play area is so far undefined.

‘OuterAreaBounds’ defines the outer area boundaries in the same way as
‘playAreaBounds’.

input = PsychVRHMD(‘GetInputState’, hmd, controllerType);

  • Get input state of controller ‘controllerType’ associated with HMD ‘hmd’.

Note that if the underlying driver does not support special VR controllers, ie.,
hmdinfo = PsychVRHMD(‘GetInfo’) returns hmdinfo.VRControllersSupported == 0, then
only a minimally useful ‘input’ state is returned, which is based on emulating or
faking input from real controllers, so this function will be of limited use. Specifically,
on emulated controllers, only the input.Valid, input.Time and input.Buttons
fields are returned, all other fields are missing.

‘controllerType’ can be one of OVR.ControllerType_LTouch, OVR.ControllerType_RTouch,
OVR.ControllerType_Touch, OVR.ControllerType_Remote, OVR.ControllerType_XBox, or
OVR.ControllerType_Active for selecting whatever controller is currently active.

Return argument ‘input’ is a struct with fields describing the state of buttons and
other input elements of the specified ‘controllerType’. It has the following fields:

‘Valid’ = 1 if ‘input’ contains valid results, 0 if input status is invalid/unavailable.
‘ActiveInputs’ = Bitmask defining which of the following struct elements do contain
meaningful input from actual physical input source devices. This is a more fine-grained
reporting of what ‘Valid’ conveys, split up into categories. The following flags will be
logical or’ed together if the corresponding input category is valid, ie. provided with
actual input data from some physical input source element, controller etc.:

+1 = ‘Buttons’ gets input from some real buttons or switches.
+2 = ‘Touches’ gets input from some real touch/proximity sensors or gesture recognizers.
+4 = ‘Trigger’ gets input from some real analog trigger sensor or gesture recognizer.
+8 = ‘Grip’ gets input from some real analog grip sensor or gesture recognizer.
+16 = ‘Thumbstick’ gets input from some real thumbstick, joystick or trackpad or similar 2D sensor.
+32 = ‘Thumbstick2’ gets input from some real secondary thumbstick, joystick or trackpad or similar 2D sensor.

‘Time’ Time of last input state change of controller.
‘Buttons’ Vector with button state on the controller, similar to the ‘keyCode’
vector returned by KbCheck() for regular keyboards. Each position in the vector
reports pressed (1) or released (0) state of a specific button. Use the OVR.Button_XXX
constants to map buttons to positions.

‘Touches’ Like ‘Buttons’ but for touch buttons. Use the OVR.Touch_XXX constants to map
touch points to positions.

‘Trigger’(1/2) = Left (1) and Right (2) trigger: Value range 0.0 - 1.0, filtered and with dead-zone.
‘TriggerNoDeadzone’(1/2) = Left (1) and Right (2) trigger: Value range 0.0 - 1.0, filtered.
‘TriggerRaw’(1/2) = Left (1) and Right (2) trigger: Value range 0.0 - 1.0, raw values unfiltered.
‘Grip’(1/2) = Left (1) and Right (2) grip button: Value range 0.0 - 1.0, filtered and with dead-zone.
‘GripNoDeadzone’(1/2) = Left (1) and Right (2) grip button: Value range 0.0 - 1.0, filtered.
‘GripRaw’(1/2) = Left (1) and Right (2) grip button: Value range 0.0 - 1.0, raw values unfiltered.

‘Thumbstick’ = 2x2 matrix: Column 1 contains left thumbsticks [x;y] axis values, column 2 contains
right sticks [x;y] axis values. Values are in range -1 to +1, filtered and with deadzone applied.
‘ThumbstickNoDeadzone’ = Like ‘Thumbstick’, filtered, but without a deadzone applied.
‘ThumbstickRaw’ = ‘Thumbstick’ raw date without deadzone or filtering applied.

Some devices driven by an OpenXR runtime may also expose a ‘Thumbstick2’ field, with same semantic
as the ‘Thumbstick’ 2x2 matrix, but for secondary 2D input sources, e.g., a 2nd thumbstick,
joystick or trackpad or similar for each hand-controller. The presence of the ‘Thumbstick2’ field
in the ‘input’ struct is not guaranteed, unless ‘ActiveInputs’ contains the +32 flag ‘Thumbstick2’.

pulseEndTime = PsychVRHMD(‘HapticPulse’, hmd, controllerType [, duration=XX][, freq=1.0][, amplitude=1.0]);

  • Trigger a haptic feedback pulse, some controller vibration, on the specified ‘controllerType’
    associated with the specified ‘hmd’. ‘duration’ is desired pulse duration in seconds. On Oculus
    devices, by default a maximum of 2.5 seconds pulse is executed, but other vendors devices may have
    a different maximum. ‘freq’ is normalized frequency in range 0.0 - 1.0. A value of 0 will try to
    disable an ongoing pulse. How this normalized ‘freq’ maps to a specific haptic device is highly
    device and runtime dependent.

‘amplitude’ is the amplitude of the vibration in normalized 0.0 - 1.0 range.

‘pulseEndTime’ returns the expected stop time of vibration in seconds, given the parameters.
Currently the function will return immediately for a (default) ‘duration’, and the pulse
will end after the maximum duration supported by the given device. Smaller ‘duration’ values than
the maximum duration will block the execution of the function until the ‘duration’ has passed on
some types of controllers.

Please note that behaviour of this function is highly dependent on the type of VR driver and
devices used. You should consult driver specific documentation for details, e.g., the help of
‘PsychOculusVR’ or ‘PsychOculusVR1’ for Oculus systems. On some drivers the function may do
nothing at all, e.g., if the ‘GetInfo’ function returns info.hapticFeedbackSupported == 0.

state = PsychVRHMD(‘PrepareRender’, hmd [, userTransformMatrix][, reqmask=1][, targetTime]);

  • Mark the start of the rendering cycle for a new 3D rendered stereoframe.
    Return a struct ‘state’ which contains various useful bits of information
    for 3D stereoscopic rendering of a scene, based on head tracking data.

‘hmd’ is the handle of the HMD which delivers tracking data and receives the
rendered content for display.

‘reqmask’ defines what kind of information is requested to be returned in
struct ‘state’. Only query information you actually need, as computing some
of this info is expensive! See below for supported values for ‘reqmask’.

‘targetTime’ is the expected time at which the rendered frame will display.
This could potentially be used by the driver to make better predictions of
camera/eye/head pose for the image. Omitting the value will use a target time
that is implementation specific, but known to give generally good results,
e.g., the midpoint of scanout of the next video frame.

‘userTransformMatrix’ is an optional 4x4 right hand side (RHS) transformation
matrix. It gets applied to the tracked head pose as a global transformation
before computing results based on head pose like, e.g., camera transformations.
You can use this to translate the “virtual head” and thereby the virtual eyes/
cameras in the 3D scene, so observer motion is not restricted to the real world
tracking volume of your headset. A typical ‘userTransformMatrix’ would be a
combined translation and rotation matrix to position the observer at some
3D location in space, then define his/her global looking direction, aka as
heading angle, yaw orientation, or rotation around the y-axis in 3D space.
Head pose tracking results would then operate relative to this global transform.
If ‘userTransformMatrix’ is left out, it will default to an identity transform,
in other words, it will do nothing.

state always contains a field state.tracked, whose bits signal the status
of head tracking for this frame. A +1 flag means that head orientation is
tracked. A +2 flag means that head position is tracked via some absolute
position tracker like, e.g., the Oculus Rift DK2 or Rift CV1 camera. A +128
flag means the HMD is actually strapped onto the subjects head and displaying
our visual content. Lack of this flag means the HMD is off and thereby blanked
and dark, or we lost access to it to another application.

state also always contains a field state.SessionState, whose bits signal general
VR session status:

+1 = Our rendering goes to the HMD, ie. we have control over it. Lack of this could
mean the Health and Safety warning is displaying at the moment and waiting for
acknowledgement, or the Oculus GUI application is in control.
+2 = HMD is present and active.
+4 = HMD is strapped onto users head. E.g., a Oculus Rift CV1 would switch off/blank
if not on the head.
+8 = DisplayLost condition! Some hardware/software malfunction, need to completely quit this
Psychtoolbox session to recover from this.
+16 = ShouldQuit The user interface / user asks us to voluntarily terminate this session.
+32 = ShouldRecenter = The user interface asks us to recenter/recalibrate our tracking origin.

‘reqmask’ defaults to 1 and can have the following values added together:

+1 = Return matrices for left and right “eye cameras” which can be directly
used as OpenGL GL_MODELVIEW matrices for rendering the scene. 4x4 matrices
for left- and right eye are contained in state.modelView{1} and {2}.

 Return position and orientation 4x4 camera view matrices which describe  
 position and orientation of the "eye cameras" relative to the world  
 reference frame. They are the inverses of state.modelView{}. These  
 matrices can be directly used to define cameras for rendering of complex  
 3D scenes with the [Horde3D](Horde3D) 3D engine. Left- and right eye matrices are  
 contained in state.cameraView{1} and state.cameraView{2}.  
  
 Additionally tracked/predicted head pose is returned in state.localHeadPoseMatrix  
 and the global head pose after application of the 'userTransformMatrix' is  
 returned in state.globalHeadPoseMatrix - this is the basis for computing  
 the camera transformation matrices.  

+2 = Return matrices for tracked left and right hands of user, ie. of tracked positions
and orientations of left and right hand tracking controllers, if any. See also
section about ‘GetInfo’ for some performance comments.

 state.handStatus(1) = Tracking status of left hand: 0 = Untracked, 1 = Orientation  
                       tracked, 2 = Position tracked, 3 = Orientation and position  
                       tracked. If handStatus is == 0 then all the following information  
                       is invalid and can not be used in any meaningful way.  
  
 state.handStatus(2) = Tracking status of right hand.  
  
 state.localHandPoseMatrix{1} = 4x4 [OpenGL](OpenGL) right handed reference frame matrix with  
                                hand position and orientation encoded to define a  
                                proper GL\_MODELVIEW transform for rendering stuff  
                                "into"/"relative to" the oriented left hand.  
  
 state.localHandPoseMatrix{2} = Ditto for the right hand.  
  
 state.globalHandPoseMatrix{1} = userTransformMatrix \* state.localHandPoseMatrix{1};  
                                 Left hand pose transformed by passed in userTransformMatrix.  
  
 state.globalHandPoseMatrix{2} = Ditto for the right hand.  
  
 state.globalHandPoseInverseMatrix{1} = Inverse of globalHandPoseMatrix{1} for collision  
                                        testing/grasping of virtual objects relative to  
                                        hand pose of left hand.  
  
 state.globalHandPoseInverseMatrix{2} = Ditto for right hand.  

+4 = Return the most recent eye gaze information on devices with built-in eye tracking hardware.
Returned information may represent the latest available measured eye
gaze data, or it may be predicted eye gaze information for the
specified ‘targetTime’, computed via interpolation or extrapolation
from actual previously measured eye gaze. This is dependent on the
specific gaze tracker implementation of your system. If the reported
gaze sample timestamps are identical to the provided ‘targetTime’
then that is one possible indication that reported gaze may be
predicted gaze instead of a direct hardware measured gaze sample.

 The following fields are mandatory as part of the state struct, if gaze  
 tracking is supported and enabled and requested:  
  
 state.gazeRaw = If no new gaze tracking data is available, returns an  
 empty [] variable. Otherwise a variable in a format that is  
 dependent on the actually used gaze tracking api and implementation.  
 It could be a vector, a struct, an array of structs... The format  
 may change without prior notice, without any regard for backward  
 compatibility, so it is mostly useful for debugging by the PTB  
 developers or other Psychtoolbox internal special use cases, not to  
 be relied on by regular user experiment scripts!  
  
 The following variables are arrays, whose length depends on the  
 used gaze tracking method. Each array element represents properties  
 of one tracked eye gaze. At a minimum, the arrays have one element  
 for the most basic gaze tracking, e.g., if the [OpenXR](OpenXR) extension  
 XR\_EXT\_eye\_gaze\_interaction is used for gaze tracking, it will only  
 report one gaze vector in index 1: A monocular gaze sample from either  
 the left or right eye, or a synthetic "cyclops eye" gaze sample, computed  
 via sensor fusion of data from a binocular gazetracker. The arrays could  
 also have 2 elements for a purely binocular eye tracker, with index 1 for  
 the left eye, and index 2 for the right eye data. On a binocular tracker,  
 it is also possible for a three element array to be returned, in  
 which case index 1 is left eye date, 2 is right eye date, and 3 is  
 synthesized "cyclops eye" data.  
  
 Please write your scripts so they can handle any number of 1, 2 or  
 three array elements meaningfully:  
  
 state.gazeStatus(i) = A flag telling if i'th gaze is unavailable  
                       (=0), available (+1) or available and somewhat  
                       trustworthy (+2). Values other than 3 (=1+2)  
                       should not really be trusted. A value of only  
                       1 could, e.g., mean that data was reported,  
                       but it is not based on an actual measured eye  
                       gaze sample, but purely extrapolated or  
                       predicted from past valid data. A value of 3  
                       is not a guarantee of high quality data, just  
                       that the data is actually measured eye gaze  
                       data and passed the minimum quality treshold.  
  
  
 state.gazeTime(i) = A timestamp of the time for which the given  
 gaze information is valid, or the value [NaN](NaN) if no valid timestamp is  
 available from the gaze tracker. Depending on gaze tracking method in  
 use, this could be a time in the past, referring to the hardware  
 timestamp of when the gaze tracker hardware acquired that sample, or  
 it could be the time in the past or near future for which the gaze  
 data was computed via prediction / extrapolation of gaze movement or  
 interpolation from past gaze tracking data history. [OpenXR](OpenXR) built in  
 gaze tracking extensions often may not report the most recent  
 measured eye gaze sample from a past tracking cycle. Instead they  
 take the user provided 'targetTime' (or predicted stimulus onset  
 time for the next to-be-presented VR/AR/MR/XR stimulus image, if  
 'targetTime' was omitted) and try to predict where the subject will  
 be looking (for a 'targetTime' in the near future) or has looked  
 (for a 'targetTime' in the near past). In case of such prediction,  
 the reported state.gazeTime(i) corresponds to the time for which  
 gaze was actually predicted. It is a bit of a hazard for scientific  
 research purposes that there is some uncertainty if timestamps refer  
 to time of real measured gaze, or to some predicted time, or that  
 prediction / interpolation / extrapolation may be used instead of  
 reporting measured data, or that the prediction method - if any - is  
 not specified or standardized across different devices, gaze  
 trackers and gaze tracking runtimes and api's. This is unfortunately  
 unavoidable, as most commercial off the shelf gaze trackers for XR  
 applications are not targeted at scientific research use cases, but  
 as human computer interaction method for operating and navigating in  
 VR and AR, e.g., for gaming and entertainment purposes. Not much we  
 could do about this, so you will have to deal with this in your  
 research paradigm or carefully select hardware with known suitable  
 properties for your specific use case.  
  
 Actual gaze information is provided in two formats, a 2D format, in  
 onscreen window pixel coordinates, ie. where in the image has the  
 subject looked, and a 3D format, as 3D gaze rays, ie. where in a  
 rendered 3D scene has the subject looked:  

2D - Onscreen window referenced:

 state.gazePos{i} = A two-element [x,y] vector of the estimated 2D user  
 gaze position in Psychtoolbox onscreen window coordinates. Iow. the  
 x,y coordinates of where the user looked. In mono display mode this  
 is done by mapping the users gaze vector to the 2D space of the  
 common image that is displayed in the left and right eye display of  
 a VR/AR/MR HMD. In stereoscopic 2D display mode or full 3D perspective  
 correct rendering mode with potential head tracking, where a different  
 image is rendered and displayed to the subjects left and right eye, the  
 mapping of indices is as follows: state.gazePos{1} is expressed wrt.  
 to the left eye image buffer, ie. the one selected via  
 [Screen](Screen)('SelectStereoDrawBuffer', win, 0);. state.gazePos{2} refers  
 to the right eye image buffer ([Screen](Screen)('SelectStereoDrawBuffer', win, 0);).  
 state.gazePos{3} for a potential synthetic "cyclops eye" gaze will  
 reference the left eye image buffer again.  

3D - 3D scene geometry referenced:

 state.gazeRayLocal{i} = encodes the subjects gaze direction / line  
 of sight within a HMD fixed reference frame:  
  
 state.gazeRayLocal{i}.gazeC = a [x,y,z] 3D vector denoting the  
 estimated position of the optical center of the subjects eye balls,  
 relative to the origin of the head-fixed reference frame.  
  
 state.gazeRayLocal{i}.gazeD = a [dx,dy,dz] 3D vector denoting the  
 gaze direction in the head-fixed x, y and z axis.  
  
 The values in gazeRayLocal therefore define a 3D line equation  
 denoting the users line of sight, a "gaze ray" so to speak:  
  
 For all scalar values t from zero to infinity, p(t) with  
 p(t) = state.gazeRayLocal{i}.gazeC + t \* state.gazeRayLocal{i}.gazeD  
 defines 3D points along the looking direction / gaze vector / gaze  
 ray of the subject, in a head-fixed reference frame.  
  
 Mathematical intersection of such a defined line equation p(t) with 3D  
 scene geometry in 3D rendering mode that is fixed wrt. to the users head  
 allows you to figure out where the user is looking in 3D space.  
  
 For a typical 3D head tracked VR / AR / MR rendering scenario, where  
 you would also set the the 'reqmask' flag +1 to retrieve head  
 tracking information and state.modelView matrices for 3D rendering,  
 the function also provides state.gazeRayGlobal{i} of the same  
 format. In this case the HMD head tracking information is used to  
 locate the subjects head position and orientation in a 3D rendered  
 scene and the gaze ray is transformed accordingly, so mathematical  
 intersection of rendered 3D geometry with the 3D line equation ...  
 p(t) = state.gazeRayGlobal{i}.gazeC + t \* state.gazeRayGlobal{i}.gazeD  
 ... allows to find the point of fixation in a 3D world even if the  
 subject is moving their head or walking around.  
  
  
 Some of the supported eye tracking implementations may provide the  
 following additional optional information for each gaze index i. If  
 the information is not available for a given implementation, either  
 an empty vector [] or the scalar value [NaN](NaN) is returned:  
  
 state.gazeConfidence(i) = A scalar value of confidence, ie. how  
 certain is the gaze tracker that reported data is trustworthy and  
 accurate. Currently unsupported on all trackers, returns [NaN](NaN).  
  
 state.gazeEyeOpening(i) = A scalar value of how far the subjects  
 eyes are open, in a normalized range 0 for closed to 1 for fully  
 open. This can be used, e.g., as another confidence measure, or for  
 eye blink detection. Supported for i=1,2 with HTC [SRAnipal](SRAnipal) gaze  
 tracking on suitable HTC [HMDs](HMDs) like the HTC Vive Pro Eye.  
  
 state.gazeEyePupilDiameter(i) = The estimated diameter of the  
 subjects pupil, presumably in millimeters. Supported for i=1,2 with  
 HTC [SRAnipal](SRAnipal) gaze tracking on suitable HTC [HMDs](HMDs) like the HTC Vive Pro Eye.  
  
 state.gazeEyeConvergenceDistance = For binocular gaze tracking, this  
 may be a scalar estimate of eye convergence distance, ie. the  
 distance of the fixation point from the eyes. May be supported on  
 some HTC [HMDs](HMDs) under [SRAnipal](SRAnipal), but has not been confirmed to work in  
 practice on the tested HTC Vive Pro Eye.  

+8 = Request return of articulated hand tracking information on suitable OpenXR
systems.

 NOTE: This feature is NOT YET IMPLEMENTED in current Psychtoolbox releases!  
  
 Returned information may represent the latest available measured hand and  
 finger configuration data, or it may be predicted configuration information  
 for the specified 'targetTime', computed via interpolation or extrapolation  
 from actual previously tracked configurations. This is dependent on the  
 specific hand tracker implementation of your XR system.  
  
 The following fields are mandatory as part of the returned state struct,  
 if hand tracking is supported and enabled and requested:  
  
 TODO, IMPLEMENTATION OF FEATURE NOT YET FINISHED.  

More flags to follow…

eyePose = PsychVRHMD(‘GetEyePose’, hmd, renderPass [, userTransformMatrix][, targetTime]);

  • Return a struct ‘eyePose’ which contains various useful bits of information
    for 3D stereoscopic rendering of the stereo view of one eye, based on head
    tracking data. This function provides essentially the same information as
    the ‘PrepareRender’ function, but only for one eye. Therefore you will need
    to call this function twice, once for each of the two renderpasses, at the
    beginning of each renderpass.

Note: The ‘GetEyePose’ function is not implemented in a meaningful/beneficial
way for modern supported types of HMD. This means that while the function will work
on all supported HMDs, there will not be any benefit on most HMDs of using it in
terms of performance or quality of the VR experience, because the underlying driver may
only emulate / fake the results for compatibility. Currently only the original driver
for the Oculus VR Rift DK1 and Rift DK2 supports this function in a way that could
improve the VR experience, none of the other drivers does, not even the modern driver
for recent Oculus HMDs. The info struct returned by PsychVRHMD(‘GetInfo’) will return
info.separateEyePosesSupported == 1 if there is a benefit to be expected from use
of this function, or info.separateEyePosesSupported == 0 if no benefit is expected
and simply using the data from PsychVRHMD(‘PrepareRender’) will provide results with
the same quality at a lower computational cost.

‘hmd’ is the handle of the HMD which delivers tracking data and receives the
rendered content for display.

‘renderPass’ defines if information should be returned for the 1st renderpass
(renderPass == 0) or for the 2nd renderpass (renderPass == 1). The driver will
decide for you if the 1st renderpass should render the left eye and the 2nd
pass the right eye, or if the 1st renderpass should render the right eye and
then the 2nd renderpass the left eye. The ordering depends on the properties
of the video display of your HMD, specifically on the video scanout order:
Is it right to left, left to right, or top to bottom? For each scanout order
there is an optimal order for the renderpasses to minimize perceived lag.

‘targetTime’ is the expected time at which the rendered frame will display.
This could potentially be used by the driver to make better predictions of
camera/eye/head pose for the image. Omitting the value will use a target time
that is implementation specific, but known to give generally good results.

‘userTransformMatrix’ is an optional 4x4 right hand side (RHS) transformation
matrix. It gets applied to the tracked head pose as a global transformation
before computing results based on head pose like, e.g., camera transformations.
You can use this to translate the “virtual head” and thereby the virtual eyes/
cameras in the 3D scene, so observer motion is not restricted to the real world
tracking volume of your headset. A typical ‘userTransformMatrix’ would be a
combined translation and rotation matrix to position the observer at some
3D location in space, then define his/her global looking direction, aka as
heading angle, yaw orientation, or rotation around the y-axis in 3D space.
Head pose tracking results would then operate relative to this global transform.
If ‘userTransformMatrix’ is left out, it will default to an identity transform,
in other words, it will do nothing.

Return values in struct ‘eyePose’:

‘eyeIndex’ The eye for which this information applies. 0 = Left eye, 1 = Right eye.
You can pass ‘eyeIndex’ into the Screen(‘SelectStereoDrawBuffer’, win, eyeIndex)
to select the proper eye target render buffer.

‘modelView’ is a 4x4 RHS OpenGL matrix which can be directly used as OpenGL
GL_MODELVIEW matrix for rendering the scene.

‘cameraView’ contains a 4x4 RHS camera matrix which describes position and
orientation of the “eye camera” relative to the world reference
frame. It is the inverse of eyePose.modelView. This matrix can
be directly used to define the camera for rendering of complex
3D scenes with the Horde3D 3D engine or other engines which want
absolute camera pose instead of the inverse matrix.

PsychVRHMD(‘SetupRenderingParameters’, hmd [, basicTask=’Tracked3DVR’][, basicRequirements][, basicQuality=0][, fov=[HMDRecommended]][, pixelsPerDisplay=1])

  • Query the HMD ‘hmd’ for its properties and setup internal rendering
    parameters in preparation for opening an onscreen window with PsychImaging
    to display properly on the HMD. See section about ‘AutoSetupHMD’ above for
    the meaning of the optional parameters ‘basicTask’, ‘basicRequirements’
    and ‘basicQuality’.

‘fov’ Optional field of view in degrees, from line of sight: [leftdeg, rightdeg,
updeg, downdeg]. If ‘fov’ is omitted, the HMD runtime will be asked for a
good default field of view and that will be used. The field of view may be
dependent on the settings in the HMD user profile of the currently selected
user. Note: Not always used with the OpenXR backend driver. See ‘help PsychOpenXR’
in the corresponding section for PsychOpenXR(‘SetupRenderingParameters’).

‘pixelsPerDisplay’ Ratio of the number of render target pixels to display pixels
at the center of distortion. Defaults to 1.0 if omitted. Lower values can
improve performance, at lower quality.

PsychVRHMD(‘SetBasicQuality’, hmd, basicQuality);

  • Set basic level of quality vs. required GPU performance.

[oldPosition, oldSize, oldOrientation] = PsychVRHMD(‘View2DParameters’, hmd, eye [, position][, size][, orientation]);

  • Query or assign 2D quad view parameters for eye ‘eye’ of the hmd.
    Such 2D quad views are used in ‘Monoscopic’ (same view for both eyes), or
    ‘Stereoscopic’ mode (one view per eye), as well as in 3D modes when a script is
    ‘Stop’ed and the user asked for use of these 2D quad views instead of projective
    views.
    This returns the current or previous settings for position and size in
    ‘oldPosition’ and ‘oldSize’.
    ‘eye’ Mandatory: 0 = Left eye or monoscopic view, 1 = right eye in stereo mode.
    Optionally you can specify new settings, as follows:
    ‘position’ 3D position of the center of the virtual viewscreen, relative to the
    eye of the subject. Unit is meters, e.g., [0, 0, -0.5] would center the view at
    x,y offset zero relative to the optical axis, and 0.5 meters away from the eye.
    Iow. the center of the viewscreen aligns with the straightforward looking
    direction of the eye, but the screen floats at 0.5 meters distance. If this
    parameter is left empty [] or omitted, then the position does not change.
    Default position at session startup is centered and at a comfortable viewing
    distance away, so staring straight forward with parallel eyes, e.g., like when
    looking at an infinite point in space, would cause the center of the stimulus
    image to be located at your fixation direction.
    ‘size’ Size of the virtual viewscreen in meters. E.g., [0.8, 1] would have the
    screen at an apparent width of 0.8 meters and an apparent height of 1 meter. If
    the parameter is omitted or left empty [], the size won’t be changed. Default
    size is 1 meter high and the width adjusted to preserve the aspect ratio of the
    Psychtoolbox onscreen window into which your script draws, so a drawn circle is
    actually circular instead of elliptic.
    ‘orientation’ A 4 component vector encoding a quaternion for orientation in
    space, ie. a [rx, ry, rz, rw] vector. Or for the most simple and most
    frequent use case: A rotation angle in degrees around the z-axis aka
    optical axis aka line of sight, e.g., 22.3 for a 22.3 degrees rotation.

oldSetting = PsychVRHMD(‘SetFastResponse’, hmd [, enable]);

  • Return old setting for ‘FastResponse’ mode in ‘oldSetting’,
    optionally disable or enable the mode via specifying the ‘enable’
    parameter as 0 or > 0. Please note that if you want to use ‘FastResponse’,
    you must request and thereby enable it at the beginning of a session, as
    the driver must do some neccessary setup prep work at startup of the HMD.
    Once it was initially enabled, you can switch the setting at runtime with
    this function.

Some drivers may implement different strategies for ‘FastResponse’, selectable
via different settings for the ‘enable’ flag here. E.g., the Oculus Rift driver
support three different methods 1, 2 and 3 at the moment.

oldSetting = PsychVRHMD(‘SetTimeWarp’, hmd [, enable]);

  • Return old setting for ‘TimeWarp’ mode in ‘oldSetting’,
    optionally enable or disable the mode via specifying the ‘enable’
    parameter as 1 or 0. Please note that if you want to use ‘TimeWarp’,
    you must request and thereby enable it at the beginning of a session, as
    the driver must do some neccessary setup prep work at startup of the HMD.
    Once it was initially enabled, you can switch the setting at runtime with
    this function.

oldSetting = PsychVRHMD(‘SetLowPersistence’, hmd [, enable]);

  • Return old setting for ‘LowPersistence’ mode in ‘oldSetting’,
    optionally enable or disable the mode via specifying the ‘enable’
    parameter as 1 or 0.

PsychVRHMD(‘SetHSWDisplayDismiss’, hmd [, dismissTypes=1+2+4]);

  • Set how the user can dismiss the “Health and safety warning display”.
    ‘dismissTypes’ can be -1 to disable the HSWD, or a value >= 0 to show
    the HSWD until a timeout and or until the user dismisses the HSWD.
    The following flags can be added to define type of dismissal:

+0 = Display until timeout, if any. Will wait forever if there isn’t any timeout!
+1 = Dismiss via keyboard keypress.
+2 = Dismiss via mouse click or mousepad tap.
+4 = Dismiss via a tap to the HMD (detected via accelerometer).

[bufferSize, imagingFlags, stereoMode] = PsychVRHMD(‘GetClientRenderingParameters’, hmd);

  • Retrieve recommended size in pixels ‘bufferSize’ = [width, height] of the client
    renderbuffer for each eye for rendering to the HMD. Returns parameters
    previously computed by PsychVRHMD(‘SetupRenderingParameters’, hmd).

Also returns ‘imagingFlags’, the required imaging mode flags for setup of
the Screen imaging pipeline. Also returns the needed ‘stereoMode’ for the
pipeline.

This function is usually called by PsychImaging(), you don’t need to deal
with it.

needPanelFitter = PsychVRHMD(‘GetPanelFitterParameters’, hmd);

  • ‘needPanelFitter’ is 1 if a custom panel fitter tasks is needed, and ‘bufferSize’
    from the PsychVRHMD(‘GetClientRenderingParameters’, hmd); defines the size of the
    clientRect for the onscreen window. ‘needPanelFitter’ is 0 if no panel fitter is
    needed.

[winRect, ovrfbOverrideRect, ovrSpecialFlags, ovrMultiSample] = PsychVRHMD(‘OpenWindowSetup’, hmd, screenid, winRect, ovrfbOverrideRect, ovrSpecialFlags, ovrMultiSample);

  • Compute special override parameters for given input/output arguments, as needed
    for a specific HMD. Take other preparatory steps as needed, immediately before the
    Screen(‘OpenWindow’) command executes. This is called as part of PsychImaging(‘OpenWindow’),
    with the user provided hmd, screenid, winRect etc.

isOutput = PsychVRHMD(‘IsHMDOutput’, hmd, scanout);

  • Returns 1 (true) if ‘scanout’ describes the video output to which the
    HMD ‘hmd’ is connected. ‘scanout’ is a struct returned by the Screen
    function Screen(‘ConfigureDisplay’, ‘Scanout’, screenid, outputid);
    This allows probing video outputs to find the one which feeds the HMD.

[projL, projR, fovL, fovR] = PsychVRHMD(‘GetStaticRenderParameters’, hmd [, clipNear=0.01][, clipFar=10000.0]);

  • Retrieve parameters needed to setup the intrinsic parameters of the virtual
    camera for scene rendering.

‘clipNear’ Optional near clipping plane for OpenGL. Defaults to 0.01.
‘clipFar’ Optional far clipping plane for OpenGL. Defaults to 10000.0.

Return arguments:

‘projL’ is the 4x4 OpenGL projection matrix for the left eye rendering.
‘projR’ is the 4x4 OpenGL projection matrix for the right eye rendering.
Please note that projL and projR are usually identical for typical rendering
scenarios.
‘fovL’ Field of view of left camera [leftAngle, rightAngle, upAngle, downAngle].
‘fovR’ Field of view of right camera [leftAngle, rightAngle, upAngle, downAngle].
Angles are expressed in units of radians.

PsychVRHMD(‘Start’, hmd);

  • Start live operations of the ‘hmd’, e.g., head tracking.

PsychVRHMD(‘Stop’, hmd);

  • Stop live operations of the ‘hmd’, e.g., head tracking.
Path   Retrieve current version from GitHub | View changelog
Psychtoolbox/PsychHardware/PsychVRToolbox/PsychVRHMD.m