Open GL中的动画

时间:2014-03-11 18:39:21

标签: opengl glut

我从未理解过如何在OpenGL中使用动画。我正在研究他的项目试图让它运作但从未让滑雪者移动。试图弄清楚如何解决这个问题。

 #include "../shared/gltools.h" // OpenGL toolkit
 #define PI 3.14159265
  float a = -5;//maybe
    float b = 29;
    float c = 27;
    float d = 28.25;
    float e = 28.5;
  bool lookUp;
  bool setback;
  bool lookDown;
  bool lookLeft;
  bool lookRight;
  bool walkForward;
  bool walkBackward;
  bool strafeLeft;
  bool strafeRight;
  float xTranslation;
  float yTranslation;
  float zTranslation;
  float yRotationAngle;
  float zRotationAngle;
  float xRotationAngle;
  int mouseLastx; 
  int mouseLasty; 
  float sunRotationAngle=0;
  float sunRadius = 150.0;
  float day=0;
  float dusk=1;
  // Light values and coordinates
  GLfloat    lightPos[] = { 0.0f, 30.0f, 0.0f, 1.0f };
  GLfloat    lightPos2[] = { 0.0f, 0.0f, 40.0f, 1.0f };
  GLfloat  specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};
  GLfloat  specular2[] = { 0.0f, 1.0f, 0.0f, 1.0f};
  GLfloat  diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f};
  GLfloat  diffuse2[] = { 0.0f, 0.3f, 0.0f, 1.0f};
  GLloat  specref[] =  { 1.0f, 1.0f, 1.0f, 1.0f };
  GLfloat  ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f};
  GLfloat  spotDir[] = { 0.0f, 0.0f, -1.0f };

  void mouseMovement(int x, int y) 
  {
    int mouseDiffx=x-mouseLastx; 
    int mouseDiffy=y-mouseLasty; 
    mouseLastx=x; 
    mouseLasty=y; //set lasty to the current y position
    xRotationAngle += (GLfloat) mouseDiffy; 
    yRotationAngle += (GLfloat) mouseDiffx;
    if (xRotationAngle>=90)
            xRotationAngle=90;
    if (xRotationAngle<=-90)
            xRotationAngle=-90;
    //cout << "x:" << x << "y:" << y << endl;
  } 


  void drawcabin()
  {
    glColor3ub(0, 0, 0);
    glBegin(GL_TRIANGLES);
        //glTranslatef(0,-5,0); // move view left
        //glNormal3f(-3,0.7,-1.7);
        //glutSolidCube(5.0f);

        glNormal3d(0,0.7,0.7);
        glVertex3d(0,6,0);
        glVertex3d(-3,3.5,-2);
        glVertex3d(2,3.5,-2);


        glNormal3d(2,-1,1);
        glVertex3d(0,6,0);
        glVertex3d(-3,3.5,-2);
        glVertex3d(2,3.5,-2);
        glTranslatef(0,-5,0); // move view left
        glNormal3d(-3,0.7,-1.7);

    glEnd();
    glColor3ub(185, 0, 0);
    glutSolidCube(5.0f);

  }
  void drawskislope()
  {
    glColor3ub(0, 0, 0);
    glBegin(GL_QUADS);
    glTranslatef(0,-5,90); // move view left
    glColor3ub(185, 122, 87);
        glNormal3d(0,5,1);
        glVertex3d(10,0,5);
        glVertex3d(10,.5,5);
        glVertex3d(15,.5,5);
        glVertex3d(15,0,5);//small square

    glColor3ub(201, 192, 187);  
        glVertex3d(11.5,.5,5);
        glVertex3d(13.5,.5,5);
        glVertex3d(13.5,-10,5);
        glVertex3d(11.5,-10,5);
        //slope start


        glTranslatef(0,-5,0); // move view left
    //  glNormal3d(-3,0.7,-1.7);

    glEnd();
  }


  void drawskier()
  {
    float a = -5;//maybe
    float b = 29;
    float c = 27;
    float d = 28.25;
    float e = 28.5;

    glBegin(GL_QUADS);
    glTranslatef(0,-5,0); // move view 
    glColor3ub(185, 122, 87);
        glNormal3d(0,5,1);
        //Do While loop
    //  do
    //  {


        // to move skier do a loop and update a in the translate
        glTranslatef(0,a,0); // move view 
        glVertex3d(c,0,5);//10
        glVertex3d(c,.1,5);//10
        glVertex3d(b,.1,5);//15
        glVertex3d(b,0,5);//skis on skier

        glNormal3d(0,5,1);
        glVertex3d(d,0,5);
        glVertex3d(d,1.35,5);
        glVertex3d(e,1.35,5);
        glVertex3d(e,0,5);//body on skier
        glutSwapBuffers;

  //    }while(b>15); //try to animate
    glEnd();
    glFlush();
    b=b-1;
            c=c-1;
            d=d-1;
            e=e-1;
            glutPostRedisplay();
        glTranslatef(30,3,0); // move view left
        glColor3ub(168, 220, 109);
        glutSolidSphere(.5,7,8);                //sphere-head


     glPushMatrix();
        glTranslatef(3.5,-100,2);
        glutSolidSphere(25,15,15);                //sphere
    glPopMatrix();


  }
  void updatescene()
  {




  }

  ///////////////////////////////////////////////////////////
  // Called to draw scene
  void RenderScene(void)
  {
    GLUquadricObj *pObj;    // Quadric Object
    pObj = gluNewQuadric(); 
    gluQuadricNormals(pObj, GLU_SMOOTH);
    GLfloat horizontalMovement=1;
    GLfloat verticalMovement=0;
    horizontalMovement=cos(xRotationAngle*PI/180);
    verticalMovement=-sin(xRotationAngle*PI/180);

        // Reset Model view matrix stack
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    horizontalMovement=cos(xRotationAngle*PI/180);
    verticalMovement=-sin(xRotationAngle*PI/180);

    if (lookDown)
    {
        xRotationAngle+=1;
        if (xRotationAngle>=90)
            xRotationAngle=90;
    }
    if (lookUp)
    {
        xRotationAngle-=1;
     if (xRotationAngle<=-90)
            xRotationAngle=-90;
    }
    if (lookRight)
    {
        yRotationAngle+=1;
        if (yRotationAngle>=360)
            yRotationAngle=0;
    }
    if (lookLeft)
    {
        yRotationAngle-=1;
        if (yRotationAngle<=-360)
            yRotationAngle=0;
    }
    if (walkForward)
    {
        zTranslation+=cos(yRotationAngle*PI/180)*horizontalMovement;
        xTranslation-=sin(yRotationAngle*PI/180)*horizontalMovement;
        yTranslation-=verticalMovement;
    }
    if (walkBackward)
    {
        zTranslation-=cos(yRotationAngle*PI/180)*horizontalMovement;
        xTranslation+=sin(yRotationAngle*PI/180)*horizontalMovement;
        yTranslation+=verticalMovement;
    }
    if (strafeRight)
    {
        zTranslation+=cos((yRotationAngle+90)*PI/180);
        xTranslation-=sin((yRotationAngle+90)*PI/180);
    }
    if (strafeLeft)
    {
        zTranslation-=cos((yRotationAngle+90)*PI/180);
        xTranslation+=sin((yRotationAngle+90)*PI/180);
    }

    if (setback)
    {
        zTranslation=0;
        xTranslation=0;
        yTranslation=0;
    }


        // Reset Model view matrix stack
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glRotatef(xRotationAngle,1,0,0);
    glRotatef(zRotationAngle,0,0,1);
    glRotatef(yRotationAngle,0,1,0);
    glTranslatef(xTranslation,yTranslation,zTranslation);




    //glRotatef(-15,1,0,0);
    //glRotatef(90,0,1,0);
    glTranslatef(0,-0.50,-10);




        glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
        sunRotationAngle++;


    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT |  GL_DEPTH_BUFFER_BIT);


    glColor3d(0,0,0);
    glLineWidth(2);


    //snow
    glColor3ub(255, 255, 255);
    glBegin(GL_QUADS);
        glNormal3f(0,1,0);
        for (int i=-100;i<=200;i+=10) //x
            for (int j=-100;j<=200;j+=10)//z
            {

                float y1=(-j)*.25;
                float y2=(-j+10)*.25;
                glVertex3d(i+10,y2,-100);
                glVertex3d(i,y2,-100);
                glVertex3d(i,y1,-100);
                glVertex3d(i+10,y1,-100);
            }
    glEnd();





    glPushMatrix();
        glTranslatef(-10,14,-50);
        drawcabin();
        drawskislope();
        drawskier();
    glPopMatrix();




    // Flush drawing commands

    glutSwapBuffers();
    glutPostRedisplay();
    //GLfloat horizontalMovement=1;
  //    GLfloat verticalMovement=0;


  }

  void TimerFunction(int value)
    {
         // Redraw the scene with new coordinates
        glutPostRedisplay();
        updatescene();
        glutTimerFunc(16,TimerFunction, 1);
    }

  ///////////////////////////////////////////////////////////
  // Setup the rendering context
  void SetupRC(void)
  {
    lookUp=false;
    lookDown=false;
    lookLeft=false;
    lookRight=false;
    walkForward=false;
    walkBackward=false;
    strafeLeft=false;
    strafeRight=false;
    yRotationAngle=0;
    xRotationAngle=0;
    zRotationAngle=0;
    xTranslation=0;
    yTranslation=0;
    zTranslation=0;
    // White background
    glClearColor(0.5f,0.95f, 1.0f, 1.0f );

    // Set drawing color to green
    glColor3f(0.0f, 1.0f, 0.0f);

    // Set color shading model to flat
    glShadeModel(GL_SMOOTH);

    // Clock wise wound polygons are front facing, this is reversed
    // because we are using triangle fans
    glFrontFace(GL_CCW);

     glEnable (GL_DEPTH_TEST);










  }

  void ChangeSize(int w, int h)
    {
    //GLfloat nRange = 100.0f;

    // Prevent a divide by zero
    if(h == 0)
        h = 1;

    // Set Viewport to window dimensions
    glViewport(0, 0, w, h);

    // Reset projection matrix stack
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Establish clipping volume (left, right, bottom, top, near, far)
    GLfloat fAspect;
     fAspect = (GLfloat)w / (GLfloat)h;
    //glOrtho(-10,10,-10,10,0,1000);
    gluPerspective(45,fAspect,0.1,1000);

    // Reset Model view matrix stack
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();


    }
  // Respond to arrow keys by moving the camera frame of reference
  void SpecialKeys(int key, int x, int y)
    {
    if(key == GLUT_KEY_UP)
        lookUp=true;

    if(key == GLUT_KEY_DOWN)
        lookDown=true;

    if(key == GLUT_KEY_LEFT)
        lookLeft=true;

    if(key == GLUT_KEY_RIGHT)
        lookRight=true;

    // Refresh the Window
    glutPostRedisplay();
    }
  void SpecialKeysUp(int key, int x, int y)
    {
    if(key == GLUT_KEY_UP)
        lookUp=false;

    if(key == GLUT_KEY_DOWN)
        lookDown=false;

    if(key == GLUT_KEY_LEFT)
        lookLeft=false;

    if(key == GLUT_KEY_RIGHT)
        lookRight=false;

    // Refresh the Window
    glutPostRedisplay();
    }

  void keyboardFunc(unsigned char key, int x, int y)
  {

    switch(key)
    {
    case 'w':
        walkForward=true;
            break;
    case 's':
        walkBackward=true;
            break;
    case 'a':
        strafeLeft=true;
            break;
    case 'd':
        strafeRight=true;
            break;
    case 'r':
        setback=true;
            break;
    default:
            break;
    }

  }

  void keyboardUpFunc(unsigned char key, int x, int y)
  {
    switch(key)
    {
    case 'w':
        walkForward=false;
            break;
    case 's':
        walkBackward=false;
            break;
    case 'a':
        strafeLeft=false;
            break;
    case 'd':
        strafeRight=false;
            break;
    default:
            break;
    }


  }
  ///////////////////////////////////////////////////////////
  // Main program entry point
  int main(int argc, char* argv[])
  {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500,500); 
    glutCreateWindow("Assignment 2");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    glutSpecialFunc(SpecialKeys);
    glutSpecialUpFunc(SpecialKeysUp);
    glutKeyboardUpFunc(keyboardUpFunc);
    glutKeyboardFunc(keyboardFunc);
    glutPassiveMotionFunc(mouseMovement);
    SetupRC();

    glutMainLoop();

    return 0;
  }

