oculus1

view src/main.cc @ 13:464e1d135d68

hurraaaay!
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 21 Sep 2013 03:00:47 +0300
parents d797639e0234
children cceffea995a4
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 disp()
142 {
143 unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
145 cam.track_vr();
147 /*glMatrixMode(GL_PROJECTION);
148 glLoadIdentity();
149 float fov = RAD_TO_DEG(vr_get_fov());
150 gluPerspective(fov, (float)rtarg_width / (float)rtarg_height, 0.25, 500.0);*/
151 float proj_matrix[16];
153 float eye_dist = vr_get_eyedist();
155 glViewport(0, 0, rtarg_width, rtarg_height);
157 glClearColor(0.1, 0.1, 0.1, 1.0);
159 // draw left view
160 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
161 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
163 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
165 glMatrixMode(GL_PROJECTION);
166 vr_get_proj_matrix(proj_matrix, VR_EYE_LEFT);
167 glLoadTransposeMatrixf(proj_matrix);
169 glMatrixMode(GL_MODELVIEW);
170 glLoadIdentity();
171 glTranslatef(eye_dist / 2.0, 0, 0);
172 cam.use_inverse();
173 draw_scene();
176 // draw right view
177 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
178 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[1], 0);
180 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
182 glMatrixMode(GL_PROJECTION);
183 vr_get_proj_matrix(proj_matrix, VR_EYE_RIGHT);
184 glLoadTransposeMatrixf(proj_matrix);
186 glMatrixMode(GL_MODELVIEW);
187 glLoadIdentity();
188 glTranslatef(-eye_dist / 2.0, 0, 0);
189 cam.use_inverse();
190 draw_scene();
192 // return to the regular window framebuffer
193 glBindFramebuffer(GL_FRAMEBUFFER, 0);
194 glViewport(0, 0, width, height);
196 glClearColor(0, 0, 0, 0);
197 glClear(GL_COLOR_BUFFER_BIT);
199 vr_draw_eye(tex[0], VR_EYE_LEFT);
200 vr_draw_eye(tex[1], VR_EYE_RIGHT);
202 glutSwapBuffers();
203 assert(glGetError() == GL_NO_ERROR);
205 glFinish();
206 }
209 static void draw_scene()
210 {
211 float lpos[] = {0, 60, 0, 1};
212 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
214 draw_grid(100.0, 2.5);
216 static Vector2 teapos[] = {
217 Vector2(-8, 8), Vector2(8, 8), Vector2(8, -8), Vector2(-8, -8)
218 };
220 for(int i=0; i<4; i++) {
221 glPushMatrix();
222 glTranslatef(teapos[i].x, 0, teapos[i].y);
223 draw_teapot();
224 glPopMatrix();
225 }
227 draw_squares();
228 }
230 static void draw_teapot()
231 {
232 static int tealist;
234 if(!tealist) {
235 tealist = glGenLists(1);
236 glNewList(tealist, GL_COMPILE);
237 glutSolidTeapot(1.0);
238 glEndList();
239 }
241 glFrontFace(GL_CW);
242 glCallList(tealist);
243 glFrontFace(GL_CCW);
244 }
246 static void draw_squares()
247 {
248 static const int num_sq = 4;
250 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
251 glDisable(GL_LIGHTING);
253 glMatrixMode(GL_MODELVIEW);
254 glPushMatrix();
255 glTranslatef(0, 1, 0);
258 glLineWidth(3.0);
259 glColor3f(1.0, 0.7, 0.2);
261 float zdist = 2.0;
262 for(int i=0; i<num_sq; i++) {
263 glBegin(GL_LINE_LOOP);
264 glVertex3f(-1, -1, -zdist);
265 glVertex3f(1, -1, -zdist);
266 glVertex3f(1, 1, -zdist);
267 glVertex3f(-1, 1, -zdist);
268 glEnd();
270 zdist += 1.0;
271 }
273 glPopMatrix();
274 glPopAttrib();
275 }
277 static void draw_grid(float size, float spacing)
278 {
279 int num_lines = size / spacing;
280 float dist = size / 2.0;
282 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
283 glDisable(GL_LIGHTING);
285 glLineWidth(1.0);
287 glBegin(GL_LINES);
288 glColor3f(0.4, 0.4, 0.4);
290 float x = -dist;
291 for(int i=0; i<=num_lines; i++) {
292 if(i != num_lines / 2) {
293 glVertex3f(-dist, 0, x);
294 glVertex3f(dist, 0, x);
295 glVertex3f(x, 0, -dist);
296 glVertex3f(x, 0, dist);
297 }
298 x += spacing;
299 }
300 glEnd();
302 glLineWidth(2.0);
304 glBegin(GL_LINES);
305 glColor3f(1.0, 0, 0);
306 glVertex3f(-dist, 0, 0);
307 glVertex3f(dist, 0, 0);
308 glColor3f(0, 1.0, 0);
309 glVertex3f(0, 0, -dist);
310 glVertex3f(0, 0, dist);
311 glEnd();
313 glPopAttrib();
314 }
316 static void idle()
317 {
318 glutPostRedisplay();
319 }
322 static void reshape(int x, int y)
323 {
324 width = x;
325 height = y;
327 if(!use_vr) {
328 rtarg_width = width;
329 rtarg_height = height;
330 }
331 }
333 static void keyb(unsigned char key, int x, int y)
334 {
335 switch(key) {
336 case 27:
337 exit(0);
339 case 'm':
340 mouselook = !mouselook;
341 if(mouselook) {
342 glutPassiveMotionFunc(passive);
343 glutSetCursor(GLUT_CURSOR_NONE);
344 glutWarpPointer(width / 2, height / 2);
345 } else {
346 glutPassiveMotionFunc(0);
347 glutSetCursor(GLUT_CURSOR_INHERIT);
348 }
349 break;
351 case 'f':
352 {
353 static bool fullscreen;
354 static int prev_xsz, prev_ysz;
356 fullscreen = !fullscreen;
358 if(fullscreen) {
359 prev_xsz = width;
360 prev_ysz = height;
361 glutFullScreen();
362 } else {
363 glutReshapeWindow(prev_xsz, prev_ysz);
364 }
365 glutPostRedisplay();
366 }
367 break;
368 }
370 keystate[key] = true;
371 glutPostRedisplay();
372 }
374 static void keyup(unsigned char key, int x, int y)
375 {
376 keystate[key] = false;
377 glutPostRedisplay();
378 }
380 static bool bnstate[32];
381 static int prev_x, prev_y;
383 static void mouse(int bn, int st, int x, int y)
384 {
385 prev_x = x;
386 prev_y = y;
387 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
388 }
390 static void motion(int x, int y)
391 {
392 if(mouselook) {
393 // just call passive, it does what we need
394 passive(x, y);
395 }
396 }
398 static void passive(int x, int y)
399 {
400 // no need to test mouselook; this callback is only set when mouselook is enabled
401 int center_x = width / 2;
402 int center_y = height / 2;
404 int dx = x - center_x;
405 int dy = y - center_y;
407 if(!dx && !dy) {
408 return;
409 }
411 float dtheta_deg = dy * 0.1;
412 float dphi_deg = dx * 0.1;
414 cam.input_rotate(DEG_TO_RAD(dtheta_deg), DEG_TO_RAD(dphi_deg), 0);
416 glutPostRedisplay();
417 glutWarpPointer(center_x, center_y);
418 }
420 static void sball_rotate(int rx, int ry, int rz)
421 {
422 }
424 static bool parse_args(int argc, char **argv)
425 {
426 for(int i=1; i<argc; i++) {
427 if(argv[i][0] == '-') {
428 if(strcmp(argv[i], "-vr") == 0) {
429 use_vr = true;
430 } else if(strcmp(argv[i], "-novr") == 0) {
431 use_vr = false;
432 } else {
433 fprintf(stderr, "invalid option: %s\n", argv[i]);
434 return false;
435 }
436 } else {
437 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
438 return false;
439 }
440 }
441 return true;
442 }