home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / progs / contrib / gears.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  12.8 KB  |  571 lines

  1. #include <stdlib.h>
  2. #include <GL/glut.h>
  3.  
  4. #include <math.h>
  5. #include <unistd.h>
  6. #include <sys/types.h>
  7. #include <stdio.h>
  8.  
  9. /* For portability... */
  10. #undef fcos
  11. #undef fsin
  12. #undef fsqrt
  13. #define fcos  cos
  14. #define fsin  sin
  15. #define fsqrt sqrt
  16.  
  17. static unsigned char ccolors[] =
  18. {0xff, 0x00, 0x00,
  19.   0x00, 0xff, 0x00,
  20.   0x00, 0x00, 0xff,
  21.   0x99, 0x99, 0x99};
  22. static int cptr = 0;
  23.  
  24. static int wd, ht;
  25.  
  26. static double d_near = 1.0;
  27. static double d_far = 2000;
  28. static int poo = 0;
  29.  
  30. typedef struct {
  31.   float rad, wid;
  32. } Profile;
  33.  
  34. void flat_face(float ir, float or, float wd);
  35. void draw_inside(float w1, float w2, float rad);
  36. void draw_outside(float w1, float w2, float rad);
  37. void tooth_side(int nt, float ir, float or, float tp, float tip, float wd);
  38.  
  39. int circle_subdiv;
  40.  
  41. void
  42. gear(int nt, float wd, float ir, float or, float sa, float tp, float tip, int ns, Profile * ip)
  43. {
  44.   /**
  45.    * nt - number of teeth 
  46.    * wd - width of gear at teeth
  47.    * ir - inside radius absolute scale
  48.    * or - radius at outside of wheel (tip of tooth) ratio of ir
  49.    * sa - angle of slant of teeth on gear (1 = slant of one whole tooth)
  50.    * tp - ratio of tooth in slice of circle (0..1] (1 = teeth are touching at base)
  51.    * tip - ratio of tip of tooth (0..tp] (cant be wider that base of tooth)
  52.    * ns - number of elements in wheel width profile
  53.    * *ip - list of float pairs {start radius, width, ...} (width is ratio to wd)
  54.    *
  55.    */
  56.  
  57.   /* gear lying on xy plane, z for width. all normals calulated 
  58.      (normalized) */
  59.  
  60.   float prev;
  61.   int k, t;
  62.  
  63.   /* estimat # times to divide circle */
  64.   if (nt <= 0)
  65.     circle_subdiv = 64;
  66.   else {
  67.     /* lowest multiple of number of teeth */
  68.     circle_subdiv = nt;
  69.     while (circle_subdiv < 64)
  70.       circle_subdiv += nt;
  71.   }
  72.  
  73.   /* --- draw wheel face --- */
  74.  
  75.   /* draw horzontal, vertical faces for each section. if first
  76.      section radius not zero, use wd for 0.. first if ns == 0
  77.      use wd for whole face. last width used to edge.  */
  78.  
  79.   if (ns <= 0) {
  80.     flat_face(0.0, ir, wd);
  81.   } else {
  82.     /* draw first flat_face, then continue in loop */
  83.     if (ip[0].rad > 0.0) {
  84.       flat_face(0.0, ip[0].rad * ir, wd);
  85.       prev = wd;
  86.       t = 0;
  87.     } else {
  88.       flat_face(0.0, ip[1].rad * ir, ip[0].wid * wd);
  89.       prev = ip[0].wid;
  90.       t = 1;
  91.     }
  92.     for (k = t; k < ns; k++) {
  93.       if (prev < ip[k].wid) {
  94.         draw_inside(prev * wd, ip[k].wid * wd, ip[k].rad * ir);
  95.       } else {
  96.         draw_outside(prev * wd, ip[k].wid * wd, ip[k].rad * ir);
  97.       }
  98.       prev = ip[k].wid;
  99.       /* - draw to edge of wheel, add final face if needed - */
  100.       if (k == ns - 1) {
  101.         flat_face(ip[k].rad * ir, ir, ip[k].wid * wd);
  102.  
  103.         /* now draw side to match tooth rim */
  104.         if (ip[k].wid < 1.0) {
  105.           draw_inside(ip[k].wid * wd, wd, ir);
  106.         } else {
  107.           draw_outside(ip[k].wid * wd, wd, ir);
  108.         }
  109.       } else {
  110.         flat_face(ip[k].rad * ir, ip[k + 1].rad * ir, ip[k].wid * wd);
  111.       }
  112.     }
  113.   }
  114.  
  115.   /* --- tooth side faces --- */
  116.   tooth_side(nt, ir, or, tp, tip, wd);
  117.  
  118.   /* --- tooth hill surface --- */
  119. }
  120.  
  121. void 
  122. tooth_side(int nt, float ir, float or, float tp, float tip, float wd)
  123. {
  124.  
  125.   float i;
  126.   float end = 2.0 * M_PI / nt;
  127.   float x[6], y[6];
  128.   float s[3], c[3];
  129.  
  130.   or = or * ir;         /* or is really a ratio of ir */
  131.   for (i = 0; i < 2.0 * M_PI - end / 4.0; i += end) {
  132.  
  133.     c[0] = fcos(i);
  134.     s[0] = fsin(i);
  135.     c[1] = fcos(i + end * (0.5 - tip / 2));
  136.     s[1] = fsin(i + end * (0.5 - tip / 2));
  137.     c[2] = fcos(i + end * (0.5 + tp / 2));
  138.     s[2] = fsin(i + end * (0.5 + tp / 2));
  139.  
  140.     x[0] = ir * c[0];
  141.     y[0] = ir * s[0];
  142.     x[5] = ir * fcos(i + end);
  143.     y[5] = ir * fsin(i + end);
  144.     /* ---treat veritices 1,4 special to match strait edge of
  145.        face */
  146.     x[1] = x[0] + (x[5] - x[0]) * (0.5 - tp / 2);
  147.     y[1] = y[0] + (y[5] - y[0]) * (0.5 - tp / 2);
  148.     x[4] = x[0] + (x[5] - x[0]) * (0.5 + tp / 2);
  149.     y[4] = y[0] + (y[5] - y[0]) * (0.5 + tp / 2);
  150.     x[2] = or * fcos(i + end * (0.5 - tip / 2));
  151.     y[2] = or * fsin(i + end * (0.5 - tip / 2));
  152.     x[3] = or * fcos(i + end * (0.5 + tip / 2));
  153.     y[3] = or * fsin(i + end * (0.5 + tip / 2));
  154.  
  155.     /* draw face trapezoids as 2 tmesh */
  156.     glNormal3f(0.0, 0.0, 1.0);
  157.     glBegin(GL_TRIANGLE_STRIP);
  158.     glVertex3f(x[2], y[2], wd / 2);
  159.     glVertex3f(x[1], y[1], wd / 2);
  160.     glVertex3f(x[3], y[3], wd / 2);
  161.     glVertex3f(x[4], y[4], wd / 2);
  162.     glEnd();
  163.  
  164.     glNormal3f(0.0, 0.0, -1.0);
  165.     glBegin(GL_TRIANGLE_STRIP);
  166.     glVertex3f(x[2], y[2], -wd / 2);
  167.     glVertex3f(x[1], y[1], -wd / 2);
  168.     glVertex3f(x[3], y[3], -wd / 2);
  169.     glVertex3f(x[4], y[4], -wd / 2);
  170.     glEnd();
  171.  
  172.     /* draw inside rim pieces */
  173.     glNormal3f(c[0], s[0], 0.0);
  174.     glBegin(GL_TRIANGLE_STRIP);
  175.     glVertex3f(x[0], y[0], -wd / 2);
  176.     glVertex3f(x[1], y[1], -wd / 2);
  177.     glVertex3f(x[0], y[0], wd / 2);
  178.     glVertex3f(x[1], y[1], wd / 2);
  179.     glEnd();
  180.  
  181.     /* draw up hill side */
  182.     {
  183.       float a, b, n;
  184.       /* calculate normal of face */
  185.       a = x[2] - x[1];
  186.       b = y[2] - y[1];
  187.       n = 1.0 / fsqrt(a * a + b * b);
  188.       a = a * n;
  189.       b = b * n;
  190.       glNormal3f(b, -a, 0.0);
  191.     }
  192.     glBegin(GL_TRIANGLE_STRIP);
  193.     glVertex3f(x[1], y[1], -wd / 2);
  194.     glVertex3f(x[2], y[2], -wd / 2);
  195.     glVertex3f(x[1], y[1], wd / 2);
  196.     glVertex3f(x[2], y[2], wd / 2);
  197.     glEnd();
  198.     /* draw top of hill */
  199.     glNormal3f(c[1], s[1], 0.0);
  200.     glBegin(GL_TRIANGLE_STRIP);
  201.     glVertex3f(x[2], y[2], -wd / 2);
  202.     glVertex3f(x[3], y[3], -wd / 2);
  203.     glVertex3f(x[2], y[2], wd / 2);
  204.     glVertex3f(x[3], y[3], wd / 2);
  205.     glEnd();
  206.  
  207.     /* draw down hill side */
  208.     {
  209.       float a, b, c;
  210.       /* calculate normal of face */
  211.       a = x[4] - x[3];
  212.       b = y[4] - y[3];
  213.       c = 1.0 / fsqrt(a * a + b * b);
  214.       a = a * c;
  215.       b = b * c;
  216.       glNormal3f(b, -a, 0.0);
  217.     }
  218.     glBegin(GL_TRIANGLE_STRIP);
  219.     glVertex3f(x[3], y[3], -wd / 2);
  220.     glVertex3f(x[4], y[4], -wd / 2);
  221.     glVertex3f(x[3], y[3], wd / 2);
  222.     glVertex3f(x[4], y[4], wd / 2);
  223.     glEnd();
  224.     /* inside rim part */
  225.     glNormal3f(c[2], s[2], 0.0);
  226.     glBegin(GL_TRIANGLE_STRIP);
  227.     glVertex3f(x[4], y[4], -wd / 2);
  228.     glVertex3f(x[5], y[5], -wd / 2);
  229.     glVertex3f(x[4], y[4], wd / 2);
  230.     glVertex3f(x[5], y[5], wd / 2);
  231.     glEnd();
  232.   }
  233. }
  234.  
  235. void 
  236. flat_face(float ir, float or, float wd)
  237. {
  238.  
  239.   int i;
  240.   float w;
  241.  
  242.   /* draw each face (top & bottom ) * */
  243.   if (poo)
  244.     printf("Face  : %f..%f wid=%f\n", ir, or, wd);
  245.   if (wd == 0.0)
  246.     return;
  247.   for (w = wd / 2; w > -wd; w -= wd) {
  248.     if (w > 0.0)
  249.       glNormal3f(0.0, 0.0, 1.0);
  250.     else
  251.       glNormal3f(0.0, 0.0, -1.0);
  252.  
  253.     if (ir == 0.0) {
  254.       /* draw as t-fan */
  255.       glBegin(GL_TRIANGLE_FAN);
  256.       glVertex3f(0.0, 0.0, w);  /* center */
  257.       glVertex3f(or, 0.0, w);
  258.       for (i = 1; i < circle_subdiv; i++) {
  259.         glVertex3f(fcos(2.0 * M_PI * i / circle_subdiv) * or,
  260.           fsin(2.0 * M_PI * i / circle_subdiv) * or,
  261.           w);
  262.       }
  263.       glVertex3f(or, 0.0, w);
  264.       glEnd();
  265.     } else {
  266.       /* draw as tmesh */
  267.       glBegin(GL_TRIANGLE_STRIP);
  268.       glVertex3f(or, 0.0, w);
  269.       glVertex3f(ir, 0.0, w);
  270.       for (i = 1; i < circle_subdiv; i++) {
  271.         glVertex3f(fcos(2.0 * M_PI * i / circle_subdiv) * or,
  272.           fsin(2.0 * M_PI * i / circle_subdiv) * or,
  273.           w);
  274.         glVertex3f(fcos(2.0 * M_PI * i / circle_subdiv) * ir,
  275.           fsin(2.0 * M_PI * i / circle_subdiv) * ir,
  276.           w);
  277.       }
  278.       glVertex3f(or, 0.0, w);
  279.       glVertex3f(ir, 0.0, w);
  280.       glEnd();
  281.  
  282.     }
  283.   }
  284. }
  285.  
  286. void 
  287. draw_inside(float w1, float w2, float rad)
  288. {
  289.  
  290.   int i, j;
  291.   float c, s;
  292.   if (poo)
  293.     printf("Inside: wid=%f..%f rad=%f\n", w1, w2, rad);
  294.   if (w1 == w2)
  295.     return;
  296.  
  297.   w1 = w1 / 2;
  298.   w2 = w2 / 2;
  299.   for (j = 0; j < 2; j++) {
  300.     if (j == 1) {
  301.       w1 = -w1;
  302.       w2 = -w2;
  303.     }
  304.     glBegin(GL_TRIANGLE_STRIP);
  305.     glNormal3f(-1.0, 0.0, 0.0);
  306.     glVertex3f(rad, 0.0, w1);
  307.     glVertex3f(rad, 0.0, w2);
  308.     for (i = 1; i < circle_subdiv; i++) {
  309.       c = fcos(2.0 * M_PI * i / circle_subdiv);
  310.       s = fsin(2.0 * M_PI * i / circle_subdiv);
  311.       glNormal3f(-c, -s, 0.0);
  312.       glVertex3f(c * rad,
  313.         s * rad,
  314.         w1);
  315.       glVertex3f(c * rad,
  316.         s * rad,
  317.         w2);
  318.     }
  319.     glNormal3f(-1.0, 0.0, 0.0);
  320.     glVertex3f(rad, 0.0, w1);
  321.     glVertex3f(rad, 0.0, w2);
  322.     glEnd();
  323.   }
  324. }
  325.  
  326. void 
  327. draw_outside(float w1, float w2, float rad)
  328. {
  329.  
  330.   int i, j;
  331.   float c, s;
  332.   if (poo)
  333.     printf("Outsid: wid=%f..%f rad=%f\n", w1, w2, rad);
  334.   if (w1 == w2)
  335.     return;
  336.  
  337.   w1 = w1 / 2;
  338.   w2 = w2 / 2;
  339.   for (j = 0; j < 2; j++) {
  340.     if (j == 1) {
  341.       w1 = -w1;
  342.       w2 = -w2;
  343.     }
  344.     glBegin(GL_TRIANGLE_STRIP);
  345.     glNormal3f(1.0, 0.0, 0.0);
  346.     glVertex3f(rad, 0.0, w1);
  347.     glVertex3f(rad, 0.0, w2);
  348.     for (i = 1; i < circle_subdiv; i++) {
  349.       c = fcos(2.0 * M_PI * i / circle_subdiv);
  350.       s = fsin(2.0 * M_PI * i / circle_subdiv);
  351.       glNormal3f(c, s, 0.0);
  352.       glVertex3f(c * rad,
  353.         s * rad,
  354.         w1);
  355.       glVertex3f(c * rad,
  356.         s * rad,
  357.         w2);
  358.     }
  359.     glNormal3f(1.0, 0.0, 0.0);
  360.     glVertex3f(rad, 0.0, w1);
  361.     glVertex3f(rad, 0.0, w2);
  362.     glEnd();
  363.   }
  364. }
  365.  
  366. Profile gear_profile[] =
  367. {0.000, 0.0,
  368.   0.300, 7.0,
  369.   0.340, 0.4,
  370.   0.550, 0.64,
  371.   0.600, 0.4,
  372.   0.950, 1.0
  373. };
  374.  
  375. float a1 = 27.0;
  376. float a2 = 67.0;
  377. float a3 = 47.0;
  378. float a4 = 87.0;
  379. float i1 = 1.2;
  380. float i2 = 3.1;
  381. float i3 = 2.3;
  382. float i4 = 1.1;
  383. void
  384. oneFrame(void)
  385. {
  386.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  387.  
  388.   glPushMatrix();
  389.   glTranslatef(0.0, 0.0, -4.0);
  390.   glRotatef(a3, 1.0, 1.0, 1.0);
  391.   glRotatef(a4, 0.0, 0.0, -1.0);
  392.   glTranslatef(0.14, 0.2, 0.0);
  393.   gear(76,
  394.     0.4, 2.0, 1.1,
  395.     0.0, 0.4, 0.04,
  396.     sizeof(gear_profile) / sizeof(Profile), gear_profile);
  397.   glPopMatrix();
  398.  
  399.   glPushMatrix();
  400.   glTranslatef(0.1, 0.2, -3.8);
  401.   glRotatef(a2, -4.0, 2.0, -1.0);
  402.   glRotatef(a1, 1.0, -3.0, 1.0);
  403.   glTranslatef(0.0, -0.2, 0.0);
  404.   gear(36,
  405.     0.4, 2.0, 1.1,
  406.     0.0, 0.7, 0.2,
  407.     sizeof(gear_profile) / sizeof(Profile), gear_profile);
  408.   glPopMatrix();
  409.  
  410.   a1 += i1;
  411.   if (a1 > 360.0)
  412.     a1 -= 360.0;
  413.   if (a1 < 0.0)
  414.     a1 -= 360.0;
  415.   a2 += i2;
  416.   if (a2 > 360.0)
  417.     a2 -= 360.0;
  418.   if (a2 < 0.0)
  419.     a2 -= 360.0;
  420.   a3 += i3;
  421.   if (a3 > 360.0)
  422.     a3 -= 360.0;
  423.   if (a3 < 0.0)
  424.     a3 -= 360.0;
  425.   a4 += i4;
  426.   if (a4 > 360.0)
  427.     a4 -= 360.0;
  428.   if (a4 < 0.0)
  429.     a4 -= 360.0;
  430.   glutSwapBuffers();
  431. }
  432.  
  433. void
  434. display(void)
  435. {
  436.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  437. }
  438.  
  439. void
  440. myReshape(int w, int h)
  441. {
  442.   wd = w;
  443.   ht = h;
  444.   glViewport(0, 0, w, h);
  445.   glMatrixMode(GL_PROJECTION);
  446.   glLoadIdentity();
  447.   glFrustum(-1.0, 1.0, -1.0, 1.0, d_near, d_far);
  448.   /**
  449.     use perspective instead:
  450.  
  451.     if (w <= h){
  452.         glOrtho( 0.0, 1.0,
  453.                  0.0, 1.0 * (GLfloat) h / (GLfloat) w,
  454.                 -16.0, 4.0);
  455.     }else{
  456.         glOrtho( 0.0, 1.0 * (GLfloat) w / (GLfloat) h,
  457.                  0.0, 1.0,
  458.                 -16.0, 4.0);
  459.     }
  460.    */
  461.   glMatrixMode(GL_MODELVIEW);
  462.   glLoadIdentity();
  463.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  464. }
  465.  
  466. void
  467. visibility(int status)
  468. {
  469.   if (status == GLUT_VISIBLE) {
  470.     glutIdleFunc(oneFrame);
  471.   } else {
  472.     glutIdleFunc(NULL);
  473.   }
  474.  
  475. }
  476.  
  477. void
  478. myinit(void)
  479. {
  480.   float f[20];
  481.   glClearColor(0.0, 0.0, 0.0, 0.0);
  482.   myReshape(640, 480);
  483.   /* glShadeModel(GL_FLAT); */
  484.   glEnable(GL_DEPTH_TEST);
  485.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  486.  
  487.   glEnable(GL_LIGHTING);
  488.  
  489.   glLightf(GL_LIGHT0, GL_SHININESS, 1.0);
  490.   f[0] = 1.3;
  491.   f[1] = 1.3;
  492.   f[2] = -3.3;
  493.   f[3] = 1.0;
  494.   glLightfv(GL_LIGHT0, GL_POSITION, f);
  495.   f[0] = 0.8;
  496.   f[1] = 1.0;
  497.   f[2] = 0.83;
  498.   f[3] = 1.0;
  499.   glLightfv(GL_LIGHT0, GL_SPECULAR, f);
  500.   glLightfv(GL_LIGHT0, GL_DIFFUSE, f);
  501.   glEnable(GL_LIGHT0);
  502.  
  503.   glLightf(GL_LIGHT1, GL_SHININESS, 1.0);
  504.   f[0] = -2.3;
  505.   f[1] = 0.3;
  506.   f[2] = -7.3;
  507.   f[3] = 1.0;
  508.   glLightfv(GL_LIGHT1, GL_POSITION, f);
  509.   f[0] = 1.0;
  510.   f[1] = 0.8;
  511.   f[2] = 0.93;
  512.   f[3] = 1.0;
  513.   glLightfv(GL_LIGHT1, GL_SPECULAR, f);
  514.   glLightfv(GL_LIGHT1, GL_DIFFUSE, f);
  515.   glEnable(GL_LIGHT1);
  516.  
  517.   /* gear material */
  518.   f[0] = 0.1;
  519.   f[1] = 0.15;
  520.   f[2] = 0.2;
  521.   f[3] = 1.0;
  522.   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, f);
  523.  
  524.   f[0] = 0.9;
  525.   f[1] = 0.3;
  526.   f[2] = 0.3;
  527.   f[3] = 1.0;
  528.   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, f);
  529.  
  530.   f[0] = 0.4;
  531.   f[1] = 0.9;
  532.   f[2] = 0.6;
  533.   f[3] = 1.0;
  534.   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, f);
  535.  
  536.   glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 4);
  537. }
  538.  
  539. void
  540. keys(unsigned char c, int x, int y)
  541. {
  542.  
  543.   if (c == 0x1b)
  544.     exit(0);            /* escape */
  545. }
  546.  
  547. int
  548. main(int argc, char **argv)
  549. {
  550.   int mode = GLUT_DOUBLE;
  551.  
  552.   glutInit(&argc, argv);
  553.  
  554.   if (argc > 1)
  555.     mode = GLUT_SINGLE;
  556.   glutInitDisplayMode(mode | GLUT_RGB | GLUT_DEPTH);
  557.   glutInitWindowPosition(100, 100);
  558.   glutInitWindowSize(640, 480);
  559.   glutCreateWindow(argv[0]);
  560.  
  561.   myinit();
  562.   glutReshapeFunc(myReshape);
  563.   glutDisplayFunc(display);
  564.   glutKeyboardFunc(keys);
  565.   glutVisibilityFunc(visibility);
  566.   glutPostRedisplay();
  567.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  568.   glutMainLoop();
  569.   return 0;             /* ANSI C requires main to return int. */
  570. }
  571.