在供过于求简单的2D动画 [英] simple 2d animation in glut

查看:219
本文介绍了在供过于求简单的2D动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个分配的事,但我似乎无法真实地融为一体prehend它。 的分配如下:将纹理背景(太阳能系统),加入纹理,以2个对象(绘制的形状),并添加一个动画,其中两个对象具有从海誓山盟&安培反​​弹;从很远的墙壁(如在屏幕的结束)。

我已经能够做到一切,除了动画。 我怎样才能做到这种动画? 附:动画中有最好的我能想出。

 的#include< GL / glut.h>
#包括< GL / gl.h>
#包括< stdio.h中>
#包括< stdlib.h中>
#包括<文件math.h>
#包括< time.h中>


浮动X;
浮动Ÿ;



无符号字符*为imageData;
INT imageRows,imageCols;

EXTERN无效loadBMP(字符*);
焦炭cotton1 [] =cotton1.bmp;
焦炭cotton2 [] =cotton2.bmp;
焦炭FONS [] =solar.bmp;

GLuint质地[3];
浮立方体[1],Vcube [1];

/ * GLUT回调处理* /

无效的init()
{
立方体[0] = 0;
Vcube [0] = 0.01;
立方体[1] = 0;
Vcube [1] = 0.01;


glShadeModel(GL_SMOOTH);

glGenTextures(3,&安培;纹理[0]);

   loadBMP(cotton1);
   glBindTexture(GL_TEXTURE_2D,纹理[0]);
   glTexImage2D(GL_TEXTURE_2D,0,3,imageCols,imageRows,
         0,GL_RGB,GL_UNSIGNED_BYTE,为imageData);

   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

     loadBMP(cotton2);
   glBindTexture(GL_TEXTURE_2D,纹理[1]);
   glTexImage2D(GL_TEXTURE_2D,0,3,imageCols,imageRows,
         0,GL_RGB,GL_UNSIGNED_BYTE,为imageData);

   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

        loadBMP(FONS);
   glBindTexture(GL_TEXTURE_2D,纹理[2]);
   glTexImage2D(GL_TEXTURE_2D,0,3,imageCols,imageRows,
         0,GL_RGB,GL_UNSIGNED_BYTE,为imageData);

   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

}

静态无效
调整(INT宽度,高度INT)
{
    常量浮动AR =(浮点)宽/(浮动)的高度;

    glViewport(0,0,宽度,高度);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

静态无效
空闲(空)
{
    glutPostRedisplay();
}

无效动画()
{
立方体[1] + = Vcube [1];
如果(立方体[1]; 0.1)
{Vcube [1] + = Vcube [1]; }
如果(立方体[1]≥0.095)
{Vcube [1] =  -  0.01; }
如果(立方体[1]; 0)
{Vcube [1] = + 0.01; }

的glTranslatef(立方体[1],0,0);
       睡眠(100);
       glutPostRedisplay();
}


无效animation2()
{
  立方体[0] + = Vcube [0];
如果(立方体[0]≤( -  0.1))
{Vcube [0]  -  = 0.01; }
如果(立方体[0]&0)
{Vcube [0]  -  = 0.01; }
如果(立方体[0]< 0.1)
{Vcube [0] + = 0.01; }


的glTranslatef(立方体[0],0,0);
       睡眠(100);
       glutPostRedisplay();
}

无效显示器(){


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


//背景
    glLoadIdentity();
    glBindTexture(GL_TEXTURE_2D,纹理[2]);
    过glEnable(GL_TEXTURE_2D);

    glPushMatrix();
     在glBegin(GL_QUADS);
      glTexCoord2f(1.0,1.0); glVertex2f(-1.0,1.0);
      glTexCoord2f(0.0,1.0); glVertex2f(1.0,1.0);
      glTexCoord2f(0.0,0.0); glVertex2f(1.0,-1.0);
      glTexCoord2f(1.0,0.0); glVertex2f(-1.0,-1.0);
      glEnd();
      glPopMatrix();
    glDisable(GL_TEXTURE_2D);

  动画();

//纹理1
    glBindTexture(GL_TEXTURE_2D,纹理[0]);

    过glEnable(GL_TEXTURE_2D);

    glPushMatrix();
    在glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.5F,0.5F); glVertex2f(0.5F,0.0); //中央
glTexCoord2f(1.0F,0.5F); glVertex2f(0.8f + X,0.0); //对
glTexCoord2f(0.75f​​,1.0F); glVertex2f(0.55f + X,0.3f + X); //右上
glTexCoord2f(0.25f,1.0F); glVertex2f(0.35f-X,0.3f + X); //左上
glTexCoord2f(0.0,0.5F); glVertex2f(0.25f-X,0.0); //剩下
glTexCoord2f(0.25f,0.0); glVertex2f(0.45F-X,-0.3f-x)的; //左下方
glTexCoord2f(0.75f​​,0.0); glVertex2f(0.7f + X,-0.2f-X); //右下角
glTexCoord2f(1.0F,0.5F); glVertex2f(0.8f + X,0.0); //对
      glEnd();
      glPopMatrix();
    glDisable(GL_TEXTURE_2D);
//纹理2

    animation2();
    glBindTexture(GL_TEXTURE_2D,纹理[1]);

    过glEnable(GL_TEXTURE_2D);
    glPushMatrix();
    在glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.5F,0.5F); glVertex2f(-0.5f,0.0); //中央