1 个答案:

答案 0 :(得分:1)

我的一般方法是使用glutTimerFunc()回调每16毫秒左右发布一次重新显示事件(约60 FPS)。

然后在glutDisplayFunc()回调中,您可以获取新的GLUT_ELAPSED_TIME来计算最后一帧的增量时间(dt)。

掌握dt,您可以更新任意数量的变量,例如角度或平移偏移。您需要使用dt而不是固定增量值来将动画速度与帧速率分离。

然后回到glutDisplayFunc()回调中,使用更新的状态变量绘制一个新帧。

这是一个使用上述方法以每秒约30度旋转方块的示例:

#include <GL/glut.h>

float angle = 0;
void update( const double dt )
{
    // in degrees per second
    const float SPEED = 30.0f;

    // update angle
    angle += ( SPEED * dt );
}

void display()
{
    // GLUT_ELAPSED_TIME is in milliseconds
    static int prvMs = glutGet( GLUT_ELAPSED_TIME );
    const int curMs = glutGet( GLUT_ELAPSED_TIME );

    // dt is in seconds
    const double dt = ( curMs - prvMs ) / 1000.0;
    prvMs = curMs;

    // update world state
    update( dt );

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    // reset projection/modelview matrices each frame;
    // this makes sure we have a known-good matrix 
    // stack each time through display()
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho( -2, 2, -2, 2, -1, 1 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    // draw rotated square
    glRotatef( angle, 0, 0, 1 );
    glBegin( GL_QUADS );
    glColor3ub( 255, 0, 0 );
    glVertex2i( -1, -1 );
    glVertex2i(  1, -1 );
    glVertex2i(  1,  1 );
    glVertex2i( -1,  1 );
    glEnd();

    glutSwapBuffers();
}

void timer( int value )
{
    glutPostRedisplay();
    glutTimerFunc( 16, timer, 0 );
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );
    glutDisplayFunc( display );
    glutTimerFunc( 0, timer, 0 );
    glutMainLoop();
    return 0;
}