flame.c revision 546
546N/A/*
546N/A * Copyright (c) 1988-91 by Patrick J. Naughton.
546N/A *
546N/A * Permission to use, copy, modify, and distribute this software and its
546N/A * documentation for any purpose and without fee is hereby granted,
546N/A * provided that the above copyright notice appear in all copies and that
546N/A * both that copyright notice and this permission notice appear in
546N/A * supporting documentation.
546N/A *
546N/A * This file is provided AS IS with no warranties of any kind. The author
546N/A * shall have no liability with respect to the infringement of copyrights,
546N/A * trade secrets or any patents by this file or any part thereof. In no
546N/A * event will the author be liable for any lost revenue or profits or
546N/A * other special, indirect and consequential damages.
546N/A */
546N/A
546N/A/*
546N/A * Copyright 1994 Sun Microsystems, Inc. All rights reserved.
546N/A * Use is subject to license terms.
546N/A *
546N/A * Permission is hereby granted, free of charge, to any person obtaining a
546N/A * copy of this software and associated documentation files (the
546N/A * "Software"), to deal in the Software without restriction, including
546N/A * without limitation the rights to use, copy, modify, merge, publish,
546N/A * distribute, and/or sell copies of the Software, and to permit persons
546N/A * to whom the Software is furnished to do so, provided that the above
546N/A * copyright notice(s) and this permission notice appear in all copies of
546N/A * the Software and that both the above copyright notice(s) and this
546N/A * permission notice appear in supporting documentation.
546N/A *
546N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
546N/A * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
546N/A * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
546N/A * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
546N/A * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
546N/A * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
546N/A * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
546N/A * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
546N/A * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
546N/A *
546N/A * Except as contained in this notice, the name of a copyright holder
546N/A * shall not be used in advertising or otherwise to promote the sale, use
546N/A * or other dealings in this Software without prior written authorization
546N/A * of the copyright holder.
546N/A */
546N/A
546N/A#ifndef lint
546N/Astatic char sccsid[] = "@(#)flame.c 35.3 08/09/18 XLOCK";
546N/A#endif
546N/A/*-
546N/A * flame.c - recursive fractal cosmic dust.
546N/A *
546N/A * Copyright (c) 1991 by Patrick J. Naughton.
546N/A *
546N/A * See xlock.c for copying information.
546N/A *
546N/A * Revision History:
546N/A * 24-Jun-91: fixed portability problem with integer mod (%).
546N/A * 06-Jun-91: Written. (received from Spot, spot@cs.cmu.edu).
546N/A */
546N/A
546N/A#include "xlock.h"
546N/A#include <math.h>
546N/A
546N/A#define MAXTOTAL 10000
546N/A#define MAXBATCH 10
546N/A
546N/Atypedef struct {
546N/A double f[2][3][20]; /* three non-homogeneous transforms */
546N/A int max_levels;
546N/A int cur_level;
546N/A int SNUM;
546N/A int ANUM;
546N/A int width, height;
546N/A int num_points;
546N/A int total_points;
546N/A int pixcol;
546N/A Window win;
546N/A XPoint pts[MAXBATCH];
546N/A} flamestruct;
546N/A
546N/Aextern XColor ssblack[];
546N/Aextern XColor sswhite[];
546N/A
546N/Astatic flamestruct flames[MAXSCREENS];
546N/A
546N/Astatic short
546N/Ahalfrandom(mv)
546N/A int mv;
546N/A{
546N/A static short lasthalf = 0;
546N/A unsigned long r;
546N/A
546N/A if (lasthalf) {
546N/A r = lasthalf;
546N/A lasthalf = 0;
546N/A } else {
546N/A r = random();
546N/A lasthalf = r >> 16;
546N/A }
546N/A return r % mv;
546N/A}
546N/A
546N/Avoid
546N/Ainitflame(win)
546N/A Window win;
546N/A{
546N/A flamestruct *fs = &flames[screen];
546N/A XWindowAttributes xwa;
546N/A
546N/A srandom(time((long *) 0));
546N/A
546N/A XGetWindowAttributes(dsp, win, &xwa);
546N/A fs->width = xwa.width;
546N/A fs->height = xwa.height;
546N/A
546N/A fs->max_levels = batchcount;
546N/A fs->win = win;
546N/A
546N/A XSetForeground(dsp, Scr[screen].gc, ssblack[screen].pixel);
546N/A XFillRectangle(dsp, win, Scr[screen].gc, 0, 0, fs->width, fs->height);
546N/A
546N/A if (Scr[screen].npixels > 2) {
546N/A fs->pixcol = halfrandom(Scr[screen].npixels);
546N/A XSetForeground(dsp, Scr[screen].gc, Scr[screen].pixels[fs->pixcol]);
546N/A } else {
546N/A XSetForeground(dsp, Scr[screen].gc, sswhite[screen].pixel);
546N/A }
546N/A}
546N/A
546N/Astatic Bool
546N/Arecurse(fs, x, y, l)
546N/A flamestruct *fs;
546N/A register double x, y;
546N/A register int l;
546N/A{
546N/A int xp, yp, i;
546N/A double nx, ny;
546N/A
546N/A if (l == fs->max_levels) {
546N/A fs->total_points++;
546N/A if (fs->total_points > MAXTOTAL) /* how long each fractal runs */
546N/A return False;
546N/A
546N/A if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0) {
546N/A xp = fs->pts[fs->num_points].x = (int) ((fs->width / 2)
546N/A * (x + 1.0));
546N/A yp = fs->pts[fs->num_points].y = (int) ((fs->height / 2)
546N/A * (y + 1.0));
546N/A fs->num_points++;
546N/A if (fs->num_points > MAXBATCH) { /* point buffer size */
546N/A XDrawPoints(dsp, fs->win, Scr[screen].gc, fs->pts,
546N/A fs->num_points, CoordModeOrigin);
546N/A fs->num_points = 0;
546N/A }
546N/A }
546N/A } else {
546N/A for (i = 0; i < fs->SNUM; i++) {
546N/A nx = fs->f[0][0][i] * x + fs->f[0][1][i] * y + fs->f[0][2][i];
546N/A ny = fs->f[1][0][i] * x + fs->f[1][1][i] * y + fs->f[1][2][i];
546N/A if (i < fs->ANUM) {
546N/A nx = sin(nx);
546N/A ny = sin(ny);
546N/A }
546N/A if (!recurse(fs, nx, ny, l + 1))
546N/A return False;
546N/A }
546N/A }
546N/A return True;
546N/A}
546N/A
546N/A
546N/Avoid
546N/Adrawflame(win)
546N/A Window win;
546N/A{
546N/A flamestruct *fs = &flames[screen];
546N/A
546N/A int i, j, k;
546N/A static alt = 0;
546N/A
546N/A if (!(fs->cur_level++ % fs->max_levels)) {
546N/A XClearWindow(dsp, fs->win);
546N/A alt = !alt;
546N/A } else {
546N/A if (Scr[screen].npixels > 2) {
546N/A XSetForeground(dsp, Scr[screen].gc,
546N/A Scr[screen].pixels[fs->pixcol]);
546N/A if (--fs->pixcol < 0)
546N/A fs->pixcol = Scr[screen].npixels - 1;
546N/A }
546N/A }
546N/A
546N/A /* number of functions */
546N/A fs->SNUM = 2 + (fs->cur_level % 3);
546N/A
546N/A /* how many of them are of alternate form */
546N/A if (alt)
546N/A fs->ANUM = 0;
546N/A else
546N/A fs->ANUM = halfrandom(fs->SNUM) + 2;
546N/A
546N/A /* 6 coefs per function */
546N/A for (k = 0; k < fs->SNUM; k++) {
546N/A for (i = 0; i < 2; i++)
546N/A for (j = 0; j < 3; j++)
546N/A fs->f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0);
546N/A }
546N/A fs->num_points = 0;
546N/A fs->total_points = 0;
546N/A (void) recurse(fs, 0.0, 0.0, 0);
546N/A XDrawPoints(dsp, win, Scr[screen].gc,
546N/A fs->pts, fs->num_points, CoordModeOrigin);
546N/A}