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