1 /* -*- Mode: C; tab-width: 4 -*-
2 * sphere.c --- draw a bunch of shaded spheres
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)sphere.c 4.00 97/01/01 xlockmore";
8 /* Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA.
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted, provided
14 * that the above copyright notice appear in all copies and that both that
15 * copyright notice and this permission notice appear in supporting
16 * documentation, and that the names of Sun or MIT not be used in advertising
17 * or publicity pertaining to distribution of the software without specific
18 * prior written permission. Sun and M.I.T. make no representations about the
19 * suitability of this software for any purpose. It is provided "as is"
20 * without any express or implied warranty.
22 * SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 * IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
27 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29 * ***************************************************************************
32 * 30-May-97: jwz@jwz.org: made it go vertically as well as horizontally.
33 * 27-May-97: jwz@jwz.org: turned into a standalone program.
34 * 2-Sep-93: xlock version (David Bagley bagleyd@bigfoot.com)
35 * 1988: Revised to use SunView canvas instead of gfxsw Sun Microsystems
36 * 1982: Orignal Algorithm Tom Duff Lucasfilm Ltd.
40 # define PROGCLASS "Sphere"
41 # define HACK_INIT init_sphere
42 # define HACK_DRAW draw_sphere
43 # define sphere_opts xlockmore_opts
44 # define DEFAULTS "*delay: 1000 \n" \
46 # define BRIGHT_COLORS
47 # include "xlockmore.h" /* from the xscreensaver distribution */
48 #else /* !STANDALONE */
49 # include "xlock.h" /* from the xlockmore distribution */
50 #endif /* !STANDALONE */
52 ModeSpecOpt sphere_opts = {
53 0, NULL, 0, NULL, NULL };
56 * (NX, NY, NZ) is the light source vector -- length should be 100
62 #define SQRT(a) ((int)sqrt((double)(a)))
67 int x0; /* x center */
68 int y0; /* y center */
76 static spherestruct *spheres = NULL;
79 init_sphere(ModeInfo * mi)
83 if (spheres == NULL) {
84 if ((spheres = (spherestruct *) calloc(MI_NUM_SCREENS(mi),
85 sizeof (spherestruct))) == NULL)
88 sp = &spheres[MI_SCREEN(mi)];
91 (void) free((void *) sp->points);
94 sp->width = MI_WIN_WIDTH(mi);
95 sp->height = MI_WIN_HEIGHT(mi);
96 sp->points = (XPoint *) malloc(sp->height * sizeof (XPoint));
98 XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
104 draw_sphere(ModeInfo * mi)
106 Display *display = MI_DISPLAY(mi);
108 spherestruct *sp = &spheres[MI_SCREEN(mi)];
109 register minx = 0, maxx = 0, miny = 0, maxy = 0, npts = 0;
111 if ((sp->dirx && ABS(sp->x) >= sp->radius) ||
112 (sp->diry && ABS(sp->y) >= sp->radius)) {
113 sp->radius = NRAND(MIN(sp->width / 2, sp->height / 2) - 1) + 1;
116 sp->dirx = (LRAND() & 1) * 2 - 1;
120 sp->diry = (LRAND() & 1) * 2 - 1;
122 sp->x0 = NRAND(sp->width);
123 sp->y0 = NRAND(sp->height);
125 sp->x = -sp->radius * sp->dirx;
126 sp->y = -sp->radius * sp->diry;
128 if (MI_NPIXELS(mi) > 2)
129 sp->color = NRAND(MI_NPIXELS(mi));
132 if (sp->x0 + sp->x < 0)
134 } else if (sp->dirx == -1) {
135 if (sp->x0 + sp->x >= sp->width)
136 sp->x = sp->width - sp->x0 - 1;
139 if (sp->y0 + sp->y < 0)
141 } else if (sp->diry == -1) {
142 if (sp->y0 + sp->y >= sp->height)
143 sp->y = sp->height - sp->y0 - 1;
146 sp->maxy = SQRT(sp->radius * sp->radius - sp->x * sp->x);
148 if (sp->y0 - sp->maxy < 0)
153 sp->maxx = SQRT(sp->radius * sp->radius - sp->y * sp->y);
155 if (sp->x0 - sp->maxx < 0)
160 if (sp->y0 + sp->maxy >= sp->height)
161 maxy = sp->height - sp->y0;
164 if (sp->x0 + sp->maxx >= sp->width)
165 maxx = sp->width - sp->x0;
167 XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi));
170 XDrawLine(display, MI_WINDOW(mi), gc,
171 sp->x0 + sp->x, sp->y0 + miny, sp->x0 + sp->x, sp->y0 + maxy);
173 XDrawLine(display, MI_WINDOW(mi), gc,
174 sp->x0 + minx, sp->y0 + sp->y, sp->x0 + maxx, sp->y0 + sp->y);
176 if (MI_NPIXELS(mi) > 2)
177 XSetForeground(display, gc, MI_PIXEL(mi, sp->color));
179 XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi));
182 for (sp->y = miny; sp->y <= maxy; sp->y++)
183 if ((NRAND(sp->radius * NR)) <=
184 (NX * sp->x + NY * sp->y + NZ *
185 SQRT(sp->radius * sp->radius - sp->x * sp->x - sp->y * sp->y))) {
186 sp->points[npts].x = sp->x + sp->x0;
187 sp->points[npts].y = sp->y + sp->y0;
191 for (sp->x = minx; sp->x <= maxx; sp->x++)
192 if ((NRAND(sp->radius * NR)) <=
193 (NX * sp->x + NY * sp->y + NZ *
194 SQRT(sp->radius * sp->radius - sp->x * sp->x - sp->y * sp->y))) {
195 sp->points[npts].x = sp->x + sp->x0;
196 sp->points[npts].y = sp->y + sp->y0;
199 XDrawPoints(display, MI_WINDOW(mi), gc, sp->points, npts, CoordModeOrigin);
202 if (sp->x0 + sp->x >= sp->width)
204 } else if (sp->dirx == -1) {
206 if (sp->x0 + sp->x < 0)
211 if (sp->y0 + sp->y >= sp->height)
213 } else if (sp->diry == -1) {
215 if (sp->y0 + sp->y < 0)
221 release_sphere(ModeInfo * mi)
223 if (spheres != NULL) {
226 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
227 spherestruct *sp = &spheres[screen];
230 (void) free((void *) sp->points);
234 (void) free((void *) spheres);
240 refresh_sphere(ModeInfo * mi)
242 spherestruct *sp = &spheres[MI_SCREEN(mi)];
244 XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));