/* uglgears.c - WindML/Mesa example program */ /* * 3-D gear wheels. This program is in the public domain. * * Brian Paul * * Conversion to GLUT by Mark J. Kilgard * Conversion to UGL/Mesa from GLUT by Stephane Raimbault */ /* DESCRIPTION Spinning gears demo */ #include <stdio.h> #include <math.h> #include <tickLib.h> #include <ugl/ugl.h> #include <ugl/uglucode.h> #include <ugl/uglevent.h> #include <ugl/uglinput.h> #include <GL/uglmesa.h> #include <GL/glu.h> #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define COUNT_FRAMES UGL_LOCAL UGL_EVENT_SERVICE_ID eventServiceId; UGL_LOCAL UGL_EVENT_Q_ID qId; UGL_LOCAL volatile UGL_BOOL stopWex; UGL_LOCAL UGL_MESA_CONTEXT umc; UGL_LOCAL GLfloat view_rotx, view_roty, view_rotz; UGL_LOCAL GLint gear1, gear2, gear3; UGL_LOCAL GLfloat angle; UGL_LOCAL GLuint limit; UGL_LOCAL GLuint count; UGL_LOCAL GLuint tickStart, tickStop, tickBySec; /* * Draw a gear wheel. You'll probably want to call this function when * building a display list since we do a lot of trig here. * * Input: inner_radius - radius of hole at center * outer_radius - radius at center of teeth * width - width of gear * teeth - number of teeth * tooth_depth - depth of tooth */ UGL_LOCAL 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); 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); 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 (); } UGL_LOCAL void drawGL (void) { #ifdef COUNT_FRAMES int time; #endif angle += 2.0; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); 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 (gear1); glPopMatrix (); glPushMatrix (); glTranslatef (3.1, -2.0, 0.0); glRotatef (-2.0*angle-9.0, 0.0, 0.0, 1.0); glCallList (gear2); glPopMatrix (); glPushMatrix (); glTranslatef (-3.1, 4.2, 0.0); glRotatef (-2.0*angle-25.0, 0.0, 0.0, 1.0); glCallList (gear3); glPopMatrix (); glPopMatrix (); glFlush(); uglMesaSwapBuffers (); #ifdef COUNT_FRAMES if (count > limit) { tickStop = tickGet (); time = (tickStop-tickStart)/tickBySec; printf (" %i fps\n", count/time); tickStart = tickStop; count = 0; } else count++; #endif } UGL_LOCAL void initGL (GLsizei width, GLsizei height) { UGL_LOCAL GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0 }; UGL_LOCAL GLfloat red[4] = {0.8, 0.1, 0.0, 1.0 }; UGL_LOCAL GLfloat green[4] = {0.0, 0.8, 0.2, 1.0 }; UGL_LOCAL GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0 }; glLightfv (GL_LIGHT0, GL_POSITION, pos); glEnable (GL_CULL_FACE); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); glEnable (GL_DEPTH_TEST); /* make the gears */ gear1 = glGenLists (1); glNewList (gear1, GL_COMPILE); glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); gear (1.0, 4.0, 1.0, 20, 0.7); glEndList (); gear2 = glGenLists (1); glNewList (gear2, GL_COMPILE); glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); gear (0.5, 2.0, 2.0, 10, 0.7); glEndList (); gear3 = glGenLists (1); glNewList (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); glViewport (0, 0, width, height); glMatrixMode (GL_PROJECTION); glLoadIdentity (); if (width>height) { GLfloat w = (GLfloat) width / (GLfloat) height; glFrustum (-w, w, -1.0, 1.0, 5.0, 60.0); } else { GLfloat h = (GLfloat) height / (GLfloat) width; glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0); } glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glTranslatef (0.0, 0.0, -40.0); #ifdef COUNT_FRAMES tickStart = tickGet (); tickBySec = sysClkRateGet (); #endif } UGL_LOCAL void echoUse(void) { printf("tGears keys:\n"); printf(" z Counter clockwise rotation (z-axis)\n"); printf(" Z Clockwise rotation (z-axis)\n"); printf(" Up Counter clockwise rotation (x-axis)\n"); printf(" Down Clockwise rotation (x-axis)\n"); printf(" Left Counter clockwise rotation (y-axis)\n"); printf(" Right Clockwise rotation (y-axis)\n"); printf(" ESC Exit\n"); } UGL_LOCAL void readKey (UGL_WCHAR key) { switch(key) { case 'z': view_rotz += 5.0; break; case 'Z': view_rotz -= 5.0; break; case UGL_UNI_UP_ARROW: view_rotx += 5.0; break; case UGL_UNI_DOWN_ARROW: view_rotx -= 5.0; break; case UGL_UNI_LEFT_ARROW: view_roty += 5.0; break; case UGL_UNI_RIGHT_ARROW: view_roty -= 5.0; break; case UGL_UNI_ESCAPE: stopWex = UGL_TRUE; break; } } UGL_LOCAL void loopEvent(void) { UGL_EVENT event; UGL_INPUT_EVENT * pInputEvent; UGL_FOREVER { if (uglEventGet (qId, &event, sizeof (event), UGL_NO_WAIT) != UGL_STATUS_Q_EMPTY) { pInputEvent = (UGL_INPUT_EVENT *)&event; if (pInputEvent->header.type == UGL_EVENT_TYPE_KEYBOARD && pInputEvent->modifiers & UGL_KEYBOARD_KEYDOWN) readKey(pInputEvent->type.keyboard.key); } drawGL(); if (stopWex) break; } } void windMLGears (UGL_BOOL windMLMode); void uglgears (void) { taskSpawn ("tGears", 210, VX_FP_TASK, 100000, (FUNCPTR)windMLGears, UGL_FALSE,1,2,3,4,5,6,7,8,9); } void windMLGears (UGL_BOOL windMLMode) { GLsizei width, height; UGL_INPUT_DEVICE_ID keyboardDevId; view_rotx=20.0; view_roty=30.0; view_rotz=0.0; angle = 0.0; limit = 100; count = 1; uglInitialize (); uglDriverFind (UGL_KEYBOARD_TYPE, 0, (UGL_UINT32 *)&keyboardDevId); uglDriverFind (UGL_EVENT_SERVICE_TYPE, 0, (UGL_UINT32 *)&eventServiceId); qId = uglEventQCreate (eventServiceId, 100); /* Double buffering */ if (windMLMode) umc = uglMesaCreateNewContext(UGL_MESA_DOUBLE | UGL_MESA_WINDML_EXCLUSIVE, NULL); else umc = uglMesaCreateNewContext(UGL_MESA_DOUBLE, NULL); if (umc == NULL) { uglDeinitialize (); return; } /* Fullscreen */ uglMesaMakeCurrentContext (umc, 0, 0, UGL_MESA_FULLSCREEN_WIDTH, UGL_MESA_FULLSCREEN_HEIGHT); uglMesaGetIntegerv(UGL_MESA_WIDTH, &width); uglMesaGetIntegerv(UGL_MESA_HEIGHT, &height); initGL (width, height); echoUse(); stopWex = UGL_FALSE; loopEvent(); uglEventQDestroy (eventServiceId, qId); uglMesaDestroyContext(); uglDeinitialize (); return; }