% Clear the workspace clear; close all; sca; % Randomly seed the random number generation rng('shuffle'); % Here we call some default settings for setting up Psychtoolbox PsychDefaultSetup(2); %---------------------------------------------------------------------- % Physical set-up variables %---------------------------------------------------------------------- % Assumed viewing distance distanceCm = 60; % Radius of the sphere sphereRadius = 5; % Number of slices that we wil use on our sphere (higher gives a smoother % surface) numSlices = 1000; % Our sphere will oscilate with a sine wave function around the X Y ans Z % axes % Amplitude of ossilation amplitude = 360; % Frequency in each dimension (these are just a few random numbers to make % the simulation look nice) frequencyX = 0.03; frequencyY = 0.04; frequencyZ = 0.035; % Angular frequency angFreqX = 2 * pi * frequencyX; angFreqY = 2 * pi * frequencyY; angFreqZ = 2 * pi * frequencyZ; % Starting phase startPhaseX = rand * 360; startPhaseY = rand * 360; startPhaseZ = rand * 360; % Zero time time = 0; %---------------------------------------------------------------------- % Screen initialisation %---------------------------------------------------------------------- % Make sure that the computer is running the OpenGL psych toolbox AssertOpenGL; % Setup Psychtoolbox for OpenGL 3D rendering support and initialize the % mogl OpenGL for Matlab wrapper InitializeMatlabOpenGL; % Number of samples per pixel for multisampling multiSample = 4; % Find the screen to use for display screenid = max(Screen('Screens')); % Set the black and white index black = BlackIndex(screenid); % Start the PsychImaging Configuration PsychImaging('PrepareConfiguration'); PsychImaging('AddTask', 'General', 'FloatingPoint32Bit'); % Open an on screen window using PsychImaging to optimise drawing [window, winRect] = PsychImaging('OpenWindow', screenid, black,... [], 32, 2, [], multiSample); % Set to maximum priority topPriorityLevel = MaxPriority(window); Priority(topPriorityLevel); % Get the width and height of the window in pixels [screenXpix, screenYpix] = Screen('WindowSize', window); % Reported dimensions of the screen in cm [widthMm, heightMm] = Screen('DisplaySize', screenid); screenWidth = widthMm / 10; screenHeight = heightMm / 10; % Measure the vertical refresh rate of the monitor ifi = Screen('GetFlipInterval', window); % Fill the screen black Screen('FillRect', window, black); Screen('Flip', window); %---------------------------------------------------------------------- % Timing information %---------------------------------------------------------------------- % Number of frames to wait before drawing again waitframes = 1; %---------------------------------------------------------------------- % Make a checkerboard texture %---------------------------------------------------------------------- % Make a colored checkerboard texture checkerNum = 10; scaleFactor = 100; colorChecker = imresize(rand(checkerNum, checkerNum, 3), scaleFactor, 'nearest'); % Convert to a texture for PTB drawing (orientation needs changing for % rendering) imageFlipped = rot90(flipud(colorChecker)); planeTexture = Screen('MakeTexture', window, imageFlipped, [], 1, 2); % Get the information we need about the texture [imw, imh] = Screen('WindowSize', planeTexture); [texNameFront, targetFront, tuFront, tvFront] = Screen('GetOpenGLTexture', window, planeTexture, imh, imw); % Bind our texture and setup filtering to allow nice presentation of our % texture glBindTexture(targetFront, texNameFront); glGenerateMipmapEXT(targetFront); glTexParameterf(targetFront, GL.TEXTURE_MAG_FILTER, GL.LINEAR); glTexParameterf(targetFront, GL.TEXTURE_MIN_FILTER, GL.LINEAR_MIPMAP_LINEAR); % Allow the texture and lighting to interact glTexEnvfv(GL.TEXTURE_ENV, GL.TEXTURE_ENV_MODE, GL.MODULATE); % This gives nice texture rendering without artifacts maxAnisotropy = glGetFloatv(GL.MAX_TEXTURE_MAX_ANISOTROPY_EXT); glTexParameterf(targetFront, GL.TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy); % Clamping behaviour shall be a cyclic repeat: glTexParameteri(targetFront, GL.TEXTURE_WRAP_S, GL.REPEAT); glTexParameteri(targetFront, GL.TEXTURE_WRAP_T, GL.REPEAT); %---------------------------------------------------------------------- % OpenGL Setup %---------------------------------------------------------------------- % Setup the OpenGL rendering context of the onscreen window for use by % OpenGL wrapper Screen('BeginOpenGL', window); % Set background color to 'black' glClearColor(0, 0, 0, 0); % Enable depth buffer glEnable(GL.DEPTH_TEST); %---------------------------------------------------------------------- % We will use perspective projection %---------------------------------------------------------------------- % Near and far clipping planes (these difine the rendering volume, anything % outside of these is not rendered) clipNear = 0.1; clipFar = 100; % Angular subtense of the screen angle = 2 * atand((screenHeight / 2) / distanceCm); % Aspect ratio of the screen aspectRatio = screenWidth / screenHeight; % 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; gluPerspective(angle, aspectRatio, clipNear, clipFar); % Setup modelview matrix: This defines the position, orientation and % direction of the virtual camera that will look at our scene with glMatrixMode(GL.MODELVIEW); glLoadIdentity; % Location of the camera cam = [0 0 0]; % Set our camera to be looking directly down the -Z axis (depth) of our % coordinate system fix = [0 0 -1]; % Define "up" 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)); %---------------------------------------------------------------------- % Setup the lighting for the environment %---------------------------------------------------------------------- % Enable OpenGL Lighting glEnable(GL.LIGHTING); % Force there to be no ambient light (OpenGL default is for there to be % some) glLightModelfv(GL.LIGHT_MODEL_AMBIENT, [0 0 0 1]); % Define a local light source glEnable(GL.LIGHT0); % Defuse light only glLightfv(GL.LIGHT0, GL.DIFFUSE, [1 1 1 1]); % Point the light at the origin (this is where we will place our sphere) glLightfv(GL.LIGHT0, GL.SPOT_DIRECTION, [0 0 -distanceCm]); % Allow normalisation glEnable(GL.NORMALIZE); %---------------------------------------------------------------------- % Create a Qudratic sphere %---------------------------------------------------------------------- % Enable and bind the texture glEnable(targetFront); glBindTexture(targetFront, texNameFront); % Make a sphere as a quadratic object and automatically generate texture % coordinates theSphere = gluNewQuadric; gluQuadricTexture(theSphere, GL.TRUE); % End the open GL wrapper for now Screen('EndOpenGL', window); %---------------------------------------------------------------------- % Keyboard information %---------------------------------------------------------------------- % Unify the keyboard names for mac and windows computers KbName('UnifyKeyNames'); % Define the keyboard keys that are listened for escapeKey = KbName('ESCAPE'); %---------------------------------------------------------------------- % Drawing Loop %---------------------------------------------------------------------- % Get a vbl for the start time vbl = Screen('Flip', window); startTimeFix = vbl; while ~KbCheck % Orientation of the square on this frame angleX = amplitude * sin(angFreqX * time + startPhaseX); angleY = amplitude * sin(angFreqY * time + startPhaseY); angleZ = amplitude * sin(angFreqZ * time + startPhaseZ); % Begin open GL Screen('BeginOpenGL', window); % Clear the buffers glClear; % Push and pop are needed to avoid accumulations of transforms glPushMatrix; % Rotate and then translate the surface (these commands need to be % issued in the opposite way in which you want them applied by OpenGL) glTranslatef(0, 0, -distanceCm); glRotatef(angleX, 1, 0, 0); glRotatef(angleY, 0, 1, 0); glRotatef(angleZ, 0, 0, 1); % Call the display list i.e. show our textured plan gluSphere(theSphere, sphereRadius, numSlices, numSlices); % Ditch the matrix transforms glPopMatrix; % End the open GL context Screen('EndOpenGL', window); % Flip to the screen vbl = Screen('Flip', window, vbl + (waitframes - 0.5) * ifi); % Increment time time = time + ifi; end % Close the screen sca