复杂的齿轮动画

来源:互联网 发布:9008端口救砖 编辑:程序博客网 时间:2024/06/09 17:16

#include <gl/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#ifndef PI
#define PI 3.14159265
#endif

static GLfloat viewRotateX=20.0,viewRotateY=30.0,viewRotateZ=0.0;
static GLfloat angle=0.0;
static GLfloat viewDist=40.0;
static GLint gear1,gear2,gear3;
static GLint T0=0;
static GLint Frames=0;
static GLint autoexit=0;
static GLint win=0;
static GLboolean visible=GL_TRUE;
static GLboolean animate=GL_TRUE;

void gear(GLfloat innerRadius,GLfloat outerRadius,GLfloat width,GLint teeth,GLfloat toothDepth)
{
    GLfloat r0,r1,r2;
    GLfloat angle,da;
    GLfloat u,v,len;
    GLint i;

    r0=innerRadius;
    r1=outerRadius-toothDepth/2.0;
    r2=outerRadius+toothDepth/2.0;
    da=2.0*PI/teeth/4.0;

    glShadeModel(GL_FLAT);
    glNormal3f(0.0,0.0,1.0);

    //正面圆
    glBegin(GL_QUAD_STRIP);
    for(i=0;i<=teeth;i++)
    {
        angle=i*2.0*PI/teeth;
        glVertex3f(r0*cos(angle),r0*sin(angle),width*0.5);
        glVertex3f(r1*cos(angle),r1*sin(angle),width*0.5);
        if(i<teeth)
        {
            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();

    //正面齿轮
    glBegin(GL_QUADS);
    for(i=0;i<=teeth;i++)
    {
        angle=i*2.0*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);

    //背面圆
    glBegin(GL_QUAD_STRIP);
    for(i=0;i<=teeth;i++)
    {
        angle=i*2.0*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),r1*sin(angle),-width*0.5);????????????????
        if(i<teeth)
        {
            glVertex3f(r1*cos(angle+3*da),r1*sin(angle+3*da),-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();

    //背面齿轮
    glBegin(GL_QUADS);
    for(i=0;i<=teeth;i++)
    {
        angle=i*2.0*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();

    //齿轮外观
    glBegin(GL_QUAD_STRIP);
    for(i=0;i<=teeth;i++)
    {
        angle=i*2.0*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);
    //圆心外观
    glBegin(GL_QUAD_STRIP);
    for(i=0;i<=teeth;i++)
    {
        angle=i*2.0*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();

}

void Initial(int argc,char** argv)
{
    static GLfloat lightPosition[4]={5.0,5.0,10.0,0.0};
    static GLfloat red[4]={0.8,0.1,0.0,1.0};
    static GLfloat green[4]={0.0,0.8,0.2,1.0};
    static GLfloat blue[4]={0.2,0.2,1.0,1.0};
    GLint i;

    glLightfv(GL_LIGHT0,GL_POSITION,lightPosition);
    glEnable(GL_CULL_FACE);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);

    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);

    for(i=1;i<argc;i++)
    {
        if(strcmp(argv[i],"-info")==0)
        {
            printf("GL_RENDERER        = %s/n", (char *) glGetString(GL_RENDERER));//渲染器
            printf("GL_VERSION        = %s/n", (char *) glGetString(GL_VERSION));//版本号
            printf("GL_VENDOR        = %s/n", (char *) glGetString(GL_VENDOR));//厂商名
            printf("GL_EXTENSIONS    = %s/n", (char *) glGetString(GL_EXTENSIONS));//到支持的扩展
        }
        else if(strcmp(argv[i],"-exit")==0)
        {
            autoexit=30;
            printf("Auto Exit after %i seconds./n",autoexit);
        }
    }
}

void cleanUp(void)
{
    glDeleteLists(gear1,1);//void glDeleteLists(GLuint list,GLsizei range);该函数删除从list起的连续range个显示序列
    glDeleteLists(gear2,1);
    glDeleteLists(gear3,1);
    glutDestroyWindow(win);//销毁以win标记的窗口
}

void idle(void)
{
    static double t0=-1;
    double dt,t=glutGet(GLUT_ELAPSED_TIME)/1000.0;
    if(t0<0.0)
        t0=t;
    dt=t-t0;
    t0=t;

    angle+=70.0*dt;
    angle=fmod(angle,360.0);

    glutPostRedisplay();
}

void updateIdleFunc(void)
{
    if(visible&&animate)
        glutIdleFunc(idle);
    else
        glutIdleFunc(NULL);
}

void myDisplay(void)
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glPushMatrix();
    glTranslatef(0.0,0.0,-viewDist);
    glRotatef(viewRotateX,1.0,0.0,0.0);
    glRotatef(viewRotateY,0.0,1.0,0.0);
    glRotatef(viewRotateZ,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();
    glutSwapBuffers();

    Frames++;
    {
        GLint t=glutGet(GLUT_ELAPSED_TIME);
        if(t-T0>=5000)
        {
            GLfloat seconds=(t-T0)/1000.0;
            GLfloat fps=Frames/seconds;
            printf("%d frames in %6.3f seconds = %6.3f FPS/n",Frames,seconds,fps);
            T0=t;
            Frames=0;
            if((t>=999.0*autoexit)&&autoexit)
            {
                cleanUp();
                exit(0);
            }
        }
    }
}

//Z,z控制Z轴;D,d控制大小;a控制暂停;Esc控制退出
void myKeyboard(unsigned char k,int x,int y)
{
    switch(k)
    {
    case 'Z':
        viewRotateZ+=5.0;
        break;
    case 'z':
        viewRotateZ-=5.0;
        break;
    case 'D':
        viewDist+=1.0;
        break;
    case 'd':
        viewDist-=1.0;;
        break;
    case 'a':
        animate=!animate;
        updateIdleFunc();
        break;
    case 27:
        cleanUp();
        exit(0);
        break;
    default:
        return;
    }
    glutPostRedisplay();
}

void myReshape(GLsizei w,GLsizei h)
{
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0,1.0,-(GLfloat)h/(GLfloat)w,(GLfloat)h/(GLfloat)w,5.0,200.0);//void glFrustum(GLdouble left,GLdouble Right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);
    glMatrixMode(GL_MODELVIEW);
}

////上下左右,控制XY轴旋转
void mySpecial(int k,int x,int y)
{
    switch(k)
    {
    case GLUT_KEY_UP:
        viewRotateX+=5.0;
        break;
    case GLUT_KEY_DOWN:
        viewRotateX-=5.0;
        break;
    case GLUT_KEY_LEFT:
        viewRotateY+=5.0;
        break;
    case GLUT_KEY_RIGHT:
        viewRotateY-=5.0;
        break;
    default:
        return;
    }
    glutPostRedisplay();
}


void myVisible(int vis)
{
    visible=vis;
    updateIdleFunc();
}

int main(int argc,char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);

    glutInitWindowSize(300,300);
    glutInitWindowPosition(100,100);
    win=glutCreateWindow("Gears");
    Initial(argc,argv);

    glutDisplayFunc(myDisplay);
    glutReshapeFunc(myReshape);
    glutKeyboardFunc(myKeyboard);
    glutSpecialFunc(mySpecial);
    glutVisibilityFunc(myVisible);
    updateIdleFunc();

    glutMainLoop();
    return 0;
}