1 | /* -*- Mode: C; tab-width: 4 -*- */ |
---|
2 | /* drift --- drifting recursive fractal cosmic flames */ |
---|
3 | |
---|
4 | #if 0 |
---|
5 | static const char sccsid[] = "@(#)drift.c 5.00 2000/11/01 xlockmore"; |
---|
6 | #endif |
---|
7 | |
---|
8 | /*- |
---|
9 | * Copyright (c) 1991 by Patrick J. Naughton. |
---|
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: Jamie Zawinski <jwz@jwz.org> compatible with xscreensaver |
---|
26 | * 01-Jan-1997: Moved new flame to drift. Compile time options now run time. |
---|
27 | * 01-Jun-1995: Updated by Scott Draves. |
---|
28 | * 27-Jun-1991: vary number of functions used. |
---|
29 | * 24-Jun-1991: fixed portability problem with integer mod (%). |
---|
30 | * 06-Jun-1991: Written, received from Scott Draves <spot@cs.cmu.edu> |
---|
31 | */ |
---|
32 | |
---|
33 | #ifdef STANDALONE |
---|
34 | #define MODE_drift |
---|
35 | #define PROGCLASS "Drift" |
---|
36 | #define HACK_INIT init_drift |
---|
37 | #define HACK_DRAW draw_drift |
---|
38 | #define drift_opts xlockmore_opts |
---|
39 | #define DEFAULTS "*delay: 10000 \n" \ |
---|
40 | "*count: 30 \n" \ |
---|
41 | "*ncolors: 200 \n" |
---|
42 | #define SMOOTH_COLORS |
---|
43 | #include "xlockmore.h" /* in xscreensaver distribution */ |
---|
44 | #include "erase.h" |
---|
45 | #else /* STANDALONE */ |
---|
46 | #include "xlock.h" /* in xlockmore distribution */ |
---|
47 | |
---|
48 | #endif /* STANDALONE */ |
---|
49 | |
---|
50 | #ifdef MODE_drift |
---|
51 | |
---|
52 | #define DEF_GROW "False" /* Grow fractals instead of animating one at a time, |
---|
53 | would then be like flame */ |
---|
54 | #define DEF_LISS "False" /* if this is defined then instead of a point |
---|
55 | bouncing around in a high dimensional sphere, we |
---|
56 | use lissojous figures. Only makes sense if |
---|
57 | grow is false. */ |
---|
58 | |
---|
59 | static Bool grow; |
---|
60 | static Bool liss; |
---|
61 | |
---|
62 | static XrmOptionDescRec opts[] = |
---|
63 | { |
---|
64 | {(char *) "-grow", (char *) ".drift.grow", XrmoptionNoArg, (caddr_t) "on"}, |
---|
65 | {(char *) "+grow", (char *) ".drift.grow", XrmoptionNoArg, (caddr_t) "off"}, |
---|
66 | {(char *) "-liss", (char *) ".drift.trail", XrmoptionNoArg, (caddr_t) "on"}, |
---|
67 | {(char *) "+liss", (char *) ".drift.trail", XrmoptionNoArg, (caddr_t) "off"} |
---|
68 | }; |
---|
69 | static argtype vars[] = |
---|
70 | { |
---|
71 | {(caddr_t *) & grow, (char *) "grow", (char *) "Grow", (char *) DEF_GROW, t_Bool}, |
---|
72 | {(caddr_t *) & liss, (char *) "liss", (char *) "Liss", (char *) DEF_LISS, t_Bool} |
---|
73 | }; |
---|
74 | static OptionStruct desc[] = |
---|
75 | { |
---|
76 | {(char *) "-/+grow", (char *) "turn on/off growing fractals, else they are animated"}, |
---|
77 | {(char *) "-/+liss", (char *) "turn on/off using lissojous figures to get points"} |
---|
78 | }; |
---|
79 | |
---|
80 | ModeSpecOpt drift_opts = |
---|
81 | {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; |
---|
82 | |
---|
83 | #ifdef USE_MODULES |
---|
84 | ModStruct drift_description = |
---|
85 | {"drift", "init_drift", "draw_drift", "release_drift", |
---|
86 | "refresh_drift", "init_drift", (char *) NULL, &drift_opts, |
---|
87 | 10000, 30, 1, 1, 64, 1.0, "", |
---|
88 | "Shows cosmic drifting flame fractals", 0, NULL}; |
---|
89 | |
---|
90 | #endif |
---|
91 | |
---|
92 | #define MAXBATCH1 200 /* mono */ |
---|
93 | #define MAXBATCH2 20 /* color */ |
---|
94 | #define FUSE 10 /* discard this many initial iterations */ |
---|
95 | #define NMAJORVARS 7 |
---|
96 | #define MAXLEV 10 |
---|
97 | |
---|
98 | typedef struct { |
---|
99 | /* shape of current flame */ |
---|
100 | int nxforms; |
---|
101 | double f[2][3][MAXLEV]; /* a bunch of non-homogeneous xforms */ |
---|
102 | int variation[10]; /* for each xform */ |
---|
103 | |
---|
104 | /* Animation */ |
---|
105 | double df[2][3][MAXLEV]; |
---|
106 | |
---|
107 | /* high-level control */ |
---|
108 | int mode; /* 0->slow/single 1->fast/many */ |
---|
109 | int nfractals; /* draw this many fractals */ |
---|
110 | int major_variation; |
---|
111 | int fractal_len; /* pts/fractal */ |
---|
112 | int color; |
---|
113 | int rainbow; /* more than one color per fractal |
---|
114 | 1-> computed by adding dimension to fractal */ |
---|
115 | |
---|
116 | int width, height; /* of window */ |
---|
117 | int timer; |
---|
118 | |
---|
119 | /* draw info about current flame */ |
---|
120 | int fuse; /* iterate this many before drawing */ |
---|
121 | int total_points; /* draw this many pts before fractal ends */ |
---|
122 | int npoints; /* how many we've computed but not drawn */ |
---|
123 | XPoint pts[MAXBATCH1]; /* here they are */ |
---|
124 | unsigned long pixcol; |
---|
125 | /* when drawing in color, we have a buffer per color */ |
---|
126 | int *ncpoints; |
---|
127 | XPoint *cpts; |
---|
128 | |
---|
129 | double x, y, c; |
---|
130 | int liss_time; |
---|
131 | Bool grow, liss; |
---|
132 | |
---|
133 | short lasthalf; |
---|
134 | long saved_random_bits; |
---|
135 | int nbits; |
---|
136 | } driftstruct; |
---|
137 | |
---|
138 | static driftstruct *drifts = (driftstruct *) NULL; |
---|
139 | |
---|
140 | static short |
---|
141 | halfrandom(driftstruct * dp, int mv) |
---|
142 | { |
---|
143 | unsigned long r; |
---|
144 | |
---|
145 | if (dp->lasthalf) { |
---|
146 | r = dp->lasthalf; |
---|
147 | dp->lasthalf = 0; |
---|
148 | } else { |
---|
149 | r = LRAND(); |
---|
150 | dp->lasthalf = (short) (r >> 16); |
---|
151 | } |
---|
152 | r = r % mv; |
---|
153 | return r; |
---|
154 | } |
---|
155 | |
---|
156 | static int |
---|
157 | frandom(driftstruct * dp, int n) |
---|
158 | { |
---|
159 | int result; |
---|
160 | |
---|
161 | if (3 > dp->nbits) { |
---|
162 | dp->saved_random_bits = LRAND(); |
---|
163 | dp->nbits = 31; |
---|
164 | } |
---|
165 | switch (n) { |
---|
166 | case 2: |
---|
167 | result = (int) (dp->saved_random_bits & 1); |
---|
168 | dp->saved_random_bits >>= 1; |
---|
169 | dp->nbits -= 1; |
---|
170 | return result; |
---|
171 | |
---|
172 | case 3: |
---|
173 | result = (int) (dp->saved_random_bits & 3); |
---|
174 | dp->saved_random_bits >>= 2; |
---|
175 | dp->nbits -= 2; |
---|
176 | if (3 == result) |
---|
177 | return frandom(dp, 3); |
---|
178 | return result; |
---|
179 | |
---|
180 | case 4: |
---|
181 | result = (int) (dp->saved_random_bits & 3); |
---|
182 | dp->saved_random_bits >>= 2; |
---|
183 | dp->nbits -= 2; |
---|
184 | return result; |
---|
185 | |
---|
186 | case 5: |
---|
187 | result = (int) (dp->saved_random_bits & 7); |
---|
188 | dp->saved_random_bits >>= 3; |
---|
189 | dp->nbits -= 3; |
---|
190 | if (4 < result) |
---|
191 | return frandom(dp, 5); |
---|
192 | return result; |
---|
193 | default: |
---|
194 | (void) fprintf(stderr, "bad arg to frandom\n"); |
---|
195 | } |
---|
196 | return 0; |
---|
197 | } |
---|
198 | |
---|
199 | #define DISTRIB_A (halfrandom(dp, 7000) + 9000) |
---|
200 | #define DISTRIB_B ((frandom(dp, 3) + 1) * (frandom(dp, 3) + 1) * 120000) |
---|
201 | #define LEN(x) (sizeof(x)/sizeof((x)[0])) |
---|
202 | |
---|
203 | static void |
---|
204 | initmode(ModeInfo * mi, int mode) |
---|
205 | { |
---|
206 | driftstruct *dp = &drifts[MI_SCREEN(mi)]; |
---|
207 | |
---|
208 | #define VARIATION_LEN 14 |
---|
209 | |
---|
210 | dp->mode = mode; |
---|
211 | |
---|
212 | dp->major_variation = halfrandom(dp, VARIATION_LEN); |
---|
213 | /* 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 6 */ |
---|
214 | dp->major_variation = ((dp->major_variation >= VARIATION_LEN >> 1) && |
---|
215 | (dp->major_variation < VARIATION_LEN - 1)) ? |
---|
216 | (dp->major_variation + 1) >> 1 : dp->major_variation >> 1; |
---|
217 | |
---|
218 | if (dp->grow) { |
---|
219 | dp->rainbow = 0; |
---|
220 | if (mode) { |
---|
221 | if (!dp->color || halfrandom(dp, 8)) { |
---|
222 | dp->nfractals = halfrandom(dp, 30) + 5; |
---|
223 | dp->fractal_len = DISTRIB_A; |
---|
224 | } else { |
---|
225 | dp->nfractals = halfrandom(dp, 5) + 5; |
---|
226 | dp->fractal_len = DISTRIB_B; |
---|
227 | } |
---|
228 | } else { |
---|
229 | dp->rainbow = dp->color; |
---|
230 | dp->nfractals = 1; |
---|
231 | dp->fractal_len = DISTRIB_B; |
---|
232 | } |
---|
233 | } else { |
---|
234 | dp->nfractals = 1; |
---|
235 | dp->rainbow = dp->color; |
---|
236 | dp->fractal_len = 2000000; |
---|
237 | } |
---|
238 | dp->fractal_len = (dp->fractal_len * MI_COUNT(mi)) / 20; |
---|
239 | |
---|
240 | MI_CLEARWINDOW(mi); |
---|
241 | } |
---|
242 | |
---|
243 | static void |
---|
244 | pick_df_coefs(ModeInfo * mi) |
---|
245 | { |
---|
246 | driftstruct *dp = &drifts[MI_SCREEN(mi)]; |
---|
247 | int i, j, k; |
---|
248 | double r; |
---|
249 | |
---|
250 | for (i = 0; i < dp->nxforms; i++) { |
---|
251 | |
---|
252 | r = 1e-6; |
---|
253 | for (j = 0; j < 2; j++) |
---|
254 | for (k = 0; k < 3; k++) { |
---|
255 | dp->df[j][k][i] = ((double) halfrandom(dp, 1000) / 500.0 - 1.0); |
---|
256 | r += dp->df[j][k][i] * dp->df[j][k][i]; |
---|
257 | } |
---|
258 | r = (3 + halfrandom(dp, 5)) * 0.01 / sqrt(r); |
---|
259 | for (j = 0; j < 2; j++) |
---|
260 | for (k = 0; k < 3; k++) |
---|
261 | dp->df[j][k][i] *= r; |
---|
262 | } |
---|
263 | } |
---|
264 | |
---|
265 | static void |
---|
266 | free_drift(driftstruct *dp) |
---|
267 | { |
---|
268 | if (dp->ncpoints != NULL) { |
---|
269 | (void) free((void *) dp->ncpoints); |
---|
270 | dp->ncpoints = (int *) NULL; |
---|
271 | } |
---|
272 | if (dp->cpts != NULL) { |
---|
273 | (void) free((void *) dp->cpts); |
---|
274 | dp->cpts = (XPoint *) NULL; |
---|
275 | } |
---|
276 | } |
---|
277 | |
---|
278 | static void |
---|
279 | initfractal(ModeInfo * mi) |
---|
280 | { |
---|
281 | driftstruct *dp = &drifts[MI_SCREEN(mi)]; |
---|
282 | int i, j, k; |
---|
283 | |
---|
284 | #define XFORM_LEN 9 |
---|
285 | |
---|
286 | dp->fuse = FUSE; |
---|
287 | dp->total_points = 0; |
---|
288 | |
---|
289 | if (!dp->ncpoints) { |
---|
290 | if ((dp->ncpoints = (int *) malloc(sizeof (int) * MI_NCOLORS(mi))) == |
---|
291 | NULL) { |
---|
292 | free_drift(dp); |
---|
293 | return; |
---|
294 | } |
---|
295 | } |
---|
296 | if (!dp->cpts) { |
---|
297 | if ((dp->cpts = (XPoint *) malloc(MAXBATCH2 * sizeof (XPoint) * |
---|
298 | MI_NCOLORS(mi))) == NULL) { |
---|
299 | free_drift(dp); |
---|
300 | return; |
---|
301 | } |
---|
302 | } |
---|
303 | |
---|
304 | if (dp->rainbow) |
---|
305 | for (i = 0; i < MI_NPIXELS(mi); i++) |
---|
306 | dp->ncpoints[i] = 0; |
---|
307 | else |
---|
308 | dp->npoints = 0; |
---|
309 | dp->nxforms = halfrandom(dp, XFORM_LEN); |
---|
310 | /* 2, 2, 2, 3, 3, 3, 4, 4, 5 */ |
---|
311 | dp->nxforms = (dp->nxforms >= XFORM_LEN - 1) + dp->nxforms / 3 + 2; |
---|
312 | |
---|
313 | dp->c = dp->x = dp->y = 0.0; |
---|
314 | if (dp->liss && !halfrandom(dp, 10)) { |
---|
315 | dp->liss_time = 0; |
---|
316 | } |
---|
317 | if (!dp->grow) |
---|
318 | pick_df_coefs(mi); |
---|
319 | for (i = 0; i < dp->nxforms; i++) { |
---|
320 | if (NMAJORVARS == dp->major_variation) |
---|
321 | dp->variation[i] = halfrandom(dp, NMAJORVARS); |
---|
322 | else |
---|
323 | dp->variation[i] = dp->major_variation; |
---|
324 | for (j = 0; j < 2; j++) |
---|
325 | for (k = 0; k < 3; k++) { |
---|
326 | if (dp->liss) |
---|
327 | dp->f[j][k][i] = sin(dp->liss_time * dp->df[j][k][i]); |
---|
328 | else |
---|
329 | dp->f[j][k][i] = ((double) halfrandom(dp, 1000) / 500.0 - 1.0); |
---|
330 | } |
---|
331 | } |
---|
332 | if (dp->color) |
---|
333 | dp->pixcol = MI_PIXEL(mi, halfrandom(dp, MI_NPIXELS(mi))); |
---|
334 | else |
---|
335 | dp->pixcol = MI_WHITE_PIXEL(mi); |
---|
336 | |
---|
337 | } |
---|
338 | |
---|
339 | |
---|
340 | void |
---|
341 | init_drift(ModeInfo * mi) |
---|
342 | { |
---|
343 | driftstruct *dp; |
---|
344 | |
---|
345 | if (drifts == NULL) { |
---|
346 | if ((drifts = (driftstruct *) calloc(MI_NUM_SCREENS(mi), |
---|
347 | sizeof (driftstruct))) == NULL) |
---|
348 | return; |
---|
349 | } |
---|
350 | dp = &drifts[MI_SCREEN(mi)]; |
---|
351 | |
---|
352 | dp->width = MI_WIDTH(mi); |
---|
353 | dp->height = MI_HEIGHT(mi); |
---|
354 | dp->color = MI_NPIXELS(mi) > 2; |
---|
355 | |
---|
356 | if (MI_IS_FULLRANDOM(mi)) { |
---|
357 | if (NRAND(3) == 0) |
---|
358 | dp->grow = True; |
---|
359 | else { |
---|
360 | dp->grow = False; |
---|
361 | dp->liss = (Bool) (LRAND() & 1); |
---|
362 | } |
---|
363 | } else { |
---|
364 | dp->grow = grow; |
---|
365 | if (dp->grow) |
---|
366 | dp->liss = False; |
---|
367 | else |
---|
368 | dp->liss = liss; |
---|
369 | } |
---|
370 | initmode(mi, 1); |
---|
371 | initfractal(mi); |
---|
372 | } |
---|
373 | |
---|
374 | static void |
---|
375 | iter(driftstruct * dp) |
---|
376 | { |
---|
377 | int i = frandom(dp, dp->nxforms); |
---|
378 | double nx, ny, nc; |
---|
379 | |
---|
380 | |
---|
381 | if (i) |
---|
382 | nc = (dp->c + 1.0) / 2.0; |
---|
383 | else |
---|
384 | nc = dp->c / 2.0; |
---|
385 | |
---|
386 | nx = dp->f[0][0][i] * dp->x + dp->f[0][1][i] * dp->y + dp->f[0][2][i]; |
---|
387 | ny = dp->f[1][0][i] * dp->x + dp->f[1][1][i] * dp->y + dp->f[1][2][i]; |
---|
388 | |
---|
389 | |
---|
390 | switch (dp->variation[i]) { |
---|
391 | case 1: |
---|
392 | /* sinusoidal */ |
---|
393 | nx = sin(nx); |
---|
394 | ny = sin(ny); |
---|
395 | break; |
---|
396 | case 2: |
---|
397 | { |
---|
398 | /* complex */ |
---|
399 | double r2 = nx * nx + ny * ny + 1e-6; |
---|
400 | |
---|
401 | nx = nx / r2; |
---|
402 | ny = ny / r2; |
---|
403 | break; |
---|
404 | } |
---|
405 | case 3: |
---|
406 | /* bent */ |
---|
407 | if (nx < 0.0) |
---|
408 | nx = nx * 2.0; |
---|
409 | if (ny < 0.0) |
---|
410 | ny = ny / 2.0; |
---|
411 | break; |
---|
412 | case 4: |
---|
413 | { |
---|
414 | /* swirl */ |
---|
415 | |
---|
416 | double r = (nx * nx + ny * ny); /* times k here is fun */ |
---|
417 | double c1 = sin(r); |
---|
418 | double c2 = cos(r); |
---|
419 | double t = nx; |
---|
420 | |
---|
421 | if (nx > 1e4 || nx < -1e4 || ny > 1e4 || ny < -1e4) |
---|
422 | ny = 1e4; |
---|
423 | else |
---|
424 | ny = c2 * t + c1 * ny; |
---|
425 | nx = c1 * nx - c2 * ny; |
---|
426 | break; |
---|
427 | } |
---|
428 | case 5: |
---|
429 | { |
---|
430 | /* horseshoe */ |
---|
431 | double r, c1, c2, t; |
---|
432 | |
---|
433 | /* Avoid atan2: DOMAIN error message */ |
---|
434 | if (nx == 0.0 && ny == 0.0) |
---|
435 | r = 0.0; |
---|
436 | else |
---|
437 | r = atan2(nx, ny); /* times k here is fun */ |
---|
438 | c1 = sin(r); |
---|
439 | c2 = cos(r); |
---|
440 | t = nx; |
---|
441 | |
---|
442 | nx = c1 * nx - c2 * ny; |
---|
443 | ny = c2 * t + c1 * ny; |
---|
444 | break; |
---|
445 | } |
---|
446 | case 6: |
---|
447 | { |
---|
448 | /* drape */ |
---|
449 | double t; |
---|
450 | |
---|
451 | /* Avoid atan2: DOMAIN error message */ |
---|
452 | if (nx == 0.0 && ny == 0.0) |
---|
453 | t = 0.0; |
---|
454 | else |
---|
455 | t = atan2(nx, ny) / M_PI; |
---|
456 | |
---|
457 | if (nx > 1e4 || nx < -1e4 || ny > 1e4 || ny < -1e4) |
---|
458 | ny = 1e4; |
---|
459 | else |
---|
460 | ny = sqrt(nx * nx + ny * ny) - 1.0; |
---|
461 | nx = t; |
---|
462 | break; |
---|
463 | } |
---|
464 | } |
---|
465 | |
---|
466 | #if 0 |
---|
467 | /* here are some others */ |
---|
468 | { |
---|
469 | /* broken */ |
---|
470 | if (nx > 1.0) |
---|
471 | nx = nx - 1.0; |
---|
472 | if (nx < -1.0) |
---|
473 | nx = nx + 1.0; |
---|
474 | if (ny > 1.0) |
---|
475 | ny = ny - 1.0; |
---|
476 | if (ny < -1.0) |
---|
477 | ny = ny + 1.0; |
---|
478 | break; |
---|
479 | } |
---|
480 | { |
---|
481 | /* complex sine */ |
---|
482 | double u = nx, v = ny; |
---|
483 | double ev = exp(v); |
---|
484 | double emv = exp(-v); |
---|
485 | |
---|
486 | nx = (ev + emv) * sin(u) / 2.0; |
---|
487 | ny = (ev - emv) * cos(u) / 2.0; |
---|
488 | } |
---|
489 | { |
---|
490 | |
---|
491 | /* polynomial */ |
---|
492 | if (nx < 0) |
---|
493 | nx = -nx * nx; |
---|
494 | else |
---|
495 | nx = nx * nx; |
---|
496 | |
---|
497 | if (ny < 0) |
---|
498 | ny = -ny * ny; |
---|
499 | else |
---|
500 | ny = ny * ny; |
---|
501 | } |
---|
502 | { |
---|
503 | /* spherical */ |
---|
504 | double r = 0.5 + sqrt(nx * nx + ny * ny + 1e-6); |
---|
505 | |
---|
506 | nx = nx / r; |
---|
507 | ny = ny / r; |
---|
508 | } |
---|
509 | { |
---|
510 | nx = atan(nx) / M_PI_2 |
---|
511 | ny = atan(ny) / M_PI_2 |
---|
512 | } |
---|
513 | #endif |
---|
514 | |
---|
515 | /* how to check nan too? some machines don't have finite(). |
---|
516 | don't need to check ny, it'll propogate */ |
---|
517 | if (nx > 1e4 || nx < -1e4) { |
---|
518 | nx = halfrandom(dp, 1000) / 500.0 - 1.0; |
---|
519 | ny = halfrandom(dp, 1000) / 500.0 - 1.0; |
---|
520 | dp->fuse = FUSE; |
---|
521 | } |
---|
522 | dp->x = nx; |
---|
523 | dp->y = ny; |
---|
524 | dp->c = nc; |
---|
525 | |
---|
526 | } |
---|
527 | |
---|
528 | static void |
---|
529 | draw(ModeInfo * mi, driftstruct * dp, Drawable d) |
---|
530 | { |
---|
531 | Display *display = MI_DISPLAY(mi); |
---|
532 | GC gc = MI_GC(mi); |
---|
533 | double x = dp->x; |
---|
534 | double y = dp->y; |
---|
535 | int fixed_x, fixed_y, npix, c, n; |
---|
536 | |
---|
537 | if (dp->fuse) { |
---|
538 | dp->fuse--; |
---|
539 | return; |
---|
540 | } |
---|
541 | if (!(x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0)) |
---|
542 | return; |
---|
543 | |
---|
544 | fixed_x = (int) ((dp->width / 2) * (x + 1.0)); |
---|
545 | fixed_y = (int) ((dp->height / 2) * (y + 1.0)); |
---|
546 | |
---|
547 | if (!dp->rainbow) { |
---|
548 | |
---|
549 | dp->pts[dp->npoints].x = fixed_x; |
---|
550 | dp->pts[dp->npoints].y = fixed_y; |
---|
551 | dp->npoints++; |
---|
552 | if (dp->npoints == MAXBATCH1) { |
---|
553 | XSetForeground(display, gc, dp->pixcol); |
---|
554 | XDrawPoints(display, d, gc, dp->pts, dp->npoints, CoordModeOrigin); |
---|
555 | dp->npoints = 0; |
---|
556 | } |
---|
557 | } else { |
---|
558 | |
---|
559 | npix = MI_NPIXELS(mi); |
---|
560 | c = (int) (dp->c * npix); |
---|
561 | |
---|
562 | if (c < 0) |
---|
563 | c = 0; |
---|
564 | if (c >= npix) |
---|
565 | c = npix - 1; |
---|
566 | n = dp->ncpoints[c]; |
---|
567 | dp->cpts[c * MAXBATCH2 + n].x = fixed_x; |
---|
568 | dp->cpts[c * MAXBATCH2 + n].y = fixed_y; |
---|
569 | if (++dp->ncpoints[c] == MAXBATCH2) { |
---|
570 | XSetForeground(display, gc, MI_PIXEL(mi, c)); |
---|
571 | XDrawPoints(display, d, gc, &(dp->cpts[c * MAXBATCH2]), |
---|
572 | dp->ncpoints[c], CoordModeOrigin); |
---|
573 | dp->ncpoints[c] = 0; |
---|
574 | } |
---|
575 | } |
---|
576 | } |
---|
577 | |
---|
578 | static void |
---|
579 | draw_flush(ModeInfo * mi, driftstruct * dp, Drawable d) |
---|
580 | { |
---|
581 | Display *display = MI_DISPLAY(mi); |
---|
582 | GC gc = MI_GC(mi); |
---|
583 | |
---|
584 | if (dp->rainbow) { |
---|
585 | int npix = MI_NPIXELS(mi); |
---|
586 | int i; |
---|
587 | |
---|
588 | for (i = 0; i < npix; i++) { |
---|
589 | if (dp->ncpoints[i]) { |
---|
590 | XSetForeground(display, gc, MI_PIXEL(mi, i)); |
---|
591 | XDrawPoints(display, d, gc, &(dp->cpts[i * MAXBATCH2]), |
---|
592 | dp->ncpoints[i], CoordModeOrigin); |
---|
593 | dp->ncpoints[i] = 0; |
---|
594 | } |
---|
595 | } |
---|
596 | } else { |
---|
597 | if (dp->npoints) |
---|
598 | XSetForeground(display, gc, dp->pixcol); |
---|
599 | XDrawPoints(display, d, gc, dp->pts, |
---|
600 | dp->npoints, CoordModeOrigin); |
---|
601 | dp->npoints = 0; |
---|
602 | } |
---|
603 | } |
---|
604 | |
---|
605 | |
---|
606 | void |
---|
607 | draw_drift(ModeInfo * mi) |
---|
608 | { |
---|
609 | Window window = MI_WINDOW(mi); |
---|
610 | driftstruct *dp; |
---|
611 | |
---|
612 | if (drifts == NULL) |
---|
613 | return; |
---|
614 | dp = &drifts[MI_SCREEN(mi)]; |
---|
615 | if (dp->ncpoints == NULL) |
---|
616 | return; |
---|
617 | |
---|
618 | MI_IS_DRAWN(mi) = True; |
---|
619 | dp->timer = 3000; |
---|
620 | while (dp->timer) { |
---|
621 | iter(dp); |
---|
622 | draw(mi, dp, window); |
---|
623 | if (dp->total_points++ > dp->fractal_len) { |
---|
624 | draw_flush(mi, dp, window); |
---|
625 | if (0 == --dp->nfractals) { |
---|
626 | #ifdef STANDALONE |
---|
627 | XSync(MI_DISPLAY(mi), False); |
---|
628 | sleep(4); /* #### make settable */ |
---|
629 | erase_full_window(MI_DISPLAY(mi), MI_WINDOW(mi)); |
---|
630 | #endif /* STANDALONE */ |
---|
631 | initmode(mi, frandom(dp, 2)); |
---|
632 | } |
---|
633 | initfractal(mi); |
---|
634 | } |
---|
635 | dp->timer--; |
---|
636 | } |
---|
637 | if (!dp->grow) { |
---|
638 | int i, j, k; |
---|
639 | |
---|
640 | draw_flush(mi, dp, window); |
---|
641 | if (dp->liss) |
---|
642 | dp->liss_time++; |
---|
643 | for (i = 0; i < dp->nxforms; i++) |
---|
644 | for (j = 0; j < 2; j++) |
---|
645 | for (k = 0; k < 3; k++) { |
---|
646 | if (dp->liss) |
---|
647 | dp->f[j][k][i] = sin(dp->liss_time * dp->df[j][k][i]); |
---|
648 | else { |
---|
649 | double t = dp->f[j][k][i] += dp->df[j][k][i]; |
---|
650 | |
---|
651 | if (t < -1.0 || 1.0 < t) |
---|
652 | dp->df[j][k][i] *= -1.0; |
---|
653 | } |
---|
654 | } |
---|
655 | } |
---|
656 | } |
---|
657 | |
---|
658 | void |
---|
659 | release_drift(ModeInfo * mi) |
---|
660 | { |
---|
661 | if (drifts != NULL) { |
---|
662 | int screen; |
---|
663 | |
---|
664 | for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) |
---|
665 | free_drift(&drifts[screen]); |
---|
666 | (void) free((void *) drifts); |
---|
667 | drifts = (driftstruct *) NULL; |
---|
668 | } |
---|
669 | } |
---|
670 | |
---|
671 | void |
---|
672 | refresh_drift(ModeInfo * mi) |
---|
673 | { |
---|
674 | MI_CLEARWINDOW(mi); |
---|
675 | } |
---|
676 | |
---|
677 | #endif /* MODE_drift */ |
---|