Skip to content

Commit

Permalink
Merge pull request Psychtoolbox-3#260 from kleinerm/xreyetracking-cle…
Browse files Browse the repository at this point in the history
…anedformerge

Merge initial OpenXR eye gaze tracking support.

- Cyclops eye single gaze reporting via XR_EXT_eye_gaze_interaction on all operating systems and capable HMD's.
- Binocular eye gaze reporting, pupil diameter estimates, eye openess estimates on MS-Windows 10+ with capable HTC HMD's.
- `help OpenXR` for basic setup instructions and references to demos and tests.
- `help PsychVRHMD` for info about how to use eyetracking, capabilities and limitations.

170 work hours spent, but only less than 120 hours funded. Another win for PTB users, another business fail!
  • Loading branch information
kleinerm authored Nov 16, 2023
2 parents 17159b2 + 4b15793 commit 99c7727
Show file tree
Hide file tree
Showing 23 changed files with 2,181 additions and 103 deletions.
391 changes: 391 additions & 0 deletions PsychSourceGL/Cohorts/SRAnipalMex.cpp

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions PsychSourceGL/License.txt
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@
% These statically included files can be found in the nanopb subfolder of the PsychOpenXRCore
% source folder, with detailed copyright and license information included.
%
% Our Virtual Reality (VR) drivers for OpenHMD and OpenXR supported HTC VR headsets
% with eye gaze tracking hardware also support more advanced eye gaze tracking by
% use of our SRAnipalMex mex file for 64-Bit Windows 10 and later. This is only
% supported on MS-Windows. The mex file uses the HTC SRAnipal SDK for interfacing
% with the HTC eye trackers SRAnipal runtime. The license text for the SRAnipal SDK
% can be found below in the section of individual licenses under the subsection
% "The HTC SRAnipal SDK license".
%
% Support for NVidia NVision stereo emitter/stereo goggles under Linux is
% implemented by use of libnvstusb from http://sourceforge.net/projects/libnvstusb/
% This library is licensed under LGPLv2 license. The source code for our
Expand Down Expand Up @@ -1752,3 +1760,40 @@
%
% =========================================================================
%
% The HTC SRAnipal SDK license:
%
% License Agreement
% For Vive Super Reality Library
%
% Copyright (c) 2017, HTC Corporation
%
% All rights reserved. Third party copyrights are property of their respective owners.
%
% Redistribution and use in source and binary forms, with or without modification,
% are permitted provided that the following conditions are met:
%
% * Redistribution's of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% * Redistribution's in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% * The name of the copyright holders may not be used to endorse or promote products
% derived from this software without specific prior written permission.
%
% This software is provided by the copyright holders and contributors "as is" and
% any express or implied warranties, including, but not limited to, the implied
% warranties of merchantability and fitness for a particular purpose are disclaimed.
% In no event shall the Intel Corporation or contributors be liable for any direct,
% indirect, incidental, special, exemplary, or consequential damages
% (including, but not limited to, procurement of substitute goods or services;
% loss of use, data, or profits; or business interruption) however caused
% and on any theory of liability, whether in contract, strict liability,
% or tort (including negligence or otherwise) arising in any way out of
% the use of this software, even if advised of the possibility of such damage.
%
% End of the HTC SRAnipal SDK license text.
%
% =========================================================================

178 changes: 164 additions & 14 deletions PsychSourceGL/Source/Common/PsychOpenXRCore/PsychOpenXRCore.c

Large diffs are not rendered by default.

