diff options
author | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
---|---|---|
committer | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
commit | d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch) | |
tree | cbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/galaxy.c | |
download | xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip |
Original 5.40
Diffstat (limited to 'hacks/galaxy.c')
-rw-r--r-- | hacks/galaxy.c | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/hacks/galaxy.c b/hacks/galaxy.c new file mode 100644 index 0000000..3a6e1f7 --- /dev/null +++ b/hacks/galaxy.c @@ -0,0 +1,451 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* galaxy --- spinning galaxies */ +/* #include<math.h>*/ +#if 0 +static const char sccsid[] = "@(#)galaxy.c 4.04 97/07/28 xlockmore"; +#endif + +/* Originally done by Uli Siegmund <uli@wombat.okapi.sub.org> on Amiga + * for EGS in Cluster + * Port from Cluster/EGS to C/Intuition by Harald Backert + * Port to X11 and incorporation into xlockmore by Hubert Feyrer + * <hubert.feyrer@rz.uni-regensburg.de> + * + * 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. + * + * Revision History: + * 26-Aug-00: robert.nagtegaal@phil.uu.nl and roland@tschai.demon.nl: + * various improvements + * 10-May-97: jwz@jwz.org: turned into a standalone program. + * 18-Apr-97: Memory leak fixed by Tom Schmidt <tschmidt@micron.com> + * 07-Apr-97: Modified by Dave Mitchell <davem@magnet.com> + * 23-Oct-94: Modified by David Bagley <bagleyd@bigfoot.com> + * random star sizes + * colors change depending on velocity + * 10-Oct-94: Add colors by Hubert Feyer + * 30-Sep-94: Initial port by Hubert Feyer + * 09-Mar-94: VMS can generate a random number 0.0 which results in a + * division by zero, corrected by Jouk Jansen + * <joukj@crys.chem.uva.nl> + */ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 20000 \n" \ + "*count: -5 \n" \ + "*cycles: 250 \n" \ + "*ncolors: 64 \n" \ + "*fpsSolid: true \n" \ + "*ignoreRotation: True \n" \ + "*lowrez: True \n" \ + +# define UNIFORM_COLORS +# define release_galaxy 0 +# define reshape_galaxy 0 +# define galaxy_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +static Bool tracks; +static Bool spin; +static Bool dbufp; + +#define DEF_TRACKS "True" +#define DEF_SPIN "True" +#define DEF_DBUF "True" + +static XrmOptionDescRec opts[] = +{ + {"-tracks", ".galaxy.tracks", XrmoptionNoArg, "on"}, + {"+tracks", ".galaxy.tracks", XrmoptionNoArg, "off"}, + {"-spin", ".galaxy.spin", XrmoptionNoArg, "on"}, + {"+spin", ".galaxy.spin", XrmoptionNoArg, "off"}, + {"-dbuf", ".galaxy.dbuf", XrmoptionNoArg, "on"}, + {"+dbuf", ".galaxy.dbuf", XrmoptionNoArg, "off"}, +}; + +static argtype vars[] = +{ + {&tracks, "tracks", "Tracks", DEF_TRACKS, t_Bool}, + {&spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&dbufp, "dbuf", "Dbuf", DEF_DBUF, t_Bool}, +}; + +static OptionStruct desc[] = +{ + {"-/+tracks", "turn on/off star tracks"}, + {"-/+spin", "do/don't spin viewpoint"}, + {"-/+dbuf", "turn on/off double buffering."}, +}; + +ENTRYPOINT ModeSpecOpt galaxy_opts = +{sizeof opts / sizeof opts[0], opts, + sizeof vars / sizeof vars[0], vars, desc}; + + +#define FLOATRAND ((double) LRAND() / ((double) MAXRAND)) + +#if 0 +#define WRAP 1 /* Warp around edges */ +#define BOUNCE 1 /* Bounce from borders */ +#endif + +#define MINSIZE 1 +#define MINGALAXIES 2 +#define MAX_STARS 3000 +#define MAX_IDELTAT 50 +/* These come originally from the Cluster-version */ +#define DEFAULT_GALAXIES 3 +#define DEFAULT_STARS 1000 +#define DEFAULT_HITITERATIONS 7500 +#define DEFAULT_IDELTAT 200 /* 0.02 */ +#define EPSILON 0.00000001 + +#define sqrt_EPSILON 0.0001 + +#define DELTAT (MAX_IDELTAT * 0.0001) + +#define GALAXYRANGESIZE 0.1 +#define GALAXYMINSIZE 0.15 +#define QCONS 0.001 + + +#define COLORBASE 16 +/* colors per galaxy */ +/* #define COLORSTEP (NUMCOLORS/COLORBASE) */ +# define COLORSTEP (MI_NCOLORS(mi)/COLORBASE) + + +typedef struct { + double pos[3], vel[3]; +} Star; + + +typedef struct { + int mass; + int nstars; + Star *stars; + XPoint *oldpoints; + XPoint *newpoints; + double pos[3], vel[3]; + int galcol; +} Galaxy; + +typedef struct { + double mat[3][3]; /* Movement of stars(?) */ + double scale; /* Scale */ + int midx; /* Middle of screen, x */ + int midy; /* Middle of screen, y */ + double size; /* */ + double diff[3]; /* */ + Galaxy *galaxies; /* the Whole Universe */ + int ngalaxies; /* # galaxies */ + int f_hititerations; /* # iterations before restart */ + int step; /* */ + double rot_y; /* rotation of eye around center of universe, around +y-axis*/ + double rot_x; /* rotation of eye around center of universe, around +x-axis */ +} unistruct; + +static unistruct *universes = NULL; + +ENTRYPOINT void +free_galaxy(ModeInfo * mi) +{ + unistruct *gp = &universes[MI_SCREEN(mi)]; + if (gp->galaxies != NULL) { + int i; + + for (i = 0; i < gp->ngalaxies; i++) { + Galaxy *gt = &gp->galaxies[i]; + + if (gt->stars != NULL) + (void) free((void *) gt->stars); + if (gt->oldpoints != NULL) + (void) free((void *) gt->oldpoints); + if (gt->newpoints != NULL) + (void) free((void *) gt->newpoints); + } + (void) free((void *) gp->galaxies); + gp->galaxies = NULL; + } +} + +static void +startover(ModeInfo * mi) +{ + unistruct *gp = &universes[MI_SCREEN(mi)]; + int i, j; /* more tmp */ + double w1, w2; /* more tmp */ + double d, v, w, h; /* yet more tmp */ + + gp->step = 0; + gp->rot_y = 0; + gp->rot_x = 0; + + if (MI_BATCHCOUNT(mi) < -MINGALAXIES) + free_galaxy(mi); + gp->ngalaxies = MI_BATCHCOUNT(mi); + if (gp->ngalaxies < -MINGALAXIES) + gp->ngalaxies = NRAND(-gp->ngalaxies - MINGALAXIES + 1) + MINGALAXIES; + + else if (gp->ngalaxies < MINGALAXIES) + gp->ngalaxies = MINGALAXIES; + if (gp->galaxies == NULL) + gp->galaxies = (Galaxy *) calloc(gp->ngalaxies, sizeof (Galaxy)); + + for (i = 0; i < gp->ngalaxies; ++i) { + Galaxy *gt = &gp->galaxies[i]; + double sinw1, sinw2, cosw1, cosw2; + + gt->galcol = NRAND(COLORBASE - 2); + if (gt->galcol > 1) + gt->galcol += 2; /* Mult 8; 16..31 no green stars */ + /* Galaxies still may have some green stars but are not all green. */ + + if (gt->stars != NULL) { + (void) free((void *) gt->stars); + gt->stars = NULL; + } + gt->nstars = (NRAND(MAX_STARS / 2)) + MAX_STARS / 2; + gt->stars = (Star *) malloc(gt->nstars * sizeof (Star)); + gt->oldpoints = (XPoint *) malloc(gt->nstars * sizeof (XPoint)); + gt->newpoints = (XPoint *) malloc(gt->nstars * sizeof (XPoint)); + + w1 = 2.0 * M_PI * FLOATRAND; + w2 = 2.0 * M_PI * FLOATRAND; + sinw1 = SINF(w1); + sinw2 = SINF(w2); + cosw1 = COSF(w1); + cosw2 = COSF(w2); + + gp->mat[0][0] = cosw2; + gp->mat[0][1] = -sinw1 * sinw2; + gp->mat[0][2] = cosw1 * sinw2; + gp->mat[1][0] = 0.0; + gp->mat[1][1] = cosw1; + gp->mat[1][2] = sinw1; + gp->mat[2][0] = -sinw2; + gp->mat[2][1] = -sinw1 * cosw2; + gp->mat[2][2] = cosw1 * cosw2; + + gt->vel[0] = FLOATRAND * 2.0 - 1.0; + gt->vel[1] = FLOATRAND * 2.0 - 1.0; + gt->vel[2] = FLOATRAND * 2.0 - 1.0; + gt->pos[0] = -gt->vel[0] * DELTAT * gp->f_hititerations + FLOATRAND - +0.5; + gt->pos[1] = -gt->vel[1] * DELTAT * gp->f_hititerations + FLOATRAND - +0.5; + gt->pos[2] = -gt->vel[2] * DELTAT * gp->f_hititerations + FLOATRAND - +0.5; + + gt->mass = (int) (FLOATRAND * 1000.0) + 1; + + gp->size = GALAXYRANGESIZE * FLOATRAND + GALAXYMINSIZE; + + for (j = 0; j < gt->nstars; ++j) { + Star *st = >->stars[j]; + XPoint *oldp = >->oldpoints[j]; + XPoint *newp = >->newpoints[j]; + + double sinw, cosw; + + w = 2.0 * M_PI * FLOATRAND; + sinw = SINF(w); + cosw = COSF(w); + d = FLOATRAND * gp->size; + h = FLOATRAND * exp(-2.0 * (d / gp->size)) / 5.0 * gp->size; + if (FLOATRAND < 0.5) + h = -h; + st->pos[0] = gp->mat[0][0] * d * cosw + gp->mat[1][0] * d * sinw + +gp->mat[2][0] * h + gt->pos[0]; + st->pos[1] = gp->mat[0][1] * d * cosw + gp->mat[1][1] * d * sinw + +gp->mat[2][1] * h + gt->pos[1]; + st->pos[2] = gp->mat[0][2] * d * cosw + gp->mat[1][2] * d * sinw + +gp->mat[2][2] * h + gt->pos[2]; + + v = sqrt(gt->mass * QCONS / sqrt(d * d + h * h)); + st->vel[0] = -gp->mat[0][0] * v * sinw + gp->mat[1][0] * v * cosw + +gt->vel[0]; + st->vel[1] = -gp->mat[0][1] * v * sinw + gp->mat[1][1] * v * cosw + +gt->vel[1]; + st->vel[2] = -gp->mat[0][2] * v * sinw + gp->mat[1][2] * v * cosw + +gt->vel[2]; + + st->vel[0] *= DELTAT; + st->vel[1] *= DELTAT; + st->vel[2] *= DELTAT; + + oldp->x = 0; + oldp->y = 0; + newp->x = 0; + newp->y = 0; + } + + } + + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + +#if 0 + (void) printf("ngalaxies=%d, f_hititerations=%d\n", gp->ngalaxies, +gp->f_hititerations); + (void) printf("f_deltat=%g\n", DELTAT); + (void) printf("Screen: "); +#endif /*0 */ +} + +ENTRYPOINT void +init_galaxy(ModeInfo * mi) +{ + unistruct *gp; + + MI_INIT (mi, universes); + gp = &universes[MI_SCREEN(mi)]; + +# ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */ + dbufp = False; +# endif + + gp->f_hititerations = MI_CYCLES(mi); + + gp->scale = (double) (MI_WIN_WIDTH(mi) + MI_WIN_HEIGHT(mi)) / 8.0; + gp->midx = MI_WIN_WIDTH(mi) / 2; + gp->midy = MI_WIN_HEIGHT(mi) / 2; + startover(mi); +} + +ENTRYPOINT void +draw_galaxy(ModeInfo * mi) +{ + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); + unistruct *gp = &universes[MI_SCREEN(mi)]; + double d, eps, cox, six, cor, sir; /* tmp */ + int i, j, k; /* more tmp */ + XPoint *dummy = NULL; + + if (! dbufp) + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + + if(spin){ + gp->rot_y += 0.01; + gp->rot_x += 0.004; + } + + cox = COSF(gp->rot_y); + six = SINF(gp->rot_y); + cor = COSF(gp->rot_x); + sir = SINF(gp->rot_x); + + eps = 1/(EPSILON * sqrt_EPSILON * DELTAT * DELTAT * QCONS); + + for (i = 0; i < gp->ngalaxies; ++i) { + Galaxy *gt = &gp->galaxies[i]; + + for (j = 0; j < gp->galaxies[i].nstars; ++j) { + Star *st = >->stars[j]; + XPoint *newp = >->newpoints[j]; + double v0 = st->vel[0]; + double v1 = st->vel[1]; + double v2 = st->vel[2]; + + for (k = 0; k < gp->ngalaxies; ++k) { + Galaxy *gtk = &gp->galaxies[k]; + double d0 = gtk->pos[0] - st->pos[0]; + double d1 = gtk->pos[1] - st->pos[1]; + double d2 = gtk->pos[2] - st->pos[2]; + + d = d0 * d0 + d1 * d1 + d2 * d2; + if (d > EPSILON) + d = gtk->mass / (d * sqrt(d)) * DELTAT * DELTAT * QCONS; + else + d = gtk->mass / (eps * sqrt(eps)); + v0 += d0 * d; + v1 += d1 * d; + v2 += d2 * d; + } + + st->vel[0] = v0; + st->vel[1] = v1; + st->vel[2] = v2; + + st->pos[0] += v0; + st->pos[1] += v1; + st->pos[2] += v2; + + newp->x = (short) (((cox * st->pos[0]) - (six * st->pos[2])) * + gp->scale) + gp->midx; + newp->y = (short) (((cor * st->pos[1]) - (sir * ((six * st->pos[0]) + + (cox * st->pos[2])))) + * gp->scale) + gp->midy; + + } + + for (k = i + 1; k < gp->ngalaxies; ++k) { + Galaxy *gtk = &gp->galaxies[k]; + double d0 = gtk->pos[0] - gt->pos[0]; + double d1 = gtk->pos[1] - gt->pos[1]; + double d2 = gtk->pos[2] - gt->pos[2]; + + d = d0 * d0 + d1 * d1 + d2 * d2; + if (d > EPSILON) + d = 1 / (d * sqrt(d)) * DELTAT * QCONS; + else + d = 1 / (EPSILON * sqrt_EPSILON) * DELTAT * QCONS; + + d0 *= d; + d1 *= d; + d2 *= d; + gt->vel[0] += d0 * gtk->mass; + gt->vel[1] += d1 * gtk->mass; + gt->vel[2] += d2 * gtk->mass; + gtk->vel[0] -= d0 * gt->mass; + gtk->vel[1] -= d1 * gt->mass; + gtk->vel[2] -= d2 * gt->mass; + } + + gt->pos[0] += gt->vel[0] * DELTAT; + gt->pos[1] += gt->vel[1] * DELTAT; + gt->pos[2] += gt->vel[2] * DELTAT; + + if (dbufp) { + XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi)); + XDrawPoints(display, window, gc, gt->oldpoints, gt->nstars, + CoordModeOrigin); + } + XSetForeground(display, gc, MI_PIXEL(mi, COLORSTEP * gt->galcol)); + XDrawPoints(display, window, gc, gt->newpoints, gt->nstars, + CoordModeOrigin); + + dummy = gt->oldpoints; + gt->oldpoints = gt->newpoints; + gt->newpoints = dummy; + } + + gp->step++; + if (gp->step > gp->f_hititerations * 4) + startover(mi); +} + +#ifndef STANDALONE +ENTRYPOINT void +refresh_galaxy(ModeInfo * mi) +{ + /* Do nothing, it will refresh by itself */ +} +#endif + +XSCREENSAVER_MODULE ("Galaxy", galaxy) |