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 <Tim.Auckland@Procket.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 PROGCLASS "Thornbird" |
---|
35 | #define HACK_INIT init_thornbird |
---|
36 | #define HACK_DRAW draw_thornbird |
---|
37 | #define thornbird_opts xlockmore_opts |
---|
38 | #define DEFAULTS "*delay: 10000 \n" \ |
---|
39 | "*count: 800 \n" \ |
---|
40 | "*cycles: 16 \n" \ |
---|
41 | "*ncolors: 64 \n" |
---|
42 | #define SMOOTH_COLORS |
---|
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 | 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, þbird_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 | 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 = þbirds[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 | 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 = þbirds[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 (erase == 0) /* change colours after "cycles" cycles */ |
---|
239 | if (++hp->pix >= MI_NPIXELS(mi)) |
---|
240 | hp->pix = 0; |
---|
241 | } else |
---|
242 | XSetForeground(dsp, gc, MI_WHITE_PIXEL(mi)); |
---|
243 | |
---|
244 | XDrawPoints(dsp, win, gc, hp->pointBuffer[current], |
---|
245 | batchcount, CoordModeOrigin); |
---|
246 | hp->inc++; |
---|
247 | |
---|
248 | } |
---|
249 | |
---|
250 | void |
---|
251 | release_thornbird(ModeInfo * mi) |
---|
252 | { |
---|
253 | if (thornbirds != NULL) { |
---|
254 | int screen; |
---|
255 | |
---|
256 | for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) |
---|
257 | free_thornbird(þbirds[screen]); |
---|
258 | (void) free((void *) thornbirds); |
---|
259 | thornbirds = (thornbirdstruct *) NULL; |
---|
260 | } |
---|
261 | } |
---|
262 | |
---|
263 | void |
---|
264 | refresh_thornbird(ModeInfo * mi) |
---|
265 | { |
---|
266 | MI_CLEARWINDOW(mi); |
---|
267 | } |
---|
268 | |
---|
269 | #endif /* MODE_thornbird */ |
---|