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