source: trunk/third/xscreensaver/hacks/galaxy.c @ 20148

Revision 20148, 11.7 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 4 -*- */
2/* galaxy --- spinning galaxies */
3/* #include<math.h>*/
4#if 0
5static const char sccsid[] = "@(#)galaxy.c 4.04 97/07/28 xlockmore";
6#endif
7
8/* Originally done by Uli Siegmund <uli@wombat.okapi.sub.org> on Amiga
9 *   for EGS in Cluster
10 * Port from Cluster/EGS to C/Intuition by Harald Backert
11 * Port to X11 and incorporation into xlockmore by Hubert Feyrer
12 *   <hubert.feyrer@rz.uni-regensburg.de>
13 *
14 * Permission to use, copy, modify, and distribute this software and its
15 * documentation for any purpose and without fee is hereby granted,
16 * provided that the above copyright notice appear in all copies and that
17 * both that copyright notice and this permission notice appear in
18 * supporting documentation.
19 *
20 * This file is provided AS IS with no warranties of any kind.  The author
21 * shall have no liability with respect to the infringement of copyrights,
22 * trade secrets or any patents by this file or any part thereof.  In no
23 * event will the author be liable for any lost revenue or profits or
24 * other special, indirect and consequential damages.
25 *
26 * Revision History:
27 * 26-Aug-00: robert.nagtegaal@phil.uu.nl and roland@tschai.demon.nl:
28 *            various improvements
29 * 10-May-97: jwz@jwz.org: turned into a standalone program.
30 * 18-Apr-97: Memory leak fixed by Tom Schmidt <tschmidt@micron.com>
31 * 07-Apr-97: Modified by Dave Mitchell <davem@magnet.com>
32 * 23-Oct-94: Modified by David Bagley <bagleyd@bigfoot.com>
33 *  random star sizes
34 *  colors change depending on velocity
35 * 10-Oct-94: Add colors by Hubert Feyer
36 * 30-Sep-94: Initial port by Hubert Feyer
37 * 09-Mar-94: VMS can generate a random number 0.0 which results in a
38 *            division by zero, corrected by Jouk Jansen
39 *            <joukj@crys.chem.uva.nl>
40 */
41
42#ifdef STANDALONE
43# define PROGCLASS     "Galaxy"
44# define HACK_INIT     init_galaxy
45# define HACK_DRAW     draw_galaxy
46# define galaxy_opts    xlockmore_opts
47# define DEFAULTS "*delay:  100  \n"   \
48     "*count:  -5   \n"   \
49     "*cycles:  250  \n"   \
50     "*size:   -3   \n"   \
51     "*ncolors:  64  \n"
52# define UNIFORM_COLORS
53# include "xlockmore.h"    /* from the xscreensaver distribution */
54#else  /* !STANDALONE */
55# include "xlock.h"     /* from the xlockmore distribution */
56#endif /* !STANDALONE */
57
58static Bool tracks;
59
60#define DEF_TRACKS "True"
61
62static XrmOptionDescRec opts[] =
63{
64 {"-tracks", ".galaxy.tracks", XrmoptionNoArg, (caddr_t) "on"},
65 {"+tracks", ".galaxy.tracks", XrmoptionNoArg, (caddr_t) "off"}
66};
67
68static argtype vars[] =
69{
70 {(caddr_t *) & tracks, "tracks", "Tracks", DEF_TRACKS, t_Bool}
71};
72
73static OptionStruct desc[] =
74{
75 {"-/+tracks", "turn on/off star tracks"}
76};
77
78ModeSpecOpt galaxy_opts = { 2, opts, 1, vars, desc };
79
80
81#define FLOATRAND ((double) LRAND() / ((double) MAXRAND))
82
83#if 0
84#define WRAP       1  /* Warp around edges */
85#define BOUNCE     1  /* Bounce from borders */
86#endif
87
88#define MINSIZE       1
89#define MINGALAXIES    2
90#define MAX_STARS    3000
91#define MAX_IDELTAT    50
92/* These come originally from the Cluster-version */
93#define DEFAULT_GALAXIES  3
94#define DEFAULT_STARS    1000
95#define DEFAULT_HITITERATIONS  7500
96#define DEFAULT_IDELTAT    200 /* 0.02 */
97#define EPSILON 0.00000001
98
99#define sqrt_EPSILON 0.0001
100
101#define DELTAT (MAX_IDELTAT * 0.0001)
102
103#define GALAXYRANGESIZE  0.1
104#define GALAXYMINSIZE  0.15
105#define QCONS    0.001
106
107
108#define COLORBASE  16
109  /* Colors for stars start here */
110#define COLORSTEP  (NUMCOLORS/COLORBASE) /* NUMCOLORS / COLORBASE colors
111per galaxy */
112
113
114typedef struct {
115 double      pos[3], vel[3];
116} Star;
117
118
119typedef struct {
120 int         mass;
121 int         nstars;
122 Star       *stars;
123 XPoint     *oldpoints;
124 XPoint     *newpoints;
125 double      pos[3], vel[3];
126 int         galcol;
127} Galaxy;
128
129typedef struct {
130 double      mat[3][3]; /* Movement of stars(?) */
131 double      scale; /* Scale */
132 int         midx; /* Middle of screen, x */
133 int         midy; /* Middle of screen, y */
134 double      size; /* */
135 double      diff[3]; /* */
136 Galaxy     *galaxies; /* the Whole Universe */
137 int         ngalaxies; /* # galaxies */
138 int         f_hititerations; /* # iterations before restart */
139 int         step; /* */
140 double      rot_y; /* rotation of eye around center of universe, around
141y-axis*/
142 double      rot_x; /* rotation of eye around center of universe, around
143x-axis */
144} unistruct;
145
146static unistruct *universes = NULL;
147
148static void
149free_galaxies(unistruct * gp)
150{
151 if (gp->galaxies != NULL) {
152  int         i;
153
154  for (i = 0; i < gp->ngalaxies; i++) {
155   Galaxy     *gt = &gp->galaxies[i];
156
157   if (gt->stars != NULL)
158    (void) free((void *) gt->stars);
159   if (gt->oldpoints != NULL)
160       (void) free((void *) gt->oldpoints);
161   if (gt->newpoints != NULL)
162       (void) free((void *) gt->newpoints);
163  }
164  (void) free((void *) gp->galaxies);
165  gp->galaxies = NULL;
166 }
167}
168
169static void
170startover(ModeInfo * mi)
171{
172 unistruct  *gp = &universes[MI_SCREEN(mi)];
173 int         i, j; /* more tmp */
174 double      w1, w2; /* more tmp */
175 double      d, v, w, h; /* yet more tmp */
176
177 gp->step = 0;
178 gp->rot_y = 0;
179 gp->rot_x = 0;
180
181 if (MI_BATCHCOUNT(mi) < -MINGALAXIES)
182  free_galaxies(gp);
183 gp->ngalaxies = MI_BATCHCOUNT(mi);
184 if (gp->ngalaxies < -MINGALAXIES)
185  gp->ngalaxies = NRAND(-gp->ngalaxies - MINGALAXIES + 1) + MINGALAXIES;
186
187 else if (gp->ngalaxies < MINGALAXIES)
188  gp->ngalaxies = MINGALAXIES;
189 if (gp->galaxies == NULL)
190  gp->galaxies = (Galaxy *) calloc(gp->ngalaxies, sizeof (Galaxy));
191
192 for (i = 0; i < gp->ngalaxies; ++i) {
193  Galaxy     *gt = &gp->galaxies[i];
194  double      sinw1, sinw2, cosw1, cosw2;
195
196  gt->galcol = NRAND(COLORBASE - 2);
197  if (gt->galcol > 1)
198   gt->galcol += 2; /* Mult 8; 16..31 no green stars */
199  /* Galaxies still may have some green stars but are not all green. */
200
201  if (gt->stars != NULL) {
202   (void) free((void *) gt->stars);
203   gt->stars = NULL;
204  }
205  gt->nstars = (NRAND(MAX_STARS / 2)) + MAX_STARS / 2;
206  gt->stars = (Star *) malloc(gt->nstars * sizeof (Star));
207  gt->oldpoints = (XPoint *) malloc(gt->nstars * sizeof (XPoint));
208  gt->newpoints = (XPoint *) malloc(gt->nstars * sizeof (XPoint));
209
210  w1 = 2.0 * M_PI * FLOATRAND;
211  w2 = 2.0 * M_PI * FLOATRAND;
212  sinw1 = SINF(w1);
213  sinw2 = SINF(w2);
214  cosw1 = COSF(w1);
215  cosw2 = COSF(w2);
216
217  gp->mat[0][0] = cosw2;
218  gp->mat[0][1] = -sinw1 * sinw2;
219  gp->mat[0][2] = cosw1 * sinw2;
220  gp->mat[1][0] = 0.0;
221  gp->mat[1][1] = cosw1;
222  gp->mat[1][2] = sinw1;
223  gp->mat[2][0] = -sinw2;
224  gp->mat[2][1] = -sinw1 * cosw2;
225  gp->mat[2][2] = cosw1 * cosw2;
226
227  gt->vel[0] = FLOATRAND * 2.0 - 1.0;
228  gt->vel[1] = FLOATRAND * 2.0 - 1.0;
229  gt->vel[2] = FLOATRAND * 2.0 - 1.0;
230  gt->pos[0] = -gt->vel[0] * DELTAT * gp->f_hititerations + FLOATRAND -
2310.5;
232  gt->pos[1] = -gt->vel[1] * DELTAT * gp->f_hititerations + FLOATRAND -
2330.5;
234  gt->pos[2] = -gt->vel[2] * DELTAT * gp->f_hititerations + FLOATRAND -
2350.5;
236
237  gt->mass = (int) (FLOATRAND * 1000.0) + 1;
238
239  gp->size = GALAXYRANGESIZE * FLOATRAND + GALAXYMINSIZE;
240
241  for (j = 0; j < gt->nstars; ++j) {
242   Star       *st = &gt->stars[j];
243   XPoint     *oldp = &gt->oldpoints[j];
244   XPoint     *newp = &gt->newpoints[j];
245
246   double      sinw, cosw;
247
248   w = 2.0 * M_PI * FLOATRAND;
249   sinw = SINF(w);
250   cosw = COSF(w);
251   d = FLOATRAND * gp->size;
252   h = FLOATRAND * exp(-2.0 * (d / gp->size)) / 5.0 * gp->size;
253   if (FLOATRAND < 0.5)
254    h = -h;
255   st->pos[0] = gp->mat[0][0] * d * cosw + gp->mat[1][0] * d * sinw +
256gp->mat[2][0] * h + gt->pos[0];
257   st->pos[1] = gp->mat[0][1] * d * cosw + gp->mat[1][1] * d * sinw +
258gp->mat[2][1] * h + gt->pos[1];
259   st->pos[2] = gp->mat[0][2] * d * cosw + gp->mat[1][2] * d * sinw +
260gp->mat[2][2] * h + gt->pos[2];
261
262   v = sqrt(gt->mass * QCONS / sqrt(d * d + h * h));
263   st->vel[0] = -gp->mat[0][0] * v * sinw + gp->mat[1][0] * v * cosw +
264gt->vel[0];
265   st->vel[1] = -gp->mat[0][1] * v * sinw + gp->mat[1][1] * v * cosw +
266gt->vel[1];
267   st->vel[2] = -gp->mat[0][2] * v * sinw + gp->mat[1][2] * v * cosw +
268gt->vel[2];
269
270   st->vel[0] *= DELTAT;
271   st->vel[1] *= DELTAT;
272   st->vel[2] *= DELTAT;
273
274   oldp->x = 0;
275   oldp->y = 0;
276   newp->x = 0;
277   newp->y = 0;
278  }
279
280 }
281
282 XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
283
284#if 0
285 (void) printf("ngalaxies=%d, f_hititerations=%d\n", gp->ngalaxies,
286gp->f_hititerations);
287 (void) printf("f_deltat=%g\n", DELTAT);
288 (void) printf("Screen: ");
289#endif /*0 */
290}
291
292void
293init_galaxy(ModeInfo * mi)
294{
295 unistruct  *gp;
296
297 if (universes == NULL) {
298  if ((universes = (unistruct *) calloc(MI_NUM_SCREENS(mi),
299      sizeof (unistruct))) == NULL)
300   return;
301 }
302 gp = &universes[MI_SCREEN(mi)];
303
304 gp->f_hititerations = MI_CYCLES(mi);
305
306 gp->scale = (double) (MI_WIN_WIDTH(mi) + MI_WIN_HEIGHT(mi)) / 8.0;
307 gp->midx =  MI_WIN_WIDTH(mi)  / 2;
308 gp->midy =  MI_WIN_HEIGHT(mi) / 2;
309 startover(mi);
310}
311
312void
313draw_galaxy(ModeInfo * mi)
314{
315 Display    *display = MI_DISPLAY(mi);
316 Window      window = MI_WINDOW(mi);
317 GC          gc = MI_GC(mi);
318 unistruct  *gp = &universes[MI_SCREEN(mi)];
319 double      d, eps, cox, six, cor, sir;  /* tmp */
320 int         i, j, k; /* more tmp */
321    XPoint    *dummy = NULL;
322
323    gp->rot_y += 0.01;
324 gp->rot_x += 0.004;
325
326 cox = COSF(gp->rot_y);
327 six = SINF(gp->rot_y);
328    cor = COSF(gp->rot_x);
329    sir = SINF(gp->rot_x);
330
331    eps = 1/(EPSILON * sqrt_EPSILON * DELTAT * DELTAT * QCONS);
332
333 for (i = 0; i < gp->ngalaxies; ++i) {
334  Galaxy     *gt = &gp->galaxies[i];
335
336  for (j = 0; j < gp->galaxies[i].nstars; ++j) {
337   Star       *st = &gt->stars[j];
338   XPoint     *newp = &gt->newpoints[j];
339   double      v0 = st->vel[0];
340   double      v1 = st->vel[1];
341   double      v2 = st->vel[2];
342
343   for (k = 0; k < gp->ngalaxies; ++k) {
344    Galaxy     *gtk = &gp->galaxies[k];
345    double      d0 = gtk->pos[0] - st->pos[0];
346    double      d1 = gtk->pos[1] - st->pos[1];
347    double      d2 = gtk->pos[2] - st->pos[2];
348
349    d = d0 * d0 + d1 * d1 + d2 * d2;
350    if (d > EPSILON)
351     d = gt->mass / (d * sqrt(d)) * DELTAT * DELTAT * QCONS;
352    else
353        d = gt->mass * eps;
354    v0 += d0 * d;
355    v1 += d1 * d;
356    v2 += d2 * d;
357   }
358
359   st->vel[0] = v0;
360   st->vel[1] = v1;
361   st->vel[2] = v2;
362
363   st->pos[0] += v0;
364   st->pos[1] += v1;
365   st->pos[2] += v2;
366
367   newp->x = (short) (((cox * st->pos[0]) - (six * st->pos[2])) *
368gp->scale) + gp->midx;
369   newp->y = (short) (((cor * st->pos[1]) - (sir * ((six * st->pos[0]) +
370(cox * st->pos[2])))) * gp->scale) + gp->midy;
371
372  }
373
374  for (k = i + 1; k < gp->ngalaxies; ++k) {
375   Galaxy     *gtk = &gp->galaxies[k];
376   double      d0 = gtk->pos[0] - gt->pos[0];
377   double      d1 = gtk->pos[1] - gt->pos[1];
378   double      d2 = gtk->pos[2] - gt->pos[2];
379
380   d = d0 * d0 + d1 * d1 + d2 * d2;
381   if (d > EPSILON)
382    d = gt->mass * gt->mass / (d * sqrt(d)) * DELTAT * QCONS;
383   else
384    d = gt->mass * gt->mass / (EPSILON * sqrt_EPSILON) * DELTAT * QCONS;
385
386   d0 *= d;
387   d1 *= d;
388   d2 *= d;
389   gt->vel[0] += d0 / gt->mass;
390   gt->vel[1] += d1 / gt->mass;
391   gt->vel[2] += d2 / gt->mass;
392   gtk->vel[0] -= d0 / gtk->mass;
393   gtk->vel[1] -= d1 / gtk->mass;
394   gtk->vel[2] -= d2 / gtk->mass;
395  }
396
397  gt->pos[0] += gt->vel[0] * DELTAT;
398  gt->pos[1] += gt->vel[1] * DELTAT;
399  gt->pos[2] += gt->vel[2] * DELTAT;
400
401         XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi));
402  XDrawPoints(display, window, gc, gt->oldpoints, gt->nstars,
403CoordModeOrigin);
404  XSetForeground(display, gc, MI_PIXEL(mi, COLORSTEP * gt->galcol));
405         XDrawPoints(display, window, gc, gt->newpoints, gt->nstars,
406CoordModeOrigin);
407
408         dummy = gt->oldpoints;
409  gt->oldpoints = gt->newpoints;
410  gt->newpoints = dummy;
411 }
412
413 gp->step++;
414 if (gp->step > gp->f_hititerations * 4)
415  startover(mi);
416}
417
418void
419release_galaxy(ModeInfo * mi)
420{
421 if (universes != NULL) {
422  int         screen;
423
424  for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
425   free_galaxies(&universes[screen]);
426  (void) free((void *) universes);
427  universes = NULL;
428 }
429}
430
431void
432refresh_galaxy(ModeInfo * mi)
433{
434 /* Do nothing, it will refresh by itself */
435}
Note: See TracBrowser for help on using the repository browser.