X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fgflux.c;h=69636f276d18f9a8f436f8b0978565addfda9426;hp=f45e9ed7f4ab8b3b36a6e218b1ee9a7a720a0d3f;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hpb=4cecfc89e5e889c7232693897c06168fb378bd5c diff --git a/hacks/glx/gflux.c b/hacks/glx/gflux.c index f45e9ed7..69636f27 100644 --- a/hacks/glx/gflux.c +++ b/hacks/glx/gflux.c @@ -2,7 +2,7 @@ /* gflux - creates a fluctuating 3D grid * requires OpenGL or MesaGL * - * Copyright (c) Josiah Pease, 2000 + * 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 @@ -39,37 +39,15 @@ */ -/*- - * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock. - * otherwise caddr_t is not defined correctly - */ - -#include - - #ifdef STANDALONE -# define PROGCLASS "gflux" -# define HACK_INIT init_gflux -# define HACK_DRAW draw_gflux -# define HACK_RESHAPE reshape_gflux -# define gflux_opts xlockmore_opts -#define DEFAULTS "*delay: 20000 \n" \ - "*showFPS: False \n" \ - "*mode: light" "\n" \ - "*squares: 19 \n" \ - "*resolution: 0 \n" \ - "*flat: 0 \n" \ - "*speed: 0.05 \n" \ - "*rotationx: 0.01 \n" \ - "*rotationy: 0.0 \n" \ - "*rotationz: 0.1 \n" \ - "*waves: 3 \n" \ - "*waveChange: 50 \n" \ - "*waveHeight: 0.8 \n" \ - "*waveFreq: 3.0 \n" \ - "*zoom: 1.0 \n" - - +#define DEFAULTS "*delay: 20000\n" \ + "*showFPS: False\n" \ + "*mode: grab\n" \ + "*useSHM: True \n" \ + "*suppressRotationAnimation: True\n" \ + +# define refresh_gflux 0 +# define release_gflux 0 # include "xlockmore.h" /* from the xscreensaver distribution */ #else /* !STANDALONE */ # include "xlock.h" /* from the xlockmore distribution */ @@ -85,76 +63,88 @@ # endif /* VMS */ #endif -#ifdef HAVE_PPM -#include -#endif - #undef countof #define countof(x) (sizeof((x))/sizeof((*x))) #include #include -#include -#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 enum {wire=0,solid,light,checker,textured,grab} _draw; /* draw style */ -static int _squares = 19; /* grid size */ -static int _resolution = 4; /* wireframe resolution */ -static int _flat = 0; -static float _speed = 0.05; -static float _rotationx = 0.01; -static float _rotationy = 0.0; -static float _rotationz = 0.1; -static float _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; -static int _waves = 3; -static int _waveChange = 50; -static float _waveHeight = 1.0; -static float _waveFreq = 3.0; #define WIDTH 320 #define HEIGHT 240 static XrmOptionDescRec opts[] = { - {"-squares", ".gflux.squares", XrmoptionSepArg, (caddr_t) NULL}, - {"-resolution", ".gflux.resolution", XrmoptionSepArg, (caddr_t) NULL}, -/* {"-draw", ".gflux.draw", XrmoptionSepArg, (caddr_t) NULL},*/ - {"-mode", ".gflux.mode", XrmoptionSepArg, (caddr_t) NULL}, - {"-flat", ".gflux.flat", XrmoptionSepArg, (caddr_t) NULL}, - {"-speed", ".gflux.speed", XrmoptionSepArg, (caddr_t) NULL}, - {"-rotationx", ".gflux.rotationx", XrmoptionSepArg, (caddr_t) NULL}, - {"-rotationy", ".gflux.rotationy", XrmoptionSepArg, (caddr_t) NULL}, - {"-rotationz", ".gflux.rotationz", XrmoptionSepArg, (caddr_t) NULL}, - {"-waves", ".gflux.waves", XrmoptionSepArg, (caddr_t) NULL}, - {"-waveChange", ".gflux.waveChange", XrmoptionSepArg, (caddr_t) NULL}, - {"-waveHeight", ".gflux.waveHeight", XrmoptionSepArg, (caddr_t) NULL}, - {"-waveFreq", ".gflux.waveFreq", XrmoptionSepArg, (caddr_t) NULL}, - {"-zoom", ".gflux.zoom", XrmoptionSepArg, (caddr_t) NULL}, + {"-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[] = { - {(caddr_t *) & _squares, "squares", "Squares", "19", t_Int}, - {(caddr_t *) & _resolution, "resolution", "Resolution", "4", t_Int}, -/* {(caddr_t *) & _draw, "draw", "Draw", "2", t_Int},*/ - {(caddr_t *) & _flat, "flat", "Flat", "0", t_Int}, - {(caddr_t *) & _speed, "speed", "Speed", "0.05", t_Float}, - {(caddr_t *) & _rotationx, "rotationx", "Rotationx", "0.01", t_Float}, - {(caddr_t *) & _rotationy, "rotationy", "Rotationy", "0.0", t_Float}, - {(caddr_t *) & _rotationz, "rotationz", "Rotationz", "0.1", t_Float}, - {(caddr_t *) & _waves, "waves", "Waves", "3", t_Int}, - {(caddr_t *) & _waveChange, "waveChange", "WaveChange", "50", t_Int}, - {(caddr_t *) & _waveHeight, "waveHeight", "WaveHeight", "1.0", t_Float}, - {(caddr_t *) & _waveFreq, "waveFreq", "WaveFreq", "3.0", t_Float}, - {(caddr_t *) & _zoom, "zoom", "Zoom", "1.0", t_Float}, + {&_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}, }; @@ -175,18 +165,18 @@ static OptionStruct desc[] = {"-zoom num", "camera control (1.0)"}, }; -ModeSpecOpt gflux_opts = {countof(opts), opts, countof(vars), vars, desc}; +ENTRYPOINT ModeSpecOpt gflux_opts = {countof(opts), opts, countof(vars), vars, desc}; #ifdef USE_MODULES ModStruct gflux_description = -{"gflux", "init_gflux", "draw_gflux", "release_gflux", +{"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}; + "GFlux: an OpenGL gflux", 0, NULL}; #endif /* structure for holding the gflux data */ -typedef struct { +typedef struct gfluxstruct { ModeInfo *modeinfo; int screen_width, screen_height; GLXContext *glx_context; @@ -198,128 +188,161 @@ typedef struct { double dispy[MAXWAVES]; double dispx[MAXWAVES]; GLfloat colour[3]; - int imageWidth; - int imageHeight; -#ifdef HAVE_PPM - pixval imageMax; - pixel **image; -#else - int imageMax; - GLubyte *image; -#endif - GLint texName; + GLuint texName; GLfloat tex_xscale; GLfloat tex_yscale; - void (*drawFunc)(void); + 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 *gflux = NULL; +static gfluxstruct *gfluxes = NULL; /* prototypes */ -void initLighting(void); -void initTexture(void); -void loadTexture(void); -void grabTexture(void); -void createTexture(void); -void displaySolid(void); /* drawFunc implementations */ -void displayLight(void); -void displayTexture(void); -void displayWire(void); -void calcGrid(void); -double getGrid(double,double,double); +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) \ {\ - gflux->colour[0] = 0.0;\ - gflux->colour[1] = 0.5+0.5*(X);\ - gflux->colour[2] = 0.5-0.5*(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 */ -void draw_gflux(ModeInfo * mi) +ENTRYPOINT void draw_gflux(ModeInfo * mi) { - gfluxstruct *gp = &gflux[MI_SCREEN(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(); - gflux->drawFunc(); + calcGrid(gp); + mi->polygon_count = gp->drawFunc(gp); if (mi->fps_p) do_fps (mi); glXSwapBuffers(display, window); } -/* reset the projection matrix */ -void resetProjection(void) { +/* 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(); -} -/* Standard reshape function */ -void -reshape_gflux(ModeInfo *mi, int width, int height) -{ - glViewport( 0, 0, width, height ); - resetProjection(); +# 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 */ -void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) +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 ); - gflux->tex_xscale = 1.0; /* maybe changed later */ - gflux->tex_yscale = 1.0; + gp->tex_xscale = 1.0; /* maybe changed later */ + gp->tex_yscale = 1.0; switch(_draw) { case solid : - gflux->drawFunc = (displaySolid); + gp->drawFunc = (displaySolid); glEnable(GL_DEPTH_TEST); break; case light : - gflux->drawFunc = (displayLight); + gp->drawFunc = (displayLight); glEnable(GL_DEPTH_TEST); initLighting(); break; case checker : - gflux->drawFunc = (displayTexture); + gp->drawFunc = (displayTexture); glEnable(GL_DEPTH_TEST); - createTexture(); - initTexture(); - initLighting(); - break; - case textured : - gflux->drawFunc = (displayTexture); - glEnable(GL_DEPTH_TEST); - loadTexture(); - initTexture(); + createTexture(gp); initLighting(); break; case grab : - gflux->drawFunc = (displayTexture); + gp->drawFunc = (displayTexture); glEnable(GL_DEPTH_TEST); - grabTexture(); - initTexture(); + grabTexture(gp); initLighting(); break; case wire : default : - gflux->drawFunc = (displayWire); + gp->drawFunc = (displayWire); glDisable(GL_DEPTH_TEST); break; } @@ -331,26 +354,25 @@ void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) /* xgflux initialization routine */ -void init_gflux(ModeInfo * mi) +ENTRYPOINT void init_gflux(ModeInfo * mi) { int screen = MI_SCREEN(mi); gfluxstruct *gp; - if (gflux == NULL) { - if ((gflux = (gfluxstruct *) - calloc(MI_NUM_SCREENS(mi), sizeof (gfluxstruct))) == NULL) - return; - } - gp = &gflux[screen]; + MI_INIT(mi, gfluxes, NULL); + 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 ("mode", "Mode"); - if (!s || !*s) _draw = wire; + 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, "stdin")) _draw = textured; else if (!strcasecmp (s, "grab")) _draw = grab; else { @@ -372,297 +394,77 @@ void init_gflux(ModeInfo * mi) } } -/* cleanup code */ -void release_gflux(ModeInfo * mi) -{ - if(gflux->image!=NULL) free(gflux->image); - if(gflux->glx_context!=NULL) free(gflux->glx_context); - if (gflux != NULL) { - (void) free((void *) gflux); - gflux = NULL; - } - FreeAllGL(mi); -} - -#ifdef HAVE_PPM - -/* load pnm from stdin using pnm libs */ -void loadTexture(void) -{ - FILE *file = stdin; - gflux->image = ppm_readppm( file, - &(gflux->imageHeight), &(gflux->imageWidth), &(gflux->imageMax) ); -} -/* creates an image for texture mapping */ -void createTexture(void) +static void createTexture(gfluxstruct *gp) { - int i,j,c; - pixel **result; - - gflux->imageHeight = gflux->imageWidth = 8; + int size = 4; + unsigned int data[] = { 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, + 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, + 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, + 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0xFFFFFFFF }; - result = ppm_allocarray(gflux->imageHeight,gflux->imageWidth); - for(i=0;iimageHeight;i++) { - for(j=0;jimageWidth;j++) { - c = (((i)%2 ^ (j)%2) ? 100 : 200 ); - PPM_ASSIGN( result[i][j] , c, c, c ); - } - } - gflux->image = result; -} + gp->tex_xscale = size; + gp->tex_yscale = size; -/* specifies image as texture */ -void initTexture(void) -{ - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glGenTextures(1, &gflux->texName); - glBindTexture(GL_TEXTURE_2D, gflux->texName); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glGenTextures (1, &gp->texName); + glBindTexture (GL_TEXTURE_2D, gp->texName); - clear_gl_error(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, gflux->imageWidth, - gflux->imageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, *(gflux->image)); - check_gl_error("texture"); -} + glTexImage2D (GL_TEXTURE_2D, 0, 3, size, size, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); -#else /* HAVE_PPM FALSE */ + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); -#define presult(A,B,C) (*(result+(A)*(gflux->imageWidth)*4+(B)*4+(C))) -void loadTexture(void) -{ - int i, j, levels, width, height; - int red,green,blue; - char s[4]; - int ppmType=0; - FILE *file = stdin; - GLubyte *result; - - fgets(s,4,file); - - if(!strncmp(s,"P6",2)) ppmType=6; - if(!strncmp(s,"P5",2)) ppmType=5; - if(!strncmp(s,"P3",2)) ppmType=3; - if(!strncmp(s,"P2",2)) ppmType=2; - if(!ppmType)exit(1); - - while((i=getc(file))=='#') - { - while(getc(file)!='\n'); - } - ungetc(i,file); - - fscanf(file,"%d %d %d",&width,&height,&levels); - - result = malloc(sizeof(GLubyte)*4*width*height); - gflux->imageWidth = width; - gflux->imageHeight = height; - - switch(ppmType) { - case 2 : /* ASCII grey */ - for(i=0;iimage = result; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } -void createTexture(void) -{ - int i,j,c; - GLubyte *result; - - gflux->imageHeight = gflux->imageWidth = 8; - - result = malloc(sizeof(GLubyte)*4*gflux->imageHeight*gflux->imageWidth); - for(i=0;iimageHeight;i++) { - for(j=0;jimageWidth;j++) { - c = (((i)%2 ^ (j)%2) ? 100 : 200 ); - presult(i,j,0) = (GLubyte) c; - presult(i,j,1) = (GLubyte) c; - presult(i,j,2) = (GLubyte) c; - presult(i,j,3) = (GLubyte) 255; - } - } - gflux->image = result; -} -/* specifies image as texture */ -void initTexture(void) +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) { - clear_gl_error(); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glGenTextures(1, &gflux->texName); - glBindTexture(GL_TEXTURE_2D, gflux->texName); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - check_gl_error("texture parameter"); - - /* Bail out if the texture is too large. */ - { - GLint width; - glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, gflux->imageWidth, - gflux->imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, - GL_TEXTURE_WIDTH, &width); - if (width <= 0) - { - glGetIntegerv (GL_MAX_TEXTURE_SIZE, &width); - fprintf (stderr, - "%s: texture too large (%dx%d -- probable max %dx%d)\n", - progname, gflux->imageWidth, gflux->imageHeight, - width, width); - return; - } - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gflux->imageWidth, - gflux->imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, gflux->image); - check_gl_error("texture creation"); + 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; } -#undef presult -#endif - - -void -grabTexture(void) +static void +grabTexture(gfluxstruct *gp) { - int real_width = gflux->modeinfo->xgwa.width; - int real_height = gflux->modeinfo->xgwa.height; - XImage *ximage = screen_to_ximage (gflux->modeinfo->xgwa.screen, - gflux->window); - Bool bigimage = False; - int size = 0; - - if (ximage->width > 1280 || /* that's too damned big... */ - ximage->height > 1280) - { - Display *dpy = gflux->modeinfo->dpy; - Visual *v = gflux->modeinfo->xgwa.visual; - int real_size = (ximage->width < ximage->height ? - real_width : real_height); - XImage *x2; - int x, y, xoff, yoff; - size = (ximage->width < ximage->height ? - ximage->width : ximage->height); - bigimage = True; - - if (size > 1024) size = 1024; - - x2 = XCreateImage (dpy, v, 32, ZPixmap, 0, 0, size, size, 32, 0); - xoff = (real_width > size ? (random() % (real_width - size)) : 0); - yoff = (real_height > size ? (random() % (real_height - size)) : 0); - -# if 0 - fprintf(stderr, "%s: cropping texture from %dx%d to %dx%d @ %d,%d\n", - progname, ximage->width, ximage->height, x2->width, x2->height, - xoff, yoff); -# endif - x2->data = ximage->data; /* we can reuse the same array */ - for (y = 0; y < x2->height; y++) - for (x = 0; x < x2->width; x++) - XPutPixel (x2, x, y, XGetPixel (ximage, x+xoff, y+yoff)); - - real_width = real_height = real_size; - ximage->data = 0; - XDestroyImage (ximage); - ximage = x2; - } - - /* Add a border. */ - { - unsigned long gray = 0xAAAAAAAAL; /* so shoot me */ - int width = (bigimage ? size : real_width); - int height = (bigimage ? size : real_height); - int i; - for (i = 0; i < real_height; i++) - { - XPutPixel (ximage, 0, i, gray); - XPutPixel (ximage, width-1, i, gray); - } - for (i = 0; i < real_width; i++) - { - XPutPixel (ximage, i, 0, gray); - XPutPixel (ximage, i, height-1, gray); - } - } - - gflux->imageWidth = ximage->width; - gflux->imageHeight = ximage->height; - gflux->image = ximage->data; - - if (bigimage) /* don't scale really large images */ - { - gflux->tex_xscale = 1; - gflux->tex_yscale = 1; - } - else - { - gflux->tex_xscale = ((GLfloat) real_width / (GLfloat) ximage->width); - gflux->tex_yscale = ((GLfloat) real_height / (GLfloat) ximage->height); - } - - ximage->data = 0; - XDestroyImage (ximage); + 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); } -void initLighting(void) +static void initLighting(void) { - static float ambientA[] = {0.0, 0.0, 0.0, 1.0}; - static float diffuseA[] = {1.0, 1.0, 1.0, 1.0}; - static float positionA[] = {5.0, 5.0, 15.0, 1.0}; + 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 float front_mat_shininess[] = {30.0}; - static float front_mat_specular[] = {0.5, 0.5, 0.5, 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 float mat_diffuse[] = {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); @@ -689,13 +491,9 @@ void initLighting(void) /* storing the values in an array */ /* is a posibility */ /************************************/ -void displayTexture(void) +static int displayTexture(gfluxstruct *gp) { - static double time = 0.0; - static double anglex = 0.0; - static double angley = 0.0; - static double anglez = 0.0; - + int polys = 0; double x,y,u,v; double z; double dx = 2.0/((double)_squares); @@ -704,8 +502,33 @@ void displayTexture(void) double du = 2.0/((double)_squares); double dv = 2.0/((double)_squares); - double xs = gflux->tex_xscale; - double ys = gflux->tex_yscale; + 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 (); @@ -714,153 +537,183 @@ void displayTexture(void) glMatrixMode (GL_MODELVIEW); glLoadIdentity(); - glRotatef(anglex,1,0,0); - glRotatef(angley,0,1,0); - glRotatef(anglez,0,0,1); + 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, gflux->texName); + glBindTexture(GL_TEXTURE_2D, gp->texName); check_gl_error("texture binding"); glColor3f(0.5,0.5,0.5); - for(x=-1,u= 0;x<0.9999;x+=dx,u+=du) { + for(x = minx, u = minu; x < maxx - 0.01; x += dx, u += du) { glBegin(GL_QUAD_STRIP); - for(y=-1,v= 0;y<=1;y+=dy,v+=dv) { - z = getGrid(x,y,time); - /* genColour(z); - glColor3fv(gflux->colour); - */ glTexCoord2f(u*xs,v*ys); + 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(x+dx,y,time)-getGrid(x-dx,y,time), - getGrid(x,y+dy,time)-getGrid(x,y-dy,time), + 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(x+dx,y,time); - /* genColour(z); - glColor3fv(gflux->colour); - */ glTexCoord2f((u+du)*xs,v*ys); + z = getGrid(gp,x+dx,y,gp->time); + glTexCoord2f((u+du)*xs,v*ys); glNormal3f( - getGrid(x+dx+dx,y,time)-getGrid(x,y,time), - getGrid(x+dx,y+dy,time)-getGrid(x+dx,y-dy,time), + 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(); } - time -= _speed; - anglex -= _rotationx; - angley -= _rotationy; - anglez -= _rotationz; + /* 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; } -void displaySolid(void) -{ - static double time = 0.0; - static double anglex = 0.0; - static double angley = 0.0; - static double anglez = 0.0; +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(anglex,1,0,0); - glRotatef(angley,0,1,0); - glRotatef(anglez,0,0,1); + 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(x,y,time); + z = getGrid(gp, x,y,gp->time); genColour(z); - glColor3fv(gflux->colour); + glColor3fv(gp->colour); glVertex3f(x,y,z); - z = getGrid(x+dx,y,time); + z = getGrid(gp, x+dx,y,gp->time); genColour(z); - glColor3fv(gflux->colour); + glColor3fv(gp->colour); glVertex3f(x+dx,y,z); + polys++; } glEnd(); } - time -= _speed; - anglex -= _rotationx; - angley -= _rotationy; - anglez -= _rotationz; + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + return polys; } -void displayLight(void) +static int displayLight(gfluxstruct *gp) { - static double time = 0.0; - static double anglex = 0.0; - static double angley = 0.0; - static double anglez = 0.0; - + int polys = 0; double x,y; double z; double dx = 2.0/((double)_squares); double dy = 2.0/((double)_squares); glLoadIdentity(); - glRotatef(anglex,1,0,0); - glRotatef(angley,0,1,0); - glRotatef(anglez,0,0,1); + 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(x,y,time); + z = getGrid(gp, x,y,gp->time); genColour(z); - glColor3fv(gflux->colour); + glColor3fv(gp->colour); glNormal3f( - getGrid(x+dx,y,time)-getGrid(x-dx,y,time), - getGrid(x,y+dy,time)-getGrid(x,y-dy,time), + 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(x+dx,y,time); + z = getGrid(gp, x+dx,y,gp->time); genColour(z); - glColor3fv(gflux->colour); + glColor3fv(gp->colour); glNormal3f( - getGrid(x+dx+dx,y,time)-getGrid(x,y,time), - getGrid(x+dx,y+dy,time)-getGrid(x+dx,y-dy,time), + 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(); } - time -= _speed; - anglex -= _rotationx; - angley -= _rotationy; - anglez -= _rotationz; + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + return polys; } -void displayWire(void) +static int displayWire(gfluxstruct *gp) { - static double time = 0.0; - static double anglex = 0.0; - static double angley = 0.0; - static double anglez = 0.0; - + int polys = 0; double x,y; double z; double dx1 = 2.0/((double)(_squares*_resolution)) - 0.00001; @@ -869,61 +722,67 @@ void displayWire(void) double dy2 = 2.0/((double)_squares) - 0.00001; glLoadIdentity(); - glRotatef(anglex,1,0,0); - glRotatef(angley,0,1,0); - glRotatef(anglez,0,0,1); + 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(x,y,time); + z = getGrid(gp, x,y,gp->time); genColour(z); - glColor3fv(gflux->colour); + 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(x,y,time); + z = getGrid(gp, x,y,gp->time); genColour(z); - glColor3fv(gflux->colour); + glColor3fv(gp->colour); glVertex3f(x,y,z); + polys++; } glEnd(); } - time -= _speed; - anglex -= _rotationx; - angley -= _rotationy; - anglez -= _rotationz; + if (! gp->button_down_p) { + gp->time -= _speed; + gp->anglex -= _rotationx; + gp->angley -= _rotationy; + gp->anglez -= _rotationz; + } + return polys; } /* generates new ripples */ -void calcGrid(void) +static void calcGrid(gfluxstruct *gp) { - static int counter=0; double tmp; - static int newWave; + + if (gp->button_down_p) return; tmp = 1.0/((double)_waveChange); - if(!(counter%_waveChange)) { - newWave = ((int)(counter*tmp))%_waves; - gflux->dispx[newWave] = -frand(1.0); - gflux->dispy[newWave] = -frand(1.0); - gflux->freq[newWave] = _waveFreq * frand(1.0); - gflux->wa[newWave] = 0.0; + 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; } - counter++; - gflux->wa[newWave] += tmp; - gflux->wa[(newWave+1)%_waves] -= tmp; + 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 */ -double getGrid(double x, double y, double a) +static double getGrid(gfluxstruct *gp, double x, double y, double a) { register int i; double retval=0.0; @@ -931,12 +790,14 @@ double getGrid(double x, double y, double a) tmp = 1.0/((float)_waves); for(i=0;i<_waves;i++) { - retval += gflux->wa[i] * tmp * sin( gflux->freq[i] - * ( (x+gflux->dispx[i]) * (x+gflux->dispx[i]) - + (y+gflux->dispy[i]) * (y+gflux->dispy[i]) +a ) ); + 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); } -#endif +XSCREENSAVER_MODULE ("GFlux", gflux) + +#endif