X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fifs.c;h=60d4d9cc503093e329c0e884fd5ea1659fa57069;hp=29a72c23144d59f3d0b93e42ee91ba284fc765dd;hb=447db08c956099b3b183886729108bf5b364c4b8;hpb=2d04c4f22466851aedb6ed0f2919d148f726b889 diff --git a/hacks/ifs.c b/hacks/ifs.c index 29a72c23..60d4d9cc 100644 --- a/hacks/ifs.c +++ b/hacks/ifs.c @@ -1,507 +1,348 @@ -/* -*- Mode: C; tab-width: 4 -*- */ -/* ifs --- modified iterated functions system */ - -#if 0 -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); +} -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; +static int delay; +static int lensnum; +static int length; +static int mode; +static Bool notranslate, noscale, norotate; +float ht,wt; +float hs,ws; +int width,height; +float r; +long wcol; +int coloffset; + +float nx,ny; + +int count; + +/*X stuff*/ +GC gc; +Window w; +Display *dpy; +Pixmap backbuffer; +XColor *colours; +int ncolours; +int screen_num; + +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 }; -static FRACTAL *Root = (FRACTAL *) NULL, *Cur_F; -static XPoint *Buf; -static int Cur_Pt; - - -/*****************************************************/ +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 DBL -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)); - if (NRAND(2)) - return (c + y); - 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)); } -static DBL -Half_Gauss_Rand(DBL c, DBL A, DBL S) +/*Draw a point on the backbuffer*/ +static void sp(float x, float y, long c) { - DBL y; - - y = (DBL) LRAND() / MAXRAND; - y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); - return (c + y); + 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); } -static void -Random_Simis(FRACTAL * F, SIMI * Cur, int i) +/*Copy backbuffer to front buffer and clear backbuffer*/ +static void draw(void) { - 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++; - } + XCopyArea( dpy, + backbuffer, w, + gc, + 0, 0, + width, height, + 0, 0); + + XSetForeground(dpy, gc, blackColor); + XFillRectangle( dpy, + backbuffer, + gc, + 0, 0, + width, height); } -static void -free_ifs_buffers(FRACTAL *Fractal) +typedef struct { + float r,s,tx,ty; + /*Rotation, Scale, Translation X & Y*/ + float ra,raa,sa,txa,tya; + + int co; +} Lens; + + +static void CreateLens(float nr, + float ns, + float nx, + float ny, + int nco, + Lens *newlens) { - 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; - } + newlens->ra=newlens->raa=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; + } + + newlens->co=nco; } - - -static void -free_ifs(Display *display, FRACTAL *Fractal) + +static float stepx(float x, float y, Lens *l) { - free_ifs_buffers(Fractal); - if (Fractal->dbuf != None) { - XFreePixmap(display, Fractal->dbuf); - Fractal->dbuf = None; - } - if (Fractal->dbuf_gc != None) { - XFreeGC(display, Fractal->dbuf_gc); - Fractal->dbuf_gc = None; - } + return l->s*cos(l->r)*x+l->s*sin(l->r)*y+l->tx; } -/***************************************************************/ - -void -init_ifs(ModeInfo * mi) +static float stepy(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*sin(l->r)*-x+l->s*cos(l->r)*y+l->ty; } - -/***************************************************************/ - -/* 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 void mutate(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; + if(!norotate) { + l->raa+=myrandom(0.002)-0.001; + l->ra+=l->raa; + l->r +=l->ra; + if(l->ra>0.07 || l->ra<-0.07) l->ra/=1.4; + if(l->raa>0.005 || l->raa<-0.005) l->raa/=1.2; + } + if(!noscale) { + l->sa+=myrandom(0.01)-0.005; + l->s +=l->sa; + if(l->s>0.4) l->sa -=0.004; + if(l->s<-0.4) l->sa +=0.004; + if(l->sa>0.07 || l->sa<-0.07) l->sa/=1.4; + } + 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; -static void -Trace(FRACTAL * F, F_PT xo, F_PT yo) +/* Calls itself times - with results from each lens/function. * + * After calls to itself, it stops iterating and draws a point. */ +static void iterate(float x, float y, long curcol, int length) { - 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++; - } - } + int i; + if(length == 0) { + sp(x,y,curcol); + } else { + /*iterate(lenses[0].stepx(x,y),lenses[0].stepy(x,y),length-1); + iterate(lenses[1].stepx(x,y),lenses[1].stepy(x,y),length-1); + iterate(lenses[2].stepx(x,y),lenses[2].stepy(x,y),length-1);*/ + 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++; } -static void -Draw_Fractal(ModeInfo * mi) +/* Come on and iterate, iterate, iterate and sing... * + * Yeah, this function just calls iterate, mutate, * + * and then draws everything. */ +static void step(void) { - 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); - } - } - - /* 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); - } - 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); - } - if (F->dbuf != 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; + int i; + if(mode == 2) { + wcol++; + wcol %= ncolours; + iterate(0,0,colours[wcol].pixel,length); + } else { + iterate(0,0,0xFFFFFF,length); + } + + + count=0; + + for(i=0;iBuffer1 == 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; - } - - MI_IS_DRAWN(mi) = True; - - Draw_Fractal(mi); - - if (F->Count >= 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++; + 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;i