| #include <stdlib.h> |
| #include <math.h> |
| #include <GL/gl.h> |
| #include "gears.h" |
| |
| struct gears { |
| GLint gear1, gear2, gear3; |
| }; |
| |
| static void |
| gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, |
| GLint teeth, GLfloat tooth_depth) |
| { |
| GLint i; |
| GLfloat r0, r1, r2; |
| GLfloat angle, da; |
| GLfloat u, v, len; |
| |
| r0 = inner_radius; |
| r1 = outer_radius - tooth_depth / 2.0; |
| r2 = outer_radius + tooth_depth / 2.0; |
| |
| da = 2.0 * M_PI / teeth / 4.0; |
| |
| glShadeModel(GL_FLAT); |
| |
| glNormal3f(0.0, 0.0, 1.0); |
| |
| /* draw front face */ |
| glBegin(GL_QUAD_STRIP); |
| for (i = 0; i <= teeth; i++) { |
| angle = i * 2.0 * M_PI / teeth; |
| glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); |
| glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); |
| if (i < teeth) { |
| glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); |
| glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); |
| } |
| } |
| glEnd(); |
| |
| /* draw front sides of teeth */ |
| glBegin(GL_QUADS); |
| da = 2.0 * M_PI / teeth / 4.0; |
| for (i = 0; i < teeth; i++) { |
| angle = i * 2.0 * M_PI / teeth; |
| |
| glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); |
| glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); |
| glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); |
| glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); |
| } |
| glEnd(); |
| |
| glNormal3f(0.0, 0.0, -1.0); |
| |
| /* draw back face */ |
| glBegin(GL_QUAD_STRIP); |
| for (i = 0; i <= teeth; i++) { |
| angle = i * 2.0 * M_PI / teeth; |
| glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); |
| glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); |
| if (i < teeth) { |
| glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); |
| glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); |
| } |
| } |
| glEnd(); |
| |
| /* draw back sides of teeth */ |
| glBegin(GL_QUADS); |
| da = 2.0 * M_PI / teeth / 4.0; |
| for (i = 0; i < teeth; i++) { |
| angle = i * 2.0 * M_PI / teeth; |
| |
| glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); |
| glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); |
| glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); |
| glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); |
| } |
| glEnd(); |
| |
| /* draw outward faces of teeth */ |
| glBegin(GL_QUAD_STRIP); |
| for (i = 0; i < teeth; i++) { |
| angle = i * 2.0 * M_PI / teeth; |
| |
| glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); |
| glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); |
| u = r2 * cos(angle + da) - r1 * cos(angle); |
| v = r2 * sin(angle + da) - r1 * sin(angle); |
| len = sqrt(u * u + v * v); |
| u /= len; |
| v /= len; |
| glNormal3f(v, -u, 0.0); |
| glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); |
| glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); |
| glNormal3f(cos(angle), sin(angle), 0.0); |
| glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); |
| glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); |
| u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); |
| v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); |
| glNormal3f(v, -u, 0.0); |
| glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); |
| glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); |
| glNormal3f(cos(angle), sin(angle), 0.0); |
| } |
| |
| glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); |
| glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); |
| |
| glEnd(); |
| |
| glShadeModel(GL_SMOOTH); |
| |
| /* draw inside radius cylinder */ |
| glBegin(GL_QUAD_STRIP); |
| for (i = 0; i <= teeth; i++) { |
| angle = i * 2.0 * M_PI / teeth; |
| glNormal3f(-cos(angle), -sin(angle), 0.0); |
| glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); |
| glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); |
| } |
| glEnd(); |
| } |
| |
| struct gears * |
| gears_create(GLfloat clear_red, GLfloat clear_green, |
| GLfloat clear_blue, GLfloat clear_alpha) |
| { |
| static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0}; |
| static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0}; |
| static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; |
| static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0}; |
| struct gears *gears; |
| |
| gears = malloc(sizeof *gears); |
| /* make the gears */ |
| gears->gear1 = glGenLists(1); |
| glNewList(gears->gear1, GL_COMPILE); |
| glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); |
| gear(1.0, 4.0, 1.0, 20, 0.7); |
| glEndList(); |
| |
| gears->gear2 = glGenLists(1); |
| glNewList(gears->gear2, GL_COMPILE); |
| glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); |
| gear(0.5, 2.0, 2.0, 10, 0.7); |
| glEndList(); |
| |
| gears->gear3 = glGenLists(1); |
| glNewList(gears->gear3, GL_COMPILE); |
| glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); |
| gear(1.3, 2.0, 0.5, 10, 0.7); |
| glEndList(); |
| |
| glEnable(GL_NORMALIZE); |
| |
| glMatrixMode(GL_PROJECTION); |
| glLoadIdentity(); |
| glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 200.0); |
| glMatrixMode(GL_MODELVIEW); |
| |
| glLightfv(GL_LIGHT0, GL_POSITION, pos); |
| glEnable(GL_CULL_FACE); |
| glEnable(GL_LIGHTING); |
| glEnable(GL_LIGHT0); |
| glEnable(GL_DEPTH_TEST); |
| |
| /* We're generating premultiplied alpha so multiply in the |
| * alpha. The gears are solid color and doesn't have |
| * anti-aliased edges, they're ok. */ |
| glClearColor(clear_red * clear_alpha, |
| clear_green * clear_alpha, |
| clear_blue * clear_alpha, |
| clear_alpha); |
| |
| return gears; |
| } |
| |
| void |
| gears_draw(struct gears *gears, GLfloat angle) |
| { |
| GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; |
| |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
| |
| glPushMatrix(); |
| |
| glTranslatef(0.0, 0.0, -50); |
| |
| glRotatef(view_rotx, 1.0, 0.0, 0.0); |
| glRotatef(view_roty, 0.0, 1.0, 0.0); |
| glRotatef(view_rotz, 0.0, 0.0, 1.0); |
| |
| glPushMatrix(); |
| glTranslatef(-3.0, -2.0, 0.0); |
| glRotatef(angle, 0.0, 0.0, 1.0); |
| glCallList(gears->gear1); |
| glPopMatrix(); |
| |
| glPushMatrix(); |
| glTranslatef(3.1, -2.0, 0.0); |
| glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); |
| glCallList(gears->gear2); |
| glPopMatrix(); |
| |
| |
| glPushMatrix(); |
| glTranslatef(-3.1, 4.2, 0.0); |
| glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); |
| glCallList(gears->gear3); |
| glPopMatrix(); |
| |
| glPopMatrix(); |
| |
| glFlush(); |
| } |