http://se.aminet.net/pub/X11/ftp.x.org/contrib/vms/xscreensaver-124.zip
[xscreensaver] / hacks / hypercube.c
1 /* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@mcom.com>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  *
11  * This code derived from TI Explorer Lisp code by Joe Keane, Fritz Mueller,
12  * and Jamie Zawinski.
13  */
14
15 #include "screenhack.h"
16 #include <math.h>
17
18 static Display *dpy;
19 static Window window;
20 static GC color0, color1, color2, color3, color4, color5, color6, color7;
21 static GC black;
22
23 static int delay;
24
25 static int observer_z;
26 static int x_offset, y_offset;
27 static int unit_pixels;
28
29 struct point_state {
30   int old_x, old_y;
31   int new_x, new_y;
32   Bool same_p;
33 };
34
35 static void
36 move_line (state0, state1, gc)
37      struct point_state *state0, *state1;
38      GC gc;
39 {
40   if (state0->same_p && state1->same_p)
41     return;
42   if (mono_p)
43     {
44       XDrawLine (dpy, window, black,
45                  state0->old_x, state0->old_y, state1->old_x, state1->old_y);
46       XDrawLine (dpy, window, gc,
47                  state0->new_x, state0->new_y, state1->new_x, state1->new_y);
48     }
49   else
50     {
51       XSegment segments [2];
52       segments [0].x1 = state0->old_x; segments [0].y1 = state0->old_y;
53       segments [0].x2 = state1->old_x; segments [0].y2 = state1->old_y;
54       segments [1].x1 = state0->new_x; segments [1].y1 = state0->new_y;
55       segments [1].x2 = state1->new_x; segments [1].y2 = state1->new_y;
56       XDrawSegments (dpy, window, gc, segments, 2);
57     }
58 }
59
60 static void
61 hyper (xy, xz, yz, xw, yw, zw)
62      double xy, xz, yz, xw, yw, zw;
63 {
64   double cos_xy = cos (xy), sin_xy = sin (xy);
65   double cos_xz = cos (xz), sin_xz = sin (xz);
66   double cos_yz = cos (yz), sin_yz = sin (yz);
67   double cos_xw = cos (xw), sin_xw = sin (xw);
68   double cos_yw = cos (yw), sin_yw = sin (yw);
69   double cos_zw = cos (zw), sin_zw = sin (zw);
70
71   double ax = 1.0, ay = 0.0, az = 0.0, aw = 0.0;
72   double bx = 0.0, by = 1.0, bz = 0.0, bw = 0.0;
73   double cx = 0.0, cy = 0.0, cz = 1.0, cw = 0.0;
74   double dx = 0.0, dy = 0.0, dz = 0.0, dw = 1.0;
75
76   double _tmp0_, _tmp1_;
77
78   struct point_state points [16];
79   memset (points, 0, sizeof (points));
80
81 #define mmmm (&points[0])
82 #define mmmp (&points[1])
83 #define mmpm (&points[2])
84 #define mmpp (&points[3])
85 #define mpmm (&points[4])
86 #define mpmp (&points[5])
87 #define mppm (&points[6])
88 #define mppp (&points[7])
89 #define pmmm (&points[8])
90 #define pmmp (&points[9])
91 #define pmpm (&points[10])
92 #define pmpp (&points[11])
93 #define ppmm (&points[12])
94 #define ppmp (&points[13])
95 #define pppm (&points[14])
96 #define pppp (&points[15])
97
98   while (1)
99     {
100       double temp_mult;
101
102 #define compute(a,b,c,d,point_state) \
103       temp_mult = (unit_pixels / (((a*az) + (b*bz) + (c*cz) + (d*dz) +    \
104                                    (a*aw) + (b*bw) + (c*cw) + (d*dw))     \
105                                   - observer_z));                         \
106   point_state->old_x = point_state->new_x;                                \
107   point_state->old_y = point_state->new_y;                                \
108   point_state->new_x = ((((a*ax) + (b*bx) + (c*cx) + (d*dx)) * temp_mult) \
109                         + x_offset);                                      \
110   point_state->new_y = ((((a*ay) + (b*by) + (c*cy) + (d*dy)) * temp_mult) \
111                         + y_offset);                                      \
112   point_state->same_p = (point_state->old_x == point_state->new_x &&      \
113                          point_state->old_y == point_state->new_y);
114
115       compute (-1, -1, -1, -1, mmmm);
116       compute (-1, -1, -1,  1, mmmp);
117       compute (-1, -1,  1, -1, mmpm);
118       compute (-1, -1,  1,  1, mmpp);
119       compute (-1,  1, -1, -1, mpmm);
120       compute (-1,  1, -1,  1, mpmp);
121       compute (-1,  1,  1, -1, mppm);
122       compute (-1,  1,  1,  1, mppp);
123       compute ( 1, -1, -1, -1, pmmm);
124       compute ( 1, -1, -1,  1, pmmp);
125       compute ( 1, -1,  1, -1, pmpm);
126       compute ( 1, -1,  1,  1, pmpp);
127       compute ( 1,  1, -1, -1, ppmm);
128       compute ( 1,  1, -1,  1, ppmp);
129       compute ( 1,  1,  1, -1, pppm);
130       compute ( 1,  1,  1,  1, pppp);
131
132       move_line (mmmm, mmmp, color0);
133       move_line (mmmm, mmpm, color0);
134       move_line (mmpm, mmpp, color0);
135       move_line (mmmp, mmpp, color0);
136       
137       move_line (pmmm, pmmp, color1);
138       move_line (pmmm, pmpm, color1);
139       move_line (pmpm, pmpp, color1);
140       move_line (pmmp, pmpp, color1);
141       
142       move_line (mpmm, mpmp, color2);
143       move_line (mpmm, mppm, color2);
144       move_line (mppm, mppp, color2);
145       move_line (mpmp, mppp, color2);
146       
147       move_line (mmpp, mppp, color3);
148       move_line (mmpp, pmpp, color3);
149       move_line (pmpp, pppp, color3);
150       move_line (mppp, pppp, color3);
151       
152       move_line (mmmm, mpmm, color4);
153       move_line (mmmm, pmmm, color4);
154       move_line (mpmm, ppmm, color4);
155       move_line (pmmm, ppmm, color4);
156       
157       move_line (mmmp, mpmp, color5);
158       move_line (mmmp, pmmp, color5);
159       move_line (pmmp, ppmp, color5);
160       move_line (mpmp, ppmp, color5);
161       
162       move_line (mmpm, mppm, color6);
163       move_line (mmpm, pmpm, color6);
164       move_line (pmpm, pppm, color6);
165       move_line (mppm, pppm, color6);
166       
167       move_line (ppmm, ppmp, color7);
168       move_line (ppmm, pppm, color7);
169       move_line (pppm, pppp, color7);
170       move_line (ppmp, pppp, color7);
171
172  /* If you get error messages about the following forms, and you think you're
173     using an ANSI C conforming compiler, then you're mistaken.  Possibly you're
174     mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa.
175     Regardless, your system is broken; it's not a bug in this program.
176   */
177 #if __STDC__
178 # define rotate(name,dim0,dim1,cos,sin) \
179       _tmp0_ = ((name##dim0 * cos) + (name##dim1 * sin)); \
180       _tmp1_ = ((name##dim1 * cos) - (name##dim0 * sin)); \
181       name##dim0 = _tmp0_; \
182       name##dim1 = _tmp1_;
183
184 # define rotates(dim0,dim1) \
185       if (sin_##dim0##dim1 != 0) {                                 \
186         rotate(a, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
187         rotate(b, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
188         rotate(c, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
189         rotate(d, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
190       }
191
192 #else /* !__STDC__, courtesy of Andreas Luik <luik@isa.de> */
193 # define rotate(name,dim0,dim1,cos,sin) \
194       _tmp0_ = ((name/**/dim0 * cos) + (name/**/dim1 * sin)); \
195       _tmp1_ = ((name/**/dim1 * cos) - (name/**/dim0 * sin)); \
196       name/**/dim0 = _tmp0_; \
197       name/**/dim1 = _tmp1_;
198
199 # define rotates(dim0,dim1) \
200       if (sin_/**/dim0/**/dim1 != 0) {                                 \
201         rotate(a,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
202         rotate(b,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
203         rotate(c,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
204         rotate(d,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
205       }
206 #endif /* !__STDC__ */
207
208       rotates (x,y);
209       rotates (x,z);
210       rotates (y,z);
211       rotates (x,w);
212       rotates (y,w);
213       rotates (z,w);
214
215       XSync (dpy, True);
216       if (delay) usleep (delay);
217     }
218 }
219
220 \f
221 char *progclass = "Hypercube";
222
223 char *defaults [] = {
224   "Hypercube.background:        black",         /* to placate SGI */
225   "Hypercube.foreground:        white",
226   "*color0:     red",
227   "*color1:     orange",
228   "*color2:     yellow",
229   "*color3:     white",
230   "*color4:     green",
231   "*color5:     cyan",
232   "*color6:     dodgerblue",
233   "*color7:     magenta",
234
235   "*xw:         0.000",
236   "*xy:         0.010",
237   "*xz:         0.005",
238   "*yw:         0.010",
239   "*yz:         0.000",
240   "*zw:         0.000",
241
242   "*observer-z: 5",
243   "*delay:      100000",
244   0
245 };
246
247 XrmOptionDescRec options [] = {
248   { "-color0",          ".color0",      XrmoptionSepArg, 0 },
249   { "-color1",          ".color1",      XrmoptionSepArg, 0 },
250   { "-color2",          ".color2",      XrmoptionSepArg, 0 },
251   { "-color3",          ".color3",      XrmoptionSepArg, 0 },
252   { "-color4",          ".color4",      XrmoptionSepArg, 0 },
253   { "-color5",          ".color5",      XrmoptionSepArg, 0 },
254   { "-color6",          ".color6",      XrmoptionSepArg, 0 },
255   { "-color7",          ".color7",      XrmoptionSepArg, 0 },
256
257   { "-xw",              ".xw",          XrmoptionSepArg, 0 },
258   { "-xy",              ".xy",          XrmoptionSepArg, 0 },
259   { "-xz",              ".xz",          XrmoptionSepArg, 0 },
260   { "-yw",              ".yw",          XrmoptionSepArg, 0 },
261   { "-yz",              ".yz",          XrmoptionSepArg, 0 },
262   { "-zw",              ".zw",          XrmoptionSepArg, 0 },
263
264   { "-observer-z",      ".observer-z",  XrmoptionSepArg, 0 },
265   { "-delay",           ".delay",       XrmoptionSepArg, 0 }
266 };
267
268 int options_size = (sizeof (options) / sizeof (options[0]));
269
270
271 void
272 screenhack (d, w)
273      Display *d;
274      Window w;
275 {
276   XGCValues gcv;
277   XWindowAttributes xgwa;
278   Colormap cmap;
279   double xy, xz, yz, xw, yw, zw;
280   unsigned long bg;
281
282   dpy = d;
283   window = w;
284   XGetWindowAttributes (dpy, window, &xgwa);
285   cmap = xgwa.colormap;
286
287   x_offset = xgwa.width / 2;
288   y_offset = xgwa.height / 2;
289   unit_pixels = xgwa.width < xgwa.height ? xgwa.width : xgwa.height;
290
291   xy = get_float_resource ("xy", "Float");
292   xz = get_float_resource ("xz", "Float");
293   yz = get_float_resource ("yz", "Float");
294   xw = get_float_resource ("xw", "Float");
295   yw = get_float_resource ("yw", "Float");
296   zw = get_float_resource ("zw", "Float");
297
298   observer_z = get_integer_resource ("observer-z", "Integer");
299
300   delay = get_integer_resource ("delay", "Integer");
301
302   bg = get_pixel_resource ("background", "Background", dpy, cmap);
303
304   if (mono_p)
305     {
306       gcv.function = GXcopy;
307       gcv.foreground = bg;
308       black = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv);
309       gcv.foreground = get_pixel_resource ("foreground", "Foreground",
310                                            dpy, cmap);
311       color0 = color1 = color2 = color3 = color4 = color5 = color6 = color7 =
312         XCreateGC (dpy, window, GCForeground|GCFunction, &gcv);
313     }
314   else
315     {
316       black = 0;
317       gcv.function = GXxor;
318 #define make_gc(color,name) \
319         gcv.foreground = bg ^ get_pixel_resource ((name), "Foreground", \
320                                                   dpy, cmap);           \
321         color = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv)
322
323       make_gc (color0,"color0");
324       make_gc (color1,"color1");
325       make_gc (color2,"color2");
326       make_gc (color3,"color3");
327       make_gc (color4,"color4");
328       make_gc (color5,"color5");
329       make_gc (color6,"color6");
330       make_gc (color7,"color7");
331     }
332
333   hyper (xy, xz, yz, xw, yw, zw);
334 }