1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
function VRHMDDemo(stereoscopic, checkerboard, withGazeTracking, deviceindex)
%
% VRHMDDemo([stereoscopic=1][, checkerboard=0][, withGazeTracking=0][, deviceindex=0])
%
% A very basic demo for the most basic setup of VR HMDs, e.g., the Oculus
% VR Rift DK2. It shows the absolute minimum of steps needed - one line of
% code - to use the first connected HMD as mono or stereo display.
%
% 'stereoscopic' if set to 1 (which is the default), configures the
% HMD as a stereoscopic display. A setting of 0 configures it as a
% monoscopic display.
%
% 'checkerboard' if set to 1 draws a checkboard pattern instead of the
% regular test image.
%
% The optional parameter 'withGazeTracking', if provided and non-zero, will
% enable some basic test of eye gaze tracking with VR HMD's which support
% eye tracking. Please note that this functionality is not available in
% official Psychtoolbox releases yet, at least not as of v3.0.19.1, and the
% api used in this demo is highly experimental and subject to backwards
% incompatible changes!
%
% 'deviceindex' if provided, selects the HMD with given index. Otherwise
% the first HMD (deviceindex 0) is chosen.
%
% The demo just renders one static simple 2D image, or image pair in
% stereoscopic mode, then displays it in a loop until a key is pressed.
% History:
% 05-Sep-2015 mk Written.
% 30-Mar-2017 mk Adapt to the reality of new VR runtimes.
% Setup unified keymapping and unit color range:
PsychDefaultSetup(2);
if nargin < 1 || isempty(stereoscopic)
stereoscopic = 1;
end
if nargin < 2 || isempty(checkerboard)
checkerboard = 0;
end
% Disable test of eye gaze tracking by default:
if nargin < 3 || isempty(withGazeTracking)
withGazeTracking = 0;
end
if withGazeTracking
% Tell that eyetracking is desired:
reqGazeTracking = 'Eyetracking ';
else
reqGazeTracking = '';
end
if nargin < 4
deviceindex = [];
end
% Select screen with highest id as Oculus output display:
screenid = max(Screen('Screens'));
% Open our fullscreen onscreen window with black background clear color:
PsychImaging('PrepareConfiguration');
% Build final task requirements:
basicReqs = ['NoTimingSupport NoTimestampingSupport ' reqGazeTracking];
% We do collect timestamps for benchmarking, but don't require them to be especially precise or trustworthy:
if ~stereoscopic
% Setup the HMD to act as a regular "monoscopic" display monitor
% by displaying the same image to both eyes:
hmd = PsychVRHMD('AutoSetupHMD', 'Monoscopic', basicReqs, [], [], deviceindex);
else
% Setup for stereoscopic presentation:
hmd = PsychVRHMD('AutoSetupHMD', 'Stereoscopic', basicReqs, [], [], deviceindex);
end
if isempty(hmd)
fprintf('No support for VR, so can not run this demo. Bye.\n');
return;
end
[win, rect] = PsychImaging('OpenWindow', screenid);
hmdinfo = PsychVRHMD('GetInfo', hmd);
% Disable gaze tracking test if unsupported by setup:
if withGazeTracking && ~hmdinfo.eyeTrackingSupported
withGazeTracking = 0;
end
Screen('TextStyle', win, 1);
Screen('TextSize', win, 100);
if checkerboard
% Apply regular checkerboard pattern as texture:
bv = zeros(32);
wv = ones(32);
myimg = double(repmat([bv wv; wv bv],32,32) > 0.5);
mytex = Screen('MakeTexture', win, myimg, [], 1);
end
% Render one view for each eye in stereoscopic mode:
vbl = [];
while ~KbCheck
for eye = 0:stereoscopic
Screen('SelectStereoDrawBuffer', win, eye);
Screen('FillRect', win, [0 0 1]);
if checkerboard
Screen('DrawTexture', win, mytex);
end
Screen('FrameRect', win, [1 1 0], [], 20);
if ~checkerboard
Screen('FillOval', win, [0.5 0.5 0.5], CenterRect([0 0 700 700], rect));
DrawFormattedText(win, sprintf('HELLO\nWORLD!\n%i', eye), 'center', 'center', [0 1 0]);
end
Screen('FillOval', win, [mod(GetSecs, 1) 0 0], CenterRect([0 0 10 10], rect));
if withGazeTracking
if eye == 0
state = PsychVRHMD('PrepareRender', hmd, [], 4);
end
Screen('FrameArc',win, [0,1,1], CenterRect([0 0 500 500], rect), mod(GetSecs, 10) * 36, 10, 20);
for i = 1:length(state.gazeStatus)
% fprintf('Eye %i: status %i pos = %i %i\n', i, state.gazeStatus(i), state.gazePos{i}(1), state.gazePos{i}(2));
% disp(state.gazeRayLocal{i}.gazeC);
if state.gazeStatus(i) >= 3
Screen('DrawDots', win, state.gazePos{i}, 5, [1, 0, i - 1], [], 1);
end
end
end
end
vbl(end+1) = Screen('Flip', win); %#ok<AGROW>
end
KbStrokeWait;
sca;
close all;
plot(1000 * diff(vbl));
fps = 1 / mean(diff(vbl)) %#ok<NOPRT,NASGU>
end
|