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