xref: /haiku/src/tests/kits/opengl/demos/gears/gears.c (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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       fflush(stdout);
223       T0 = t;
224       Frames = 0;
225       if ((t >= 999.0 * autoexit) && (autoexit)) {
226         cleanup();
227         exit(0);
228       }
229     }
230   }
231 }
232 
233 
234 static void
235 idle(void)
236 {
237   static double t0 = -1.;
238   double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
239   if (t0 < 0.0)
240     t0 = t;
241   dt = t - t0;
242   t0 = t;
243 
244   angle += 70.0 * dt;  /* 70 degrees per second */
245   angle = fmod(angle, 360.0); /* prevents eventual overflow */
246 
247   glutPostRedisplay();
248 }
249 
250 static void
251 update_idle_func(void)
252 {
253   if (Visible && Animate)
254     glutIdleFunc(idle);
255   else
256     glutIdleFunc(NULL);
257 }
258 
259 /* change view angle, exit upon ESC */
260 /* ARGSUSED1 */
261 static void
262 key(unsigned char k, int x, int y)
263 {
264   switch (k) {
265   case 'z':
266     view_rotz += 5.0;
267     break;
268   case 'Z':
269     view_rotz -= 5.0;
270     break;
271   case 'd':
272      viewDist += 1.0;
273      break;
274   case 'D':
275      viewDist -= 1.0;
276      break;
277   case 'a':
278      Animate = !Animate;
279      update_idle_func();
280      break;
281   case 27:  /* Escape */
282     cleanup();
283     exit(0);
284     break;
285   default:
286     return;
287   }
288   glutPostRedisplay();
289 }
290 
291 /* change view angle */
292 /* ARGSUSED1 */
293 static void
294 special(int k, int x, int y)
295 {
296   switch (k) {
297   case GLUT_KEY_UP:
298     view_rotx += 5.0;
299     break;
300   case GLUT_KEY_DOWN:
301     view_rotx -= 5.0;
302     break;
303   case GLUT_KEY_LEFT:
304     view_roty += 5.0;
305     break;
306   case GLUT_KEY_RIGHT:
307     view_roty -= 5.0;
308     break;
309   default:
310     return;
311   }
312   glutPostRedisplay();
313 }
314 
315 /* new window size or exposure */
316 static void
317 reshape(int width, int height)
318 {
319   GLfloat h = (GLfloat) height / (GLfloat) width;
320 
321   glViewport(0, 0, (GLint) width, (GLint) height);
322   glMatrixMode(GL_PROJECTION);
323   glLoadIdentity();
324   glFrustum(-1.0, 1.0, -h, h, 5.0, 200.0);
325   glMatrixMode(GL_MODELVIEW);
326 }
327 
328 static void
329 init(int argc, char *argv[])
330 {
331   static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
332   static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
333   static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
334   static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
335   GLint i;
336 
337   glLightfv(GL_LIGHT0, GL_POSITION, pos);
338   glEnable(GL_CULL_FACE);
339   glEnable(GL_LIGHTING);
340   glEnable(GL_LIGHT0);
341   glEnable(GL_DEPTH_TEST);
342 
343   /* make the gears */
344   gear1 = glGenLists(1);
345   glNewList(gear1, GL_COMPILE);
346   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
347   gear(1.0, 4.0, 1.0, 20, 0.7);
348   glEndList();
349 
350   gear2 = glGenLists(1);
351   glNewList(gear2, GL_COMPILE);
352   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
353   gear(0.5, 2.0, 2.0, 10, 0.7);
354   glEndList();
355 
356   gear3 = glGenLists(1);
357   glNewList(gear3, GL_COMPILE);
358   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
359   gear(1.3, 2.0, 0.5, 10, 0.7);
360   glEndList();
361 
362   glEnable(GL_NORMALIZE);
363 
364   for ( i=1; i<argc; i++ ) {
365     if (strcmp(argv[i], "-info")==0) {
366       printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
367       printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
368       printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
369       printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
370     }
371     else if ( strcmp(argv[i], "-exit")==0) {
372       autoexit = 30;
373       printf("Auto Exit after %i seconds.\n", autoexit );
374     }
375   }
376 
377   glClearColor(1.0, 1.0, 1.0, 0.0);
378 }
379 
380 
381 static void
382 visible(int vis)
383 {
384    Visible = vis;
385    update_idle_func();
386 }
387 
388 int main(int argc, char *argv[])
389 {
390   glutInit(&argc, argv);
391   glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
392 
393   glutInitWindowPosition(0, 0);
394   glutInitWindowSize(300, 300);
395   win = glutCreateWindow("Gears");
396   init(argc, argv);
397 
398   glutDisplayFunc(draw);
399   glutReshapeFunc(reshape);
400   glutKeyboardFunc(key);
401   glutSpecialFunc(special);
402   glutVisibilityFunc(visible);
403   update_idle_func();
404 
405   glutMainLoop();
406   return 0;             /* ANSI C requires main to return int. */
407 }
408