/* -*- Mode: C; tab-width: 4 -*- */ /* thornbird --- continuously varying Thornbird set */ #if 0 static const char sccsid[] = "@(#)thornbird.c 5.00 2000/11/01 xlockmore"; #endif /*- * Copyright (c) 1996 by Tim Auckland * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * * "thornbird" shows a view of the "Bird in a Thornbush" fractal, * continuously varying the three free parameters. * * Revision History: * 01-Nov-2000: Allocation checks * 04-Jun-1999: 3D tumble added by Tim Auckland * 31-Jul-1997: Adapted from discrete.c Copyright (c) 1996 by Tim Auckland */ #ifdef STANDALONE # define MODE_thornbird #define DEFAULTS "*delay: 10000 \n" \ "*count: 100 \n" \ "*cycles: 400 \n" \ "*ncolors: 64 \n" \ "*fpsSolid: true \n" \ "*ignoreRotation: True \n" \ "*lowrez: True \n" \ # define BRIGHT_COLORS # define release_thornbird 0 # define reshape_thornbird 0 # define thornbird_handle_event 0 # include "xlockmore.h" /* in xscreensaver distribution */ #else /* STANDALONE */ # include "xlock.h" /* in xlockmore distribution */ #endif /* STANDALONE */ #ifdef MODE_thornbird ENTRYPOINT ModeSpecOpt thornbird_opts = {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; #ifdef USE_MODULES ModStruct thornbird_description = {"thornbird", "init_thornbird", "draw_thornbird", (char *) NULL, "refresh_thornbird", "init_thornbird", "free_thornbird", þbird_opts, 1000, 800, 16, 1, 64, 1.0, "", "Shows an animated Bird in a Thorn Bush fractal map", 0, NULL}; #endif #define balance_rand(v) ((LRAND()/MAXRAND*(v))-((v)/2)) /* random around 0 */ typedef struct { int maxx; int maxy; /* max of the screen */ double a; double b; double c; double d; double e; double i; double j; /* thornbird parameters */ struct { double f1; double f2; } liss; struct { double theta; double dtheta; double phi; double dphi; } tumble; int inc; int pix; int count; int nbuffers; XPoint **pointBuffer; /* pointer for XDrawPoints */ } thornbirdstruct; static thornbirdstruct *thornbirds = (thornbirdstruct *) NULL; ENTRYPOINT void free_thornbird(ModeInfo * mi) { thornbirdstruct *hp = þbirds[MI_SCREEN(mi)]; if (hp->pointBuffer != NULL) { int buffer; for (buffer = 0; buffer < hp->nbuffers; buffer++) if (hp->pointBuffer[buffer] != NULL) (void) free((void *) hp->pointBuffer[buffer]); (void) free((void *) hp->pointBuffer); hp->pointBuffer = (XPoint **) NULL; } } ENTRYPOINT void init_thornbird (ModeInfo * mi) { thornbirdstruct *hp; MI_INIT (mi, thornbirds); hp = þbirds[MI_SCREEN(mi)]; hp->maxx = MI_WIDTH(mi); hp->maxy = MI_HEIGHT(mi); hp->b = 0.1; hp->i = hp->j = 0.1; hp->pix = 0; hp->inc = 0; hp->nbuffers = MI_CYCLES(mi); if (hp->pointBuffer == NULL) if ((hp->pointBuffer = (XPoint **) calloc(MI_CYCLES(mi), sizeof (XPoint *))) == NULL) { free_thornbird(mi); return; } if (hp->pointBuffer[0] == NULL) if ((hp->pointBuffer[0] = (XPoint *) malloc(MI_COUNT(mi) * sizeof (XPoint))) == NULL) { free_thornbird(mi); return; } /* select frequencies for parameter variation */ hp->liss.f1 = LRAND() % 5000; hp->liss.f2 = LRAND() % 2000; /* choose random 3D tumbling */ hp->tumble.theta = 0; hp->tumble.phi = 0; hp->tumble.dtheta = balance_rand(0.001); hp->tumble.dphi = balance_rand(0.005); /* Clear the background. */ MI_CLEARWINDOW(mi); hp->count = 0; } ENTRYPOINT void draw_thornbird(ModeInfo * mi) { Display *dsp = MI_DISPLAY(mi); Window win = MI_WINDOW(mi); double oldj, oldi; int batchcount = MI_COUNT(mi); int k; XPoint *xp; GC gc = MI_GC(mi); int erase; int current; double sint, cost, sinp, cosp; thornbirdstruct *hp; if (thornbirds == NULL) return; hp = þbirds[MI_SCREEN(mi)]; if (hp->pointBuffer == NULL) return; erase = (hp->inc + 1) % MI_CYCLES(mi); current = hp->inc % MI_CYCLES(mi); k = batchcount; xp = hp->pointBuffer[current]; /* vary papameters */ hp->a = 1.99 + (0.4 * sin(hp->inc / hp->liss.f1) + 0.05 * cos(hp->inc / hp->liss.f2)); hp->c = 0.80 + (0.15 * cos(hp->inc / hp->liss.f1) + 0.05 * sin(hp->inc / hp->liss.f2)); /* vary view */ hp->tumble.theta += hp->tumble.dtheta; hp->tumble.phi += hp->tumble.dphi; sint = sin(hp->tumble.theta); cost = cos(hp->tumble.theta); sinp = sin(hp->tumble.phi); cosp = cos(hp->tumble.phi); while (k--) { oldj = hp->j; oldi = hp->i; hp->j = oldi; hp->i = (1 - hp->c) * cos(M_PI * hp->a * oldj) + hp->c * hp->b; hp->b = oldj; xp->x = (short) (hp->maxx / 2 * (1 + sint*hp->j + cost*cosp*hp->i - cost*sinp*hp->b)); xp->y = (short) (hp->maxy / 2 * (1 - cost*hp->j + sint*cosp*hp->i - sint*sinp*hp->b)); xp++; } MI_IS_DRAWN(mi) = True; if (MI_COUNT(mi) < 1) MI_COUNT(mi) = 1; if (hp->pointBuffer[erase] == NULL) { if ((hp->pointBuffer[erase] = (XPoint *) malloc(MI_COUNT(mi) * sizeof (XPoint))) == NULL) { free_thornbird(mi); return; } } else { XSetForeground(dsp, gc, MI_BLACK_PIXEL(mi)); XDrawPoints(dsp, win, gc, hp->pointBuffer[erase], batchcount, CoordModeOrigin); } if (MI_NPIXELS(mi) > 2) { XSetForeground(dsp, gc, MI_PIXEL(mi, hp->pix)); #if 0 if (erase == 0) /* change colours after "cycles" cycles */ #else if (!((hp->inc + 1) % (1 + (MI_CYCLES(mi) / 3)))) /* jwz: sooner */ #endif if (++hp->pix >= MI_NPIXELS(mi)) hp->pix = 0; } else XSetForeground(dsp, gc, MI_WHITE_PIXEL(mi)); XDrawPoints(dsp, win, gc, hp->pointBuffer[current], batchcount, CoordModeOrigin); hp->inc++; } #ifndef STANDALONE ENTRYPOINT void refresh_thornbird (ModeInfo * mi) { MI_CLEARWINDOW(mi); } #endif XSCREENSAVER_MODULE ("Thornbird", thornbird) #endif /* MODE_thornbird */