home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / demos / gears.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  8KB  |  310 lines

  1. /* gears.c */
  2.  
  3. /*
  4.  * 3-D gear wheels.  This program is in the public domain.
  5.  *
  6.  * Brian Paul
  7.  */
  8.  
  9.  
  10. #include <math.h>
  11. #include <stdlib.h>
  12. #include "gltk.h"
  13.  
  14.  
  15. #ifndef M_PI
  16. #  define M_PI 3.14159265
  17. #endif
  18.  
  19.  
  20. /*
  21.  * Draw a gear wheel.  You'll probably want to call this function when
  22.  * building a display list since we do a lot of trig here.
  23.  *
  24.  * Input:  inner_radius - radius of hole at center
  25.  *         outer_radius - radius at center of teeth
  26.  *         width - width of gear
  27.  *         teeth - number of teeth
  28.  *         tooth_depth - depth of tooth
  29.  */
  30. static void gear( GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
  31.           GLint teeth, GLfloat tooth_depth )
  32. {
  33.    GLint i;
  34.    GLfloat r0, r1, r2;
  35.    GLfloat angle, da;
  36.    GLfloat u, v, len;
  37.  
  38.    r0 = inner_radius;
  39.    r1 = outer_radius - tooth_depth/2.0;
  40.    r2 = outer_radius + tooth_depth/2.0;
  41.  
  42.    da = 2.0*M_PI / teeth / 4.0;
  43.  
  44.    glShadeModel( GL_FLAT );
  45.  
  46.    glNormal3f( 0.0, 0.0, 1.0 );
  47.  
  48.    /* draw front face */
  49.    glBegin( GL_QUAD_STRIP );
  50.    for (i=0;i<=teeth;i++) {
  51.       angle = i * 2.0*M_PI / teeth;
  52.       glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
  53.       glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
  54.       glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
  55.       glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
  56.    }
  57.    glEnd();
  58.  
  59.    /* draw front sides of teeth */
  60.    glBegin( GL_QUADS );
  61.    da = 2.0*M_PI / teeth / 4.0;
  62.    for (i=0;i<teeth;i++) {
  63.       angle = i * 2.0*M_PI / teeth;
  64.  
  65.       glVertex3f( r1*cos(angle),      r1*sin(angle),      width*0.5 );
  66.       glVertex3f( r2*cos(angle+da),   r2*sin(angle+da),   width*0.5 );
  67.       glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 );
  68.       glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
  69.    }
  70.    glEnd();
  71.  
  72.  
  73.    glNormal3f( 0.0, 0.0, -1.0 );
  74.  
  75.    /* draw back face */
  76.    glBegin( GL_QUAD_STRIP );
  77.    for (i=0;i<=teeth;i++) {
  78.       angle = i * 2.0*M_PI / teeth;
  79.       glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
  80.       glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
  81.       glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
  82.       glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
  83.    }
  84.    glEnd();
  85.  
  86.    /* draw back sides of teeth */
  87.    glBegin( GL_QUADS );
  88.    da = 2.0*M_PI / teeth / 4.0;
  89.    for (i=0;i<teeth;i++) {
  90.       angle = i * 2.0*M_PI / teeth;
  91.  
  92.       glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
  93.       glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
  94.       glVertex3f( r2*cos(angle+da),   r2*sin(angle+da),   -width*0.5 );
  95.       glVertex3f( r1*cos(angle),      r1*sin(angle),      -width*0.5 );
  96.    }
  97.    glEnd();
  98.  
  99.  
  100.    /* draw outward faces of teeth */
  101.    glBegin( GL_QUAD_STRIP );
  102.    for (i=0;i<teeth;i++) {
  103.       angle = i * 2.0*M_PI / teeth;
  104.  
  105.       glVertex3f( r1*cos(angle),      r1*sin(angle),       width*0.5 );
  106.       glVertex3f( r1*cos(angle),      r1*sin(angle),      -width*0.5 );
  107.       u = r2*cos(angle+da) - r1*cos(angle);
  108.       v = r2*sin(angle+da) - r1*sin(angle);
  109.       len = sqrt( u*u + v*v );
  110.       u /= len;
  111.       v /= len;
  112.       glNormal3f( v, -u, 0.0 );
  113.       glVertex3f( r2*cos(angle+da),   r2*sin(angle+da),    width*0.5 );
  114.       glVertex3f( r2*cos(angle+da),   r2*sin(angle+da),   -width*0.5 );
  115.       glNormal3f( cos(angle), sin(angle), 0.0 );
  116.       glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da),  width*0.5 );
  117.       glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
  118.       u = r1*cos(angle+3*da) - r2*cos(angle+2*da);
  119.       v = r1*sin(angle+3*da) - r2*sin(angle+2*da);
  120.       glNormal3f( v, -u, 0.0 );
  121.       glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da),  width*0.5 );
  122.       glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
  123.       glNormal3f( cos(angle), sin(angle), 0.0 );
  124.    }
  125.  
  126.    glVertex3f( r1*cos(0), r1*sin(0), width*0.5 );
  127.    glVertex3f( r1*cos(0), r1*sin(0), -width*0.5 );
  128.  
  129.    glEnd();
  130.  
  131.  
  132.    glShadeModel( GL_SMOOTH );
  133.  
  134.    /* draw inside radius cylinder */
  135.    glBegin( GL_QUAD_STRIP );
  136.    for (i=0;i<=teeth;i++) {
  137.       angle = i * 2.0*M_PI / teeth;
  138.       glNormal3f( -cos(angle), -sin(angle), 0.0 );
  139.       glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
  140.       glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
  141.    }
  142.    glEnd();
  143.       
  144. }
  145.  
  146.  
  147. static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0;
  148. static GLint gear1, gear2, gear3;
  149. static GLfloat angle = 0.0;
  150.  
  151. static GLuint limit;
  152. static GLuint count = 1;
  153.  
  154.  
  155. static void draw( void )
  156. {
  157.    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  158.  
  159.    glPushMatrix();
  160.    glRotatef( view_rotx, 1.0, 0.0, 0.0 );
  161.    glRotatef( view_roty, 0.0, 1.0, 0.0 );
  162.    glRotatef( view_rotz, 0.0, 0.0, 1.0 );
  163.  
  164.    glPushMatrix();
  165.    glTranslatef( -3.0, -2.0, 0.0 );
  166.    glRotatef( angle, 0.0, 0.0, 1.0 );
  167.    glCallList(gear1);
  168.    glPopMatrix();
  169.  
  170.    glPushMatrix();
  171.    glTranslatef( 3.1, -2.0, 0.0 );
  172.    glRotatef( -2.0*angle-9.0, 0.0, 0.0, 1.0 );
  173.    glCallList(gear2);
  174.    glPopMatrix();
  175.  
  176.    glPushMatrix();
  177.    glTranslatef( -3.1, 4.2, 0.0 );
  178.    glRotatef( -2.0*angle-25.0, 0.0, 0.0, 1.0 );
  179.    glCallList(gear3);
  180.    glPopMatrix();
  181.  
  182.    glPopMatrix();
  183.  
  184.    tkSwapBuffers();
  185.  
  186.    count++;
  187.    if (count==limit) {
  188.       tkQuit();
  189.    }
  190. }
  191.  
  192.  
  193.  
  194. static void idle( void )
  195. {
  196.    angle += 2.0;
  197.    draw();
  198. }
  199.  
  200.  
  201.  
  202. /* change view angle, exit upon ESC */
  203. static GLenum key(int k, GLenum mask)
  204. {
  205.    switch (k) {
  206.       case TK_UP:
  207.          view_rotx += 5.0;
  208.      return GL_TRUE;
  209.       case TK_DOWN:
  210.          view_rotx -= 5.0;
  211.      return GL_TRUE;
  212.       case TK_LEFT:
  213.          view_roty += 5.0;
  214.      return GL_TRUE;
  215.       case TK_RIGHT:
  216.          view_roty -= 5.0;
  217.      return GL_TRUE;
  218.       case TK_z:
  219.      view_rotz += 5.0;
  220.      return GL_TRUE;
  221.       case TK_Z:
  222.      view_rotz -= 5.0;
  223.      return GL_TRUE;
  224.       case TK_ESCAPE:
  225.      tkQuit();
  226.    }
  227.    return GL_FALSE;
  228. }
  229.  
  230.  
  231.  
  232. /* new window size or exposure */
  233. static void reshape( int width, int height )
  234. {
  235.    GLfloat  h = (GLfloat) height / (GLfloat) width;
  236.  
  237.    glViewport(0, 0, (GLint)width, (GLint)height);
  238.    glMatrixMode(GL_PROJECTION);
  239.    glLoadIdentity();
  240.    glFrustum( -1.0, 1.0, -h, h, 5.0, 60.0 );
  241.    glMatrixMode(GL_MODELVIEW);
  242.    glLoadIdentity();
  243.    glTranslatef( 0.0, 0.0, -40.0 );
  244.    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  245.  
  246. }
  247.  
  248.  
  249. static void init( void )
  250. {
  251.    static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0 };
  252.    static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0 };
  253.    static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0 };
  254.    static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0 };
  255.  
  256.    glLightfv( GL_LIGHT0, GL_POSITION, pos );
  257.    glEnable( GL_CULL_FACE );
  258.    glEnable( GL_LIGHTING );
  259.    glEnable( GL_LIGHT0 );
  260.    glEnable( GL_DEPTH_TEST );
  261.  
  262.    /* make the gears */
  263.    gear1 = glGenLists(1);
  264.    glNewList(gear1, GL_COMPILE);
  265.    glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red );
  266.    gear( 1.0, 4.0, 1.0, 20, 0.7 );
  267.    glEndList();
  268.  
  269.    gear2 = glGenLists(1);
  270.    glNewList(gear2, GL_COMPILE);
  271.    glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
  272.    gear( 0.5, 2.0, 2.0, 10, 0.7 );
  273.    glEndList();
  274.  
  275.    gear3 = glGenLists(1);
  276.    glNewList(gear3, GL_COMPILE);
  277.    glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue );
  278.    gear( 1.3, 2.0, 0.5, 10, 0.7 );
  279.    glEndList();
  280.  
  281.    glEnable( GL_NORMALIZE );
  282. }
  283.  
  284.  
  285. main( int argc, char *argv[] )
  286. {
  287.    if (argc>1) {
  288.       /* do 'n' frames then exit */
  289.       limit = atoi( argv[1] ) + 1;
  290.    }
  291.    else {
  292.       limit = 0;
  293.    }
  294.    tkInitPosition(0, 0, 300, 300);
  295.    tkInitDisplayMode( TK_RGB | TK_DEPTH | TK_DOUBLE | TK_DIRECT );
  296.  
  297.    if (tkInitWindow("Gears") == GL_FALSE) {
  298.       tkQuit();
  299.    }
  300.  
  301.    init();
  302.  
  303.    tkExposeFunc( reshape );
  304.    tkReshapeFunc( reshape );
  305.    tkKeyDownFunc( key );
  306.    tkIdleFunc( idle );
  307.    tkDisplayFunc( draw );
  308.    tkExec();
  309. }
  310.