nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: nuclear@0: #include nuclear@0: #ifndef __APPLE__ nuclear@0: #include nuclear@0: #else nuclear@0: #include nuclear@0: #endif nuclear@0: nuclear@0: #include "scene.h" nuclear@0: nuclear@0: void disp(void); nuclear@0: void render(unsigned int msec); nuclear@0: void proj_matrix(float eye); nuclear@0: void view_matrix(float eye); nuclear@0: nuclear@9: void idle(void); nuclear@0: void reshape(int x, int y); nuclear@0: void keyb(unsigned char key, int x, int y); nuclear@0: void keyb_up(unsigned char key, int x, int y); nuclear@0: void mouse(int bn, int state, int x, int y); nuclear@0: void motion(int x, int y); nuclear@0: void sball_motion(int x, int y, int z); nuclear@0: void sball_rotate(int x, int y, int z); nuclear@0: void sball_button(int bn, int state); nuclear@0: int parse_args(int argc, char **argv); nuclear@0: nuclear@0: int win_width, win_height; nuclear@0: int stereo; nuclear@0: int flip_winding; nuclear@3: int auto_rot; nuclear@0: float cam_theta, cam_phi, cam_dist = 10; nuclear@0: float near_clip = 0.5; nuclear@0: float far_clip = 1000.0; nuclear@0: float fov = M_PI / 4.0; nuclear@0: float stereo_focus_dist = 1.0; nuclear@0: float stereo_eye_sep = 1.0 / 30.0; nuclear@0: nuclear@3: int verbose = 0; nuclear@3: nuclear@0: struct scene scn; nuclear@0: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@4: float amb[] = {0.01, 0.01, 0.01, 1}; nuclear@3: float ldir[] = {-1, 1, 1, 0}; nuclear@0: float dx, dy, dz, diag; nuclear@0: nuclear@8: nuclear@0: glutInitWindowSize(800, 600); nuclear@0: glutInit(&argc, argv); nuclear@0: glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (stereo ? GLUT_STEREO : 0)); nuclear@4: glutCreateWindow("OpenGL 3D viewer"); nuclear@0: nuclear@0: glutDisplayFunc(disp); nuclear@0: glutReshapeFunc(reshape); nuclear@0: glutKeyboardFunc(keyb); nuclear@0: glutKeyboardUpFunc(keyb_up); nuclear@0: glutMouseFunc(mouse); nuclear@0: glutMotionFunc(motion); nuclear@0: glutSpaceballMotionFunc(sball_motion); nuclear@0: glutSpaceballRotateFunc(sball_rotate); nuclear@0: glutSpaceballButtonFunc(sball_button); nuclear@3: if(auto_rot) { nuclear@9: glutIdleFunc(idle); nuclear@3: } nuclear@0: nuclear@0: glewInit(); nuclear@0: nuclear@4: glEnable(GL_NORMALIZE); nuclear@0: glEnable(GL_DEPTH_TEST); nuclear@0: glEnable(GL_CULL_FACE); nuclear@0: glEnable(GL_LIGHTING); nuclear@0: glEnable(GL_LIGHT0); nuclear@0: glLightfv(GL_LIGHT0, GL_POSITION, ldir); nuclear@0: nuclear@4: glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb); nuclear@4: nuclear@8: nuclear@8: init_scene(&scn); nuclear@8: if(parse_args(argc, argv) == -1) { nuclear@0: return 1; nuclear@0: } nuclear@8: if(verbose) { nuclear@8: printf("scene bounds: %.2f %.2f %.2f -> %.2f %.2f %.2f\n", scn.bbox.min[0], scn.bbox.min[1], nuclear@8: scn.bbox.min[2], scn.bbox.max[0], scn.bbox.max[1], scn.bbox.max[2]); nuclear@8: } nuclear@8: nuclear@0: dx = scn.bbox.max[0] - scn.bbox.min[0]; nuclear@0: dy = scn.bbox.max[1] - scn.bbox.min[1]; nuclear@0: dz = scn.bbox.max[2] - scn.bbox.min[2]; nuclear@0: diag = sqrt(dx * dx + dy * dy + dz * dz); nuclear@0: cam_dist = diag / fov; nuclear@0: printf("camera distance: %f\n", cam_dist); nuclear@0: nuclear@0: glutMainLoop(); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: nuclear@0: void disp(void) nuclear@0: { nuclear@0: unsigned int tm = glutGet(GLUT_ELAPSED_TIME); nuclear@0: nuclear@0: if(stereo) { nuclear@0: glDrawBuffer(GL_BACK_LEFT); nuclear@0: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@0: proj_matrix(-1); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glLoadIdentity(); nuclear@0: view_matrix(-1); nuclear@0: nuclear@0: render(tm); nuclear@0: nuclear@0: glDrawBuffer(GL_BACK_RIGHT); nuclear@0: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@0: proj_matrix(1); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glLoadIdentity(); nuclear@0: view_matrix(1); nuclear@0: nuclear@0: render(tm); nuclear@0: } else { nuclear@0: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@0: proj_matrix(0); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glLoadIdentity(); nuclear@0: view_matrix(0); nuclear@0: nuclear@0: render(tm); nuclear@0: } nuclear@0: nuclear@0: glutSwapBuffers(); nuclear@0: } nuclear@0: nuclear@0: void render(unsigned int msec) nuclear@0: { nuclear@0: if(auto_rot) { nuclear@0: glRotatef(msec / 10, 0, 1, 0); nuclear@0: } nuclear@0: render_scene(&scn); nuclear@0: } nuclear@0: nuclear@0: void proj_matrix(float eye) nuclear@0: { nuclear@0: float vfov_rad = fov; nuclear@0: float top = near_clip * tan(vfov_rad * 0.5); nuclear@0: float right = top * (float)win_width / (float)win_height; nuclear@0: nuclear@0: float frust_shift = eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist); nuclear@0: nuclear@0: glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip); nuclear@0: } nuclear@0: nuclear@0: void view_matrix(float eye) nuclear@0: { nuclear@0: float offs = stereo_eye_sep * eye * 0.5; nuclear@0: glTranslatef(offs, 0, 0); nuclear@0: nuclear@0: glTranslatef(0, 0, -cam_dist); nuclear@0: glRotatef(cam_phi, 1, 0, 0); nuclear@0: glRotatef(cam_theta, 0, 1, 0); nuclear@0: } nuclear@0: nuclear@9: void idle(void) nuclear@9: { nuclear@9: glutPostRedisplay(); nuclear@9: } nuclear@9: nuclear@0: void reshape(int x, int y) nuclear@0: { nuclear@0: glViewport(0, 0, x, y); nuclear@0: win_width = x; nuclear@0: win_height = y; nuclear@0: } nuclear@0: nuclear@0: static int stereo_shift_key; nuclear@0: nuclear@0: void keyb(unsigned char key, int x, int y) nuclear@0: { nuclear@0: switch(key) { nuclear@0: case 'q': nuclear@0: case 27: nuclear@0: exit(0); nuclear@0: nuclear@0: case 's': nuclear@0: stereo_shift_key = 1; nuclear@0: break; nuclear@0: nuclear@0: case 'c': nuclear@0: { nuclear@0: static int flip; nuclear@0: glFrontFace((++flip & 1) ? GL_CW : GL_CCW); nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case 'C': nuclear@0: { nuclear@0: static int cull = 1; nuclear@0: if(++cull & 1) { nuclear@0: glEnable(GL_CULL_FACE); nuclear@0: } else { nuclear@0: glDisable(GL_CULL_FACE); nuclear@0: } nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case 'w': nuclear@0: { nuclear@0: static int wire; nuclear@0: glPolygonMode(GL_FRONT_AND_BACK, (++wire & 1) ? GL_LINE : GL_FILL); nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case 'l': nuclear@0: { nuclear@0: static int lit = 1; nuclear@0: if(++lit & 1) { nuclear@0: glEnable(GL_LIGHTING); nuclear@0: } else { nuclear@0: glDisable(GL_LIGHTING); nuclear@0: } nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case ' ': nuclear@0: auto_rot = !auto_rot; nuclear@0: if(auto_rot) { nuclear@9: glutIdleFunc(idle); nuclear@0: } else { nuclear@0: glutIdleFunc(0); nuclear@0: } nuclear@0: glutPostRedisplay(); nuclear@0: break; nuclear@0: nuclear@5: case 'f': nuclear@5: { nuclear@5: static int fullscr; nuclear@9: static int orig_xsz, orig_ysz; nuclear@5: if(++fullscr & 1) { nuclear@9: int vp[4]; nuclear@9: glGetIntegerv(GL_VIEWPORT, vp); nuclear@9: orig_xsz = vp[2]; nuclear@9: orig_ysz = vp[3]; nuclear@5: glutFullScreen(); nuclear@5: } else { nuclear@9: glutReshapeWindow(orig_xsz, orig_ysz); nuclear@9: glutPositionWindow(20, 40); nuclear@5: } nuclear@5: } nuclear@5: break; nuclear@5: nuclear@5: { nuclear@5: static float bgval; nuclear@5: case '=': nuclear@5: bgval += 0.1; nuclear@5: if(bgval > 1.0) nuclear@5: bgval = 1.0; nuclear@5: glClearColor(bgval, bgval, bgval, 1.0); nuclear@5: glutPostRedisplay(); nuclear@5: break; nuclear@5: nuclear@5: case '-': nuclear@5: bgval -= 0.1; nuclear@5: if(bgval < 0.0) nuclear@5: bgval = 0.0; nuclear@5: glClearColor(bgval, bgval, bgval, 1.0); nuclear@5: glutPostRedisplay(); nuclear@5: break; nuclear@5: } nuclear@5: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void keyb_up(unsigned char key, int x, int y) nuclear@0: { nuclear@0: switch(key) { nuclear@0: case 's': nuclear@0: stereo_shift_key = 0; nuclear@0: break; nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: nuclear@0: static int bnstate[32]; nuclear@0: static int prev_x, prev_y; nuclear@0: void mouse(int bn, int state, int x, int y) nuclear@0: { nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN ? 1 : 0; nuclear@0: } nuclear@0: nuclear@0: void motion(int x, int y) nuclear@0: { nuclear@0: int dx = x - prev_x; nuclear@0: int dy = y - prev_y; nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: nuclear@0: if(stereo_shift_key && dy != 0) { nuclear@0: stereo_focus_dist += dy * 0.1; nuclear@0: stereo_eye_sep = stereo_focus_dist / 30.0; nuclear@0: glutPostRedisplay(); nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: if(bnstate[0]) { nuclear@0: cam_theta += dx * 0.5; nuclear@0: cam_phi += dy * 0.5; nuclear@0: nuclear@0: if(cam_phi < -90) nuclear@0: cam_phi = -90; nuclear@0: if(cam_phi > 90) nuclear@0: cam_phi = 90; nuclear@0: nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: if(bnstate[2]) { nuclear@0: cam_dist += dy * 0.1; nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void sball_motion(int x, int y, int z) nuclear@0: { nuclear@0: } nuclear@0: nuclear@0: void sball_rotate(int x, int y, int z) nuclear@0: { nuclear@0: cam_theta += y * 0.05; nuclear@0: cam_phi += x * 0.05; nuclear@0: nuclear@0: if(cam_phi < -90) nuclear@0: cam_phi = -90; nuclear@0: if(cam_phi > 90) nuclear@0: cam_phi = 90; nuclear@0: nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: nuclear@0: void sball_button(int bn, int state) nuclear@0: { nuclear@0: } nuclear@0: nuclear@0: int parse_args(int argc, char **argv) nuclear@0: { nuclear@8: int i, num_loaded = 0; nuclear@0: nuclear@0: for(i=1; i