glTexCoord2f(1.0F,0.5F); glVertex2f(-0.2f + Y,0.0); //对
glTexCoord2f(0.75f​​,1.0F); glVertex2f(-0.4f + Y,0.2F + Y); //右上
glTexCoord2f(0.25f,1.0F); glVertex2f(-0.7f-Y,0.1F + Y); //左上
glTexCoord2f(0.0,0.5F); glVertex2f(-0.8f-Y,0.0); //剩下
glTexCoord2f(0.25f,0.0); glVertex2f(-0.7f,Y,-0.1f-Y); //左下方
glTexCoord2f(0.75f​​,0.0); glVertex2f(-0.3f + Y,-0.2f-Y); //右下角
glTexCoord2f(1.0F,0.5F); glVertex2f(-0.2f + Y,0.0); //对
      glEnd();
      glPopMatrix();
    glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
glFlush();
}


静态无效
键(无符号字符键,诠释一个,int b)在
{
    开关(钥匙)
    {
        案例27:
        案例'Q':
            出口(0);
            打破;

        案+:
             如果((X + 0.01)&所述; 0.98)
             X = X + 0.01;
             如果((Y + 0.01)&所述; 0.98)
             Y = Y + 0.01;
            打破;

        外壳 '-':
             如果((X-0.1)>( -  0.15))
                X = X-0.01;
             如果((Y-0.1)GT( -  0.10))
                Y = Y-0.01;
           打破;

        案例'O':
             如果((X + 0.01)&所述; 0.98)
             X = X + 0.01;
             打破;
        案P:
             如果((X-0.1)>( -  0.15))
             X = X-0.01;
             打破;


        外壳 '[':
             如果((Y + 0.01)&所述; 0.98)
             Y = Y + 0.01;
             打破;
        外壳 ']':
             如果((Y-0.1)GT( -  0.10))
             Y = Y-0.01;
             打破;



    }
    glutPostRedisplay();
}

INT主(INT ARGC,字符* argv的[]){
   glutInit(安培; ARGC,ARGV);

   glutInitWindowSize(640,640);
   glutInitWindowPosition(50,50);
   glutCreateWindow(作业3号);
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);



   glutReshapeFunc(调整);
   glutDisplayFunc(显示);
   glutKeyboardFunc(键);
   glutIdleFunc(空闲);

   glClearColor(1.0,1.0,1.0,1.0);

   在里面();

   glutMainLoop();
   返回EXIT_SUCCESS;
}
 

解决方案

问题1:你错了一个OpenGL场景图。把你的动画1的功能,例如:

 无效animation2(
     )
{
    立方体[0] + = Vcube [0];
    如果(立方体[0]≤(-0.1)){
        Vcube [0]  -  = 0.01;
    }
    如果(立方体[0]&0){
        Vcube [0]  -  = 0.01;
    }
    如果(立方体[0]< 0.1){
        Vcube [0] + = 0.01;
    }


    的glTranslatef(立方体[0],0,0);
    睡眠(100);
    glutPostRedisplay();
}
 

这是的glTranslatef 那里结束只是垃圾对周围的一切矩阵是目前在OpenGL上下文激活。这不是如何做到这一点。

下一个问题是:你调用从图纸code中的动画功能。在起草所有的现场状态的点应确定。此外,调用该动画功能将睡在你的显示功能。这不是如何做到这一点。

好了,该怎么做:首先把所有的动画进展者功能集成到空闲循环。不睡觉,而不是衡量动画迭代之间的时间,并相应推动动画。不要在动画函数调用glutPostRedisplay。在空闲处理器是的,但不是在动画的结尾。在绘图code使用评估动画的状态进行相应放置物品。使用矩阵堆栈(glPushMatrix,glPopMatrix)让事情变得很好地分离。


 的#include< GL / glut.h>

#包括< stdio.h中>
#包括< stdlib.h中>
#包括<文件math.h>

/ *为gettimeofday的* /
#包括< SYS / time.h中>

/ *一般情况下,全局变量乱抛垃圾,你的程序应该避免。
 *我承认,有时连我自己都不遵守这个规则,尤其是
 *利用GLUT才能跳一些很神秘的箍,以避免它。
 *所以,在这种情况下,是的,有全局变量是适宜的。
 *
 *全局变量的原则思路是把数据放进去,即
 *有效和相同的整个方案的。更重要的是他们
 *不能用于绕过数据。
 *
 *这也是一个不错的主意,使这些变量静态的,所以他们是
 *包含withing这个编译单元。
 * /
静浮X;
静浮ÿ;

/ *这不是全局变量应该如何使用。他们已经习惯了身边之间传递数据
 *功能。不这样做!
 *
 *另外这忽略了extern关键字。除非编译单元加载
 * BMP文件宣称这些是为extern,因此依靠其它编译单元
 *揭露他们这个样子,这code是可能打破。

