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

Revision 20148, 8.3 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/* sphere --- a bunch of shaded spheres */
3
4#if 0
5static const char sccsid[] = "@(#)sphere.c      5.00 2000/11/01 xlockmore";
6#endif
7
8/*-
9 * Copyright (c) 1988 by Sun Microsystems
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 * 30-May-1997: <jwz@jwz.org> made it go vertically as well as horizontally.
26 * 27-May-1997: <jwz@jwz.org> turned into a standalone program.
27 * 02-Sep-1993: xlock version David Bagley <bagleyd@tux.org>
28 * 1988: Revised to use SunView canvas instead of gfxsw Sun Microsystems
29 * 1982: Orignal Algorithm Tom Duff Lucasfilm Ltd.
30 */
31
32/*-
33 * original copyright
34 * **************************************************************************
35 * Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA.
36 *
37 * All Rights Reserved
38 *
39 * Permission to use, copy, modify, and distribute this software and its
40 * documentation for any purpose and without fee is hereby granted, provided
41 * that the above copyright notice appear in all copies and that both that
42 * copyright notice and this permission notice appear in supporting
43 * documentation, and that the names of Sun or MIT not be used in advertising
44 * or publicity pertaining to distribution of the software without specific
45 * prior written permission. Sun and M.I.T. make no representations about the
46 * suitability of this software for any purpose. It is provided "as is"
47 * without any express or implied warranty.
48 *
49 * SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
51 * IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
52 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
53 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
54 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
55 * SOFTWARE.
56 * ***************************************************************************
57 */
58
59#ifdef STANDALONE
60#define MODE_sphere
61#define PROGCLASS "Sphere"
62#define HACK_INIT init_sphere
63#define HACK_DRAW draw_sphere
64#define sphere_opts xlockmore_opts
65#define DEFAULTS "*delay: 1000 \n" \
66 "*cycles: 20 \n" \
67 "*size: 0 \n" \
68 "*ncolors: 64 \n"
69#define BRIGHT_COLORS
70#include "xlockmore.h"          /* from the xscreensaver distribution */
71#else /* !STANDALONE */
72#include "xlock.h"              /* from the xlockmore distribution */
73#endif /* !STANDALONE */
74
75#ifdef MODE_sphere
76
77ModeSpecOpt sphere_opts =
78{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
79
80#ifdef USE_MODULES
81ModStruct   sphere_description =
82{"sphere", "init_sphere", "draw_sphere", "release_sphere",
83 "refresh_sphere", "init_sphere", (char *) NULL, &sphere_opts,
84 5000, 1, 20, 0, 64, 1.0, "",
85 "Shows a bunch of shaded spheres", 0, NULL};
86
87#endif
88
89/*-
90 * (NX, NY, NZ) is the light source vector -- length should be 100
91 */
92#define NX 48
93#define NY (-36)
94#define NZ 80
95#define NR 100
96#define SQRT(a) ((int)sqrt((double)(a)))
97
98typedef struct {
99        int         width, height;
100        int         radius;
101        int         x0;         /* x center */
102        int         y0;         /* y center */
103        int         color;
104        int         x, y;
105        int         dirx, diry;
106        int         shadowx, shadowy;
107        int         maxx, maxy;
108        XPoint     *points;
109} spherestruct;
110
111static spherestruct *spheres = (spherestruct *) NULL;
112
113void
114init_sphere(ModeInfo * mi)
115{
116        spherestruct *sp;
117
118        if (spheres == NULL) {
119                if ((spheres = (spherestruct *) calloc(MI_NUM_SCREENS(mi),
120                                             sizeof (spherestruct))) == NULL)
121                        return;
122        }
123        sp = &spheres[MI_SCREEN(mi)];
124
125        if (sp->points != NULL) {
126                (void) free((void *) sp->points);
127                sp->points = (XPoint *) NULL;
128        }
129        sp->width = MAX(MI_WIDTH(mi), 4);
130        sp->height = MAX(MI_HEIGHT(mi), 4);
131        if ((sp->points = (XPoint *) malloc(MIN(sp->width, sp->height) *
132                         sizeof (XPoint))) == NULL) {
133                return;
134        }
135
136        MI_CLEARWINDOW(mi);
137
138        sp->dirx = 1;
139        sp->x = sp->radius;
140        sp->shadowx = (LRAND() & 1) ? 1 : -1;
141        sp->shadowy = (LRAND() & 1) ? 1 : -1;
142}
143
144void
145draw_sphere(ModeInfo * mi)
146{
147        Display    *display = MI_DISPLAY(mi);
148        GC          gc = MI_GC(mi);
149        int         sqrd, nd;
150        register int minx = 0, maxx = 0, miny = 0, maxy = 0, npts = 0;
151        spherestruct *sp;
152
153        if (spheres == NULL)
154                return;
155        sp = &spheres[MI_SCREEN(mi)];
156        if (sp->points == NULL)
157                return;
158
159        MI_IS_DRAWN(mi) = True;
160        if ((sp->dirx && ABS(sp->x) >= sp->radius) ||
161            (sp->diry && ABS(sp->y) >= sp->radius)) {
162                sp->radius = NRAND(MIN(sp->width / 2, sp->height / 2) - 1) + 1;
163
164                if (LRAND() & 1) {
165                        sp->dirx = (int) (LRAND() & 1) * 2 - 1;
166                        sp->diry = 0;
167                } else {
168                        sp->dirx = 0;
169                        sp->diry = (int) (LRAND() & 1) * 2 - 1;
170                }
171                sp->x0 = NRAND(sp->width);
172                sp->y0 = NRAND(sp->height);
173
174                sp->x = -sp->radius * sp->dirx;
175                sp->y = -sp->radius * sp->diry;
176
177                if (MI_NPIXELS(mi) > 2)
178                        sp->color = NRAND(MI_NPIXELS(mi));
179        }
180        if (sp->dirx == 1) {
181                if (sp->x0 + sp->x < 0)
182                        sp->x = -sp->x0;
183        } else if (sp->dirx == -1) {
184                if (sp->x0 + sp->x >= sp->width)
185                        sp->x = sp->width - sp->x0 - 1;
186        }
187        if (sp->diry == 1) {
188                if (sp->y0 + sp->y < 0)
189                        sp->y = -sp->y0;
190        } else if (sp->diry == -1) {
191                if (sp->y0 + sp->y >= sp->height)
192                        sp->y = sp->height - sp->y0 - 1;
193        }
194        if (sp->dirx) {
195                sp->maxy = SQRT(sp->radius * sp->radius - sp->x * sp->x);
196                miny = -sp->maxy;
197                if (sp->y0 - sp->maxy < 0)
198                        miny = -sp->y0;
199                maxy = sp->maxy;
200        }
201        if (sp->diry) {
202                sp->maxx = SQRT(sp->radius * sp->radius - sp->y * sp->y);
203                minx = -sp->maxx;
204                if (sp->x0 - sp->maxx < 0)
205                        minx = -sp->x0;
206                maxx = sp->maxx;
207        }
208        if (sp->dirx) {
209                if (sp->y0 + sp->maxy >= sp->height)
210                        maxy = sp->height - sp->y0;
211        }
212        if (sp->diry) {
213                if (sp->x0 + sp->maxx >= sp->width)
214                        maxx = sp->width - sp->x0;
215        }
216        XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
217
218        if (sp->dirx)
219                XDrawLine(display, MI_WINDOW(mi), gc,
220                sp->x0 + sp->x, sp->y0 + miny, sp->x0 + sp->x, sp->y0 + maxy);
221        if (sp->diry)
222                XDrawLine(display, MI_WINDOW(mi), gc,
223                sp->x0 + minx, sp->y0 + sp->y, sp->x0 + maxx, sp->y0 + sp->y);
224
225        if (MI_NPIXELS(mi) > 2)
226                XSetForeground(display, gc, MI_PIXEL(mi, sp->color));
227        else
228                XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
229
230        if (sp->dirx) {
231                sqrd = sp->radius * sp->radius - sp->x * sp->x;
232                nd = NX * sp->shadowx * sp->x;
233                for (sp->y = miny; sp->y <= maxy; sp->y++)
234                        if ((NRAND(sp->radius * NR)) <= nd + NY * sp->shadowy * sp->y +
235                            NZ * SQRT(sqrd - sp->y * sp->y)) {
236                                sp->points[npts].x = sp->x + sp->x0;
237                                sp->points[npts].y = sp->y + sp->y0;
238                                npts++;
239                        }
240        }
241        if (sp->diry) {
242                sqrd = sp->radius * sp->radius - sp->y * sp->y;
243                nd = NY * sp->shadowy * sp->y;
244                for (sp->x = minx; sp->x <= maxx; sp->x++)
245                        if ((NRAND(sp->radius * NR)) <= NX * sp->shadowx * sp->x + nd +
246                            NZ * SQRT(sqrd - sp->x * sp->x)) {
247                                sp->points[npts].x = sp->x + sp->x0;
248                                sp->points[npts].y = sp->y + sp->y0;
249                                npts++;
250                        }
251        }
252        XDrawPoints(display, MI_WINDOW(mi), gc, sp->points, npts, CoordModeOrigin);
253        if (sp->dirx == 1) {
254                sp->x++;
255                if (sp->x0 + sp->x >= sp->width)
256                        sp->x = sp->radius;
257        } else if (sp->dirx == -1) {
258                sp->x--;
259                if (sp->x0 + sp->x < 0)
260                        sp->x = -sp->radius;
261        }
262        if (sp->diry == 1) {
263                sp->y++;
264                if (sp->y0 + sp->y >= sp->height)
265                        sp->y = sp->radius;
266        } else if (sp->diry == -1) {
267                sp->y--;
268                if (sp->y0 + sp->y < 0)
269                        sp->y = -sp->radius;
270        }
271}
272
273void
274release_sphere(ModeInfo * mi)
275{
276        if (spheres != NULL) {
277                int         screen;
278
279                for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
280                        spherestruct *sp = &spheres[screen];
281
282                        if (sp->points) {
283                                (void) free((void *) sp->points);
284                                /* sp->points = NULL; */
285                        }
286                }
287                (void) free((void *) spheres);
288                spheres = (spherestruct *) NULL;
289        }
290}
291
292void
293refresh_sphere(ModeInfo * mi)
294{
295        spherestruct *sp;
296
297        if (spheres == NULL)
298                return;
299        sp = &spheres[MI_SCREEN(mi)];
300
301        MI_CLEARWINDOW(mi);
302
303        sp->x = -sp->radius;
304}
305
306#endif /* MODE_sphere */
Note: See TracBrowser for help on using the repository browser.