1 /* -*- Mode: C; tab-width: 4 -*- emacs friendly */
2 /* gflux - creates a fluctuating 3D grid
3 * requires OpenGL or MesaGL
5 * Copyright (c) Josiah Pease, 2000, 2003
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
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
18 * Personal thanks to Kevin Moss, Paul Sheahee and Jamie Zawinski
20 * some xscreensaver code lifted from superquadrics. Most other glx hacks
21 * used as reference at some time.
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
27 * Josiah Pease <gfluxcode@jpease.force9.co.uk> 21 July 2000
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 * 11 May 2002 : fixed image problems with large images
43 #define DEFAULTS "*delay: 20000\n" \
49 # define refresh_gflux 0
50 # include "xlockmore.h" /* from the xscreensaver distribution */
51 #else /* !STANDALONE */
52 # include "xlock.h" /* from the xlockmore distribution */
53 #endif /* !STANDALONE */
55 #ifdef USE_GL /* whole file */
59 # include <X11/Xmu/Drawing.h>
61 # include <Xmu/Drawing.h>
66 #define countof(x) (sizeof((x))/sizeof((*x)))
73 #include "grab-ximage.h"
74 #include "gltrackball.h"
77 static enum {wire=0,solid,light,checker,grab} _draw;
79 # define DEF_SQUARES "19"
80 # define DEF_RESOLUTION "4"
83 # define DEF_SPEED "0.05"
84 # define DEF_ROTATIONX "0.01"
85 # define DEF_ROTATIONY "0.0"
86 # define DEF_ROTATIONZ "0.1"
87 # define DEF_WAVES "3"
88 # define DEF_WAVE_CHANGE "50"
89 # define DEF_WAVE_HEIGHT "1.0"
90 # define DEF_WAVE_FREQ "3.0"
91 # define DEF_ZOOM "1.0"
95 static int _squares; /* grid size */
96 static int _resolution; /* wireframe resolution */
100 static float _rotationx;
101 static float _rotationy;
102 static float _rotationz;
106 static int _waveChange;
107 static float _waveHeight;
108 static float _waveFreq;
114 static XrmOptionDescRec opts[] = {
115 {"-squares", ".gflux.squares", XrmoptionSepArg, 0},
116 {"-resolution", ".gflux.resolution", XrmoptionSepArg, 0},
117 /* {"-draw", ".gflux.draw", XrmoptionSepArg, 0},*/
118 {"-mode", ".gflux.mode", XrmoptionSepArg, 0},
119 {"-wireframe", ".gflux.mode", XrmoptionNoArg, "wire"},
120 {"-flat", ".gflux.flat", XrmoptionSepArg, 0},
121 {"-speed", ".gflux.speed", XrmoptionSepArg, 0},
122 {"-rotationx", ".gflux.rotationx", XrmoptionSepArg, 0},
123 {"-rotationy", ".gflux.rotationy", XrmoptionSepArg, 0},
124 {"-rotationz", ".gflux.rotationz", XrmoptionSepArg, 0},
125 {"-waves", ".gflux.waves", XrmoptionSepArg, 0},
126 {"-waveChange", ".gflux.waveChange", XrmoptionSepArg, 0},
127 {"-waveHeight", ".gflux.waveHeight", XrmoptionSepArg, 0},
128 {"-waveFreq", ".gflux.waveFreq", XrmoptionSepArg, 0},
129 {"-zoom", ".gflux.zoom", XrmoptionSepArg, 0},
133 static argtype vars[] = {
134 {&_squares, "squares", "Squares", DEF_SQUARES, t_Int},
135 {&_resolution, "resolution", "Resolution", DEF_RESOLUTION, t_Int},
136 /* {&_draw, "draw", "Draw", DEF_DRAW, t_Int},*/
137 {&_flat, "flat", "Flat", DEF_FLAT, t_Int},
138 {&_speed, "speed", "Speed", DEF_SPEED, t_Float},
139 {&_rotationx, "rotationx", "Rotationx", DEF_ROTATIONX, t_Float},
140 {&_rotationy, "rotationy", "Rotationy", DEF_ROTATIONY, t_Float},
141 {&_rotationz, "rotationz", "Rotationz", DEF_ROTATIONZ, t_Float},
142 {&_waves, "waves", "Waves", DEF_WAVES, t_Int},
143 {&_waveChange, "waveChange", "WaveChange", DEF_WAVE_CHANGE, t_Int},
144 {&_waveHeight, "waveHeight", "WaveHeight", DEF_WAVE_HEIGHT, t_Float},
145 {&_waveFreq, "waveFreq", "WaveFreq", DEF_WAVE_FREQ, t_Float},
146 {&_zoom, "zoom", "Zoom", DEF_ZOOM, t_Float},
150 static OptionStruct desc[] =
152 {"-squares num", "size of grid in squares (19)"},
153 {"-resolution num", "detail of lines making grid, wireframe only (4)"},
154 /* {"-draw num", "draw method to use: 0=wireframe 1=solid 2=lit (0)"},*/
155 {"-flat num", "shading method, not wireframe: 0=smooth 1=flat (0)"},
156 {"-speed num", "speed of waves (0.05)"},
157 {"-rotationx num", "speed of xrotation (0.01)"},
158 {"-rotationy num", "speed of yrotation (0.00)"},
159 {"-rotationz num", "speed of zrotation (0.10)"},
160 {"-waves num", "number of simultanious waves (3)"},
161 {"-waveChange num", "number of cyles for a wave to change (50)"},
162 {"-waveHeight num", "height of waves (1.0)"},
163 {"-waveFreq num", "max frequency of a wave (3.0)"},
164 {"-zoom num", "camera control (1.0)"},
167 ENTRYPOINT ModeSpecOpt gflux_opts = {countof(opts), opts, countof(vars), vars, desc};
170 ModStruct gflux_description =
171 {"gflux", "init_gflux", "draw_gflux", "release_gflux",
172 "draw_gflux", "init_gflux", NULL, &gflux_opts,
173 1000, 1, 2, 1, 4, 1.0, "",
174 "GFlux: an OpenGL gflux", 0, NULL};
177 /* structure for holding the gflux data */
178 typedef struct gfluxstruct {
180 int screen_width, screen_height;
181 GLXContext *glx_context;
184 #define MAXWAVES 10 /* should be dynamic */
186 double freq[MAXWAVES];
187 double dispy[MAXWAVES];
188 double dispx[MAXWAVES];
194 int img_width, img_height;
195 int (*drawFunc)(struct gfluxstruct *);
197 trackball_state *trackball;
209 Bool waiting_for_image_p;
212 static gfluxstruct *gfluxes = NULL;
215 static void initLighting(void);
216 static void grabTexture(gfluxstruct *);
217 static void createTexture(gfluxstruct *);
218 static int displaySolid(gfluxstruct *); /* drawFunc implementations */
219 static int displayLight(gfluxstruct *);
220 static int displayTexture(gfluxstruct *);
221 static int displayWire(gfluxstruct *);
222 static void calcGrid(gfluxstruct *);
223 static double getGrid(gfluxstruct *,double,double,double);
225 /* as macro for speed */
226 /* could do with colour cycling here */
227 /* void genColour(double);*/
228 #define genColour(X) \
230 gp->colour[0] = 0.0;\
231 gp->colour[1] = 0.5+0.5*(X);\
232 gp->colour[2] = 0.5-0.5*(X);\
235 /* BEGINNING OF FUNCTIONS */
239 gflux_handle_event (ModeInfo *mi, XEvent *event)
241 gfluxstruct *gp = &gfluxes[MI_SCREEN(mi)];
243 if (event->xany.type == ButtonPress &&
244 event->xbutton.button == Button1)
246 gp->button_down_p = True;
247 gltrackball_start (gp->trackball,
248 event->xbutton.x, event->xbutton.y,
249 MI_WIDTH (mi), MI_HEIGHT (mi));
252 else if (event->xany.type == ButtonRelease &&
253 event->xbutton.button == Button1)
255 gp->button_down_p = False;
258 else if (event->xany.type == ButtonPress &&
259 (event->xbutton.button == Button4 ||
260 event->xbutton.button == Button5 ||
261 event->xbutton.button == Button6 ||
262 event->xbutton.button == Button7))
264 gltrackball_mousewheel (gp->trackball, event->xbutton.button, 10,
265 !!event->xbutton.state);
268 else if (event->xany.type == MotionNotify &&
271 gltrackball_track (gp->trackball,
272 event->xmotion.x, event->xmotion.y,
273 MI_WIDTH (mi), MI_HEIGHT (mi));
282 userRot(gfluxstruct *gp)
284 /* Do it twice because we don't track the device's orientation. */
285 glRotatef( current_device_rotation(), 0, 0, 1);
286 gltrackball_rotate (gp->trackball);
287 glRotatef(-current_device_rotation(), 0, 0, 1);
290 /* draw the gflux once */
291 ENTRYPOINT void draw_gflux(ModeInfo * mi)
293 gfluxstruct *gp = &gfluxes[MI_SCREEN(mi)];
294 Display *display = MI_DISPLAY(mi);
295 Window window = MI_WINDOW(mi);
297 if (!gp->glx_context) return;
299 /* Just keep running before the texture has come in. */
300 /* if (gp->waiting_for_image_p) return; */
302 glXMakeCurrent(display, window, *(gp->glx_context));
305 mi->polygon_count = gp->drawFunc(gp);
306 if (mi->fps_p) do_fps (mi);
307 glXSwapBuffers(display, window);
311 /* reset the projection matrix */
312 static void resetProjection(void)
314 glMatrixMode(GL_PROJECTION);
316 glFrustum(-_zoom,_zoom,-0.8*_zoom,0.8*_zoom,2,6);
317 glTranslatef(0.0,0.0,-4.0);
318 glMatrixMode(GL_MODELVIEW);
322 /* Standard reshape function */
324 reshape_gflux(ModeInfo *mi, int width, int height)
326 glViewport( 0, 0, width, height );
331 /* main OpenGL initialization routine */
332 static void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height)
334 gfluxstruct *gp = &gfluxes[MI_SCREEN(mi)];
336 reshape_gflux(mi, width, height);
337 glViewport( 0, 0, width, height );
339 gp->tex_xscale = 1.0; /* maybe changed later */
340 gp->tex_yscale = 1.0;
344 gp->drawFunc = (displaySolid);
345 glEnable(GL_DEPTH_TEST);
348 gp->drawFunc = (displayLight);
349 glEnable(GL_DEPTH_TEST);
353 gp->drawFunc = (displayTexture);
354 glEnable(GL_DEPTH_TEST);
359 gp->drawFunc = (displayTexture);
360 glEnable(GL_DEPTH_TEST);
366 gp->drawFunc = (displayWire);
367 glDisable(GL_DEPTH_TEST);
371 if(_flat) glShadeModel(GL_FLAT);
372 else glShadeModel(GL_SMOOTH);
377 /* xgflux initialization routine */
378 ENTRYPOINT void init_gflux(ModeInfo * mi)
380 int screen = MI_SCREEN(mi);
383 if (gfluxes == NULL) {
384 if ((gfluxes = (gfluxstruct *)
385 calloc(MI_NUM_SCREENS(mi), sizeof (gfluxstruct))) == NULL)
388 gp = &gfluxes[screen];
390 gp->trackball = gltrackball_init ();
392 gp->time = frand(1000.0); /* don't run two screens in lockstep */
395 char *s = get_string_resource (mi->dpy, "mode", "Mode");
396 if (!s || !*s) _draw = wire;
397 else if (!strcasecmp (s, "wire")) _draw = wire;
398 else if (!strcasecmp (s, "solid")) _draw = solid;
399 else if (!strcasecmp (s, "light")) _draw = light;
400 else if (!strcasecmp (s, "checker")) _draw = checker;
401 else if (!strcasecmp (s, "grab")) _draw = grab;
405 "%s: mode must be one of: wire, solid, "
406 "light, checker, or grab; not \"%s\"\n",
413 gp->window = MI_WINDOW(mi);
414 if ((gp->glx_context = init_GL(mi)) != NULL) {
415 reshape_gflux(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
416 initializeGL(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
423 ENTRYPOINT void release_gflux(ModeInfo * mi)
425 if (gfluxes != NULL) {
426 free((void *) gfluxes);
433 static void createTexture(gfluxstruct *gp)
436 unsigned int data[] = { 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA,
437 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF,
438 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA,
439 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF };
441 gp->tex_xscale = size;
442 gp->tex_yscale = size;
444 glGenTextures (1, &gp->texName);
445 glBindTexture (GL_TEXTURE_2D, gp->texName);
447 glTexImage2D (GL_TEXTURE_2D, 0, 3, size, size, 0,
448 GL_RGBA, GL_UNSIGNED_BYTE, data);
450 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
451 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
453 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
454 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
459 image_loaded_cb (const char *filename, XRectangle *geometry,
460 int image_width, int image_height,
461 int texture_width, int texture_height,
464 gfluxstruct *gp = (gfluxstruct *) closure;
465 gp->img_geom = *geometry;
467 gp->tex_xscale = (GLfloat) image_width / texture_width;
468 gp->tex_yscale = -(GLfloat) image_height / texture_height;
469 gp->img_width = image_width;
470 gp->img_height = image_height;
472 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
473 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
474 (gp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
476 gp->waiting_for_image_p = False;
480 grabTexture(gfluxstruct *gp)
482 if (MI_IS_WIREFRAME(gp->modeinfo))
485 gp->waiting_for_image_p = True;
487 load_texture_async (gp->modeinfo->xgwa.screen, gp->modeinfo->window,
488 *gp->glx_context, 0, 0, gp->mipmap_p, gp->texName,
489 image_loaded_cb, gp);
493 static void initLighting(void)
495 static const float ambientA[] = {0.0, 0.0, 0.0, 1.0};
496 static const float diffuseA[] = {1.0, 1.0, 1.0, 1.0};
497 static const float positionA[] = {5.0, 5.0, 15.0, 1.0};
499 static const float front_mat_shininess[] = {30.0};
500 static const float front_mat_specular[] = {0.5, 0.5, 0.5, 1.0};
502 static const float mat_diffuse[] = {0.5, 0.5, 0.5, 1.0};
504 glMaterialfv(GL_FRONT, GL_SHININESS, front_mat_shininess);
505 glMaterialfv(GL_FRONT, GL_SPECULAR, front_mat_specular);
507 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
509 glLightfv(GL_LIGHT0, GL_AMBIENT, ambientA);
510 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseA);
511 glLightfv(GL_LIGHT0, GL_POSITION, positionA);
512 glEnable(GL_LIGHTING);
514 glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1);
516 glEnable(GL_NORMALIZE); /* would it be faster ... */
517 glEnable(GL_COLOR_MATERIAL);
518 glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
521 /************************************/
522 /* draw implementations */
523 /* somewhat inefficient since they */
524 /* all calculate previously */
525 /* calculated values again */
526 /* storing the values in an array */
527 /* is a posibility */
528 /************************************/
529 static int displayTexture(gfluxstruct *gp)
534 double dx = 2.0/((double)_squares);
535 double dy = 2.0/((double)_squares);
537 double du = 2.0/((double)_squares);
538 double dv = 2.0/((double)_squares);
540 double xs = gp->tex_xscale;
541 double ys = gp->tex_yscale;
543 double minx, miny, maxx, maxy;
547 minx = (GLfloat) gp->img_geom.x / gp->img_width;
548 miny = (GLfloat) gp->img_geom.y / gp->img_height;
549 maxx = ((GLfloat) (gp->img_geom.x + gp->img_geom.width) /
551 maxy = ((GLfloat) (gp->img_geom.y + gp->img_geom.height) /
555 minx = (minx * 2) - 1;
556 miny = (miny * 2) - 1;
557 maxx = (maxx * 2) - 1;
558 maxy = (maxy * 2) - 1;
568 glMatrixMode (GL_TEXTURE);
570 glTranslatef(-1,-1,0);
572 glMatrixMode (GL_MODELVIEW);
576 glRotatef(gp->anglex,1,0,0);
577 glRotatef(gp->angley,0,1,0);
578 glRotatef(gp->anglez,0,0,1);
579 glScalef(1,1,(GLfloat)_waveHeight);
580 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
581 glEnable(GL_TEXTURE_2D);
584 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
585 glBindTexture(GL_TEXTURE_2D, gp->texName);
586 check_gl_error("texture binding");
588 glColor3f(0.5,0.5,0.5);
590 for(x = minx, u = minu; x < maxx - 0.01; x += dx, u += du) {
591 glBegin(GL_QUAD_STRIP);
592 for (y = miny, v = minv; y <= maxy + 0.01; y += dy, v += dv) {
593 z = getGrid(gp,x,y,gp->time);
594 glTexCoord2f(u*xs,v*ys);
596 getGrid(gp,x+dx,y,gp->time)-getGrid(gp, x-dx,y,gp->time),
597 getGrid(gp,x,y+dy,gp->time)-getGrid(gp, x,y-dy,gp->time),
602 z = getGrid(gp,x+dx,y,gp->time);
603 glTexCoord2f((u+du)*xs,v*ys);
605 getGrid(gp,x+dx+dx,y,gp->time)-getGrid(gp, x,y,gp->time),
606 getGrid(gp,x+dx,y+dy,gp->time)-getGrid(gp, x+dx,y-dy,gp->time),
609 glVertex3f(x+dx,y,z);
615 /* Draw a border around the grid.
617 glColor3f(0.4, 0.4, 0.4);
618 glDisable(GL_TEXTURE_2D);
619 glEnable (GL_LINE_SMOOTH);
621 glBegin(GL_LINE_LOOP);
623 for (x = minx; x <= maxx; x += dx) {
624 glVertex3f (x, y, getGrid (gp, x, y, gp->time));
628 for (y = miny; y <= maxy; y += dy) {
629 glVertex3f (x, y, getGrid (gp, x, y, gp->time));
633 for (x = maxx; x >= minx; x -= dx) {
634 glVertex3f (x, y, getGrid (gp, x, y, gp->time));
638 for (y = maxy; y >= miny; y -= dy) {
639 glVertex3f (x, y, getGrid (gp, x, y, gp->time));
643 glEnable(GL_TEXTURE_2D);
645 if (! gp->button_down_p) {
647 gp->anglex -= _rotationx;
648 gp->angley -= _rotationy;
649 gp->anglez -= _rotationz;
654 static int displaySolid(gfluxstruct *gp)
659 double dx = 2.0/((double)_squares);
660 double dy = 2.0/((double)_squares);
663 glRotatef(gp->anglex,1,0,0);
664 glRotatef(gp->angley,0,1,0);
665 glRotatef(gp->anglez,0,0,1);
667 glScalef(1,1,(GLfloat)_waveHeight);
668 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
670 for(x=-1;x<0.9999;x+=dx) {
671 glBegin(GL_QUAD_STRIP);
672 for(y=-1;y<=1;y+=dy) {
673 z = getGrid(gp, x,y,gp->time);
675 glColor3fv(gp->colour);
678 z = getGrid(gp, x+dx,y,gp->time);
680 glColor3fv(gp->colour);
681 glVertex3f(x+dx,y,z);
687 if (! gp->button_down_p) {
689 gp->anglex -= _rotationx;
690 gp->angley -= _rotationy;
691 gp->anglez -= _rotationz;
697 static int displayLight(gfluxstruct *gp)
702 double dx = 2.0/((double)_squares);
703 double dy = 2.0/((double)_squares);
706 glRotatef(gp->anglex,1,0,0);
707 glRotatef(gp->angley,0,1,0);
708 glRotatef(gp->anglez,0,0,1);
710 glScalef(1,1,(GLfloat)_waveHeight);
711 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
713 for(x=-1;x<0.9999;x+=dx) {
714 glBegin(GL_QUAD_STRIP);
715 for(y=-1;y<=1;y+=dy) {
716 z = getGrid(gp, x,y,gp->time);
718 glColor3fv(gp->colour);
720 getGrid(gp, x+dx,y,gp->time)-getGrid(gp, x-dx,y,gp->time),
721 getGrid(gp, x,y+dy,gp->time)-getGrid(gp, x,y-dy,gp->time),
726 z = getGrid(gp, x+dx,y,gp->time);
728 glColor3fv(gp->colour);
730 getGrid(gp, x+dx+dx,y,gp->time)-getGrid(gp, x,y,gp->time),
731 getGrid(gp, x+dx,y+dy,gp->time)-getGrid(gp, x+dx,y-dy,gp->time),
734 glVertex3f(x+dx,y,z);
740 if (! gp->button_down_p) {
742 gp->anglex -= _rotationx;
743 gp->angley -= _rotationy;
744 gp->anglez -= _rotationz;
749 static int displayWire(gfluxstruct *gp)
754 double dx1 = 2.0/((double)(_squares*_resolution)) - 0.00001;
755 double dy1 = 2.0/((double)(_squares*_resolution)) - 0.00001;
756 double dx2 = 2.0/((double)_squares) - 0.00001;
757 double dy2 = 2.0/((double)_squares) - 0.00001;
760 glRotatef(gp->anglex,1,0,0);
761 glRotatef(gp->angley,0,1,0);
762 glRotatef(gp->anglez,0,0,1);
764 glScalef(1,1,(GLfloat)_waveHeight);
765 glClear(GL_COLOR_BUFFER_BIT);
767 for(x=-1;x<=1;x+=dx2) {
768 glBegin(GL_LINE_STRIP);
769 for(y=-1;y<=1;y+=dy1) {
770 z = getGrid(gp, x,y,gp->time);
772 glColor3fv(gp->colour);
778 for(y=-1;y<=1;y+=dy2) {
779 glBegin(GL_LINE_STRIP);
780 for(x=-1;x<=1;x+=dx1) {
781 z = getGrid(gp, x,y,gp->time);
783 glColor3fv(gp->colour);
790 if (! gp->button_down_p) {
792 gp->anglex -= _rotationx;
793 gp->angley -= _rotationy;
794 gp->anglez -= _rotationz;
799 /* generates new ripples */
800 static void calcGrid(gfluxstruct *gp)
804 if (gp->button_down_p) return;
806 tmp = 1.0/((double)_waveChange);
807 if(!(gp->counter%_waveChange)) {
808 gp->newWave = ((int)(gp->counter*tmp))%_waves;
809 gp->dispx[gp->newWave] = -frand(1.0);
810 gp->dispy[gp->newWave] = -frand(1.0);
811 gp->freq[gp->newWave] = _waveFreq * frand(1.0);
812 gp->wa[gp->newWave] = 0.0;
815 gp->wa[gp->newWave] += tmp;
816 gp->wa[(gp->newWave+1)%_waves] -= tmp;
819 /* returns a height for the grid given time and x,y space co-ords */
820 static double getGrid(gfluxstruct *gp, double x, double y, double a)
826 tmp = 1.0/((float)_waves);
827 for(i=0;i<_waves;i++) {
828 retval += gp->wa[i] * tmp * sin( gp->freq[i]
829 * ( (x+gp->dispx[i]) * (x+gp->dispx[i])
830 + (y+gp->dispy[i]) * (y+gp->dispy[i]) +a ) );
836 XSCREENSAVER_MODULE ("GFlux", gflux)