无符号字符*为imageData;
INT imageRows,imageCols;

EXTERN无效loadBMP(字符*);

 * BTW:你并不需要在这里extern关键字。

 *而是有一个可爱的小功能加载BMP文件,并把它变成一个
 *新分配的纹理对象。
* /

GLuint loadBmpToTexture(字符常量* const的文件名)
{
    / *此实现作为一个练习的读者* /
    返回0;
}

静态双FTIME(无效)
{
    / *现在,这是一个有点复杂:有没有便携式高分辨率
     *定时器功能。在Linux和Unix一样(因此也MacOS X的)你有
     * gettimeofday的,在Windows上有高性能计数器。
     * ...完全讨厌。
     *看看这里的比较:
     * http://www.songho.ca/misc/timer/timer.html
     *
     *由于我在Linux中,这是使用函数gettimeofday
     * /

    timeval结构吨;
    函数gettimeofday(& T公司,NULL);

    返回1.0 * t.tv_sec + 1E-6 * t.tv_usec;
}

/ *在这个变量我们存储动画的最后一次迭代的时间
 *循环,以确定时间为下一个时间差。 * /
静态双last_T;

/ *其实这些应该是char类型常量的*常量
 *这是C的阵列就像你已经声明他们更细的一个细节
 *这里是可变的,但不断的大小。
 *但是你通常不希望字符串常量是这样的。在preferred
 *作案手法是在只读存储器和指针的字符串常量
 * 给他们。喜欢这个:
 * /
字符常量* const的cotton1 =cotton1.bmp;
字符常量* const的cotton2 =cotton2.bmp;
字符常量* const的FONS =solar.bmp;

/ *好了,现在考虑,如果你有几个对象,不只是两个或会发生什么
 * 三?你将如何跟踪所有这些指标?真的,这是很糟糕的风格。
 *如果你的数据属于在一起,就像一个对象的状态,把它变成一个结构
 *然后还用非常有用的变量名。
 * /

GLuint texture_background;

typedef结构s_Cube {
    浮X,V_x;
    GLuint质感;
} 立方体;

/ *我们也可以静态初始化这里* /
立方体立方体[2] = {
    {-0.05,0.01,0},
    {0.05,-0.02,0}
};

/ * GLUT回调处理* /

静态无效的init(无效)
{
    / * loadBmpToTexture被定义为返回0失败的情况下
     *这也是OpenGL的默认纹理对象,所以这
     *安全地失败。 * /
    texture_background = loadBmpToTexture(FONS);
    立方体[0] .texture = loadBmpToTexture(cotton1);
    魔方[1] .texture = loadBmpToTexture(cotton2);

    glClearColor(0.0,0.5,0.7,1.0);

    last_T = FTIME();
}

静态无效动画(
    浮动常量速度
     )
{
    / *我们的目标是让立方体反弹到对方
     *(碰撞),并与壁。首先碰撞:* /

    如果(立方体[0] .X>立方体[1] .X&安培;&安培;立方体[0] .V_x大于0&安培;&安培;立方体[1] .V_x℃,){
        / *立方体弹开对方。交换它们的速度* /
        双常量V_x =立方体[0] .V_x;
        立方体[0] .V_x =魔方[1] .V_x;
        魔方[1] .V_x = V_x;

        双常量X =立方体[0] .X;
        立方体[0] .X =魔方[1] .X;
        魔方[1] .X = X;
    }

    / *与壁弹跳* /
    如果(立方体[0] .X&其中; -0.1&安培;&安培;立方体[0] .V_x℃,){
        / *左立方体弹到左墙* /
        立方体[0] .V_x * = -1;
    }

    如果(立方体[1] .X> 0.1&安培;&安培;立方体[1] .V_x大于0){
        / *正确的立方体弹到左墙* /
        立方体[1] .V_x * = -1;
    }

    立方体[0] .X + =速度*立方[0] .V_x;
    魔方[1] .X + =速度*立方[1] .V_x;
}

/ *理想情况下,我们会使用一个precise动画循环在这里交错事件处理。
 *不幸的是GLUT不提供这些,所以我们用这个神秘的杂牌。
 *
 *它会得到更稳健一点通过将整个时间到显示功能
 *不过还好放弃葡萄糖转运,并得到一个真正的事件循环。
 * /
静态无效空转(
    无效)
{
    常量双now_T = FTIME();
    常量双delta_T = now_T  -  last_T;
    last_T = now_T;

    常量倍速= delta_T * 60;

    动画(速度);
    glutPostRedisplay();
}


静态无效的显示(无效)
{
    / *我们尽可能地做到无状态越好。是的,在一个有状态的脸
     * API,如OpenGL的,这听起来有点迂腐。 * /
    const int的宽度= glutGet(GLUT_WINDOW_WIDTH);
    const int的高度= glutGet(GLUT_WINDOW_HEIGHT);
    常量浮动AR =(浮点)宽/(浮动)的高度;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    / *这是设置说来说去最佳实践相关图纸
     *  - 包括凸起 - 在绘图函数* /
    glViewport(0,0,宽度,高度);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-ar,芳,-1,1,-1,1);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
