source: trunk/third/xscreensaver/hacks/strange.c @ 20148

Revision 20148, 10.9 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 4 -*- */
2/* strange --- strange attractors */
3
4#if 0
5static const char sccsid[] = "@(#)strange.c     5.00 2000/11/01 xlockmore";
6#endif
7
8/*-
9 * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr>
10 *
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
16 *
17 * This file is provided AS IS with no warranties of any kind.  The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof.  In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
22 *
23 * Revision History:
24 * 01-Nov-2000: Allocation checks
25 * 10-May-1997: jwz@jwz.org: turned into a standalone program.
26 *              Made it render into an offscreen bitmap and then copy
27 *              that onto the screen, to reduce flicker.
28 *
29 * strange attractors are not so hard to find...
30 */
31
32#ifdef STANDALONE
33#define MODE_strange
34#define PROGCLASS "Strange"
35#define HACK_INIT init_strange
36#define HACK_DRAW draw_strange
37#define strange_opts xlockmore_opts
38#define DEFAULTS "*delay: 2000 \n" \
39 "*ncolors: 100 \n"
40#define SMOOTH_COLORS
41#include "xlockmore.h"          /* from the xscreensaver distribution */
42#else /* !STANDALONE */
43#include "xlock.h"              /* from the xlockmore distribution */
44#endif /* !STANDALONE */
45
46#ifdef MODE_strange
47
48ModeSpecOpt strange_opts =
49{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
50
51#ifdef USE_MODULES
52ModStruct   strange_description =
53{"strange", "init_strange", "draw_strange", "release_strange",
54 "init_strange", "init_strange", (char *) NULL, &strange_opts,
55 1000, 1, 1, 1, 64, 1.0, "",
56 "Shows strange attractors", 0, NULL};
57
58#endif
59
60typedef float DBL;
61typedef int PRM;
62
63#define UNIT (1<<12)
64#define UNIT2 (1<<14)
65/* #define UNIT2 (3140*UNIT/1000) */
66
67#define SKIP_FIRST      100
68#define MAX_POINTS      5500
69#define DBL_To_PRM(x)  (PRM)( (DBL)(UNIT)*(x) )
70
71
72#define DO_FOLD(a) (a)<0 ? -A->Fold[ (-(a))&(UNIT2-1) ] : A->Fold[ (a)&(UNIT2-1) ]
73
74#if 0
75#define DO_FOLD(a) (a)<-UNIT2 ? -A->Fold[(-(a))%UNIT2] : (a)<0 ? -A->Fold[ -(a) ] :\
76(a)>UNIT2 ? A->Fold[ (a)%UNIT2 ] : A->Fold[ (a) ]
77#define DO_FOLD(a) DBL_To_PRM( sin( (DBL)(a)/UNIT ) )
78#define DO_FOLD(a) (a)<0 ? DBL_To_PRM( exp( 16.0*(a)/UNIT2 ) )-1.0 : \
79DBL_To_PRM( 1.0-exp( -16.0*(a)/UNIT2 ) )
80#endif
81
82/******************************************************************/
83
84#define MAX_PRM 3*5
85
86typedef struct _ATTRACTOR {
87        DBL         Prm1[MAX_PRM], Prm2[MAX_PRM];
88        PRM         Prm[MAX_PRM], *Fold;
89        void        (*Iterate) (struct _ATTRACTOR *, PRM, PRM, PRM *, PRM *);
90        XPoint     *Buffer1, *Buffer2;
91        int         Cur_Pt, Max_Pt;
92        int         Col, Count, Speed;
93        int         Width, Height;
94        Pixmap      dbuf;       /* jwz */
95        GC          dbuf_gc;
96} ATTRACTOR;
97
98static ATTRACTOR *Root = (ATTRACTOR *) NULL;
99
100static DBL  Amp_Prm[MAX_PRM] =
101{
102        1.0, 3.5, 3.5, 2.5, 4.7,
103        1.0, 3.5, 3.6, 2.5, 4.7,
104        1.0, 1.5, 2.2, 2.1, 3.5
105};
106static DBL  Mid_Prm[MAX_PRM] =
107{
108        0.0, 1.5, 0.0, .5, 1.5,
109        0.0, 1.5, 0.0, .5, 1.5,
110        0.0, 1.5, -1.0, -.5, 2.5,
111};
112
113static      DBL
114Gauss_Rand(DBL c, DBL A, DBL S)
115{
116        DBL         y;
117
118        y = (DBL) LRAND() / MAXRAND;
119        y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S));
120        if (NRAND(2))
121                return (c + y);
122        else
123                return (c - y);
124}
125
126static void
127Random_Prm(DBL * Prm)
128{
129        int         i;
130
131        for (i = 0; i < MAX_PRM; ++i)
132                Prm[i] = Gauss_Rand(Mid_Prm[i], Amp_Prm[i], 4.0);
133}
134
135/***************************************************************/
136
137   /* 2 examples of non-linear map */
138
139static void
140Iterate_X2(ATTRACTOR * A, PRM x, PRM y, PRM * xo, PRM * yo)
141{
142        PRM         xx, yy, xy, x2y, y2x, Tmp;
143
144        xx = (x * x) / UNIT;
145        x2y = (xx * y) / UNIT;
146        yy = (y * y) / UNIT;
147        y2x = (yy * x) / UNIT;
148        xy = (x * y) / UNIT;
149
150        Tmp = A->Prm[1] * xx + A->Prm[2] * xy + A->Prm[3] * yy + A->Prm[4] * x2y;
151        Tmp = A->Prm[0] - y + (Tmp / UNIT);
152        *xo = DO_FOLD(Tmp);
153        Tmp = A->Prm[6] * xx + A->Prm[7] * xy + A->Prm[8] * yy + A->Prm[9] * y2x;
154        Tmp = A->Prm[5] + x + (Tmp / UNIT);
155        *yo = DO_FOLD(Tmp);
156}
157
158static void
159Iterate_X3(ATTRACTOR * A, PRM x, PRM y, PRM * xo, PRM * yo)
160{
161        PRM         xx, yy, xy, x2y, y2x, Tmp_x, Tmp_y, Tmp_z;
162
163        xx = (x * x) / UNIT;
164        x2y = (xx * y) / UNIT;
165        yy = (y * y) / UNIT;
166        y2x = (yy * x) / UNIT;
167        xy = (x * y) / UNIT;
168
169        Tmp_x = A->Prm[1] * xx + A->Prm[2] * xy + A->Prm[3] * yy + A->Prm[4] * x2y;
170        Tmp_x = A->Prm[0] - y + (Tmp_x / UNIT);
171        Tmp_x = DO_FOLD(Tmp_x);
172
173        Tmp_y = A->Prm[6] * xx + A->Prm[7] * xy + A->Prm[8] * yy + A->Prm[9] * y2x;
174        Tmp_y = A->Prm[5] + x + (Tmp_y / UNIT);
175
176        Tmp_y = DO_FOLD(Tmp_y);
177
178        Tmp_z = A->Prm[11] * xx + A->Prm[12] * xy + A->Prm[13] * yy + A->Prm[14] * y2x;
179        Tmp_z = A->Prm[10] + x + (Tmp_z / UNIT);
180        Tmp_z = UNIT + Tmp_z * Tmp_z / UNIT;
181
182        *xo = (Tmp_x * UNIT) / Tmp_z;
183        *yo = (Tmp_y * UNIT) / Tmp_z;
184}
185
186static void (*Funcs[2]) (ATTRACTOR *, PRM, PRM, PRM *, PRM *) = {
187        Iterate_X2, Iterate_X3
188};
189
190/***************************************************************/
191
192static void
193free_strange(Display *display, ATTRACTOR *A)
194{
195        if (A->Buffer1 != NULL) {
196                (void) free((void *) A->Buffer1);
197                A->Buffer1 = (XPoint *) NULL;
198        }
199        if (A->Buffer2 != NULL) {
200                (void) free((void *) A->Buffer2);
201                A->Buffer2 = (XPoint *) NULL;
202        }
203        if (A->dbuf) {
204                XFreePixmap(display, A->dbuf);
205                A->dbuf = None;
206        }
207        if (A->dbuf_gc) {
208                XFreeGC(display, A->dbuf_gc);
209                A->dbuf_gc = None;
210        }
211        if (A->Fold != NULL) {
212                (void) free((void *) A->Fold);
213                A->Fold = (PRM *) NULL;
214        }
215}
216
217void
218draw_strange(ModeInfo * mi)
219{
220        int         i, j, n, Cur_Pt;
221        PRM         x, y, xo, yo;
222        DBL         u;
223        XPoint     *Buf;
224        Display    *display = MI_DISPLAY(mi);
225        Window      window = MI_WINDOW(mi);
226        GC          gc = MI_GC(mi);
227        DBL         Lx, Ly;
228        void        (*Iterate) (ATTRACTOR *, PRM, PRM, PRM *, PRM *);
229        PRM         xmin, xmax, ymin, ymax;
230        ATTRACTOR  *A;
231
232        if (Root == NULL)
233                return;
234        A = &Root[MI_SCREEN(mi)];
235        if (A->Fold == NULL)
236                return;
237
238        Cur_Pt = A->Cur_Pt;
239        Iterate = A->Iterate;
240
241        u = (DBL) (A->Count) / 1000.0;
242        for (j = MAX_PRM - 1; j >= 0; --j)
243                A->Prm[j] = DBL_To_PRM((1.0 - u) * A->Prm1[j] + u * A->Prm2[j]);
244
245        x = y = DBL_To_PRM(.0);
246        for (n = SKIP_FIRST; n; --n) {
247                (*Iterate) (A, x, y, &xo, &yo);
248                x = xo + NRAND(8) - 4;
249                y = yo + NRAND(8) - 4;
250        }
251
252        xmax = 0;
253        xmin = UNIT * 4;
254        ymax = 0;
255        ymin = UNIT * 4;
256        A->Cur_Pt = 0;
257        Buf = A->Buffer2;
258        Lx = (DBL) A->Width / UNIT / 2.2;
259        Ly = (DBL) A->Height / UNIT / 2.2;
260        for (n = A->Max_Pt; n; --n) {
261                (*Iterate) (A, x, y, &xo, &yo);
262                Buf->x = (int) (Lx * (x + DBL_To_PRM(1.1)));
263                Buf->y = (int) (Ly * (DBL_To_PRM(1.1) - y));
264                /* (void) fprintf( stderr, "X,Y: %d %d    ", Buf->x, Buf->y ); */
265                Buf++;
266                A->Cur_Pt++;
267                if (xo > xmax)
268                        xmax = xo;
269                else if (xo < xmin)
270                        xmin = xo;
271                if (yo > ymax)
272                        ymax = yo;
273                else if (yo < ymin)
274                        ymin = yo;
275                x = xo + NRAND(8) - 4;
276                y = yo + NRAND(8) - 4;
277        }
278
279        MI_IS_DRAWN(mi) = True;
280
281        XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
282
283        if (A->dbuf != None) {          /* jwz */
284                XSetForeground(display, A->dbuf_gc, 0);
285/* XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer1,
286   Cur_Pt,CoordModeOrigin); */
287                XFillRectangle(display, A->dbuf, A->dbuf_gc, 0, 0, A->Width, A->Height);
288        } else
289                XDrawPoints(display, window, gc, A->Buffer1, Cur_Pt, CoordModeOrigin);
290
291        if (MI_NPIXELS(mi) < 2)
292                XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
293        else
294                XSetForeground(display, gc, MI_PIXEL(mi, A->Col % MI_NPIXELS(mi)));
295
296        if (A->dbuf != None) {
297                XSetForeground(display, A->dbuf_gc, 1);
298                XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer2, A->Cur_Pt,
299                            CoordModeOrigin);
300                XCopyPlane(display, A->dbuf, window, gc, 0, 0, A->Width, A->Height, 0, 0, 1);
301        } else
302                XDrawPoints(display, window, gc, A->Buffer2, A->Cur_Pt, CoordModeOrigin);
303
304        Buf = A->Buffer1;
305        A->Buffer1 = A->Buffer2;
306        A->Buffer2 = Buf;
307
308        if ((xmax - xmin < DBL_To_PRM(.2)) && (ymax - ymin < DBL_To_PRM(.2)))
309                A->Count += 4 * A->Speed;
310        else
311                A->Count += A->Speed;
312        if (A->Count >= 1000) {
313                for (i = MAX_PRM - 1; i >= 0; --i)
314                        A->Prm1[i] = A->Prm2[i];
315                Random_Prm(A->Prm2);
316                A->Count = 0;
317        }
318        A->Col++;
319}
320
321
322/***************************************************************/
323
324void
325init_strange(ModeInfo * mi)
326{
327        Display    *display = MI_DISPLAY(mi);
328        Window      window = MI_WINDOW(mi);
329        GC          gc = MI_GC(mi);
330        ATTRACTOR  *Attractor;
331
332        if (Root == NULL) {
333                if ((Root = (ATTRACTOR *) calloc(MI_NUM_SCREENS(mi),
334                                sizeof (ATTRACTOR))) == NULL)
335                        return;
336        }
337        Attractor = &Root[MI_SCREEN(mi)];
338
339        if (Attractor->Fold == NULL) {
340                int         i;
341
342                if ((Attractor->Fold = (PRM *) calloc(UNIT2 + 1,
343                                sizeof (PRM))) == NULL) {
344                        free_strange(display, Attractor);
345                        return;
346                }
347                for (i = 0; i <= UNIT2; ++i) {
348                        DBL         x;
349
350                        /* x = ( DBL )(i)/UNIT2; */
351                        /* x = sin( M_PI/2.0*x ); */
352                        /* x = sqrt( x ); */
353                        /* x = x*x; */
354                        /* x = x*(1.0-x)*4.0; */
355                        x = (DBL) (i) / UNIT;
356                        x = sin(x);
357                        Attractor->Fold[i] = DBL_To_PRM(x);
358                }
359        }
360        if (Attractor->Buffer1 == NULL)
361                if ((Attractor->Buffer1 = (XPoint *) calloc(MAX_POINTS,
362                                sizeof (XPoint))) == NULL) {
363                        free_strange(display, Attractor);
364                        return;
365                }
366        if (Attractor->Buffer2 == NULL)
367                if ((Attractor->Buffer2 = (XPoint *) calloc(MAX_POINTS,
368                                sizeof (XPoint))) == NULL) {
369                        free_strange(display, Attractor);
370                        return;
371                }
372        Attractor->Max_Pt = MAX_POINTS;
373
374        Attractor->Width = MI_WIDTH(mi);
375        Attractor->Height = MI_HEIGHT(mi);
376        Attractor->Cur_Pt = 0;
377        Attractor->Count = 0;
378        Attractor->Col = NRAND(MI_NPIXELS(mi));
379        Attractor->Speed = 4;
380
381        Attractor->Iterate = Funcs[NRAND(2)];
382        Random_Prm(Attractor->Prm1);
383        Random_Prm(Attractor->Prm2);
384#ifndef NO_DBUF
385        if (Attractor->dbuf != None)
386                XFreePixmap(display, Attractor->dbuf);
387        Attractor->dbuf = XCreatePixmap(display, window,
388             Attractor->Width, Attractor->Height, 1);
389        /* Allocation checked */
390        if (Attractor->dbuf != None) {
391                XGCValues   gcv;
392
393                gcv.foreground = 0;
394                gcv.background = 0;
395                gcv.graphics_exposures = False;
396                gcv.function = GXcopy;
397
398                if (Attractor->dbuf_gc != None)
399                        XFreeGC(display, Attractor->dbuf_gc);
400
401                if ((Attractor->dbuf_gc = XCreateGC(display, Attractor->dbuf,
402                                GCForeground | GCBackground | GCGraphicsExposures | GCFunction,
403                                &gcv)) == None) {
404                        XFreePixmap(display, Attractor->dbuf);
405                        Attractor->dbuf = None;
406                } else {
407                        XFillRectangle(display, Attractor->dbuf, Attractor->dbuf_gc,
408                                0, 0, Attractor->Width, Attractor->Height);
409                        XSetBackground(display, gc, MI_BLACK_PIXEL(mi));
410                        XSetFunction(display, gc, GXcopy);
411                }
412        }
413#endif
414
415        MI_CLEARWINDOW(mi);
416
417        /* Do not want any exposure events from XCopyPlane */
418        XSetGraphicsExposures(display, MI_GC(mi), False);
419}
420
421/***************************************************************/
422
423void
424release_strange(ModeInfo * mi)
425{
426        if (Root != NULL) {
427                int         screen;
428
429                for (screen = 0; screen < MI_NUM_SCREENS(mi); ++screen)
430                        free_strange(MI_DISPLAY(mi), &Root[screen]);
431                (void) free((void *) Root);
432                Root = (ATTRACTOR *) NULL;
433        }
434}
435
436#endif /* MODE_strange */
Note: See TracBrowser for help on using the repository browser.