http://packetstorm.tacticalflex.com/UNIX/admin/xscreensaver-3.27.tar.gz
[xscreensaver] / hacks / glx / gflux.c
1 /* -*- Mode: C; tab-width: 4 -*- emacs friendly */
2
3 /* gflux - creates a fluctuating 3D grid 
4  * requires OpenGL or MesaGL
5  * 
6  * Copyright (c) Josiah Pease, 2000
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation.  No representations are made about the suitability of this
12  * software for any purpose.  It is provided "as is" without express or 
13  * implied warranty.
14  *
15  * Thanks go to all those who worked on...
16  * MesaGL, OpenGL, UtahGLX, XFree86, gcc, vim, rxvt, the PNM (anymap) format
17  * xscreensaver and the thousands of other tools, apps and daemons that make
18  * linux usable  
19  * Personal thanks to Kevin Moss, Paul Sheahee and Jamie Zawinski
20  * 
21  * some xscreensaver code lifted from superquadrics.  Most other glx hacks 
22  * used as reference at some time.
23  *
24  * This hack and others can cause UtahGLX to crash my X server
25  * wireframe looks good with software only rendering anyway
26  * If anyone can work out why and supply a fix I'd love to hear from them
27  * 
28  * Josiah Pease <gfluxcode@jpease.force9.co.uk> 21 July 2000
29  * 
30  * History 
31  * 10 June 2000 : wireframe rippling grid standalone written
32  * 18 June 2000 : xscreensaver code added
33  * 25 June 2000 : solid and light added
34  * 04 July 2000 : majour bug hunt, xscreensaver code rewritten
35  * 08 July 2000 : texture mapping, rotation and zoom added
36  * 21 July 2000 : cleaned up code from bug hunts, manpage written
37  */
38
39
40 /*-
41  * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
42  * otherwise caddr_t is not defined correctly
43  */
44
45 #include <X11/Intrinsic.h>
46
47
48 #ifdef STANDALONE
49 # define PROGCLASS                                              "gflux"
50 # define HACK_INIT                                              init_gflux
51 # define HACK_DRAW                                              draw_gflux
52 # define gflux_opts                             xlockmore_opts
53 #define DEFAULTS                        "*squares:      19      \n" \
54                                         "*resolution:   0       \n" \
55                                         "*draw:         0       \n" \
56                                         "*flat:         0       \n" \
57                                         "*speed:        0.05    \n" \
58                                         "*rotationx:    0.01    \n" \
59                                         "*rotationy:    0.0     \n" \
60                                         "*rotationz:    0.1     \n" \
61                                         "*waves:        3       \n" \
62                                         "*waveChange:   50      \n" \
63                                         "*waveHeight:   1.0     \n" \
64                                         "*waveFreq:    3.0     \n" \
65                                         "*zoom:         1.0     \n" 
66
67
68 # include "xlockmore.h"                         /* from the xscreensaver distribution */
69 #else /* !STANDALONE */
70 # include "xlock.h"                                     /* from the xlockmore distribution */
71 #endif /* !STANDALONE */
72
73 #ifdef USE_GL /* whole file */
74
75 #ifdef HAVE_XPM
76 # include <X11/xpm.h>
77 # ifndef PIXEL_ALREADY_TYPEDEFED
78 # define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
79 # endif
80 #endif
81
82 #ifdef HAVE_XMU
83 # ifndef VMS
84 #  include <X11/Xmu/Drawing.h>
85 #else  /* VMS */
86 #  include <Xmu/Drawing.h>
87 # endif /* VMS */
88 #endif
89
90 #undef countof
91 #define countof(x) (sizeof((x))/sizeof((*x)))
92
93 #include <stdlib.h>
94 #include <stdio.h>
95
96 #include <GL/gl.h>
97 #include <GL/glu.h>
98 #include <GL/glx.h>
99
100 #include <math.h>
101
102 static enum {wire=0,solid,light,checker,textured} _draw; /* draw style */
103 static int _squares = 19;                                 /* grid size */
104 static int _resolution = 4;                    /* wireframe resolution */
105 static int _flat = 0;
106
107 static float _speed = 0.05;
108 static float _rotationx = 0.01;
109 static float _rotationy = 0.0;
110 static float _rotationz = 0.1;
111 static float _zoom = 1.0;
112
113 static int _waves = 3;
114 static int _waveChange = 50;
115 static float _waveHeight = 1.0;
116 static float _waveFreq = 3.0;
117
118 #define WIDTH 320
119 #define HEIGHT 240
120
121 static XrmOptionDescRec opts[] = {
122     {"-squares", ".gflux.squares", XrmoptionSepArg, (caddr_t) NULL},
123     {"-resolution", ".gflux.resolution", XrmoptionSepArg, (caddr_t) NULL},
124     {"-draw", ".gflux.draw", XrmoptionSepArg, (caddr_t) NULL},
125     {"-flat", ".gflux.flat", XrmoptionSepArg, (caddr_t) NULL},
126     {"-speed", ".gflux.speed", XrmoptionSepArg, (caddr_t) NULL},
127     {"-rotationx", ".gflux.rotationx", XrmoptionSepArg, (caddr_t) NULL},
128     {"-rotationy", ".gflux.rotationy", XrmoptionSepArg, (caddr_t) NULL},
129     {"-rotationz", ".gflux.rotationz", XrmoptionSepArg, (caddr_t) NULL},
130     {"-waves", ".gflux.waves", XrmoptionSepArg, (caddr_t) NULL},
131     {"-waveChange", ".gflux.waveChange", XrmoptionSepArg, (caddr_t) NULL},
132     {"-waveHeight", ".gflux.waveHeight", XrmoptionSepArg, (caddr_t) NULL},
133     {"-waveFreq", ".gflux.waveFreq", XrmoptionSepArg, (caddr_t) NULL},
134     {"-zoom", ".gflux.zoom", XrmoptionSepArg, (caddr_t) NULL},
135 };
136
137
138 static argtype vars[] = {
139     {(caddr_t *) & _squares, "squares", "Squares", "19", t_Int},
140     {(caddr_t *) & _resolution, "resolution", "Resolution", "4", t_Int},
141     {(caddr_t *) & _draw, "draw", "Draw", "0", t_Int},
142     {(caddr_t *) & _flat, "flat", "Flat", "0", t_Int},
143     {(caddr_t *) & _speed, "speed", "Speed", "0.05", t_Float},
144     {(caddr_t *) & _rotationx, "rotationx", "Rotationx", "0.01", t_Float},
145     {(caddr_t *) & _rotationy, "rotationy", "Rotationy", "0.0", t_Float},
146     {(caddr_t *) & _rotationz, "rotationz", "Rotationz", "0.1", t_Float},
147     {(caddr_t *) & _waves, "waves", "Waves", "3", t_Int},
148     {(caddr_t *) & _waveChange, "waveChange", "WaveChange", "50", t_Int},
149     {(caddr_t *) & _waveHeight, "waveHeight", "WaveHeight", "1.0", t_Float},
150     {(caddr_t *) & _waveFreq, "waveFreq", "WaveFreq", "3.0", t_Float},
151     {(caddr_t *) & _zoom, "zoom", "Zoom", "1.0", t_Float},
152 };
153
154
155 static OptionStruct desc[] =
156 {
157     {"-squares num", "size of grid in squares (19)"},
158     {"-resolution num", "detail of lines making grid, wireframe only (4)"},
159     {"-draw num", "draw method to use: 0=wireframe 1=solid 2=lit (0)"},
160     {"-flat num", "shading method, not wireframe: 0=smooth 1=flat (0)"},
161     {"-speed num", "speed of waves (0.05)"},
162     {"-rotationx num", "speed of xrotation (0.01)"},
163     {"-rotationy num", "speed of yrotation (0.00)"},
164     {"-rotationz num", "speed of zrotation (0.10)"},
165     {"-waves num", "number of simultanious waves (3)"},
166     {"-waveChange num", "number of cyles for a wave to change (50)"},
167     {"-waveHeight num", "height of waves (1.0)"},
168     {"-waveFreq num", "max frequency of a wave (3.0)"},
169     {"-zoom num", "camera control (1.0)"},
170 };
171
172 ModeSpecOpt gflux_opts = {countof(opts), opts, countof(vars), vars, desc};
173
174 #ifdef USE_MODULES
175 ModStruct   gflux_description =
176 {"gflux", "init_gflux", "draw_gflux", "release_gflux",
177  "draw_gflux", "init_gflux", NULL, &gflux_opts,
178  1000, 1, 2, 1, 4, 1.0, "",
179  "Gflux: an OpenGL gflux", 0, NULL};
180 #endif
181
182 /* structure for holding the gflux data */
183 typedef struct {
184     int screen_width, screen_height;
185     GLXContext *glx_context;
186     Window window;
187     XColor fg, bg;
188 #define MAXWAVES 10   /* should be dynamic    */
189     double wa[MAXWAVES];
190     double freq[MAXWAVES];
191     double dispy[MAXWAVES];
192     double dispx[MAXWAVES];
193     GLfloat colour[3];
194     int imageWidth;
195     int imageHeight;
196     GLubyte *image;
197     GLint texName;
198     void (*drawFunc)(void);
199 } gfluxstruct;
200 static gfluxstruct *gflux = NULL;
201
202 /* prototypes */
203 void initLighting(void);
204 void initTexture(void);
205 void loadTexture(void);
206 void createTexture(void);
207 void displaySolid(void);            /* drawFunc implementations */
208 void displayLight(void);
209 void displayTexture(void);
210 void displayWire(void);
211 void calcGrid(void);
212 double getGrid(double,double,double);
213
214 /* as macro for speed */
215 /* could do with colour cycling here */
216 /* void genColour(double);*/
217 #define genColour(X) \
218 {\
219     gflux->colour[0] = 0.0;\
220     gflux->colour[1] = 0.5+0.5*(X);\
221     gflux->colour[2] = 0.5-0.5*(X);\
222 }
223
224 /* BEGINNING OF FUNCTIONS */
225
226
227 /* draw the gflux once */
228 void draw_gflux(ModeInfo * mi)
229 {
230     gfluxstruct *gp = &gflux[MI_SCREEN(mi)];
231     Display    *display = MI_DISPLAY(mi);
232     Window      window = MI_WINDOW(mi);
233
234     if (!gp->glx_context) return;
235
236     glXMakeCurrent(display, window, *(gp->glx_context));
237
238     calcGrid();
239     gflux->drawFunc();
240     glXSwapBuffers(display, window);
241 }
242
243
244 /* reset the projection matrix */
245 void resetProjection(void) {
246     glMatrixMode(GL_PROJECTION);
247     glLoadIdentity();
248     glFrustum(-_zoom,_zoom,-0.8*_zoom,0.8*_zoom,2,6);
249     glTranslatef(0.0,0.0,-4.0);
250     glMatrixMode(GL_MODELVIEW);
251     glLoadIdentity();
252 }
253
254 /* Standard reshape function */
255 static void
256 reshape(int width, int height)
257 {
258     glViewport( 0, 0, width, height );
259     resetProjection();
260 }
261
262
263 /* main OpenGL initialization routine */
264 void initializeGL(GLsizei width, GLsizei height) 
265 {
266   reshape(width, height);
267   glViewport( 0, 0, width, height ); 
268   switch(_draw) {
269     case solid :
270       gflux->drawFunc = (displaySolid);
271       glEnable(GL_DEPTH_TEST);
272     break;
273     case light :
274       gflux->drawFunc = (displayLight);
275       glEnable(GL_DEPTH_TEST);
276       initLighting();
277         break;
278         case checker :
279       gflux->drawFunc = (displayTexture);
280       glEnable(GL_DEPTH_TEST);
281       createTexture();
282       initTexture();
283       initLighting();
284     break;
285         case textured :
286       gflux->drawFunc = (displayTexture);
287       glEnable(GL_DEPTH_TEST);
288       loadTexture();
289       initTexture();
290       initLighting();
291     break;
292     case wire :
293         default :
294       gflux->drawFunc = (displayWire);
295       glDisable(GL_DEPTH_TEST);
296     break;
297   }
298
299   if(_flat) glShadeModel(GL_FLAT);
300   else glShadeModel(GL_SMOOTH);
301
302 }
303
304
305 /* xgflux initialization routine */
306 void init_gflux(ModeInfo * mi)
307 {
308     int screen = MI_SCREEN(mi);
309     gfluxstruct *gp;
310
311     if (gflux == NULL) {
312         if ((gflux = (gfluxstruct *) 
313                  calloc(MI_NUM_SCREENS(mi), sizeof (gfluxstruct))) == NULL)
314             return;
315     }
316     gp = &gflux[screen];
317
318     gp->window = MI_WINDOW(mi);
319     if ((gp->glx_context = init_GL(mi)) != NULL) {
320         reshape(MI_WIDTH(mi), MI_HEIGHT(mi));
321         initializeGL(MI_WIDTH(mi), MI_HEIGHT(mi));
322     } else {
323         MI_CLEARWINDOW(mi);
324     }
325 }
326
327 /* cleanup code */
328 void release_gflux(ModeInfo * mi)
329 {
330     if(gflux->image!=NULL) free(gflux->image);
331     if(gflux->glx_context!=NULL) free(gflux->glx_context);
332     if (gflux != NULL) {
333         (void) free((void *) gflux);
334         gflux = NULL;
335     }
336     FreeAllGL(mi);
337 }
338
339 /* loads several different types of PNM image from stdin */
340 #define presult(A,B,C) (*(result+(A)*(gflux->imageWidth)*4+(B)*4+(C)))
341 void loadTexture(void)
342 {
343     int i, j, levels, width, height;
344     int red,green,blue;
345     char s[4];
346     int ppmType=0;
347     FILE *file = stdin;
348     GLubyte *result;
349
350     fgets(s,4,file);
351
352     if(!strncmp(s,"P6",2)) ppmType=6;
353     if(!strncmp(s,"P5",2)) ppmType=5;
354     if(!strncmp(s,"P3",2)) ppmType=3;
355     if(!strncmp(s,"P2",2)) ppmType=2;
356     if(!ppmType)exit(1);
357
358     while((i=getc(file))=='#')
359     {
360         while(getc(file)!='\n');
361     }
362     ungetc(i,file);
363
364     fscanf(file,"%d %d %d",&width,&height,&levels);
365
366     result = malloc(sizeof(GLubyte)*4*width*height);
367     gflux->imageWidth = width;
368         gflux->imageHeight = height;
369
370     switch(ppmType) {
371         case 2 :    /* ASCII grey */
372             for(i=0;i<height;i++) {
373                 for(j=0;j<width;j++) {
374                     fscanf(file,"%d",&red);
375                     presult(j,i,0) = red;
376                     presult(j,i,1) = red;
377                     presult(j,i,2) = red;
378                 }
379             }
380             break;
381         case 3 :    /* ASCII rgb */
382             for(i=0;i<height;i++) {
383                 for(j=0;j<width;j++) {
384                     fscanf(file,"%d %d %d",&red,&green,&blue);
385                     presult(j,i,0) = red;
386                     presult(j,i,1) = green;
387                     presult(j,i,2) = blue;
388                 }
389             }
390             break;
391         case 5 :    /* Binary grey */
392             getc(file); /* seems nessessary */
393             for(i=0;i<height;i++) {
394                 for(j=0;j<width;j++) {
395                     red = getc(file);
396                     presult(j,i,0) = red;
397                     presult(j,i,1) = red;
398                     presult(j,i,2) = red;
399                 }
400             }
401         break;
402         case 6 :    /* Binary rgb */
403             getc(file); /* seems nessessary */
404             for(i=0;i<height;i++) {
405                 for(j=0;j<width;j++) {
406                     red = getc(file);
407                     green = getc(file);
408                     blue = getc(file);
409                     presult(j,i,0) = red;
410                     presult(j,i,1) = green;
411                     presult(j,i,2) = blue;
412                 }
413             }
414         break;
415     }
416         gflux->image = result;
417 }
418
419 /* creates an image for texture mapping */
420 void createTexture(void)
421 {
422     int i,j,c;
423     GLubyte *result;
424
425         gflux->imageHeight = gflux->imageWidth = 8;
426
427         result = malloc(sizeof(GLubyte)*4*gflux->imageHeight*gflux->imageWidth);
428     for(i=0;i<gflux->imageHeight;i++) {
429         for(j=0;j<gflux->imageWidth;j++) {
430             c = (((i)%2 ^ (j)%2) ? 100 : 200 );
431             presult(i,j,0) = (GLubyte) c;
432             presult(i,j,1) = (GLubyte) c;
433             presult(i,j,2) = (GLubyte) c;
434             presult(i,j,3) = (GLubyte) 255;
435         }
436     }
437         gflux->image = result;
438 }
439 #undef presult
440
441 /* specifies image as texture */    
442 void initTexture(void)
443 {
444         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
445         glGenTextures(1, &gflux->texName);
446         glBindTexture(GL_TEXTURE_2D, gflux->texName);
447         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
448         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
449         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
450         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
451     clear_gl_error();
452         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gflux->imageWidth,
453                         gflux->imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, gflux->image);
454     check_gl_error("texture");
455 }
456
457 void initLighting(void)
458 {
459     static float ambientA[] = {0.0, 0.0, 0.0, 1.0};
460     static float diffuseA[] = {1.0, 1.0, 1.0, 1.0};
461     static float positionA[] = {5.0, 5.0, 15.0, 1.0};
462
463     static float front_mat_shininess[] = {30.0};
464     static float front_mat_specular[] = {0.5, 0.5, 0.5, 1.0};
465
466     static float mat_diffuse[] = {0.5, 0.5, 0.5, 1.0};
467
468     glMaterialfv(GL_FRONT, GL_SHININESS, front_mat_shininess);
469     glMaterialfv(GL_FRONT, GL_SPECULAR, front_mat_specular);
470
471     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
472
473     glLightfv(GL_LIGHT0, GL_AMBIENT, ambientA);
474     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseA);
475     glLightfv(GL_LIGHT0, GL_POSITION, positionA);
476     glEnable(GL_LIGHTING);
477     glEnable(GL_LIGHT0);
478     glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1);
479
480     glEnable(GL_NORMALIZE);         /* would it be faster ...   */
481     glEnable(GL_COLOR_MATERIAL);
482     glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
483 }
484
485 /************************************/
486 /* draw implementations             */
487 /* somewhat inefficient since they  */
488 /* all calculate previously         */
489 /* calculated values again          */
490 /* storing the values in an array   */
491 /* is a posibility                  */
492 /************************************/
493 void displayTexture(void)
494 {
495     static double time = 0.0;
496     static double anglex = 0.0;
497     static double angley = 0.0;
498     static double anglez = 0.0;
499
500     double x,y,u,v;
501     double z;
502     double dx = 2.0/((double)_squares);
503     double dy = 2.0/((double)_squares);
504
505         glMatrixMode (GL_TEXTURE);
506         glLoadIdentity ();
507         glTranslatef(-1,-1,0);
508         glScalef(0.5,0.5,1);
509         glMatrixMode (GL_MODELVIEW);
510
511     glLoadIdentity();
512     glRotatef(anglex,1,0,0);
513     glRotatef(angley,0,1,0);
514     glRotatef(anglez,0,0,1);
515     glScalef(1,1,(GLfloat)_waveHeight);
516     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
517         glEnable(GL_TEXTURE_2D);
518         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
519         glBindTexture(GL_TEXTURE_2D, gflux->texName);
520         glColor3f(0.5,0.5,0.5);
521
522     for(x=-1,u=0;x<=1;x+=dx,u+=dx) {
523         glBegin(GL_QUAD_STRIP);
524         for(y=-1,v=0;y<=1;y+=dy,v+=dx) {
525             z = getGrid(x,y,time);
526         /*  genColour(z);
527             glColor3fv(gflux->colour);
528         */  glTexCoord2f(u,v);
529             glNormal3f(
530                 getGrid(x+dx,y,time)-getGrid(x-dx,y,time),
531                 getGrid(x,y+dy,time)-getGrid(x,y-dy,time),
532                 1
533             );
534             glVertex3f(x,y,z);
535
536             z = getGrid(x+dx,y,time);
537         /*  genColour(z);
538             glColor3fv(gflux->colour);
539         */  glTexCoord2f(u+dx,v);
540             glNormal3f(
541                 getGrid(x+dx+dx,y,time)-getGrid(x,y,time),
542                 getGrid(x+dx,y+dy,time)-getGrid(x+dx,y-dy,time),
543                 1
544             );
545             glVertex3f(x+dx,y,z);
546         }
547         glEnd();
548     }
549
550     time -= _speed;
551     anglex -= _rotationx;
552     angley -= _rotationy;
553     anglez -= _rotationz;
554 }
555 void displaySolid(void)
556 {
557     static double time = 0.0;
558     static double anglex = 0.0;
559     static double angley = 0.0;
560     static double anglez = 0.0;
561
562     double x,y;
563     double z;
564     double dx = 2.0/((double)_squares);
565     double dy = 2.0/((double)_squares);
566
567     glLoadIdentity();
568     glRotatef(anglex,1,0,0);
569     glRotatef(angley,0,1,0);
570     glRotatef(anglez,0,0,1);
571     glScalef(1,1,(GLfloat)_waveHeight);
572     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
573
574     for(x=-1;x<=1;x+=dx) {
575         glBegin(GL_QUAD_STRIP);
576         for(y=-1;y<=1;y+=dy) {
577             z = getGrid(x,y,time);
578             genColour(z);
579             glColor3fv(gflux->colour);
580             glVertex3f(x,y,z);
581
582             z = getGrid(x+dx,y,time);
583             genColour(z);
584             glColor3fv(gflux->colour);
585             glVertex3f(x+dx,y,z);
586         }
587         glEnd();
588     }
589
590     time -= _speed;
591     anglex -= _rotationx;
592     angley -= _rotationy;
593     anglez -= _rotationz;
594
595 }
596
597 void displayLight(void)
598 {
599     static double time = 0.0;
600     static double anglex = 0.0;
601     static double angley = 0.0;
602     static double anglez = 0.0;
603
604     double x,y;
605     double z;
606     double dx = 2.0/((double)_squares);
607     double dy = 2.0/((double)_squares);
608
609     glLoadIdentity();
610     glRotatef(anglex,1,0,0);
611     glRotatef(angley,0,1,0);
612     glRotatef(anglez,0,0,1);
613     glScalef(1,1,(GLfloat)_waveHeight);
614     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
615
616     for(x=-1;x<=1;x+=dx) {
617         glBegin(GL_QUAD_STRIP);
618         for(y=-1;y<=1;y+=dy) {
619             z = getGrid(x,y,time);
620             genColour(z);
621             glColor3fv(gflux->colour);
622             glNormal3f(
623                 getGrid(x+dx,y,time)-getGrid(x-dx,y,time),
624                 getGrid(x,y+dy,time)-getGrid(x,y-dy,time),
625                 1
626             );
627             glVertex3f(x,y,z);
628
629             z = getGrid(x+dx,y,time);
630             genColour(z);
631             glColor3fv(gflux->colour);
632             glNormal3f(
633                 getGrid(x+dx+dx,y,time)-getGrid(x,y,time),
634                 getGrid(x+dx,y+dy,time)-getGrid(x+dx,y-dy,time),
635                 1
636             );
637             glVertex3f(x+dx,y,z);
638         }
639         glEnd();
640     }
641
642     time -= _speed;
643     anglex -= _rotationx;
644     angley -= _rotationy;
645     anglez -= _rotationz;
646 }
647
648 void displayWire(void)
649 {
650     static double time = 0.0;
651     static double anglex = 0.0;
652     static double angley = 0.0;
653     static double anglez = 0.0;
654
655     double x,y;
656     double z;
657     double dx1 = 2.0/((double)(_squares*_resolution)) - 0.00001;
658     double dy1 = 2.0/((double)(_squares*_resolution)) - 0.00001;
659     double dx2 = 2.0/((double)_squares) - 0.00001;
660     double dy2 = 2.0/((double)_squares) - 0.00001;
661
662     glLoadIdentity();
663     glRotatef(anglex,1,0,0);
664     glRotatef(angley,0,1,0);
665     glRotatef(anglez,0,0,1);
666     glScalef(1,1,(GLfloat)_waveHeight);
667     glClear(GL_COLOR_BUFFER_BIT);
668
669     for(x=-1;x<=1;x+=dx2) {
670         glBegin(GL_LINE_STRIP);
671         for(y=-1;y<=1;y+=dy1) {
672             z = getGrid(x,y,time);
673             genColour(z);
674             glColor3fv(gflux->colour);
675             glVertex3f(x,y,z);
676         }
677         glEnd();
678     }
679     for(y=-1;y<=1;y+=dy2) {
680         glBegin(GL_LINE_STRIP);
681         for(x=-1;x<=1;x+=dx1) {
682             z = getGrid(x,y,time);
683             genColour(z);
684             glColor3fv(gflux->colour);
685             glVertex3f(x,y,z);
686         }
687         glEnd();
688     }
689
690     time -= _speed;
691     anglex -= _rotationx;
692     angley -= _rotationy;
693     anglez -= _rotationz;
694 }
695
696 /* generates new ripples */
697 void calcGrid(void)
698 {
699     static int counter=0;
700     double tmp;
701     static int newWave;
702
703     tmp = 1.0/((double)_waveChange);
704     if(!(counter%_waveChange)) {
705         newWave = ((int)(counter*tmp))%_waves;
706         gflux->dispx[newWave] = 1.0 - ((double)random())/RAND_MAX;
707         gflux->dispy[newWave] = 1.0 - ((double)random())/RAND_MAX;
708         gflux->freq[newWave] = _waveFreq * ((float)random())/RAND_MAX;
709         gflux->wa[newWave] = 0.0;
710     }
711     counter++;
712     gflux->wa[newWave] += tmp;
713     gflux->wa[(newWave+1)%_waves] -= tmp;
714 }
715
716 /* returns a height for the grid given time and x,y space co-ords */
717 double getGrid(double x, double y, double a)
718 {
719     register int i;
720     double retval=0.0;
721     double tmp;
722
723     tmp = 1.0/((float)_waves);
724     for(i=0;i<_waves;i++) {
725       retval += gflux->wa[i] * tmp * sin( gflux->freq[i]
726               * ( (x+gflux->dispx[i]) * (x+gflux->dispx[i]) 
727                 + (y+gflux->dispy[i]) * (y+gflux->dispy[i]) +a ) );
728     }
729     return(retval);
730 }
731
732 #endif
733