lorenz.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:17k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /*
  2.  * Lorenz Attractor Demo
  3.  *
  4.  * Adapted from code originally written for the 4D60GT by
  5.  * Aaron T. Ferrucci (aaronf@cse.ucsc.edu), 7/3/92.
  6.  *
  7.  * Description:
  8.  *
  9.  * This program shows some particles stuck in a Lorenz attractor (the parameters
  10.  * used are r=28, b=8/3, sigma=10). The eye is attracted to the red particle,
  11.  * with a force directly proportionate to distance. A command line
  12.  * puts the whole mess inside a box made of hexagons. I think this helps to
  13.  * maintain the illusion of 3 dimensions, but it can slow things down.
  14.  * Other options allow you to play with the redraw rate and the number of new
  15.  * lines per redraw. So you can customize it to the speed of your machine.
  16.  * 
  17.  * For general info on Lorenz attractors I recommend "An Introduction to
  18.  * the Lorenz Equations", IEEE Transactions on Circuits and Systems, August '83.
  19.  *
  20.  * Bugs: hidden surface removal doesn't apply to hexagons, and
  21.  * works poorly on lines when they are too close together.
  22.  *
  23.  * Notes on OpenGL port:
  24.  * 
  25.  * The timer functions do not exist in OpenGL, so the drawing occurs in a
  26.  * continuous loop, controlled by step, stop and go input from the keyboard.
  27.  * Perhaps system function could be called to control timing.
  28.  *
  29.  */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <math.h>
  34. #include <time.h>
  35. #include <GL/glut.h>
  36. float
  37. random_float(void)
  38. {
  39.   return (float)rand()/RAND_MAX;
  40. }
  41. void
  42. seed_random_float(long seed)
  43. {
  44.   srand(seed);
  45. }
  46. static GLuint asphere;
  47. #define POINTMASK 511
  48. #define G (0.002) /* eyept to red sphere gravity */
  49. #define LG (0.3)
  50. #define CUBESIDE (120.)
  51. #define CUBESCALE (23.)
  52. #define CUBEOFFX (-4.)
  53. #define CUBEOFFY (0.)
  54. #define CUBEOFFZ (57.)
  55. #define FALSE 0
  56. #define TRUE 1
  57. /* globals */
  58. float sigma = 10., r = 28., b = 8./3., dt = 0.003;
  59. int rp = 0, bp = 0, gp = 0, yp = 0, mp = 0;
  60. long xmax, ymax, zmax, zmin;
  61. float rv[POINTMASK+1][3], /* red points */
  62. bv[POINTMASK+1][3], /* blue points */
  63. gv[POINTMASK+1][3], /* green points */
  64. yv[POINTMASK+1][3], /* yellow points */
  65. mv[POINTMASK+1][3]; /* magenta points */
  66. int lpf; /* number of new lines per frame */
  67. float eyex[3], /* eye location */
  68.  eyev[3], /* eye velocity */
  69.  eyel[3]; /* lookat point location */
  70. GLint fovy = 600;
  71. float dx, dy, dz;
  72. GLUquadricObj *quadObj;
  73. float cubeoffx = CUBEOFFX;
  74. float cubeoffy = CUBEOFFY;
  75. float cubeoffz = CUBEOFFZ;
  76. float farplane = 80.;
  77. int animate = 1;
  78. /* option flags */
  79. GLboolean hexflag, /* hexagons? */
  80. sflag, 
  81. fflag,
  82. wflag,
  83. gflag,
  84. debug;
  85. /* option values */
  86. short hexbright; /* brightness for hexagon color */
  87. int speed, /* speed (number of new line segs per redraw) */
  88.     frame; /* frame rate (actually noise value for TIMER0) */
  89. float a = 0,
  90.     da; /* hexagon rotational velocity (.1 degree/redraw) */
  91. float gravity;
  92. /* function declarations */
  93. void init_3d(void);
  94. void init_graphics(void);
  95. void draw_hexcube(void);
  96. void draw_hexplane(void);
  97. void draw_hexagon(void);
  98. void move_eye(void);
  99. void redraw(void);
  100. void next_line(float v[][3], int *p);
  101. void parse_args(int argc, char **argv);
  102. void print_usage(char*);
  103. void print_info(void);
  104. void sphdraw(float args[4]);
  105. void setPerspective(int angle, float aspect, float zNear, float zFar);
  106. static void Reshape(int width, int height)
  107. {
  108.       glViewport(0,0,width,height);
  109.       glClear(GL_COLOR_BUFFER_BIT);
  110.       xmax = width;
  111.       ymax = height;
  112. }
  113. /* ARGSUSED1 */
  114. static void Key(unsigned char key, int x, int y)
  115. {
  116.     switch (key) {
  117.       case 'g':
  118. animate = 1;
  119. glutPostRedisplay();
  120. break;
  121.       case 's':
  122.  animate = 0;
  123.  glutPostRedisplay();
  124.  break;
  125.       case 27:
  126. gluDeleteQuadric(quadObj);
  127. exit(0);
  128.     }
  129. }
  130. static void Draw(void)
  131. {
  132.     int i;
  133.     if (animate) {
  134. i = speed;
  135. while (i--) {
  136.     next_line(rv, &rp);
  137.     next_line(bv, &bp);
  138.     next_line(gv, &gp);
  139.     next_line(yv, &yp);
  140.     next_line(mv, &mp);
  141. }
  142. glPushMatrix();
  143. move_eye();
  144. redraw();
  145. glPopMatrix();
  146.     }
  147. }
  148. int main(int argc, char **argv)
  149. {
  150.     glutInitWindowSize(600, 600);
  151.     glutInit(&argc, argv);
  152.     parse_args(argc, argv);
  153.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  154.     glutCreateWindow("Lorenz Attractors");
  155.     init_3d();
  156.     init_graphics();
  157.     /* draw the first POINTMASK points in each color */
  158.     while(rp < POINTMASK) {
  159. next_line(rv, &rp);
  160. next_line(bv, &bp);
  161. next_line(gv, &gp);
  162. next_line(yv, &yp);
  163. next_line(mv, &mp);
  164.     }
  165.     eyex[0] = eyex[1] = eyex[2] = 0.;
  166.     eyel[0] = rv[rp][0];
  167.     eyel[1] = rv[rp][1];
  168.     eyel[2] = rv[rp][2];
  169.     glPushMatrix();
  170.     move_eye();
  171.     redraw();
  172.     glPopMatrix();
  173.     glutReshapeFunc(Reshape);
  174.     glutKeyboardFunc(Key);
  175.     glutIdleFunc(Draw);
  176.     glutDisplayFunc(Draw);
  177.     glutMainLoop();
  178.     return 0;             /* ANSI C requires main to return int. */
  179. }
  180. /* compute the next point on the path according to Lorenz' equations. */
  181. void next_line(float v[][3], int *p)
  182. {
  183.     dx = sigma * (v[*p][1] - v[*p][0]) * dt;
  184.     dy = (r*v[*p][0] - v[*p][1] + v[*p][0]*v[*p][2]) * dt;
  185.     dz = (v[*p][0] *v[*p][1] + b*v[*p][2]) * dt;
  186.     v[(*p + 1) & POINTMASK][0] = v[*p][0] + dx;
  187.     v[(*p + 1) & POINTMASK][1] = v[*p][1] + dy;
  188.     v[(*p + 1) & POINTMASK][2] = v[*p][2] - dz;
  189.     *p = (*p + 1) & POINTMASK;
  190. }
  191. void drawLines(int index, float array[POINTMASK][3])
  192. {
  193.     int p;
  194.     int i;
  195. #define LINE_STEP 4
  196.     p = (index+1)&POINTMASK;
  197.     i = LINE_STEP-(p % LINE_STEP);
  198.     if (i == LINE_STEP) i=0;
  199.     glBegin(GL_LINE_STRIP);
  200. /* draw points in order from oldest to newest */
  201. while(p != index) {
  202.     if (i == 0) {
  203. glVertex3fv(array[p]);
  204. i = LINE_STEP;
  205.     } 
  206.     i--;
  207.     p = (p+1) & POINTMASK;
  208. }
  209. glVertex3fv(array[index]);
  210.     glEnd();
  211. }
  212. void redraw(void)
  213. {
  214.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  215.     if(hexflag)
  216. draw_hexcube();
  217.     glColor3f(1.0, 0.0, 0.0);
  218.     drawLines(rp, rv);
  219.     sphdraw(rv[rp]);
  220.     glColor3f(0.0, 0.0, 1.0);
  221.     drawLines(bp, bv);
  222.     sphdraw(bv[bp]);
  223.     glColor3f(0.0, 1.0, 0.0);
  224.     drawLines(gp, gv);
  225.     sphdraw(gv[gp]);
  226.     glColor3f(1.0, 0.0, 1.0);
  227.     drawLines(yp, yv);
  228.     sphdraw(yv[yp]);
  229.     glColor3f(0.0, 1.0, 1.0);
  230.     drawLines(mp, mv);
  231.     sphdraw(mv[mp]);
  232.     glutSwapBuffers();
  233. }
  234. void move_eye(void)
  235. {
  236.     /* first move the eye */
  237.     eyev[0] += gravity * (rv[rp][0] - eyex[0]);
  238.     eyev[1] += gravity * (rv[rp][1] - eyex[1]);
  239.     eyev[2] += gravity * (rv[rp][2] - eyex[2]);
  240.     /* adjust position using new velocity */
  241.     eyex[0] += eyev[0] * dt;
  242.     eyex[1] += eyev[1] * dt;
  243.     eyex[2] += eyev[2] * dt;
  244.     /* move the lookat point */
  245.     /* it catches up to the red point if it's moving slowly enough */
  246.     eyel[0] += LG * (rv[rp][0] - eyel[0]);
  247.     eyel[1] += LG * (rv[rp][1] - eyel[1]);
  248.     eyel[2] += LG * (rv[rp][2] - eyel[2]);
  249.     /* change view */
  250.     gluLookAt(eyex[0], eyex[1], eyex[2], eyel[0], eyel[1], eyel[2],
  251.       0, 1, 0);
  252. }
  253. void draw_hexcube(void)
  254. {
  255.     a += da;
  256.     if(a >= 720.) /* depends on slowest rotation factor */
  257. a = 0.;
  258.     /* draw hexplanes, without changing z-values */
  259.     glDepthMask(GL_FALSE); 
  260.     glDisable(GL_DEPTH_TEST);
  261.     /* x-y plane */
  262.     glColor3f(0.2, 0.2, 0.6);
  263.     glPushMatrix();
  264.     glTranslatef(cubeoffx, cubeoffy, cubeoffz);
  265.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  266.     draw_hexplane();
  267.     glPopMatrix();
  268.     /* x-y plane, translated */
  269.     glPushMatrix();
  270.     glTranslatef(cubeoffx, cubeoffy, cubeoffz - 2*CUBESIDE);
  271.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  272.     draw_hexplane();
  273.     glPopMatrix();
  274.     glColor3f(0.6, 0.2, 0.2);
  275.     /* x-z plane, translate low */
  276.     glPushMatrix();
  277.     glRotatef(90, 1.0, 0.0, 0.0);
  278.     glTranslatef(cubeoffx, cubeoffz - CUBESIDE, -cubeoffy + CUBESIDE);
  279.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  280.     draw_hexplane();
  281.     glPopMatrix();
  282.     /* x-z plane, translate high */
  283.     glPushMatrix();
  284.     glRotatef(90, 1.0, 0.0, 0.0);
  285.     glTranslatef(cubeoffx, cubeoffz - CUBESIDE, -cubeoffy - CUBESIDE);
  286.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  287.     draw_hexplane();
  288.     glPopMatrix();
  289.     glColor3f(0.2, 0.6, 0.2);
  290.     /* y-z plane, translate low */
  291.     glPushMatrix();
  292.     glRotatef(90, 0.0, 1.0, 0.0);
  293.     glTranslatef(-cubeoffz + CUBESIDE, cubeoffy, cubeoffx + CUBESIDE);
  294.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  295.     draw_hexplane();
  296.     glPopMatrix();
  297.     /* y-z plane, translate high */
  298.     glPushMatrix();
  299.     glRotatef (90, 0.0, 1.0, 0.0);
  300.     glTranslatef(-cubeoffz + CUBESIDE, cubeoffy, cubeoffx - CUBESIDE);
  301.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  302.     draw_hexplane();
  303.     glPopMatrix();
  304.     glFlush();
  305.     glDepthMask(GL_TRUE);
  306.     glEnable(GL_DEPTH_TEST);
  307. }
  308. float hex_data[8][3] =  {
  309.     {0., 0., 0.},
  310.     {1.155, 0., 0.},
  311.     {0.577, 1., 0.},
  312.     {-0.577, 1., 0.},
  313.     {-1.155, 0., 0.},
  314.     {-0.577, -1., 0.},
  315.     {0.577, -1., 0.},
  316.     {1.155, 0., 0.},
  317. };
  318. /* draws a hexagon 2 units across, in the x-y plane, */
  319. /* centered at <0, 0, 0> */
  320. void draw_hexagon(void)
  321. {
  322.     if(wflag) {
  323. glPushMatrix();
  324. glRotatef(a, 0.0, 0.0, 1.0);
  325.     }
  326.     glBegin(GL_TRIANGLE_FAN);
  327. glVertex3fv(hex_data[0]);
  328. glVertex3fv(hex_data[1]);
  329. glVertex3fv(hex_data[2]);
  330. glVertex3fv(hex_data[3]);
  331. glVertex3fv(hex_data[4]);
  332. glVertex3fv(hex_data[5]);
  333. glVertex3fv(hex_data[6]);
  334. glVertex3fv(hex_data[7]);
  335.     glEnd();
  336.     if(wflag)
  337. glPopMatrix();
  338. }
  339. void tmp_draw_hexplane(void)
  340. {
  341.     glRectf(-2.0, -2.0, 2.0, 2.0);
  342. }
  343. /* draw 7 hexagons */
  344. void draw_hexplane(void)
  345. {
  346.     if(wflag) {
  347. glPushMatrix();
  348. glRotatef(-0.5*a, 0.0, 0.0, 1.0);
  349.     }
  350.     /* center , <0, 0, 0> */
  351.     draw_hexagon();
  352.     /* 12 o'clock, <0, 4, 0> */
  353.     glTranslatef(0., 4., 0.);
  354.     draw_hexagon();
  355.     /* 10 o'clock, <-3.464, 2, 0> */
  356.     glTranslatef(-3.464, -2., 0.);
  357.     draw_hexagon();
  358.     /* 8 o'clock, <-3.464, -2, 0> */
  359.     glTranslatef(0., -4., 0.);
  360.     draw_hexagon();
  361.     /* 6 o'clock, <0, -4, 0> */
  362.     glTranslatef(3.464, -2., 0.);
  363.     draw_hexagon();
  364.     /* 4 o'clock, <3.464, -2, 0> */
  365.     glTranslatef(3.464, 2., 0.);
  366.     draw_hexagon();
  367.     /* 2 o'clock, <3.464, 2, 0> */
  368.     glTranslatef(0., 4., 0.);
  369.     draw_hexagon();
  370.     if(wflag)
  371. glPopMatrix();
  372. }
  373. void sphdraw(float args[3])
  374. {
  375.     glPushMatrix();
  376.     glTranslatef(args[0], args[1], args[2]);
  377.     glCallList(asphere);
  378.     glPopMatrix();
  379. }
  380. void setPerspective(int angle, float aspect, float zNear, float zFar)
  381. {
  382.     glPushAttrib(GL_TRANSFORM_BIT);
  383.     glMatrixMode(GL_PROJECTION);
  384.     gluPerspective(angle * 0.1, aspect, zNear, zFar);
  385.     glPopAttrib();
  386. }
  387. /* initialize global 3-vectors */
  388. void init_3d(void)
  389. {
  390.     (void)seed_random_float((long)time((time_t*)NULL));
  391.     /* initialize colored points */
  392.     rv[0][0] = (float)random_float() * 10.;
  393.     rv[0][1] = (float)random_float() * 10.;
  394.     rv[0][2] = (float)random_float() * 10. - 10.;
  395.     bv[0][0] = rv[0][0] + (float)random_float()*5.;
  396.     bv[0][1] = rv[0][1] + (float)random_float()*5.;
  397.     bv[0][0] = rv[0][2] + (float)random_float()*5.;
  398.     gv[0][0] = rv[0][0] + (float)random_float()*5.;
  399.     gv[0][1] = rv[0][1] + (float)random_float()*5.;
  400.     gv[0][0] = rv[0][2] + (float)random_float()*5.;
  401.     yv[0][0] = rv[0][0] + (float)random_float()*5.;
  402.     yv[0][1] = rv[0][1] + (float)random_float()*5.;
  403.     yv[0][0] = rv[0][2] + (float)random_float()*5.;
  404.     mv[0][0] = rv[0][0] + (float)random_float()*5.;
  405.     mv[0][1] = rv[0][1] + (float)random_float()*5.;
  406.     mv[0][0] = rv[0][2] + (float)random_float()*5.;
  407.     /* initialize eye velocity */
  408.     eyev[0] = eyev[1] = eyev[2] = 0.;
  409. }
  410. void init_graphics(void)
  411. {
  412.     int width = 600;
  413.     int height = 600;
  414.     xmax = width;
  415.     ymax = height;
  416.     glDrawBuffer(GL_BACK);
  417.     glEnable(GL_DEPTH_TEST);
  418.     glClearColor(0.0, 0.0, 0.0, 0.0);
  419.     glClearDepth(1.0);
  420.     glEnable(GL_CULL_FACE);
  421.     glCullFace(GL_BACK);
  422.     glViewport(0, 0, xmax, ymax);
  423.     setPerspective(fovy, (float)xmax/(float)ymax, 0.01, farplane);
  424.     quadObj = gluNewQuadric();
  425.     gluQuadricNormals(quadObj, GLU_NONE);
  426.     asphere = glGenLists(1);
  427.     glNewList(asphere, GL_COMPILE);
  428.     gluSphere(quadObj, 0.3, 12, 8);
  429.     glEndList();
  430. }
  431. #define USAGE "usage message: this space for rentn"
  432. void parse_args(int argc, char **argv)
  433. {
  434.     hexflag = sflag = fflag = wflag = gflag = debug = FALSE;
  435.     while (--argc) {
  436. if (strcmp("-X", argv[argc]) == 0) {
  437.     debug = TRUE;
  438. } else if (strcmp("-h", argv[argc]) == 0) {
  439.     print_usage(argv[0]);
  440.     exit(1);
  441. } else if (strcmp("-i", argv[argc]) == 0) {
  442.     print_info();
  443.     exit(1);
  444. } else if (strcmp("-x", argv[argc]) == 0) {
  445.     hexflag = TRUE;
  446.     farplane = 300.;
  447. } else if (strcmp("-s", argv[argc]) == 0) {
  448.     sflag = TRUE;
  449.     if (argv[argc+1])
  450. speed = atoi(argv[argc+1]);
  451.     else {
  452. printf("%s: -s option requires an argument.n", argv[0]);
  453. exit(1);
  454.     }
  455. } else if (strcmp("-f", argv[argc]) == 0) {
  456.     fflag = TRUE;
  457.     if (argv[argc+1])
  458. frame = atoi(argv[argc+1]);
  459.     else {
  460. printf("%s: -f option requires an argument.n", argv[0]);
  461. exit(1);
  462.     }
  463.     if(frame < 0) {
  464. fprintf(stderr, "Try a small positive value for n");
  465. fprintf(stderr, "'f'; this is the number of vertical ");
  466. fprintf(stderr, "retraces per redrawn");
  467. fprintf(stderr, "Try %s -h for helpn", argv[0]);
  468. exit(1);
  469.     }
  470. } else if (strcmp("-w", argv[argc]) == 0) {
  471.     wflag = TRUE;
  472.     if (argv[argc+1])
  473. da = atof(argv[argc+1]);
  474.     else {
  475. printf("%s: -w option requires an argument.n", argv[0]);
  476. exit(1);
  477.     }
  478.     if(da > 10.) {
  479. fprintf(stderr, "That's a large rotational velocity ('w')");
  480. fprintf(stderr, " but you asked for itn");
  481.     }
  482.     break;
  483. } else if (strcmp("-g", argv[argc]) == 0) {
  484.     gflag = TRUE;
  485.     if (argv[argc+1])
  486. gravity = atof(argv[argc+1]);
  487.     else {
  488. printf("%s: -g option requires an argument.n", argv[0]);
  489. exit(1);
  490.     }
  491.     if(gravity <= 0) {
  492. fprintf(stderr, "Gravity ('g') should be positiven");
  493. fprintf(stderr, "Try %s -h for helpn", argv[0]);
  494.     }
  495. } else if (strcmp("-?", argv[argc]) == 0) {
  496.     fprintf(stderr, USAGE);
  497. }
  498.     }
  499.     /* set up default values */
  500.     if(!sflag)
  501. speed = 3;
  502.     if(!fflag)
  503. frame = 2;
  504.     if(!wflag)
  505. da = 0.;
  506.     if(!gflag)
  507. gravity = G;
  508. }
  509. void print_usage(char *program)
  510. {
  511. printf("nUsage: %s [-h] [-i] [-x] [-s speed]", program);
  512. printf(" [-w rot_v] [-g gravity]nn");
  513. printf("-h              Print this message.n");
  514. printf("-i              Print information about the demo.n");
  515. printf("-x              Enclose the particles in a box made of hexagons.n");
  516. printf("-s speed        Sets the number of new line segments per redraw n");
  517. printf("                interval per line. Default value: 3.n");
  518. /*** The X port does not currently include a timer, so this feature is disabled.
  519. printf("-f framenoise   Sets the number of vertical retraces per redrawn");
  520. printf("                interval. Example: -f 2 specifies one redraw pern");
  521. printf("                2 vertical retraces, or 30 frames per second.n");
  522. printf("                Default value: 2.n");
  523. ************/
  524. printf("-w rot_v        Spins the hexagons on their centers, and the sidesn");
  525. printf("                of the box on their centers. Hexagons spin at then");
  526. printf("                rate rot_v degrees per redraw, and box sides spinn");
  527. printf("                at -rot_v/2 degrees per redraw.n");
  528. printf("-g gravity      Sets the strength of the attraction of the eye ton");
  529. printf("                the red particle. Actually, it's not gravity sincen");
  530. printf("                the attraction is proportionate to distance.n");
  531. printf("                Default value: 0.002. Try large values!n");
  532. /* input added for GLX port */
  533. printf(" Executions control:  n");
  534. printf("    <spacebar> step through single framesn");
  535. printf("    g begin continuous framesn");
  536. printf("    s stop continuous framesn");
  537. }
  538. void print_info(void)
  539. {
  540. printf("nLORENZ ATTRACTOR DEMOnn");
  541. printf("This program shows some particles stuck in a Lorenz attractor (the n");
  542. printf("parameters used are r=28, b=8/3, sigma=10). The eye is attracted to n");
  543. printf("the red particle, with a force directly proportional to distance. n");
  544. printf("A command line argument puts the particles inside a box made of hexagons, n");
  545. printf("helping  to maintain the sense of 3 dimensions, but it can slow things down.n");
  546. printf("Other options allow you to play with the redraw rate and gravity.nn");
  547. printf("Try lorenz -h for the usage message.n");
  548. }