function [] = StereoTeapotDemo(viewMode)
% StereoTeapotDemo - Demonstrate the combo of OpenGL 3d and PsychToolbox
% stereo pipeline (anaglyph, LCD shutter, etc.).
%
% This is a reprise of the UtahTeapotDemo with stereo vision support. Set
% viewMode to 1 for LCD shutter glasses, 2-5 for split screen 6-9 for
% anaglyph
%
% 07-May-2007 - Created by Patrick Mineault
% Is the script running in OpenGL Psychtoolbox?
AssertOpenGL;
% Find the screen to use for display:
screenid=max(Screen('Screens'));
% Disable Synctests for this simple demo:
Screen('Preference','SkipSyncTests',1);
% Setup Psychtoolbox for OpenGL 3D rendering support and initialize the
% mogl OpenGL for Matlab wrapper:
global GL;
InitializeMatlabOpenGL(1);
if(nargin() < 1)
viewMode = 9; %Default to red/blue anaglyph
end
% Open a double-buffered full-screen window on the main displays screen.
[win , winRect] = Screen('OpenWindow', screenid, 0, [0 0 1280 1024], 32, 2, viewMode, 0, kPsychNeedFastBackingStore);
% Setup the OpenGL rendering context of the onscreen window for use by
% OpenGL wrapper. After this command, all following OpenGL commands will
% draw into the onscreen window 'win':
Screen('BeginOpenGL', win);
% Get the aspect ratio of the screen:
ar=winRect(4)/winRect(3);
% Turn on OpenGL local lighting model: The lighting model supported by
% OpenGL is a local Phong model with Gouraud shading.
glEnable(GL.LIGHTING);
% Enable the first local light source GL.LIGHT_0. Each OpenGL
% implementation is guaranteed to support at least 8 light sources.
glEnable(GL.LIGHT0);
% Enable two-sided lighting - Back sides of polygons are lit as well.
glLightModelfv(GL.LIGHT_MODEL_TWO_SIDE,GL.TRUE);
% Enable proper occlusion handling via depth tests:
glEnable(GL.DEPTH_TEST);
% Define the cubes light reflection properties by setting up reflection
% coefficients for ambient, diffuse and specular reflection:
glMaterialfv(GL.FRONT_AND_BACK,GL.AMBIENT, [ 1 1 1 1 ]);
glMaterialfv(GL.FRONT_AND_BACK,GL.DIFFUSE, [ .78 .57 .11 1 ]);
glMaterialfv(GL.FRONT_AND_BACK,GL.SPECULAR, [ 1 1 1 1 ]);
glMaterialfv(GL.FRONT_AND_BACK,GL.SHININESS,128);
% Set projection matrix: This defines a perspective projection,
% corresponding to the model of a pin-hole camera - which is a good
% approximation of the human eye and of standard real world cameras --
% well, the best aproximation one can do with 3 lines of code ;-)
glMatrixMode(GL.PROJECTION);
glLoadIdentity;
% Setup modelview matrix: This defines the position, orientation and
% looking direction of the virtual camera:
glMatrixMode(GL.MODELVIEW);
glLoadIdentity;
% Setup position and emission properties of the light source:
% Set background color to 'black':
glClearColor(0,0,0,0);
% Point lightsource at (1,2,3)...
glLightfv(GL.LIGHT0,GL.POSITION,[ 0 0 -100 0 ]);
% Emits white (1,1,1,1) diffuse light:
glLightfv(GL.LIGHT0,GL.DIFFUSE, [ 1 1 1 1 ]);
% Emits reddish (1,1,1,1) specular light:
glLightfv(GL.LIGHT0,GL.SPECULAR, [ 1 0 0 1 ]);
% There's also some blue, but weak (R,G,B) = (0.1, 0.1, 0.1)
% ambient light present:
glLightfv(GL.LIGHT0,GL.AMBIENT, [ .1 .1 .6 1 ]);
%Screen('EndOpenGL', win);
% Initialize amount and direction of rotation
theta=0;
rotatev=[ 0 0 1 ];
numframes = 1;
Screen('EndOpenGL', win);
% Animation loop: Run until key press...
while (1)
% Calculate rotation angle for next frame:
theta=mod(theta+0.3,360);
rotatev=rotatev+0.1*[ sin((pi/180)*theta) sin((pi/180)*2*theta) sin((pi/180)*theta/5) ];
rotatev=rotatev/sqrt(sum(rotatev.^2));
RenderScene(0, theta, rotatev, win)
RenderScene(1, theta, rotatev, win)
Screen('Flip', win);
% Check for keyboard press and exit, if so:
if KbCheck
break;
end
numframes = numframes + 1;
end
% Close onscreen window and release all other ressources:
Screen('CloseAll');
% Reenable Synctests after this simple demo:
Screen('Preference','SkipSyncTests',1);
% Well done!
%return
%Render the Teapot
function [] = RenderScene(whichEye, theta, rotatev, win)
global GL;
%%Render an eye
Screen('SelectStereoDrawBuffer', win, whichEye);
Screen('BeginOpenGL', win);
% Setup cubes rotation around axis:
glMatrixMode(GL.PROJECTION);
glPushMatrix;
%Appropriate values for each parameter are listed
%The last parameter is the important one, which defines eye position
StereoProjection(-6.0, 4.8, 6.0, -4.8, 6.0, -6.0, 0, 10, -0.3+0.6*whichEye);
glMatrixMode(GL.MODELVIEW);
glPushMatrix;
%rotate us some teapot
glRotated(theta,rotatev(1),rotatev(2),rotatev(3));
% Clear out the backbuffer: This also cleans the depth-buffer for
% proper occlusion handling:
glClear;
glutSolidTeapot(3 );
glPopMatrix;
glMatrixMode(GL.PROJECTION);
glPopMatrix;
% Finish OpenGL rendering into PTB window and check for OpenGL errors.
Screen('EndOpenGL', win);
%Set up the stereo projection matrices. Taken verbatim from Quoc Vuong's
%class Computer Graphics for Vision Research,
%http://www.kyb.mpg.de/bu/people/qvuong/CGV05.html
function [] = StereoProjection(left, top, right, bottom, near, far, zero_plane, dist, eye)
%{
Perform the perspective projection for one eye's subfield.
The projection is in the direction of the negative z-axis.
[default: -6.0, 6.0, -4.8, 4.8]
left, right, bottom, top = the coordinate range, in the plane of zero parallax setting,
which will be displayed on the screen.
The ratio between (right-left) and (top-bottom) should equal the aspect
ratio of the display.
[default: 6.0, -6.0]
near, far = the z-coordinate values of the clipping planes.
[default: 0.0]
zero_plane = the z-coordinate of the plane of zero parallax setting.
[default: 14.5]
dist = the distance from the center of projection to the plane of zero parallax.
[default: -0.3]
eye = half the eye separation; positive for the right eye subfield,
negative for the left eye subfield.
%}
dx = right - left;
dy = top - bottom;
xmid = (right + left) / 2.0;
ymid = (top + bottom) / 2.0;
clip_near = dist + zero_plane - near;
clip_far = dist + zero_plane - far;
n_over_d = clip_near / dist;
topw = n_over_d * dy / 2.0;
bottomw = -topw;
rightw = n_over_d * (dx / 2.0 - eye);
leftw = n_over_d *(-dx / 2.0 - eye);
%// Create a fustrum, and shift it off axis
%// glTranslate() applies to PROJECTION matrix
glLoadIdentity();
glFrustum(leftw, rightw, bottomw, topw, clip_near, clip_far);
glTranslatef(-xmid - eye, -ymid, -zero_plane -dist);