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 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
% BitsLutStereoDemo
%
% demonstration of displaying a precalculated texture based movie, whilst
% separately animating the LUT, and whilst
% controlling the FE1 goggles using a Tlock packet.
%
% For use with the OSX version of Psychtoolbox.
% tested with version 1.0.5, Matlab release 14 sp 2 and OSX 10.3.9
% uses the hidden 'LoadNormalizedGammaTable' screen function.
%
% Please note that this demo needs the Bits++ from Cambridge Research Systems!!
%
% Sections have been lifted from the OSX movie demo etc.
%
% 26/04/2005 ejw wrote it.
clear; close all
% Define screen
whichScreen=max(Screen('Screens'));
% Find the color values which correspond to white and black. Though on OS
% X we currently only support true color and thus, for scalar color
% arguments,
% black is always 0 and white 255, this rule is not true on other platforms will
% not remain true on OS X after we add other color depth modes.
white=WhiteIndex(whichScreen);
black=BlackIndex(whichScreen);
gray=GrayIndex(whichScreen);
% Open up the a window on the screen.
% This is done by calling the Screen function of the Psychophysics
% Toolbox. We need to open the onscreen window first, so that
% the offscreen storage allocated subsequently is properly
% matched to the onscreen frame buffer.
[window,screenRect] = Screen('OpenWindow',whichScreen,128,[],32,2);
% THE FOLLOWING STEP IS IMPORTANT.
% make sure the graphics card LUT is set to a linear ramp
% (else the encoded data will not be recognised by Bits++).
% There is a bug with the underlying OpenGL function, hence the scaling 0 to 255/256.
% This demo will not work using a default gamma table in the graphics card,
% or even if you set the gamma to 1.0, due to this bug.
% This is NOT a bug with Psychtoolbox!
Screen('LoadNormalizedGammaTable',window,linspace(0,(255/256),256)'*ones(1,3));
% draw a gray background on front and back buffers
%Screen('FillRect',window, gray);
%Screen('Flip', window);
%Screen('FillRect',window, gray);
% =================================================================
% CODE NEEDED HERE !
% "linear_lut" should be replaced here with one giving the inverse
% characteristic of the monitor.
% =================================================================
% restore the Bits++ LUT to a linear ramp
linear_lut = repmat(round(linspace(0, 2^16 -1, 256))', 1, 3);
BitsPlusSetClut(window,linear_lut);
% find out how big the window is
[screenWidth, screenHeight]=Screen('WindowSize', window);
[y,x] = meshgrid(-(screenHeight - 1)/2: (screenHeight - 1)/2, -(screenWidth - 1)/2: (screenWidth - 1)/2);
blend_image = sqrt((exp(-abs(5*x/((screenWidth - 1)/2))).^2) + (exp(-abs(5*y/((screenHeight - 1)/2))).^2));
% encode the image in mono++ format
encoded_image = BitsPlusPackMonoImage(blend_image*((2^16)-1));
Screen('PutImage', window, encoded_image);
Screen(window,'Flip');
Screen('PutImage', window, encoded_image);
% textures can't seem to be bigger than the screen, though they have to be
% square. So the max texture size is the smaller of the screen dimensions!!
max_texture_size = min([screenWidth screenHeight]);
% pre calculate two counter rotating gratings
% some graphics cards have a hardware texture size limit of 256 square
% (any bigger and it is slow). Be aware that textures use up RAM very quickly.
texture_size=180; % the diagonal dimension of 180 x 180 is 255, which is our
% maximum number of LUT entries
if (max_texture_size < texture_size)
error('screen must have a minimum resolution of 256');
end
% check that the screen width is at least 524 pixels
if (screenWidth < 524)
error('window is not big enough to encode the Bits++ CLUT');
end
image=zeros(texture_size,texture_size,3);
[x,y] = meshgrid(-(texture_size - 1)/2: (texture_size - 1)/2, -(texture_size - 1)/2: (texture_size - 1)/2);
% number of cycles of sine wave in patch
speed=10/359;
cycles_across=5;
% unfortunately we have to iterate this, to generate the textures??
for orient=0:359
fprintf('Calculating angle %d\n',orient);
phase = round(128 + sin(pi*orient/180)*y + cos(pi*orient/180)*x);
image(:,:,1) = 0;
image(:,:,2) = 0;
image(:,:,3) = phase;
left(orient + 1)= Screen('MakeTexture',whichScreen,image);
phase = round(128 - sin(pi*orient/180)*y + cos(pi*orient/180)*x);
image(:,:,1) = 0;
image(:,:,2) = 0;
image(:,:,3) = phase;
right(orient + 1)= Screen('MakeTexture',whichScreen,image);
end
% create some drifting sinewave LUTs
[index,offset,gun] = meshgrid(0: 255, 0: 359, 1: 3);
% =================================================================
% CODE NEEDED HERE !
% the code needs to apply the inverse characteristic of the monitor.
% =================================================================
luts = (2^16 - 1) * (sin(cycles_across * 2 * pi * (index/255 + (offset*speed))) + 1) / 2;
% now quickly display the previously calculated textures,
% addind the control for the goggles
fprintf('Displaying counter-rotating gratings, hold a key to exit \n');
while(~KbCheck)
for orient= 1:360
% encode the LUT
newClutRow = BitsPlusEncodeClutRow(squeeze(luts(orient,:,:)));
rect=[0 0 size(newClutRow,2) 1];
Screen('PutImage', window, newClutRow, rect, rect);
Screen('DrawTexture',window,left(orient));
% bitsgoggles adds the one line image to control the digital o/p
% then calls 'Flip'
% Note that bitsGoggles controls the goggle state for the frame
% >after< it is displayed, hence we set the right goggle open now
bitsGoggles(1,0,window);
% encode the LUT
newClutRow = BitsPlusEncodeClutRow(squeeze(luts(orient,:,:)));
rect=[0 0 size(newClutRow,2) 1];
Screen('PutImage', window, newClutRow, rect, rect);
Screen('DrawTexture',window,right(orient));
% bitsgoggles adds the one line image to control the digital o/p
% then calls 'Flip'
% Note that bitsGoggles controls the goggle state for the frame
% >after< it is displayed, hence we set the left goggle open now
bitsGoggles(0,1,window);
end
end
% reset the digital output data
Mask=0;
Command=0;
Data=zeros(1,248);
bitsEncodeDIO(Mask,Data,Command, window);
% if the system only has one screen, set the LUT in Bits++ to a linear ramp
% if the system has two or more screens, then blank the screen.
if (whichScreen == 0)
% =================================================================
% CODE NEEDED HERE !
% "linear_lut" should be replaced here with one giving the inverse
% characteristic of the monitor.
% =================================================================
% restore the Bits++ LUT to a linear ramp
linear_lut = repmat(round(linspace(0, 2^16 -1, 256))', 1, 3);
BitsPlusSetClut(window,linear_lut);
% draw a gray background on front and back buffers to clear out any old LUTs
Screen('FillRect',window, gray);
Screen('Flip', window);
Screen('FillRect',window, gray);
Screen('Flip', window);
% Close the window.
Screen('CloseAll');
else
% Blank the screen
BitsPlusSetClut(window,zeros(256,3));
% draw a black background on front and back buffers to clear out any old LUTs
Screen('FillRect',window, black);
Screen('Flip', window);
Screen('FillRect',window, black);
Screen('Flip', window);
Screen('CloseAll');
end
|