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@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@9: static FpsCamera 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@0: 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@9: glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE); nuclear@0: glutCreateWindow("oculus test 01"); 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@9: if(GLEW_ARB_multisample) { nuclear@9: glEnable(GL_MULTISAMPLE); nuclear@9: } nuclear@8: 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@9: cam.input_move(0, 1.75, 0); nuclear@9: nuclear@1: if(vr_init(VR_INIT_OCULUS) == -1) { nuclear@5: return false; nuclear@0: } nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: static void cleanup() nuclear@0: { nuclear@1: vr_shutdown(); nuclear@0: } nuclear@0: nuclear@0: static void disp() nuclear@0: { nuclear@4: unsigned int msec = glutGet(GLUT_ELAPSED_TIME); nuclear@4: nuclear@3: // test rift sensor nuclear@3: float quat[4], euler[3]; nuclear@3: nuclear@3: vr_get_rotation(quat); nuclear@3: vr_get_rotation_euler(euler); nuclear@3: nuclear@5: Quaternion qrot(quat[3], quat[0], quat[1], quat[2]); nuclear@5: nuclear@4: static unsigned int prev_print; nuclear@4: if(msec - prev_print > 1000) { nuclear@9: printf("q(%.3f + %.3fi + %.3fj + %.3fk)", quat[3], quat[0], quat[1], quat[2]); nuclear@4: printf(" - euler(%.3f %.3f %.3f)\n", euler[0], euler[1], euler[2]); nuclear@4: prev_print = msec; nuclear@4: } nuclear@3: nuclear@0: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@0: gluPerspective(45.0, (float)width / (float)height, 0.5, 500.0); nuclear@0: nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@9: glLoadIdentity(); nuclear@0: nuclear@9: Matrix4x4 mat = qrot.inverse().get_rotation_matrix(); nuclear@9: load_matrix(mat); nuclear@9: nuclear@9: cam.use_inverse(); nuclear@9: nuclear@9: draw_scene(); nuclear@9: nuclear@9: glutSwapBuffers(); nuclear@9: assert(glGetError() == GL_NO_ERROR); nuclear@9: } nuclear@9: 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@9: void draw_grid(float size, float spacing) nuclear@9: { nuclear@9: int num_lines = size / spacing; nuclear@9: float dist = size / 2.0; nuclear@9: nuclear@9: glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT); nuclear@9: glDisable(GL_LIGHTING); nuclear@9: nuclear@9: glLineWidth(1.0); nuclear@9: nuclear@9: glBegin(GL_LINES); nuclear@9: glColor3f(0.4, 0.4, 0.4); nuclear@9: nuclear@9: float x = -dist; nuclear@9: for(int i=0; i<=num_lines; i++) { nuclear@9: if(i != num_lines / 2) { nuclear@9: glVertex3f(-dist, 0, x); nuclear@9: glVertex3f(dist, 0, x); nuclear@9: glVertex3f(x, 0, -dist); nuclear@9: glVertex3f(x, 0, dist); nuclear@9: } nuclear@9: x += spacing; nuclear@9: } nuclear@9: glEnd(); nuclear@9: nuclear@9: glLineWidth(2.0); nuclear@9: nuclear@9: glBegin(GL_LINES); nuclear@9: glColor3f(1.0, 0, 0); nuclear@9: glVertex3f(-dist, 0, 0); nuclear@9: glVertex3f(dist, 0, 0); nuclear@9: glColor3f(0, 1.0, 0); nuclear@9: glVertex3f(0, 0, -dist); nuclear@9: glVertex3f(0, 0, dist); nuclear@9: glEnd(); nuclear@9: nuclear@9: glPopAttrib(); nuclear@9: } nuclear@9: nuclear@9: nuclear@9: static void draw_scene() nuclear@9: { nuclear@0: float lpos[] = {0, 60, 0, 1}; nuclear@0: glLightfv(GL_LIGHT0, GL_POSITION, lpos); nuclear@0: nuclear@9: static Vector2 teapos[] = { nuclear@9: Vector2(-8, 8), Vector2(8, 8), Vector2(8, -8), Vector2(-8, -8) nuclear@9: }; nuclear@8: nuclear@9: for(int i=0; i<4; i++) { nuclear@9: glPushMatrix(); nuclear@9: glTranslatef(teapos[i].x, 0, teapos[i].y); nuclear@9: draw_teapot(); nuclear@9: glPopMatrix(); nuclear@9: } nuclear@0: nuclear@9: draw_grid(100.0, 2.5); nuclear@0: } nuclear@0: nuclear@0: static void idle() nuclear@0: { nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: static void reshape(int x, int y) nuclear@0: { nuclear@0: width = x; nuclear@0: height = y; nuclear@0: } nuclear@0: nuclear@0: static void keyb(unsigned char key, int x, int y) nuclear@0: { nuclear@0: switch(key) { nuclear@0: case 27: nuclear@0: exit(0); nuclear@8: nuclear@8: case 'm': nuclear@8: mouselook = !mouselook; nuclear@8: if(mouselook) { nuclear@8: glutPassiveMotionFunc(passive); nuclear@8: glutSetCursor(GLUT_CURSOR_NONE); nuclear@8: glutWarpPointer(width / 2, height / 2); nuclear@8: } else { nuclear@8: glutPassiveMotionFunc(0); nuclear@8: glutSetCursor(GLUT_CURSOR_INHERIT); nuclear@8: } nuclear@8: break; nuclear@0: } nuclear@8: nuclear@8: keystate[key] = true; nuclear@8: glutPostRedisplay(); nuclear@8: } nuclear@8: nuclear@8: static void keyup(unsigned char key, int x, int y) nuclear@8: { nuclear@8: keystate[key] = false; nuclear@8: glutPostRedisplay(); nuclear@8: } nuclear@8: nuclear@8: static bool bnstate[32]; nuclear@8: static int prev_x, prev_y; nuclear@8: nuclear@8: static void mouse(int bn, int st, int x, int y) nuclear@8: { nuclear@8: prev_x = x; nuclear@8: prev_y = y; nuclear@8: bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN; nuclear@8: } nuclear@8: nuclear@8: static void motion(int x, int y) nuclear@8: { nuclear@8: if(mouselook) { nuclear@8: // just call passive, it does what we need nuclear@8: passive(x, y); nuclear@8: } nuclear@8: } nuclear@8: nuclear@8: static void passive(int x, int y) nuclear@8: { nuclear@8: // no need to test mouselook; this callback is only set when mouselook is enabled nuclear@8: int center_x = width / 2; nuclear@8: int center_y = height / 2; nuclear@8: nuclear@8: int dx = x - center_x; nuclear@8: int dy = y - center_y; nuclear@8: nuclear@8: if(!dx && !dy) { nuclear@8: return; nuclear@8: } nuclear@8: nuclear@9: float dtheta_deg = dy * 0.1; nuclear@9: float dphi_deg = dx * 0.1; nuclear@9: nuclear@9: cam.input_rotate(DEG_TO_RAD(dtheta_deg), DEG_TO_RAD(dphi_deg), 0); nuclear@9: nuclear@8: glutPostRedisplay(); nuclear@8: glutWarpPointer(center_x, center_y); nuclear@0: } nuclear@0: nuclear@0: static void sball_rotate(int rx, int ry, int rz) nuclear@0: { nuclear@0: } nuclear@1: nuclear@1: static bool parse_args(int argc, char **argv) nuclear@1: { nuclear@1: for(int i=1; i