http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.01.tar.gz
[xscreensaver] / hacks / thornbird.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* thornbird --- continuously varying Thornbird set */
3
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)thornbird.c   5.00 2000/11/01 xlockmore";
6
7 #endif
8
9 /*-
10  * Copyright (c) 1996 by Tim Auckland <Tim.Auckland@Procket.com>
11  *
12  * Permission to use, copy, modify, and distribute this software and its
13  * documentation for any purpose and without fee is hereby granted,
14  * provided that the above copyright notice appear in all copies and that
15  * both that copyright notice and this permission notice appear in
16  * supporting documentation.
17  *
18  * This file is provided AS IS with no warranties of any kind.  The author
19  * shall have no liability with respect to the infringement of copyrights,
20  * trade secrets or any patents by this file or any part thereof.  In no
21  * event will the author be liable for any lost revenue or profits or
22  * other special, indirect and consequential damages.
23  *
24  * "thornbird" shows a view of the "Bird in a Thornbush" fractal,
25  * continuously varying the three free parameters.
26  *
27  * Revision History:
28  * 01-Nov-2000: Allocation checks
29  * 04-Jun-1999: 3D tumble added by Tim Auckland
30  * 31-Jul-1997: Adapted from discrete.c Copyright (c) 1996 by Tim Auckland
31  */
32
33 #ifdef STANDALONE
34 #define MODE_thornbird
35 #define PROGCLASS "Thornbird"
36 #define HACK_INIT init_thornbird
37 #define HACK_DRAW draw_thornbird
38 #define thornbird_opts xlockmore_opts
39 #define DEFAULTS "*delay: 10000 \n" \
40  "*count: 800 \n" \
41  "*cycles: 16 \n" \
42  "*ncolors: 64 \n"
43 #define SMOOTH_COLORS
44 #include "xlockmore.h"          /* in xscreensaver distribution */
45 #else /* STANDALONE */
46 #include "xlock.h"              /* in xlockmore distribution */
47 #endif /* STANDALONE */
48
49 #ifdef MODE_thornbird
50
51 ModeSpecOpt thornbird_opts =
52 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
53
54 #ifdef USE_MODULES
55 ModStruct   thornbird_description =
56 {"thornbird", "init_thornbird", "draw_thornbird", "release_thornbird",
57  "refresh_thornbird", "init_thornbird", (char *) NULL, &thornbird_opts,
58  1000, 800, 16, 1, 64, 1.0, "",
59  "Shows an animated Bird in a Thorn Bush fractal map", 0, NULL};
60
61 #endif
62
63 #define balance_rand(v) ((LRAND()/MAXRAND*(v))-((v)/2)) /* random around 0 */
64
65 typedef struct {
66         int         maxx;
67         int         maxy;       /* max of the screen */
68         double      a;
69         double      b;
70         double      c;
71         double      d;
72         double      e;
73         double      i;
74         double      j;          /* thornbird parameters */
75     struct {
76           double  f1;
77           double  f2;
78         }           liss;
79     struct {
80           double  theta;
81           double  dtheta;
82           double  phi;
83           double  dphi;
84         }           tumble;
85     int         inc;
86         int         pix;
87         int         count;
88         int         nbuffers;
89         XPoint    **pointBuffer;        /* pointer for XDrawPoints */
90 } thornbirdstruct;
91
92 static thornbirdstruct *thornbirds = (thornbirdstruct *) NULL;
93
94 static void
95 free_thornbird(thornbirdstruct *hp)
96 {
97         if (hp->pointBuffer != NULL) {
98                 int         buffer;
99
100                 for (buffer = 0; buffer < hp->nbuffers; buffer++)
101                         if (hp->pointBuffer[buffer] != NULL)
102                                 (void) free((void *) hp->pointBuffer[buffer]);
103                 (void) free((void *) hp->pointBuffer);
104                 hp->pointBuffer = (XPoint **) NULL;
105         }
106 }
107
108 void
109 init_thornbird(ModeInfo * mi)
110 {
111         thornbirdstruct *hp;
112
113         if (thornbirds == NULL) {
114                 if ((thornbirds =
115                      (thornbirdstruct *) calloc(MI_NUM_SCREENS(mi),
116                                           sizeof (thornbirdstruct))) == NULL)
117                         return;
118         }
119         hp = &thornbirds[MI_SCREEN(mi)];
120
121
122         hp->maxx = MI_WIDTH(mi);
123         hp->maxy = MI_HEIGHT(mi);
124
125         hp->b = 0.1;
126         hp->i = hp->j = 0.1;
127
128         hp->pix = 0;
129         hp->inc = 0;
130
131         hp->nbuffers = MI_CYCLES(mi);
132
133         if (hp->pointBuffer == NULL)
134                 if ((hp->pointBuffer = (XPoint **) calloc(MI_CYCLES(mi),
135                                 sizeof (XPoint *))) == NULL) {
136                         free_thornbird(hp);
137                         return;
138                 }
139
140         if (hp->pointBuffer[0] == NULL)
141                 if ((hp->pointBuffer[0] = (XPoint *) malloc(MI_COUNT(mi) *
142                                 sizeof (XPoint))) == NULL) {
143                         free_thornbird(hp);
144                         return;
145                 }
146
147         /* select frequencies for parameter variation */
148         hp->liss.f1 = LRAND() % 5000;
149         hp->liss.f2 = LRAND() % 2000;
150
151         /* choose random 3D tumbling */
152         hp->tumble.theta = 0;
153         hp->tumble.phi = 0;
154         hp->tumble.dtheta = balance_rand(0.001);
155         hp->tumble.dphi = balance_rand(0.005);
156
157         /* Clear the background. */
158         MI_CLEARWINDOW(mi);
159
160         hp->count = 0;
161 }
162
163
164 void
165 draw_thornbird(ModeInfo * mi)
166 {
167         Display    *dsp = MI_DISPLAY(mi);
168         Window      win = MI_WINDOW(mi);
169         double      oldj, oldi;
170         int         batchcount = MI_COUNT(mi);
171         int         k;
172         XPoint     *xp;
173         GC          gc = MI_GC(mi);
174         int         erase;
175         int         current;
176
177         double      sint, cost, sinp, cosp;
178         thornbirdstruct *hp;
179
180         if (thornbirds == NULL)
181                 return;
182         hp = &thornbirds[MI_SCREEN(mi)];
183         if (hp->pointBuffer == NULL)
184                 return;
185
186         erase = (hp->inc + 1) % MI_CYCLES(mi);
187         current = hp->inc % MI_CYCLES(mi);
188         k = batchcount;
189
190
191         xp = hp->pointBuffer[current];
192
193         /* vary papameters */
194         hp->a = 1.99 + (0.4 * sin(hp->inc / hp->liss.f1) +
195                                         0.05 * cos(hp->inc / hp->liss.f2));
196         hp->c = 0.80 + (0.15 * cos(hp->inc / hp->liss.f1) +
197                                         0.05 * sin(hp->inc / hp->liss.f2));
198
199         /* vary view */
200         hp->tumble.theta += hp->tumble.dtheta;
201         hp->tumble.phi += hp->tumble.dphi;
202         sint = sin(hp->tumble.theta);
203         cost = cos(hp->tumble.theta);
204         sinp = sin(hp->tumble.phi);
205         cosp = cos(hp->tumble.phi);
206
207         while (k--) {
208                 oldj = hp->j;
209                 oldi = hp->i;
210
211                 hp->j = oldi;
212                 hp->i = (1 - hp->c) * cos(M_PI * hp->a * oldj) + hp->c * hp->b;
213                 hp->b = oldj;
214
215                 xp->x = (short)
216                   (hp->maxx / 2 * (1
217                                                    + sint*hp->j + cost*cosp*hp->i - cost*sinp*hp->b));
218                 xp->y = (short)
219                   (hp->maxy / 2 * (1
220                                                    - cost*hp->j + sint*cosp*hp->i - sint*sinp*hp->b));
221                 xp++;
222         }
223
224         MI_IS_DRAWN(mi) = True;
225
226         if (hp->pointBuffer[erase] == NULL) {
227                 if ((hp->pointBuffer[erase] = (XPoint *) malloc(MI_COUNT(mi) *
228                                 sizeof (XPoint))) == NULL) {
229                         free_thornbird(hp);
230                         return;
231                 }
232         } else {
233                 XSetForeground(dsp, gc, MI_BLACK_PIXEL(mi));
234                 XDrawPoints(dsp, win, gc, hp->pointBuffer[erase],
235                             batchcount, CoordModeOrigin);
236         }
237         if (MI_NPIXELS(mi) > 2) {
238                 XSetForeground(dsp, gc, MI_PIXEL(mi, hp->pix));
239                 if (erase == 0) /* change colours after "cycles" cycles */
240                         if (++hp->pix >= MI_NPIXELS(mi))
241                                 hp->pix = 0;
242         } else
243                 XSetForeground(dsp, gc, MI_WHITE_PIXEL(mi));
244
245         XDrawPoints(dsp, win, gc, hp->pointBuffer[current],
246                     batchcount, CoordModeOrigin);
247         hp->inc++;
248
249 }
250
251 void
252 release_thornbird(ModeInfo * mi)
253 {
254         if (thornbirds != NULL) {
255                 int         screen;
256
257                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
258                         free_thornbird(&thornbirds[screen]);
259                 (void) free((void *) thornbirds);
260                 thornbirds = (thornbirdstruct *) NULL;
261         }
262 }
263
264 void
265 refresh_thornbird(ModeInfo * mi)
266 {
267         MI_CLEARWINDOW(mi);
268 }
269
270 #endif /* MODE_thornbird */