nuclear@0: #include nuclear@0: #include nuclear@1: #include nuclear@0: #include nuclear@8: #include "opengl.h" nuclear@1: #include "vr.h" nuclear@0: #include "camera.h" nuclear@0: nuclear@0: static bool init(); nuclear@0: static void cleanup(); nuclear@0: static void disp(); nuclear@9: static void draw_scene(); nuclear@12: static void draw_teapot(); nuclear@13: static void draw_squares(); nuclear@12: static void draw_grid(float size, float spacing); nuclear@0: static void idle(); nuclear@0: static void reshape(int x, int y); nuclear@0: static void keyb(unsigned char key, int x, int y); nuclear@8: static void keyup(unsigned char key, int x, int y); nuclear@8: static void mouse(int bn, int st, int x, int y); nuclear@8: static void motion(int x, int y); nuclear@8: static void passive(int x, int y); nuclear@0: static void sball_rotate(int rx, int ry, int rz); nuclear@1: static bool parse_args(int argc, char **argv); nuclear@0: nuclear@10: static VRFpsCamera cam; nuclear@0: static int width, height; nuclear@1: static bool use_vr = false; nuclear@8: static bool mouselook = false; nuclear@8: nuclear@8: static bool keystate[256]; nuclear@8: nuclear@12: static int rtarg_width, rtarg_height; nuclear@12: static unsigned int fbo, tex[2], zbuf; nuclear@12: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@3: glutInitWindowSize(1280, 800); nuclear@0: glutInit(&argc, argv); nuclear@1: nuclear@1: if(!parse_args(argc, argv)) { nuclear@1: return 1; nuclear@1: } nuclear@1: nuclear@12: glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); nuclear@12: glutCreateWindow("oculus vr test 01"); nuclear@12: nuclear@12: width = glutGet(GLUT_WINDOW_WIDTH); nuclear@12: height = glutGet(GLUT_WINDOW_HEIGHT); nuclear@0: nuclear@0: glutDisplayFunc(disp); nuclear@0: glutIdleFunc(idle); nuclear@0: glutReshapeFunc(reshape); nuclear@0: glutKeyboardFunc(keyb); nuclear@8: glutKeyboardUpFunc(keyup); nuclear@8: glutMouseFunc(mouse); nuclear@8: glutMotionFunc(motion); nuclear@0: glutSpaceballRotateFunc(sball_rotate); nuclear@0: nuclear@0: if(!init()) { nuclear@0: return 1; nuclear@0: } nuclear@0: atexit(cleanup); nuclear@0: nuclear@0: glutMainLoop(); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static bool init() nuclear@0: { nuclear@9: glewInit(); // this must be first nuclear@9: nuclear@0: glEnable(GL_DEPTH_TEST); nuclear@0: glEnable(GL_LIGHTING); nuclear@0: glEnable(GL_CULL_FACE); nuclear@0: nuclear@0: glEnable(GL_LIGHT0); nuclear@0: glEnable(GL_LIGHTING); nuclear@0: nuclear@11: // y = height of neck nuclear@11: cam.input_move(0, 1.65, 0); nuclear@9: nuclear@12: if(use_vr) { nuclear@12: if(vr_init(VR_INIT_OCULUS) == -1) { nuclear@12: return false; nuclear@12: } nuclear@12: nuclear@12: // reshape to the size of the VR display nuclear@12: int xsz = vr_get_width(); nuclear@12: int ysz = vr_get_height(); nuclear@12: nuclear@12: glutReshapeWindow(xsz, ysz); nuclear@12: nuclear@12: rtarg_width = (xsz + xsz / 2) / 2; nuclear@12: rtarg_height = ysz + ysz / 2; nuclear@12: } else { nuclear@12: rtarg_width = width; nuclear@12: rtarg_height = height; nuclear@0: } nuclear@12: nuclear@13: printf("render target: %dx%d\n", rtarg_width, rtarg_height); nuclear@13: nuclear@12: // create render targets for each eye nuclear@12: GLenum wrap_mode = GL_CLAMP_TO_EDGE; nuclear@12: if(!GLEW_SGIS_texture_edge_clamp) { nuclear@12: wrap_mode = GL_CLAMP; nuclear@12: } nuclear@12: nuclear@12: glGenTextures(2, tex); nuclear@12: for(int i=0; i<2; i++) { nuclear@12: glBindTexture(GL_TEXTURE_2D, tex[i]); nuclear@12: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@12: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@12: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode); nuclear@12: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode); nuclear@12: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_width, rtarg_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); nuclear@12: } nuclear@12: nuclear@12: // create the depth render buffer nuclear@12: glGenRenderbuffers(1, &zbuf); nuclear@12: glBindRenderbuffer(GL_RENDERBUFFER, zbuf); nuclear@12: glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_width, rtarg_height); nuclear@12: nuclear@12: // create the FBO nuclear@12: glGenFramebuffers(1, &fbo); nuclear@12: glBindFramebuffer(GL_FRAMEBUFFER, fbo); nuclear@12: glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0); nuclear@12: glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf); nuclear@12: nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: static void cleanup() nuclear@0: { nuclear@12: glDeleteTextures(2, tex); nuclear@12: glDeleteRenderbuffers(1, &zbuf); nuclear@12: glDeleteFramebuffers(1, &fbo); nuclear@1: vr_shutdown(); nuclear@0: } nuclear@0: nuclear@14: static void handle_input(float dt) nuclear@14: { nuclear@14: Vector3 inpv; nuclear@14: float offs = dt * 2.0; nuclear@14: nuclear@14: if(keystate['w'] || keystate['W']) { nuclear@14: inpv.z -= offs; nuclear@14: } nuclear@14: if(keystate['s'] || keystate['S']) { nuclear@14: inpv.z += offs; nuclear@14: } nuclear@14: if(keystate['d'] || keystate['D']) { nuclear@14: inpv.x += offs; nuclear@14: } nuclear@14: if(keystate['a'] || keystate['A']) { nuclear@14: inpv.x -= offs; nuclear@14: } nuclear@14: nuclear@14: cam.input_move(inpv.x, inpv.y, inpv.z); nuclear@14: } nuclear@14: nuclear@0: static void disp() nuclear@0: { nuclear@14: static long prev_msec; nuclear@14: long msec = glutGet(GLUT_ELAPSED_TIME); nuclear@14: float dt = (msec - prev_msec) / 1000.0; nuclear@14: prev_msec = msec; nuclear@4: nuclear@14: handle_input(dt); nuclear@12: cam.track_vr(); nuclear@0: nuclear@13: /*glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@13: float fov = RAD_TO_DEG(vr_get_fov()); nuclear@13: gluPerspective(fov, (float)rtarg_width / (float)rtarg_height, 0.25, 500.0);*/ nuclear@13: float proj_matrix[16]; nuclear@13: nuclear@13: float eye_dist = vr_get_eyedist(); nuclear@12: nuclear@12: glViewport(0, 0, rtarg_width, rtarg_height); nuclear@12: nuclear@12: glClearColor(0.1, 0.1, 0.1, 1.0); nuclear@12: nuclear@12: // draw left view nuclear@12: glBindFramebuffer(GL_FRAMEBUFFER, fbo); nuclear@12: glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0); nuclear@12: nuclear@12: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@0: nuclear@13: glMatrixMode(GL_PROJECTION); nuclear@13: vr_get_proj_matrix(proj_matrix, VR_EYE_LEFT); nuclear@13: glLoadTransposeMatrixf(proj_matrix); nuclear@13: nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@9: glLoadIdentity(); nuclear@13: glTranslatef(eye_dist / 2.0, 0, 0); nuclear@12: cam.use_inverse(); nuclear@12: draw_scene(); nuclear@0: nuclear@12: nuclear@12: // draw right view nuclear@12: glBindFramebuffer(GL_FRAMEBUFFER, fbo); nuclear@12: glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[1], 0); nuclear@12: nuclear@12: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@12: nuclear@13: glMatrixMode(GL_PROJECTION); nuclear@13: vr_get_proj_matrix(proj_matrix, VR_EYE_RIGHT); nuclear@13: glLoadTransposeMatrixf(proj_matrix); nuclear@13: nuclear@12: glMatrixMode(GL_MODELVIEW); nuclear@12: glLoadIdentity(); nuclear@13: glTranslatef(-eye_dist / 2.0, 0, 0); nuclear@9: cam.use_inverse(); nuclear@12: draw_scene(); nuclear@9: nuclear@12: // return to the regular window framebuffer nuclear@12: glBindFramebuffer(GL_FRAMEBUFFER, 0); nuclear@12: glViewport(0, 0, width, height); nuclear@12: nuclear@12: glClearColor(0, 0, 0, 0); nuclear@12: glClear(GL_COLOR_BUFFER_BIT); nuclear@12: nuclear@12: vr_draw_eye(tex[0], VR_EYE_LEFT); nuclear@12: vr_draw_eye(tex[1], VR_EYE_RIGHT); nuclear@9: nuclear@9: glutSwapBuffers(); nuclear@9: assert(glGetError() == GL_NO_ERROR); nuclear@13: nuclear@13: glFinish(); nuclear@9: } nuclear@9: nuclear@12: nuclear@12: static void draw_scene() nuclear@12: { nuclear@12: float lpos[] = {0, 60, 0, 1}; nuclear@12: glLightfv(GL_LIGHT0, GL_POSITION, lpos); nuclear@12: nuclear@14: draw_grid(50.0, 2.5); nuclear@13: nuclear@12: static Vector2 teapos[] = { nuclear@12: Vector2(-8, 8), Vector2(8, 8), Vector2(8, -8), Vector2(-8, -8) nuclear@12: }; nuclear@12: nuclear@12: for(int i=0; i<4; i++) { nuclear@12: glPushMatrix(); nuclear@12: glTranslatef(teapos[i].x, 0, teapos[i].y); nuclear@12: draw_teapot(); nuclear@12: glPopMatrix(); nuclear@12: } nuclear@12: nuclear@13: draw_squares(); nuclear@12: } nuclear@12: nuclear@9: static void draw_teapot() nuclear@9: { nuclear@9: static int tealist; nuclear@9: nuclear@9: if(!tealist) { nuclear@9: tealist = glGenLists(1); nuclear@9: glNewList(tealist, GL_COMPILE); nuclear@9: glutSolidTeapot(1.0); nuclear@9: glEndList(); nuclear@9: } nuclear@9: nuclear@9: glFrontFace(GL_CW); nuclear@9: glCallList(tealist); nuclear@9: glFrontFace(GL_CCW); nuclear@9: } nuclear@9: nuclear@13: static void draw_squares() nuclear@13: { nuclear@14: static const int num_sq = 8; nuclear@13: nuclear@13: glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT); nuclear@13: glDisable(GL_LIGHTING); nuclear@13: nuclear@13: glMatrixMode(GL_MODELVIEW); nuclear@13: glPushMatrix(); nuclear@13: glTranslatef(0, 1, 0); nuclear@13: nuclear@13: nuclear@14: glLineWidth(2.0); nuclear@13: glColor3f(1.0, 0.7, 0.2); nuclear@13: nuclear@13: float zdist = 2.0; nuclear@13: for(int i=0; i