1 | /*
|
---|
2 | * 3-D gear wheels. This program is in the public domain.
|
---|
3 | *
|
---|
4 | * Command line options:
|
---|
5 | * -info print GL implementation information
|
---|
6 | * -exit automatically exit after 30 seconds
|
---|
7 | *
|
---|
8 | *
|
---|
9 | * Brian Paul
|
---|
10 | */
|
---|
11 |
|
---|
12 | /* Conversion to GLUT by Mark J. Kilgard */
|
---|
13 |
|
---|
14 |
|
---|
15 |
|
---|
16 | #include <math.h>
|
---|
17 | #include <stdlib.h>
|
---|
18 | #include <stdio.h>
|
---|
19 | #include <string.h>
|
---|
20 | #include <GL/glut.h>
|
---|
21 |
|
---|
22 | #ifndef M_PI
|
---|
23 | #define M_PI 3.14159265
|
---|
24 | #endif
|
---|
25 |
|
---|
26 | static GLint T0 = 0;
|
---|
27 | static GLint Frames = 0;
|
---|
28 | static GLint autoexit = 0;
|
---|
29 | static GLint win = 0;
|
---|
30 | static GLboolean Visible = GL_TRUE;
|
---|
31 | static GLboolean Animate = GL_TRUE;
|
---|
32 | static GLfloat viewDist = 40.0;
|
---|
33 |
|
---|
34 |
|
---|
35 | /**
|
---|
36 |
|
---|
37 | Draw a gear wheel. You'll probably want to call this function when
|
---|
38 | building a display list since we do a lot of trig here.
|
---|
39 |
|
---|
40 | Input: inner_radius - radius of hole at center
|
---|
41 | outer_radius - radius at center of teeth
|
---|
42 | width - width of gear
|
---|
43 | teeth - number of teeth
|
---|
44 | tooth_depth - depth of tooth
|
---|
45 |
|
---|
46 | **/
|
---|
47 |
|
---|
48 | static void
|
---|
49 | gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
|
---|
50 | GLint teeth, GLfloat tooth_depth)
|
---|
51 | {
|
---|
52 | GLint i;
|
---|
53 | GLfloat r0, r1, r2;
|
---|
54 | GLfloat angle, da;
|
---|
55 | GLfloat u, v, len;
|
---|
56 |
|
---|
57 | r0 = inner_radius;
|
---|
58 | r1 = outer_radius - tooth_depth / 2.0;
|
---|
59 | r2 = outer_radius + tooth_depth / 2.0;
|
---|
60 |
|
---|
61 | da = 2.0 * M_PI / teeth / 4.0;
|
---|
62 |
|
---|
63 | glShadeModel(GL_FLAT);
|
---|
64 |
|
---|
65 | glNormal3f(0.0, 0.0, 1.0);
|
---|
66 |
|
---|
67 | /* draw front face */
|
---|
68 | glBegin(GL_QUAD_STRIP);
|
---|
69 | for (i = 0; i <= teeth; i++) {
|
---|
70 | angle = i * 2.0 * M_PI / teeth;
|
---|
71 | glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
---|
72 | glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
---|
73 | if (i < teeth) {
|
---|
74 | glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
---|
75 | glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
|
---|
76 | }
|
---|
77 | }
|
---|
78 | glEnd();
|
---|
79 |
|
---|
80 | /* draw front sides of teeth */
|
---|
81 | glBegin(GL_QUADS);
|
---|
82 | da = 2.0 * M_PI / teeth / 4.0;
|
---|
83 | for (i = 0; i < teeth; i++) {
|
---|
84 | angle = i * 2.0 * M_PI / teeth;
|
---|
85 |
|
---|
86 | glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
---|
87 | glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
|
---|
88 | glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
|
---|
89 | glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
|
---|
90 | }
|
---|
91 | glEnd();
|
---|
92 |
|
---|
93 | glNormal3f(0.0, 0.0, -1.0);
|
---|
94 |
|
---|
95 | /* draw back face */
|
---|
96 | glBegin(GL_QUAD_STRIP);
|
---|
97 | for (i = 0; i <= teeth; i++) {
|
---|
98 | angle = i * 2.0 * M_PI / teeth;
|
---|
99 | glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
---|
100 | glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
---|
101 | if (i < teeth) {
|
---|
102 | glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
|
---|
103 | glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
---|
104 | }
|
---|
105 | }
|
---|
106 | glEnd();
|
---|
107 |
|
---|
108 | /* draw back sides of teeth */
|
---|
109 | glBegin(GL_QUADS);
|
---|
110 | da = 2.0 * M_PI / teeth / 4.0;
|
---|
111 | for (i = 0; i < teeth; i++) {
|
---|
112 | angle = i * 2.0 * M_PI / teeth;
|
---|
113 |
|
---|
114 | glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
|
---|
115 | glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
|
---|
116 | glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
|
---|
117 | glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
---|
118 | }
|
---|
119 | glEnd();
|
---|
120 |
|
---|
121 | /* draw outward faces of teeth */
|
---|
122 | glBegin(GL_QUAD_STRIP);
|
---|
123 | for (i = 0; i < teeth; i++) {
|
---|
124 | angle = i * 2.0 * M_PI / teeth;
|
---|
125 |
|
---|
126 | glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
---|
127 | glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
---|
128 | u = r2 * cos(angle + da) - r1 * cos(angle);
|
---|
129 | v = r2 * sin(angle + da) - r1 * sin(angle);
|
---|
130 | len = sqrt(u * u + v * v);
|
---|
131 | u /= len;
|
---|
132 | v /= len;
|
---|
133 | glNormal3f(v, -u, 0.0);
|
---|
134 | glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
|
---|
135 | glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
|
---|
136 | glNormal3f(cos(angle), sin(angle), 0.0);
|
---|
137 | glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
|
---|
138 | glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
|
---|
139 | u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
|
---|
140 | v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
|
---|
141 | glNormal3f(v, -u, 0.0);
|
---|
142 | glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
|
---|
143 | glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
|
---|
144 | glNormal3f(cos(angle), sin(angle), 0.0);
|
---|
145 | }
|
---|
146 |
|
---|
147 | glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
|
---|
148 | glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
|
---|
149 |
|
---|
150 | glEnd();
|
---|
151 |
|
---|
152 | glShadeModel(GL_SMOOTH);
|
---|
153 |
|
---|
154 | /* draw inside radius cylinder */
|
---|
155 | glBegin(GL_QUAD_STRIP);
|
---|
156 | for (i = 0; i <= teeth; i++) {
|
---|
157 | angle = i * 2.0 * M_PI / teeth;
|
---|
158 | glNormal3f(-cos(angle), -sin(angle), 0.0);
|
---|
159 | glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
---|
160 | glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
---|
161 | }
|
---|
162 | glEnd();
|
---|
163 |
|
---|
164 | }
|
---|
165 |
|
---|
166 | static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
|
---|
167 | static GLint gear1, gear2, gear3;
|
---|
168 | static GLfloat angle = 0.0;
|
---|
169 |
|
---|
170 | static void
|
---|
171 | cleanup(void)
|
---|
172 | {
|
---|
173 | glDeleteLists(gear1, 1);
|
---|
174 | glDeleteLists(gear2, 1);
|
---|
175 | glDeleteLists(gear3, 1);
|
---|
176 | glutDestroyWindow(win);
|
---|
177 | }
|
---|
178 |
|
---|
179 | static void
|
---|
180 | draw(void)
|
---|
181 | {
|
---|
182 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
---|
183 |
|
---|
184 | glPushMatrix();
|
---|
185 |
|
---|
186 | glTranslatef(0.0, 0.0, -viewDist);
|
---|
187 |
|
---|
188 | glRotatef(view_rotx, 1.0, 0.0, 0.0);
|
---|
189 | glRotatef(view_roty, 0.0, 1.0, 0.0);
|
---|
190 | glRotatef(view_rotz, 0.0, 0.0, 1.0);
|
---|
191 |
|
---|
192 | glPushMatrix();
|
---|
193 | glTranslatef(-3.0, -2.0, 0.0);
|
---|
194 | glRotatef(angle, 0.0, 0.0, 1.0);
|
---|
195 | glCallList(gear1);
|
---|
196 | glPopMatrix();
|
---|
197 |
|
---|
198 | glPushMatrix();
|
---|
199 | glTranslatef(3.1, -2.0, 0.0);
|
---|
200 | glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
|
---|
201 | glCallList(gear2);
|
---|
202 | glPopMatrix();
|
---|
203 |
|
---|
204 | glPushMatrix();
|
---|
205 | glTranslatef(-3.1, 4.2, 0.0);
|
---|
206 | glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
|
---|
207 | glCallList(gear3);
|
---|
208 | glPopMatrix();
|
---|
209 |
|
---|
210 | glPopMatrix();
|
---|
211 |
|
---|
212 | glutSwapBuffers();
|
---|
213 |
|
---|
214 | Frames++;
|
---|
215 |
|
---|
216 | {
|
---|
217 | GLint t = glutGet(GLUT_ELAPSED_TIME);
|
---|
218 | if (t - T0 >= 5000) {
|
---|
219 | GLfloat seconds = (t - T0) / 1000.0;
|
---|
220 | GLfloat fps = Frames / seconds;
|
---|
221 | printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
|
---|
222 | T0 = t;
|
---|
223 | Frames = 0;
|
---|
224 | if ((t >= 999.0 * autoexit) && (autoexit)) {
|
---|
225 | cleanup();
|
---|
226 | exit(0);
|
---|
227 | }
|
---|
228 | }
|
---|
229 | }
|
---|
230 | }
|
---|
231 |
|
---|
232 |
|
---|
233 | static void
|
---|
234 | idle(void)
|
---|
235 | {
|
---|
236 | static double t0 = -1.;
|
---|
237 | double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
|
---|
238 | if (t0 < 0.0)
|
---|
239 | t0 = t;
|
---|
240 | dt = t - t0;
|
---|
241 | t0 = t;
|
---|
242 |
|
---|
243 | angle += 70.0 * dt; /* 70 degrees per second */
|
---|
244 | angle = fmod(angle, 360.0); /* prevents eventual overflow */
|
---|
245 |
|
---|
246 | glutPostRedisplay();
|
---|
247 | }
|
---|
248 |
|
---|
249 | static void
|
---|
250 | update_idle_func(void)
|
---|
251 | {
|
---|
252 | if (Visible && Animate)
|
---|
253 | glutIdleFunc(idle);
|
---|
254 | else
|
---|
255 | glutIdleFunc(NULL);
|
---|
256 | }
|
---|
257 |
|
---|
258 | /* change view angle, exit upon ESC */
|
---|
259 | /* ARGSUSED1 */
|
---|
260 | static void
|
---|
261 | key(unsigned char k, int x, int y)
|
---|
262 | {
|
---|
263 | switch (k) {
|
---|
264 | case 'z':
|
---|
265 | view_rotz += 5.0;
|
---|
266 | break;
|
---|
267 | case 'Z':
|
---|
268 | view_rotz -= 5.0;
|
---|
269 | break;
|
---|
270 | case 'd':
|
---|
271 | viewDist += 1.0;
|
---|
272 | break;
|
---|
273 | case 'D':
|
---|
274 | viewDist -= 1.0;
|
---|
275 | break;
|
---|
276 | case 'a':
|
---|
277 | Animate = !Animate;
|
---|
278 | update_idle_func();
|
---|
279 | break;
|
---|
280 | case 27: /* Escape */
|
---|
281 | cleanup();
|
---|
282 | exit(0);
|
---|
283 | break;
|
---|
284 | default:
|
---|
285 | return;
|
---|
286 | }
|
---|
287 | glutPostRedisplay();
|
---|
288 | }
|
---|
289 |
|
---|
290 | /* change view angle */
|
---|
291 | /* ARGSUSED1 */
|
---|
292 | static void
|
---|
293 | special(int k, int x, int y)
|
---|
294 | {
|
---|
295 | switch (k) {
|
---|
296 | case GLUT_KEY_UP:
|
---|
297 | view_rotx += 5.0;
|
---|
298 | break;
|
---|
299 | case GLUT_KEY_DOWN:
|
---|
300 | view_rotx -= 5.0;
|
---|
301 | break;
|
---|
302 | case GLUT_KEY_LEFT:
|
---|
303 | view_roty += 5.0;
|
---|
304 | break;
|
---|
305 | case GLUT_KEY_RIGHT:
|
---|
306 | view_roty -= 5.0;
|
---|
307 | break;
|
---|
308 | default:
|
---|
309 | return;
|
---|
310 | }
|
---|
311 | glutPostRedisplay();
|
---|
312 | }
|
---|
313 |
|
---|
314 | /* new window size or exposure */
|
---|
315 | static void
|
---|
316 | reshape(int width, int height)
|
---|
317 | {
|
---|
318 | GLfloat h = (GLfloat) height / (GLfloat) width;
|
---|
319 |
|
---|
320 | glViewport(0, 0, (GLint) width, (GLint) height);
|
---|
321 | glMatrixMode(GL_PROJECTION);
|
---|
322 | glLoadIdentity();
|
---|
323 | glFrustum(-1.0, 1.0, -h, h, 5.0, 200.0);
|
---|
324 | glMatrixMode(GL_MODELVIEW);
|
---|
325 | }
|
---|
326 |
|
---|
327 | static void
|
---|
328 | init(int argc, char *argv[])
|
---|
329 | {
|
---|
330 | static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
|
---|
331 | static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
|
---|
332 | static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
|
---|
333 | static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
|
---|
334 | GLint i;
|
---|
335 |
|
---|
336 | glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
---|
337 | glEnable(GL_CULL_FACE);
|
---|
338 | glEnable(GL_LIGHTING);
|
---|
339 | glEnable(GL_LIGHT0);
|
---|
340 | glEnable(GL_DEPTH_TEST);
|
---|
341 |
|
---|
342 | /* make the gears */
|
---|
343 | gear1 = glGenLists(1);
|
---|
344 | glNewList(gear1, GL_COMPILE);
|
---|
345 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
|
---|
346 | gear(1.0, 4.0, 1.0, 20, 0.7);
|
---|
347 | glEndList();
|
---|
348 |
|
---|
349 | gear2 = glGenLists(1);
|
---|
350 | glNewList(gear2, GL_COMPILE);
|
---|
351 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
|
---|
352 | gear(0.5, 2.0, 2.0, 10, 0.7);
|
---|
353 | glEndList();
|
---|
354 |
|
---|
355 | gear3 = glGenLists(1);
|
---|
356 | glNewList(gear3, GL_COMPILE);
|
---|
357 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
|
---|
358 | gear(1.3, 2.0, 0.5, 10, 0.7);
|
---|
359 | glEndList();
|
---|
360 |
|
---|
361 | glEnable(GL_NORMALIZE);
|
---|
362 |
|
---|
363 | for ( i=1; i<argc; i++ ) {
|
---|
364 | if (strcmp(argv[i], "-info")==0) {
|
---|
365 | printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
---|
366 | printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
---|
367 | printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
---|
368 | printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
---|
369 | }
|
---|
370 | else if ( strcmp(argv[i], "-exit")==0) {
|
---|
371 | autoexit = 30;
|
---|
372 | printf("Auto Exit after %i seconds.\n", autoexit );
|
---|
373 | }
|
---|
374 | }
|
---|
375 | }
|
---|
376 |
|
---|
377 |
|
---|
378 | static void
|
---|
379 | visible(int vis)
|
---|
380 | {
|
---|
381 | Visible = vis;
|
---|
382 | update_idle_func();
|
---|
383 | }
|
---|
384 |
|
---|
385 | int main(int argc, char *argv[])
|
---|
386 | {
|
---|
387 | glutInit(&argc, argv);
|
---|
388 | glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
|
---|
389 |
|
---|
390 | glutInitWindowPosition(0, 0);
|
---|
391 | glutInitWindowSize(300, 300);
|
---|
392 | win = glutCreateWindow("Gears");
|
---|
393 | init(argc, argv);
|
---|
394 |
|
---|
395 | glutDisplayFunc(draw);
|
---|
396 | glutReshapeFunc(reshape);
|
---|
397 | glutKeyboardFunc(key);
|
---|
398 | glutSpecialFunc(special);
|
---|
399 | glutVisibilityFunc(visible);
|
---|
400 | update_idle_func();
|
---|
401 |
|
---|
402 | glutMainLoop();
|
---|
403 | return 0; /* ANSI C requires main to return int. */
|
---|
404 | }
|
---|