1

我目前正在绘制 3D 空间中的 lorenz 吸引子,并尝试在屏幕上绘制动画。我在我的显示函数中编写了以下 while 循环,认为它会按我的预期进行。

    int i;
    float x = 0, y = 1, z = 0;
    glBegin(GL_LINE_STRIP);

    while (i < initialIterations) {
        glColor3f(0,1,0);
        // compute a new point using the strange attractor equations
        float dx = sigma*(y-x);
        float dy = x*(r-z) - y;
        float dz = x*y - b*z;

        // save the new point
        x = x + dx*dt;
        y = y + dy*dt;
        z = z + dz*dt;        

        glVertex3f(x/50,y/50,z/50);
        i++;
    }

    glEnd();

但是它只是绘制了整个吸引子的图表,并没有显示每次迭代。

4

2 回答 2

4

如果您的上下文是双缓冲的,那么将无法看到此动画,因为它会在屏幕外绘制所有内容,然后在调用 swapbuffers 后将图片翻转到屏幕上。

如果你想解决这个问题,而不是绘制整个吸引子,设置一个循环计数器,这样在第 0 帧,你只画点 0,在第 1 帧你画点 0 到 1,在第 2 帧你画点 0 到 2 , ETC。

如果您的上下文是单缓冲的,您可以在绘制时看到它的动画,尽管它可能非常快以至于您永远无法看到它动画。它可能在大约一毫秒内完成绘制该循环。如果您希望动画对人眼可见,则需要在每个循环之间放置某种等待或睡眠。

于 2012-09-20T18:15:01.777 回答
1

试一试:

#include <GL/glut.h>
#include <vector>

struct Vertex
{
    Vertex( float x, float y, float z ) : x(x), y(y), z(z) {}
    float x;
    float y;
    float z;
};
std::vector< Vertex > verts;

void fillVerts()
{
    // calculate vertices
    // http://paulbourke.net/fractals/lorenz/
    int N = 10000;
    int i = 0;
    double x0, y0, z0, x1, y1, z1;
    double h = 0.01;
    double a = 10.0;
    double b = 28.0;
    double c = 8.0 / 3.0;

    x0 = 0.1;
    y0 = 0;
    z0 = 0;
    for( i = 0; i < N; i++ ) 
    {
        x1 = x0 + h * a * (y0 - x0);
        y1 = y0 + h * (x0 * (b - z0) - y0);
        z1 = z0 + h * (x0 * y0 - c * z0);
        x0 = x1;
        y0 = y1;
        z0 = z1;

        if( i > 100 )
        {
            verts.push_back( Vertex( x0, y0, z0 ) );
        }
    }
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef( 0, 0, -10 );

    // spin
    static float angle = 0;
    angle += 0.1;
    glRotatef( angle, 1, 1, 1 );

    // resize
    float s = 1 / 10.0f;
    glScalef(s,s,s);

    // animate index
    static size_t curIdx = 0;
    curIdx += 2;
    if( curIdx >= verts.size() )
        curIdx = 0;

    // draw curve
    glEnableClientState( GL_VERTEX_ARRAY );
    glVertexPointer( 3, GL_FLOAT, 0, &verts[0] );
    glDrawArrays( GL_LINE_STRIP, 0, curIdx );
    glDisableClientState( GL_VERTEX_ARRAY );

    glutSwapBuffers();
}

void reshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective( 60, (double)w / (double)h, 1.0, 10000.0 );
}

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

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

    glutInitWindowSize(800,600);
    glutCreateWindow("Attractor");

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutTimerFunc(0, timer, 0);

    fillVerts();
    glutMainLoop();
    return 0;
}

它用于glutTimerFunc()每隔 16 毫秒左右戳一下显示函数,此时它会绘制接下来的两个 Lorenz 顶点。

于 2012-09-20T18:54:16.050 回答