view3d

view src/main.c @ 5:58ddd42848f9

foo
author John Tsiombikas <nuclear@mutantstargoat.com>
date Thu, 19 Jan 2012 07:37:31 +0200
parents 0aee5df08cfc
children 5562a637e5aa
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 reshape(int x, int y);
20 void keyb(unsigned char key, int x, int y);
21 void keyb_up(unsigned char key, int x, int y);
22 void mouse(int bn, int state, int x, int y);
23 void motion(int x, int y);
24 void sball_motion(int x, int y, int z);
25 void sball_rotate(int x, int y, int z);
26 void sball_button(int bn, int state);
27 int parse_args(int argc, char **argv);
29 char *scene_fname;
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;
51 glutInitWindowSize(800, 600);
52 glutInit(&argc, argv);
54 if(parse_args(argc, argv) == -1) {
55 return 1;
56 }
58 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (stereo ? GLUT_STEREO : 0));
59 glutCreateWindow("OpenGL 3D viewer");
61 glutDisplayFunc(disp);
62 glutReshapeFunc(reshape);
63 glutKeyboardFunc(keyb);
64 glutKeyboardUpFunc(keyb_up);
65 glutMouseFunc(mouse);
66 glutMotionFunc(motion);
67 glutSpaceballMotionFunc(sball_motion);
68 glutSpaceballRotateFunc(sball_rotate);
69 glutSpaceballButtonFunc(sball_button);
70 if(auto_rot) {
71 glutIdleFunc(glutPostRedisplay);
72 }
74 glewInit();
76 glEnable(GL_NORMALIZE);
77 glEnable(GL_DEPTH_TEST);
78 glEnable(GL_CULL_FACE);
79 glEnable(GL_LIGHTING);
80 glEnable(GL_LIGHT0);
81 glLightfv(GL_LIGHT0, GL_POSITION, ldir);
83 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
85 if((load_scene(&scn, scene_fname)) == -1) {
86 fprintf(stderr, "failed to load: %s\n", scene_fname);
87 return 1;
88 }
89 dx = scn.bbox.max[0] - scn.bbox.min[0];
90 dy = scn.bbox.max[1] - scn.bbox.min[1];
91 dz = scn.bbox.max[2] - scn.bbox.min[2];
92 diag = sqrt(dx * dx + dy * dy + dz * dz);
93 cam_dist = diag / fov;
94 printf("camera distance: %f\n", cam_dist);
96 glutMainLoop();
97 return 0;
98 }
101 void disp(void)
102 {
103 unsigned int tm = glutGet(GLUT_ELAPSED_TIME);
105 if(stereo) {
106 glDrawBuffer(GL_BACK_LEFT);
107 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
109 glMatrixMode(GL_PROJECTION);
110 glLoadIdentity();
111 proj_matrix(-1);
112 glMatrixMode(GL_MODELVIEW);
113 glLoadIdentity();
114 view_matrix(-1);
116 render(tm);
118 glDrawBuffer(GL_BACK_RIGHT);
119 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
121 glMatrixMode(GL_PROJECTION);
122 glLoadIdentity();
123 proj_matrix(1);
124 glMatrixMode(GL_MODELVIEW);
125 glLoadIdentity();
126 view_matrix(1);
128 render(tm);
129 } else {
130 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
132 glMatrixMode(GL_PROJECTION);
133 glLoadIdentity();
134 proj_matrix(0);
135 glMatrixMode(GL_MODELVIEW);
136 glLoadIdentity();
137 view_matrix(0);
139 render(tm);
140 }
142 glutSwapBuffers();
143 }
145 void render(unsigned int msec)
146 {
147 if(auto_rot) {
148 glRotatef(msec / 10, 0, 1, 0);
149 }
150 render_scene(&scn);
151 }
153 void proj_matrix(float eye)
154 {
155 float vfov_rad = fov;
156 float top = near_clip * tan(vfov_rad * 0.5);
157 float right = top * (float)win_width / (float)win_height;
159 float frust_shift = eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist);
161 glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip);
162 }
164 void view_matrix(float eye)
165 {
166 float offs = stereo_eye_sep * eye * 0.5;
167 glTranslatef(offs, 0, 0);
169 glTranslatef(0, 0, -cam_dist);
170 glRotatef(cam_phi, 1, 0, 0);
171 glRotatef(cam_theta, 0, 1, 0);
172 }
174 void reshape(int x, int y)
175 {
176 glViewport(0, 0, x, y);
177 win_width = x;
178 win_height = y;
179 }
181 static int stereo_shift_key;
183 void keyb(unsigned char key, int x, int y)
184 {
185 switch(key) {
186 case 'q':
187 case 27:
188 exit(0);
190 case 's':
191 stereo_shift_key = 1;
192 break;
194 case 'c':
195 {
196 static int flip;
197 glFrontFace((++flip & 1) ? GL_CW : GL_CCW);
198 glutPostRedisplay();
199 }
200 break;
202 case 'C':
203 {
204 static int cull = 1;
205 if(++cull & 1) {
206 glEnable(GL_CULL_FACE);
207 } else {
208 glDisable(GL_CULL_FACE);
209 }
210 glutPostRedisplay();
211 }
212 break;
214 case 'w':
215 {
216 static int wire;
217 glPolygonMode(GL_FRONT_AND_BACK, (++wire & 1) ? GL_LINE : GL_FILL);
218 glutPostRedisplay();
219 }
220 break;
222 case 'l':
223 {
224 static int lit = 1;
225 if(++lit & 1) {
226 glEnable(GL_LIGHTING);
227 } else {
228 glDisable(GL_LIGHTING);
229 }
230 glutPostRedisplay();
231 }
232 break;
234 case ' ':
235 auto_rot = !auto_rot;
236 if(auto_rot) {
237 glutIdleFunc(glutPostRedisplay);
238 } else {
239 glutIdleFunc(0);
240 }
241 glutPostRedisplay();
242 break;
244 case 'f':
245 {
246 static int fullscr;
247 if(++fullscr & 1) {
248 glutFullScreen();
249 } else {
250 glutPositionWindow(20, 20);
251 }
252 }
253 break;
255 {
256 static float bgval;
257 case '=':
258 bgval += 0.1;
259 if(bgval > 1.0)
260 bgval = 1.0;
261 glClearColor(bgval, bgval, bgval, 1.0);
262 glutPostRedisplay();
263 break;
265 case '-':
266 bgval -= 0.1;
267 if(bgval < 0.0)
268 bgval = 0.0;
269 glClearColor(bgval, bgval, bgval, 1.0);
270 glutPostRedisplay();
271 break;
272 }
274 default:
275 break;
276 }
277 }
279 void keyb_up(unsigned char key, int x, int y)
280 {
281 switch(key) {
282 case 's':
283 stereo_shift_key = 0;
284 break;
286 default:
287 break;
288 }
289 }
292 static int bnstate[32];
293 static int prev_x, prev_y;
294 void mouse(int bn, int state, int x, int y)
295 {
296 prev_x = x;
297 prev_y = y;
298 bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN ? 1 : 0;
299 }
301 void motion(int x, int y)
302 {
303 int dx = x - prev_x;
304 int dy = y - prev_y;
305 prev_x = x;
306 prev_y = y;
308 if(stereo_shift_key && dy != 0) {
309 stereo_focus_dist += dy * 0.1;
310 stereo_eye_sep = stereo_focus_dist / 30.0;
311 glutPostRedisplay();
312 return;
313 }
315 if(bnstate[0]) {
316 cam_theta += dx * 0.5;
317 cam_phi += dy * 0.5;
319 if(cam_phi < -90)
320 cam_phi = -90;
321 if(cam_phi > 90)
322 cam_phi = 90;
324 glutPostRedisplay();
325 }
326 if(bnstate[2]) {
327 cam_dist += dy * 0.1;
328 glutPostRedisplay();
329 }
330 }
332 void sball_motion(int x, int y, int z)
333 {
334 }
336 void sball_rotate(int x, int y, int z)
337 {
338 cam_theta += y * 0.05;
339 cam_phi += x * 0.05;
341 if(cam_phi < -90)
342 cam_phi = -90;
343 if(cam_phi > 90)
344 cam_phi = 90;
346 glutPostRedisplay();
347 }
349 void sball_button(int bn, int state)
350 {
351 }
353 int parse_args(int argc, char **argv)
354 {
355 int i;
357 for(i=1; i<argc; i++) {
358 if(argv[i][0] == '-') {
359 if(argv[i][2] != 0)
360 goto inval;
361 switch(argv[i][1]) {
362 case 's':
363 stereo = 1;
364 break;
366 case 'c':
367 flip_winding = 1;
368 break;
370 case 'v':
371 verbose = !verbose;
372 break;
374 default:
375 goto inval;
376 }
377 } else {
378 if(scene_fname) {
379 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
380 return -1;
381 }
382 scene_fname = argv[i];
383 }
384 }
386 if(!scene_fname) {
387 fprintf(stderr, "you must pass the filename of a scene to open\n");
388 return -1;
389 }
391 return 0;
393 inval:
394 fprintf(stderr, "invalid argument: %s\n", argv[i]);
395 return -1;
396 }