//背景
    如果(texture_background){
        glBindTexture(GL_TEXTURE_2D,texture_background);
        过glEnable(GL_TEXTURE_2D);
        在glBegin(GL_QUADS);
        glTexCoord2f(1.0,1.0);
        glVertex2f(-1.0,1.0);
        glTexCoord2f(0.0,1.0);
        glVertex2f(1.0,1.0);
        glTexCoord2f(0.0,0.0);
        glVertex2f(1.0,-1.0);
        glTexCoord2f(1.0,0.0);
        glVertex2f(-1.0,-1.0);
        glEnd();
        glDisable(GL_TEXTURE_2D);
    }

//纹理1
    glBindTexture(GL_TEXTURE_2D,立方体[1] .texture);
    过glEnable(GL_TEXTURE_2D);
    / *请记住我们仍然在模型视图矩阵模式。
     *这种推创建当前模型视图矩阵的拷贝,
     *为我们所掌握。随着下面的流行,我们恢复到
     *国家现在保存。 push和pop窝。 * /
    glPushMatrix();

    / *这适用于我们的动画位置到模型视图矩阵。
     *所有几何画图,遵循的是受本附加
     *改造,直到矩阵再次改变。 * /
    的glTranslatef(立方体[1]的.x,0,0);
    在glBegin(GL_TRIANGLE_FAN);
    glTexCoord2f(0.5F,0.5F);
    glVertex2f(0.5F,0.0); //中央
    glTexCoord2f(1.0F,0.5F);
    glVertex2f(0.8f + X,0.0); //对
    glTexCoord2f(0.75f​​,1.0F);
    glVertex2f(0.55f + X,0.3f + X); //右上
    glTexCoord2f(0.25f,1.0F);
    glVertex2f(0.35f  -  X,0.3f + X); //左上
    glTexCoord2f(0.0,0.5F);
    glVertex2f(0.25f  -  X,0.0); //剩下
    glTexCoord2f(0.25f,0.0);
    glVertex2f(0.45F  -  X,-0.3f  -  X); //左下方
    glTexCoord2f(0.75f​​,0.0);
    glVertex2f(0.7f + X,-0.2f  -  X); //右下角
    glTexCoord2f(1.0F,0.5F);
    glVertex2f(0.8f + X,0.0); //对
    glEnd();
    glPopMatrix();
    glDisable(GL_TEXTURE_2D);
//纹理2
    / *在原来的code您没有使用其它质地,
     *可能是因为你失去了跟踪变量和指标。 * /
    glBindTexture(GL_TEXTURE_2D,立方体[0] .texture);
    过glEnable(GL_TEXTURE_2D);
    glPushMatrix();
    的glTranslatef(立方体[0]的.x,0,0);
    在glBegin(GL_TRIANGLE_FAN);
    glTexCoord2f(0.5F,0.5F);
    glVertex2f(-0.5f,0.0); //中央
    glTexCoord2f(1.0F,0.5F);
    glVertex2f(-0.2f + Y,0.0); //对
    glTexCoord2f(0.75f​​,1.0F);
    glVertex2f(-0.4f + Y,0.2F + Y); //右上
    glTexCoord2f(0.25f,1.0F);
    glVertex2f(-0.7f  -  Y,0.1F + Y); //左上
    glTexCoord2f(0.0,0.5F);
    glVertex2f(-0.8f  -  Y,0.0); //剩下
    glTexCoord2f(0.25f,0.0);
    glVertex2f(-0.7f  -  Y,-0.1f  -  Y); //左下方
    glTexCoord2f(0.75f​​,0.0);
    glVertex2f(-0.3f + Y,-0.2f  -  Y); //右下角
    glTexCoord2f(1.0F,0.5F);
    glVertex2f(-0.2f + Y,0.0); //对
    glEnd();
    glPopMatrix();
    glDisable(GL_TEXTURE_2D);

    glutSwapBuffers();
    / *在这里你glfinish在是完全没有意义的。
     *首先,它都属于_before_ glutSwapBuffers。
     *第二glutSwapBuffers意味着glfinish在,所以这是完全多余的。 * /
}


静态无效键(
    无符号的字符键,
    诠释一个,
    int b)在
{
    开关(钥匙){
    案例27:
    案例'Q':
        出口(0);
        打破;

    案+:
        如果((X + 0.01)&所述; 0.98)
            X = X + 0.01;
        如果((Y + 0.01)&所述; 0.98)
            Y = Y + 0.01;
        打破;

    外壳 '-':
        如果((X  -  0.1)>(-0.15))
            X = X  -  0.01;
        如果((Y  -  0.1)>(-0.10))
            Y = Y  -  0.01;
        打破;

    案例'O':
        如果((X + 0.01)&所述; 0.98)
            X = X + 0.01;
        打破;
    案P:
        如果((X  -  0.1)>(-0.15))
            X = X  -  0.01;
        打破;


    外壳 '[':
        如果((Y + 0.01)&所述; 0.98)
            Y = Y + 0.01;
        打破;
    外壳 ']':
        如果((Y  -  0.1)>(-0.10))
            Y = Y  -  0.01;
        打破;
    }
    glutPostRedisplay();
}

