132001f49Smrg/* 232001f49Smrg * 3-D gear wheels. This program is in the public domain. 332001f49Smrg * 432001f49Smrg * Command line options: 532001f49Smrg * -info print GL implementation information 632001f49Smrg * -exit automatically exit after 30 seconds 732001f49Smrg * -noanim turn off animation 832001f49Smrg * 932001f49Smrg * 1032001f49Smrg * Brian Paul 1132001f49Smrg */ 1232001f49Smrg 1332001f49Smrg/* Conversion to GLUT by Mark J. Kilgard */ 1432001f49Smrg 1532001f49Smrg 1632001f49Smrg 1732001f49Smrg#include <math.h> 1832001f49Smrg#include <stdlib.h> 1932001f49Smrg#include <stdio.h> 2032001f49Smrg#include <string.h> 2132001f49Smrg#include "glut_wrap.h" 2232001f49Smrg 2332001f49Smrg#ifndef M_PI 2432001f49Smrg#define M_PI 3.14159265 2532001f49Smrg#endif 2632001f49Smrg 2732001f49Smrgstatic GLint T0 = 0; 2832001f49Smrgstatic GLint Frames = 0; 2932001f49Smrgstatic GLint autoexit = 0; 3032001f49Smrgstatic GLint win = 0; 3132001f49Smrgstatic GLboolean Visible = GL_TRUE; 3232001f49Smrgstatic GLboolean Animate = GL_TRUE; 3332001f49Smrgstatic GLfloat viewDist = 40.0; 3432001f49Smrg 3532001f49Smrg 3632001f49Smrg/** 3732001f49Smrg 3832001f49Smrg Draw a gear wheel. You'll probably want to call this function when 3932001f49Smrg building a display list since we do a lot of trig here. 4032001f49Smrg 4132001f49Smrg Input: inner_radius - radius of hole at center 4232001f49Smrg outer_radius - radius at center of teeth 4332001f49Smrg width - width of gear 4432001f49Smrg teeth - number of teeth 4532001f49Smrg tooth_depth - depth of tooth 4632001f49Smrg 4732001f49Smrg **/ 4832001f49Smrg 4932001f49Smrgstatic void 5032001f49Smrggear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, 5132001f49Smrg GLint teeth, GLfloat tooth_depth) 5232001f49Smrg{ 5332001f49Smrg GLint i; 5432001f49Smrg GLfloat r0, r1, r2; 5532001f49Smrg GLfloat angle, da; 5632001f49Smrg GLfloat u, v, len; 5732001f49Smrg 5832001f49Smrg r0 = inner_radius; 5932001f49Smrg r1 = outer_radius - tooth_depth / 2.0; 6032001f49Smrg r2 = outer_radius + tooth_depth / 2.0; 6132001f49Smrg 6232001f49Smrg da = 2.0 * M_PI / teeth / 4.0; 6332001f49Smrg 6432001f49Smrg glShadeModel(GL_FLAT); 6532001f49Smrg 6632001f49Smrg glNormal3f(0.0, 0.0, 1.0); 6732001f49Smrg 6832001f49Smrg /* draw front face */ 6932001f49Smrg glBegin(GL_QUAD_STRIP); 7032001f49Smrg for (i = 0; i <= teeth; i++) { 7132001f49Smrg angle = i * 2.0 * M_PI / teeth; 7232001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 7332001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 7432001f49Smrg if (i < teeth) { 7532001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 7632001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); 7732001f49Smrg } 7832001f49Smrg } 7932001f49Smrg glEnd(); 8032001f49Smrg 8132001f49Smrg /* draw front sides of teeth */ 8232001f49Smrg glBegin(GL_QUADS); 8332001f49Smrg da = 2.0 * M_PI / teeth / 4.0; 8432001f49Smrg for (i = 0; i < teeth; i++) { 8532001f49Smrg angle = i * 2.0 * M_PI / teeth; 8632001f49Smrg 8732001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 8832001f49Smrg glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 8932001f49Smrg glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); 9032001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); 9132001f49Smrg } 9232001f49Smrg glEnd(); 9332001f49Smrg 9432001f49Smrg glNormal3f(0.0, 0.0, -1.0); 9532001f49Smrg 9632001f49Smrg /* draw back face */ 9732001f49Smrg glBegin(GL_QUAD_STRIP); 9832001f49Smrg for (i = 0; i <= teeth; i++) { 9932001f49Smrg angle = i * 2.0 * M_PI / teeth; 10032001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 10132001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 10232001f49Smrg if (i < teeth) { 10332001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); 10432001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 10532001f49Smrg } 10632001f49Smrg } 10732001f49Smrg glEnd(); 10832001f49Smrg 10932001f49Smrg /* draw back sides of teeth */ 11032001f49Smrg glBegin(GL_QUADS); 11132001f49Smrg da = 2.0 * M_PI / teeth / 4.0; 11232001f49Smrg for (i = 0; i < teeth; i++) { 11332001f49Smrg angle = i * 2.0 * M_PI / teeth; 11432001f49Smrg 11532001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); 11632001f49Smrg glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); 11732001f49Smrg glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 11832001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 11932001f49Smrg } 12032001f49Smrg glEnd(); 12132001f49Smrg 12232001f49Smrg /* draw outward faces of teeth */ 12332001f49Smrg glBegin(GL_QUAD_STRIP); 12432001f49Smrg for (i = 0; i < teeth; i++) { 12532001f49Smrg angle = i * 2.0 * M_PI / teeth; 12632001f49Smrg 12732001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 12832001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 12932001f49Smrg u = r2 * cos(angle + da) - r1 * cos(angle); 13032001f49Smrg v = r2 * sin(angle + da) - r1 * sin(angle); 13132001f49Smrg len = sqrt(u * u + v * v); 13232001f49Smrg u /= len; 13332001f49Smrg v /= len; 13432001f49Smrg glNormal3f(v, -u, 0.0); 13532001f49Smrg glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 13632001f49Smrg glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 13732001f49Smrg glNormal3f(cos(angle), sin(angle), 0.0); 13832001f49Smrg glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); 13932001f49Smrg glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); 14032001f49Smrg u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); 14132001f49Smrg v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); 14232001f49Smrg glNormal3f(v, -u, 0.0); 14332001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); 14432001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); 14532001f49Smrg glNormal3f(cos(angle), sin(angle), 0.0); 14632001f49Smrg } 14732001f49Smrg 14832001f49Smrg glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); 14932001f49Smrg glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); 15032001f49Smrg 15132001f49Smrg glEnd(); 15232001f49Smrg 15332001f49Smrg glShadeModel(GL_SMOOTH); 15432001f49Smrg 15532001f49Smrg /* draw inside radius cylinder */ 15632001f49Smrg glBegin(GL_QUAD_STRIP); 15732001f49Smrg for (i = 0; i <= teeth; i++) { 15832001f49Smrg angle = i * 2.0 * M_PI / teeth; 15932001f49Smrg glNormal3f(-cos(angle), -sin(angle), 0.0); 16032001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 16132001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 16232001f49Smrg } 16332001f49Smrg glEnd(); 16432001f49Smrg 16532001f49Smrg} 16632001f49Smrg 16732001f49Smrgstatic GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; 16832001f49Smrgstatic GLint gear1, gear2, gear3; 16932001f49Smrgstatic GLfloat angle = 0.0; 17032001f49Smrg 17132001f49Smrgstatic void 17232001f49Smrgcleanup(void) 17332001f49Smrg{ 17432001f49Smrg glDeleteLists(gear1, 1); 17532001f49Smrg glDeleteLists(gear2, 1); 17632001f49Smrg glDeleteLists(gear3, 1); 17732001f49Smrg glutDestroyWindow(win); 17832001f49Smrg} 17932001f49Smrg 18032001f49Smrgstatic void 18132001f49Smrgdraw(void) 18232001f49Smrg{ 18332001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 18432001f49Smrg 18532001f49Smrg glPushMatrix(); 18632001f49Smrg 18732001f49Smrg glTranslatef(0.0, 0.0, -viewDist); 18832001f49Smrg 18932001f49Smrg glRotatef(view_rotx, 1.0, 0.0, 0.0); 19032001f49Smrg glRotatef(view_roty, 0.0, 1.0, 0.0); 19132001f49Smrg glRotatef(view_rotz, 0.0, 0.0, 1.0); 19232001f49Smrg 19332001f49Smrg glPushMatrix(); 19432001f49Smrg glTranslatef(-3.0, -2.0, 0.0); 19532001f49Smrg glRotatef(angle, 0.0, 0.0, 1.0); 19632001f49Smrg glCallList(gear1); 19732001f49Smrg glPopMatrix(); 19832001f49Smrg 19932001f49Smrg glPushMatrix(); 20032001f49Smrg glTranslatef(3.1, -2.0, 0.0); 20132001f49Smrg glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); 20232001f49Smrg glCallList(gear2); 20332001f49Smrg glPopMatrix(); 20432001f49Smrg 20532001f49Smrg glPushMatrix(); 20632001f49Smrg glTranslatef(-3.1, 4.2, 0.0); 20732001f49Smrg glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); 20832001f49Smrg glCallList(gear3); 20932001f49Smrg glPopMatrix(); 21032001f49Smrg 21132001f49Smrg glPopMatrix(); 21232001f49Smrg 21332001f49Smrg glutSwapBuffers(); 21432001f49Smrg 21532001f49Smrg Frames++; 21632001f49Smrg 21732001f49Smrg { 21832001f49Smrg GLint t = glutGet(GLUT_ELAPSED_TIME); 21932001f49Smrg if (t - T0 >= 5000) { 22032001f49Smrg GLfloat seconds = (t - T0) / 1000.0; 22132001f49Smrg GLfloat fps = Frames / seconds; 22232001f49Smrg printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps); 22332001f49Smrg fflush(stdout); 22432001f49Smrg T0 = t; 22532001f49Smrg Frames = 0; 22632001f49Smrg if ((t >= 999.0 * autoexit) && (autoexit)) { 22732001f49Smrg cleanup(); 22832001f49Smrg exit(0); 22932001f49Smrg } 23032001f49Smrg } 23132001f49Smrg } 23232001f49Smrg} 23332001f49Smrg 23432001f49Smrg 23532001f49Smrgstatic void 23632001f49Smrgidle(void) 23732001f49Smrg{ 23832001f49Smrg static double t0 = -1.; 23932001f49Smrg double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; 24032001f49Smrg if (t0 < 0.0) 24132001f49Smrg t0 = t; 24232001f49Smrg dt = t - t0; 24332001f49Smrg t0 = t; 24432001f49Smrg 24532001f49Smrg angle += 70.0 * dt; /* 70 degrees per second */ 24632001f49Smrg angle = fmod(angle, 360.0); /* prevents eventual overflow */ 24732001f49Smrg 24832001f49Smrg glutPostRedisplay(); 24932001f49Smrg} 25032001f49Smrg 25132001f49Smrgstatic void 25232001f49Smrgupdate_idle_func(void) 25332001f49Smrg{ 25432001f49Smrg if (Visible && Animate) 25532001f49Smrg glutIdleFunc(idle); 25632001f49Smrg else 25732001f49Smrg glutIdleFunc(NULL); 25832001f49Smrg} 25932001f49Smrg 26032001f49Smrg/* change view angle, exit upon ESC */ 26132001f49Smrg/* ARGSUSED1 */ 26232001f49Smrgstatic void 26332001f49Smrgkey(unsigned char k, int x, int y) 26432001f49Smrg{ 26532001f49Smrg switch (k) { 26632001f49Smrg case 'z': 26732001f49Smrg view_rotz += 5.0; 26832001f49Smrg break; 26932001f49Smrg case 'Z': 27032001f49Smrg view_rotz -= 5.0; 27132001f49Smrg break; 27232001f49Smrg case 'd': 27332001f49Smrg viewDist += 1.0; 27432001f49Smrg break; 27532001f49Smrg case 'D': 27632001f49Smrg viewDist -= 1.0; 27732001f49Smrg break; 27832001f49Smrg case 'a': 27932001f49Smrg Animate = !Animate; 28032001f49Smrg update_idle_func(); 28132001f49Smrg break; 28232001f49Smrg case 27: /* Escape */ 28332001f49Smrg cleanup(); 28432001f49Smrg exit(0); 28532001f49Smrg break; 28632001f49Smrg default: 28732001f49Smrg return; 28832001f49Smrg } 28932001f49Smrg glutPostRedisplay(); 29032001f49Smrg} 29132001f49Smrg 29232001f49Smrg/* change view angle */ 29332001f49Smrg/* ARGSUSED1 */ 29432001f49Smrgstatic void 29532001f49Smrgspecial(int k, int x, int y) 29632001f49Smrg{ 29732001f49Smrg switch (k) { 29832001f49Smrg case GLUT_KEY_UP: 29932001f49Smrg view_rotx += 5.0; 30032001f49Smrg break; 30132001f49Smrg case GLUT_KEY_DOWN: 30232001f49Smrg view_rotx -= 5.0; 30332001f49Smrg break; 30432001f49Smrg case GLUT_KEY_LEFT: 30532001f49Smrg view_roty += 5.0; 30632001f49Smrg break; 30732001f49Smrg case GLUT_KEY_RIGHT: 30832001f49Smrg view_roty -= 5.0; 30932001f49Smrg break; 31032001f49Smrg default: 31132001f49Smrg return; 31232001f49Smrg } 31332001f49Smrg glutPostRedisplay(); 31432001f49Smrg} 31532001f49Smrg 31632001f49Smrg/* new window size or exposure */ 31732001f49Smrgstatic void 31832001f49Smrgreshape(int width, int height) 31932001f49Smrg{ 32032001f49Smrg GLfloat h = (GLfloat) height / (GLfloat) width; 32132001f49Smrg 32232001f49Smrg glViewport(0, 0, (GLint) width, (GLint) height); 32332001f49Smrg glMatrixMode(GL_PROJECTION); 32432001f49Smrg glLoadIdentity(); 32532001f49Smrg glFrustum(-1.0, 1.0, -h, h, 5.0, 200.0); 32632001f49Smrg glMatrixMode(GL_MODELVIEW); 32732001f49Smrg} 32832001f49Smrg 32932001f49Smrgstatic void 33032001f49Smrginit(int argc, char *argv[]) 33132001f49Smrg{ 33232001f49Smrg static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0}; 33332001f49Smrg static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0}; 33432001f49Smrg static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0}; 33532001f49Smrg static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; 33632001f49Smrg GLint i; 33732001f49Smrg 33832001f49Smrg glLightfv(GL_LIGHT0, GL_POSITION, pos); 33932001f49Smrg glEnable(GL_CULL_FACE); 34032001f49Smrg glEnable(GL_LIGHTING); 34132001f49Smrg glEnable(GL_LIGHT0); 34232001f49Smrg glEnable(GL_DEPTH_TEST); 34332001f49Smrg 34432001f49Smrg /* make the gears */ 34532001f49Smrg gear1 = glGenLists(1); 34632001f49Smrg glNewList(gear1, GL_COMPILE); 34732001f49Smrg glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); 34832001f49Smrg gear(1.0, 4.0, 1.0, 20, 0.7); 34932001f49Smrg glEndList(); 35032001f49Smrg 35132001f49Smrg gear2 = glGenLists(1); 35232001f49Smrg glNewList(gear2, GL_COMPILE); 35332001f49Smrg glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); 35432001f49Smrg gear(0.5, 2.0, 2.0, 10, 0.7); 35532001f49Smrg glEndList(); 35632001f49Smrg 35732001f49Smrg gear3 = glGenLists(1); 35832001f49Smrg glNewList(gear3, GL_COMPILE); 35932001f49Smrg glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); 36032001f49Smrg gear(1.3, 2.0, 0.5, 10, 0.7); 36132001f49Smrg glEndList(); 36232001f49Smrg 36332001f49Smrg glEnable(GL_NORMALIZE); 36432001f49Smrg 36532001f49Smrg for ( i=1; i<argc; i++ ) { 36632001f49Smrg if (strcmp(argv[i], "-info")==0) { 36732001f49Smrg printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 36832001f49Smrg printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 36932001f49Smrg printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 37032001f49Smrg printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); 3717ec3b29aSmrg fflush(stdout); 37232001f49Smrg } 37332001f49Smrg else if ( strcmp(argv[i], "-exit")==0) { 37432001f49Smrg autoexit = 30; 37532001f49Smrg printf("Auto Exit after %i seconds.\n", autoexit ); 3767ec3b29aSmrg fflush(stdout); 37732001f49Smrg } 37832001f49Smrg else if (strcmp(argv[i], "-noanim") == 0) { 37932001f49Smrg Animate = GL_FALSE; 38032001f49Smrg } 38132001f49Smrg } 38232001f49Smrg} 38332001f49Smrg 38432001f49Smrg 38532001f49Smrgstatic void 38632001f49Smrgvisible(int vis) 38732001f49Smrg{ 38832001f49Smrg Visible = vis; 38932001f49Smrg update_idle_func(); 39032001f49Smrg} 39132001f49Smrg 39232001f49Smrgint main(int argc, char *argv[]) 39332001f49Smrg{ 39432001f49Smrg glutInitWindowSize(300, 300); 39532001f49Smrg glutInit(&argc, argv); 39632001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); 39732001f49Smrg win = glutCreateWindow("Gears"); 39832001f49Smrg init(argc, argv); 39932001f49Smrg 40032001f49Smrg glutDisplayFunc(draw); 40132001f49Smrg glutReshapeFunc(reshape); 40232001f49Smrg glutKeyboardFunc(key); 40332001f49Smrg glutSpecialFunc(special); 40432001f49Smrg glutVisibilityFunc(visible); 40532001f49Smrg update_idle_func(); 40632001f49Smrg 40732001f49Smrg glutMainLoop(); 40832001f49Smrg return 0; /* ANSI C requires main to return int. */ 40932001f49Smrg} 410