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 * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
44 * otherwise caddr_t is not defined correctly
47 #include <X11/Intrinsic.h>
51 # define PROGCLASS "gflux"
52 # define HACK_INIT init_gflux
53 # define HACK_DRAW draw_gflux
54 # define HACK_RESHAPE reshape_gflux
55 # define HACK_HANDLE_EVENT gflux_handle_event
56 # define EVENT_MASK PointerMotionMask
57 # define gflux_opts xlockmore_opts
58 #define DEFAULTS "*delay: 20000 \n" \
59 "*showFPS: False \n" \
65 "*rotationx: 0.01 \n" \
66 "*rotationy: 0.0 \n" \
67 "*rotationz: 0.1 \n" \
69 "*waveChange: 50 \n" \
70 "*waveHeight: 0.8 \n" \
75 # include "xlockmore.h" /* from the xscreensaver distribution */
76 #else /* !STANDALONE */
77 # include "xlock.h" /* from the xlockmore distribution */
78 #endif /* !STANDALONE */
80 #ifdef USE_GL /* whole file */
84 # include <X11/Xmu/Drawing.h>
86 # include <Xmu/Drawing.h>
95 #define countof(x) (sizeof((x))/sizeof((*x)))
106 #include "grab-ximage.h"
107 #include "gltrackball.h"
110 static enum {wire=0,solid,light,checker,textured,grab} _draw; /* draw style */
111 static int _squares = 19; /* grid size */
112 static int _resolution = 4; /* wireframe resolution */
113 static int _flat = 0;
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;
121 static int _waves = 3;
122 static int _waveChange = 50;
123 static float _waveHeight = 1.0;
124 static float _waveFreq = 3.0;
126 static trackball_state *trackball;
127 static Bool button_down_p = False;
132 static XrmOptionDescRec opts[] = {
133 {"-squares", ".gflux.squares", XrmoptionSepArg, (caddr_t) NULL},
134 {"-resolution", ".gflux.resolution", XrmoptionSepArg, (caddr_t) NULL},
135 /* {"-draw", ".gflux.draw", XrmoptionSepArg, (caddr_t) NULL},*/
136 {"-mode", ".gflux.mode", XrmoptionSepArg, (caddr_t) NULL},
137 {"-flat", ".gflux.flat", XrmoptionSepArg, (caddr_t) NULL},
138 {"-speed", ".gflux.speed", XrmoptionSepArg, (caddr_t) NULL},
139 {"-rotationx", ".gflux.rotationx", XrmoptionSepArg, (caddr_t) NULL},
140 {"-rotationy", ".gflux.rotationy", XrmoptionSepArg, (caddr_t) NULL},
141 {"-rotationz", ".gflux.rotationz", XrmoptionSepArg, (caddr_t) NULL},
142 {"-waves", ".gflux.waves", XrmoptionSepArg, (caddr_t) NULL},
143 {"-waveChange", ".gflux.waveChange", XrmoptionSepArg, (caddr_t) NULL},
144 {"-waveHeight", ".gflux.waveHeight", XrmoptionSepArg, (caddr_t) NULL},
145 {"-waveFreq", ".gflux.waveFreq", XrmoptionSepArg, (caddr_t) NULL},
146 {"-zoom", ".gflux.zoom", XrmoptionSepArg, (caddr_t) NULL},
150 static argtype vars[] = {
151 {(caddr_t *) & _squares, "squares", "Squares", "19", t_Int},
152 {(caddr_t *) & _resolution, "resolution", "Resolution", "4", t_Int},
153 /* {(caddr_t *) & _draw, "draw", "Draw", "2", t_Int},*/
154 {(caddr_t *) & _flat, "flat", "Flat", "0", t_Int},
155 {(caddr_t *) & _speed, "speed", "Speed", "0.05", t_Float},
156 {(caddr_t *) & _rotationx, "rotationx", "Rotationx", "0.01", t_Float},
157 {(caddr_t *) & _rotationy, "rotationy", "Rotationy", "0.0", t_Float},
158 {(caddr_t *) & _rotationz, "rotationz", "Rotationz", "0.1", t_Float},
159 {(caddr_t *) & _waves, "waves", "Waves", "3", t_Int},
160 {(caddr_t *) & _waveChange, "waveChange", "WaveChange", "50", t_Int},
161 {(caddr_t *) & _waveHeight, "waveHeight", "WaveHeight", "1.0", t_Float},
162 {(caddr_t *) & _waveFreq, "waveFreq", "WaveFreq", "3.0", t_Float},
163 {(caddr_t *) & _zoom, "zoom", "Zoom", "1.0", t_Float},
167 static OptionStruct desc[] =
169 {"-squares num", "size of grid in squares (19)"},
170 {"-resolution num", "detail of lines making grid, wireframe only (4)"},
171 /* {"-draw num", "draw method to use: 0=wireframe 1=solid 2=lit (0)"},*/
172 {"-flat num", "shading method, not wireframe: 0=smooth 1=flat (0)"},
173 {"-speed num", "speed of waves (0.05)"},
174 {"-rotationx num", "speed of xrotation (0.01)"},
175 {"-rotationy num", "speed of yrotation (0.00)"},
176 {"-rotationz num", "speed of zrotation (0.10)"},
177 {"-waves num", "number of simultanious waves (3)"},
178 {"-waveChange num", "number of cyles for a wave to change (50)"},
179 {"-waveHeight num", "height of waves (1.0)"},
180 {"-waveFreq num", "max frequency of a wave (3.0)"},
181 {"-zoom num", "camera control (1.0)"},
184 ModeSpecOpt gflux_opts = {countof(opts), opts, countof(vars), vars, desc};
187 ModStruct gflux_description =
188 {"gflux", "init_gflux", "draw_gflux", "release_gflux",
189 "draw_gflux", "init_gflux", NULL, &gflux_opts,
190 1000, 1, 2, 1, 4, 1.0, "",
191 "Gflux: an OpenGL gflux", 0, NULL};
194 /* structure for holding the gflux data */
197 int screen_width, screen_height;
198 GLXContext *glx_context;
201 #define MAXWAVES 10 /* should be dynamic */
203 double freq[MAXWAVES];
204 double dispy[MAXWAVES];
205 double dispx[MAXWAVES];
219 void (*drawFunc)(void);
221 static gfluxstruct *gflux = NULL;
224 void initLighting(void);
225 void initTexture(void);
226 void loadTexture(void);
227 void grabTexture(void);
228 void createTexture(void);
229 void displaySolid(void); /* drawFunc implementations */
230 void displayLight(void);
231 void displayTexture(void);
232 void displayWire(void);
234 double getGrid(double,double,double);
236 /* as macro for speed */
237 /* could do with colour cycling here */
238 /* void genColour(double);*/
239 #define genColour(X) \
241 gflux->colour[0] = 0.0;\
242 gflux->colour[1] = 0.5+0.5*(X);\
243 gflux->colour[2] = 0.5-0.5*(X);\
246 /* BEGINNING OF FUNCTIONS */
250 gflux_handle_event (ModeInfo *mi, XEvent *event)
252 if (event->xany.type == ButtonPress &&
253 event->xbutton.button & Button1)
255 button_down_p = True;
256 gltrackball_start (trackball,
257 event->xbutton.x, event->xbutton.y,
258 MI_WIDTH (mi), MI_HEIGHT (mi));
261 else if (event->xany.type == ButtonRelease &&
262 event->xbutton.button & Button1)
264 button_down_p = False;
267 else if (event->xany.type == MotionNotify &&
270 gltrackball_track (trackball,
271 event->xmotion.x, event->xmotion.y,
272 MI_WIDTH (mi), MI_HEIGHT (mi));
283 gltrackball_rotate (trackball);
286 /* draw the gflux once */
287 void draw_gflux(ModeInfo * mi)
289 gfluxstruct *gp = &gflux[MI_SCREEN(mi)];
290 Display *display = MI_DISPLAY(mi);
291 Window window = MI_WINDOW(mi);
293 if (!gp->glx_context) return;
295 glXMakeCurrent(display, window, *(gp->glx_context));
299 if (mi->fps_p) do_fps (mi);
300 glXSwapBuffers(display, window);
304 /* reset the projection matrix */
305 void resetProjection(void) {
306 glMatrixMode(GL_PROJECTION);
308 glFrustum(-_zoom,_zoom,-0.8*_zoom,0.8*_zoom,2,6);
309 glTranslatef(0.0,0.0,-4.0);
310 glMatrixMode(GL_MODELVIEW);
314 /* Standard reshape function */
316 reshape_gflux(ModeInfo *mi, int width, int height)
318 glViewport( 0, 0, width, height );
323 /* main OpenGL initialization routine */
324 void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height)
326 reshape_gflux(mi, width, height);
327 glViewport( 0, 0, width, height );
329 gflux->tex_xscale = 1.0; /* maybe changed later */
330 gflux->tex_yscale = 1.0;
334 gflux->drawFunc = (displaySolid);
335 glEnable(GL_DEPTH_TEST);
338 gflux->drawFunc = (displayLight);
339 glEnable(GL_DEPTH_TEST);
343 gflux->drawFunc = (displayTexture);
344 glEnable(GL_DEPTH_TEST);
350 gflux->drawFunc = (displayTexture);
351 glEnable(GL_DEPTH_TEST);
357 gflux->drawFunc = (displayTexture);
358 glEnable(GL_DEPTH_TEST);
365 gflux->drawFunc = (displayWire);
366 glDisable(GL_DEPTH_TEST);
370 if(_flat) glShadeModel(GL_FLAT);
371 else glShadeModel(GL_SMOOTH);
376 /* xgflux initialization routine */
377 void init_gflux(ModeInfo * mi)
379 int screen = MI_SCREEN(mi);
383 if ((gflux = (gfluxstruct *)
384 calloc(MI_NUM_SCREENS(mi), sizeof (gfluxstruct))) == NULL)
389 trackball = gltrackball_init ();
392 char *s = get_string_resource ("mode", "Mode");
393 if (!s || !*s) _draw = wire;
394 else if (!strcasecmp (s, "wire")) _draw = wire;
395 else if (!strcasecmp (s, "solid")) _draw = solid;
396 else if (!strcasecmp (s, "light")) _draw = light;
397 else if (!strcasecmp (s, "checker")) _draw = checker;
398 else if (!strcasecmp (s, "stdin")) _draw = textured;
399 else if (!strcasecmp (s, "grab")) _draw = grab;
403 "%s: mode must be one of: wire, solid, "
404 "light, checker, or grab; not \"%s\"\n",
411 gp->window = MI_WINDOW(mi);
412 if ((gp->glx_context = init_GL(mi)) != NULL) {
413 reshape_gflux(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
414 initializeGL(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
421 void release_gflux(ModeInfo * mi)
423 if(gflux->image!=NULL) free(gflux->image);
424 if(gflux->glx_context!=NULL) free(gflux->glx_context);
426 (void) free((void *) gflux);
434 /* load pnm from stdin using pnm libs */
435 void loadTexture(void)
438 gflux->image = ppm_readppm( file,
439 &(gflux->imageHeight), &(gflux->imageWidth), &(gflux->imageMax) );
442 /* creates an image for texture mapping */
443 void createTexture(void)
448 gflux->imageHeight = gflux->imageWidth = 8;
450 result = ppm_allocarray(gflux->imageHeight,gflux->imageWidth);
451 for(i=0;i<gflux->imageHeight;i++) {
452 for(j=0;j<gflux->imageWidth;j++) {
453 c = (((i)%2 ^ (j)%2) ? 100 : 200 );
454 PPM_ASSIGN( result[i][j] , c, c, c );
457 gflux->image = result;
460 /* specifies image as texture */
461 void initTexture(void)
463 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
464 glGenTextures(1, &gflux->texName);
465 glBindTexture(GL_TEXTURE_2D, gflux->texName);
466 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
467 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
468 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
469 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
472 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, gflux->imageWidth,
473 gflux->imageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, *(gflux->image));
474 check_gl_error("texture");
477 #else /* HAVE_PPM FALSE */
479 #define presult(A,B,C) (*(result+(A)*(gflux->imageWidth)*4+(B)*4+(C)))
480 void loadTexture(void)
482 int i, j, levels, width, height;
491 if(!strncmp(s,"P6",2)) ppmType=6;
492 if(!strncmp(s,"P5",2)) ppmType=5;
493 if(!strncmp(s,"P3",2)) ppmType=3;
494 if(!strncmp(s,"P2",2)) ppmType=2;
497 while((i=getc(file))=='#')
499 while(getc(file)!='\n');
503 fscanf(file,"%d %d %d",&width,&height,&levels);
505 result = malloc(sizeof(GLubyte)*4*width*height);
506 gflux->imageWidth = width;
507 gflux->imageHeight = height;
510 case 2 : /* ASCII grey */
511 for(i=0;i<height;i++) {
512 for(j=0;j<width;j++) {
513 fscanf(file,"%d",&red);
514 presult(j,i,0) = red;
515 presult(j,i,1) = red;
516 presult(j,i,2) = red;
520 case 3 : /* ASCII rgb */
521 for(i=0;i<height;i++) {
522 for(j=0;j<width;j++) {
523 fscanf(file,"%d %d %d",&red,&green,&blue);
524 presult(j,i,0) = red;
525 presult(j,i,1) = green;
526 presult(j,i,2) = blue;
530 case 5 : /* Binary grey */
531 getc(file); /* seems nessessary */
532 for(i=0;i<height;i++) {
533 for(j=0;j<width;j++) {
535 presult(j,i,0) = red;
536 presult(j,i,1) = red;
537 presult(j,i,2) = red;
541 case 6 : /* Binary rgb */
542 getc(file); /* seems nessessary */
543 for(i=0;i<height;i++) {
544 for(j=0;j<width;j++) {
548 presult(j,i,0) = red;
549 presult(j,i,1) = green;
550 presult(j,i,2) = blue;
555 gflux->image = result;
558 void createTexture(void)
563 gflux->imageHeight = gflux->imageWidth = 8;
565 result = malloc(sizeof(GLubyte)*4*gflux->imageHeight*gflux->imageWidth);
566 for(i=0;i<gflux->imageHeight;i++) {
567 for(j=0;j<gflux->imageWidth;j++) {
568 c = (((i)%2 ^ (j)%2) ? 100 : 200 );
569 presult(i,j,0) = (GLubyte) c;
570 presult(i,j,1) = (GLubyte) c;
571 presult(i,j,2) = (GLubyte) c;
572 presult(i,j,3) = (GLubyte) 255;
575 gflux->image = result;
578 /* specifies image as texture */
579 void initTexture(void)
582 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
583 glGenTextures(1, &gflux->texName);
584 glBindTexture(GL_TEXTURE_2D, gflux->texName);
585 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
586 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
587 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
588 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
589 check_gl_error("texture parameter");
591 /* Bail out if the texture is too large. */
594 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, gflux->imageWidth,
595 gflux->imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
596 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0,
597 GL_TEXTURE_WIDTH, &width);
600 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &width);
602 "%s: texture too large (%dx%d -- probable max %dx%d)\n",
603 progname, gflux->imageWidth, gflux->imageHeight,
609 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gflux->imageWidth,
610 gflux->imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, gflux->image);
611 check_gl_error("texture creation");
621 int real_width = gflux->modeinfo->xgwa.width;
622 int real_height = gflux->modeinfo->xgwa.height;
623 XImage *ximage = screen_to_ximage (gflux->modeinfo->xgwa.screen,
625 Bool bigimage = False;
628 if (ximage->width > 1280 || /* that's too damned big... */
629 ximage->height > 1280)
631 Display *dpy = gflux->modeinfo->dpy;
632 Visual *v = gflux->modeinfo->xgwa.visual;
633 int real_size = (ximage->width < ximage->height ?
634 real_width : real_height);
636 int x, y, xoff, yoff;
637 size = (ximage->width < ximage->height ?
638 ximage->width : ximage->height);
641 if (size > 1024) size = 1024;
643 x2 = XCreateImage (dpy, v, 32, ZPixmap, 0, 0, size, size, 32, 0);
644 xoff = (real_width > size ? (random() % (real_width - size)) : 0);
645 yoff = (real_height > size ? (random() % (real_height - size)) : 0);
648 fprintf(stderr, "%s: cropping texture from %dx%d to %dx%d @ %d,%d\n",
649 progname, ximage->width, ximage->height, x2->width, x2->height,
652 x2->data = ximage->data; /* we can reuse the same array */
653 for (y = 0; y < x2->height; y++)
654 for (x = 0; x < x2->width; x++)
655 XPutPixel (x2, x, y, XGetPixel (ximage, x+xoff, y+yoff));
657 real_width = real_height = real_size;
659 XDestroyImage (ximage);
665 unsigned long gray = 0xAAAAAAAAL; /* so shoot me */
666 int width = (bigimage ? size : real_width);
667 int height = (bigimage ? size : real_height);
669 for (i = 0; i < real_height; i++)
671 XPutPixel (ximage, 0, i, gray);
672 XPutPixel (ximage, width-1, i, gray);
674 for (i = 0; i < real_width; i++)
676 XPutPixel (ximage, i, 0, gray);
677 XPutPixel (ximage, i, height-1, gray);
681 gflux->imageWidth = ximage->width;
682 gflux->imageHeight = ximage->height;
683 gflux->image = (GLubyte *) ximage->data;
685 if (bigimage) /* don't scale really large images */
687 gflux->tex_xscale = 1;
688 gflux->tex_yscale = 1;
692 gflux->tex_xscale = ((GLfloat) real_width / (GLfloat) ximage->width);
693 gflux->tex_yscale = ((GLfloat) real_height / (GLfloat) ximage->height);
697 XDestroyImage (ximage);
701 void initLighting(void)
703 static float ambientA[] = {0.0, 0.0, 0.0, 1.0};
704 static float diffuseA[] = {1.0, 1.0, 1.0, 1.0};
705 static float positionA[] = {5.0, 5.0, 15.0, 1.0};
707 static float front_mat_shininess[] = {30.0};
708 static float front_mat_specular[] = {0.5, 0.5, 0.5, 1.0};
710 static float mat_diffuse[] = {0.5, 0.5, 0.5, 1.0};
712 glMaterialfv(GL_FRONT, GL_SHININESS, front_mat_shininess);
713 glMaterialfv(GL_FRONT, GL_SPECULAR, front_mat_specular);
715 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
717 glLightfv(GL_LIGHT0, GL_AMBIENT, ambientA);
718 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseA);
719 glLightfv(GL_LIGHT0, GL_POSITION, positionA);
720 glEnable(GL_LIGHTING);
722 glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1);
724 glEnable(GL_NORMALIZE); /* would it be faster ... */
725 glEnable(GL_COLOR_MATERIAL);
726 glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
729 /************************************/
730 /* draw implementations */
731 /* somewhat inefficient since they */
732 /* all calculate previously */
733 /* calculated values again */
734 /* storing the values in an array */
735 /* is a posibility */
736 /************************************/
737 void displayTexture(void)
739 static double time = 0.0;
740 static double anglex = 0.0;
741 static double angley = 0.0;
742 static double anglez = 0.0;
746 double dx = 2.0/((double)_squares);
747 double dy = 2.0/((double)_squares);
749 double du = 2.0/((double)_squares);
750 double dv = 2.0/((double)_squares);
752 double xs = gflux->tex_xscale;
753 double ys = gflux->tex_yscale;
755 glMatrixMode (GL_TEXTURE);
757 glTranslatef(-1,-1,0);
759 glMatrixMode (GL_MODELVIEW);
762 glRotatef(anglex,1,0,0);
763 glRotatef(angley,0,1,0);
764 glRotatef(anglez,0,0,1);
766 glScalef(1,1,(GLfloat)_waveHeight);
767 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
768 glEnable(GL_TEXTURE_2D);
771 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
772 glBindTexture(GL_TEXTURE_2D, gflux->texName);
773 check_gl_error("texture binding");
775 glColor3f(0.5,0.5,0.5);
777 for(x=-1,u= 0;x<0.9999;x+=dx,u+=du) {
778 glBegin(GL_QUAD_STRIP);
779 for(y=-1,v= 0;y<=1;y+=dy,v+=dv) {
780 z = getGrid(x,y,time);
782 glColor3fv(gflux->colour);
783 */ glTexCoord2f(u*xs,v*ys);
785 getGrid(x+dx,y,time)-getGrid(x-dx,y,time),
786 getGrid(x,y+dy,time)-getGrid(x,y-dy,time),
791 z = getGrid(x+dx,y,time);
793 glColor3fv(gflux->colour);
794 */ glTexCoord2f((u+du)*xs,v*ys);
796 getGrid(x+dx+dx,y,time)-getGrid(x,y,time),
797 getGrid(x+dx,y+dy,time)-getGrid(x+dx,y-dy,time),
800 glVertex3f(x+dx,y,z);
805 if (! button_down_p) {
807 anglex -= _rotationx;
808 angley -= _rotationy;
809 anglez -= _rotationz;
812 void displaySolid(void)
814 static double time = 0.0;
815 static double anglex = 0.0;
816 static double angley = 0.0;
817 static double anglez = 0.0;
821 double dx = 2.0/((double)_squares);
822 double dy = 2.0/((double)_squares);
825 glRotatef(anglex,1,0,0);
826 glRotatef(angley,0,1,0);
827 glRotatef(anglez,0,0,1);
829 glScalef(1,1,(GLfloat)_waveHeight);
830 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
832 for(x=-1;x<0.9999;x+=dx) {
833 glBegin(GL_QUAD_STRIP);
834 for(y=-1;y<=1;y+=dy) {
835 z = getGrid(x,y,time);
837 glColor3fv(gflux->colour);
840 z = getGrid(x+dx,y,time);
842 glColor3fv(gflux->colour);
843 glVertex3f(x+dx,y,z);
848 if (! button_down_p) {
850 anglex -= _rotationx;
851 angley -= _rotationy;
852 anglez -= _rotationz;
857 void displayLight(void)
859 static double time = 0.0;
860 static double anglex = 0.0;
861 static double angley = 0.0;
862 static double anglez = 0.0;
866 double dx = 2.0/((double)_squares);
867 double dy = 2.0/((double)_squares);
870 glRotatef(anglex,1,0,0);
871 glRotatef(angley,0,1,0);
872 glRotatef(anglez,0,0,1);
874 glScalef(1,1,(GLfloat)_waveHeight);
875 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
877 for(x=-1;x<0.9999;x+=dx) {
878 glBegin(GL_QUAD_STRIP);
879 for(y=-1;y<=1;y+=dy) {
880 z = getGrid(x,y,time);
882 glColor3fv(gflux->colour);
884 getGrid(x+dx,y,time)-getGrid(x-dx,y,time),
885 getGrid(x,y+dy,time)-getGrid(x,y-dy,time),
890 z = getGrid(x+dx,y,time);
892 glColor3fv(gflux->colour);
894 getGrid(x+dx+dx,y,time)-getGrid(x,y,time),
895 getGrid(x+dx,y+dy,time)-getGrid(x+dx,y-dy,time),
898 glVertex3f(x+dx,y,z);
903 if (! button_down_p) {
905 anglex -= _rotationx;
906 angley -= _rotationy;
907 anglez -= _rotationz;
911 void displayWire(void)
913 static double time = 0.0;
914 static double anglex = 0.0;
915 static double angley = 0.0;
916 static double anglez = 0.0;
920 double dx1 = 2.0/((double)(_squares*_resolution)) - 0.00001;
921 double dy1 = 2.0/((double)(_squares*_resolution)) - 0.00001;
922 double dx2 = 2.0/((double)_squares) - 0.00001;
923 double dy2 = 2.0/((double)_squares) - 0.00001;
926 glRotatef(anglex,1,0,0);
927 glRotatef(angley,0,1,0);
928 glRotatef(anglez,0,0,1);
930 glScalef(1,1,(GLfloat)_waveHeight);
931 glClear(GL_COLOR_BUFFER_BIT);
933 for(x=-1;x<=1;x+=dx2) {
934 glBegin(GL_LINE_STRIP);
935 for(y=-1;y<=1;y+=dy1) {
936 z = getGrid(x,y,time);
938 glColor3fv(gflux->colour);
943 for(y=-1;y<=1;y+=dy2) {
944 glBegin(GL_LINE_STRIP);
945 for(x=-1;x<=1;x+=dx1) {
946 z = getGrid(x,y,time);
948 glColor3fv(gflux->colour);
954 if (! button_down_p) {
956 anglex -= _rotationx;
957 angley -= _rotationy;
958 anglez -= _rotationz;
962 /* generates new ripples */
965 static int counter=0;
969 if (button_down_p) return;
971 tmp = 1.0/((double)_waveChange);
972 if(!(counter%_waveChange)) {
973 newWave = ((int)(counter*tmp))%_waves;
974 gflux->dispx[newWave] = -frand(1.0);
975 gflux->dispy[newWave] = -frand(1.0);
976 gflux->freq[newWave] = _waveFreq * frand(1.0);
977 gflux->wa[newWave] = 0.0;
980 gflux->wa[newWave] += tmp;
981 gflux->wa[(newWave+1)%_waves] -= tmp;
984 /* returns a height for the grid given time and x,y space co-ords */
985 double getGrid(double x, double y, double a)
991 tmp = 1.0/((float)_waves);
992 for(i=0;i<_waves;i++) {
993 retval += gflux->wa[i] * tmp * sin( gflux->freq[i]
994 * ( (x+gflux->dispx[i]) * (x+gflux->dispx[i])
995 + (y+gflux->dispy[i]) * (y+gflux->dispy[i]) +a ) );