OpenGL - 显示循环迭代的每个点

时间:2012-09-20 18:06:33

标签: opengl loops while-loop

我目前正致力于在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();

然而它只是绘制整个吸引子并且不显示每次迭代。

2 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分: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顶点。