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

Revision 20148, 8.8 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/* grav --- planets spinning around a pulsar */
3
4#if 0
5static const char sccsid[] = "@(#)grav.c        5.00 2000/11/01 xlockmore";
6#endif
7
8/*-
9 * Copyright (c) 1993 by Greg Boewring <gb@pobox.com>
10 *
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
16 *
17 * This file is provided AS IS with no warranties of any kind.  The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof.  In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
22 *
23 * Revision History:
24 * 01-Nov-2000: Allocation checks
25 * 10-May-1997: Compatible with xscreensaver
26 * 11-Jul-1994: color version
27 * 06-Oct-1993: Written by Greg Bowering <gb@pobox.com>
28 */
29
30#ifdef STANDALONE
31#define MODE_grav
32#define PROGCLASS "Grav"
33#define HACK_INIT init_grav
34#define HACK_DRAW draw_grav
35#define grav_opts xlockmore_opts
36#define DEFAULTS "*delay: 10000 \n" \
37 "*count: 12 \n" \
38 "*ncolors: 64 \n"
39#define BRIGHT_COLORS
40#include "xlockmore.h"          /* in xscreensaver distribution */
41#else /* STANDALONE */
42#include "xlock.h"              /* in xlockmore distribution */
43
44#endif /* STANDALONE */
45
46#ifdef MODE_grav
47
48#define DEF_DECAY "False"       /* Damping for decaying orbits */
49#define DEF_TRAIL "False"       /* For trails (works good in mono only) */
50
51static Bool decay;
52static Bool trail;
53
54static XrmOptionDescRec opts[] =
55{
56        {(char *) "-decay", (char *) ".grav.decay", XrmoptionNoArg, (caddr_t) "on"},
57        {(char *) "+decay", (char *) ".grav.decay", XrmoptionNoArg, (caddr_t) "off"},
58        {(char *) "-trail", (char *) ".grav.trail", XrmoptionNoArg, (caddr_t) "on"},
59        {(char *) "+trail", (char *) ".grav.trail", XrmoptionNoArg, (caddr_t) "off"}
60};
61static argtype vars[] =
62{
63        {(caddr_t *) & decay, (char *) "decay", (char *) "Decay", (char *) DEF_DECAY, t_Bool},
64        {(caddr_t *) & trail, (char *) "trail", (char *) "Trail", (char *) DEF_TRAIL, t_Bool}
65};
66static OptionStruct desc[] =
67{
68        {(char *) "-/+decay", (char *) "turn on/off decaying orbits"},
69        {(char *) "-/+trail", (char *) "turn on/off trail dots"}
70};
71
72ModeSpecOpt grav_opts =
73{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
74
75#ifdef USE_MODULES
76ModStruct   grav_description =
77{"grav", "init_grav", "draw_grav", "release_grav",
78 "refresh_grav", "init_grav", (char *) NULL, &grav_opts,
79 10000, -12, 1, 1, 64, 1.0, "",
80 "Shows orbiting planets", 0, NULL};
81
82#endif
83
84#define GRAV                    -0.02   /* Gravitational constant */
85#define DIST                    16.0
86#define COLLIDE                 0.0001
87#define ALMOST                  15.99
88#define HALF                    0.5
89/* #define INTRINSIC_RADIUS     200.0 */
90#define INTRINSIC_RADIUS        ((float) (gp->height/5))
91#define STARRADIUS              (unsigned int)(gp->height/(2*DIST))
92#define AVG_RADIUS              (INTRINSIC_RADIUS/DIST)
93#define RADIUS                  (unsigned int)(INTRINSIC_RADIUS/(POS(Z)+DIST))
94
95#define XR                      HALF*ALMOST
96#define YR                      HALF*ALMOST
97#define ZR                      HALF*ALMOST
98
99#define VR                      0.04
100
101#define DIMENSIONS              3
102#define X                       0
103#define Y                       1
104#define Z                       2
105
106#define DAMP                    0.999999
107#define MaxA                    0.1     /* Maximum acceleration (w/ damping) */
108
109#define POS(c) planet->P[c]
110#define VEL(c) planet->V[c]
111#define ACC(c) planet->A[c]
112
113#define Planet(x,y)\
114  if ((x) >= 0 && (y) >= 0 && (x) <= gp->width && (y) <= gp->height) {\
115    if (planet->ri < 2)\
116     XDrawPoint(display, window, gc, (x), (y));\
117    else\
118     XFillArc(display, window, gc,\
119      (x) - planet->ri / 2, (y) - planet->ri / 2, planet->ri, planet->ri,\
120      0, 23040);\
121   }
122
123#define FLOATRAND(min,max)      ((min)+(LRAND()/MAXRAND)*((max)-(min)))
124
125typedef struct {
126        double      P[DIMENSIONS], V[DIMENSIONS], A[DIMENSIONS];
127        int         xi, yi, ri;
128        unsigned long colors;
129} planetstruct;
130
131typedef struct {
132        int         width, height;
133        int         x, y, sr, nplanets;
134        unsigned long starcolor;
135        planetstruct *planets;
136} gravstruct;
137
138static gravstruct *gravs = (gravstruct *) NULL;
139
140static void
141init_planet(ModeInfo * mi, planetstruct * planet)
142{
143        Display    *display = MI_DISPLAY(mi);
144        Window      window = MI_WINDOW(mi);
145        GC          gc = MI_GC(mi);
146        gravstruct *gp = &gravs[MI_SCREEN(mi)];
147
148        if (MI_NPIXELS(mi) > 2)
149                planet->colors = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
150        else
151                planet->colors = MI_WHITE_PIXEL(mi);
152        /* Initialize positions */
153        POS(X) = FLOATRAND(-XR, XR);
154        POS(Y) = FLOATRAND(-YR, YR);
155        POS(Z) = FLOATRAND(-ZR, ZR);
156
157        if (POS(Z) > -ALMOST) {
158                planet->xi = (int)
159                        ((double) gp->width * (HALF + POS(X) / (POS(Z) + DIST)));
160                planet->yi = (int)
161                        ((double) gp->height * (HALF + POS(Y) / (POS(Z) + DIST)));
162        } else
163                planet->xi = planet->yi = -1;
164        planet->ri = RADIUS;
165
166        /* Initialize velocities */
167        VEL(X) = FLOATRAND(-VR, VR);
168        VEL(Y) = FLOATRAND(-VR, VR);
169        VEL(Z) = FLOATRAND(-VR, VR);
170
171        /* Draw planets */
172        Planet(planet->xi, planet->yi);
173}
174
175static void
176draw_planet(ModeInfo * mi, planetstruct * planet)
177{
178        Display    *display = MI_DISPLAY(mi);
179        Window      window = MI_WINDOW(mi);
180        GC          gc = MI_GC(mi);
181        gravstruct *gp = &gravs[MI_SCREEN(mi)];
182        double      D;          /* A distance variable to work with */
183        register unsigned char cmpt;
184
185        D = POS(X) * POS(X) + POS(Y) * POS(Y) + POS(Z) * POS(Z);
186        if (D < COLLIDE)
187                D = COLLIDE;
188        D = sqrt(D);
189        D = D * D * D;
190        for (cmpt = X; cmpt < DIMENSIONS; cmpt++) {
191                ACC(cmpt) = POS(cmpt) * GRAV / D;
192                if (decay) {
193                        if (ACC(cmpt) > MaxA)
194                                ACC(cmpt) = MaxA;
195                        else if (ACC(cmpt) < -MaxA)
196                                ACC(cmpt) = -MaxA;
197                        VEL(cmpt) = VEL(cmpt) + ACC(cmpt);
198                        VEL(cmpt) *= DAMP;
199                } else {
200                        /* update velocity */
201                        VEL(cmpt) = VEL(cmpt) + ACC(cmpt);
202                }
203                /* update position */
204                POS(cmpt) = POS(cmpt) + VEL(cmpt);
205        }
206
207        gp->x = planet->xi;
208        gp->y = planet->yi;
209
210        if (POS(Z) > -ALMOST) {
211                planet->xi = (int)
212                        ((double) gp->width * (HALF + POS(X) / (POS(Z) + DIST)));
213                planet->yi = (int)
214                        ((double) gp->height * (HALF + POS(Y) / (POS(Z) + DIST)));
215        } else
216                planet->xi = planet->yi = -1;
217
218        /* Mask */
219        XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
220        Planet(gp->x, gp->y);
221        if (trail) {
222                XSetForeground(display, gc, planet->colors);
223                XDrawPoint(display, MI_WINDOW(mi), gc, gp->x, gp->y);
224        }
225        /* Move */
226        gp->x = planet->xi;
227        gp->y = planet->yi;
228        planet->ri = RADIUS;
229
230        /* Redraw */
231        XSetForeground(display, gc, planet->colors);
232        Planet(gp->x, gp->y);
233}
234
235void
236init_grav(ModeInfo * mi)
237{
238        Display    *display = MI_DISPLAY(mi);
239        GC          gc = MI_GC(mi);
240        unsigned char ball;
241        gravstruct *gp;
242
243        if (gravs == NULL) {
244                if ((gravs = (gravstruct *) calloc(MI_NUM_SCREENS(mi),
245                                               sizeof (gravstruct))) == NULL)
246                        return;
247        }
248        gp = &gravs[MI_SCREEN(mi)];
249
250        gp->width = MI_WIDTH(mi);
251        gp->height = MI_HEIGHT(mi);
252
253        gp->sr = STARRADIUS;
254
255        gp->nplanets = MI_COUNT(mi);
256        if (gp->nplanets < 0) {
257                if (gp->planets) {
258                        (void) free((void *) gp->planets);
259                        gp->planets = (planetstruct *) NULL;
260                }
261                gp->nplanets = NRAND(-gp->nplanets) + 1;        /* Add 1 so its not too boring */
262        }
263        if (gp->planets == NULL) {
264                if ((gp->planets = (planetstruct *) calloc(gp->nplanets,
265                                sizeof (planetstruct))) == NULL)
266                        return;
267        }
268
269        MI_CLEARWINDOW(mi);
270
271        if (MI_NPIXELS(mi) > 2)
272                gp->starcolor = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
273        else
274                gp->starcolor = MI_WHITE_PIXEL(mi);
275        for (ball = 0; ball < (unsigned char) gp->nplanets; ball++)
276                init_planet(mi, &gp->planets[ball]);
277
278        /* Draw centrepoint */
279        XDrawArc(display, MI_WINDOW(mi), gc,
280                 gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr,
281                 0, 23040);
282}
283
284void
285draw_grav(ModeInfo * mi)
286{
287        Display    *display = MI_DISPLAY(mi);
288        Window      window = MI_WINDOW(mi);
289        GC          gc = MI_GC(mi);
290        register unsigned char ball;
291        gravstruct *gp;
292
293        if (gravs == NULL)
294                        return;
295        gp = &gravs[MI_SCREEN(mi)];
296        if (gp->planets == NULL)
297                return;
298
299        MI_IS_DRAWN(mi) = True;
300        /* Mask centrepoint */
301        XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
302        XDrawArc(display, window, gc,
303                 gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr,
304                 0, 23040);
305
306        /* Resize centrepoint */
307        switch (NRAND(4)) {
308                case 0:
309                        if (gp->sr < (int) STARRADIUS)
310                                gp->sr++;
311                        break;
312                case 1:
313                        if (gp->sr > 2)
314                                gp->sr--;
315        }
316
317        /* Draw centrepoint */
318        XSetForeground(display, gc, gp->starcolor);
319        XDrawArc(display, window, gc,
320                 gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr,
321                 0, 23040);
322
323        for (ball = 0; ball < (unsigned char) gp->nplanets; ball++)
324                draw_planet(mi, &gp->planets[ball]);
325}
326
327void
328release_grav(ModeInfo * mi)
329{
330        if (gravs != NULL) {
331                int         screen;
332
333                for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
334                        gravstruct *gp = &gravs[screen];
335
336                        if (gp->planets)
337                                (void) free((void *) gp->planets);
338                }
339                (void) free((void *) gravs);
340                gravs = (gravstruct *) NULL;
341        }
342}
343
344void
345refresh_grav(ModeInfo * mi)
346{
347        MI_CLEARWINDOW(mi);
348}
349
350#endif /* MODE_grav */
Note: See TracBrowser for help on using the repository browser.