From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/glx/gflux.c | 803 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 803 insertions(+) create mode 100644 hacks/glx/gflux.c (limited to 'hacks/glx/gflux.c') diff --git a/hacks/glx/gflux.c b/hacks/glx/gflux.c new file mode 100644 index 0000000..dbbb11c --- /dev/null +++ b/hacks/glx/gflux.c @@ -0,0 +1,803 @@ +/* -*- Mode: C; tab-width: 4 -*- emacs friendly */ +/* gflux - creates a fluctuating 3D grid + * requires OpenGL or MesaGL + * + * Copyright (c) Josiah Pease, 2000, 2003 + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * Thanks go to all those who worked on... + * MesaGL, OpenGL, UtahGLX, XFree86, gcc, vim, rxvt, the PNM (anymap) format + * xscreensaver and the thousands of other tools, apps and daemons that make + * linux usable + * Personal thanks to Kevin Moss, Paul Sheahee and Jamie Zawinski + * + * some xscreensaver code lifted from superquadrics. Most other glx hacks + * used as reference at some time. + * + * This hack and others can cause UtahGLX to crash my X server + * wireframe looks good with software only rendering anyway + * If anyone can work out why and supply a fix I'd love to hear from them + * + * Josiah Pease 21 July 2000 + * + * History + * 10 June 2000 : wireframe rippling grid standalone written + * 18 June 2000 : xscreensaver code added + * 25 June 2000 : solid and light added + * 04 July 2000 : majour bug hunt, xscreensaver code rewritten + * 08 July 2000 : texture mapping, rotation and zoom added + * 21 July 2000 : cleaned up code from bug hunts, manpage written + * 24 November 2000 : fixed x co-ord calculation in solid - textured + * 05 March 2001 : put back non pnmlib code with #ifdefs + * 11 May 2002 : fixed image problems with large images + */ + + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000\n" \ + "*showFPS: False\n" \ + "*mode: grab\n" \ + "*useSHM: True \n" \ + "*suppressRotationAnimation: True\n" \ + +# define free_gflux 0 +# define release_gflux 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL /* whole file */ + +#ifdef HAVE_XMU +# ifndef VMS +# include +#else /* VMS */ +# include +# endif /* VMS */ +#endif + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include +#include + +#include + +#include "grab-ximage.h" +#include "gltrackball.h" + + +static enum {wire=0,solid,light,checker,grab} _draw; + +# define DEF_SQUARES "19" +# define DEF_RESOLUTION "4" +# define DEF_DRAW "2" +# define DEF_FLAT "0" +# define DEF_SPEED "0.05" +# define DEF_ROTATIONX "0.01" +# define DEF_ROTATIONY "0.0" +# define DEF_ROTATIONZ "0.1" +# define DEF_WAVES "3" +# define DEF_WAVE_CHANGE "50" +# define DEF_WAVE_HEIGHT "1.0" +# define DEF_WAVE_FREQ "3.0" +# define DEF_ZOOM "1.0" + + + +static int _squares; /* grid size */ +static int _resolution; /* wireframe resolution */ +static int _flat; + +static float _speed; +static float _rotationx; +static float _rotationy; +static float _rotationz; +static float _zoom; + +static int _waves; +static int _waveChange; +static float _waveHeight; +static float _waveFreq; + + +#define WIDTH 320 +#define HEIGHT 240 + +static XrmOptionDescRec opts[] = { + {"-squares", ".gflux.squares", XrmoptionSepArg, 0}, + {"-resolution", ".gflux.resolution", XrmoptionSepArg, 0}, +/* {"-draw", ".gflux.draw", XrmoptionSepArg, 0},*/ + {"-mode", ".gflux.mode", XrmoptionSepArg, 0}, + {"-wireframe", ".gflux.mode", XrmoptionNoArg, "wire"}, + {"-flat", ".gflux.flat", XrmoptionSepArg, 0}, + {"-speed", ".gflux.speed", XrmoptionSepArg, 0}, + {"-rotationx", ".gflux.rotationx", XrmoptionSepArg, 0}, + {"-rotationy", ".gflux.rotationy", XrmoptionSepArg, 0}, + {"-rotationz", ".gflux.rotationz", XrmoptionSepArg, 0}, + {"-waves", ".gflux.waves", XrmoptionSepArg, 0}, + {"-waveChange", ".gflux.waveChange", XrmoptionSepArg, 0}, + {"-waveHeight", ".gflux.waveHeight", XrmoptionSepArg, 0}, + {"-waveFreq", ".gflux.waveFreq", XrmoptionSepArg, 0}, + {"-zoom", ".gflux.zoom", XrmoptionSepArg, 0}, +}; + + +static argtype vars[] = { + {&_squares, "squares", "Squares", DEF_SQUARES, t_Int}, + {&_resolution, "resolution", "Resolution", DEF_RESOLUTION, t_Int}, +/* {&_draw, "draw", "Draw", DEF_DRAW, t_Int},*/ + {&_flat, "flat", "Flat", DEF_FLAT, t_Int}, + {&_speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&_rotationx, "rotationx", "Rotationx", DEF_ROTATIONX, t_Float}, + {&_rotationy, "rotationy", "Rotationy", DEF_ROTATIONY, t_Float}, + {&_rotationz, "rotationz", "Rotationz", DEF_ROTATIONZ, t_Float}, + {&_waves, "waves", "Waves", DEF_WAVES, t_Int}, + {&_waveChange, "waveChange", "WaveChange", DEF_WAVE_CHANGE, t_Int}, + {&_waveHeight, "waveHeight", "WaveHeight", DEF_WAVE_HEIGHT, t_Float}, + {&_waveFreq, "waveFreq", "WaveFreq", DEF_WAVE_FREQ, t_Float}, + {&_zoom, "zoom", "Zoom", DEF_ZOOM, t_Float}, +}; + + +static OptionStruct desc[] = +{ + {"-squares num", "size of grid in squares (19)"}, + {"-resolution num", "detail of lines making grid, wireframe only (4)"}, +/* {"-draw num", "draw method to use: 0=wireframe 1=solid 2=lit (0)"},*/ + {"-flat num", "shading method, not wireframe: 0=smooth 1=flat (0)"}, + {"-speed num", "speed of waves (0.05)"}, + {"-rotationx num", "speed of xrotation (0.01)"}, + {"-rotationy num", "speed of yrotation (0.00)"}, + {"-rotationz num", "speed of zrotation (0.10)"}, + {"-waves num", "number of simultanious waves (3)"}, + {"-waveChange num", "number of cyles for a wave to change (50)"}, + {"-waveHeight num", "height of waves (1.0)"}, + {"-waveFreq num", "max frequency of a wave (3.0)"}, + {"-zoom num", "camera control (1.0)"}, +}; + +ENTRYPOINT ModeSpecOpt gflux_opts = {countof(opts), opts, countof(vars), vars, desc}; + +#ifdef USE_MODULES +ModStruct gflux_description = +{"gflux", "init_gflux", "draw_gflux", NULL, + "draw_gflux", "init_gflux", NULL, &gflux_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "GFlux: an OpenGL gflux", 0, NULL}; +#endif + +/* structure for holding the gflux data */ +typedef struct gfluxstruct { + ModeInfo *modeinfo; + int screen_width, screen_height; + GLXContext *glx_context; + Window window; + XColor fg, bg; +#define MAXWAVES 10 /* should be dynamic */ + double wa[MAXWAVES]; + double freq[MAXWAVES]; + double dispy[MAXWAVES]; + double dispx[MAXWAVES]; + GLfloat colour[3]; + GLuint texName; + GLfloat tex_xscale; + GLfloat tex_yscale; + XRectangle img_geom; + int img_width, img_height; + int (*drawFunc)(struct gfluxstruct *); + + trackball_state *trackball; + Bool button_down_p; + + double time; + double anglex; + double angley; + double anglez; + + int counter; + int newWave; + + Bool mipmap_p; + Bool waiting_for_image_p; + +} gfluxstruct; +static gfluxstruct *gfluxes = NULL; + +/* prototypes */ +static void initLighting(void); +static void grabTexture(gfluxstruct *); +static void createTexture(gfluxstruct *); +static int displaySolid(gfluxstruct *); /* drawFunc implementations */ +static int displayLight(gfluxstruct *); +static int displayTexture(gfluxstruct *); +static int displayWire(gfluxstruct *); +static void calcGrid(gfluxstruct *); +static double getGrid(gfluxstruct *,double,double,double); + +/* as macro for speed */ +/* could do with colour cycling here */ +/* void genColour(double);*/ +#define genColour(X) \ +{\ + gp->colour[0] = 0.0;\ + gp->colour[1] = 0.5+0.5*(X);\ + gp->colour[2] = 0.5-0.5*(X);\ +} + +/* BEGINNING OF FUNCTIONS */ + + +ENTRYPOINT Bool +gflux_handle_event (ModeInfo *mi, XEvent *event) +{ + gfluxstruct *gp = &gfluxes[MI_SCREEN(mi)]; + + if (gltrackball_event_handler (event, gp->trackball, + MI_WIDTH (mi), MI_HEIGHT (mi), + &gp->button_down_p)) + return True; + else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) + { + if (_draw == grab) { + grabTexture(gp); + return True; + } + } + + return False; +} + + +static void +userRot(gfluxstruct *gp) +{ + gltrackball_rotate (gp->trackball); +} + +/* draw the gflux once */ +ENTRYPOINT void draw_gflux(ModeInfo * mi) +{ + gfluxstruct *gp = &gfluxes[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!gp->glx_context) return; + + /* Just keep running before the texture has come in. */ + /* if (gp->waiting_for_image_p) return; */ + + glXMakeCurrent(display, window, *(gp->glx_context)); + + calcGrid(gp); + mi->polygon_count = gp->drawFunc(gp); + if (mi->fps_p) do_fps (mi); + glXSwapBuffers(display, window); +} + + +/* Standard reshape function */ +ENTRYPOINT void +reshape_gflux(ModeInfo *mi, int width, int height) +{ + glViewport( 0, 0, width, height ); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-_zoom,_zoom,-0.8*_zoom,0.8*_zoom,2,6); + glTranslatef(0.0,0.0,-4.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + +# ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */ + { + GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi); + int o = (int) current_device_rotation(); + if (o != 0 && o != 180 && o != -180) + glScalef (1/h, 1/h, 1/h); + } +# endif +} + + +/* main OpenGL initialization routine */ +static void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) +{ + gfluxstruct *gp = &gfluxes[MI_SCREEN(mi)]; + + reshape_gflux(mi, width, height); + glViewport( 0, 0, width, height ); + + gp->tex_xscale = 1.0; /* maybe changed later */ + gp->tex_yscale = 1.0; + + switch(_draw) { + case solid : + gp->drawFunc = (displaySolid); + glEnable(GL_DEPTH_TEST); + break; + case light : + gp->drawFunc = (displayLight); + glEnable(GL_DEPTH_TEST); + initLighting(); + break; + case checker : + gp->drawFunc = (displayTexture); + glEnable(GL_DEPTH_TEST); + createTexture(gp); + initLighting(); + break; + case grab : + gp->drawFunc = (displayTexture); + glEnable(GL_DEPTH_TEST); + grabTexture(gp); + initLighting(); + break; + case wire : + default : + gp->drawFunc = (displayWire); + glDisable(GL_DEPTH_TEST); + break; + } + + if(_flat) glShadeModel(GL_FLAT); + else glShadeModel(GL_SMOOTH); + +} + + +/* xgflux initialization routine */ +ENTRYPOINT void init_gflux(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + gfluxstruct *gp; + + MI_INIT(mi, gfluxes); + gp = &gfluxes[screen]; + + gp->trackball = gltrackball_init (True); + + gp->time = frand(1000.0); /* don't run two screens in lockstep */ + + { + char *s = get_string_resource (mi->dpy, "mode", "Mode"); + if (!s || !*s) _draw = grab; + else if (!strcasecmp (s, "wire")) _draw = wire; + else if (!strcasecmp (s, "solid")) _draw = solid; + else if (!strcasecmp (s, "light")) _draw = light; + else if (!strcasecmp (s, "checker")) _draw = checker; + else if (!strcasecmp (s, "grab")) _draw = grab; + else + { + fprintf (stderr, + "%s: mode must be one of: wire, solid, " + "light, checker, or grab; not \"%s\"\n", + progname, s); + exit (1); + } + } + + gp->modeinfo = mi; + gp->window = MI_WINDOW(mi); + if ((gp->glx_context = init_GL(mi)) != NULL) { + reshape_gflux(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + initializeGL(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } +} + + +static void createTexture(gfluxstruct *gp) +{ + int size = 4; + unsigned int data[] = { 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, + 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, + 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, + 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF }; + + gp->tex_xscale = size; + gp->tex_yscale = size; + + glGenTextures (1, &gp->texName); + glBindTexture (GL_TEXTURE_2D, gp->texName); + + glTexImage2D (GL_TEXTURE_2D, 0, 3, size, size, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +} + + +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + gfluxstruct *gp = (gfluxstruct *) closure; + gp->img_geom = *geometry; + + gp->tex_xscale = (GLfloat) image_width / texture_width; + gp->tex_yscale = -(GLfloat) image_height / texture_height; + gp->img_width = image_width; + gp->img_height = image_height; + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (gp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)); + + gp->waiting_for_image_p = False; +} + +static void +grabTexture(gfluxstruct *gp) +{ + if (MI_IS_WIREFRAME(gp->modeinfo)) + return; + + gp->waiting_for_image_p = True; + gp->mipmap_p = True; + load_texture_async (gp->modeinfo->xgwa.screen, gp->modeinfo->window, + *gp->glx_context, 0, 0, gp->mipmap_p, gp->texName, + image_loaded_cb, gp); +} + + +static void initLighting(void) +{ + static const float ambientA[] = {0.0, 0.0, 0.0, 1.0}; + static const float diffuseA[] = {1.0, 1.0, 1.0, 1.0}; + static const float positionA[] = {5.0, 5.0, 15.0, 1.0}; + + static const float front_mat_shininess[] = {30.0}; + static const float front_mat_specular[] = {0.5, 0.5, 0.5, 1.0}; + + static const float mat_diffuse[] = {0.5, 0.5, 0.5, 1.0}; + + glMaterialfv(GL_FRONT, GL_SHININESS, front_mat_shininess); + glMaterialfv(GL_FRONT, GL_SPECULAR, front_mat_specular); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambientA); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseA); + glLightfv(GL_LIGHT0, GL_POSITION, positionA); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1); + + glEnable(GL_NORMALIZE); /* would it be faster ... */ + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); +} + +/************************************/ +/* draw implementations */ +/* somewhat inefficient since they */ +/* all calculate previously */ +/* calculated values again */ +/* storing the values in an array */ +/* is a posibility */ +/************************************/ +static int displayTexture(gfluxstruct *gp) +{ + int polys = 0; + double x,y,u,v; + double z; + double dx = 2.0/((double)_squares); + double dy = 2.0/((double)_squares); + + double du = 2.0/((double)_squares); + double dv = 2.0/((double)_squares); + + double xs = gp->tex_xscale; + double ys = gp->tex_yscale; + + double minx, miny, maxx, maxy; + double minu, minv; + +#if 0 + minx = (GLfloat) gp->img_geom.x / gp->img_width; + miny = (GLfloat) gp->img_geom.y / gp->img_height; + maxx = ((GLfloat) (gp->img_geom.x + gp->img_geom.width) / + gp->img_width); + maxy = ((GLfloat) (gp->img_geom.y + gp->img_geom.height) / + gp->img_height); + minu = minx; + minv = miny; + minx = (minx * 2) - 1; + miny = (miny * 2) - 1; + maxx = (maxx * 2) - 1; + maxy = (maxy * 2) - 1; +#else + minx = -1; + miny = -1; + maxx = 1; + maxy = 1; + minv = 0; + minu = 0; +#endif + + glMatrixMode (GL_TEXTURE); + glLoadIdentity (); + glTranslatef(-1,-1,0); + glScalef(0.5,0.5,1); + glMatrixMode (GL_MODELVIEW); + + glLoadIdentity(); + userRot(gp); + glRotatef(gp->anglex,1,0,0); + glRotatef(gp->angley,0,1,0); + glRotatef(gp->anglez,0,0,1); + glScalef(1,1,(GLfloat)_waveHeight); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glEnable(GL_TEXTURE_2D); + + clear_gl_error(); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBindTexture(GL_TEXTURE_2D, gp->texName); + check_gl_error("texture binding"); + + glColor3f(0.5,0.5,0.5); + + for(x = minx, u = minu; x < maxx - 0.01; x += dx, u += du) { + glBegin(GL_QUAD_STRIP); + for (y = miny, v = minv; y <= maxy + 0.01; y += dy, v += dv) { + z = getGrid(gp,x,y,gp->time); + glTexCoord2f(u*xs,v*ys); + glNormal3f( + getGrid(gp,x+dx,y,gp->time)-getGrid(gp, x-dx,y,gp->time), + getGrid(gp,x,y+dy,gp->time)-getGrid(gp, x,y-dy,gp->time), + 1 + ); + glVertex3f(x,y,z); + + z = getGrid(gp,x+dx,y,gp->time); + glTexCoord2f((u+du)*xs,v*ys); + glNormal3f( + getGrid(gp,x+dx+dx,y,gp->time)-getGrid(gp, x,y,gp->time), + getGrid(gp,x+dx,y+dy,gp->time)-getGrid(gp, x+dx,y-dy,gp->time), + 1 + ); + glVertex3f(x+dx,y,z); + polys++; + } + glEnd(); + } + + /* Draw a border around the grid. + */ + glColor3f(0.4, 0.4, 0.4); + glDisable(GL_TEXTURE_2D); + glEnable (GL_LINE_SMOOTH); + + glBegin(GL_LINE_LOOP); + y = miny; + for (x = minx; x <= maxx; x += dx) { + glVertex3f (x, y, getGrid (gp, x, y, gp->time)); + polys++; + } + x = maxx; + for (y = miny; y <= maxy; y += dy) { + glVertex3f (x, y, getGrid (gp, x, y, gp->time)); + polys++; + } + y = maxy; + for (x = maxx; x >= minx; x -= dx) { + glVertex3f (x, y, getGrid (gp, x, y, gp->time)); + polys++; + } + x = minx; + for (y = maxy; y >= miny; y -= dy) { + glVertex3f (x, y, getGrid (gp, x, y, gp->time)); + polys++; + } + glEnd(); + glEnable(GL_TEXTURE_2D); + + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + return polys; +} + +static int displaySolid(gfluxstruct *gp) +{ + int polys = 0; + double x,y; + double z; + double dx = 2.0/((double)_squares); + double dy = 2.0/((double)_squares); + + glLoadIdentity(); + glRotatef(gp->anglex,1,0,0); + glRotatef(gp->angley,0,1,0); + glRotatef(gp->anglez,0,0,1); + userRot(gp); + glScalef(1,1,(GLfloat)_waveHeight); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + for(x=-1;x<0.9999;x+=dx) { + glBegin(GL_QUAD_STRIP); + for(y=-1;y<=1;y+=dy) { + z = getGrid(gp, x,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glVertex3f(x,y,z); + + z = getGrid(gp, x+dx,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glVertex3f(x+dx,y,z); + polys++; + } + glEnd(); + } + + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + + return polys; +} + +static int displayLight(gfluxstruct *gp) +{ + int polys = 0; + double x,y; + double z; + double dx = 2.0/((double)_squares); + double dy = 2.0/((double)_squares); + + glLoadIdentity(); + glRotatef(gp->anglex,1,0,0); + glRotatef(gp->angley,0,1,0); + glRotatef(gp->anglez,0,0,1); + userRot(gp); + glScalef(1,1,(GLfloat)_waveHeight); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + for(x=-1;x<0.9999;x+=dx) { + glBegin(GL_QUAD_STRIP); + for(y=-1;y<=1;y+=dy) { + z = getGrid(gp, x,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glNormal3f( + getGrid(gp, x+dx,y,gp->time)-getGrid(gp, x-dx,y,gp->time), + getGrid(gp, x,y+dy,gp->time)-getGrid(gp, x,y-dy,gp->time), + 1 + ); + glVertex3f(x,y,z); + + z = getGrid(gp, x+dx,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glNormal3f( + getGrid(gp, x+dx+dx,y,gp->time)-getGrid(gp, x,y,gp->time), + getGrid(gp, x+dx,y+dy,gp->time)-getGrid(gp, x+dx,y-dy,gp->time), + 1 + ); + glVertex3f(x+dx,y,z); + polys++; + } + glEnd(); + } + + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + return polys; +} + +static int displayWire(gfluxstruct *gp) +{ + int polys = 0; + double x,y; + double z; + double dx1 = 2.0/((double)(_squares*_resolution)) - 0.00001; + double dy1 = 2.0/((double)(_squares*_resolution)) - 0.00001; + double dx2 = 2.0/((double)_squares) - 0.00001; + double dy2 = 2.0/((double)_squares) - 0.00001; + + glLoadIdentity(); + glRotatef(gp->anglex,1,0,0); + glRotatef(gp->angley,0,1,0); + glRotatef(gp->anglez,0,0,1); + userRot(gp); + glScalef(1,1,(GLfloat)_waveHeight); + glClear(GL_COLOR_BUFFER_BIT); + + for(x=-1;x<=1;x+=dx2) { + glBegin(GL_LINE_STRIP); + for(y=-1;y<=1;y+=dy1) { + z = getGrid(gp, x,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glVertex3f(x,y,z); + polys++; + } + glEnd(); + } + for(y=-1;y<=1;y+=dy2) { + glBegin(GL_LINE_STRIP); + for(x=-1;x<=1;x+=dx1) { + z = getGrid(gp, x,y,gp->time); + genColour(z); + glColor3fv(gp->colour); + glVertex3f(x,y,z); + polys++; + } + glEnd(); + } + + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + return polys; +} + +/* generates new ripples */ +static void calcGrid(gfluxstruct *gp) +{ + double tmp; + + if (gp->button_down_p) return; + + tmp = 1.0/((double)_waveChange); + if(!(gp->counter%_waveChange)) { + gp->newWave = ((int)(gp->counter*tmp))%_waves; + gp->dispx[gp->newWave] = -frand(1.0); + gp->dispy[gp->newWave] = -frand(1.0); + gp->freq[gp->newWave] = _waveFreq * frand(1.0); + gp->wa[gp->newWave] = 0.0; + } + gp->counter++; + gp->wa[gp->newWave] += tmp; + gp->wa[(gp->newWave+1)%_waves] -= tmp; +} + +/* returns a height for the grid given time and x,y space co-ords */ +static double getGrid(gfluxstruct *gp, double x, double y, double a) +{ + register int i; + double retval=0.0; + double tmp; + + tmp = 1.0/((float)_waves); + for(i=0;i<_waves;i++) { + retval += gp->wa[i] * tmp * sin( gp->freq[i] + * ( (x+gp->dispx[i]) * (x+gp->dispx[i]) + + (y+gp->dispy[i]) * (y+gp->dispy[i]) +a ) ); + } + return(retval); +} + + +XSCREENSAVER_MODULE ("GFlux", gflux) + +#endif -- cgit v1.2.3-55-g7522