1/*
2 * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22/*
23 * This is a port of the infamous "glxgears" demo to straight EGL
24 * Port by Dane Rushton 10 July 2005
25 *
26 * No command line options.
27 * Program runs for 5 seconds then exits, outputing framerate to console
28 */
29
30#include <math.h>
31#include "gl_wrap.h"
32#include <EGL/egl.h>
33
34#include "eglut.h"
35
36static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
37static GLint gear1, gear2, gear3;
38static GLfloat angle = 0.0;
39
40/*
41 *
42 *  Draw a gear wheel.  You'll probably want to call this function when
43 *  building a display list since we do a lot of trig here.
44 *
45 *  Input:  inner_radius - radius of hole at center
46 *          outer_radius - radius at center of teeth
47 *          width - width of gear
48 *          teeth - number of teeth
49 *          tooth_depth - depth of tooth
50 */
51static void
52gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
53     GLint teeth, GLfloat tooth_depth)
54{
55   GLint i;
56   GLfloat r0, r1, r2;
57   GLfloat angle, da;
58   GLfloat u, v, len;
59
60   r0 = inner_radius;
61   r1 = outer_radius - tooth_depth / 2.0;
62   r2 = outer_radius + tooth_depth / 2.0;
63
64   da = 2.0 * M_PI / teeth / 4.0;
65
66   glShadeModel(GL_FLAT);
67
68   glNormal3f(0.0, 0.0, 1.0);
69
70   /* draw front face */
71   glBegin(GL_QUAD_STRIP);
72   for (i = 0; i <= teeth; i++) {
73      angle = i * 2.0 * M_PI / teeth;
74      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
75      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
76      if (i < teeth) {
77	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
78	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
79		    width * 0.5);
80      }
81   }
82   glEnd();
83
84   /* draw front sides of teeth */
85   glBegin(GL_QUADS);
86   da = 2.0 * M_PI / teeth / 4.0;
87   for (i = 0; i < teeth; i++) {
88      angle = i * 2.0 * M_PI / teeth;
89
90      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
91      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
92      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
93		 width * 0.5);
94      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
95		 width * 0.5);
96   }
97   glEnd();
98
99   glNormal3f(0.0, 0.0, -1.0);
100
101   /* draw back face */
102   glBegin(GL_QUAD_STRIP);
103   for (i = 0; i <= teeth; i++) {
104      angle = i * 2.0 * M_PI / teeth;
105      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
106      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
107      if (i < teeth) {
108	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
109		    -width * 0.5);
110	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
111      }
112   }
113   glEnd();
114
115   /* draw back sides of teeth */
116   glBegin(GL_QUADS);
117   da = 2.0 * M_PI / teeth / 4.0;
118   for (i = 0; i < teeth; i++) {
119      angle = i * 2.0 * M_PI / teeth;
120
121      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
122		 -width * 0.5);
123      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
124		 -width * 0.5);
125      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
126      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
127   }
128   glEnd();
129
130   /* draw outward faces of teeth */
131   glBegin(GL_QUAD_STRIP);
132   for (i = 0; i < teeth; i++) {
133      angle = i * 2.0 * M_PI / teeth;
134
135      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
136      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
137      u = r2 * cos(angle + da) - r1 * cos(angle);
138      v = r2 * sin(angle + da) - r1 * sin(angle);
139      len = sqrt(u * u + v * v);
140      u /= len;
141      v /= len;
142      glNormal3f(v, -u, 0.0);
143      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
144      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
145      glNormal3f(cos(angle), sin(angle), 0.0);
146      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
147		 width * 0.5);
148      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
149		 -width * 0.5);
150      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
151      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
152      glNormal3f(v, -u, 0.0);
153      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
154		 width * 0.5);
155      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
156		 -width * 0.5);
157      glNormal3f(cos(angle), sin(angle), 0.0);
158   }
159
160   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
161   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
162
163   glEnd();
164
165   glShadeModel(GL_SMOOTH);
166
167   /* draw inside radius cylinder */
168   glBegin(GL_QUAD_STRIP);
169   for (i = 0; i <= teeth; i++) {
170      angle = i * 2.0 * M_PI / teeth;
171      glNormal3f(-cos(angle), -sin(angle), 0.0);
172      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
173      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
174   }
175   glEnd();
176}
177
178
179static void
180draw(void)
181{
182   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
183
184   glPushMatrix();
185   glRotatef(view_rotx, 1.0, 0.0, 0.0);
186   glRotatef(view_roty, 0.0, 1.0, 0.0);
187   glRotatef(view_rotz, 0.0, 0.0, 1.0);
188
189   glPushMatrix();
190   glTranslatef(-3.0, -2.0, 0.0);
191   glRotatef(angle, 0.0, 0.0, 1.0);
192   glCallList(gear1);
193   glPopMatrix();
194
195   glPushMatrix();
196   glTranslatef(3.1, -2.0, 0.0);
197   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
198   glCallList(gear2);
199   glPopMatrix();
200
201   glPushMatrix();
202   glTranslatef(-3.1, 4.2, 0.0);
203   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
204   glCallList(gear3);
205   glPopMatrix();
206
207   glPopMatrix();
208}
209
210
211static void
212idle(void)
213{
214  static double t0 = -1.;
215  double dt, t = eglutGet(EGLUT_ELAPSED_TIME) / 1000.0;
216  if (t0 < 0.0)
217    t0 = t;
218  dt = t - t0;
219  t0 = t;
220
221  angle += 70.0 * dt;  /* 70 degrees per second */
222  angle = fmod(angle, 360.0); /* prevents eventual overflow */
223
224  eglutPostRedisplay();
225}
226
227/* new window size or exposure */
228static void
229reshape(int width, int height)
230{
231   GLfloat h = (GLfloat) height / (GLfloat) width;
232
233   glViewport(0, 0, (GLint) width, (GLint) height);
234
235   glMatrixMode(GL_PROJECTION);
236   glLoadIdentity();
237   glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
238
239   glMatrixMode(GL_MODELVIEW);
240   glLoadIdentity();
241   glTranslatef(0.0, 0.0, -40.0);
242}
243
244
245
246static void
247init(void)
248{
249   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
250   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
251   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
252   static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
253
254   glLightfv(GL_LIGHT0, GL_POSITION, pos);
255   glEnable(GL_CULL_FACE);
256   glEnable(GL_LIGHTING);
257   glEnable(GL_LIGHT0);
258   glEnable(GL_DEPTH_TEST);
259
260   /* make the gears */
261   gear1 = glGenLists(1);
262   glNewList(gear1, GL_COMPILE);
263   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
264   gear(1.0, 4.0, 1.0, 20, 0.7);
265   glEndList();
266
267   gear2 = glGenLists(1);
268   glNewList(gear2, GL_COMPILE);
269   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
270   gear(0.5, 2.0, 2.0, 10, 0.7);
271   glEndList();
272
273   gear3 = glGenLists(1);
274   glNewList(gear3, GL_COMPILE);
275   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
276   gear(1.3, 2.0, 0.5, 10, 0.7);
277   glEndList();
278
279   glEnable(GL_NORMALIZE);
280}
281
282int
283main(int argc, char *argv[])
284{
285   eglutInitWindowSize(300, 300);
286   eglutInitAPIMask(EGLUT_OPENGL_BIT);
287   eglutInit(argc, argv);
288
289   eglutCreateWindow("eglgears");
290
291   eglutIdleFunc(idle);
292   eglutReshapeFunc(reshape);
293   eglutDisplayFunc(draw);
294
295   init();
296   glDrawBuffer(GL_BACK);
297
298   eglutMainLoop();
299
300   return 0;
301}
302