X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fifs.c;h=5579abe04ed04780878f30c65bfff4c0dfab0ab5;hb=3f438031d610c7e15fd33876a879b97e290e05fb;hp=e3e0dc62a658a45d707d1f7d108edd31dbeb5756;hpb=96bdd7cf6ea60c418a76921acaf0e34d6f5be930;p=xscreensaver diff --git a/hacks/ifs.c b/hacks/ifs.c index e3e0dc62..5579abe0 100644 --- a/hacks/ifs.c +++ b/hacks/ifs.c @@ -1,508 +1,369 @@ -/* -*- Mode: C; tab-width: 4 -*- */ -/* ifs --- modified iterated functions system */ - -#if !defined( lint ) && !defined( SABER ) -static const char sccsid[] = "@(#)ifs.c 5.00 2000/11/01 xlockmore"; - -#endif - -/*- - * Copyright (c) 1997 by Massimino Pascal - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appear in all copies and that - * both that copyright notice and this permission notice appear in - * supporting documentation. - * - * This file is provided AS IS with no warranties of any kind. The author - * shall have no liability with respect to the infringement of copyrights, - * trade secrets or any patents by this file or any part thereof. In no - * event will the author be liable for any lost revenue or profits or - * other special, indirect and consequential damages. - * - * If this mode is weird and you have an old MetroX server, it is buggy. - * There is a free SuSE-enhanced MetroX X server that is fine. - * - * When shown ifs, Diana Rose (4 years old) said, "It looks like dancing." - * - * Revision History: - * 01-Nov-2000: Allocation checks - * 10-May-1997: jwz@jwz.org: turned into a standalone program. - * Made it render into an offscreen bitmap and then copy - * that onto the screen, to reduce flicker. - */ - -#ifdef STANDALONE -#define MODE_ifs -#define PROGCLASS "IFS" -#define HACK_INIT init_ifs -#define HACK_DRAW draw_ifs -#define ifs_opts xlockmore_opts -#define DEFAULTS "*delay: 20000 \n" \ - "*ncolors: 100 \n" -#define SMOOTH_COLORS -#include "xlockmore.h" /* in xscreensaver distribution */ -#else /* STANDALONE */ -#include "xlock.h" /* in xlockmore distribution */ -#endif /* STANDALONE */ - -#ifdef MODE_ifs - -ModeSpecOpt ifs_opts = -{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; - -#ifdef USE_MODULES -ModStruct ifs_description = -{"ifs", "init_ifs", "draw_ifs", "release_ifs", - "init_ifs", "init_ifs", (char *) NULL, &ifs_opts, - 1000, 1, 1, 1, 64, 1.0, "", - "Shows a modified iterated function system", 0, NULL}; - -#endif - -/*****************************************************/ - -typedef float DBL; -typedef int F_PT; - -/* typedef float F_PT; */ - -/*****************************************************/ - -#define FIX 12 -#define UNIT ( 1< +#include +#include +#include +#include + +#include "screenhack.h" + +static float +myrandom(float up) +{ + return(((float)random()/RAND_MAX)*up); +} - DBL c_x, c_y; - DBL r, r2, A, A2; - F_PT Ct, St, Ct2, St2; - F_PT Cx, Cy; - F_PT R, R2; +static int delay; +static int lensnum; +static int length; +static int mode; +static Bool notranslate, noscale, norotate; +static float ht,wt; +static float hs,ws; +static int width,height; +static long wcol; + +static int count; + +/*X stuff*/ +static GC gc; +static Window w; +static Display *dpy; +static Pixmap backbuffer; +static XColor *colours; +static int ncolours; +static int screen_num; + +static int blackColor, whiteColor; + +char *progclass = "IFS"; + +char *defaults [] = { + ".lensnum: 3", + ".length: 9", + ".mode: 0", + ".colors: 200", + "*delay: 10000", + "*notranslate: False", + "*noscale: False", + "*norotate: False", + 0 }; -struct Fractal_Struct { - - int Nb_Simi; - SIMI Components[5 * MAX_SIMI]; - int Depth, Col; - int Count, Speed; - int Width, Height, Lx, Ly; - DBL r_mean, dr_mean, dr2_mean; - int Cur_Pt, Max_Pt; - XPoint *Buffer1, *Buffer2; - Pixmap dbuf; - GC dbuf_gc; +XrmOptionDescRec options [] = { + { "-detail", ".length", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { "-functions", ".lensnum", XrmoptionSepArg, 0 }, + { "-notranslate", ".notranslate", XrmoptionNoArg, "True" }, + { "-noscale", ".noscale", XrmoptionNoArg, "True" }, + { "-norotate", ".norotate", XrmoptionNoArg, "True" }, + { 0, 0, 0, 0 } }; -static FRACTAL *Root = (FRACTAL *) NULL, *Cur_F; -static XPoint *Buf; -static int Cur_Pt; - - -/*****************************************************/ - -static DBL -Gauss_Rand(DBL c, DBL A, DBL S) -{ - DBL y; - - y = (DBL) LRAND() / MAXRAND; - y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); - if (NRAND(2)) - return (c + y); - return (c - y); -} - -static DBL -Half_Gauss_Rand(DBL c, DBL A, DBL S) +/*Takes the average of two colours, with some nifty bit-shifting*/ +static long +blend(long c1, long c2) { - DBL y; - - y = (DBL) LRAND() / MAXRAND; - y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); - return (c + y); + long R1=(c1 & 0xFF0000) >> 16; + long R2=(c2 & 0xFF0000) >> 16; + long G1=(c1 & 0x00FF00) >> 8; + long G2=(c2 & 0x00FF00) >> 8; + long B1=(c1 & 0x0000FF); + long B2=(c2 & 0x0000FF); + + return (((R1+R2)/2 << 16) | ((G1+G2)/2 << 8) | ((B1+B2)/2)); } +/*Draw a point on the backbuffer*/ static void -Random_Simis(FRACTAL * F, SIMI * Cur, int i) +sp(float x, float y, long c) { - while (i--) { - Cur->c_x = Gauss_Rand(0.0, .8, 4.0); - Cur->c_y = Gauss_Rand(0.0, .8, 4.0); - Cur->r = Gauss_Rand(F->r_mean, F->dr_mean, 3.0); - Cur->r2 = Half_Gauss_Rand(0.0, F->dr2_mean, 2.0); - Cur->A = Gauss_Rand(0.0, 360.0, 4.0) * (M_PI / 180.0); - Cur->A2 = Gauss_Rand(0.0, 360.0, 4.0) * (M_PI / 180.0); - Cur++; - } + x+=16; x*=wt; + y=16.5-y; y*=ht; + if(x<0 || x>=width || y<0 || y>=height) return; + XSetForeground(dpy, gc, c); + XDrawPoint(dpy, backbuffer, gc, (int)x, (int)y); } +/*Copy backbuffer to front buffer and clear backbuffer*/ static void -free_ifs_buffers(FRACTAL *Fractal) +draw(void) { - if (Fractal->Buffer1 != NULL) { - (void) free((void *) Fractal->Buffer1); - Fractal->Buffer1 = (XPoint *) NULL; - } - if (Fractal->Buffer2 != NULL) { - (void) free((void *) Fractal->Buffer2); - Fractal->Buffer2 = (XPoint *) NULL; - } + XCopyArea( dpy, + backbuffer, w, + gc, + 0, 0, + width, height, + 0, 0); + + XSetForeground(dpy, gc, blackColor); + XFillRectangle( dpy, + backbuffer, + gc, + 0, 0, + width, height); } +typedef struct { + float r,s,tx,ty; + /*Rotation, Scale, Translation X & Y*/ + float ro,rt,rc; + /*Old Rotation, Rotation Target, Rotation Counter*/ + float so,st,sc; + /*Old Scale, Scale Target, Scale Counter*/ + float sa,txa,tya; + /*Scale change, Translation change*/ + + int co; +} Lens; + static void -free_ifs(Display *display, FRACTAL *Fractal) +CreateLens( float nr, + float ns, + float nx, + float ny, + int nco, + Lens *newlens) { - free_ifs_buffers(Fractal); - if (Fractal->dbuf != None) { - XFreePixmap(display, Fractal->dbuf); - Fractal->dbuf = None; + newlens->sa=newlens->txa=newlens->tya=0; + if(!norotate) newlens->r=nr; + else newlens->r=0; + + if(!noscale) newlens->s=ns; + else newlens->s=0.5; + + if(!notranslate) { + newlens->tx=nx; + newlens->ty=ny; + } else { + newlens->tx=nx; + newlens->tx=ny; } - if (Fractal->dbuf_gc != None) { - XFreeGC(display, Fractal->dbuf_gc); - Fractal->dbuf_gc = None; - } -} - -/***************************************************************/ -void -init_ifs(ModeInfo * mi) + newlens->rc=newlens->sc=1; + newlens->co=nco; +} + +static float +stepx(float x, float y, Lens *l) { - Display *display = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - GC gc = MI_GC(mi); - int i; - FRACTAL *Fractal; - - if (Root == NULL) { - Root = (FRACTAL *) calloc( - MI_NUM_SCREENS(mi), sizeof (FRACTAL)); - if (Root == NULL) - return; - } - Fractal = &Root[MI_SCREEN(mi)]; - - free_ifs_buffers(Fractal); - i = (NRAND(4)) + 2; /* Number of centers */ - switch (i) { - case 3: - Fractal->Depth = MAX_DEPTH_3; - Fractal->r_mean = .6; - Fractal->dr_mean = .4; - Fractal->dr2_mean = .3; - break; - - case 4: - Fractal->Depth = MAX_DEPTH_4; - Fractal->r_mean = .5; - Fractal->dr_mean = .4; - Fractal->dr2_mean = .3; - break; - - case 5: - Fractal->Depth = MAX_DEPTH_5; - Fractal->r_mean = .5; - Fractal->dr_mean = .4; - Fractal->dr2_mean = .3; - break; - - default: - case 2: - Fractal->Depth = MAX_DEPTH_2; - Fractal->r_mean = .7; - Fractal->dr_mean = .3; - Fractal->dr2_mean = .4; - break; - } - /* (void) fprintf( stderr, "N=%d\n", i ); */ - Fractal->Nb_Simi = i; - Fractal->Max_Pt = Fractal->Nb_Simi - 1; - for (i = 0; i <= Fractal->Depth + 2; ++i) - Fractal->Max_Pt *= Fractal->Nb_Simi; - - if ((Fractal->Buffer1 = (XPoint *) calloc(Fractal->Max_Pt, - sizeof (XPoint))) == NULL) { - free_ifs(display, Fractal); - return; - } - if ((Fractal->Buffer2 = (XPoint *) calloc(Fractal->Max_Pt, - sizeof (XPoint))) == NULL) { - free_ifs(display, Fractal); - return; - } - Fractal->Speed = 6; - Fractal->Width = MI_WIDTH(mi); - Fractal->Height = MI_HEIGHT(mi); - Fractal->Cur_Pt = 0; - Fractal->Count = 0; - Fractal->Lx = (Fractal->Width - 1) / 2; - Fractal->Ly = (Fractal->Height - 1) / 2; - Fractal->Col = NRAND(MI_NPIXELS(mi) - 1) + 1; - - Random_Simis(Fractal, Fractal->Components, 5 * MAX_SIMI); - -#ifndef NO_DBUF - if (Fractal->dbuf != None) - XFreePixmap(display, Fractal->dbuf); - Fractal->dbuf = XCreatePixmap(display, window, - Fractal->Width, Fractal->Height, 1); - /* Allocation checked */ - if (Fractal->dbuf != None) { - XGCValues gcv; - - gcv.foreground = 0; - gcv.background = 0; - gcv.graphics_exposures = False; - gcv.function = GXcopy; - - if (Fractal->dbuf_gc != None) - XFreeGC(display, Fractal->dbuf_gc); - if ((Fractal->dbuf_gc = XCreateGC(display, Fractal->dbuf, - GCForeground | GCBackground | GCGraphicsExposures | GCFunction, - &gcv)) == None) { - XFreePixmap(display, Fractal->dbuf); - Fractal->dbuf = None; - } else { - XFillRectangle(display, Fractal->dbuf, - Fractal->dbuf_gc, 0, 0, Fractal->Width, Fractal->Height); - XSetBackground(display, gc, MI_BLACK_PIXEL(mi)); - XSetFunction(display, gc, GXcopy); - } - } -#endif - MI_CLEARWINDOW(mi); - - /* don't want any exposure events from XCopyPlane */ - XSetGraphicsExposures(display, gc, False); - + return l->s*cos(l->r)*x+l->s*sin(l->r)*y+l->tx; } - - -/***************************************************************/ - -/* Should be taken care of already... but just in case */ -#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus) -#undef inline -#define inline /* */ -#endif -static inline void -Transform(SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y) +static float +stepy(float x, float y, Lens *l) { - F_PT xx, yy; - - xo = xo - Simi->Cx; - xo = (xo * Simi->R) / UNIT; - yo = yo - Simi->Cy; - yo = (yo * Simi->R) / UNIT; - - xx = xo - Simi->Cx; - xx = (xx * Simi->R2) / UNIT; - yy = -yo - Simi->Cy; - yy = (yy * Simi->R2) / UNIT; - - *x = ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2) / UNIT) + Simi->Cx; - *y = ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2) / UNIT) + Simi->Cy; + return l->s*sin(l->r)*-x+l->s*cos(l->r)*y+l->ty; } - -/***************************************************************/ - static void -Trace(FRACTAL * F, F_PT xo, F_PT yo) +mutate(Lens *l) { - F_PT x, y, i; - SIMI *Cur; - - Cur = Cur_F->Components; - for (i = Cur_F->Nb_Simi; i; --i, Cur++) { - Transform(Cur, xo, yo, &x, &y); - /* Buf->x = F->Lx + (x * F->Lx / (UNIT * 2)); */ - /* Buf->y = F->Ly - (y * F->Ly / (UNIT * 2)); */ - Buf->x = (UNIT * 2 + x) * F->Lx / (UNIT * 2); - Buf->y = (UNIT * 2 - y) * F->Ly / (UNIT * 2); - Buf++; - Cur_Pt++; - - if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) { - F->Depth--; - Trace(F, x, y); - F->Depth++; + if(!norotate) { + float factor; + if(l->rc >= 1) { + l->rc= 0; + l->ro = l->rt; + l->rt = myrandom(4)-2; + } + factor = (sin((-M_PI / 2.0) + M_PI * l->rc) + 1.0) / 2.0; + l->r=l->ro + (l->rt - l->ro) * factor; + l->rc+=0.01; + + } + if(!noscale) { + float factor; + if(l->sc >= 1) { + /*Reset counter, obtain new target value*/ + l->sc= 0; + l->so = l->st; + l->st = myrandom(2)-1; } + factor = (sin((-M_PI / 2.0) + M_PI * l->sc) + 1.0) / 2.0; + /* Take average of old target and new target, using factor to * + * weight. It's computed sinusoidally, resulting in smooth, * + * rhythmic transitions. */ + l->s=l->so + (l->st - l->so) * factor; + l->sc+=0.01; + } + if(!notranslate) { + l->txa+=myrandom(0.004)-0.002; + l->tya+=myrandom(0.004)-0.002; + l->tx+=l->txa; + l->ty+=l->tya; + if(l->tx>6) l->txa-=0.004; + if(l->ty>6) l->tya-=0.004; + if(l->tx<-6) l->txa+=0.004; + if(l->ty<-6) l->tya+=0.004; + if(l->txa>0.05 || l->txa<-0.05) l->txa/=1.7; + if(l->tya>0.05 || l->tya<-0.05) l->tya/=1.7; } + + /*Groovy, colour-shifting functions!*/ + l->co++; + l->co %= ncolours; } +Lens **lenses; + +/* Calls itself times - with results from each lens/function. * + * After calls to itself, it stops iterating and draws a point. */ static void -Draw_Fractal(ModeInfo * mi) +iterate(float x, float y, long curcol, int length) { - Display *display = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - GC gc = MI_GC(mi); - FRACTAL *F = &Root[MI_SCREEN(mi)]; - int i, j; - F_PT x, y, xo, yo; - SIMI *Cur, *Simi; - - for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) { - Cur->Cx = DBL_To_F_PT(Cur->c_x); - Cur->Cy = DBL_To_F_PT(Cur->c_y); - - Cur->Ct = DBL_To_F_PT(cos(Cur->A)); - Cur->St = DBL_To_F_PT(sin(Cur->A)); - Cur->Ct2 = DBL_To_F_PT(cos(Cur->A2)); - Cur->St2 = DBL_To_F_PT(sin(Cur->A2)); - - Cur->R = DBL_To_F_PT(Cur->r); - Cur->R2 = DBL_To_F_PT(Cur->r2); - } - - - Cur_Pt = 0; - Cur_F = F; - Buf = F->Buffer2; - for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) { - xo = Cur->Cx; - yo = Cur->Cy; - for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) { - if (Simi == Cur) - continue; - Transform(Simi, xo, yo, &x, &y); - Trace(F, x, y); + int i; + if(length == 0) { + sp(x,y,curcol); + } else { + for(i=0;ico].pixel ), length-1); break; + case 1 : iterate(stepx( x, y, lenses[i]), stepy( x, y, lenses[i]), colours[(int)lenses[i]->co].pixel, length-1); break; + case 2 : iterate(stepx( x, y, lenses[i]), stepy( x, y, lenses[i]), curcol, length-1); break; + default: exit(0); + } } } + count++; +} - /* Erase previous */ - if (F->Cur_Pt) { - XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); - if (F->dbuf != None) { - XSetForeground(display, F->dbuf_gc, 0); - /* XDrawPoints(display, F->dbuf, F->dbuf_gc, F->Buffer1, F->Cur_Pt, - CoordModeOrigin); */ - XFillRectangle(display, F->dbuf, F->dbuf_gc, 0, 0, - F->Width, F->Height); - } else - XDrawPoints(display, window, gc, F->Buffer1, F->Cur_Pt, CoordModeOrigin); +/* Come on and iterate, iterate, iterate and sing... * + * Yeah, this function just calls iterate, mutate, * + * and then draws everything. */ +static void +step(void) +{ + int i; + if(mode == 2) { + wcol++; + wcol %= ncolours; + iterate(0,0,colours[wcol].pixel,length); + } else { + iterate(0,0,0xFFFFFF,length); } - if (MI_NPIXELS(mi) < 2) - XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); - else - XSetForeground(display, gc, MI_PIXEL(mi, F->Col % MI_NPIXELS(mi))); - if (Cur_Pt) { - if (F->dbuf != None) { - XSetForeground(display, F->dbuf_gc, 1); - XDrawPoints(display, F->dbuf, F->dbuf_gc, F->Buffer2, Cur_Pt, - CoordModeOrigin); - } else - XDrawPoints(display, window, gc, F->Buffer2, Cur_Pt, CoordModeOrigin); + + + count=0; + + for(i=0;idbuf != None) - XCopyPlane(display, F->dbuf, window, gc, 0, 0, F->Width, F->Height, 0, 0, 1); - - F->Cur_Pt = Cur_Pt; - Buf = F->Buffer1; - F->Buffer1 = F->Buffer2; - F->Buffer2 = Buf; + draw(); } - -void -draw_ifs(ModeInfo * mi) +static void +init_ifs(void) { - int i; - DBL u, uu, v, vv, u0, u1, u2, u3; - SIMI *S, *S1, *S2, *S3, *S4; - FRACTAL *F; - - if (Root == NULL) - return; - F = &Root[MI_SCREEN(mi)]; - if (F->Buffer1 == NULL) - return; - - u = (DBL) (F->Count) * (DBL) (F->Speed) / 1000.0; - uu = u * u; - v = 1.0 - u; - vv = v * v; - u0 = vv * v; - u1 = 3.0 * vv * u; - u2 = 3.0 * v * uu; - u3 = u * uu; - - S = F->Components; - S1 = S + F->Nb_Simi; - S2 = S1 + F->Nb_Simi; - S3 = S2 + F->Nb_Simi; - S4 = S3 + F->Nb_Simi; - - for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) { - S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x; - S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y; - S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r; - S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2; - S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A; - S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2; + Window rw; + int i; + XWindowAttributes xgwa; + + delay = get_integer_resource("delay", "Delay"); + length = get_integer_resource("length", "Detail"); + mode = get_integer_resource("mode", "Mode"); + + norotate = get_boolean_resource("norotate", "NoRotate"); + noscale = get_boolean_resource("noscale", "NoScale"); + notranslate = get_boolean_resource("notranslate", "NoTranslate"); + + lensnum = get_integer_resource("lensnum", "Functions"); + + lenses = malloc(sizeof(Lens)*lensnum); + + for(i=0;iCount >= 1000 / F->Speed) { - S = F->Components; - S1 = S + F->Nb_Simi; - S2 = S1 + F->Nb_Simi; - S3 = S2 + F->Nb_Simi; - S4 = S3 + F->Nb_Simi; - - for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) { - S2->c_x = 2.0 * S4->c_x - S3->c_x; - S2->c_y = 2.0 * S4->c_y - S3->c_y; - S2->r = 2.0 * S4->r - S3->r; - S2->r2 = 2.0 * S4->r2 - S3->r2; - S2->A = 2.0 * S4->A - S3->A; - S2->A2 = 2.0 * S4->A2 - S3->A2; - - *S1 = *S4; - } - Random_Simis(F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi); - - Random_Simis(F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi); - - F->Count = 0; - } else - F->Count++; - - F->Col++; } - -/***************************************************************/ - void -release_ifs(ModeInfo * mi) +screenhack (Display *display, Window window) { - if (Root != NULL) { - int screen; - - for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) - free_ifs(MI_DISPLAY(mi), &Root[screen]); - (void) free((void *) Root); - Root = (FRACTAL *) NULL; + dpy = display; + w = window; + + init_ifs(); + + while (1) { + step(); + screenhack_handle_events(dpy); + if (delay) usleep(delay); } } - -#endif /* MODE_ifs */