view3d

view src/main.c @ 9:d2e283764fca

fixed fullscreen separate idle func so it works on windows too
author nuclear@neutrino-win7.lan
date Sat, 28 Jan 2012 02:56:27 +0200
parents 5562a637e5aa
children
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
5 #include <GL/glew.h>
6 #ifndef __APPLE__
7 #include <GL/glut.h>
8 #else
9 #include <GLUT/glut.h>
10 #endif
12 #include "scene.h"
14 void disp(void);
15 void render(unsigned int msec);
16 void proj_matrix(float eye);
17 void view_matrix(float eye);
19 void idle(void);
20 void reshape(int x, int y);
21 void keyb(unsigned char key, int x, int y);
22 void keyb_up(unsigned char key, int x, int y);
23 void mouse(int bn, int state, int x, int y);
24 void motion(int x, int y);
25 void sball_motion(int x, int y, int z);
26 void sball_rotate(int x, int y, int z);
27 void sball_button(int bn, int state);
28 int parse_args(int argc, char **argv);
30 int win_width, win_height;
31 int stereo;
32 int flip_winding;
33 int auto_rot;
34 float cam_theta, cam_phi, cam_dist = 10;
35 float near_clip = 0.5;
36 float far_clip = 1000.0;
37 float fov = M_PI / 4.0;
38 float stereo_focus_dist = 1.0;
39 float stereo_eye_sep = 1.0 / 30.0;
41 int verbose = 0;
43 struct scene scn;
45 int main(int argc, char **argv)
46 {
47 float amb[] = {0.01, 0.01, 0.01, 1};
48 float ldir[] = {-1, 1, 1, 0};
49 float dx, dy, dz, diag;
52 glutInitWindowSize(800, 600);
53 glutInit(&argc, argv);
54 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (stereo ? GLUT_STEREO : 0));
55 glutCreateWindow("OpenGL 3D viewer");
57 glutDisplayFunc(disp);
58 glutReshapeFunc(reshape);
59 glutKeyboardFunc(keyb);
60 glutKeyboardUpFunc(keyb_up);
61 glutMouseFunc(mouse);
62 glutMotionFunc(motion);
63 glutSpaceballMotionFunc(sball_motion);
64 glutSpaceballRotateFunc(sball_rotate);
65 glutSpaceballButtonFunc(sball_button);
66 if(auto_rot) {
67 glutIdleFunc(idle);
68 }
70 glewInit();
72 glEnable(GL_NORMALIZE);
73 glEnable(GL_DEPTH_TEST);
74 glEnable(GL_CULL_FACE);
75 glEnable(GL_LIGHTING);
76 glEnable(GL_LIGHT0);
77 glLightfv(GL_LIGHT0, GL_POSITION, ldir);
79 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
82 init_scene(&scn);
83 if(parse_args(argc, argv) == -1) {
84 return 1;
85 }
86 if(verbose) {
87 printf("scene bounds: %.2f %.2f %.2f -> %.2f %.2f %.2f\n", scn.bbox.min[0], scn.bbox.min[1],
88 scn.bbox.min[2], scn.bbox.max[0], scn.bbox.max[1], scn.bbox.max[2]);
89 }
91 dx = scn.bbox.max[0] - scn.bbox.min[0];
92 dy = scn.bbox.max[1] - scn.bbox.min[1];
93 dz = scn.bbox.max[2] - scn.bbox.min[2];
94 diag = sqrt(dx * dx + dy * dy + dz * dz);
95 cam_dist = diag / fov;
96 printf("camera distance: %f\n", cam_dist);
98 glutMainLoop();
99 return 0;
100 }
103 void disp(void)
104 {
105 unsigned int tm = glutGet(GLUT_ELAPSED_TIME);
107 if(stereo) {
108 glDrawBuffer(GL_BACK_LEFT);
109 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
111 glMatrixMode(GL_PROJECTION);
112 glLoadIdentity();
113 proj_matrix(-1);
114 glMatrixMode(GL_MODELVIEW);
115 glLoadIdentity();
116 view_matrix(-1);
118 render(tm);
120 glDrawBuffer(GL_BACK_RIGHT);
121 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
123 glMatrixMode(GL_PROJECTION);
124 glLoadIdentity();
125 proj_matrix(1);
126 glMatrixMode(GL_MODELVIEW);
127 glLoadIdentity();
128 view_matrix(1);
130 render(tm);
131 } else {
132 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
134 glMatrixMode(GL_PROJECTION);
135 glLoadIdentity();
136 proj_matrix(0);
137 glMatrixMode(GL_MODELVIEW);
138 glLoadIdentity();
139 view_matrix(0);
141 render(tm);
142 }
144 glutSwapBuffers();
145 }
147 void render(unsigned int msec)
148 {
149 if(auto_rot) {
150 glRotatef(msec / 10, 0, 1, 0);
151 }
152 render_scene(&scn);
153 }
155 void proj_matrix(float eye)
156 {
157 float vfov_rad = fov;
158 float top = near_clip * tan(vfov_rad * 0.5);
159 float right = top * (float)win_width / (float)win_height;
161 float frust_shift = eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist);
163 glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip);
164 }
166 void view_matrix(float eye)
167 {
168 float offs = stereo_eye_sep * eye * 0.5;
169 glTranslatef(offs, 0, 0);
171 glTranslatef(0, 0, -cam_dist);
172 glRotatef(cam_phi, 1, 0, 0);
173 glRotatef(cam_theta, 0, 1, 0);
174 }
176 void idle(void)
177 {
178 glutPostRedisplay();
179 }
181 void reshape(int x, int y)
182 {
183 glViewport(0, 0, x, y);
184 win_width = x;
185 win_height = y;
186 }
188 static int stereo_shift_key;
190 void keyb(unsigned char key, int x, int y)
191 {
192 switch(key) {
193 case 'q':
194 case 27:
195 exit(0);
197 case 's':
198 stereo_shift_key = 1;
199 break;
201 case 'c':
202 {
203 static int flip;
204 glFrontFace((++flip & 1) ? GL_CW : GL_CCW);
205 glutPostRedisplay();
206 }
207 break;
209 case 'C':
210 {
211 static int cull = 1;
212 if(++cull & 1) {
213 glEnable(GL_CULL_FACE);
214 } else {
215 glDisable(GL_CULL_FACE);
216 }
217 glutPostRedisplay();
218 }
219 break;
221 case 'w':
222 {
223 static int wire;
224 glPolygonMode(GL_FRONT_AND_BACK, (++wire & 1) ? GL_LINE : GL_FILL);
225 glutPostRedisplay();
226 }
227 break;
229 case 'l':
230 {
231 static int lit = 1;
232 if(++lit & 1) {
233 glEnable(GL_LIGHTING);
234 } else {
235 glDisable(GL_LIGHTING);
236 }
237 glutPostRedisplay();
238 }
239 break;
241 case ' ':
242 auto_rot = !auto_rot;
243 if(auto_rot) {
244 glutIdleFunc(idle);
245 } else {
246 glutIdleFunc(0);
247 }
248 glutPostRedisplay();
249 break;
251 case 'f':
252 {
253 static int fullscr;
254 static int orig_xsz, orig_ysz;
255 if(++fullscr & 1) {
256 int vp[4];
257 glGetIntegerv(GL_VIEWPORT, vp);
258 orig_xsz = vp[2];
259 orig_ysz = vp[3];
260 glutFullScreen();
261 } else {
262 glutReshapeWindow(orig_xsz, orig_ysz);
263 glutPositionWindow(20, 40);
264 }
265 }
266 break;
268 {
269 static float bgval;
270 case '=':
271 bgval += 0.1;
272 if(bgval > 1.0)
273 bgval = 1.0;
274 glClearColor(bgval, bgval, bgval, 1.0);
275 glutPostRedisplay();
276 break;
278 case '-':
279 bgval -= 0.1;
280 if(bgval < 0.0)
281 bgval = 0.0;
282 glClearColor(bgval, bgval, bgval, 1.0);
283 glutPostRedisplay();
284 break;
285 }
287 default:
288 break;
289 }
290 }
292 void keyb_up(unsigned char key, int x, int y)
293 {
294 switch(key) {
295 case 's':
296 stereo_shift_key = 0;
297 break;
299 default:
300 break;
301 }
302 }
305 static int bnstate[32];
306 static int prev_x, prev_y;
307 void mouse(int bn, int state, int x, int y)
308 {
309 prev_x = x;
310 prev_y = y;
311 bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN ? 1 : 0;
312 }
314 void motion(int x, int y)
315 {
316 int dx = x - prev_x;
317 int dy = y - prev_y;
318 prev_x = x;
319 prev_y = y;
321 if(stereo_shift_key && dy != 0) {
322 stereo_focus_dist += dy * 0.1;
323 stereo_eye_sep = stereo_focus_dist / 30.0;
324 glutPostRedisplay();
325 return;
326 }
328 if(bnstate[0]) {
329 cam_theta += dx * 0.5;
330 cam_phi += dy * 0.5;
332 if(cam_phi < -90)
333 cam_phi = -90;
334 if(cam_phi > 90)
335 cam_phi = 90;
337 glutPostRedisplay();
338 }
339 if(bnstate[2]) {
340 cam_dist += dy * 0.1;
341 glutPostRedisplay();
342 }
343 }
345 void sball_motion(int x, int y, int z)
346 {
347 }
349 void sball_rotate(int x, int y, int z)
350 {
351 cam_theta += y * 0.05;
352 cam_phi += x * 0.05;
354 if(cam_phi < -90)
355 cam_phi = -90;
356 if(cam_phi > 90)
357 cam_phi = 90;
359 glutPostRedisplay();
360 }
362 void sball_button(int bn, int state)
363 {
364 }
366 int parse_args(int argc, char **argv)
367 {
368 int i, num_loaded = 0;
370 for(i=1; i<argc; i++) {
371 if(argv[i][0] == '-') {
372 if(argv[i][2] != 0)
373 goto inval;
374 switch(argv[i][1]) {
375 case 's':
376 stereo = 1;
377 break;
379 case 'c':
380 flip_winding = 1;
381 break;
383 case 'v':
384 verbose = !verbose;
385 break;
387 default:
388 goto inval;
389 }
390 } else {
391 if((load_scene(&scn, argv[i])) == -1) {
392 fprintf(stderr, "failed to load: %s\n", argv[1]);
393 return -1;
394 }
395 num_loaded++;
396 }
397 }
399 if(num_loaded == 0) {
400 fprintf(stderr, "you must pass the filename of a scene to open\n");
401 return -1;
402 }
404 return 0;
406 inval:
407 fprintf(stderr, "invalid argument: %s\n", argv[i]);
408 return -1;
409 }