home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / newopg.zip / LORENZ.C < prev    next >
Text File  |  1994-08-22  |  25KB  |  962 lines

  1. static char sccsid[] = "@(#)39    1.5  R2/OPENGL/test/samples/demos/lorenz.c, gltest, r5gos325, 9334325c 8/25/93 15:13:28";
  2. /*
  3.  *   COMPONENT_NAME: GLTEST
  4.  *
  5.  *   FUNCTIONS: SetColorIndices
  6.  *        WaitForMapNotify
  7.  *        draw_hexagon
  8.  *        draw_hexcube
  9.  *        draw_hexplane
  10.  *        init_3d
  11.  *        init_graphics
  12.  *        main
  13.  *        move_eye
  14.  *        next_line
  15.  *        parse_args
  16.  *        perspective
  17.  *        print_usage
  18.  *        redraw
  19.  *        sphdraw
  20.  *        tmp_draw_hexplane
  21.  *        
  22.  *
  23.  *   ORIGINS: 21,27
  24.  *
  25.  *   This module contains IBM CONFIDENTIAL code. -- (IBM
  26.  *   Confidential Restricted when combined with the aggregated
  27.  *   modules for this product)
  28.  *   OBJECT CODE ONLY SOURCE MATERIALS
  29.  *
  30.  *   (C) COPYRIGHT International Business Machines Corp. 1992,1993
  31.  *   All Rights Reserved
  32.  *   US Government Users Restricted Rights - Use, duplication or
  33.  *   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  34.  */
  35.  
  36. /*
  37.  *  Lorenz Attractor Demo
  38.  *
  39.  * This demo has been ported to OpenGL from the  GL4 program by Aaron Ferrucci.
  40.  *
  41.  * Description:
  42.  *
  43.  * This program shows some particles stuck in a Lorenz attractor (the parameters
  44.  * used are r=28, b=8/3, sigma=10). The eye is attracted to the red particle,
  45.  * with a force directly proportionate to distance. A command line
  46.  * puts the whole mess inside a box made of hexagons. I think this helps to
  47.  * maintain the illusion of 3 dimensions, but it can slow things down.
  48.  * Other options allow you to play with the redraw rate and the number of new
  49.  * lines per redraw. So you can customize it to the speed of your machine.
  50.  * Try lorenz -h for more info.
  51.  * 
  52.  * For general info on Lorenz attractors I recommend "An Introduction to
  53.  * the Lorenz Equations", IEEE Transactions on Circuits and Systems, August '83.
  54.  *
  55.  * Notes on OpenGL port:
  56.  * 
  57.  * The timer functions do not exist in OpenGL, so the drawing occurs in a
  58.  * continuous loop, controlled by step, stop and go input from the keyboard.
  59.  * Perhaps system function could be called to control timing.
  60.  */
  61.  
  62. #define __EXTENSIONS__
  63. #include <GL/glx.h>
  64. #include <GL/glu.h>
  65. #include <X11/keysym.h>
  66.  
  67. #include <sys/time.h>
  68. #include <math.h>
  69. #include <time.h>
  70. #include <stdio.h>
  71. #include <stdlib.h>
  72. #ifdef AIXV3 
  73. /*
  74. #include <getopt.h>
  75. */
  76. #else
  77. #include <getopt.h>
  78. #endif
  79.  
  80. static Display *dpy;
  81. static Window window;
  82.  
  83. #define POINTMASK (unsigned long)511
  84. #define G (0.002)    /* eyept to red sphere gravity */
  85. #define LG (0.3)
  86. #define CUBESIDE (120.)
  87. #define CUBESCALE (23.)
  88. #define CUBEOFFX (-4.)
  89. #define CUBEOFFY (0.)
  90. #define CUBEOFFZ (57.)
  91. #define FALSE 0
  92. #define TRUE 1
  93.  
  94. /* globals */
  95. GLint blackIndex, whiteIndex, redIndex, greenIndex, blueIndex, cyanIndex,
  96.     magentaIndex, yellowIndex, darkRedIndex, darkGreenIndex, darkBlueIndex;
  97. float sigma = 10., r = 28., b = 8./3., dt = 0.003;
  98. unsigned long rp = 0, bp = 0, gp = 0, yp = 0, mp = 0;
  99. long xmax, ymax, zmax, zmin;
  100. float rv[POINTMASK+1][3],            /* red points */
  101.     bv[POINTMASK+1][3],        /* blue points */
  102.     gv[POINTMASK+1][3],        /* green points */
  103.     yv[POINTMASK+1][3],        /* yellow points */
  104.     mv[POINTMASK+1][3];        /* magenta points */
  105.  
  106. int lpf;                /* number of new lines per frame */
  107.  
  108. float eyex[3],    /* eye location */
  109.      eyev[3],    /* eye velocity */
  110.      eyel[3];    /* lookat point location */
  111. GLint fovy = 600;
  112. float dx, dy, dz;
  113. GLUquadricObj *quadObj;
  114.  
  115. float cubeoffx = CUBEOFFX;
  116. float cubeoffy = CUBEOFFY;
  117. float cubeoffz = CUBEOFFZ;
  118. float farplane = 80.;
  119.  
  120. /* option flags */
  121. #ifdef AIXV3
  122. GLboolean hexflag,        /* hexagons? */
  123.     sflag,             
  124.         rflag,
  125.     fflag,            
  126.     wflag,
  127.     gflag,
  128.     debug;
  129. #else
  130. GLboolean hexflag,        /* hexagons? */
  131.     sflag,             
  132.     fflag,            
  133.     wflag,
  134.     gflag,
  135.     debug;
  136. #endif
  137.  
  138. /* option values */
  139. short hexbright;    /* brightness for hexagon color */
  140. #ifdef AIXV3
  141. int doubleBuffer=1;
  142. #endif
  143. int speed,        /* speed (number of new line segs per redraw) */
  144.     frame;        /* frame rate (actually noise value for TIMER0) */
  145. float a = 0,
  146.     da;            /* hexagon rotational velocity (.1 degree/redraw) */
  147. float gravity;
  148.  
  149. /* function declarations */
  150. void init_3d(void);
  151. void init_graphics(void);
  152. void draw_hexcube(void);
  153. void draw_hexplane(void);
  154. void draw_hexagon(void);
  155. void move_eye(void);
  156. void redraw(void);
  157. void next_line(float v[][3], unsigned long *p);
  158. void parse_args(int argc, char **argv);
  159. void print_usage(char*);
  160. void sphdraw(float args[4]);
  161. void perspective(int angle, float aspect, float zNear, float zFar);
  162.  
  163.  
  164. int main(int argc, char **argv)
  165. {
  166.     int i,j;
  167.     int animate = 1, doRedraw = 1;
  168.  
  169.     parse_args(argc, argv);
  170.  
  171.     init_3d();
  172.     init_graphics();
  173.  
  174.     /* draw the first POINTMASK points in each color */
  175.     while(rp < POINTMASK) {
  176.     next_line(rv, &rp);
  177.     next_line(bv, &bp);
  178.     next_line(gv, &gp);
  179.     next_line(yv, &yp);
  180.     next_line(mv, &mp);
  181.     }
  182.  
  183.     eyex[0] = eyex[1] = eyex[2] = 0.;
  184.     eyel[0] = rv[rp][0];
  185.     eyel[1] = rv[rp][1];
  186.     eyel[2] = rv[rp][2];
  187.     
  188.     glPushMatrix();
  189.     move_eye();
  190.     redraw();
  191.     glPopMatrix();
  192.  
  193.     for (;;) {
  194.     XEvent ev;
  195.  
  196.     if (XPending(dpy)) {
  197.       XNextEvent(dpy, &ev);
  198.       switch (ev.type) {
  199.         case KeyPress:
  200.           {
  201.         char buf[100];
  202.         int ret;
  203.         KeySym ks;
  204.         ret = XLookupString(&ev.xkey, buf, sizeof(buf), &ks, 0);
  205.         if (ret) {
  206.             switch (ks) {
  207.               case XK_Escape:
  208.             gluDeleteQuadric(quadObj);
  209.             return 0;
  210.               case XK_space:
  211.             doRedraw = 1;
  212.             break;
  213.               case XK_g:
  214.             animate = 1;
  215.             break;
  216.               case XK_S: case XK_s:
  217.              animate = 0;
  218.              break;
  219.               case XK_X: case XK_x:
  220.             cubeoffx += ((ev.xkey.state & ShiftMask) ? -1. : 1.);
  221.             printf("<cubeoffx,cubeoffy,cubeoffz> = <%f,%f,%f>\n",
  222.                    cubeoffx, cubeoffy, cubeoffz);
  223.             break;
  224.               case XK_Y: case XK_y:
  225.             cubeoffy += ((ev.xkey.state & ShiftMask) ? -1. : 1.);
  226.             printf("<cubeoffx,cubeoffy,cubeoffz> = <%f,%f,%f>\n",
  227.                    cubeoffx, cubeoffy, cubeoffz);
  228.             break;
  229.               case XK_Z: case XK_z:
  230.             cubeoffz += ((ev.xkey.state & ShiftMask) ? -1. : 1.);
  231.             printf("<cubeoffx,cubeoffy,cubeoffz> = <%f,%f,%f>\n",
  232.                    cubeoffx, cubeoffy, cubeoffz);
  233.             break;
  234.               case XK_minus:
  235.             farplane -= 5.;
  236.             if(farplane <= 0)
  237.                 farplane = 10.;
  238.             perspective(fovy, (float)xmax/(float)ymax,
  239.                     0.00001, farplane);
  240.             printf("farplane = %f\n", farplane);
  241.             break;
  242.               case XK_equal:
  243.             farplane += 5.;
  244.             perspective(fovy, (float)xmax/(float)ymax,
  245.                     0.00001, farplane);
  246.             printf("farplane = %f\n", farplane);
  247.             break;
  248.               default:
  249.             break;
  250.             }
  251.         }
  252.         }
  253.         break;
  254.         case ConfigureNotify:
  255.         xmax = ev.xconfigure.width;
  256.         ymax = ev.xconfigure.height;
  257.         glViewport(0, 0, xmax, ymax);
  258.         break;
  259.       }
  260.       } 
  261.       if (doRedraw || animate) {
  262.         i = speed;
  263.         while (i--) {
  264.         next_line(rv, &rp);
  265.         next_line(bv, &bp);
  266.         next_line(gv, &gp);
  267.         next_line(yv, &yp);
  268.         next_line(mv, &mp);
  269.         }
  270.         glPushMatrix();
  271.         move_eye();
  272.         redraw();
  273.         glPopMatrix();
  274.         doRedraw = 0;
  275.       }
  276.     }
  277. }
  278.  
  279. /* compute the next point on the path according to Lorenz' equations. */
  280. void next_line(float v[][3], unsigned long *p)
  281. {
  282.  
  283.     dx = sigma * (v[*p][1] - v[*p][0]) * dt;
  284.     dy = (r*v[*p][0] - v[*p][1] + v[*p][0]*v[*p][2]) * dt;
  285.     dz = (v[*p][0] *v[*p][1] + b*v[*p][2]) * dt;    
  286.     
  287.     v[(*p + 1) & POINTMASK][0] = v[*p][0] + dx;
  288.     v[(*p + 1) & POINTMASK][1] = v[*p][1] + dy;
  289.     v[(*p + 1) & POINTMASK][2] = v[*p][2] - dz;
  290.     *p = (*p + 1) & POINTMASK;
  291. }
  292.  
  293.  
  294. void redraw(void)
  295. {
  296.     unsigned long p = (rp+1)&POINTMASK;
  297.     float sph[4];
  298.     
  299.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  300.  
  301.     if(hexflag)
  302.     draw_hexcube();
  303.  
  304.     /* draw red points */
  305.     glIndexi(redIndex);
  306.     
  307.     glBegin(GL_LINE_STRIP);
  308.     /* draw points in order from oldest to newest */
  309.     while(p != rp) {
  310.         glVertex3fv(rv[p]);
  311.         p = (p + 1) & POINTMASK;
  312.     }
  313.     glVertex3fv(rv[rp]);
  314.     glEnd();
  315.  
  316.     sph[0] = rv[rp][0];
  317.     sph[1] = rv[rp][1];
  318.     sph[2] = rv[rp][2];
  319.     sph[3] = 0.1;
  320.     sphdraw(sph);
  321.  
  322.     /* draw blue points */
  323.     p = (bp + 1) & POINTMASK;
  324.     glIndexi(blueIndex);
  325.     glBegin(GL_LINE_STRIP);
  326.     while(p != bp) {
  327.         glVertex3fv(bv[p]);
  328.         p = (p + 1) & POINTMASK;
  329.     }
  330.     glVertex3fv(bv[bp]);
  331.     glEnd();
  332.  
  333.     sph[0] = bv[bp][0];
  334.     sph[1] = bv[bp][1];
  335.     sph[2] = bv[bp][2];
  336.     sph[3] = 0.1;
  337.     sphdraw(sph);
  338.     
  339.     /* draw green points */
  340.     p = (gp + 1) & POINTMASK;
  341.     glIndexi(greenIndex);
  342.  
  343.     glBegin(GL_LINE_STRIP);
  344.     while(p != gp) {
  345.         glVertex3fv(gv[p]);
  346.         p = (p + 1) & POINTMASK;
  347.     }
  348.     glVertex3fv(gv[gp]);
  349.     glEnd();
  350.  
  351.     sph[0] = gv[gp][0];
  352.     sph[1] = gv[gp][1];
  353.     sph[2] = gv[gp][2];
  354.     sph[3] = 0.1;
  355.     sphdraw(sph);
  356.  
  357.     /* draw yellow points */
  358.     p = (yp + 1) & POINTMASK;
  359.     glIndexi(yellowIndex);
  360.  
  361.     glBegin(GL_LINE_STRIP);
  362.     while(p != yp) {
  363.         glVertex3fv(yv[p]);
  364.         p = (p + 1) & POINTMASK;
  365.     }
  366.     glVertex3fv(yv[yp]);
  367.     glEnd();
  368.  
  369.     sph[0] = yv[yp][0];
  370.     sph[1] = yv[yp][1];
  371.     sph[2] = yv[yp][2];
  372.     sph[3] = 0.1;
  373.     sphdraw(sph);
  374.  
  375.     /* draw magenta points */
  376.     p = (mp + 1) & POINTMASK;
  377.     glIndexi(magentaIndex);
  378.  
  379.     glBegin(GL_LINE_STRIP);
  380.     while(p != mp) {
  381.         glVertex3fv(mv[p]);
  382.         p = (p + 1) & POINTMASK;
  383.     }
  384.     glVertex3fv(mv[mp]);
  385.     glEnd();
  386.  
  387.     sph[0] = mv[mp][0];
  388.     sph[1] = mv[mp][1];
  389.     sph[2] = mv[mp][2];
  390.     sph[3] = 0.1;
  391.     sphdraw(sph);
  392.  
  393. #ifdef AIXV3
  394.     if (doubleBuffer) {
  395.         glXSwapBuffers(dpy, window);
  396.     }
  397.     else {
  398.         glFlush();
  399.     }
  400. #else
  401.     glXSwapBuffers(dpy, window);
  402. #endif
  403. }
  404.  
  405. void move_eye(void)
  406. {
  407.     /* first move the eye */
  408.     eyev[0] += gravity * (rv[rp][0] - eyex[0]);
  409.     eyev[1] += gravity * (rv[rp][1] - eyex[1]);
  410.     eyev[2] += gravity * (rv[rp][2] - eyex[2]);
  411.  
  412.     /* adjust position using new velocity */
  413.     eyex[0] += eyev[0] * dt;
  414.     eyex[1] += eyev[1] * dt;
  415.     eyex[2] += eyev[2] * dt;
  416.  
  417.     /* move the lookat point */
  418.     /* it catches up to the red point if it's moving slowly enough */
  419.     eyel[0] += LG * (rv[rp][0] - eyel[0]);
  420.     eyel[1] += LG * (rv[rp][1] - eyel[1]);
  421.     eyel[2] += LG * (rv[rp][2] - eyel[2]);
  422.  
  423.     /* change view */
  424.     gluLookAt(eyex[0], eyex[1], eyex[2], eyel[0], eyel[1], eyel[2],
  425.           0, 1, 0);
  426. }
  427.  
  428. void draw_hexcube(void)
  429. {
  430.  
  431.     a += da;
  432.     if(a >= 720.)        /* depends on slowest rotation factor */
  433.     a = 0.;
  434.  
  435.     /* draw hexplanes, without changing z-values */
  436.     glDepthMask(GL_FALSE); 
  437.     glDisable(GL_DEPTH_TEST);
  438.  
  439.     /* x-y plane */
  440.     glIndexi(darkBlueIndex);
  441.     glPushMatrix();
  442.     glTranslatef(cubeoffx, cubeoffy, cubeoffz);
  443.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  444.     draw_hexplane();
  445.     glPopMatrix();
  446.  
  447.     /* x-y plane, translated */
  448.     glPushMatrix();
  449.     glTranslatef(cubeoffx, cubeoffy, cubeoffz - 2*CUBESIDE);
  450.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  451.     draw_hexplane();
  452.     glPopMatrix();
  453.  
  454.     glIndexi(darkRedIndex);
  455.     /* x-z plane, translate low */
  456.     glPushMatrix();
  457.     glRotatef(90, 1.0, 0.0, 0.0);
  458.     glTranslatef(cubeoffx, cubeoffz - CUBESIDE, -cubeoffy + CUBESIDE);
  459.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  460.     draw_hexplane();
  461.     glPopMatrix();
  462.  
  463.     /* x-z plane, translate high */
  464.     glPushMatrix();
  465.     glRotatef(90, 1.0, 0.0, 0.0);
  466.     glTranslatef(cubeoffx, cubeoffz - CUBESIDE, -cubeoffy - CUBESIDE);
  467.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  468.     draw_hexplane();
  469.     glPopMatrix();
  470.  
  471.     glIndexi(darkGreenIndex);
  472.     /* y-z plane, translate low */
  473.     glPushMatrix();
  474.     glRotatef(90, 0.0, 1.0, 0.0);
  475.     glTranslatef(-cubeoffz + CUBESIDE, cubeoffy, cubeoffx + CUBESIDE);
  476.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  477.     draw_hexplane();
  478.     glPopMatrix();
  479.     
  480.     /* y-z plane, translate high */
  481.     glPushMatrix();
  482.     glRotatef (90, 0.0, 1.0, 0.0);
  483.     glTranslatef(-cubeoffz + CUBESIDE, cubeoffy, cubeoffx - CUBESIDE);
  484.     glScalef(CUBESCALE, CUBESCALE, CUBESCALE);
  485.     draw_hexplane();
  486.     glPopMatrix();
  487.  
  488.     glFlush();
  489.     glDepthMask(GL_TRUE);
  490.     glEnable(GL_DEPTH_TEST);
  491. }
  492.  
  493. float hex_data[8][3] =  {
  494.     {0., 0., 0.},
  495.     {1.155, 0., 0.},
  496.     {0.577, 1., 0.},
  497.     {-0.577, 1., 0.},
  498.     {-1.155, 0., 0.},
  499.     {-0.577, -1., 0.},
  500.     {0.577, -1., 0.},
  501.     {1.155, 0., 0.},
  502. };
  503.  
  504. /* draws a hexagon 2 units across, in the x-y plane, */
  505. /* centered at <0, 0, 0> */
  506.  
  507. void draw_hexagon(void)
  508. {
  509.     if(wflag) {
  510.     glPushMatrix();
  511.     glRotatef(a, 0.0, 0.0, 1.0);
  512.     }
  513.  
  514.     glBegin(GL_TRIANGLE_FAN);
  515.     glVertex3fv(hex_data[0]);
  516.     glVertex3fv(hex_data[1]);
  517.     glVertex3fv(hex_data[2]);
  518.     glVertex3fv(hex_data[3]);
  519.     glVertex3fv(hex_data[4]);
  520.     glVertex3fv(hex_data[5]);
  521.     glVertex3fv(hex_data[6]);
  522.     glVertex3fv(hex_data[7]);
  523.     glEnd();
  524.  
  525.     if(wflag)
  526.     glPopMatrix();
  527. }
  528.  
  529. void tmp_draw_hexplane(void)
  530. {
  531.     glRectf(-2.0, -2.0, 2.0, 2.0);
  532. }
  533.  
  534. /* draw 7 hexagons */
  535. void draw_hexplane(void)
  536. {
  537.     if(wflag) {
  538.     glPushMatrix();
  539.     glRotatef(-0.5*a, 0.0, 0.0, 1.0);
  540.     }
  541.  
  542.     /* center , <0, 0, 0> */
  543.     draw_hexagon();
  544.  
  545.     /* 12 o'clock, <0, 4, 0> */
  546.     glTranslatef(0., 4., 0.);
  547.     draw_hexagon();
  548.  
  549.     /* 10 o'clock, <-3.464, 2, 0> */
  550.     glTranslatef(-3.464, -2., 0.);
  551.     draw_hexagon();
  552.  
  553.     /* 8 o'clock, <-3.464, -2, 0> */
  554.     glTranslatef(0., -4., 0.);
  555.     draw_hexagon();
  556.  
  557.     /* 6 o'clock, <0, -4, 0> */
  558.     glTranslatef(3.464, -2., 0.);
  559.     draw_hexagon();
  560.  
  561.     /* 4 o'clock, <3.464, -2, 0> */
  562.     glTranslatef(3.464, 2., 0.);
  563.     draw_hexagon();
  564.  
  565.     /* 2 o'clock, <3.464, 2, 0> */
  566.     glTranslatef(0., 4., 0.);
  567.     draw_hexagon();
  568.  
  569.     if(wflag)
  570.     glPopMatrix();
  571. }
  572.  
  573. void sphdraw(float args[4])
  574. {
  575.     glPushMatrix();
  576.     glTranslatef(args[0], args[1], args[2]);
  577.     gluSphere(quadObj, 0.3, 12, 8);
  578.     glPopMatrix();
  579. }
  580.  
  581. void perspective(int angle, float aspect, float zNear, float zFar)
  582. {
  583.     glPushAttrib(GL_TRANSFORM_BIT);
  584.     glMatrixMode(GL_PROJECTION);
  585.     glLoadIdentity();
  586.     gluPerspective(angle * 0.1, aspect, zNear, zFar);
  587.     glPopAttrib();
  588. }
  589.  
  590. /* initialize global 3-vectors */
  591. void init_3d(void)
  592. {
  593.     (void)srand48((long)time((time_t*)NULL));
  594.  
  595.     /* initialize colored points */
  596.     rv[0][0] = (float)drand48() * 10.;
  597.     rv[0][1] = (float)drand48() * 10.;
  598.     rv[0][2] = (float)drand48() * 10. - 10.;
  599.  
  600.     bv[0][0] = rv[0][0] + (float)drand48()*5.;
  601.     bv[0][1] = rv[0][1] + (float)drand48()*5.;
  602.     bv[0][0] = rv[0][2] + (float)drand48()*5.;
  603.  
  604.     gv[0][0] = rv[0][0] + (float)drand48()*5.;
  605.     gv[0][1] = rv[0][1] + (float)drand48()*5.;
  606.     gv[0][0] = rv[0][2] + (float)drand48()*5.;
  607.  
  608.     yv[0][0] = rv[0][0] + (float)drand48()*5.;
  609.     yv[0][1] = rv[0][1] + (float)drand48()*5.;
  610.     yv[0][0] = rv[0][2] + (float)drand48()*5.;
  611.  
  612.     mv[0][0] = rv[0][0] + (float)drand48()*5.;
  613.     mv[0][1] = rv[0][1] + (float)drand48()*5.;
  614.     mv[0][0] = rv[0][2] + (float)drand48()*5.;
  615.  
  616.     /* initialize eye velocity */
  617.     eyev[0] = eyev[1] = eyev[2] = 0.;
  618. }
  619.  
  620. void SetColorIndices(Colormap cmap)
  621. {
  622. XColor color, exact;
  623.  
  624.     XAllocNamedColor(dpy, cmap, "black", &color, &exact);
  625.     blackIndex = color.pixel;
  626.     XAllocNamedColor(dpy, cmap, "white", &color, &exact);
  627.     whiteIndex = color.pixel;
  628.  
  629.     XAllocNamedColor(dpy, cmap, "red", &color, &exact);
  630.     redIndex = color.pixel;
  631.     color.red = color.red /2;
  632.     color.green = color.green /2;
  633.     color.blue = color.blue/2;
  634.     XAllocColor(dpy, cmap, &color);
  635.     darkRedIndex = color.pixel;
  636.  
  637.     XAllocNamedColor(dpy, cmap, "green", &color, &exact);
  638.     greenIndex = color.pixel;
  639.     color.red = color.red /2;
  640.     color.green = color.green /2;
  641.     color.blue = color.blue/2;
  642.     XAllocColor(dpy, cmap, &color);
  643.     darkGreenIndex = color.pixel;
  644.  
  645.     XAllocNamedColor(dpy, cmap, "blue", &color, &exact);
  646.     blueIndex = color.pixel;
  647.     color.red = color.red /2;
  648.     color.green = color.green /2;
  649.     color.blue = color.blue/2;
  650.     XAllocColor(dpy, cmap, &color);
  651.     darkBlueIndex = color.pixel;
  652.  
  653.     XAllocNamedColor(dpy, cmap, "yellow", &color, &exact);
  654.     yellowIndex = color.pixel;
  655.     XAllocNamedColor(dpy, cmap, "cyan", &color, &exact);
  656.     cyanIndex = color.pixel;
  657.     XAllocNamedColor(dpy, cmap, "magenta", &color, &exact);
  658.     magentaIndex = color.pixel;
  659. }
  660.  
  661.  
  662. /***rgb settings
  663. static int attributes[] = {
  664.     GLX_RGBA,
  665.     GLX_RED_SIZE, 1,
  666.     GLX_GREEN_SIZE, 1,
  667.     GLX_BLUE_SIZE, 1,
  668.     GLX_DOUBLEBUFFER, 
  669.     GLX_DEPTH_SIZE, 1,
  670.     None,
  671. };
  672. ********/
  673. #ifdef AIXV3
  674. static int attr_sb[] = {
  675.     GLX_DEPTH_SIZE, 1,
  676.     None,
  677. };
  678. #endif
  679. static int attributes[] = {
  680.     GLX_DOUBLEBUFFER, 
  681.     GLX_DEPTH_SIZE, 1,
  682.     None,
  683. };
  684.  
  685. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  686. {
  687.     if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
  688.     return GL_TRUE;
  689.     }
  690.     return GL_FALSE;
  691. }
  692.  
  693. void init_graphics(void)
  694. {
  695.     XVisualInfo *vi;
  696.     Colormap cmap;
  697.     XSetWindowAttributes swa;
  698.     GLXContext cx;
  699.     XEvent event;
  700.     GLboolean needDisplay;
  701.     int width = 600;
  702.     int height = 600;
  703.     XTextProperty textProp;
  704.     char *winName = "Lorenz Demo";
  705.  
  706.     dpy = XOpenDisplay(0);
  707.     if (!dpy) {
  708.     fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY"));
  709.     exit(-1);
  710.     }
  711.  
  712. #ifdef AIXV3
  713.     if (doubleBuffer) {
  714.        vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributes);
  715.        if (!vi) {
  716.        fprintf(stderr, "No doublebuffered color index visual on \"%s\"\n",
  717.         getenv("DISPLAY"));
  718.        exit(-1);
  719.        }
  720.     } else {
  721.        vi = glXChooseVisual(dpy, DefaultScreen(dpy), attr_sb);
  722.        if (!vi) {
  723.             fprintf(stderr, "No color index visual on \"%s\"\n",
  724.              getenv("DISPLAY"));
  725.            exit(-1);
  726.        }
  727.     }
  728. #else
  729.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributes);
  730.     if (!vi) {
  731.         fprintf(stderr, "No doublebuffered color index visual on \"%s\"\n",getenv("DISPLAY"));
  732.         exit(-1);
  733.     }
  734. #endif
  735.  
  736.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  737.                AllocNone);
  738.     swa.border_pixel = 0;
  739.     swa.colormap = cmap;
  740.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
  741.     | KeyReleaseMask;
  742.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 10, 10,
  743.                width, height,
  744.                0, vi->depth, InputOutput, vi->visual,
  745.                CWBorderPixel|CWColormap|CWEventMask, &swa);
  746.     XSetWMColormapWindows(dpy, window, &window, 1);
  747.     XStringListToTextProperty(&winName, 1, &textProp);
  748.     XSetWMName(dpy, window, &textProp);
  749.     SetColorIndices(cmap);
  750.     XMapWindow(dpy, window);
  751.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  752.  
  753.     cx = glXCreateContext(dpy, vi, 0, GL_FALSE);
  754.     if (!glXMakeCurrent(dpy, window, cx)) {
  755.     fprintf(stderr, "Can't make window current to context\n");
  756.     exit(-1);
  757.     }
  758.  
  759.     xmax = width;
  760.     ymax = height;
  761. #ifdef AIXV3
  762.     if (doubleBuffer) {
  763.        glDrawBuffer(GL_BACK);
  764.     } else {
  765.        glDrawBuffer(GL_FRONT);
  766.     }
  767. #else
  768.     glDrawBuffer(GL_BACK);
  769. #endif
  770.     glEnable(GL_DEPTH_TEST);
  771.     glClearIndex(blackIndex);
  772.     glClearDepth(1.0);
  773.  
  774.     glViewport(0, 0, xmax, ymax);
  775.     perspective(fovy, (float)xmax/(float)ymax, 0.00001, farplane);
  776.     quadObj = gluNewQuadric();
  777. }
  778.  
  779. extern char *optarg;
  780. extern int optind, opterr;
  781.  
  782. #define USAGE "usage message: this space for rent\n"
  783. void parse_args(int argc, char **argv)
  784. {
  785.     int c;
  786. #ifdef AIXV3
  787.     int i;
  788. #endif
  789.  
  790. #ifdef AIXV3
  791.     hexflag = sflag = rflag = fflag = wflag = gflag = debug = FALSE;
  792. #else
  793.     hexflag = sflag = fflag = wflag = gflag = debug = FALSE;
  794. #endif
  795.     opterr = 0;
  796.  
  797. #ifndef AIXV3
  798.     while( (c = getopt(argc, argv, "Xhx:s:f:w:g:")) != -1)
  799.     switch(c) {
  800. #else
  801.     for (i = 1; i < argc; i++) {
  802.       if (argv[i][0] == '-')   {
  803.     switch(argv[i][1]) {
  804. #endif
  805.       case 'X':
  806.         debug = TRUE;
  807.         break;
  808.       case 'h':
  809.         print_usage(argv[0]);
  810.         exit(1);    
  811. #ifdef AIXV3
  812.           case 's':
  813.             doubleBuffer = 0;
  814.             break;
  815. #endif
  816.       case 'x':
  817.         hexflag = TRUE;
  818. /*****   hexbright is not used (brightness cannot be changed)    ******
  819.         hexbright = (short)atoi(optarg);
  820.         if(hexbright > (short)255 || hexbright <= (short)0) {
  821.         fprintf(stderr, "Need a brightness value between 0 and ");
  822.         fprintf(stderr, "255 after 'x' option.\n");
  823.         fprintf(stderr, "Try %s -h for help\n", argv[0]);
  824.         exit(1);
  825.         }
  826.  *****   * * * * * * * * * * * * * * * * * * * * * * * * * * *   ******/
  827.         farplane = 300.;
  828.         break;
  829. #ifdef AIXV3
  830.       case 'r':
  831.         rflag = TRUE;
  832.             i++;
  833.             optarg = argv[i];
  834.         speed = atoi(optarg);
  835.         if(speed < 0) {
  836.         fprintf(stderr, "Use a small positive value for rate  ('r').\n");
  837.         fprintf(stderr, "Try %s -h for help\n", argv[0]);
  838.         exit(1);
  839.         }
  840. #else
  841.           case 's':
  842.         sflag = TRUE;
  843.         speed = atoi(optarg);
  844.         if(speed < 0) {
  845.         fprintf(stderr, "Use a small positive value for speed  ('s').\n");
  846.         fprintf(stderr, "Try %s -h for help\n", argv[0]);
  847.         exit(1);
  848.         }
  849. #endif
  850.         break;
  851.       case 'f':
  852.         fflag = TRUE;
  853. #ifdef AIXV3
  854.             i++;
  855.             optarg = argv[i];
  856. #endif
  857.         frame = atoi(optarg);
  858.         if(frame < 0) {
  859.         fprintf(stderr, "Try a small positive value for \n");
  860.         fprintf(stderr, "'f'; this is the number of vertical ");
  861.         fprintf(stderr, "retraces per redraw\n");
  862.         fprintf(stderr, "Try %s -h for help\n", argv[0]);
  863.         exit(1);
  864.         }
  865.         break;
  866.       case 'w':
  867.         wflag = TRUE;
  868. #ifdef AIXV3
  869.             i++;
  870.             optarg = argv[i];
  871. #endif
  872.         da = atof(optarg);
  873.         if(da > 10.) {
  874.         fprintf(stderr, "That's a large rotational velocity ('w')");
  875.         fprintf(stderr, " but you asked for it\n");
  876.         }
  877.         break;
  878.       case 'g':
  879.         gflag = TRUE;
  880. #ifdef AIXV3
  881.             i++;
  882.             optarg = argv[i];
  883. #endif
  884.         gravity = atof(optarg);
  885.         if(gravity <= 0.0) {
  886.         fprintf(stderr, "Gravity ('g') should be positive\n");
  887.         fprintf(stderr, "Try %s -h for help\n", argv[0]);
  888.         }
  889.         break;
  890.       case '?':
  891.         fprintf(stderr, USAGE);
  892.     }
  893.        }
  894.       }
  895.  
  896.     /* set up default values */
  897. #ifdef AIXV3
  898.     if(!rflag)
  899. #else
  900.     if(!sflag)
  901. #endif
  902.     speed = 3;
  903.     if(!fflag)
  904.     frame = 2;    
  905.     if(!wflag)
  906.     da = 0.;
  907.     if(!gflag)
  908.     gravity = G;
  909. }
  910.  
  911.  
  912.     /* while( (c = getopt(argc, argv, "Xhx:s:f:w:g:")) != -1) */
  913. void print_usage(char *program)
  914. {
  915. #ifdef AIXV3
  916. /* printf("\nUsage: %s [-h] [-x b] [-r rate] [-s single buffer]", program); */
  917. printf("\nUsage: %s [-h] [-x] [-r rate] [-s]", program);
  918. #else
  919. /* printf("\nUsage: %s [-h] [-x b] [-s speed] [-s single buffer]", program); */
  920. printf("\nUsage: %s [-h] [-x] [-s speed]", program);
  921. #endif
  922. printf(" [-f framenoise] [-w rot_v] [-g gravity]\n\n");
  923. printf("-h              Print this message.\n");
  924. /*****     Currently b is not being used to control brightness.   *****
  925. printf("-x b            Enclose the particles in a box made of hexagons,\n");
  926. printf("                whose brightness is b.\n");
  927.  *****                                                            *****/
  928. printf("-x              Enclose the particles in a box made of hexagons.\n");
  929. #ifdef AIXV3
  930. printf("-r rate         Sets the number of new line segments per redraw \n");
  931. printf("                interval per line. Default value: 3.\n");
  932. printf("-s single buffer Single buffer mode.\n");
  933. #else
  934. printf("-s speed        Sets the number of new line segments per redraw \n");
  935. printf("                interval per line. Default value: 3.\n");
  936. #endif
  937.  
  938. /*** The X port does not currently include a timer, so this feature is disabled.
  939. printf("-f framenoise   Sets the number of vertical retraces per redraw\n");
  940. printf("                interval. Example: -f 2 specifies one redraw per\n");
  941. printf("                2 vertical retraces, or 30 frames per second.\n");
  942. printf("                Default value: 2.\n");
  943. ************/
  944.  
  945. printf("-w rot_v        Spins the hexagons on their centers, and the sides\n");
  946. printf("                of the box on their centers. Hexagons spin at the\n");
  947. printf("                rate rot_v degrees per redraw, and box sides spin\n");
  948. printf("                at -rot_v/2 degrees per redraw.\n");
  949. printf("-g gravity      Sets the strength of the attraction of the eye to\n");
  950. printf("                the red particle. Actually, it's not gravity since\n");
  951. printf("                the attraction is proportionate to distance.\n");
  952. printf("                Default value: 0.002. Try large values!\n");
  953. /* input added for GLX port */
  954. printf(" Executions control:  \n");
  955. printf("    <spacebar>    step through single frames\n");
  956. printf("    g        begin continuous frames\n");
  957. printf("    s        stop continuous frames\n");
  958. printf("\nBugs: hidden surface removal doesn't apply to hexagons, and\n");
  959. printf("works poorly on lines when they are too close together.\n");
  960.  
  961. }
  962.