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@16
|
8 #include "sdr.h"
|
nuclear@0
|
9
|
nuclear@0
|
10 static bool init();
|
nuclear@0
|
11 static void cleanup();
|
nuclear@0
|
12 static void disp();
|
nuclear@16
|
13 static void disp_vr();
|
nuclear@9
|
14 static void draw_scene();
|
nuclear@16
|
15 static void draw_teapot(float size);
|
nuclear@13
|
16 static void draw_squares();
|
nuclear@12
|
17 static void draw_grid(float size, float spacing);
|
nuclear@16
|
18 static void toggle_mouselook();
|
nuclear@16
|
19 static void toggle_fullscreen();
|
nuclear@0
|
20 static void idle();
|
nuclear@0
|
21 static void reshape(int x, int y);
|
nuclear@0
|
22 static void keyb(unsigned char key, int x, int y);
|
nuclear@8
|
23 static void keyup(unsigned char key, int x, int y);
|
nuclear@8
|
24 static void mouse(int bn, int st, int x, int y);
|
nuclear@8
|
25 static void motion(int x, int y);
|
nuclear@8
|
26 static void passive(int x, int y);
|
nuclear@0
|
27 static void sball_rotate(int rx, int ry, int rz);
|
nuclear@1
|
28 static bool parse_args(int argc, char **argv);
|
nuclear@0
|
29
|
nuclear@10
|
30 static VRFpsCamera cam;
|
nuclear@0
|
31 static int width, height;
|
nuclear@1
|
32 static bool use_vr = false;
|
nuclear@8
|
33
|
nuclear@8
|
34 static bool keystate[256];
|
nuclear@8
|
35
|
nuclear@12
|
36 static int rtarg_width, rtarg_height;
|
nuclear@12
|
37 static unsigned int fbo, tex[2], zbuf;
|
nuclear@12
|
38
|
nuclear@16
|
39 static unsigned int teapot_sdr;
|
nuclear@16
|
40
|
nuclear@16
|
41 static bool fullscreen_pending;
|
nuclear@16
|
42
|
nuclear@0
|
43 int main(int argc, char **argv)
|
nuclear@0
|
44 {
|
nuclear@3
|
45 glutInitWindowSize(1280, 800);
|
nuclear@0
|
46 glutInit(&argc, argv);
|
nuclear@1
|
47
|
nuclear@1
|
48 if(!parse_args(argc, argv)) {
|
nuclear@1
|
49 return 1;
|
nuclear@1
|
50 }
|
nuclear@1
|
51
|
nuclear@12
|
52 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
|
nuclear@12
|
53 glutCreateWindow("oculus vr test 01");
|
nuclear@12
|
54
|
nuclear@12
|
55 width = glutGet(GLUT_WINDOW_WIDTH);
|
nuclear@12
|
56 height = glutGet(GLUT_WINDOW_HEIGHT);
|
nuclear@0
|
57
|
nuclear@16
|
58 glutDisplayFunc(use_vr ? disp_vr : disp);
|
nuclear@0
|
59 glutIdleFunc(idle);
|
nuclear@0
|
60 glutReshapeFunc(reshape);
|
nuclear@0
|
61 glutKeyboardFunc(keyb);
|
nuclear@8
|
62 glutKeyboardUpFunc(keyup);
|
nuclear@8
|
63 glutMouseFunc(mouse);
|
nuclear@8
|
64 glutMotionFunc(motion);
|
nuclear@0
|
65 glutSpaceballRotateFunc(sball_rotate);
|
nuclear@0
|
66
|
nuclear@0
|
67 if(!init()) {
|
nuclear@0
|
68 return 1;
|
nuclear@0
|
69 }
|
nuclear@0
|
70 atexit(cleanup);
|
nuclear@0
|
71
|
nuclear@0
|
72 glutMainLoop();
|
nuclear@0
|
73 return 0;
|
nuclear@0
|
74 }
|
nuclear@0
|
75
|
nuclear@0
|
76 static bool init()
|
nuclear@0
|
77 {
|
nuclear@9
|
78 glewInit(); // this must be first
|
nuclear@9
|
79
|
nuclear@0
|
80 glEnable(GL_DEPTH_TEST);
|
nuclear@0
|
81 glEnable(GL_LIGHTING);
|
nuclear@0
|
82 glEnable(GL_CULL_FACE);
|
nuclear@0
|
83
|
nuclear@0
|
84 glEnable(GL_LIGHT0);
|
nuclear@0
|
85 glEnable(GL_LIGHTING);
|
nuclear@16
|
86 glEnable(GL_NORMALIZE);
|
nuclear@0
|
87
|
nuclear@11
|
88 // y = height of neck
|
nuclear@11
|
89 cam.input_move(0, 1.65, 0);
|
nuclear@9
|
90
|
nuclear@12
|
91 if(use_vr) {
|
nuclear@12
|
92 if(vr_init(VR_INIT_OCULUS) == -1) {
|
nuclear@12
|
93 return false;
|
nuclear@12
|
94 }
|
nuclear@12
|
95
|
nuclear@12
|
96 // reshape to the size of the VR display
|
nuclear@12
|
97 int xsz = vr_get_width();
|
nuclear@12
|
98 int ysz = vr_get_height();
|
nuclear@12
|
99
|
nuclear@12
|
100 glutReshapeWindow(xsz, ysz);
|
nuclear@12
|
101
|
nuclear@12
|
102 rtarg_width = (xsz + xsz / 2) / 2;
|
nuclear@12
|
103 rtarg_height = ysz + ysz / 2;
|
nuclear@16
|
104
|
nuclear@16
|
105 printf("render target: %dx%d\n", rtarg_width, rtarg_height);
|
nuclear@16
|
106
|
nuclear@16
|
107 // create render targets for each eye
|
nuclear@16
|
108 GLenum wrap_mode = GL_CLAMP_TO_EDGE;
|
nuclear@16
|
109 if(!GLEW_SGIS_texture_edge_clamp) {
|
nuclear@16
|
110 wrap_mode = GL_CLAMP;
|
nuclear@16
|
111 }
|
nuclear@16
|
112
|
nuclear@16
|
113 glGenTextures(2, tex);
|
nuclear@16
|
114 for(int i=0; i<2; i++) {
|
nuclear@16
|
115 glBindTexture(GL_TEXTURE_2D, tex[i]);
|
nuclear@16
|
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@16
|
117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@16
|
118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode);
|
nuclear@16
|
119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode);
|
nuclear@16
|
120 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_width, rtarg_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
nuclear@16
|
121 }
|
nuclear@16
|
122
|
nuclear@16
|
123 // create the depth render buffer
|
nuclear@16
|
124 glGenRenderbuffers(1, &zbuf);
|
nuclear@16
|
125 glBindRenderbuffer(GL_RENDERBUFFER, zbuf);
|
nuclear@16
|
126 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_width, rtarg_height);
|
nuclear@16
|
127
|
nuclear@16
|
128 // create the FBO
|
nuclear@16
|
129 glGenFramebuffers(1, &fbo);
|
nuclear@16
|
130 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@16
|
131 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
|
nuclear@16
|
132 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf);
|
nuclear@0
|
133 }
|
nuclear@12
|
134
|
nuclear@16
|
135 teapot_sdr = create_program_load("sdr/phong.v.glsl", "sdr/phong.p.glsl");
|
nuclear@12
|
136
|
nuclear@0
|
137 return true;
|
nuclear@0
|
138 }
|
nuclear@0
|
139
|
nuclear@0
|
140 static void cleanup()
|
nuclear@0
|
141 {
|
nuclear@12
|
142 glDeleteTextures(2, tex);
|
nuclear@12
|
143 glDeleteRenderbuffers(1, &zbuf);
|
nuclear@12
|
144 glDeleteFramebuffers(1, &fbo);
|
nuclear@1
|
145 vr_shutdown();
|
nuclear@0
|
146 }
|
nuclear@0
|
147
|
nuclear@14
|
148 static void handle_input(float dt)
|
nuclear@14
|
149 {
|
nuclear@14
|
150 Vector3 inpv;
|
nuclear@14
|
151 float offs = dt * 2.0;
|
nuclear@14
|
152
|
nuclear@14
|
153 if(keystate['w'] || keystate['W']) {
|
nuclear@14
|
154 inpv.z -= offs;
|
nuclear@14
|
155 }
|
nuclear@14
|
156 if(keystate['s'] || keystate['S']) {
|
nuclear@14
|
157 inpv.z += offs;
|
nuclear@14
|
158 }
|
nuclear@14
|
159 if(keystate['d'] || keystate['D']) {
|
nuclear@14
|
160 inpv.x += offs;
|
nuclear@14
|
161 }
|
nuclear@14
|
162 if(keystate['a'] || keystate['A']) {
|
nuclear@14
|
163 inpv.x -= offs;
|
nuclear@14
|
164 }
|
nuclear@14
|
165
|
nuclear@14
|
166 cam.input_move(inpv.x, inpv.y, inpv.z);
|
nuclear@14
|
167 }
|
nuclear@14
|
168
|
nuclear@16
|
169 // display function used in regular mode
|
nuclear@0
|
170 static void disp()
|
nuclear@0
|
171 {
|
nuclear@14
|
172 static long prev_msec;
|
nuclear@14
|
173 long msec = glutGet(GLUT_ELAPSED_TIME);
|
nuclear@14
|
174 float dt = (msec - prev_msec) / 1000.0;
|
nuclear@14
|
175 prev_msec = msec;
|
nuclear@4
|
176
|
nuclear@14
|
177 handle_input(dt);
|
nuclear@16
|
178
|
nuclear@16
|
179 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@16
|
180
|
nuclear@16
|
181 glMatrixMode(GL_PROJECTION);
|
nuclear@16
|
182 glLoadIdentity();
|
nuclear@16
|
183 gluPerspective(45, (float)width / (float)height, 0.25, 500.0);
|
nuclear@16
|
184
|
nuclear@16
|
185 glMatrixMode(GL_MODELVIEW);
|
nuclear@16
|
186 glLoadIdentity();
|
nuclear@16
|
187 cam.use_inverse();
|
nuclear@16
|
188 draw_scene();
|
nuclear@16
|
189
|
nuclear@16
|
190 glutSwapBuffers();
|
nuclear@16
|
191 assert(glGetError() == GL_NO_ERROR);
|
nuclear@16
|
192 }
|
nuclear@16
|
193
|
nuclear@16
|
194 // display function used in VR mode
|
nuclear@16
|
195 static void disp_vr()
|
nuclear@16
|
196 {
|
nuclear@16
|
197 static long prev_msec;
|
nuclear@16
|
198 long msec = glutGet(GLUT_ELAPSED_TIME);
|
nuclear@16
|
199 float dt = (msec - prev_msec) / 1000.0;
|
nuclear@16
|
200 prev_msec = msec;
|
nuclear@16
|
201
|
nuclear@16
|
202 handle_input(dt);
|
nuclear@12
|
203 cam.track_vr();
|
nuclear@0
|
204
|
nuclear@13
|
205 float proj_matrix[16];
|
nuclear@13
|
206
|
nuclear@13
|
207 float eye_dist = vr_get_eyedist();
|
nuclear@12
|
208
|
nuclear@12
|
209 glViewport(0, 0, rtarg_width, rtarg_height);
|
nuclear@12
|
210
|
nuclear@12
|
211 glClearColor(0.1, 0.1, 0.1, 1.0);
|
nuclear@12
|
212
|
nuclear@12
|
213 // draw left view
|
nuclear@12
|
214 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@12
|
215 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
|
nuclear@12
|
216
|
nuclear@12
|
217 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@0
|
218
|
nuclear@13
|
219 glMatrixMode(GL_PROJECTION);
|
nuclear@13
|
220 vr_get_proj_matrix(proj_matrix, VR_EYE_LEFT);
|
nuclear@13
|
221 glLoadTransposeMatrixf(proj_matrix);
|
nuclear@13
|
222
|
nuclear@0
|
223 glMatrixMode(GL_MODELVIEW);
|
nuclear@9
|
224 glLoadIdentity();
|
nuclear@13
|
225 glTranslatef(eye_dist / 2.0, 0, 0);
|
nuclear@12
|
226 cam.use_inverse();
|
nuclear@12
|
227 draw_scene();
|
nuclear@0
|
228
|
nuclear@12
|
229
|
nuclear@12
|
230 // draw right view
|
nuclear@12
|
231 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@12
|
232 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[1], 0);
|
nuclear@12
|
233
|
nuclear@12
|
234 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@12
|
235
|
nuclear@13
|
236 glMatrixMode(GL_PROJECTION);
|
nuclear@13
|
237 vr_get_proj_matrix(proj_matrix, VR_EYE_RIGHT);
|
nuclear@13
|
238 glLoadTransposeMatrixf(proj_matrix);
|
nuclear@13
|
239
|
nuclear@12
|
240 glMatrixMode(GL_MODELVIEW);
|
nuclear@12
|
241 glLoadIdentity();
|
nuclear@13
|
242 glTranslatef(-eye_dist / 2.0, 0, 0);
|
nuclear@9
|
243 cam.use_inverse();
|
nuclear@12
|
244 draw_scene();
|
nuclear@9
|
245
|
nuclear@12
|
246 // return to the regular window framebuffer
|
nuclear@12
|
247 glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
nuclear@12
|
248 glViewport(0, 0, width, height);
|
nuclear@12
|
249
|
nuclear@12
|
250 glClearColor(0, 0, 0, 0);
|
nuclear@12
|
251 glClear(GL_COLOR_BUFFER_BIT);
|
nuclear@12
|
252
|
nuclear@12
|
253 vr_draw_eye(tex[0], VR_EYE_LEFT);
|
nuclear@12
|
254 vr_draw_eye(tex[1], VR_EYE_RIGHT);
|
nuclear@9
|
255
|
nuclear@9
|
256 glutSwapBuffers();
|
nuclear@9
|
257 assert(glGetError() == GL_NO_ERROR);
|
nuclear@13
|
258
|
nuclear@13
|
259 glFinish();
|
nuclear@9
|
260 }
|
nuclear@9
|
261
|
nuclear@12
|
262 static void draw_scene()
|
nuclear@12
|
263 {
|
nuclear@12
|
264 float lpos[] = {0, 60, 0, 1};
|
nuclear@12
|
265 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
|
nuclear@12
|
266
|
nuclear@14
|
267 draw_grid(50.0, 2.5);
|
nuclear@13
|
268
|
nuclear@16
|
269 static const Vector2 teapos[] = {
|
nuclear@16
|
270 Vector2(-8, -8), Vector2(8, -8), Vector2(8, 8), Vector2(-8, 8)
|
nuclear@12
|
271 };
|
nuclear@16
|
272 static const float teasize[] = { 1.0, 2.0, 1.7, 1.4 };
|
nuclear@16
|
273 static const float teacolor[][4] = {
|
nuclear@16
|
274 {1.0, 0.4, 0.2, 1.0}, {0.2, 0.35, 1.0, 1.0}, {1.0, 0.9, 0.3, 1.0}, {0.3, 1.0, 0.4, 1.0}
|
nuclear@16
|
275 };
|
nuclear@16
|
276 static const float spec[] = {0.8, 0.8, 0.8, 1.0};
|
nuclear@16
|
277
|
nuclear@16
|
278 glUseProgram(teapot_sdr);
|
nuclear@12
|
279
|
nuclear@12
|
280 for(int i=0; i<4; i++) {
|
nuclear@16
|
281 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, teacolor[i]);
|
nuclear@16
|
282 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
|
nuclear@16
|
283 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.0);
|
nuclear@16
|
284
|
nuclear@12
|
285 glPushMatrix();
|
nuclear@12
|
286 glTranslatef(teapos[i].x, 0, teapos[i].y);
|
nuclear@16
|
287 draw_teapot(teasize[i]);
|
nuclear@12
|
288 glPopMatrix();
|
nuclear@12
|
289 }
|
nuclear@16
|
290 glUseProgram(0);
|
nuclear@12
|
291
|
nuclear@13
|
292 draw_squares();
|
nuclear@12
|
293 }
|
nuclear@12
|
294
|
nuclear@16
|
295 static void draw_teapot(float size)
|
nuclear@9
|
296 {
|
nuclear@9
|
297 static int tealist;
|
nuclear@9
|
298
|
nuclear@9
|
299 if(!tealist) {
|
nuclear@9
|
300 tealist = glGenLists(1);
|
nuclear@9
|
301 glNewList(tealist, GL_COMPILE);
|
nuclear@9
|
302 glutSolidTeapot(1.0);
|
nuclear@9
|
303 glEndList();
|
nuclear@9
|
304 }
|
nuclear@9
|
305
|
nuclear@16
|
306 glMatrixMode(GL_MODELVIEW);
|
nuclear@16
|
307 glPushMatrix();
|
nuclear@16
|
308 glScalef(size, size, size);
|
nuclear@16
|
309 glTranslatef(0, 0.73, 0);
|
nuclear@16
|
310
|
nuclear@9
|
311 glFrontFace(GL_CW);
|
nuclear@9
|
312 glCallList(tealist);
|
nuclear@9
|
313 glFrontFace(GL_CCW);
|
nuclear@16
|
314
|
nuclear@16
|
315 glPopMatrix();
|
nuclear@9
|
316 }
|
nuclear@9
|
317
|
nuclear@13
|
318 static void draw_squares()
|
nuclear@13
|
319 {
|
nuclear@14
|
320 static const int num_sq = 8;
|
nuclear@13
|
321
|
nuclear@13
|
322 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
|
nuclear@13
|
323 glDisable(GL_LIGHTING);
|
nuclear@13
|
324
|
nuclear@13
|
325 glMatrixMode(GL_MODELVIEW);
|
nuclear@13
|
326 glPushMatrix();
|
nuclear@13
|
327 glTranslatef(0, 1, 0);
|
nuclear@13
|
328
|
nuclear@13
|
329
|
nuclear@14
|
330 glLineWidth(2.0);
|
nuclear@13
|
331 glColor3f(1.0, 0.7, 0.2);
|
nuclear@13
|
332
|
nuclear@13
|
333 float zdist = 2.0;
|
nuclear@13
|
334 for(int i=0; i<num_sq; i++) {
|
nuclear@13
|
335 glBegin(GL_LINE_LOOP);
|
nuclear@13
|
336 glVertex3f(-1, -1, -zdist);
|
nuclear@13
|
337 glVertex3f(1, -1, -zdist);
|
nuclear@13
|
338 glVertex3f(1, 1, -zdist);
|
nuclear@13
|
339 glVertex3f(-1, 1, -zdist);
|
nuclear@13
|
340 glEnd();
|
nuclear@13
|
341
|
nuclear@14
|
342 zdist += 2.0;
|
nuclear@13
|
343 }
|
nuclear@13
|
344
|
nuclear@13
|
345 glPopMatrix();
|
nuclear@13
|
346 glPopAttrib();
|
nuclear@13
|
347 }
|
nuclear@13
|
348
|
nuclear@12
|
349 static void draw_grid(float size, float spacing)
|
nuclear@9
|
350 {
|
nuclear@9
|
351 int num_lines = size / spacing;
|
nuclear@9
|
352 float dist = size / 2.0;
|
nuclear@9
|
353
|
nuclear@9
|
354 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
|
nuclear@9
|
355 glDisable(GL_LIGHTING);
|
nuclear@9
|
356
|
nuclear@9
|
357 glLineWidth(1.0);
|
nuclear@9
|
358
|
nuclear@9
|
359 glBegin(GL_LINES);
|
nuclear@9
|
360 glColor3f(0.4, 0.4, 0.4);
|
nuclear@9
|
361
|
nuclear@9
|
362 float x = -dist;
|
nuclear@9
|
363 for(int i=0; i<=num_lines; i++) {
|
nuclear@9
|
364 if(i != num_lines / 2) {
|
nuclear@9
|
365 glVertex3f(-dist, 0, x);
|
nuclear@9
|
366 glVertex3f(dist, 0, x);
|
nuclear@9
|
367 glVertex3f(x, 0, -dist);
|
nuclear@9
|
368 glVertex3f(x, 0, dist);
|
nuclear@9
|
369 }
|
nuclear@9
|
370 x += spacing;
|
nuclear@9
|
371 }
|
nuclear@9
|
372 glEnd();
|
nuclear@9
|
373
|
nuclear@9
|
374 glLineWidth(2.0);
|
nuclear@9
|
375
|
nuclear@9
|
376 glBegin(GL_LINES);
|
nuclear@9
|
377 glColor3f(1.0, 0, 0);
|
nuclear@9
|
378 glVertex3f(-dist, 0, 0);
|
nuclear@9
|
379 glVertex3f(dist, 0, 0);
|
nuclear@9
|
380 glColor3f(0, 1.0, 0);
|
nuclear@9
|
381 glVertex3f(0, 0, -dist);
|
nuclear@9
|
382 glVertex3f(0, 0, dist);
|
nuclear@9
|
383 glEnd();
|
nuclear@9
|
384
|
nuclear@9
|
385 glPopAttrib();
|
nuclear@9
|
386 }
|
nuclear@9
|
387
|
nuclear@16
|
388 static bool mouselook;
|
nuclear@16
|
389
|
nuclear@16
|
390 static void toggle_mouselook()
|
nuclear@16
|
391 {
|
nuclear@16
|
392 mouselook = !mouselook;
|
nuclear@16
|
393 if(mouselook) {
|
nuclear@16
|
394 glutPassiveMotionFunc(passive);
|
nuclear@16
|
395 glutSetCursor(GLUT_CURSOR_NONE);
|
nuclear@16
|
396 glutWarpPointer(width / 2, height / 2);
|
nuclear@16
|
397 } else {
|
nuclear@16
|
398 glutPassiveMotionFunc(0);
|
nuclear@16
|
399 glutSetCursor(GLUT_CURSOR_INHERIT);
|
nuclear@16
|
400 }
|
nuclear@16
|
401 }
|
nuclear@16
|
402
|
nuclear@22
|
403 static bool fullscreen;
|
nuclear@16
|
404 static void toggle_fullscreen()
|
nuclear@16
|
405 {
|
nuclear@16
|
406 static int prev_x, prev_y;
|
nuclear@16
|
407 static int prev_xsz, prev_ysz;
|
nuclear@16
|
408
|
nuclear@16
|
409 fullscreen = !fullscreen;
|
nuclear@16
|
410
|
nuclear@16
|
411 if(fullscreen) {
|
nuclear@16
|
412 prev_x = glutGet(GLUT_WINDOW_X);
|
nuclear@16
|
413 prev_y = glutGet(GLUT_WINDOW_Y);
|
nuclear@16
|
414 prev_xsz = width;
|
nuclear@16
|
415 prev_ysz = height;
|
nuclear@16
|
416
|
nuclear@16
|
417 if(use_vr) {
|
nuclear@16
|
418 // go fullscreen to the correct monitor
|
nuclear@16
|
419 int x, y;
|
nuclear@16
|
420 vr_get_display_pos(&x, &y);
|
nuclear@16
|
421 glutPositionWindow(x, y);
|
nuclear@16
|
422
|
nuclear@16
|
423 // also warp the mouse and enable mouselook
|
nuclear@16
|
424 glutWarpPointer(x + width / 2, y + height / 2);
|
nuclear@16
|
425
|
nuclear@16
|
426 /* Ok this next line needs some explanation:
|
nuclear@16
|
427 * glutPositionWindow, doesn't necessarilly get executed directly.
|
nuclear@16
|
428 * GLUT might defer it for the next round of event processing, just
|
nuclear@16
|
429 * so that it may coalesce multiple positioning requests.
|
nuclear@16
|
430 * However that means that if we just called glutFullScreen right
|
nuclear@16
|
431 * here, the window manager would have no idea that the window will
|
nuclear@16
|
432 * move to another monitor, thus making it the size of the monitor
|
nuclear@16
|
433 * it occupied before the move.
|
nuclear@16
|
434 * So I'm setting a flag here, and execute the glutFullScreen call
|
nuclear@16
|
435 * at the next idle invocation. (would display be a safer place?).
|
nuclear@16
|
436 */
|
nuclear@16
|
437 fullscreen_pending = true;
|
nuclear@16
|
438 } else {
|
nuclear@16
|
439 glutFullScreen();
|
nuclear@16
|
440 toggle_mouselook();
|
nuclear@16
|
441 }
|
nuclear@16
|
442 } else {
|
nuclear@16
|
443 glutReshapeWindow(prev_xsz, prev_ysz);
|
nuclear@16
|
444 glutPositionWindow(prev_x, prev_y);
|
nuclear@16
|
445
|
nuclear@16
|
446 if(mouselook) {
|
nuclear@16
|
447 toggle_mouselook();
|
nuclear@16
|
448 }
|
nuclear@16
|
449 }
|
nuclear@16
|
450 glutPostRedisplay();
|
nuclear@16
|
451 }
|
nuclear@16
|
452
|
nuclear@16
|
453
|
nuclear@0
|
454 static void idle()
|
nuclear@0
|
455 {
|
nuclear@16
|
456 if(fullscreen_pending) {
|
nuclear@16
|
457 glutFullScreen();
|
nuclear@16
|
458
|
nuclear@16
|
459 if(!mouselook) {
|
nuclear@16
|
460 toggle_mouselook();
|
nuclear@16
|
461 }
|
nuclear@16
|
462 fullscreen_pending = false;
|
nuclear@16
|
463 }
|
nuclear@0
|
464 glutPostRedisplay();
|
nuclear@0
|
465 }
|
nuclear@0
|
466
|
nuclear@0
|
467
|
nuclear@0
|
468 static void reshape(int x, int y)
|
nuclear@0
|
469 {
|
nuclear@0
|
470 width = x;
|
nuclear@0
|
471 height = y;
|
nuclear@12
|
472
|
nuclear@12
|
473 if(!use_vr) {
|
nuclear@12
|
474 rtarg_width = width;
|
nuclear@12
|
475 rtarg_height = height;
|
nuclear@12
|
476 }
|
nuclear@0
|
477 }
|
nuclear@0
|
478
|
nuclear@0
|
479 static void keyb(unsigned char key, int x, int y)
|
nuclear@0
|
480 {
|
nuclear@0
|
481 switch(key) {
|
nuclear@0
|
482 case 27:
|
nuclear@0
|
483 exit(0);
|
nuclear@8
|
484
|
nuclear@8
|
485 case 'm':
|
nuclear@16
|
486 toggle_mouselook();
|
nuclear@8
|
487 break;
|
nuclear@12
|
488
|
nuclear@12
|
489 case 'f':
|
nuclear@16
|
490 toggle_fullscreen();
|
nuclear@12
|
491 break;
|
nuclear@0
|
492 }
|
nuclear@8
|
493
|
nuclear@8
|
494 keystate[key] = true;
|
nuclear@8
|
495 glutPostRedisplay();
|
nuclear@8
|
496 }
|
nuclear@8
|
497
|
nuclear@8
|
498 static void keyup(unsigned char key, int x, int y)
|
nuclear@8
|
499 {
|
nuclear@8
|
500 keystate[key] = false;
|
nuclear@8
|
501 glutPostRedisplay();
|
nuclear@8
|
502 }
|
nuclear@8
|
503
|
nuclear@8
|
504 static bool bnstate[32];
|
nuclear@8
|
505 static int prev_x, prev_y;
|
nuclear@8
|
506
|
nuclear@8
|
507 static void mouse(int bn, int st, int x, int y)
|
nuclear@8
|
508 {
|
nuclear@8
|
509 prev_x = x;
|
nuclear@8
|
510 prev_y = y;
|
nuclear@8
|
511 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
|
nuclear@8
|
512 }
|
nuclear@8
|
513
|
nuclear@8
|
514 static void motion(int x, int y)
|
nuclear@8
|
515 {
|
nuclear@8
|
516 if(mouselook) {
|
nuclear@8
|
517 // just call passive, it does what we need
|
nuclear@8
|
518 passive(x, y);
|
nuclear@8
|
519 }
|
nuclear@8
|
520 }
|
nuclear@8
|
521
|
nuclear@8
|
522 static void passive(int x, int y)
|
nuclear@8
|
523 {
|
nuclear@8
|
524 // no need to test mouselook; this callback is only set when mouselook is enabled
|
nuclear@8
|
525 int center_x = width / 2;
|
nuclear@8
|
526 int center_y = height / 2;
|
nuclear@8
|
527
|
nuclear@8
|
528 int dx = x - center_x;
|
nuclear@8
|
529 int dy = y - center_y;
|
nuclear@8
|
530
|
nuclear@22
|
531 if(use_vr && fullscreen) {
|
nuclear@22
|
532 dy = 0;
|
nuclear@22
|
533 }
|
nuclear@22
|
534
|
nuclear@8
|
535 if(!dx && !dy) {
|
nuclear@8
|
536 return;
|
nuclear@8
|
537 }
|
nuclear@8
|
538
|
nuclear@9
|
539 float dtheta_deg = dy * 0.1;
|
nuclear@9
|
540 float dphi_deg = dx * 0.1;
|
nuclear@9
|
541
|
nuclear@9
|
542 cam.input_rotate(DEG_TO_RAD(dtheta_deg), DEG_TO_RAD(dphi_deg), 0);
|
nuclear@9
|
543
|
nuclear@8
|
544 glutPostRedisplay();
|
nuclear@8
|
545 glutWarpPointer(center_x, center_y);
|
nuclear@0
|
546 }
|
nuclear@0
|
547
|
nuclear@0
|
548 static void sball_rotate(int rx, int ry, int rz)
|
nuclear@0
|
549 {
|
nuclear@0
|
550 }
|
nuclear@1
|
551
|
nuclear@1
|
552 static bool parse_args(int argc, char **argv)
|
nuclear@1
|
553 {
|
nuclear@1
|
554 for(int i=1; i<argc; i++) {
|
nuclear@1
|
555 if(argv[i][0] == '-') {
|
nuclear@1
|
556 if(strcmp(argv[i], "-vr") == 0) {
|
nuclear@1
|
557 use_vr = true;
|
nuclear@1
|
558 } else if(strcmp(argv[i], "-novr") == 0) {
|
nuclear@1
|
559 use_vr = false;
|
nuclear@1
|
560 } else {
|
nuclear@1
|
561 fprintf(stderr, "invalid option: %s\n", argv[i]);
|
nuclear@1
|
562 return false;
|
nuclear@1
|
563 }
|
nuclear@1
|
564 } else {
|
nuclear@1
|
565 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
|
nuclear@1
|
566 return false;
|
nuclear@1
|
567 }
|
nuclear@1
|
568 }
|
nuclear@1
|
569 return true;
|
nuclear@1
|
570 }
|