% Clear the workspace clear; close all; sca; % Here we call some default settings for setting up Psychtoolbox PsychDefaultSetup(2); %-------------------------------------------------------------------------- % Screen initialisation %-------------------------------------------------------------------------- % Make sure that the computer is running the OpenGL psych toolbox AssertOpenGL; % Find the screen to use for displaying the stimuli. By using "max" this % will display on an external monitor if one is connected. screenid = max(Screen('Screens')); % Determine the values of black and white black = BlackIndex(screenid); white = WhiteIndex(screenid); % Initialise OpenGL InitializeMatlabOpenGL; % Set up our screen [window, windowRect] = PsychImaging('OpenWindow', screenid, black, [], 32, 2); % Get the vertical refresh rate of the monitor ifi = Screen('GetFlipInterval', window); % Get the width and height of the window in pixels [screenXpix, screenYpix] = Screen('WindowSize', window); % Determine the center of the screen. We will need this later when we draw % our dots. [center(1), center(2)] = RectCenter(windowRect); % Queries the display size in mm as reported by the operating system. Note % that there are some complexities here. See Screen DisplaySize? for % information. So always measure your screen size directly. We just use the % reported value for the purposes of this demo. [widthMM, heightMM] = Screen('DisplaySize', screenid); % Convert to CM screenYcm = heightMM / 10; screenXcm = widthMM / 10; %-------------------------------------------------------------------------- % Projection information %-------------------------------------------------------------------------- % Start the OpenGL context (you have to do this before you issue OpenGL % commands such as we are using here) Screen('BeginOpenGL', window); % Enable proper occlusion handling via depth tests glEnable(GL.DEPTH_TEST); % Enable blending for anti-aliased lines glEnable(GL.BLEND); glBlendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA); % Set the line width in pixels glLineWidth(6); % Lets set up a projection matrix, the projection matrix defines how images % in our 3D simulated scene are projected to the images on our 2D monitor glMatrixMode(GL.PROJECTION); glLoadIdentity; % We are using orthographic projection for our necker cube, this is what % makes the stimulus ambiguous. depthClipLimit = 1000; glOrtho(-screenXcm/2, screenXcm/2,... -screenYcm/2, screenYcm/2, -depthClipLimit, depthClipLimit); % Setup modelview matrix: This defines the position, orientation and % looking direction of the virtual camera that will be look at our scene. glMatrixMode(GL.MODELVIEW); glLoadIdentity; % Location of the camera is at the origin cam = [0 0 0]; % Nominal distance of the object: this is a nominal distance as it will not % effect the size of the rendered image due to this being orthographic % projection. We just need to make sure that the position of the object is % within the clipping planes of the glOrtho(...) call. dist = -100; % Start angle for the cube angle = rand * 360; % Rotation per second and frame: the object will rotate 60 degree per % second rotPerSec = 60; rotPerFrame = rotPerSec * ifi; % Set our camera to be looking directly down the Z axis (depth) of our % coordinate system. fix = [0 0 dist]; % Define "up": this sets the orientation of our coordinate system up = [0 1 0]; % Here we set up the attributes of our camera using the variables we have % defined in the last three lines of code gluLookAt(cam(1), cam(2), cam(3), fix(1), fix(2), fix(3), up(1), up(2), up(3)); % Set background color to 'black' (the 'clear' color) glClearColor(0, 0, 0, 0); % Clear out the backbuffer glClear; % For now we end the OpenGL context to allow us to call standard screen % functions of PTB Screen('EndOpenGL', window); %-------------------------------------------------------------------------- % Stimulus information / timing %-------------------------------------------------------------------------- % Our stimulus is very simple and can be drawn in a single line of OpenGL % code. All we need to do is specify its size. Here just a 3rd of our % reported screen height. cubeSize = screenYcm / 3; % Position of our cube relative to the camera cubePos = [0 0 dist]; % We will update the stimulus on each frame waitframes = 1; % Get a flip to sync our timing vbl = Screen(window, 'Flip'); %-------------------------------------------------------------------------- % Drawing Loop %-------------------------------------------------------------------------- % Stimulus drawing loop (exits when any button is pressed) while ~KbCheck % Begin OpenGL again for this frame as we will be issuing OpenGL % commands Screen('BeginOpenGL', window); % Push the matrix stack glPushMatrix; % Clear stuff glClear; % Translate glTranslatef(cubePos(1), cubePos(2), cubePos(3)); % Rotate the cube (in reality OpenGL will rotate and then translate the % cube. That is the instructions are applied the reverse in which you % state them. glRotatef(25, 1, 0, 1); glRotatef(angle, 0, 1, 0); % Render the cube: we will color it white, we are not useing lighting % and material properties here, just standard RGB colors. glColor3f(white, white, white); glutWireCube(cubeSize); % Pop the matrix now that we applied our transformations glPopMatrix; % End the OpenGL context so that we can flip to the screen Screen('EndOpenGL', window); % Flip to the screen vbl = Screen('Flip', window, vbl + (waitframes - 0.5) * ifi); % Increment the angle of the cube angle = angle + rotPerFrame; end % Clean up and leave the building sca;