INT主(
    INT ARGC,
    字符* argv的[])
{
    glutInit(安培; ARGC,ARGV);

    glutInitWindowSize(640,640);
    glutInitWindowPosition(50,50);
    / * glutInitDisplayMode必须在调用glutCreateWindow之前调用
     *过剩,像OpenGL是有状态的* /
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutCreateWindow(作业3号);

    glutDisplayFunc(显示);
    glutKeyboardFunc(键);
    glutIdleFunc(空闲);

    在里面();

    glutMainLoop();
    返回EXIT_SUCCESS;
}
 

I have an assignment to do, but i can't seem to trully comprehend it. The assignment is as follows : Adding a texture to background (solar system), adding texture to 2 objects (drawn shapes) and adding an animation where the two objects have to bounce from eachother & from far walls (as in end of screen).

I have managed to do everything except the animation. How can I do this kind of animation? p.s. animation in there is the best i could come up with.

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


float x;
float y;



unsigned char *imageData;
int imageRows, imageCols;

extern void loadBMP(char *);
char cotton1[] = "cotton1.bmp";
char cotton2[] = "cotton2.bmp";
char fons[] = "solar.bmp";

GLuint texture[3];
float cube[1], Vcube[1];

/* GLUT callback Handlers */

void init()
{
cube[0]=0;
Vcube[0]=0.01;
cube[1]=0;
Vcube[1]=0.01;


glShadeModel(GL_SMOOTH);

glGenTextures( 3, &texture[0] );

   loadBMP(cotton1);
   glBindTexture( GL_TEXTURE_2D, texture[0] );
   glTexImage2D(GL_TEXTURE_2D, 0, 3, imageCols, imageRows,
         0, GL_RGB, GL_UNSIGNED_BYTE, imageData);

   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

     loadBMP(cotton2);
   glBindTexture( GL_TEXTURE_2D, texture[1] );
   glTexImage2D(GL_TEXTURE_2D, 0, 3, imageCols, imageRows,
         0, GL_RGB, GL_UNSIGNED_BYTE, imageData);

   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

        loadBMP(fons);
   glBindTexture( GL_TEXTURE_2D, texture[2] );
   glTexImage2D(GL_TEXTURE_2D, 0, 3, imageCols, imageRows,
         0, GL_RGB, GL_UNSIGNED_BYTE, imageData);

   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

}

static void 
resize(int width, int height)
{
    const float ar = (float) width / (float) height;

    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity() ;
}

static void 
idle(void)
{
    glutPostRedisplay();
}

void animation()
{
cube[1]+=Vcube[1];
if (cube[1]<0.1)
{ Vcube[1]+=Vcube[1]; }
if (cube[1]>0.095)
{ Vcube[1]=-0.01; }
if (cube[1]<0)
{ Vcube[1]=+0.01; }

glTranslatef(cube[1],0,0);
       Sleep(100);
       glutPostRedisplay();
}


void animation2()
{
  cube[0]+=Vcube[0];
if (cube[0]<(-0.1))
{ Vcube[0]-=0.01; }
if (cube[0]>0)
{ Vcube[0]-=0.01; }
if (cube[0]<0.1)
{ Vcube[0]+=0.01; }


glTranslatef(cube[0],0,0);
       Sleep(100);
       glutPostRedisplay();
}

void display() {


    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);  


//Background
    glLoadIdentity();
    glBindTexture( GL_TEXTURE_2D, texture[2]);
    glEnable( GL_TEXTURE_2D );

    glPushMatrix();
     glBegin( GL_QUADS );
      glTexCoord2f(1.0,1.0); glVertex2f(-1.0,1.0);
      glTexCoord2f(0.0,1.0); glVertex2f(1.0,1.0);
      glTexCoord2f(0.0,0.0); glVertex2f(1.0,-1.0);
      glTexCoord2f(1.0,0.0); glVertex2f(-1.0,-1.0);
      glEnd();
      glPopMatrix();
    glDisable(GL_TEXTURE_2D);

  animation();

//TEXTURE 1
    glBindTexture( GL_TEXTURE_2D, texture[0]);

    glEnable( GL_TEXTURE_2D );

    glPushMatrix();
    glBegin( GL_TRIANGLE_FAN );
glTexCoord2f(0.5f, 0.5f);  glVertex2f(  0.5f,  0.0f);   //center
glTexCoord2f(1.0f, 0.5f);  glVertex2f(  0.8f+x,  0.0f);   //right
glTexCoord2f(0.75f, 1.0f); glVertex2f(  0.55f+x, 0.3f+x);  //top right
glTexCoord2f(0.25f, 1.0f); glVertex2f(  0.35f-x, 0.3f+x);   //Top left
glTexCoord2f(0.0f, 0.5f);  glVertex2f(  0.25f-x, 0.0f);   //left
glTexCoord2f(0.25f, 0.0f); glVertex2f(  0.45f-x,-0.3f-x);   //bottom left
glTexCoord2f(0.75f, 0.0f); glVertex2f(  0.7f+x, -0.2f-x);   //bottom right
glTexCoord2f(1.0f, 0.5f);  glVertex2f(  0.8f+x,  0.0f);   //right
      glEnd();
      glPopMatrix();
    glDisable(GL_TEXTURE_2D);
