X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fgflux.c;h=51aa59778b31c20fecd18daba5bc961b8045cbc4;hp=23fce87c78301571bcdde8ecfbd8311e377ffeca;hb=ffd8c0873576a9e3065696a624dce6b766b77062;hpb=3d9140a05b5272fed0883a0af0a71e30ef44d47f diff --git a/hacks/glx/gflux.c b/hacks/glx/gflux.c index 23fce87c..51aa5977 100644 --- a/hacks/glx/gflux.c +++ b/hacks/glx/gflux.c @@ -1,9 +1,8 @@ /* -*- Mode: C; tab-width: 4 -*- emacs friendly */ - /* 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 @@ -34,28 +33,25 @@ * 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 */ -/*- - * 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 HACK_HANDLE_EVENT gflux_handle_event +# define EVENT_MASK PointerMotionMask # define gflux_opts xlockmore_opts #define DEFAULTS "*delay: 20000 \n" \ "*showFPS: False \n" \ + "*mode: light" "\n" \ "*squares: 19 \n" \ "*resolution: 0 \n" \ - "*draw: 0 \n" \ "*flat: 0 \n" \ "*speed: 0.05 \n" \ "*rotationx: 0.01 \n" \ @@ -63,9 +59,9 @@ "*rotationz: 0.1 \n" \ "*waves: 3 \n" \ "*waveChange: 50 \n" \ - "*waveHeight: 1.0 \n" \ - "*waveFreq: 3.0 \n" \ - "*zoom: 1.0 \n" + "*waveHeight: 0.8 \n" \ + "*waveFreq: 3.0 \n" \ + "*zoom: 1.0 \n" # include "xlockmore.h" /* from the xscreensaver distribution */ @@ -75,13 +71,6 @@ #ifdef USE_GL /* whole file */ -#ifdef HAVE_XPM -# include -# ifndef PIXEL_ALREADY_TYPEDEFED -# define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */ -# endif -#endif - #ifdef HAVE_XMU # ifndef VMS # include @@ -90,6 +79,10 @@ # endif /* VMS */ #endif +#ifdef HAVE_PPM +#include +#endif + #undef countof #define countof(x) (sizeof((x))/sizeof((*x))) @@ -102,7 +95,11 @@ #include -static enum {wire=0,solid,light,checker,textured} _draw; /* draw style */ +#include "grab-ximage.h" +#include "gltrackball.h" + + +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; @@ -118,40 +115,44 @@ static int _waveChange = 50; static float _waveHeight = 1.0; static float _waveFreq = 3.0; +static trackball_state *trackball; +static Bool button_down_p = False; + #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}, - {"-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}, + {"-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", "0", 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", "19", t_Int}, + {&_resolution, "resolution", "Resolution", "4", t_Int}, +/* {&_draw, "draw", "Draw", "2", t_Int},*/ + {&_flat, "flat", "Flat", "0", t_Int}, + {&_speed, "speed", "Speed", "0.05", t_Float}, + {&_rotationx, "rotationx", "Rotationx", "0.01", t_Float}, + {&_rotationy, "rotationy", "Rotationy", "0.0", t_Float}, + {&_rotationz, "rotationz", "Rotationz", "0.1", t_Float}, + {&_waves, "waves", "Waves", "3", t_Int}, + {&_waveChange, "waveChange", "WaveChange", "50", t_Int}, + {&_waveHeight, "waveHeight", "WaveHeight", "1.0", t_Float}, + {&_waveFreq, "waveFreq", "WaveFreq", "3.0", t_Float}, + {&_zoom, "zoom", "Zoom", "1.0", t_Float}, }; @@ -159,7 +160,7 @@ 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)"}, +/* {"-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)"}, @@ -184,6 +185,7 @@ ModStruct gflux_description = /* structure for holding the gflux data */ typedef struct { + ModeInfo *modeinfo; int screen_width, screen_height; GLXContext *glx_context; Window window; @@ -196,8 +198,16 @@ typedef struct { GLfloat colour[3]; int imageWidth; int imageHeight; - GLubyte *image; +#ifdef HAVE_PPM + pixval imageMax; + pixel **image; +#else + int imageMax; + GLubyte *image; +#endif GLuint texName; + GLfloat tex_xscale; + GLfloat tex_yscale; void (*drawFunc)(void); } gfluxstruct; static gfluxstruct *gflux = NULL; @@ -206,6 +216,7 @@ static gfluxstruct *gflux = NULL; void initLighting(void); void initTexture(void); void loadTexture(void); +void grabTexture(void); void createTexture(void); void displaySolid(void); /* drawFunc implementations */ void displayLight(void); @@ -227,6 +238,43 @@ double getGrid(double,double,double); /* BEGINNING OF FUNCTIONS */ +Bool +gflux_handle_event (ModeInfo *mi, XEvent *event) +{ + if (event->xany.type == ButtonPress && + event->xbutton.button & Button1) + { + button_down_p = True; + gltrackball_start (trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button & Button1) + { + button_down_p = False; + return True; + } + else if (event->xany.type == MotionNotify && + button_down_p) + { + gltrackball_track (trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + +static void +userRot(void) +{ + gltrackball_rotate (trackball); +} + /* draw the gflux once */ void draw_gflux(ModeInfo * mi) { @@ -269,6 +317,10 @@ void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) { reshape_gflux(mi, width, height); glViewport( 0, 0, width, height ); + + gflux->tex_xscale = 1.0; /* maybe changed later */ + gflux->tex_yscale = 1.0; + switch(_draw) { case solid : gflux->drawFunc = (displaySolid); @@ -292,6 +344,13 @@ void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) loadTexture(); initTexture(); initLighting(); + break; + case grab : + gflux->drawFunc = (displayTexture); + glEnable(GL_DEPTH_TEST); + grabTexture(); + initTexture(); + initLighting(); break; case wire : default : @@ -319,6 +378,28 @@ void init_gflux(ModeInfo * mi) } gp = &gflux[screen]; + trackball = gltrackball_init (); + + { + char *s = get_string_resource ("mode", "Mode"); + if (!s || !*s) _draw = wire; + 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 + { + 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)); @@ -340,7 +421,53 @@ void release_gflux(ModeInfo * mi) FreeAllGL(mi); } -/* loads several different types of PNM image from stdin */ +#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) +{ + int i,j,c; + pixel **result; + + gflux->imageHeight = gflux->imageWidth = 8; + + 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; +} + +/* 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); + + 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"); +} + +#else /* HAVE_PPM FALSE */ + #define presult(A,B,C) (*(result+(A)*(gflux->imageWidth)*4+(B)*4+(C))) void loadTexture(void) { @@ -369,7 +496,7 @@ void loadTexture(void) result = malloc(sizeof(GLubyte)*4*width*height); gflux->imageWidth = width; - gflux->imageHeight = height; + gflux->imageHeight = height; switch(ppmType) { case 2 : /* ASCII grey */ @@ -385,7 +512,7 @@ void loadTexture(void) case 3 : /* ASCII rgb */ for(i=0;iimage = result; + gflux->image = result; } -/* creates an image for texture mapping */ void createTexture(void) { int i,j,c; GLubyte *result; - gflux->imageHeight = gflux->imageWidth = 8; + gflux->imageHeight = gflux->imageWidth = 8; - result = malloc(sizeof(GLubyte)*4*gflux->imageHeight*gflux->imageWidth); + 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 ); @@ -438,26 +564,133 @@ void createTexture(void) presult(i,j,3) = (GLubyte) 255; } } - gflux->image = result; + gflux->image = result; } -#undef presult -/* specifies image as texture */ +/* 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); clear_gl_error(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gflux->imageWidth, - gflux->imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, gflux->image); - check_gl_error("texture"); + 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"); } +#undef presult +#endif + + +void +grabTexture(void) +{ + 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, + NULL); + 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 = (GLubyte *) 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); +} + + void initLighting(void) { static float ambientA[] = {0.0, 0.0, 0.0, 1.0}; @@ -506,6 +739,12 @@ void displayTexture(void) 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 = gflux->tex_xscale; + double ys = gflux->tex_yscale; + glMatrixMode (GL_TEXTURE); glLoadIdentity (); glTranslatef(-1,-1,0); @@ -516,20 +755,25 @@ void displayTexture(void) glRotatef(anglex,1,0,0); glRotatef(angley,0,1,0); glRotatef(anglez,0,0,1); + userRot(); 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); - glColor3f(0.5,0.5,0.5); + check_gl_error("texture binding"); - for(x=-1,u=0;x<=1;x+=dx,u+=dx) { + glColor3f(0.5,0.5,0.5); + + for(x=-1,u= 0;x<0.9999;x+=dx,u+=du) { glBegin(GL_QUAD_STRIP); - for(y=-1,v=0;y<=1;y+=dy,v+=dx) { + for(y=-1,v= 0;y<=1;y+=dy,v+=dv) { z = getGrid(x,y,time); /* genColour(z); glColor3fv(gflux->colour); - */ glTexCoord2f(u,v); + */ 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), @@ -540,7 +784,7 @@ void displayTexture(void) z = getGrid(x+dx,y,time); /* genColour(z); glColor3fv(gflux->colour); - */ glTexCoord2f(u+dx,v); + */ 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), @@ -551,10 +795,12 @@ void displayTexture(void) glEnd(); } - time -= _speed; - anglex -= _rotationx; - angley -= _rotationy; - anglez -= _rotationz; + if (! button_down_p) { + time -= _speed; + anglex -= _rotationx; + angley -= _rotationy; + anglez -= _rotationz; + } } void displaySolid(void) { @@ -572,10 +818,11 @@ void displaySolid(void) glRotatef(anglex,1,0,0); glRotatef(angley,0,1,0); glRotatef(anglez,0,0,1); + userRot(); glScalef(1,1,(GLfloat)_waveHeight); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - for(x=-1;x<=1;x+=dx) { + for(x=-1;x<0.9999;x+=dx) { glBegin(GL_QUAD_STRIP); for(y=-1;y<=1;y+=dy) { z = getGrid(x,y,time); @@ -591,10 +838,12 @@ void displaySolid(void) glEnd(); } - time -= _speed; - anglex -= _rotationx; - angley -= _rotationy; - anglez -= _rotationz; + if (! button_down_p) { + time -= _speed; + anglex -= _rotationx; + angley -= _rotationy; + anglez -= _rotationz; + } } @@ -614,10 +863,11 @@ void displayLight(void) glRotatef(anglex,1,0,0); glRotatef(angley,0,1,0); glRotatef(anglez,0,0,1); + userRot(); glScalef(1,1,(GLfloat)_waveHeight); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - for(x=-1;x<=1;x+=dx) { + for(x=-1;x<0.9999;x+=dx) { glBegin(GL_QUAD_STRIP); for(y=-1;y<=1;y+=dy) { z = getGrid(x,y,time); @@ -643,10 +893,12 @@ void displayLight(void) glEnd(); } - time -= _speed; - anglex -= _rotationx; - angley -= _rotationy; - anglez -= _rotationz; + if (! button_down_p) { + time -= _speed; + anglex -= _rotationx; + angley -= _rotationy; + anglez -= _rotationz; + } } void displayWire(void) @@ -667,6 +919,7 @@ void displayWire(void) glRotatef(anglex,1,0,0); glRotatef(angley,0,1,0); glRotatef(anglez,0,0,1); + userRot(); glScalef(1,1,(GLfloat)_waveHeight); glClear(GL_COLOR_BUFFER_BIT); @@ -691,10 +944,12 @@ void displayWire(void) glEnd(); } - time -= _speed; - anglex -= _rotationx; - angley -= _rotationy; - anglez -= _rotationz; + if (! button_down_p) { + time -= _speed; + anglex -= _rotationx; + angley -= _rotationy; + anglez -= _rotationz; + } } /* generates new ripples */ @@ -704,12 +959,14 @@ void calcGrid(void) double tmp; static int newWave; + if (button_down_p) return; + tmp = 1.0/((double)_waveChange); if(!(counter%_waveChange)) { newWave = ((int)(counter*tmp))%_waves; - gflux->dispx[newWave] = 1.0 - ((double)random())/RAND_MAX; - gflux->dispy[newWave] = 1.0 - ((double)random())/RAND_MAX; - gflux->freq[newWave] = _waveFreq * ((float)random())/RAND_MAX; + gflux->dispx[newWave] = -frand(1.0); + gflux->dispy[newWave] = -frand(1.0); + gflux->freq[newWave] = _waveFreq * frand(1.0); gflux->wa[newWave] = 0.0; } counter++;