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