47 changes: 30 additions & 17 deletions PsychSourceGL/Source/windowsmakeit64_twisty.m
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,26 @@ function windowsmakeit64_twisty(what, onoctave)
movefile(['..\Projects\Windows\build\IOPort.' mexext], [PsychtoolboxRoot 'PsychBasic\MatlabWindowsFilesR2007a\']);
end

if what == 5
% Build PsychCV
% Disabled for now: As long as it contains 3rd party code, we can't
% really distribute it in a precompiled version for Matlab under our
% new license. Distribution of compiled mex files for octave would
% be possible, but see below...
% clear PsychCV
% mex -outdir ..\Projects\Windows\build -output PsychCV -DPTBMODULE_PsychCV -largeArrayDims -DMEX_DOUBLE_HANDLE -ID:\install\QuickTimeSDK\CIncludes -ICommon\Base -ICommon\PsychCV -IWindows\Base -I..\Cohorts\ARToolkit\include Windows\Base\*.c Common\Base\*.c Common\PsychCV\*.c kernel32.lib user32.lib gdi32.lib advapi32.lib glu32.lib opengl32.lib winmm.lib delayimp.lib libARvideo.lib libARgsub.lib libARgsub_lite.lib libARgsubUtil.lib libARMulti.lib libAR.lib
% movefile(['..\Projects\Windows\build\PsychCV.' mexext], [PsychtoolboxRoot 'PsychBasic\MatlabWindowsFilesR2007a\']);
if what == 5 && exist('..\..\..\SRAnipalCSDK', 'dir')
% Build SRAnipalMex on MS-Windows for Matlab 64 Bit:
%
% This requires the proprietary HTC SRAnipal SDK installed side by side
% to the Psychtoolbox-3 folder in a folder called SRAnipalCSDK.
%
% The SDK can be found at the time of this writing under the following URL
% (free sign up for a developer account with HTC and agreeing to a license
% required):
%
% https://developer-express.vive.com/resources/vive-sense/eye-and-facial-tracking-sdk/
%
% Specifically, e.g., for the v1.3.6.8 SDK, you have to unzip the SDK zip file,
% then move the "01_C" subfolder from "...\SRAnipalSDK-v1.3.6.8\SDK-v1.3.6.8\SDK\01_C"
% into a parent folder next to the Psychtoolbox-3 folder and rename it from "01_C" to
% "SRAnipalCSDK". This is a one type preparation step on a new build system.
%
clear SRAnipalMex;
mex -outdir ..\Projects\Windows\build -output SRAnipalMex -I..\..\..\SRAnipalCSDK\include -L..\..\..\SRAnipalCSDK\lib ..\Cohorts\SRAnipalMex.cpp -lSRanipal
movefile(['..\Projects\Windows\build\SRAnipalMex.' mexext], [PsychtoolboxRoot 'PsychBasic\MatlabWindowsFilesR2007a\']);
end

if what == 6
Expand Down Expand Up @@ -299,14 +310,16 @@ function windowsmakeit64_twisty(what, onoctave)
movefile(['..\Projects\Windows\build\IOPort.' mexext], target);
end

if what == 5
% Build PsychCV.mex
% NOTE: Link is currently broken. Also we don't build and
% distribute PsychCV.mex at the moment. Let's see if anybody
% actually misses this mex file...
% clear PsychCV
% mexoctave --output ..\Projects\Windows\build\PsychCV.mex -DPTBMODULE_PsychCV -DPTBOCTAVE3MEX -ID:\install\QuickTimeSDK\CIncludes -ID:\MicrosoftDirectXSDK\Include -ICommon\Base -ICommon\PsychCV -IWindows\Base -I..\Cohorts\ARToolkit\include Windows\Base\*.c Common\Base\*.c Common\PsychCV\*.c kernel32.lib user32.lib gdi32.lib advapi32.lib glu32.lib opengl32.lib winmm.lib delayimp.lib libARvideo.lib libARgsub.lib libARgsub_lite.lib libARgsubUtil.lib libARMulti.lib libAR.lib
%movefile(['..\Projects\Windows\build\PsychCV.' mexext], target);
if what == 5 && exist('..\..\..\SRAnipalCSDK', 'dir')
% Build SRAnipalMex on MS-Windows for Octave 64 Bit:
%
% This requires the proprietary HTC SRAnipal SDK installed side by side
% to the Psychtoolbox-3 folder in a folder called SRAnipalCSDK. See above
% Matlab build path for the SDK download location and setup instructions.
%
clear SRAnipalMex;
mexoctave --output ..\Projects\Windows\build\SRAnipalMex.mex -I..\..\..\SRAnipalCSDK\include -L..\..\..\SRAnipalCSDK\lib ..\Cohorts\SRAnipalMex.cpp -lSRanipal
movefile(['..\Projects\Windows\build\SRAnipalMex.' mexext], target);
end

if what == 6
Expand Down
45 changes: 45 additions & 0 deletions Psychtoolbox/License.txt
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@
% These statically included files can be found in the nanopb subfolder of the PsychOpenXRCore
% source folder, with detailed copyright and license information included.
%
% Our Virtual Reality (VR) drivers for OpenHMD and OpenXR supported HTC VR headsets
% with eye gaze tracking hardware also support more advanced eye gaze tracking by
% use of our SRAnipalMex mex file for 64-Bit Windows 10 and later. This is only
% supported on MS-Windows. The mex file uses the HTC SRAnipal SDK for interfacing
% with the HTC eye trackers SRAnipal runtime. The license text for the SRAnipal SDK
% can be found below in the section of individual licenses under the subsection
% "The HTC SRAnipal SDK license".
%
% Support for NVidia NVision stereo emitter/stereo goggles under Linux is
% implemented by use of libnvstusb from http://sourceforge.net/projects/libnvstusb/
% This library is licensed under LGPLv2 license. The source code for our
Expand Down Expand Up @@ -1752,3 +1760,40 @@
%
% =========================================================================
%
% The HTC SRAnipal SDK license:
%
% License Agreement
% For Vive Super Reality Library
%
% Copyright (c) 2017, HTC Corporation
%
% All rights reserved. Third party copyrights are property of their respective owners.
%
% Redistribution and use in source and binary forms, with or without modification,
% are permitted provided that the following conditions are met:
%
% * Redistribution's of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% * Redistribution's in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% * The name of the copyright holders may not be used to endorse or promote products
% derived from this software without specific prior written permission.
%
% This software is provided by the copyright holders and contributors "as is" and
% any express or implied warranties, including, but not limited to, the implied
% warranties of merchantability and fitness for a particular purpose are disclaimed.
% In no event shall the Intel Corporation or contributors be liable for any direct,
% indirect, incidental, special, exemplary, or consequential damages
% (including, but not limited to, procurement of substitute goods or services;
% loss of use, data, or profits; or business interruption) however caused
% and on any theory of liability, whether in contract, strict liability,
% or tort (including negligence or otherwise) arising in any way out of
% the use of this software, even if advised of the possibility of such damage.
%
% End of the HTC SRAnipal SDK license text.
%
% =========================================================================

Binary file not shown.
Binary file not shown.
Binary file modified Psychtoolbox/PsychBasic/Octave5LinuxFiles64/PsychOpenXRCore.mex
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified Psychtoolbox/PsychBasic/PsychOpenXRCore.mexa64
Binary file not shown.
32 changes: 18 additions & 14 deletions Psychtoolbox/PsychDemos/GazeContingentDemo.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ function GazeContingentDemo(mode, ms, myimgfile, usehmd)
% two images based on a spatial gaussian weight mask. Compositing is done
% by the graphics hardware.
%
% If you set the optional 'usehmd' parameter to 1 then the demo will display on
% a VR HMD, and if that HMD has a suported eyetracker, it will be used to move
% the foveated area gaze contingent with the users tracked gaze.
%
% See also: PsychDemos, MovieDemo, DriftDemo

% HISTORY
%
% mm/dd/yy
%
% mm/dd/yy
%
% 7/23/05 mk Derived it from Frans Cornelissens AlphaImageDemoOSX.
% 11/19/06 dhb Remove OSX from name.

Expand Down Expand Up @@ -56,7 +60,7 @@ function GazeContingentDemo(mode, ms, myimgfile, usehmd)
gazetracking = 0;

try
fprintf('GazeContingentDemo (%s)\n', datestr(now)); %#ok<TNOW1,DATST>
fprintf('GazeContingentDemo (%s)\n', datestr(now)); %#ok<TNOW1,DATST>
fprintf('Press a key or click on mouse to stop demo.\n');

PsychDefaultSetup(1);
Expand Down Expand Up @@ -143,12 +147,12 @@ function GazeContingentDemo(mode, ms, myimgfile, usehmd)
% Fovea contains color-inverted image data:
foveaimdata(:,:,:) = 255 - imdata(:,:,:);
% Periphery contains original data:
peripheryimdata = imdata;
peripheryimdata = imdata;
case 4
% Test-case: One shouldn't see any foveated region on the
% screen - this is a basic correctness test for blending.
foveaimdata = imdata;
peripheryimdata = imdata;
peripheryimdata = imdata;
otherwise
% Unknown mode! We force abortion:
fprintf('Invalid mode provided!');
Expand Down Expand Up @@ -190,7 +194,7 @@ function GazeContingentDemo(mode, ms, myimgfile, usehmd)
% initially to center of screen:
[a,b]=RectCenter(wRect);
SetMouse(a,b,screenNumber); % set cursor and wait for it to take effect

HideCursor;
buttons=0;

Expand All @@ -209,11 +213,11 @@ function GazeContingentDemo(mode, ms, myimgfile, usehmd)
ncount = 0;

oldvbl = Screen('Flip', w);

% Infinite display loop: Whenever "gaze position" changes, we update
% the display accordingly. Loop aborts on keyboard press or mouse
% click or after 10000 frames...
while (ncount < 10000)
while (ncount < 10000)
% Query current mouse cursor position (our "pseudo-eyetracker") -
% (mx,my) is our gaze position.
if hurryup == 0
Expand All @@ -231,9 +235,9 @@ function GazeContingentDemo(mode, ms, myimgfile, usehmd)
% without query of the mouse:
mx=500 + 500*sin(ncount/10); my=300;
end

% We only redraw if gazepos. has changed:
if (mx~=mxold || my~=myold)
if (mx~=mxold || my~=myold)
% Compute position and size of source- and destinationrect and
% clip it, if necessary...
myrect=[mx-ms my-ms mx+ms+1 my+ms+1]; % center dRect on current mouseposition
Expand All @@ -243,7 +247,7 @@ function GazeContingentDemo(mode, ms, myimgfile, usehmd)
% Valid destination rectangle?
if ~IsEmptyRect(dRect)
% Yes! Draw image for current frame:

% Step 1: Draw the alpha-mask into the backbuffer. It
% defines the aperture for foveation: The center of gaze
% has zero alpha value. Alpha values increase with distance from
Expand Down Expand Up @@ -279,7 +283,7 @@ function GazeContingentDemo(mode, ms, myimgfile, usehmd)
% syncing to retrace if hurryup is == 1.
vbl = Screen('Flip', w, 0, 2, 2*hurryup);
if hurryup
vbl = GetSecs; %#ok<UNRCH>
vbl = GetSecs; %#ok<UNRCH>
end
tavg = tavg + (vbl-oldvbl);
oldvbl=vbl;
Expand All @@ -305,15 +309,15 @@ function GazeContingentDemo(mode, ms, myimgfile, usehmd)
Screen('BlendFunction', w, GL_ONE, GL_ZERO);
Screen('DrawTexture', w, foveatex);
Screen('Flip', w);

% The same command which closes onscreen and offscreen windows also
% closes textures.
sca;
ShowCursor;
Priority(0);
tavg = tavg / ncount * 1000;
fprintf('End of GazeContingentDemo. Avg. redraw time is %f ms = %f Hz.\n\n', tavg, 1000 / tavg);
return;
return;
catch
%this "catch" section executes in case of an error in the "try" section
%above. Importantly, it closes the onscreen window if its open.
Expand Down
4 changes: 2 additions & 2 deletions Psychtoolbox/PsychDemos/OpenGL4MatlabDemos/VRHMDDemo1.m
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function VRHMDDemo1(multiSample, fountain, checkerboard, gpumeasure, debugView,
% 10-Sep-2015 mk Written. Derived from DrawDots3DDemo.m

% GL data structure needed for all OpenGL demos:
global GL; %#ok<GVMIS>
global GL; %#ok<GVMIS>

if nargin < 1 || isempty(multiSample)
multiSample = 4;
Expand Down Expand Up @@ -224,7 +224,7 @@ function VRHMDDemo1(multiSample, fountain, checkerboard, gpumeasure, debugView,
% also assign an alpha value that makes the particles "fade out" at the end
% of there lifetime:
particlecolors = rand(3, nparticles);

% Maximum speed for particles:
maxspeed = 1.25;

Expand Down
6 changes: 3 additions & 3 deletions Psychtoolbox/PsychDemos/VRHMDDemo.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
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
Expand Down Expand Up @@ -131,14 +131,14 @@ function VRHMDDemo(stereoscopic, checkerboard, withGazeTracking, deviceindex)
end
end
end
vbl(end+1) = Screen('Flip', win); %#ok<AGROW>
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>
fps = 1 / mean(diff(vbl)) %#ok<NOPRT,NASGU>

end
Loading

0 comments on commit 99c7727

Please sign in to comment.