【问题标题】:Animate rectangle height increase/decrease?动画矩形高度增加/减少?
【发布时间】:2021-08-16 12:13:34
【问题描述】:

我想知道如何在 OpenGL 中制作一个表示高度增加/减少的矩形的动画。我知道我应该使用 glScale 和 glTranslate 函数。

下面,我将附上到目前为止我使用过的代码,其中我设法应用了一个非常基本的矩形过渡。

#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdlib.h>

static GLfloat trans = 0.0;

void init(void)
{
    glClearColor(0.2, 0.2, 0.2, 0.2);
    glShadeModel(GL_FLAT);
}
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glPushMatrix();
    glTranslatef(0.0 , trans, 1.0);
    glColor3f(1.0, 1.0, 1.0);
    glRectf(-25.0, -25.0, 25.0, 25.0);
    glPopMatrix();
    glColor3f(0.0, 0.0, 1.0);
    glRectf(-15.0, -15.0, 15.0, 15.0);
    glutSwapBuffers();
}
void transLeft(void)
{
    trans = trans - 0.05;
    if (trans < -75)
        trans = -75;
    glutPostRedisplay();
}
void transRight(void)
{
    trans = trans + 0.05;
    if (trans > 75)
        trans = 75;

    glutPostRedisplay();
}

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-100.0, 100.0, -100.0, 100.0, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
void mouse(int button, int state, int x, int y)
{
    switch (button) {
    case GLUT_LEFT_BUTTON:
        if (state == GLUT_DOWN)
            glutIdleFunc(transLeft);
        break;
    case GLUT_RIGHT_BUTTON:
        if (state == GLUT_DOWN)
            glutIdleFunc(transRight);
        break;
    default:
        break;
    }
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutMainLoop();
    return 0;
}

【问题讨论】:

  • 要么将glRect 中的硬编码坐标更改为变量,要么将glScalef(zoom,zoom,1.0) 放在您的显示函数中glTranslate 之后或之前(取决于您想要实现的目标),请注意可能需要更改转换值(乘以或除以zoom),其中zoom=1.0 是可变的以更改大小...通过zoom*=1.025zoom/=1.025 更新它以获取inc/dec 大小...在某些键盘上点击或鼠标滚轮或其他...
  • 一段代码或类似的东西不会伤害我或任何东西,但如果你没有时间或者只是不想这样做,那也没关系。我仍然无法让它工作,我想如果你能发布一个实际的代码行,我会更好地理解。
  • @EmanuelComan 其实评论glScalef(zoom,zoom,1.0)中有一行代码。您可以为 x 和 y 使用单独的比例:glScalef(zoom_x, zoom_x,1.0)。按时间更改zoom_xzoom_y。尝试 [0.5, 1.5] 范围内的值。
  • 是的,我知道,但我试过了,但还是不行,我想知道除了这个命令之外我是否应该添加其他任何东西。此外,我不确定我应该将该命令放在我的代码中的什么位置。
  • @EmanuelComan 你必须在glTranslatef之后添加glScale

标签: c animation opengl glut opengl-compat


【解决方案1】:

所以你想要可变高度的矩形(基于什么?)。

glScale(1.0,zoom,1.0)直接放在行之前或之后

glTranslatef(0.0 , trans, 1.0);

在您的display(void) 函数中将执行此操作。缩放保持您的动画状态并以值 zoom=1.0 开始并更改大小,您只需像这样递增/递减:zoom*=1.025 or zoom/=1.025

但是,通常最好将硬编码的矩形顶点与基于参数或时间的可变顶点或您想要更改的任何内容进行交换。这样,您可以使用参数在最小和最大矩形大小之间进行插值,而无需更改矩阵,如果您不小心,这可能会对其他对象造成问题,而且这种方式还提供了更方便的动画控制。例如你有:

glRectf(-25.0, -25.0, 25.0, 25.0);

并希望将其设置为动画大小:

glRectf(-25.0, -35.0, 25.0, 35.0);

随着时间的推移,您可以这样做:

  1. 添加一些全局或静态变量来保存您的矩形大小、位置和动画状态:

                   // x0, y0beg, y0end,   x1,y1beg,y1end
    float myrec[]={-25.0, -25.0, -35.0, 25.0, 25.0, 35.0}; 
    float t=0.0; // parameter in range <0.0,1.0>
    
  2. 在显示中计算您的矩形实际坐标并进行渲染

    你可以像这样使用线性插值:

    glRectf(myrect[0],myrect[1]+((myrect[2]-myrect[1])*t),
            myrect[3],myrect[4]+((myrect[5]-myrect[4])*t));
    
  3. 在某处为您设置t 动画

    在哪里取决于你想要实现的目标......如果你有计时器或某个呼叫,si 一次又一次地重复,你可以将其中的 t 增加一些步骤,例如:

    t+=dt/T;
    if (t>1.0) t=1.0; // use t=0.0; if you want to repeat the animation after it finishes
    

    dt 是重复调用的平均时间,T 是整个动画完成的时间。我不使用 GLUT,所以我只是假设您的 Display 被重复调用(例如每秒 60 次)并希望动画在 2 秒内完成:

    // dt = 1.0/60
    // T  = 2.0
    t+=(1.0/120.0);
    if (t>1.0) t=1.0; // use t=0.0; if you want to repeat the animation after it 
    

    您还可以使用上次调用的经过时间(通过您可以使用的某些操作系统或环境功能测量它,我通常在 Windows 上使用性能计时器/计数器)而不是 dt

如果您有更多这样的矩形,您可以将其封装到某个函数中,并使用指向其myrect 值和参数t 的指针调用它,例如:

void draw_rect(float *myrec,float t)
   {
   glRectf(myrect[0],myrect[1]+((myrect[2]-myrect[1])*t),
           myrect[3],myrect[4]+((myrect[5]-myrect[4])*t));
   }

float rec0[]={-25.0, -25.0, -35.0, 25.0, 25.0, 35.0}; 
float rec1[]={-15.0, -15.0, -25.0, 15.0, 15.0, 25.0}; 
float t=0.0; // parameter in range <0.0,1.0>
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glPushMatrix();
    glTranslatef(0.0 , trans, 1.0);
    glColor3f(1.0, 1.0, 1.0);
    draw_rect(rec0,t);
    glPopMatrix();
    glColor3f(0.0, 0.0, 1.0);
    draw_rect(rec1,t);
    glutSwapBuffers();

    t+=(1.0/120.0);
    if (t>1.0) t=0.0;
}

【讨论】:

    猜你喜欢
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    • 2012-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    相关资源
    最近更新 更多