//TEXTURE 2

    animation2();   
    glBindTexture( GL_TEXTURE_2D, texture[1]);

    glEnable( GL_TEXTURE_2D );
    glPushMatrix();
    glBegin( GL_TRIANGLE_FAN );
glTexCoord2f(0.5f, 0.5f);  glVertex2f( -0.5f,  0.0f);  //center
glTexCoord2f(1.0f, 0.5f);  glVertex2f( -0.2f+y,  0.0f);  //right
glTexCoord2f(0.75f, 1.0f); glVertex2f( -0.4f+y,  0.2f+y);  //top right
glTexCoord2f(0.25f, 1.0f); glVertex2f( -0.7f-y,  0.1f+y);  //Top left
glTexCoord2f(0.0f, 0.5f);  glVertex2f( -0.8f-y,  0.0f);  //left
glTexCoord2f(0.25f, 0.0f); glVertex2f( -0.7f-y, -0.1f-y);  //bottom left
glTexCoord2f(0.75f, 0.0f); glVertex2f( -0.3f+y, -0.2f-y);  //bottom right
glTexCoord2f(1.0f, 0.5f);  glVertex2f( -0.2f+y,  0.0f);  //right
      glEnd();
      glPopMatrix();
    glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
glFlush();
}


static void 
key(unsigned char key, int a, int b)
{
    switch (key) 
    {
        case 27 : 
        case 'q':
            exit(0);
            break;

        case '+':
             if ((x+0.01)<0.98)
             x=x+0.01;
             if ((y+0.01)<0.98)
             y=y+0.01;         
            break;

        case '-':
             if ((x-0.1)>(-0.15))
                x=x-0.01;
             if ((y-0.1)>(-0.10))
                y=y-0.01;
           break;

        case 'o':
             if ((x+0.01)<0.98)
             x=x+0.01;
             break;
        case 'p':
             if ((x-0.1)>(-0.15))
             x=x-0.01;
             break;


        case '[':
             if ((y+0.01)<0.98)
             y=y+0.01;
             break;
        case ']':
             if ((y-0.1)>(-0.10))
             y=y-0.01;
             break;



    }
    glutPostRedisplay();
}

int main(int argc, char *argv[]) {
   glutInit(&argc, argv);   

   glutInitWindowSize(640, 640);   
   glutInitWindowPosition(50, 50); 
   glutCreateWindow("Assignment number 3"); 
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);



   glutReshapeFunc(resize);
   glutDisplayFunc(display);      
   glutKeyboardFunc(key);         
   glutIdleFunc(idle);

   glClearColor(1.0, 1.0, 1.0, 1.0);

   init();

   glutMainLoop();               
   return EXIT_SUCCESS;
}

解决方案

Problem 1: You mistake OpenGL for a scene graph. Take your animation1 function for example:

void animation2(
     )
{
    cube[0] += Vcube[0];
    if( cube[0] < ( -0.1 ) ) {
        Vcube[0] -= 0.01;
    }
    if( cube[0] > 0 ) {
        Vcube[0] -= 0.01;
    }
    if( cube[0] < 0.1 ) {
        Vcube[0] += 0.01;
    }


    glTranslatef( cube[0], 0, 0 );
    Sleep( 100 );
    glutPostRedisplay(  );
}

That glTranslatef there at the end will just trash around on whatever matrix is currently active in the OpenGL context. That's not how to do it.

Next problem: You're calling the animation functions from the drawing code. At the point of drawing all the scene state should be determined. Also, calling that animation function will sleep in your display function. That's not how to do it.

Okay, what to do: First put all the animation progressor functions into the idle loop. Don't sleep, instead measure the time between animation iterations and advance the animation accordingly. Don't call glutPostRedisplay in the animation functions. At the end of the idle handler yes, but not in the animators. In the drawing code use the evaluated animation state to place objects accordingly. Use the matrix stack (glPushMatrix, glPopMatrix) to keep things nicely separated.


#include <GL/glut.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/* for gettimeofday */
#include <sys/time.h>

/* In general, littering your program with global variables should be avoided.
 * I admit, that sometimes even I don't adhere to this rule, and especially
 * using GLUT it takes to jump several very arcane hoops to avoid it.
 * So in this case, yes, having global variables is in order.
 *
 * The principle idea of global variables is to put data into them, that is
 * valid and the same for the whole of the program. More importantly they
 * must not be used to pass around data.
 *
 * It's also a good idea to make those variables static, so that they are
 * contained withing this compilation unit.
 */
static float x;
static float y;

/* This is not how globals should be used. They're used to pass data around between
 * functions. DON'T DO THAT!
 *
 * Also this misses the extern keyword. Unless the compilation unit loading the
 * bmp files declares those being extern, hence relying on another compilation unit
 * to expose them like this, this code is likely to break.

unsigned char *imageData;
int imageRows, imageCols;

extern void loadBMP(char *); 

 * BTW: You don't need the extern keyword here.

 * Instead have a nice little function that loads a BMP file and puts it into a
 * newly allocated texture object.
*/

