/* This is an OpenGL/GLUT implementation of the "plane" stereo demonstration program found in Appendix 1 of "The CrystalEyes Handbook" by Lenny Lipton, 1991, StereoGraphics Corp. */ /* Ported to OpenGL/GLUT by Mike Blackwell, mkb@cs.cmu.edu, Oct. 1995. */ #include #include #include #include #include "interlace_stencil.c" #define SPEED 100 /* How often to update rotation - milliseconds */ #define STEP 1.0 /* How much to rotate - degrees */ double position = 0; /* Rotation of plane */ void reshape(int w, int h) { glViewport(0,0, w, h); interlace_stencil (w,h); } /* Clean up and quit */ void all_done(void) { exit(0); } /* ARGSUSED */ void timer(int value) { position -= STEP; if (position < 0.0) position = 360.0 - STEP; glutPostRedisplay(); glutTimerFunc(SPEED, timer, 0); } /* ARGSUSED1 */ void keyboard(unsigned char key, int x, int y) { switch (key) { case '\033': all_done(); break; default: putchar('\007'); fflush(stdout); break; } } /* This routine performs the perspective projection for one eye's subfield. The projection is in the direction of the negative z axis. xmin, ymax, ymin, ymax = the coordinate range, in the plane of zero parallax setting, that will be displayed on the screen. The ratio between (xmax-xmin) and (ymax-ymin) should equal the aspect ration of the display. znear, zfar = the z-coordinate values of the clipping planes. zzps = the z-coordinate of the plane of zero parallax setting. dist = the distance from the center of projection to the plane of zero parallax. eye = half the eye separation; positive for the right eye subfield, negative for the left eye subfield. */ void stereoproj(float xmin, float xmax, float ymin, float ymax, float znear, float zfar, float zzps, float dist, float eye) { float xmid, ymid, clip_near, clip_far, top, bottom, left, right, dx, dy, n_over_d; dx = xmax - xmin; dy = ymax - ymin; xmid = (xmax + xmin) / 2.0; ymid = (ymax + ymin) / 2.0; clip_near = dist + zzps - znear; clip_far = dist + zzps - zfar; n_over_d = clip_near / dist; top = n_over_d * dy / 2.0; bottom = -top; right = n_over_d * (dx / 2.0 - eye); left = n_over_d * (-dx / 2.0 - eye); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(left, right, bottom, top, clip_near, clip_far); glTranslatef(-xmid - eye, -ymid, -zzps - dist); } void draw_airplane(void) { static float airplane[9][3] = { {0.0, 0.5, -4.5}, {3.0, 0.5, -4.5}, {3.0, 0.5, -3.5}, {0.0, 0.5, 0.0}, {0.0, 0.5, 3.25}, {0.0, -0.5, 5.5}, {-3.0, 0.5, -3.5}, {-3.0, 0.5, -4.5}, {0.0, -0.5, -4.5} }; /* glColor3ub(0xb0, 0x30, 0xff); Purple color */ glBegin(GL_LINE_LOOP); glVertex3fv(airplane[6]); glVertex3fv(airplane[7]); glVertex3fv(airplane[1]); glVertex3fv(airplane[2]); glVertex3fv(airplane[4]); glEnd(); glBegin(GL_LINE_LOOP); glVertex3fv(airplane[0]); glVertex3fv(airplane[4]); glVertex3fv(airplane[5]); glVertex3fv(airplane[8]); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(airplane[6]); glVertex3fv(airplane[3]); glVertex3fv(airplane[2]); glEnd(); } /* This routine puts a stereo image of a paper airplane onto the screen */ void redraw(void) { glLineWidth(4); /* we must restore the line width seting */ /* Draw left subfield */ /* stereo_left_buffer() */ /* following command replace glDrawBuffer(GL_BACK_LEFT); */ glStencilFunc(GL_NOTEQUAL,1,1); /* draws if stencil <> 1 */ glClearColor(0.07, 0.07, 0.07, 0.00); glClear(GL_COLOR_BUFFER_BIT); /* Z-coordinate of plane of zero parallax is 0.0. In that plane, the coord range drawn to the screen will be (-6.0 to 6.0, -4.8 to 4.8). Z-coordinate clipping planes are -6.0 and 6.0. The eyes are set at world coord distance 14.5 from the plane of zero parallax, and the eye separation is 0.62 in world coords. These two values were calculated using equations 11 to 15, and 17 to 19 in chapter 5. */ stereoproj(-6.0, 6.0, -4.8, 4.8, 6.0, -6.0, 0.0, 14.5, -0.31); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef((float) position, 0.0, 1.0, 0.0); glRotatef(-10.0, 1.0, 0.0, 0.0); glColor3f(0.7,0,0); /* left airplain red */ draw_airplane(); glFlush(); /* Draw right subfield */ /* stereo_right_buffer(); */ /* following command replace glDrawBuffer(GL_BACK_RIGHT); */ glStencilFunc(GL_EQUAL,1,1); /* draws if stencil <> 0 */ /* we can not cear twice */ /* glClearColor(0.07, 0.07, 0.07, 0.00); */ /* glClear(GL_COLOR_BUFFER_BIT); */ /* Same as above stereoproj() call, except that eye arg is positive */ stereoproj(-6.0, 6.0, -4.8, 4.8, 6.0, -6.0, 0.0, 14.5, 0.31); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef((float) position, 0.0, 1.0, 0.0); glRotatef(-10.0, 1.0, 0.0, 0.0); glColor3f(0,0,1); /* right airplain blue */ draw_airplane(); glFlush(); glutSwapBuffers(); /* Update screen */ } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_STENCIL); glutCreateWindow("GLUT-based SGI hack stereo demo"); /* glutFullScreen(); */ /* glutSetCursor(GLUT_CURSOR_NONE); */ /* start_fullscreen_stereo(); */ glutReshapeFunc(reshape); glutDisplayFunc(redraw); glutKeyboardFunc(keyboard); glutTimerFunc(SPEED, timer, 0); /* glEnable(GL_LINE_SMOOTH); */ /* glEnable(GL_BLEND); */ /* glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); */ /* glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); */ /* glLineWidth(1.5); */ glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }