gears.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:13k
源码类别:

GIS编程

开发平台:

Visual C++

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