lorenz.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:17k
- /*
- * Lorenz Attractor Demo
- *
- * Adapted from code originally written for the 4D60GT by
- * Aaron T. Ferrucci (aaronf@cse.ucsc.edu), 7/3/92.
- *
- * Description:
- *
- * This program shows some particles stuck in a Lorenz attractor (the parameters
- * used are r=28, b=8/3, sigma=10). The eye is attracted to the red particle,
- * with a force directly proportionate to distance. A command line
- * puts the whole mess inside a box made of hexagons. I think this helps to
- * maintain the illusion of 3 dimensions, but it can slow things down.
- * Other options allow you to play with the redraw rate and the number of new
- * lines per redraw. So you can customize it to the speed of your machine.
- *
- * For general info on Lorenz attractors I recommend "An Introduction to
- * the Lorenz Equations", IEEE Transactions on Circuits and Systems, August '83.
- *
- * Bugs: hidden surface removal doesn't apply to hexagons, and
- * works poorly on lines when they are too close together.
- *
- * Notes on OpenGL port:
- *
- * The timer functions do not exist in OpenGL, so the drawing occurs in a
- * continuous loop, controlled by step, stop and go input from the keyboard.
- * Perhaps system function could be called to control timing.
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <time.h>
- #include <GL/glut.h>
- float
- random_float(void)
- {
- return (float)rand()/RAND_MAX;
- }
- void
- seed_random_float(long seed)
- {
- srand(seed);
- }
- static GLuint asphere;
- #define POINTMASK 511
- #define G (0.002) /* eyept to red sphere gravity */
- #define LG (0.3)
- #define CUBESIDE (120.)
- #define CUBESCALE (23.)
- #define CUBEOFFX (-4.)
- #define CUBEOFFY (0.)
- #define CUBEOFFZ (57.)
- #define FALSE 0
- #define TRUE 1
- /* globals */
- float sigma = 10., r = 28., b = 8./3., dt = 0.003;
- int rp = 0, bp = 0, gp = 0, yp = 0, mp = 0;
- long xmax, ymax, zmax, zmin;
- float rv[POINTMASK+1][3], /* red points */
- bv[POINTMASK+1][3], /* blue points */
- gv[POINTMASK+1][3], /* green points */
- yv[POINTMASK+1][3], /* yellow points */
- mv[POINTMASK+1][3]; /* magenta points */
- int lpf; /* number of new lines per frame */
- float eyex[3], /* eye location */
- eyev[3], /* eye velocity */
- eyel[3]; /* lookat point location */
- GLint fovy = 600;
- float dx, dy, dz;
- GLUquadricObj *quadObj;
- float cubeoffx = CUBEOFFX;
- float cubeoffy = CUBEOFFY;
- float cubeoffz = CUBEOFFZ;
- float farplane = 80.;
- int animate = 1;
- /* option flags */
- GLboolean hexflag, /* hexagons? */
- sflag,
- fflag,
- wflag,
- gflag,
- debug;
- /* option values */
- short hexbright; /* brightness for hexagon color */
- int speed, /* speed (number of new line segs per redraw) */
- frame; /* frame rate (actually noise value for TIMER0) */
- float a = 0,
- da; /* hexagon rotational velocity (.1 degree/redraw) */
- float gravity;
- /* function declarations */
- void init_3d(void);
- void init_graphics(void);
- void draw_hexcube(void);
- void draw_hexplane(void);
- void draw_hexagon(void);
- void move_eye(void);
- void redraw(void);
- void next_line(float v[][3], int *p);
- void parse_args(int argc, char **argv);
- void print_usage(char*);
- void print_info(void);
- void sphdraw(float args[4]);
- void setPerspective(int angle, float aspect, float zNear, float zFar);
- static void Reshape(int width, int height)
- {
- glViewport(0,0,width,height);
- glClear(GL_COLOR_BUFFER_BIT);
- xmax = width;
- ymax = height;
- }
- /* ARGSUSED1 */
- static void Key(unsigned char key, int x, int y)
- {
- switch (key) {
- case 'g':
- animate = 1;
- glutPostRedisplay();
- break;
- case 's':
- animate = 0;
- glutPostRedisplay();
- break;
- case 27:
- gluDeleteQuadric(quadObj);
- exit(0);
- }
- }
- static void Draw(void)
- {
- int i;
- if (animate) {
- i = speed;
- while (i--) {
- next_line(rv, &rp);
- next_line(bv, &bp);
- next_line(gv, &gp);
- next_line(yv, &yp);
- next_line(mv, &mp);
- }
- glPushMatrix();
- move_eye();
- redraw();
- glPopMatrix();
- }
- }
- int main(int argc, char **argv)
- {
- glutInitWindowSize(600, 600);
- glutInit(&argc, argv);
- parse_args(argc, argv);
- glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
- glutCreateWindow("Lorenz Attractors");
- init_3d();
- init_graphics();
- /* draw the first POINTMASK points in each color */
- while(rp < POINTMASK) {
- next_line(rv, &rp);
- next_line(bv, &bp);
- next_line(gv, &gp);
- next_line(yv, &yp);
- next_line(mv, &mp);
- }
- eyex[0] = eyex[1] = eyex[2] = 0.;
- eyel[0] = rv[rp][0];
- eyel[1] = rv[rp][1];
- eyel[2] = rv[rp][2];
-
- glPushMatrix();
- move_eye();
- redraw();
- glPopMatrix();
- glutReshapeFunc(Reshape);
- glutKeyboardFunc(Key);
- glutIdleFunc(Draw);
- glutDisplayFunc(Draw);
- glutMainLoop();
- return 0; /* ANSI C requires main to return int. */
- }
- /* compute the next point on the path according to Lorenz' equations. */
- void next_line(float v[][3], int *p)
- {
- dx = sigma * (v[*p][1] - v[*p][0]) * dt;
- dy = (r*v[*p][0] - v[*p][1] + v[*p][0]*v[*p][2]) * dt;
- dz = (v[*p][0] *v[*p][1] + b*v[*p][2]) * dt;
-
- v[(*p + 1) & POINTMASK][0] = v[*p][0] + dx;
- v[(*p + 1) & POINTMASK][1] = v[*p][1] + dy;
- v[(*p + 1) & POINTMASK][2] = v[*p][2] - dz;
- *p = (*p + 1) & POINTMASK;
- }
- void drawLines(int index, float array[POINTMASK][3])
- {
- int p;
- int i;
- #define LINE_STEP 4
- p = (index+1)&POINTMASK;
- i = LINE_STEP-(p % LINE_STEP);
- if (i == LINE_STEP) i=0;
- glBegin(GL_LINE_STRIP);
- /* draw points in order from oldest to newest */
- while(p != index) {
- if (i == 0) {
- glVertex3fv(array[p]);
- i = LINE_STEP;
- }
- i--;
- p = (p+1) & POINTMASK;
- }
- glVertex3fv(array[index]);
- glEnd();
- }
- void redraw(void)
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- if(hexflag)
- draw_hexcube();
- glColor3f(1.0, 0.0, 0.0);
- drawLines(rp, rv);
- sphdraw(rv[rp]);
- glColor3f(0.0, 0.0, 1.0);
- drawLines(bp, bv);
- sphdraw(bv[bp]);
-
- glColor3f(0.0, 1.0, 0.0);
- drawLines(gp, gv);
- sphdraw(gv[gp]);
- glColor3f(1.0, 0.0, 1.0);
- drawLines(yp, yv);
- sphdraw(yv[yp]);
- glColor3f(0.0, 1.0, 1.0);
- drawLines(mp, mv);
- sphdraw(mv[mp]);
- glutSwapBuffers();
- }
- void move_eye(void)
- {
- /* first move the eye */
- eyev[0] += gravity * (rv[rp][0] - eyex[0]);
- eyev[1] += gravity * (rv[rp][1] - eyex[1]);
- eyev[2] += gravity * (rv[rp][2] - eyex[2]);
- /* adjust position using new velocity */
- eyex[0] += eyev[0] * dt;
- eyex[1] += eyev[1] * dt;
- eyex[2] += eyev[2] * dt;
- /* move the lookat point */
- /* it catches up to the red point if it's moving slowly enough */
- eyel[0] += LG * (rv[rp][0] - eyel[0]);
- eyel[1] += LG * (rv[rp][1] - eyel[1]);
- eyel[2] += LG * (rv[rp][2] - eyel[2]);
- /* change view */
- gluLookAt(eyex[0], eyex[1], eyex[2], eyel[0], eyel[1], eyel[2],
- 0, 1, 0);
- }
- void draw_hexcube(void)
- {
- a += da;
- if(a >= 720.) /* depends on slowest rotation factor */
- a = 0.;
- /* draw hexplanes, without changing z-values */
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- /* x-y plane */
- glColor3f(0.2, 0.2, 0.6);
- glPushMatrix();
- glTranslatef(cubeoffx, cubeoffy, cubeoffz);
- glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
- draw_hexplane();
- glPopMatrix();
- /* x-y plane, translated */
- glPushMatrix();
- glTranslatef(cubeoffx, cubeoffy, cubeoffz - 2*CUBESIDE);
- glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
- draw_hexplane();
- glPopMatrix();
- glColor3f(0.6, 0.2, 0.2);
- /* x-z plane, translate low */
- glPushMatrix();
- glRotatef(90, 1.0, 0.0, 0.0);
- glTranslatef(cubeoffx, cubeoffz - CUBESIDE, -cubeoffy + CUBESIDE);
- glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
- draw_hexplane();
- glPopMatrix();
- /* x-z plane, translate high */
- glPushMatrix();
- glRotatef(90, 1.0, 0.0, 0.0);
- glTranslatef(cubeoffx, cubeoffz - CUBESIDE, -cubeoffy - CUBESIDE);
- glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
- draw_hexplane();
- glPopMatrix();
- glColor3f(0.2, 0.6, 0.2);
- /* y-z plane, translate low */
- glPushMatrix();
- glRotatef(90, 0.0, 1.0, 0.0);
- glTranslatef(-cubeoffz + CUBESIDE, cubeoffy, cubeoffx + CUBESIDE);
- glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
- draw_hexplane();
- glPopMatrix();
-
- /* y-z plane, translate high */
- glPushMatrix();
- glRotatef (90, 0.0, 1.0, 0.0);
- glTranslatef(-cubeoffz + CUBESIDE, cubeoffy, cubeoffx - CUBESIDE);
- glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
- draw_hexplane();
- glPopMatrix();
- glFlush();
- glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- }
- float hex_data[8][3] = {
- {0., 0., 0.},
- {1.155, 0., 0.},
- {0.577, 1., 0.},
- {-0.577, 1., 0.},
- {-1.155, 0., 0.},
- {-0.577, -1., 0.},
- {0.577, -1., 0.},
- {1.155, 0., 0.},
- };
- /* draws a hexagon 2 units across, in the x-y plane, */
- /* centered at <0, 0, 0> */
- void draw_hexagon(void)
- {
- if(wflag) {
- glPushMatrix();
- glRotatef(a, 0.0, 0.0, 1.0);
- }
- glBegin(GL_TRIANGLE_FAN);
- glVertex3fv(hex_data[0]);
- glVertex3fv(hex_data[1]);
- glVertex3fv(hex_data[2]);
- glVertex3fv(hex_data[3]);
- glVertex3fv(hex_data[4]);
- glVertex3fv(hex_data[5]);
- glVertex3fv(hex_data[6]);
- glVertex3fv(hex_data[7]);
- glEnd();
- if(wflag)
- glPopMatrix();
- }
- void tmp_draw_hexplane(void)
- {
- glRectf(-2.0, -2.0, 2.0, 2.0);
- }
- /* draw 7 hexagons */
- void draw_hexplane(void)
- {
- if(wflag) {
- glPushMatrix();
- glRotatef(-0.5*a, 0.0, 0.0, 1.0);
- }
- /* center , <0, 0, 0> */
- draw_hexagon();
- /* 12 o'clock, <0, 4, 0> */
- glTranslatef(0., 4., 0.);
- draw_hexagon();
- /* 10 o'clock, <-3.464, 2, 0> */
- glTranslatef(-3.464, -2., 0.);
- draw_hexagon();
- /* 8 o'clock, <-3.464, -2, 0> */
- glTranslatef(0., -4., 0.);
- draw_hexagon();
- /* 6 o'clock, <0, -4, 0> */
- glTranslatef(3.464, -2., 0.);
- draw_hexagon();
- /* 4 o'clock, <3.464, -2, 0> */
- glTranslatef(3.464, 2., 0.);
- draw_hexagon();
- /* 2 o'clock, <3.464, 2, 0> */
- glTranslatef(0., 4., 0.);
- draw_hexagon();
- if(wflag)
- glPopMatrix();
- }
- void sphdraw(float args[3])
- {
- glPushMatrix();
- glTranslatef(args[0], args[1], args[2]);
- glCallList(asphere);
- glPopMatrix();
- }
- void setPerspective(int angle, float aspect, float zNear, float zFar)
- {
- glPushAttrib(GL_TRANSFORM_BIT);
- glMatrixMode(GL_PROJECTION);
- gluPerspective(angle * 0.1, aspect, zNear, zFar);
- glPopAttrib();
- }
- /* initialize global 3-vectors */
- void init_3d(void)
- {
- (void)seed_random_float((long)time((time_t*)NULL));
- /* initialize colored points */
- rv[0][0] = (float)random_float() * 10.;
- rv[0][1] = (float)random_float() * 10.;
- rv[0][2] = (float)random_float() * 10. - 10.;
- bv[0][0] = rv[0][0] + (float)random_float()*5.;
- bv[0][1] = rv[0][1] + (float)random_float()*5.;
- bv[0][0] = rv[0][2] + (float)random_float()*5.;
- gv[0][0] = rv[0][0] + (float)random_float()*5.;
- gv[0][1] = rv[0][1] + (float)random_float()*5.;
- gv[0][0] = rv[0][2] + (float)random_float()*5.;
- yv[0][0] = rv[0][0] + (float)random_float()*5.;
- yv[0][1] = rv[0][1] + (float)random_float()*5.;
- yv[0][0] = rv[0][2] + (float)random_float()*5.;
- mv[0][0] = rv[0][0] + (float)random_float()*5.;
- mv[0][1] = rv[0][1] + (float)random_float()*5.;
- mv[0][0] = rv[0][2] + (float)random_float()*5.;
- /* initialize eye velocity */
- eyev[0] = eyev[1] = eyev[2] = 0.;
- }
- void init_graphics(void)
- {
- int width = 600;
- int height = 600;
- xmax = width;
- ymax = height;
- glDrawBuffer(GL_BACK);
- glEnable(GL_DEPTH_TEST);
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClearDepth(1.0);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- glViewport(0, 0, xmax, ymax);
- setPerspective(fovy, (float)xmax/(float)ymax, 0.01, farplane);
- quadObj = gluNewQuadric();
- gluQuadricNormals(quadObj, GLU_NONE);
- asphere = glGenLists(1);
- glNewList(asphere, GL_COMPILE);
- gluSphere(quadObj, 0.3, 12, 8);
- glEndList();
- }
- #define USAGE "usage message: this space for rentn"
- void parse_args(int argc, char **argv)
- {
- hexflag = sflag = fflag = wflag = gflag = debug = FALSE;
- while (--argc) {
- if (strcmp("-X", argv[argc]) == 0) {
- debug = TRUE;
- } else if (strcmp("-h", argv[argc]) == 0) {
- print_usage(argv[0]);
- exit(1);
- } else if (strcmp("-i", argv[argc]) == 0) {
- print_info();
- exit(1);
- } else if (strcmp("-x", argv[argc]) == 0) {
- hexflag = TRUE;
- farplane = 300.;
- } else if (strcmp("-s", argv[argc]) == 0) {
- sflag = TRUE;
- if (argv[argc+1])
- speed = atoi(argv[argc+1]);
- else {
- printf("%s: -s option requires an argument.n", argv[0]);
- exit(1);
- }
- } else if (strcmp("-f", argv[argc]) == 0) {
- fflag = TRUE;
- if (argv[argc+1])
- frame = atoi(argv[argc+1]);
- else {
- printf("%s: -f option requires an argument.n", argv[0]);
- exit(1);
- }
- if(frame < 0) {
- fprintf(stderr, "Try a small positive value for n");
- fprintf(stderr, "'f'; this is the number of vertical ");
- fprintf(stderr, "retraces per redrawn");
- fprintf(stderr, "Try %s -h for helpn", argv[0]);
- exit(1);
- }
- } else if (strcmp("-w", argv[argc]) == 0) {
- wflag = TRUE;
- if (argv[argc+1])
- da = atof(argv[argc+1]);
- else {
- printf("%s: -w option requires an argument.n", argv[0]);
- exit(1);
- }
- if(da > 10.) {
- fprintf(stderr, "That's a large rotational velocity ('w')");
- fprintf(stderr, " but you asked for itn");
- }
- break;
- } else if (strcmp("-g", argv[argc]) == 0) {
- gflag = TRUE;
- if (argv[argc+1])
- gravity = atof(argv[argc+1]);
- else {
- printf("%s: -g option requires an argument.n", argv[0]);
- exit(1);
- }
- if(gravity <= 0) {
- fprintf(stderr, "Gravity ('g') should be positiven");
- fprintf(stderr, "Try %s -h for helpn", argv[0]);
- }
- } else if (strcmp("-?", argv[argc]) == 0) {
- fprintf(stderr, USAGE);
- }
- }
- /* set up default values */
- if(!sflag)
- speed = 3;
- if(!fflag)
- frame = 2;
- if(!wflag)
- da = 0.;
- if(!gflag)
- gravity = G;
- }
- void print_usage(char *program)
- {
- printf("nUsage: %s [-h] [-i] [-x] [-s speed]", program);
- printf(" [-w rot_v] [-g gravity]nn");
- printf("-h Print this message.n");
- printf("-i Print information about the demo.n");
- printf("-x Enclose the particles in a box made of hexagons.n");
- printf("-s speed Sets the number of new line segments per redraw n");
- printf(" interval per line. Default value: 3.n");
- /*** The X port does not currently include a timer, so this feature is disabled.
- printf("-f framenoise Sets the number of vertical retraces per redrawn");
- printf(" interval. Example: -f 2 specifies one redraw pern");
- printf(" 2 vertical retraces, or 30 frames per second.n");
- printf(" Default value: 2.n");
- ************/
- printf("-w rot_v Spins the hexagons on their centers, and the sidesn");
- printf(" of the box on their centers. Hexagons spin at then");
- printf(" rate rot_v degrees per redraw, and box sides spinn");
- printf(" at -rot_v/2 degrees per redraw.n");
- printf("-g gravity Sets the strength of the attraction of the eye ton");
- printf(" the red particle. Actually, it's not gravity sincen");
- printf(" the attraction is proportionate to distance.n");
- printf(" Default value: 0.002. Try large values!n");
- /* input added for GLX port */
- printf(" Executions control: n");
- printf(" <spacebar> step through single framesn");
- printf(" g begin continuous framesn");
- printf(" s stop continuous framesn");
- }
- void print_info(void)
- {
- printf("nLORENZ ATTRACTOR DEMOnn");
- printf("This program shows some particles stuck in a Lorenz attractor (the n");
- printf("parameters used are r=28, b=8/3, sigma=10). The eye is attracted to n");
- printf("the red particle, with a force directly proportional to distance. n");
- printf("A command line argument puts the particles inside a box made of hexagons, n");
- printf("helping to maintain the sense of 3 dimensions, but it can slow things down.n");
- printf("Other options allow you to play with the redraw rate and gravity.nn");
- printf("Try lorenz -h for the usage message.n");
- }