1

私は現在、ローレンツ アトラクタを 3D 空間でグラフ化する作業を行っており、画面上でそのグラフ化をアニメーション化しようとしています。期待どおりに動作すると考えて、表示関数に次の 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

コンテキストがdouble-bufferedの場合、このアニメーションを表示することはできません。これは、スワップ バッファを呼び出すと、すべてが画面外に描画され、画像が画面に反転されるためです。

これを回避したい場合は、アトラクタ全体を描画する代わりに、フレーム 0 ではポイント 0 のみを描画し、フレーム 1 ではポイント 0 から 1 を描画し、フレーム 2 ではポイント 0 から 2 を描画するようにループ カウンターをセットアップします。など

コンテキストがsingle-bufferedの場合、描画中にアニメーションが表示されますが、非常に高速であるため、アニメーションが表示されることはありません。おそらく1ミリ秒程度でそのループの描画が終了します。アニメーションを人間の目に見えるようにする場合は、各ループの間に何らかの待機またはスリープを入れる必要があります。

于 2012-09-20T18:15:01.777 に答える
1

Give this a shot:

#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;
}

It uses glutTimerFunc() to poke the display function every 16 milliseconds or so, at which point it draws the next two Lorenz vertices.

于 2012-09-20T18:54:16.050 に答える