X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fstrange.c;h=148bbcadcd5820f981ce45eba6c162165c5adf70;hb=6afd6db0ae9396cd7ff897ade597cd5483f49b0e;hp=b5f3795092ca94ec1a4b837352347a83652c24c2;hpb=c1b9b55ad8d59dc05ef55e316aebf5863e7dfa56;p=xscreensaver diff --git a/hacks/strange.c b/hacks/strange.c index b5f37950..148bbcad 100644 --- a/hacks/strange.c +++ b/hacks/strange.c @@ -6,56 +6,80 @@ static const char sccsid[] = "@(#)strange.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. - * - * 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. - * - * strange attractors are not so hard to find... - */ +* 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. +* +* 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. +* +* strange attractors are not so hard to find... +*/ + +/* TODO: Bring over tweaks from 3.x version. +* For a good idea of what's missing, diff strange.c.20081107-good2 against strange.c-3.29 +* We forked from the 3.29 series at 20081107, so anything added since then may be missing. +*/ #ifdef STANDALONE # define MODE_strange # define DEFAULTS "*delay: 10000 \n" \ "*ncolors: 100 \n" \ - "*fpsClear: True \n" + "*fpsSolid: True \n" \ + "*ignoreRotation: True \n" \ # define SMOOTH_COLORS # define refresh_strange 0 -# define reshape_strange 0 -# define strange_handle_event 0 # include "xlockmore.h" /* from the xscreensaver distribution */ #else /* !STANDALONE */ # include "xlock.h" /* from the xlockmore distribution */ #endif /* !STANDALONE */ #ifdef MODE_strange +#define DEF_CURVE "10" +#define DEF_POINTS "5500" +/*static int curve;*/ +static int points; + +static XrmOptionDescRec opts[] = +{ +/* {"-curve", ".strange.curve", XrmoptionSepArg, 0}, */ + {"-points", ".strange.points", XrmoptionSepArg, 0}, +}; +static argtype vars[] = +{ +/* {&curve, "curve", "Curve", DEF_CURVE, t_Int},*/ + {&points, "points", "Points", DEF_POINTS, t_Int}, +}; +static OptionStruct desc[] = +{ +/* {"-curve", "set the curve factor of the attractors"},*/ + {"-points", "change the number of points/iterations each frame"}, +}; ENTRYPOINT ModeSpecOpt strange_opts = -{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; +{sizeof opts / sizeof opts[0], opts, +sizeof vars / sizeof vars[0], vars, desc}; #ifdef USE_MODULES ModStruct strange_description = {"strange", "init_strange", "draw_strange", "release_strange", - "init_strange", "init_strange", (char *) NULL, &strange_opts, - 1000, 1, 1, 1, 64, 1.0, "", - "Shows strange attractors", 0, NULL}; - +"init_strange", "init_strange", (char *) NULL, &strange_opts, +1000, 1, 1, 1, 64, 1.0, "", +"Shows strange attractors", 0, NULL}; #endif #ifdef HAVE_COCOA @@ -70,7 +94,6 @@ typedef int PRM; /* #define UNIT2 (3140*UNIT/1000) */ #define SKIP_FIRST 100 -#define MAX_POINTS 5500 #define DBL_To_PRM(x) (PRM)( (DBL)(UNIT)*(x) ) @@ -84,6 +107,18 @@ typedef int PRM; DBL_To_PRM( 1.0-exp( -16.0*(a)/UNIT2 ) ) #endif +/* useAccumulator performs two functions: +* If it is defined, then support for the accumulator will be compiled. +* It is also the condition for which the accumulator renderer will engage. +*/ +#define useAccumulator (Root->Max_Pt > 6000) +#define ACC_GAMMA 10.0 +#define NUM_COLS 150 +/* Extra options: */ +#define VARY_SPEED_TO_AVOID_BOREDOM +#define POINTS_HISTORY +#define MERGE_FRAMES 3 + /******************************************************************/ #define MAX_PRM 3*5 @@ -98,10 +133,25 @@ typedef struct _ATTRACTOR { int Width, Height; Pixmap dbuf; /* jwz */ GC dbuf_gc; + #ifdef useAccumulator + int **accMap; + #endif } ATTRACTOR; static ATTRACTOR *Root = (ATTRACTOR *) NULL; +#ifdef useAccumulator +static XColor* cols; +#endif + +#ifdef POINTS_HISTORY +static int numOldPoints; +static int* oldPointsX; +static int* oldPointsY; +static int oldPointsIndex; +static int startedClearing; +#endif + static DBL Amp_Prm[MAX_PRM] = { 1.0, 3.5, 3.5, 2.5, 4.7, @@ -139,7 +189,7 @@ Random_Prm(DBL * Prm) /***************************************************************/ - /* 2 examples of non-linear map */ + /* 2 examples of non-linear map */ static void Iterate_X2(ATTRACTOR * A, PRM x, PRM y, PRM * xo, PRM * yo) @@ -243,10 +293,24 @@ draw_strange(ModeInfo * mi) Cur_Pt = A->Cur_Pt; Iterate = A->Iterate; - u = (DBL) (A->Count) / 1000.0; + u = (DBL) (A->Count) / 40000.0; for (j = MAX_PRM - 1; j >= 0; --j) A->Prm[j] = DBL_To_PRM((1.0 - u) * A->Prm1[j] + u * A->Prm2[j]); + /* We collect the accumulation of the orbits in the 2d int array field. */ +#ifndef POINTS_HISTORY + #ifdef useAccumulator + if (useAccumulator) { + for (i=0;iWidth;i++) { + for (j=0;jHeight;j++) { + A->accMap[i][j] = 0; + + } + } + } + #endif +#endif + x = y = DBL_To_PRM(.0); for (n = SKIP_FIRST; n; --n) { (*Iterate) (A, x, y, &xo, &yo); @@ -264,11 +328,40 @@ draw_strange(ModeInfo * mi) Ly = (DBL) A->Height / UNIT / 2.2; for (n = A->Max_Pt; n; --n) { (*Iterate) (A, x, y, &xo, &yo); - Buf->x = (int) (Lx * (x + DBL_To_PRM(1.1))); - Buf->y = (int) (Ly * (DBL_To_PRM(1.1) - y)); + #ifdef useAccumulator + if (useAccumulator) { + int mx,my; + mx = (short) ( A->Width*0.1 + A->Width*0.8 * (xo - xmin) / (xmax - xmin) ); + my = (short) ( A->Width*0.1 + (A->Height - A->Width*0.2) * (yo - ymin) / (ymax - ymin) ); + if (mx>=0 && my>=0 && mxWidth && myHeight) { + A->accMap[mx][my]++; + } +#ifdef POINTS_HISTORY + /* #define clearOldPoint(i) { if (startedClearing) { field[oldPoints[i].x][oldPoints[i].y]--; } } + #define saveUnplot(X,Y) { clearOldPoint(oldPointsIndex) oldPoints[oldPointsIndex].x = X; oldPoints[oldPointsIndex].y = Y; oldPointsIndex = (oldPointsIndex + 1) % numOldPoints; if (oldPointsIndex==0) { startedClearing=1; } } + saveUnplot(mx,my) */ + if (startedClearing) { + int oldX = oldPointsX[oldPointsIndex]; + int oldY = oldPointsY[oldPointsIndex]; + if (oldX>=0 && oldY>=0 && oldXWidth && oldYHeight) { + A->accMap[oldX][oldY]--; + } + } + oldPointsX[oldPointsIndex] = mx; + oldPointsY[oldPointsIndex] = my; + oldPointsIndex = (oldPointsIndex + 1) % numOldPoints; + if (oldPointsIndex==0) { startedClearing=1; } +#endif + } else { + #endif + Buf->x = (int) (Lx * (x + DBL_To_PRM(1.1))); + Buf->y = (int) (Ly * (DBL_To_PRM(1.1) - y)); + Buf++; + A->Cur_Pt++; + #ifdef useAccumulator + } + #endif /* (void) fprintf( stderr, "X,Y: %d %d ", Buf->x, Buf->y ); */ - Buf++; - A->Cur_Pt++; if (xo > xmax) xmax = xo; else if (xo < xmin) @@ -285,10 +378,78 @@ draw_strange(ModeInfo * mi) XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + #ifdef useAccumulator + if (useAccumulator) { + float colorScale; + int col; + #ifdef VARY_SPEED_TO_AVOID_BOREDOM + int pixelCount = 0; + #endif + colorScale = (A->Width*A->Height/640.0/480.0*800000.0/(float)A->Max_Pt*(float)NUM_COLS/256); + if (A->dbuf != None) { + XSetForeground(display, A->dbuf_gc, 0); + XFillRectangle(display, A->dbuf, A->dbuf_gc, 0, 0, A->Width, A->Height); + } else { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XFillRectangle(display, window, gc, 0, 0, A->Width, A->Height); + } + for (i=0;iWidth;i++) { + for (j=0;jHeight;j++) { + if (A->accMap[i][j]>0) { + col = (float)A->accMap[i][j] * colorScale; + if (col>NUM_COLS-1) { + col = NUM_COLS-1; + } + #ifdef VARY_SPEED_TO_AVOID_BOREDOM + if (col>0) { + if (colCol % MI_NPIXELS(mi)));*/ + XSetForeground(display, gc, cols[col].pixel); + if (A->dbuf != None) { + XSetForeground(display, A->dbuf_gc, cols[col].pixel); + XDrawPoint(display, A->dbuf, A->dbuf_gc, i, j); + } else { + XSetForeground(display, gc, cols[col].pixel); + XDrawPoint(display, window, gc, i, j); + } + } + } + } + if (A->dbuf != None) { + XCopyArea(display, A->dbuf, window, gc, 0, 0, A->Width, A->Height, 0, 0); + } + #ifdef VARY_SPEED_TO_AVOID_BOREDOM + /* Increaase the rate of change of the parameters if the attractor has become visually boring. */ + if ((xmax - xmin < DBL_To_PRM(.2)) && (ymax - ymin < DBL_To_PRM(.2))) { + A->Speed *= 1.25; + } else if (pixelCount>0 && pixelCountWidth*A->Height/1000) { + A->Speed *= 1.25; /* A->Count = 1000; */ + } else { + A->Speed = 4; /* reset to normal/default */ + } + if (A->Speed > 32) + A->Speed = 32; + A->Count += A->Speed; + if (A->Count >= 1000) { + for (i = MAX_PRM - 1; i >= 0; --i) + A->Prm1[i] = A->Prm2[i]; + Random_Prm(A->Prm2); + A->Count = 0; + } + #endif + } else { + #endif + if (A->dbuf != None) { /* jwz */ XSetForeground(display, A->dbuf_gc, 0); /* XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer1, - Cur_Pt,CoordModeOrigin); */ + Cur_Pt,CoordModeOrigin); */ XFillRectangle(display, A->dbuf, A->dbuf_gc, 0, 0, A->Width, A->Height); } else XDrawPoints(display, window, gc, A->Buffer1, Cur_Pt, CoordModeOrigin); @@ -306,6 +467,10 @@ draw_strange(ModeInfo * mi) } else XDrawPoints(display, window, gc, A->Buffer2, A->Cur_Pt, CoordModeOrigin); + #ifdef useAccumulator + } + #endif + Buf = A->Buffer1; A->Buffer1 = A->Buffer2; A->Buffer2 = Buf; @@ -321,6 +486,7 @@ draw_strange(ModeInfo * mi) A->Count = 0; } A->Col++; + mi->recursion_depth = A->Count; } @@ -330,12 +496,17 @@ ENTRYPOINT void init_strange(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); -#ifndef NO_DBUF Window window = MI_WINDOW(mi); +#ifndef NO_DBUF GC gc = MI_GC(mi); #endif ATTRACTOR *Attractor; +#ifdef POINTS_HISTORY + startedClearing=0; + oldPointsIndex=0; +#endif + if (Root == NULL) { if ((Root = (ATTRACTOR *) calloc(MI_NUM_SCREENS(mi), sizeof (ATTRACTOR))) == NULL) @@ -364,19 +535,21 @@ init_strange(ModeInfo * mi) Attractor->Fold[i] = DBL_To_PRM(x); } } + + Attractor->Max_Pt = points; + if (Attractor->Buffer1 == NULL) - if ((Attractor->Buffer1 = (XPoint *) calloc(MAX_POINTS, + if ((Attractor->Buffer1 = (XPoint *) calloc(Attractor->Max_Pt, sizeof (XPoint))) == NULL) { free_strange(display, Attractor); return; } if (Attractor->Buffer2 == NULL) - if ((Attractor->Buffer2 = (XPoint *) calloc(MAX_POINTS, + if ((Attractor->Buffer2 = (XPoint *) calloc(Attractor->Max_Pt, sizeof (XPoint))) == NULL) { free_strange(display, Attractor); return; } - Attractor->Max_Pt = MAX_POINTS; Attractor->Width = MI_WIDTH(mi); Attractor->Height = MI_HEIGHT(mi); @@ -391,8 +564,13 @@ init_strange(ModeInfo * mi) #ifndef NO_DBUF if (Attractor->dbuf != None) XFreePixmap(display, Attractor->dbuf); +#ifdef useAccumulator +#define colorDepth ( useAccumulator ? MI_DEPTH(mi) : 1 ) +#else +#define colorDepth 1 +#endif Attractor->dbuf = XCreatePixmap(display, window, - Attractor->Width, Attractor->Height, 1); + Attractor->Width, Attractor->Height, colorDepth); /* Allocation checked */ if (Attractor->dbuf != None) { XGCValues gcv; @@ -411,7 +589,7 @@ init_strange(ModeInfo * mi) #ifndef HAVE_COCOA GCGraphicsExposures | #endif /* HAVE_COCOA */ - GCFunction | GCForeground | GCBackground, + GCFunction | GCForeground | GCBackground, &gcv)) == None) { XFreePixmap(display, Attractor->dbuf); Attractor->dbuf = None; @@ -424,12 +602,73 @@ init_strange(ModeInfo * mi) } #endif + +#ifdef useAccumulator + #define A Attractor + if (useAccumulator) { + XWindowAttributes xgwa; + int i,j; + XGetWindowAttributes (display, window, &xgwa); + /* cmap = xgwa.colormap; */ + /* cmap = XCreateColormap(display, window, MI_VISUAL(mi), AllocAll); */ + Attractor->accMap = (int**)calloc(Attractor->Width,sizeof(int*)); + for (i=0;iWidth;i++) { + Attractor->accMap[i] = (int*)calloc(Attractor->Height,sizeof(int)); + for (j=0;jHeight;j++) { + Attractor->accMap[i][j] = 0; + } + } +#ifdef POINTS_HISTORY + numOldPoints = A->Max_Pt * MERGE_FRAMES; + oldPointsX = (int*)calloc(numOldPoints,sizeof(int)); + oldPointsY = (int*)calloc(numOldPoints,sizeof(int)); +#endif + cols = (XColor*)calloc(NUM_COLS,sizeof(XColor)); + for (i=0;iWidth;i++) { + (void) free((void *) Root->accMap[i]); + } + (void) free((void *) Root->accMap); +#endif +#ifdef POINTS_HISTORY + free(oldPointsX); + free(oldPointsY); +#endif for (screen = 0; screen < MI_NUM_SCREENS(mi); ++screen) free_strange(MI_DISPLAY(mi), &Root[screen]); (void) free((void *) Root); @@ -445,6 +696,18 @@ release_strange(ModeInfo * mi) } } +ENTRYPOINT Bool +strange_handle_event (ModeInfo *mi, XEvent *event) +{ + if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) + { + reshape_strange (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + return True; + } + return False; +} + + XSCREENSAVER_MODULE ("Strange", strange) #endif /* MODE_strange */