我目前正致力于在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();
然而它只是绘制整个吸引子并且不显示每次迭代。
答案 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顶点。