oculus1

annotate src/main.cc @ 14:cceffea995a4

implemented wasd controls and clamping of the texcoords to [0, 1]
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 21 Sep 2013 03:35:53 +0300
parents 464e1d135d68
children f3672317e5c2
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@13 14 static void draw_squares();
nuclear@12 15 static void draw_grid(float size, float spacing);
nuclear@0 16 static void idle();
nuclear@0 17 static void reshape(int x, int y);
nuclear@0 18 static void keyb(unsigned char key, int x, int y);
nuclear@8 19 static void keyup(unsigned char key, int x, int y);
nuclear@8 20 static void mouse(int bn, int st, int x, int y);
nuclear@8 21 static void motion(int x, int y);
nuclear@8 22 static void passive(int x, int y);
nuclear@0 23 static void sball_rotate(int rx, int ry, int rz);
nuclear@1 24 static bool parse_args(int argc, char **argv);
nuclear@0 25
nuclear@10 26 static VRFpsCamera cam;
nuclear@0 27 static int width, height;
nuclear@1 28 static bool use_vr = false;
nuclear@8 29 static bool mouselook = false;
nuclear@8 30
nuclear@8 31 static bool keystate[256];
nuclear@8 32
nuclear@12 33 static int rtarg_width, rtarg_height;
nuclear@12 34 static unsigned int fbo, tex[2], zbuf;
nuclear@12 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@13 101 printf("render target: %dx%d\n", rtarg_width, rtarg_height);
nuclear@13 102
nuclear@12 103 // create render targets for each eye
nuclear@12 104 GLenum wrap_mode = GL_CLAMP_TO_EDGE;
nuclear@12 105 if(!GLEW_SGIS_texture_edge_clamp) {
nuclear@12 106 wrap_mode = GL_CLAMP;
nuclear@12 107 }
nuclear@12 108
nuclear@12 109 glGenTextures(2, tex);
nuclear@12 110 for(int i=0; i<2; i++) {
nuclear@12 111 glBindTexture(GL_TEXTURE_2D, tex[i]);
nuclear@12 112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@12 113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@12 114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode);
nuclear@12 115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode);
nuclear@12 116 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_width, rtarg_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
nuclear@12 117 }
nuclear@12 118
nuclear@12 119 // create the depth render buffer
nuclear@12 120 glGenRenderbuffers(1, &zbuf);
nuclear@12 121 glBindRenderbuffer(GL_RENDERBUFFER, zbuf);
nuclear@12 122 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_width, rtarg_height);
nuclear@12 123
nuclear@12 124 // create the FBO
nuclear@12 125 glGenFramebuffers(1, &fbo);
nuclear@12 126 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@12 127 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
nuclear@12 128 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf);
nuclear@12 129
nuclear@0 130 return true;
nuclear@0 131 }
nuclear@0 132
nuclear@0 133 static void cleanup()
nuclear@0 134 {
nuclear@12 135 glDeleteTextures(2, tex);
nuclear@12 136 glDeleteRenderbuffers(1, &zbuf);
nuclear@12 137 glDeleteFramebuffers(1, &fbo);
nuclear@1 138 vr_shutdown();
nuclear@0 139 }
nuclear@0 140
nuclear@14 141 static void handle_input(float dt)
nuclear@14 142 {
nuclear@14 143 Vector3 inpv;
nuclear@14 144 float offs = dt * 2.0;
nuclear@14 145
nuclear@14 146 if(keystate['w'] || keystate['W']) {
nuclear@14 147 inpv.z -= offs;
nuclear@14 148 }
nuclear@14 149 if(keystate['s'] || keystate['S']) {
nuclear@14 150 inpv.z += offs;
nuclear@14 151 }
nuclear@14 152 if(keystate['d'] || keystate['D']) {
nuclear@14 153 inpv.x += offs;
nuclear@14 154 }
nuclear@14 155 if(keystate['a'] || keystate['A']) {
nuclear@14 156 inpv.x -= offs;
nuclear@14 157 }
nuclear@14 158
nuclear@14 159 cam.input_move(inpv.x, inpv.y, inpv.z);
nuclear@14 160 }
nuclear@14 161
nuclear@0 162 static void disp()
nuclear@0 163 {
nuclear@14 164 static long prev_msec;
nuclear@14 165 long msec = glutGet(GLUT_ELAPSED_TIME);
nuclear@14 166 float dt = (msec - prev_msec) / 1000.0;
nuclear@14 167 prev_msec = msec;
nuclear@4 168
nuclear@14 169 handle_input(dt);
nuclear@12 170 cam.track_vr();
nuclear@0 171
nuclear@13 172 /*glMatrixMode(GL_PROJECTION);
nuclear@0 173 glLoadIdentity();
nuclear@13 174 float fov = RAD_TO_DEG(vr_get_fov());
nuclear@13 175 gluPerspective(fov, (float)rtarg_width / (float)rtarg_height, 0.25, 500.0);*/
nuclear@13 176 float proj_matrix[16];
nuclear@13 177
nuclear@13 178 float eye_dist = vr_get_eyedist();
nuclear@12 179
nuclear@12 180 glViewport(0, 0, rtarg_width, rtarg_height);
nuclear@12 181
nuclear@12 182 glClearColor(0.1, 0.1, 0.1, 1.0);
nuclear@12 183
nuclear@12 184 // draw left view
nuclear@12 185 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@12 186 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
nuclear@12 187
nuclear@12 188 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@0 189
nuclear@13 190 glMatrixMode(GL_PROJECTION);
nuclear@13 191 vr_get_proj_matrix(proj_matrix, VR_EYE_LEFT);
nuclear@13 192 glLoadTransposeMatrixf(proj_matrix);
nuclear@13 193
nuclear@0 194 glMatrixMode(GL_MODELVIEW);
nuclear@9 195 glLoadIdentity();
nuclear@13 196 glTranslatef(eye_dist / 2.0, 0, 0);
nuclear@12 197 cam.use_inverse();
nuclear@12 198 draw_scene();
nuclear@0 199
nuclear@12 200
nuclear@12 201 // draw right view
nuclear@12 202 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@12 203 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[1], 0);
nuclear@12 204
nuclear@12 205 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@12 206
nuclear@13 207 glMatrixMode(GL_PROJECTION);
nuclear@13 208 vr_get_proj_matrix(proj_matrix, VR_EYE_RIGHT);
nuclear@13 209 glLoadTransposeMatrixf(proj_matrix);
nuclear@13 210
nuclear@12 211 glMatrixMode(GL_MODELVIEW);
nuclear@12 212 glLoadIdentity();
nuclear@13 213 glTranslatef(-eye_dist / 2.0, 0, 0);
nuclear@9 214 cam.use_inverse();
nuclear@12 215 draw_scene();
nuclear@9 216
nuclear@12 217 // return to the regular window framebuffer
nuclear@12 218 glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@12 219 glViewport(0, 0, width, height);
nuclear@12 220
nuclear@12 221 glClearColor(0, 0, 0, 0);
nuclear@12 222 glClear(GL_COLOR_BUFFER_BIT);
nuclear@12 223
nuclear@12 224 vr_draw_eye(tex[0], VR_EYE_LEFT);
nuclear@12 225 vr_draw_eye(tex[1], VR_EYE_RIGHT);
nuclear@9 226
nuclear@9 227 glutSwapBuffers();
nuclear@9 228 assert(glGetError() == GL_NO_ERROR);
nuclear@13 229
nuclear@13 230 glFinish();
nuclear@9 231 }
nuclear@9 232
nuclear@12 233
nuclear@12 234 static void draw_scene()
nuclear@12 235 {
nuclear@12 236 float lpos[] = {0, 60, 0, 1};
nuclear@12 237 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
nuclear@12 238
nuclear@14 239 draw_grid(50.0, 2.5);
nuclear@13 240
nuclear@12 241 static Vector2 teapos[] = {
nuclear@12 242 Vector2(-8, 8), Vector2(8, 8), Vector2(8, -8), Vector2(-8, -8)
nuclear@12 243 };
nuclear@12 244
nuclear@12 245 for(int i=0; i<4; i++) {
nuclear@12 246 glPushMatrix();
nuclear@12 247 glTranslatef(teapos[i].x, 0, teapos[i].y);
nuclear@12 248 draw_teapot();
nuclear@12 249 glPopMatrix();
nuclear@12 250 }
nuclear@12 251
nuclear@13 252 draw_squares();
nuclear@12 253 }
nuclear@12 254
nuclear@9 255 static void draw_teapot()
nuclear@9 256 {
nuclear@9 257 static int tealist;
nuclear@9 258
nuclear@9 259 if(!tealist) {
nuclear@9 260 tealist = glGenLists(1);
nuclear@9 261 glNewList(tealist, GL_COMPILE);
nuclear@9 262 glutSolidTeapot(1.0);
nuclear@9 263 glEndList();
nuclear@9 264 }
nuclear@9 265
nuclear@9 266 glFrontFace(GL_CW);
nuclear@9 267 glCallList(tealist);
nuclear@9 268 glFrontFace(GL_CCW);
nuclear@9 269 }
nuclear@9 270
nuclear@13 271 static void draw_squares()
nuclear@13 272 {
nuclear@14 273 static const int num_sq = 8;
nuclear@13 274
nuclear@13 275 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
nuclear@13 276 glDisable(GL_LIGHTING);
nuclear@13 277
nuclear@13 278 glMatrixMode(GL_MODELVIEW);
nuclear@13 279 glPushMatrix();
nuclear@13 280 glTranslatef(0, 1, 0);
nuclear@13 281
nuclear@13 282
nuclear@14 283 glLineWidth(2.0);
nuclear@13 284 glColor3f(1.0, 0.7, 0.2);
nuclear@13 285
nuclear@13 286 float zdist = 2.0;
nuclear@13 287 for(int i=0; i<num_sq; i++) {
nuclear@13 288 glBegin(GL_LINE_LOOP);
nuclear@13 289 glVertex3f(-1, -1, -zdist);
nuclear@13 290 glVertex3f(1, -1, -zdist);
nuclear@13 291 glVertex3f(1, 1, -zdist);
nuclear@13 292 glVertex3f(-1, 1, -zdist);
nuclear@13 293 glEnd();
nuclear@13 294
nuclear@14 295 zdist += 2.0;
nuclear@13 296 }
nuclear@13 297
nuclear@13 298 glPopMatrix();
nuclear@13 299 glPopAttrib();
nuclear@13 300 }
nuclear@13 301
nuclear@12 302 static void draw_grid(float size, float spacing)
nuclear@9 303 {
nuclear@9 304 int num_lines = size / spacing;
nuclear@9 305 float dist = size / 2.0;
nuclear@9 306
nuclear@9 307 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
nuclear@9 308 glDisable(GL_LIGHTING);
nuclear@9 309
nuclear@9 310 glLineWidth(1.0);
nuclear@9 311
nuclear@9 312 glBegin(GL_LINES);
nuclear@9 313 glColor3f(0.4, 0.4, 0.4);
nuclear@9 314
nuclear@9 315 float x = -dist;
nuclear@9 316 for(int i=0; i<=num_lines; i++) {
nuclear@9 317 if(i != num_lines / 2) {
nuclear@9 318 glVertex3f(-dist, 0, x);
nuclear@9 319 glVertex3f(dist, 0, x);
nuclear@9 320 glVertex3f(x, 0, -dist);
nuclear@9 321 glVertex3f(x, 0, dist);
nuclear@9 322 }
nuclear@9 323 x += spacing;
nuclear@9 324 }
nuclear@9 325 glEnd();
nuclear@9 326
nuclear@9 327 glLineWidth(2.0);
nuclear@9 328
nuclear@9 329 glBegin(GL_LINES);
nuclear@9 330 glColor3f(1.0, 0, 0);
nuclear@9 331 glVertex3f(-dist, 0, 0);
nuclear@9 332 glVertex3f(dist, 0, 0);
nuclear@9 333 glColor3f(0, 1.0, 0);
nuclear@9 334 glVertex3f(0, 0, -dist);
nuclear@9 335 glVertex3f(0, 0, dist);
nuclear@9 336 glEnd();
nuclear@9 337
nuclear@9 338 glPopAttrib();
nuclear@9 339 }
nuclear@9 340
nuclear@0 341 static void idle()
nuclear@0 342 {
nuclear@0 343 glutPostRedisplay();
nuclear@0 344 }
nuclear@0 345
nuclear@0 346
nuclear@0 347 static void reshape(int x, int y)
nuclear@0 348 {
nuclear@0 349 width = x;
nuclear@0 350 height = y;
nuclear@12 351
nuclear@12 352 if(!use_vr) {
nuclear@12 353 rtarg_width = width;
nuclear@12 354 rtarg_height = height;
nuclear@12 355 }
nuclear@0 356 }
nuclear@0 357
nuclear@0 358 static void keyb(unsigned char key, int x, int y)
nuclear@0 359 {
nuclear@0 360 switch(key) {
nuclear@0 361 case 27:
nuclear@0 362 exit(0);
nuclear@8 363
nuclear@8 364 case 'm':
nuclear@8 365 mouselook = !mouselook;
nuclear@8 366 if(mouselook) {
nuclear@8 367 glutPassiveMotionFunc(passive);
nuclear@8 368 glutSetCursor(GLUT_CURSOR_NONE);
nuclear@8 369 glutWarpPointer(width / 2, height / 2);
nuclear@8 370 } else {
nuclear@8 371 glutPassiveMotionFunc(0);
nuclear@8 372 glutSetCursor(GLUT_CURSOR_INHERIT);
nuclear@8 373 }
nuclear@8 374 break;
nuclear@12 375
nuclear@12 376 case 'f':
nuclear@12 377 {
nuclear@12 378 static bool fullscreen;
nuclear@12 379 static int prev_xsz, prev_ysz;
nuclear@12 380
nuclear@12 381 fullscreen = !fullscreen;
nuclear@12 382
nuclear@12 383 if(fullscreen) {
nuclear@12 384 prev_xsz = width;
nuclear@12 385 prev_ysz = height;
nuclear@12 386 glutFullScreen();
nuclear@12 387 } else {
nuclear@12 388 glutReshapeWindow(prev_xsz, prev_ysz);
nuclear@12 389 }
nuclear@12 390 glutPostRedisplay();
nuclear@12 391 }
nuclear@12 392 break;
nuclear@0 393 }
nuclear@8 394
nuclear@8 395 keystate[key] = true;
nuclear@8 396 glutPostRedisplay();
nuclear@8 397 }
nuclear@8 398
nuclear@8 399 static void keyup(unsigned char key, int x, int y)
nuclear@8 400 {
nuclear@8 401 keystate[key] = false;
nuclear@8 402 glutPostRedisplay();
nuclear@8 403 }
nuclear@8 404
nuclear@8 405 static bool bnstate[32];
nuclear@8 406 static int prev_x, prev_y;
nuclear@8 407
nuclear@8 408 static void mouse(int bn, int st, int x, int y)
nuclear@8 409 {
nuclear@8 410 prev_x = x;
nuclear@8 411 prev_y = y;
nuclear@8 412 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
nuclear@8 413 }
nuclear@8 414
nuclear@8 415 static void motion(int x, int y)
nuclear@8 416 {
nuclear@8 417 if(mouselook) {
nuclear@8 418 // just call passive, it does what we need
nuclear@8 419 passive(x, y);
nuclear@8 420 }
nuclear@8 421 }
nuclear@8 422
nuclear@8 423 static void passive(int x, int y)
nuclear@8 424 {
nuclear@8 425 // no need to test mouselook; this callback is only set when mouselook is enabled
nuclear@8 426 int center_x = width / 2;
nuclear@8 427 int center_y = height / 2;
nuclear@8 428
nuclear@8 429 int dx = x - center_x;
nuclear@8 430 int dy = y - center_y;
nuclear@8 431
nuclear@8 432 if(!dx && !dy) {
nuclear@8 433 return;
nuclear@8 434 }
nuclear@8 435
nuclear@9 436 float dtheta_deg = dy * 0.1;
nuclear@9 437 float dphi_deg = dx * 0.1;
nuclear@9 438
nuclear@9 439 cam.input_rotate(DEG_TO_RAD(dtheta_deg), DEG_TO_RAD(dphi_deg), 0);
nuclear@9 440
nuclear@8 441 glutPostRedisplay();
nuclear@8 442 glutWarpPointer(center_x, center_y);
nuclear@0 443 }
nuclear@0 444
nuclear@0 445 static void sball_rotate(int rx, int ry, int rz)
nuclear@0 446 {
nuclear@0 447 }
nuclear@1 448
nuclear@1 449 static bool parse_args(int argc, char **argv)
nuclear@1 450 {
nuclear@1 451 for(int i=1; i<argc; i++) {
nuclear@1 452 if(argv[i][0] == '-') {
nuclear@1 453 if(strcmp(argv[i], "-vr") == 0) {
nuclear@1 454 use_vr = true;
nuclear@1 455 } else if(strcmp(argv[i], "-novr") == 0) {
nuclear@1 456 use_vr = false;
nuclear@1 457 } else {
nuclear@1 458 fprintf(stderr, "invalid option: %s\n", argv[i]);
nuclear@1 459 return false;
nuclear@1 460 }
nuclear@1 461 } else {
nuclear@1 462 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
nuclear@1 463 return false;
nuclear@1 464 }
nuclear@1 465 }
nuclear@1 466 return true;
nuclear@1 467 }