276 lines
6.5 KiB
C
276 lines
6.5 KiB
C
/* -*- Mode: C; tab-width: 4 -*- */
|
|
/* thornbird --- continuously varying Thornbird set */
|
|
|
|
#if !defined( lint ) && !defined( SABER )
|
|
static const char sccsid[] = "@(#)thornbird.c 5.00 2000/11/01 xlockmore";
|
|
|
|
#endif
|
|
|
|
/*-
|
|
* Copyright (c) 1996 by Tim Auckland <tda10.geo@yahoo.com>
|
|
*
|
|
* 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 PROGCLASS "Thornbird"
|
|
#define HACK_INIT init_thornbird
|
|
#define HACK_DRAW draw_thornbird
|
|
#define thornbird_opts xlockmore_opts
|
|
#define DEFAULTS "*delay: 1000 \n" \
|
|
"*count: 800 \n" \
|
|
"*cycles: 16 \n" \
|
|
"*ncolors: 100 \n"
|
|
#define SMOOTH_COLORS
|
|
#include "xlockmore.h" /* in xscreensaver distribution */
|
|
#else /* STANDALONE */
|
|
#include "xlock.h" /* in xlockmore distribution */
|
|
#endif /* STANDALONE */
|
|
|
|
#ifdef MODE_thornbird
|
|
|
|
ModeSpecOpt thornbird_opts =
|
|
{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
|
|
|
|
#ifdef USE_MODULES
|
|
ModStruct thornbird_description =
|
|
{"thornbird", "init_thornbird", "draw_thornbird", "release_thornbird",
|
|
"refresh_thornbird", "init_thornbird", (char *) NULL, þ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;
|
|
|
|
static void
|
|
free_thornbird(thornbirdstruct *hp)
|
|
{
|
|
if (hp->pointBuffer != NULL) {
|
|
int buffer;
|
|
|
|
for (buffer = 0; buffer < hp->nbuffers; buffer++)
|
|
if (hp->pointBuffer[buffer] != NULL)
|
|
free(hp->pointBuffer[buffer]);
|
|
free(hp->pointBuffer);
|
|
hp->pointBuffer = (XPoint **) NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
init_thornbird(ModeInfo * mi)
|
|
{
|
|
thornbirdstruct *hp;
|
|
|
|
if (thornbirds == NULL) {
|
|
if ((thornbirds =
|
|
(thornbirdstruct *) calloc(MI_NUM_SCREENS(mi),
|
|
sizeof (thornbirdstruct))) == NULL)
|
|
return;
|
|
}
|
|
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(hp);
|
|
return;
|
|
}
|
|
|
|
if (hp->pointBuffer[0] == NULL)
|
|
if ((hp->pointBuffer[0] = (XPoint *) malloc(MI_COUNT(mi) *
|
|
sizeof (XPoint))) == NULL) {
|
|
free_thornbird(hp);
|
|
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;
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
if (MI_CYCLES(mi) < 1) {
|
|
current = 0;
|
|
erase = 0;
|
|
} else {
|
|
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 (hp->pointBuffer[erase] == NULL) {
|
|
if ((hp->pointBuffer[erase] = (XPoint *) malloc(MI_COUNT(mi) *
|
|
sizeof (XPoint))) == NULL) {
|
|
free_thornbird(hp);
|
|
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 (erase == 0) /* change colours after "cycles" cycles */
|
|
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++;
|
|
|
|
}
|
|
|
|
void
|
|
release_thornbird(ModeInfo * mi)
|
|
{
|
|
if (thornbirds != NULL) {
|
|
int screen;
|
|
|
|
for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
|
|
free_thornbird(þbirds[screen]);
|
|
free(thornbirds);
|
|
thornbirds = (thornbirdstruct *) NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
refresh_thornbird(ModeInfo * mi)
|
|
{
|
|
MI_CLEARWINDOW(mi);
|
|
}
|
|
|
|
#endif /* MODE_thornbird */
|