oculus1

annotate src/main.cc @ 12:d797639e0234

moving on to the distortion... not correct yet
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 20 Sep 2013 10:14:29 +0300
parents 39ec672a5158
children 464e1d135d68
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@1 3 #include <string.h>
nuclear@0 4 #include <assert.h>
nuclear@8 5 #include "opengl.h"
nuclear@1 6 #include "vr.h"
nuclear@0 7 #include "camera.h"
nuclear@0 8
nuclear@0 9 static bool init();
nuclear@0 10 static void cleanup();
nuclear@0 11 static void disp();
nuclear@9 12 static void draw_scene();
nuclear@12 13 static void draw_teapot();
nuclear@12 14 static void draw_grid(float size, float spacing);
nuclear@0 15 static void idle();
nuclear@0 16 static void reshape(int x, int y);
nuclear@0 17 static void keyb(unsigned char key, int x, int y);
nuclear@8 18 static void keyup(unsigned char key, int x, int y);
nuclear@8 19 static void mouse(int bn, int st, int x, int y);
nuclear@8 20 static void motion(int x, int y);
nuclear@8 21 static void passive(int x, int y);
nuclear@0 22 static void sball_rotate(int rx, int ry, int rz);
nuclear@1 23 static bool parse_args(int argc, char **argv);
nuclear@0 24
nuclear@10 25 static VRFpsCamera cam;
nuclear@0 26 static int width, height;
nuclear@1 27 static bool use_vr = false;
nuclear@8 28 static bool mouselook = false;
nuclear@8 29
nuclear@8 30 static bool keystate[256];
nuclear@8 31
nuclear@12 32 static int rtarg_width, rtarg_height;
nuclear@12 33 static unsigned int fbo, tex[2], zbuf;
nuclear@12 34
nuclear@0 35
nuclear@0 36 int main(int argc, char **argv)
nuclear@0 37 {
nuclear@3 38 glutInitWindowSize(1280, 800);
nuclear@0 39 glutInit(&argc, argv);
nuclear@1 40
nuclear@1 41 if(!parse_args(argc, argv)) {
nuclear@1 42 return 1;
nuclear@1 43 }
nuclear@1 44
nuclear@12 45 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
nuclear@12 46 glutCreateWindow("oculus vr test 01");
nuclear@12 47
nuclear@12 48 width = glutGet(GLUT_WINDOW_WIDTH);
nuclear@12 49 height = glutGet(GLUT_WINDOW_HEIGHT);
nuclear@0 50
nuclear@0 51 glutDisplayFunc(disp);
nuclear@0 52 glutIdleFunc(idle);
nuclear@0 53 glutReshapeFunc(reshape);
nuclear@0 54 glutKeyboardFunc(keyb);
nuclear@8 55 glutKeyboardUpFunc(keyup);
nuclear@8 56 glutMouseFunc(mouse);
nuclear@8 57 glutMotionFunc(motion);
nuclear@0 58 glutSpaceballRotateFunc(sball_rotate);
nuclear@0 59
nuclear@0 60 if(!init()) {
nuclear@0 61 return 1;
nuclear@0 62 }
nuclear@0 63 atexit(cleanup);
nuclear@0 64
nuclear@0 65 glutMainLoop();
nuclear@0 66 return 0;
nuclear@0 67 }
nuclear@0 68
nuclear@0 69 static bool init()
nuclear@0 70 {
nuclear@9 71 glewInit(); // this must be first
nuclear@9 72
nuclear@0 73 glEnable(GL_DEPTH_TEST);
nuclear@0 74 glEnable(GL_LIGHTING);
nuclear@0 75 glEnable(GL_CULL_FACE);
nuclear@0 76
nuclear@0 77 glEnable(GL_LIGHT0);
nuclear@0 78 glEnable(GL_LIGHTING);
nuclear@0 79
nuclear@11 80 // y = height of neck
nuclear@11 81 cam.input_move(0, 1.65, 0);
nuclear@9 82
nuclear@12 83 if(use_vr) {
nuclear@12 84 if(vr_init(VR_INIT_OCULUS) == -1) {
nuclear@12 85 return false;
nuclear@12 86 }
nuclear@12 87
nuclear@12 88 // reshape to the size of the VR display
nuclear@12 89 int xsz = vr_get_width();
nuclear@12 90 int ysz = vr_get_height();
nuclear@12 91
nuclear@12 92 glutReshapeWindow(xsz, ysz);
nuclear@12 93
nuclear@12 94 rtarg_width = (xsz + xsz / 2) / 2;
nuclear@12 95 rtarg_height = ysz + ysz / 2;
nuclear@12 96 } else {
nuclear@12 97 rtarg_width = width;
nuclear@12 98 rtarg_height = height;
nuclear@0 99 }
nuclear@12 100
nuclear@12 101 // create render targets for each eye
nuclear@12 102 GLenum wrap_mode = GL_CLAMP_TO_EDGE;
nuclear@12 103 if(!GLEW_SGIS_texture_edge_clamp) {
nuclear@12 104 wrap_mode = GL_CLAMP;
nuclear@12 105 }
nuclear@12 106
nuclear@12 107 glGenTextures(2, tex);
nuclear@12 108 for(int i=0; i<2; i++) {
nuclear@12 109 glBindTexture(GL_TEXTURE_2D, tex[i]);
nuclear@12 110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@12 111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@12 112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode);
nuclear@12 113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode);
nuclear@12 114 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_width, rtarg_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
nuclear@12 115 }
nuclear@12 116
nuclear@12 117 // create the depth render buffer
nuclear@12 118 glGenRenderbuffers(1, &zbuf);
nuclear@12 119 glBindRenderbuffer(GL_RENDERBUFFER, zbuf);
nuclear@12 120 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_width, rtarg_height);
nuclear@12 121
nuclear@12 122 // create the FBO
nuclear@12 123 glGenFramebuffers(1, &fbo);
nuclear@12 124 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@12 125 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
nuclear@12 126 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf);
nuclear@12 127
nuclear@0 128 return true;
nuclear@0 129 }
nuclear@0 130
nuclear@0 131 static void cleanup()
nuclear@0 132 {
nuclear@12 133 glDeleteTextures(2, tex);
nuclear@12 134 glDeleteRenderbuffers(1, &zbuf);
nuclear@12 135 glDeleteFramebuffers(1, &fbo);
nuclear@1 136 vr_shutdown();
nuclear@0 137 }
nuclear@0 138
nuclear@0 139 static void disp()
nuclear@0 140 {
nuclear@4 141 unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
nuclear@4 142
nuclear@12 143 cam.track_vr();
nuclear@0 144
nuclear@0 145 glMatrixMode(GL_PROJECTION);
nuclear@0 146 glLoadIdentity();
nuclear@12 147 gluPerspective(RAD_TO_DEG(vr_get_fov()), (float)rtarg_width / (float)rtarg_height, 0.5, 500.0);
nuclear@12 148
nuclear@12 149 glViewport(0, 0, rtarg_width, rtarg_height);
nuclear@12 150
nuclear@12 151 glClearColor(0.1, 0.1, 0.1, 1.0);
nuclear@12 152
nuclear@12 153 // draw left view
nuclear@12 154 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@12 155 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
nuclear@12 156
nuclear@12 157 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@0 158
nuclear@0 159 glMatrixMode(GL_MODELVIEW);
nuclear@9 160 glLoadIdentity();
nuclear@12 161 cam.use_inverse();
nuclear@12 162 glTranslatef(0.32, 0, 0);
nuclear@12 163 draw_scene();
nuclear@0 164
nuclear@12 165
nuclear@12 166 // draw right view
nuclear@12 167 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@12 168 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[1], 0);
nuclear@12 169
nuclear@12 170 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@12 171
nuclear@12 172 glMatrixMode(GL_MODELVIEW);
nuclear@12 173 glLoadIdentity();
nuclear@9 174 cam.use_inverse();
nuclear@12 175 glTranslatef(-0.32, 0, 0);
nuclear@12 176 draw_scene();
nuclear@9 177
nuclear@12 178 // return to the regular window framebuffer
nuclear@12 179 glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@12 180 glViewport(0, 0, width, height);
nuclear@12 181
nuclear@12 182 glClearColor(0, 0, 0, 0);
nuclear@12 183 glClear(GL_COLOR_BUFFER_BIT);
nuclear@12 184
nuclear@12 185 vr_draw_eye(tex[0], VR_EYE_LEFT);
nuclear@12 186 vr_draw_eye(tex[1], VR_EYE_RIGHT);
nuclear@9 187
nuclear@9 188 glutSwapBuffers();
nuclear@9 189 assert(glGetError() == GL_NO_ERROR);
nuclear@9 190 }
nuclear@9 191
nuclear@12 192
nuclear@12 193 static void draw_scene()
nuclear@12 194 {
nuclear@12 195 float lpos[] = {0, 60, 0, 1};
nuclear@12 196 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
nuclear@12 197
nuclear@12 198 static Vector2 teapos[] = {
nuclear@12 199 Vector2(-8, 8), Vector2(8, 8), Vector2(8, -8), Vector2(-8, -8)
nuclear@12 200 };
nuclear@12 201
nuclear@12 202 for(int i=0; i<4; i++) {
nuclear@12 203 glPushMatrix();
nuclear@12 204 glTranslatef(teapos[i].x, 0, teapos[i].y);
nuclear@12 205 draw_teapot();
nuclear@12 206 glPopMatrix();
nuclear@12 207 }
nuclear@12 208
nuclear@12 209 draw_grid(100.0, 2.5);
nuclear@12 210 }
nuclear@12 211
nuclear@9 212 static void draw_teapot()
nuclear@9 213 {
nuclear@9 214 static int tealist;
nuclear@9 215
nuclear@9 216 if(!tealist) {
nuclear@9 217 tealist = glGenLists(1);
nuclear@9 218 glNewList(tealist, GL_COMPILE);
nuclear@9 219 glutSolidTeapot(1.0);
nuclear@9 220 glEndList();
nuclear@9 221 }
nuclear@9 222
nuclear@9 223 glFrontFace(GL_CW);
nuclear@9 224 glCallList(tealist);
nuclear@9 225 glFrontFace(GL_CCW);
nuclear@9 226 }
nuclear@9 227
nuclear@12 228 static void draw_grid(float size, float spacing)
nuclear@9 229 {
nuclear@9 230 int num_lines = size / spacing;
nuclear@9 231 float dist = size / 2.0;
nuclear@9 232
nuclear@9 233 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
nuclear@9 234 glDisable(GL_LIGHTING);
nuclear@9 235
nuclear@9 236 glLineWidth(1.0);
nuclear@9 237
nuclear@9 238 glBegin(GL_LINES);
nuclear@9 239 glColor3f(0.4, 0.4, 0.4);
nuclear@9 240
nuclear@9 241 float x = -dist;
nuclear@9 242 for(int i=0; i<=num_lines; i++) {
nuclear@9 243 if(i != num_lines / 2) {
nuclear@9 244 glVertex3f(-dist, 0, x);
nuclear@9 245 glVertex3f(dist, 0, x);
nuclear@9 246 glVertex3f(x, 0, -dist);
nuclear@9 247 glVertex3f(x, 0, dist);
nuclear@9 248 }
nuclear@9 249 x += spacing;
nuclear@9 250 }
nuclear@9 251 glEnd();
nuclear@9 252
nuclear@9 253 glLineWidth(2.0);
nuclear@9 254
nuclear@9 255 glBegin(GL_LINES);
nuclear@9 256 glColor3f(1.0, 0, 0);
nuclear@9 257 glVertex3f(-dist, 0, 0);
nuclear@9 258 glVertex3f(dist, 0, 0);
nuclear@9 259 glColor3f(0, 1.0, 0);
nuclear@9 260 glVertex3f(0, 0, -dist);
nuclear@9 261 glVertex3f(0, 0, dist);
nuclear@9 262 glEnd();
nuclear@9 263
nuclear@9 264 glPopAttrib();
nuclear@9 265 }
nuclear@9 266
nuclear@0 267 static void idle()
nuclear@0 268 {
nuclear@0 269 glutPostRedisplay();
nuclear@0 270 }
nuclear@0 271
nuclear@0 272
nuclear@0 273 static void reshape(int x, int y)
nuclear@0 274 {
nuclear@0 275 width = x;
nuclear@0 276 height = y;
nuclear@12 277
nuclear@12 278 if(!use_vr) {
nuclear@12 279 rtarg_width = width;
nuclear@12 280 rtarg_height = height;
nuclear@12 281 }
nuclear@0 282 }
nuclear@0 283
nuclear@0 284 static void keyb(unsigned char key, int x, int y)
nuclear@0 285 {
nuclear@0 286 switch(key) {
nuclear@0 287 case 27:
nuclear@0 288 exit(0);
nuclear@8 289
nuclear@8 290 case 'm':
nuclear@8 291 mouselook = !mouselook;
nuclear@8 292 if(mouselook) {
nuclear@8 293 glutPassiveMotionFunc(passive);
nuclear@8 294 glutSetCursor(GLUT_CURSOR_NONE);
nuclear@8 295 glutWarpPointer(width / 2, height / 2);
nuclear@8 296 } else {
nuclear@8 297 glutPassiveMotionFunc(0);
nuclear@8 298 glutSetCursor(GLUT_CURSOR_INHERIT);
nuclear@8 299 }
nuclear@8 300 break;
nuclear@12 301
nuclear@12 302 case 'f':
nuclear@12 303 {
nuclear@12 304 static bool fullscreen;
nuclear@12 305 static int prev_xsz, prev_ysz;
nuclear@12 306
nuclear@12 307 fullscreen = !fullscreen;
nuclear@12 308
nuclear@12 309 if(fullscreen) {
nuclear@12 310 prev_xsz = width;
nuclear@12 311 prev_ysz = height;
nuclear@12 312 glutFullScreen();
nuclear@12 313 } else {
nuclear@12 314 glutReshapeWindow(prev_xsz, prev_ysz);
nuclear@12 315 }
nuclear@12 316 glutPostRedisplay();
nuclear@12 317 }
nuclear@12 318 break;
nuclear@0 319 }
nuclear@8 320
nuclear@8 321 keystate[key] = true;
nuclear@8 322 glutPostRedisplay();
nuclear@8 323 }
nuclear@8 324
nuclear@8 325 static void keyup(unsigned char key, int x, int y)
nuclear@8 326 {
nuclear@8 327 keystate[key] = false;
nuclear@8 328 glutPostRedisplay();
nuclear@8 329 }
nuclear@8 330
nuclear@8 331 static bool bnstate[32];
nuclear@8 332 static int prev_x, prev_y;
nuclear@8 333
nuclear@8 334 static void mouse(int bn, int st, int x, int y)
nuclear@8 335 {
nuclear@8 336 prev_x = x;
nuclear@8 337 prev_y = y;
nuclear@8 338 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
nuclear@8 339 }
nuclear@8 340
nuclear@8 341 static void motion(int x, int y)
nuclear@8 342 {
nuclear@8 343 if(mouselook) {
nuclear@8 344 // just call passive, it does what we need
nuclear@8 345 passive(x, y);
nuclear@8 346 }
nuclear@8 347 }
nuclear@8 348
nuclear@8 349 static void passive(int x, int y)
nuclear@8 350 {
nuclear@8 351 // no need to test mouselook; this callback is only set when mouselook is enabled
nuclear@8 352 int center_x = width / 2;
nuclear@8 353 int center_y = height / 2;
nuclear@8 354
nuclear@8 355 int dx = x - center_x;
nuclear@8 356 int dy = y - center_y;
nuclear@8 357
nuclear@8 358 if(!dx && !dy) {
nuclear@8 359 return;
nuclear@8 360 }
nuclear@8 361
nuclear@9 362 float dtheta_deg = dy * 0.1;
nuclear@9 363 float dphi_deg = dx * 0.1;
nuclear@9 364
nuclear@9 365 cam.input_rotate(DEG_TO_RAD(dtheta_deg), DEG_TO_RAD(dphi_deg), 0);
nuclear@9 366
nuclear@8 367 glutPostRedisplay();
nuclear@8 368 glutWarpPointer(center_x, center_y);
nuclear@0 369 }
nuclear@0 370
nuclear@0 371 static void sball_rotate(int rx, int ry, int rz)
nuclear@0 372 {
nuclear@0 373 }
nuclear@1 374
nuclear@1 375 static bool parse_args(int argc, char **argv)
nuclear@1 376 {
nuclear@1 377 for(int i=1; i<argc; i++) {
nuclear@1 378 if(argv[i][0] == '-') {
nuclear@1 379 if(strcmp(argv[i], "-vr") == 0) {
nuclear@1 380 use_vr = true;
nuclear@1 381 } else if(strcmp(argv[i], "-novr") == 0) {
nuclear@1 382 use_vr = false;
nuclear@1 383 } else {
nuclear@1 384 fprintf(stderr, "invalid option: %s\n", argv[i]);
nuclear@1 385 return false;
nuclear@1 386 }
nuclear@1 387 } else {
nuclear@1 388 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
nuclear@1 389 return false;
nuclear@1 390 }
nuclear@1 391 }
nuclear@1 392 return true;
nuclear@1 393 }