oculus1

view 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
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 #include "opengl.h"
6 #include "vr.h"
7 #include "camera.h"
9 static bool init();
10 static void cleanup();
11 static void disp();
12 static void draw_scene();
13 static void draw_teapot();
14 static void draw_squares();
15 static void draw_grid(float size, float spacing);
16 static void idle();
17 static void reshape(int x, int y);
18 static void keyb(unsigned char key, int x, int y);
19 static void keyup(unsigned char key, int x, int y);
20 static void mouse(int bn, int st, int x, int y);
21 static void motion(int x, int y);
22 static void passive(int x, int y);
23 static void sball_rotate(int rx, int ry, int rz);
24 static bool parse_args(int argc, char **argv);
26 static VRFpsCamera cam;
27 static int width, height;
28 static bool use_vr = false;
29 static bool mouselook = false;
31 static bool keystate[256];
33 static int rtarg_width, rtarg_height;
34 static unsigned int fbo, tex[2], zbuf;
36 int main(int argc, char **argv)
37 {
38 glutInitWindowSize(1280, 800);
39 glutInit(&argc, argv);
41 if(!parse_args(argc, argv)) {
42 return 1;
43 }
45 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
46 glutCreateWindow("oculus vr test 01");
48 width = glutGet(GLUT_WINDOW_WIDTH);
49 height = glutGet(GLUT_WINDOW_HEIGHT);
51 glutDisplayFunc(disp);
52 glutIdleFunc(idle);
53 glutReshapeFunc(reshape);
54 glutKeyboardFunc(keyb);
55 glutKeyboardUpFunc(keyup);
56 glutMouseFunc(mouse);
57 glutMotionFunc(motion);
58 glutSpaceballRotateFunc(sball_rotate);
60 if(!init()) {
61 return 1;
62 }
63 atexit(cleanup);
65 glutMainLoop();
66 return 0;
67 }
69 static bool init()
70 {
71 glewInit(); // this must be first
73 glEnable(GL_DEPTH_TEST);
74 glEnable(GL_LIGHTING);
75 glEnable(GL_CULL_FACE);
77 glEnable(GL_LIGHT0);
78 glEnable(GL_LIGHTING);
80 // y = height of neck
81 cam.input_move(0, 1.65, 0);
83 if(use_vr) {
84 if(vr_init(VR_INIT_OCULUS) == -1) {
85 return false;
86 }
88 // reshape to the size of the VR display
89 int xsz = vr_get_width();
90 int ysz = vr_get_height();
92 glutReshapeWindow(xsz, ysz);
94 rtarg_width = (xsz + xsz / 2) / 2;
95 rtarg_height = ysz + ysz / 2;
96 } else {
97 rtarg_width = width;
98 rtarg_height = height;
99 }
101 printf("render target: %dx%d\n", rtarg_width, rtarg_height);
103 // create render targets for each eye
104 GLenum wrap_mode = GL_CLAMP_TO_EDGE;
105 if(!GLEW_SGIS_texture_edge_clamp) {
106 wrap_mode = GL_CLAMP;
107 }
109 glGenTextures(2, tex);
110 for(int i=0; i<2; i++) {
111 glBindTexture(GL_TEXTURE_2D, tex[i]);
112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode);
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode);
116 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_width, rtarg_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
117 }
119 // create the depth render buffer
120 glGenRenderbuffers(1, &zbuf);
121 glBindRenderbuffer(GL_RENDERBUFFER, zbuf);
122 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_width, rtarg_height);
124 // create the FBO
125 glGenFramebuffers(1, &fbo);
126 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
127 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
128 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf);
130 return true;
131 }
133 static void cleanup()
134 {
135 glDeleteTextures(2, tex);
136 glDeleteRenderbuffers(1, &zbuf);
137 glDeleteFramebuffers(1, &fbo);
138 vr_shutdown();
139 }
141 static void handle_input(float dt)
142 {
143 Vector3 inpv;
144 float offs = dt * 2.0;
146 if(keystate['w'] || keystate['W']) {
147 inpv.z -= offs;
148 }
149 if(keystate['s'] || keystate['S']) {
150 inpv.z += offs;
151 }
152 if(keystate['d'] || keystate['D']) {
153 inpv.x += offs;
154 }
155 if(keystate['a'] || keystate['A']) {
156 inpv.x -= offs;
157 }
159 cam.input_move(inpv.x, inpv.y, inpv.z);
160 }
162 static void disp()
163 {
164 static long prev_msec;
165 long msec = glutGet(GLUT_ELAPSED_TIME);
166 float dt = (msec - prev_msec) / 1000.0;
167 prev_msec = msec;
169 handle_input(dt);
170 cam.track_vr();
172 /*glMatrixMode(GL_PROJECTION);
173 glLoadIdentity();
174 float fov = RAD_TO_DEG(vr_get_fov());
175 gluPerspective(fov, (float)rtarg_width / (float)rtarg_height, 0.25, 500.0);*/
176 float proj_matrix[16];
178 float eye_dist = vr_get_eyedist();
180 glViewport(0, 0, rtarg_width, rtarg_height);
182 glClearColor(0.1, 0.1, 0.1, 1.0);
184 // draw left view
185 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
186 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
188 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
190 glMatrixMode(GL_PROJECTION);
191 vr_get_proj_matrix(proj_matrix, VR_EYE_LEFT);
192 glLoadTransposeMatrixf(proj_matrix);
194 glMatrixMode(GL_MODELVIEW);
195 glLoadIdentity();
196 glTranslatef(eye_dist / 2.0, 0, 0);
197 cam.use_inverse();
198 draw_scene();
201 // draw right view
202 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
203 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[1], 0);
205 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
207 glMatrixMode(GL_PROJECTION);
208 vr_get_proj_matrix(proj_matrix, VR_EYE_RIGHT);
209 glLoadTransposeMatrixf(proj_matrix);
211 glMatrixMode(GL_MODELVIEW);
212 glLoadIdentity();
213 glTranslatef(-eye_dist / 2.0, 0, 0);
214 cam.use_inverse();
215 draw_scene();
217 // return to the regular window framebuffer
218 glBindFramebuffer(GL_FRAMEBUFFER, 0);
219 glViewport(0, 0, width, height);
221 glClearColor(0, 0, 0, 0);
222 glClear(GL_COLOR_BUFFER_BIT);
224 vr_draw_eye(tex[0], VR_EYE_LEFT);
225 vr_draw_eye(tex[1], VR_EYE_RIGHT);
227 glutSwapBuffers();
228 assert(glGetError() == GL_NO_ERROR);
230 glFinish();
231 }
234 static void draw_scene()
235 {
236 float lpos[] = {0, 60, 0, 1};
237 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
239 draw_grid(50.0, 2.5);
241 static Vector2 teapos[] = {
242 Vector2(-8, 8), Vector2(8, 8), Vector2(8, -8), Vector2(-8, -8)
243 };
245 for(int i=0; i<4; i++) {
246 glPushMatrix();
247 glTranslatef(teapos[i].x, 0, teapos[i].y);
248 draw_teapot();
249 glPopMatrix();
250 }
252 draw_squares();
253 }
255 static void draw_teapot()
256 {
257 static int tealist;
259 if(!tealist) {
260 tealist = glGenLists(1);
261 glNewList(tealist, GL_COMPILE);
262 glutSolidTeapot(1.0);
263 glEndList();
264 }
266 glFrontFace(GL_CW);
267 glCallList(tealist);
268 glFrontFace(GL_CCW);
269 }
271 static void draw_squares()
272 {
273 static const int num_sq = 8;
275 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
276 glDisable(GL_LIGHTING);
278 glMatrixMode(GL_MODELVIEW);
279 glPushMatrix();
280 glTranslatef(0, 1, 0);
283 glLineWidth(2.0);
284 glColor3f(1.0, 0.7, 0.2);
286 float zdist = 2.0;
287 for(int i=0; i<num_sq; i++) {
288 glBegin(GL_LINE_LOOP);
289 glVertex3f(-1, -1, -zdist);
290 glVertex3f(1, -1, -zdist);
291 glVertex3f(1, 1, -zdist);
292 glVertex3f(-1, 1, -zdist);
293 glEnd();
295 zdist += 2.0;
296 }
298 glPopMatrix();
299 glPopAttrib();
300 }
302 static void draw_grid(float size, float spacing)
303 {
304 int num_lines = size / spacing;
305 float dist = size / 2.0;
307 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
308 glDisable(GL_LIGHTING);
310 glLineWidth(1.0);
312 glBegin(GL_LINES);
313 glColor3f(0.4, 0.4, 0.4);
315 float x = -dist;
316 for(int i=0; i<=num_lines; i++) {
317 if(i != num_lines / 2) {
318 glVertex3f(-dist, 0, x);
319 glVertex3f(dist, 0, x);
320 glVertex3f(x, 0, -dist);
321 glVertex3f(x, 0, dist);
322 }
323 x += spacing;
324 }
325 glEnd();
327 glLineWidth(2.0);
329 glBegin(GL_LINES);
330 glColor3f(1.0, 0, 0);
331 glVertex3f(-dist, 0, 0);
332 glVertex3f(dist, 0, 0);
333 glColor3f(0, 1.0, 0);
334 glVertex3f(0, 0, -dist);
335 glVertex3f(0, 0, dist);
336 glEnd();
338 glPopAttrib();
339 }
341 static void idle()
342 {
343 glutPostRedisplay();
344 }
347 static void reshape(int x, int y)
348 {
349 width = x;
350 height = y;
352 if(!use_vr) {
353 rtarg_width = width;
354 rtarg_height = height;
355 }
356 }
358 static void keyb(unsigned char key, int x, int y)
359 {
360 switch(key) {
361 case 27:
362 exit(0);
364 case 'm':
365 mouselook = !mouselook;
366 if(mouselook) {
367 glutPassiveMotionFunc(passive);
368 glutSetCursor(GLUT_CURSOR_NONE);
369 glutWarpPointer(width / 2, height / 2);
370 } else {
371 glutPassiveMotionFunc(0);
372 glutSetCursor(GLUT_CURSOR_INHERIT);
373 }
374 break;
376 case 'f':
377 {
378 static bool fullscreen;
379 static int prev_xsz, prev_ysz;
381 fullscreen = !fullscreen;
383 if(fullscreen) {
384 prev_xsz = width;
385 prev_ysz = height;
386 glutFullScreen();
387 } else {
388 glutReshapeWindow(prev_xsz, prev_ysz);
389 }
390 glutPostRedisplay();
391 }
392 break;
393 }
395 keystate[key] = true;
396 glutPostRedisplay();
397 }
399 static void keyup(unsigned char key, int x, int y)
400 {
401 keystate[key] = false;
402 glutPostRedisplay();
403 }
405 static bool bnstate[32];
406 static int prev_x, prev_y;
408 static void mouse(int bn, int st, int x, int y)
409 {
410 prev_x = x;
411 prev_y = y;
412 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
413 }
415 static void motion(int x, int y)
416 {
417 if(mouselook) {
418 // just call passive, it does what we need
419 passive(x, y);
420 }
421 }
423 static void passive(int x, int y)
424 {
425 // no need to test mouselook; this callback is only set when mouselook is enabled
426 int center_x = width / 2;
427 int center_y = height / 2;
429 int dx = x - center_x;
430 int dy = y - center_y;
432 if(!dx && !dy) {
433 return;
434 }
436 float dtheta_deg = dy * 0.1;
437 float dphi_deg = dx * 0.1;
439 cam.input_rotate(DEG_TO_RAD(dtheta_deg), DEG_TO_RAD(dphi_deg), 0);
441 glutPostRedisplay();
442 glutWarpPointer(center_x, center_y);
443 }
445 static void sball_rotate(int rx, int ry, int rz)
446 {
447 }
449 static bool parse_args(int argc, char **argv)
450 {
451 for(int i=1; i<argc; i++) {
452 if(argv[i][0] == '-') {
453 if(strcmp(argv[i], "-vr") == 0) {
454 use_vr = true;
455 } else if(strcmp(argv[i], "-novr") == 0) {
456 use_vr = false;
457 } else {
458 fprintf(stderr, "invalid option: %s\n", argv[i]);
459 return false;
460 }
461 } else {
462 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
463 return false;
464 }
465 }
466 return true;
467 }