GLuint loadBmpToTexture(char const * const filename)
{
    /* Implementation of this left as an exercise to the reader */
    return 0;
}

static double ftime(void)
{
    /* Now this is a bit complicated: There's no portable high resolution
     * timer function. On Linux and Unices (hence also MacOS X) you have
     * gettimeofday, on Windows there are the High Performance Counters.
     * ... Totally annoying. 
     * Look here for a comparison:
     * http://www.songho.ca/misc/timer/timer.html
     *
     * Since I'm on a Linux box this is using gettimeofday
     */

    struct timeval t;
    gettimeofday(&t, NULL);

    return 1.0*t.tv_sec + 1e-6*t.tv_usec;
}

/* In this variable we store the time of the last iteration of the animation
 * loop to determine the time to time difference for the next one. */
static double last_T;

/* Actually those should be of type char const * const
 * This is one of the finer details of C. The arrays like you've declared them
 * here are mutable, but of constant size.
 * However you normally don't want string constant be like this. The preferred
 * modus operandi is to have the string constants in read only memory and pointers
 * to them. Like this:
 */
char const * const cotton1 = "cotton1.bmp";
char const * const cotton2 = "cotton2.bmp";
char const * const fons = "solar.bmp";

/* Okay, now consider what would happen if you had several objects, not just two or
 * three? How would you keep track of all those indices? Really, that's bad style.
 * If you've data belonging together, like state of an object, put it into a struct
 * and then also use useful variable names.
 */

GLuint texture_background;

typedef struct s_Cube {
    float x, V_x;
    GLuint texture;
} Cube;

/* also we can statically initialize here */
Cube cube[2] = {
    {-0.05, 0.01, 0},
    {0.05, -0.02, 0}
};

/* GLUT callback Handlers */

static void init(void)
{
    /* loadBmpToTexture is defined to return 0 in case of failure
     * which is also the OpenGL default texture object, so this
     * fails safely. */
    texture_background = loadBmpToTexture(fons);
    cube[0].texture = loadBmpToTexture(cotton1);
    cube[1].texture = loadBmpToTexture(cotton2);

    glClearColor( 0.0, 0.5, 0.7, 1.0 );

    last_T = ftime();
}

static void animation(
    float const speed
     )
{
    /* The objective is to let the cubes bounce into each other
     * (collision) and with the walls. First the collision: */

    if( cube[0].x > cube[1].x && cube[0].V_x > 0 && cube[1].V_x < 0 ) {
        /* cubes bounced off each other. Exchange their velocities */
        double const V_x = cube[0].V_x;
        cube[0].V_x = cube[1].V_x;
        cube[1].V_x = V_x;

        double const x = cube[0].x;
        cube[0].x = cube[1].x;
        cube[1].x = x;
    }

    /* and the wall bounce */
    if( cube[0].x < -0.1 && cube[0].V_x < 0 ) {
        /* left cube bounced into left wall */
        cube[0].V_x *= -1;
    }

    if( cube[1].x > 0.1 && cube[1].V_x > 0 ) {
        /* right cube bounced into left wall */
        cube[1].V_x *= -1;
    }

    cube[0].x += speed * cube[0].V_x;
    cube[1].x += speed * cube[1].V_x;
}

/* Ideally we'd use a precise animation loop interleaved with event processing here.
 * Unfortunately GLUT doesn't offer those, so we use this arcane kludge.
 *
 * It would get a bit more robust by putting the whole timing into the display function
 * but better abandon GLUT and get a true event loop.
 */
static void idle(
    void )
{
    const double now_T = ftime();
    const double delta_T = now_T - last_T;
    last_T = now_T;

    const double speed = delta_T * 60;

    animation( speed );
    glutPostRedisplay(  );
}


