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