mesa/progs/windml/uglgears.c

429 lines
10 KiB
C

/* 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;
}