static void display(void)
{
    /* We try to be as stateless as possible. Yes, in the face of a statefull
     * API, like OpenGL, this may sound a bit pedantic. */
    const int width = glutGet(GLUT_WINDOW_WIDTH);
    const int height = glutGet(GLUT_WINDOW_HEIGHT);
    const float ar = ( float ) width / ( float ) height;

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    /* It's really best practice to set everything related to drawing
     * – and that includes the projection – in the drawing function */
    glViewport( 0, 0, width, height );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho(-ar, ar, -1, 1, -1, 1);

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
//Background
    if(texture_background) {
        glBindTexture( GL_TEXTURE_2D, texture_background );
        glEnable( GL_TEXTURE_2D );
        glBegin( GL_QUADS );
        glTexCoord2f( 1.0, 1.0 );
        glVertex2f( -1.0, 1.0 );
        glTexCoord2f( 0.0, 1.0 );
        glVertex2f( 1.0, 1.0 );
        glTexCoord2f( 0.0, 0.0 );
        glVertex2f( 1.0, -1.0 );
        glTexCoord2f( 1.0, 0.0 );
        glVertex2f( -1.0, -1.0 );
        glEnd();
        glDisable( GL_TEXTURE_2D );
    }

//TEXTURE 1
    glBindTexture( GL_TEXTURE_2D, cube[1].texture );
    glEnable( GL_TEXTURE_2D );
    /* Remember we're still in modelview matrix mode.
     * This push creates a copy of the currently modelview matrix,
     * for our disposal. With a following pop we restore to the
     * state saved now. Pushes and Pops nest. */
    glPushMatrix();

    /* This applies our animation position to the modelview matrix.
     * All geometry drawing to follow is subject to this additional
     * transformation, until the matrix changes again. */
    glTranslatef(cube[1].x, 0, 0);
    glBegin( GL_TRIANGLE_FAN );
    glTexCoord2f( 0.5f, 0.5f );
    glVertex2f( 0.5f, 0.0f );   //center
    glTexCoord2f( 1.0f, 0.5f );
    glVertex2f( 0.8f + x, 0.0f );   //right
    glTexCoord2f( 0.75f, 1.0f );
    glVertex2f( 0.55f + x, 0.3f + x );  //top right
    glTexCoord2f( 0.25f, 1.0f );
    glVertex2f( 0.35f - x, 0.3f + x );  //Top left
    glTexCoord2f( 0.0f, 0.5f );
    glVertex2f( 0.25f - x, 0.0f );  //left
    glTexCoord2f( 0.25f, 0.0f );
    glVertex2f( 0.45f - x, -0.3f - x ); //bottom left
    glTexCoord2f( 0.75f, 0.0f );
    glVertex2f( 0.7f + x, -0.2f - x );  //bottom right
    glTexCoord2f( 1.0f, 0.5f );
    glVertex2f( 0.8f + x, 0.0f );   //right
    glEnd(  );
    glPopMatrix(  );
    glDisable( GL_TEXTURE_2D );
//TEXTURE 2
    /* in the original code you didn't use the other texture, 
     * Probably because you lost track of variables and indices. */
    glBindTexture( GL_TEXTURE_2D, cube[0].texture ); 
    glEnable( GL_TEXTURE_2D );
    glPushMatrix();
    glTranslatef(cube[0].x, 0, 0);
    glBegin( GL_TRIANGLE_FAN );
    glTexCoord2f( 0.5f, 0.5f );
    glVertex2f( -0.5f, 0.0f );  //center
    glTexCoord2f( 1.0f, 0.5f );
    glVertex2f( -0.2f + y, 0.0f );  //right
    glTexCoord2f( 0.75f, 1.0f );
    glVertex2f( -0.4f + y, 0.2f + y );  //top right
    glTexCoord2f( 0.25f, 1.0f );
    glVertex2f( -0.7f - y, 0.1f + y );  //Top left
    glTexCoord2f( 0.0f, 0.5f );
    glVertex2f( -0.8f - y, 0.0f );  //left
    glTexCoord2f( 0.25f, 0.0f );
    glVertex2f( -0.7f - y, -0.1f - y ); //bottom left
    glTexCoord2f( 0.75f, 0.0f );
    glVertex2f( -0.3f + y, -0.2f - y ); //bottom right
    glTexCoord2f( 1.0f, 0.5f );
    glVertex2f( -0.2f + y, 0.0f );  //right
    glEnd();
    glPopMatrix();
    glDisable( GL_TEXTURE_2D );

    glutSwapBuffers();
    /* Your glFinish here was totally pointless.
     * First it would belong _before_ glutSwapBuffers.
     * Second glutSwapBuffers implies a glFinish, so it's totally redundant. */
}


static void key(
    unsigned char key,
    int a,
    int b )
{
    switch ( key ) {
    case 27:
    case 'q':
        exit( 0 );
        break;

    case '+':
        if( ( x + 0.01 ) < 0.98 )
            x = x + 0.01;
        if( ( y + 0.01 ) < 0.98 )
            y = y + 0.01;
        break;

    case '-':
        if( ( x - 0.1 ) > ( -0.15 ) )
            x = x - 0.01;
        if( ( y - 0.1 ) > ( -0.10 ) )
            y = y - 0.01;
        break;

    case 'o':
        if( ( x + 0.01 ) < 0.98 )
            x = x + 0.01;
        break;
    case 'p':
        if( ( x - 0.1 ) > ( -0.15 ) )
            x = x - 0.01;
        break;


    case '[':
        if( ( y + 0.01 ) < 0.98 )
            y = y + 0.01;
        break;
    case ']':
        if( ( y - 0.1 ) > ( -0.10 ) )
            y = y - 0.01;
        break;
    }
    glutPostRedisplay();
}

int main(
    int argc,
    char *argv[] )
{
    glutInit( &argc, argv );

    glutInitWindowSize( 640, 640 );
    glutInitWindowPosition( 50, 50 );
    /* glutInitDisplayMode must be called before calling glutCreateWindow
     * GLUT, like OpenGL is stateful */
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
    glutCreateWindow( "Assignment number 3" );

    glutDisplayFunc( display );
    glutKeyboardFunc( key );
    glutIdleFunc( idle );

    init();

    glutMainLoop(  );
    return EXIT_SUCCESS;
}

这篇关于在供过于求简单的2D动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